Repository: Netflix/ember-nf-graph Branch: master Commit: 851b63edc969 Files: 290 Total size: 2.4 MB Directory structure: gitextract_jjd60v_k/ ├── .editorconfig ├── .ember-cli ├── .eslintrc.js ├── .gitignore ├── .npmignore ├── .travis.yml ├── .watchmanconfig ├── CHANGELOG.md ├── LICENSE.md ├── OSSMETADATA ├── README.md ├── addon/ │ ├── .gitkeep │ ├── components/ │ │ ├── .gitignore │ │ ├── nf-area-stack.js │ │ ├── nf-area.js │ │ ├── nf-bars-group.js │ │ ├── nf-bars.js │ │ ├── nf-brush-selection.js │ │ ├── nf-component.js │ │ ├── nf-crosshairs.js │ │ ├── nf-dot.js │ │ ├── nf-graph-content.js │ │ ├── nf-graph-yieldables.js │ │ ├── nf-graph.js │ │ ├── nf-group.js │ │ ├── nf-horizontal-line.js │ │ ├── nf-line.js │ │ ├── nf-plot.js │ │ ├── nf-plots.js │ │ ├── nf-range-marker.js │ │ ├── nf-range-markers.js │ │ ├── nf-right-tick.js │ │ ├── nf-selection-box.js │ │ ├── nf-svg-image.js │ │ ├── nf-svg-line.js │ │ ├── nf-svg-path.js │ │ ├── nf-svg-rect.js │ │ ├── nf-tick-label.js │ │ ├── nf-tracker.js │ │ ├── nf-vertical-line.js │ │ ├── nf-x-axis.js │ │ ├── nf-y-axis.js │ │ └── nf-y-diff.js │ ├── mixins/ │ │ ├── .gitignore │ │ ├── graph-area-utils.js │ │ ├── graph-data-graphic.js │ │ ├── graph-graphic-with-tracking-dot.js │ │ ├── graph-line-utils.js │ │ ├── graph-registered-graphic.js │ │ ├── graph-requires-scale-source.js │ │ └── graph-selectable-graphic.js │ ├── styles/ │ │ └── addon.css │ ├── templates/ │ │ └── components/ │ │ ├── nf-area-stack.hbs │ │ ├── nf-area.hbs │ │ ├── nf-bars-group.hbs │ │ ├── nf-bars.hbs │ │ ├── nf-brush-selection.hbs │ │ ├── nf-component.hbs │ │ ├── nf-crosshairs.hbs │ │ ├── nf-dot.hbs │ │ ├── nf-graph-content.hbs │ │ ├── nf-graph-yieldables.hbs │ │ ├── nf-graph.hbs │ │ ├── nf-group.hbs │ │ ├── nf-horizontal-line.hbs │ │ ├── nf-line.hbs │ │ ├── nf-plot.hbs │ │ ├── nf-plots.hbs │ │ ├── nf-range-marker.hbs │ │ ├── nf-range-markers.hbs │ │ ├── nf-right-tick.hbs │ │ ├── nf-selection-box.hbs │ │ ├── nf-svg-image.hbs │ │ ├── nf-svg-line.hbs │ │ ├── nf-svg-path.hbs │ │ ├── nf-svg-rect.hbs │ │ ├── nf-tick-label.hbs │ │ ├── nf-tracker.hbs │ │ ├── nf-vertical-line.hbs │ │ ├── nf-x-axis.hbs │ │ ├── nf-y-axis.hbs │ │ └── nf-y-diff.hbs │ └── utils/ │ ├── nf/ │ │ ├── array-helpers.js │ │ ├── graph-event.js │ │ ├── graph-mouse-event.js │ │ ├── graph-position.js │ │ ├── scale-utils.js │ │ ├── scroll-area-action-context.js │ │ ├── svg-dom.js │ │ └── tracked-array-property.js │ └── parse-property-expression.js ├── app/ │ ├── .gitkeep │ └── components/ │ ├── .gitignore │ ├── nf-area-stack.js │ ├── nf-area.js │ ├── nf-bars-group.js │ ├── nf-bars.js │ ├── nf-brush-selection.js │ ├── nf-component.js │ ├── nf-crosshairs.js │ ├── nf-dot.js │ ├── nf-graph-content.js │ ├── nf-graph-yieldables.js │ ├── nf-graph.js │ ├── nf-group.js │ ├── nf-horizontal-line.js │ ├── nf-line.js │ ├── nf-plot.js │ ├── nf-plots.js │ ├── nf-range-marker.js │ ├── nf-range-markers.js │ ├── nf-right-tick.js │ ├── nf-selection-box.js │ ├── nf-svg-image.js │ ├── nf-svg-line.js │ ├── nf-svg-path.js │ ├── nf-svg-rect.js │ ├── nf-tick-label.js │ ├── nf-tracker.js │ ├── nf-vertical-line.js │ ├── nf-x-axis.js │ ├── nf-y-axis.js │ └── nf-y-diff.js ├── config/ │ ├── ember-try.js │ └── environment.js ├── docs/ │ ├── api.js │ ├── assets/ │ │ ├── css/ │ │ │ └── main.css │ │ ├── index.html │ │ ├── js/ │ │ │ ├── api-filter.js │ │ │ ├── api-list.js │ │ │ ├── api-search.js │ │ │ ├── apidocs.js │ │ │ └── yui-prettify.js │ │ └── vendor/ │ │ └── prettify/ │ │ ├── CHANGES.html │ │ ├── COPYING │ │ ├── README.html │ │ ├── prettify-min.css │ │ └── prettify-min.js │ ├── classes/ │ │ ├── components.nf-area-stack.html │ │ ├── components.nf-area.html │ │ ├── components.nf-bars.html │ │ ├── components.nf-crosshair.html │ │ ├── components.nf-dot.html │ │ ├── components.nf-gg.html │ │ ├── components.nf-graph-content.html │ │ ├── components.nf-graph.html │ │ ├── components.nf-horizontal-line.html │ │ ├── components.nf-line.html │ │ ├── components.nf-plot.html │ │ ├── components.nf-range-marker.html │ │ ├── components.nf-range-markers.html │ │ ├── components.nf-right-tick.html │ │ ├── components.nf-selection-box.html │ │ ├── components.nf-svg-image.html │ │ ├── components.nf-svg-line.html │ │ ├── components.nf-svg-path.html │ │ ├── components.nf-svg-rect.html │ │ ├── components.nf-tracker.html │ │ ├── components.nf-vertical-line.html │ │ ├── components.nf-x-axis.html │ │ ├── components.nf-y-axis.html │ │ ├── components.nf-y-diff.html │ │ ├── index.html │ │ ├── mixins.graph-area-utils.html │ │ ├── mixins.graph-data-graphic.html │ │ ├── mixins.graph-has-graph-parent.html │ │ ├── mixins.graph-line-utils.html │ │ ├── mixins.graph-registered-graphic.html │ │ ├── mixins.graph-requires-scale-source.html │ │ ├── mixins.graph-selectable-graphic.html │ │ ├── utils.nf.graph-event.html │ │ ├── utils.nf.graph-mouse-event.html │ │ ├── utils.nf.graph-position.html │ │ ├── utils.nf.scroll-area-action-context.html │ │ └── utils.parse-property-expression.html │ ├── data.json │ ├── files/ │ │ ├── addon_mixins_graph-area-utils.js.html │ │ ├── addon_mixins_graph-data-graphic.js.html │ │ ├── addon_mixins_graph-graphic-with-tracking-dot.js.html │ │ ├── addon_mixins_graph-has-graph-parent.js.html │ │ ├── addon_mixins_graph-line-utils.js.html │ │ ├── addon_mixins_graph-registered-graphic.js.html │ │ ├── addon_mixins_graph-requires-scale-source.js.html │ │ ├── addon_mixins_graph-selectable-graphic.js.html │ │ ├── addon_utils_nf_array-helpers.js.html │ │ ├── addon_utils_nf_graph-event.js.html │ │ ├── addon_utils_nf_graph-mouse-event.js.html │ │ ├── addon_utils_nf_graph-position.js.html │ │ ├── addon_utils_nf_scale-utils.js.html │ │ ├── addon_utils_nf_scroll-area-action-context.js.html │ │ ├── addon_utils_nf_svg-dom.js.html │ │ ├── addon_utils_parse-property-expression.js.html │ │ ├── app_components_nf-area-stack.js.html │ │ ├── app_components_nf-area.js.html │ │ ├── app_components_nf-bars.js.html │ │ ├── app_components_nf-crosshair.js.html │ │ ├── app_components_nf-dot.js.html │ │ ├── app_components_nf-gg.js.html │ │ ├── app_components_nf-graph-content.js.html │ │ ├── app_components_nf-graph.js.html │ │ ├── app_components_nf-horizontal-line.js.html │ │ ├── app_components_nf-line.js.html │ │ ├── app_components_nf-plot.js.html │ │ ├── app_components_nf-plots.js.html │ │ ├── app_components_nf-range-marker.js.html │ │ ├── app_components_nf-range-markers.js.html │ │ ├── app_components_nf-right-tick.js.html │ │ ├── app_components_nf-selection-box.js.html │ │ ├── app_components_nf-svg-image.js.html │ │ ├── app_components_nf-svg-line.js.html │ │ ├── app_components_nf-svg-path.js.html │ │ ├── app_components_nf-svg-rect.js.html │ │ ├── app_components_nf-tracker.js.html │ │ ├── app_components_nf-vertical-line.js.html │ │ ├── app_components_nf-x-axis.js.html │ │ ├── app_components_nf-y-axis.js.html │ │ ├── app_components_nf-y-diff.js.html │ │ └── index.html │ ├── index.html │ └── modules/ │ ├── index.html │ ├── scale-utils.html │ ├── utils_nf_array-helpers.html │ └── utils_nf_svg-dom.html ├── ember-cli-build.js ├── index.js ├── package.json ├── protractor.conf.js ├── testem.js ├── tests/ │ ├── dummy/ │ │ ├── app/ │ │ │ ├── app.js │ │ │ ├── components/ │ │ │ │ ├── .gitkeep │ │ │ │ ├── bars-with-line.js │ │ │ │ ├── basic-area-graph.js │ │ │ │ ├── basic-bar-graph.js │ │ │ │ ├── basic-line-graph.js │ │ │ │ ├── brush-select-zoom.js │ │ │ │ ├── detailed-line-graph.js │ │ │ │ ├── graph-primitives.js │ │ │ │ ├── mouse-tracking-data.js │ │ │ │ ├── mouse-tracking.js │ │ │ │ └── stacked-area-graph.js │ │ │ ├── controllers/ │ │ │ │ ├── .gitkeep │ │ │ │ └── nf-graph/ │ │ │ │ ├── index.js │ │ │ │ └── nf-bars.js │ │ │ ├── helpers/ │ │ │ │ ├── .gitkeep │ │ │ │ └── format-hour-minute.js │ │ │ ├── index.html │ │ │ ├── models/ │ │ │ │ └── .gitkeep │ │ │ ├── resolver.js │ │ │ ├── router.js │ │ │ ├── routes/ │ │ │ │ ├── .gitkeep │ │ │ │ ├── index.js │ │ │ │ └── nf-graph/ │ │ │ │ ├── index.js │ │ │ │ └── nf-bars.js │ │ │ ├── services/ │ │ │ │ ├── data-generator.js │ │ │ │ └── utility.js │ │ │ ├── styles/ │ │ │ │ └── app.css │ │ │ └── templates/ │ │ │ ├── application.hbs │ │ │ ├── components/ │ │ │ │ ├── bars-with-line.hbs │ │ │ │ ├── basic-area-graph.hbs │ │ │ │ ├── basic-bar-graph.hbs │ │ │ │ ├── basic-line-graph.hbs │ │ │ │ ├── brush-select-zoom.hbs │ │ │ │ ├── detailed-line-graph.hbs │ │ │ │ ├── graph-primitives.hbs │ │ │ │ ├── mouse-tracking-data.hbs │ │ │ │ ├── mouse-tracking.hbs │ │ │ │ └── stacked-area-graph.hbs │ │ │ ├── examples.hbs │ │ │ └── nf-graph/ │ │ │ ├── index.hbs │ │ │ └── nf-bars.hbs │ │ ├── config/ │ │ │ ├── environment.js │ │ │ └── targets.js │ │ └── public/ │ │ ├── .gitkeep │ │ └── robots.txt │ ├── helpers/ │ │ ├── destroy-app.js │ │ ├── module-for-acceptance.js │ │ └── start-app.js │ ├── index.html │ ├── perf/ │ │ └── first.spec.js │ ├── test-helper.js │ └── unit/ │ ├── .gitkeep │ ├── addon/ │ │ └── mixins/ │ │ └── graph-data-graphic-test.js │ └── app/ │ └── components/ │ ├── nf-bars-test.js │ ├── nf-graph-test.js │ ├── nf-horizontal-line-test.js │ ├── nf-vertical-line-test.js │ ├── nf-x-axis-test.js │ └── nf-y-axis-test.js ├── vendor/ │ └── .gitkeep └── yuidoc.json ================================================ FILE CONTENTS ================================================ ================================================ FILE: .editorconfig ================================================ # EditorConfig helps developers define and maintain consistent # coding styles between different editors and IDEs # editorconfig.org root = true [*] end_of_line = lf charset = utf-8 trim_trailing_whitespace = true insert_final_newline = true indent_style = space indent_size = 2 [*.hbs] insert_final_newline = false [*.{diff,md}] trim_trailing_whitespace = false ================================================ FILE: .ember-cli ================================================ { /** Ember CLI sends analytics information by default. The data is completely anonymous, but there are times when you might want to disable this behavior. Setting `disableAnalytics` to true will prevent any data from being sent. */ "disableAnalytics": false } ================================================ FILE: .eslintrc.js ================================================ module.exports = { root: true, parserOptions: { ecmaVersion: 2017, sourceType: 'module' }, plugins: [ 'ember' ], extends: [ 'eslint:recommended', 'plugin:ember/recommended' ], env: { browser: true }, globals: { d3: true, Rx: true }, rules: { 'ember/no-on-calls-in-components': 'off', 'ember/closure-actions': 'off' }, overrides: [ // node files { files: [ 'index.js', 'testem.js', 'ember-cli-build.js', 'config/**/*.js', 'tests/dummy/config/**/*.js' ], excludedFiles: [ 'app/**', 'addon/**', 'tests/dummy/app/**' ], parserOptions: { sourceType: 'script', ecmaVersion: 2015 }, env: { browser: false, node: true }, plugins: ['node'], rules: Object.assign({}, require('eslint-plugin-node').configs.recommended.rules, { // add your custom rules and overrides for node files here }) }, // test files { files: ['tests/**/*.js'], excludedFiles: ['tests/dummy/**/*.js'], env: { embertest: true }, rules: { 'ember/avoid-leaking-state-in-ember-objects': 'off' } }, { files: ['protractor.conf.js', 'tests/perf/**/*.js'], env: { mocha: true, node: true }, globals: { '$': true, browser: true }, rules: { 'ember/no-global-jquery': 'off' } } ] }; ================================================ FILE: .gitignore ================================================ # See https://help.github.com/ignore-files/ for more about ignoring files. # compiled output /dist /tmp # dependencies /node_modules /bower_components # misc /.sass-cache /connect.lock /coverage/* /libpeerconnection.log npm-debug.log* yarn-error.log testem.log # ember-try .node_modules.ember-try/ bower.json.ember-try package.json.ember-try ================================================ FILE: .npmignore ================================================ /bower_components /config/ember-try.js /dist /tests /tmp **/.gitkeep .bowerrc .editorconfig .ember-cli .eslintrc.js .gitignore .watchmanconfig .travis.yml bower.json ember-cli-build.js testem.js # ember-try .node_modules.ember-try/ bower.json.ember-try package.json.ember-try ================================================ FILE: .travis.yml ================================================ --- language: node_js node_js: # we recommend testing addons with the same minimum supported node version as Ember CLI # so that your addon works for all apps - "6" sudo: false dist: trusty addons: chrome: stable cache: yarn: true directories: - $HOME/.npm env: global: # See https://git.io/vdao3 for details. - JOBS=1 matrix: # we recommend new addons test the current and previous LTS # as well as latest stable release (bonus points to beta/canary) - EMBER_TRY_SCENARIO=ember-lts-2.12 - EMBER_TRY_SCENARIO=ember-lts-2.16 - EMBER_TRY_SCENARIO=ember-release - EMBER_TRY_SCENARIO=ember-beta - EMBER_TRY_SCENARIO=ember-canary - EMBER_TRY_SCENARIO=ember-default matrix: fast_finish: true allow_failures: - env: EMBER_TRY_SCENARIO=ember-canary install: - yarn install script: - yarn run lint:js # Usually, it's ok to finish the test scenario without reverting # to the addon's original dependency state, skipping "cleanup". - node_modules/.bin/ember try:one $EMBER_TRY_SCENARIO --skip-cleanup ================================================ FILE: .watchmanconfig ================================================ { "ignore_dirs": ["tmp", "dist"] } ================================================ FILE: CHANGELOG.md ================================================ # Changelog ### 1.0.0-beta.30 - FIX memory leak in nf-area caused by overriding `_unregister` - FIX null reference error in nf-area caused when data is empty ### 1.0.0-beta.29 - UPDATE Readd tracking capabilities to nf-bars ### 1.0.0-beta.28 - REMOVE all SASS files and dependencies from styles - BREAKING style complexity has been reduced - BREAKING add additional path to nf-area to create tracing line at top ### 1.0.0-beta.27 - UPDATE Readd `hoverData` output to tracked components. ### 1.0.0-beta.26 - FIX Ensure tracked data updates when firstVisibleData or lastVisibleData has updated in certain tracking modes ### 1.0.0-beta.25 - FIX issue where firstVisibleData and lastVisibleData would error if no data is present ### 1.0.0-beta.24 - FIX trackingData no longer throws errors when underlying data is not present ### 1.0.0-beta.23 - FIX `snap-last` and `snap-first` type trackingModes will now initialize properly and render ### 1.0.0-beta.22 - FIX fix regression in `nf-line` tracking behavior - FIX `nf-bars` should actually render bars again (doh) - FIX `nf-brush-selection` will no longer throw errors to console while brushing ### 1.0.0-beta.21 - UPDATE components with tracking capabilities (`nf-line`, `nf-area` and `nf-bars`) updated to support additional data passed with trackingData, rendered values are `renderX` and `renderY`, where actual values are still at `x` and `y`. This was to account for new stacked area functionality. - UPDATE `nf-bars` now will render a tracking dot if `showTrackingDot` is set to `true` - BREAKING `nf-line`, `nf-area` and `nf-bars` will no longer emit values, actions or events for `hoverChange` and `hoverEnd`. `didTrack` still functions, though. ### 1.0.0-beta.20 - UPDATE `nf-graph` component now has `didAutoUpdateMinX`, `didAutoUpdateMinY`, `didAutoUpdateMaxX`, `didAutoUpdateMaxX` that will trigger when the corresponding values are updated automatically by a mode of `"push-tick"`, `"auto"` or `"tick"`. - UPDATE `nf-graph` component now has actions `autoScaleXAction` and `autoScaleYAction` that will send when the auto update events (mentioned above) trigger. ### 1.0.0-beta.19 - FIX issue where `nf-area` having null data would throw an unhandled error. ### 1.0.0-beta.18 - FIX axes components will once again use the passed templates for pre-Glimmer Ember. ### 1.0.0-beta.17 - ADD `nf-tracker` component. This is a component for templatable tracking dots - UPDATE `nf-line` and `nf-area` to use `nf-tracker` for tracking dot generation - UPDATE improved performance on hover/tracking - UPDATE add `aggregate` to `nf-area-stack` component to sum y values of areas for stacking purposes. Defaults to `false` currently, but should be used with `true` from this point on, as it will default to `true` in future versions. - UPDATE switch templates to attribute syntax - UPDATE switch most computed properties to new computed property syntax - FIX nf-graph should work with Glimmer now (thanks @jamesarosen) - BREAKING graph components such as `nf-line` and `nf-area` will no longer sort your data for you. This is done for performance reasons. ### 1.0.0-beta.16 - FIX [#64](https://github.com/Netflix/ember-nf-graph/issues/64) put `tickFactory` back where it belongs on the axes components - FIX [#59](https://github.com/Netflix/ember-nf-graph/pull/59) fixed an issue where nf-bars scales had the wrong domain values. ### 1.0.0-beta.15 - FIX Moved ember-new-computed to deps not devDeps ### 1.0.0-beta.14 - FIX [#63](https://github.com/Netflix/ember-nf-graph/pull/63) Uses new computed property syntax w/ polyfill for host apps running older ember ### 1.0.0-beta.13 - FIX [#56](https://github.com/Netflix/ember-nf-graph/pull/56) Added rxjs to host app bower blueprint - FIX rxjs dependency added to `index.js` - UPDATE removed dependency on `ember-cli-rx` ### 1.0.0-beta.12 - FIX performance issue with axes caused by graphics registering after render - FIX issue where `nf-area-stack` would not stack some `nf-area` components ### 1.0.0-beta.11 - Update Ember-CLI to `0.2.3` and Ember to `~1.11.3` - FIX [#53](//github.com/Netflix/ember-nf-graph/issues/53) remove event hooks and registrations that were causing recalculations and re-renders. ### 1.0.0-beta.10 - FIX [#44](//github.com/Netflix/ember-nf-graph/issues/44) remove nf-scroll-area, which was leftover from splitting out nf-table - FIX [#41](//github.com/Netflix/ember-nf-graph/issues/41) fix assertion error that was caused in certain tracking modes - FIX [#16](//github.com/Netflix/ember-nf-graph/issues/16) patched addClass so Ember will actually update classes on SVG elements using classNameBindings - UPDATE [#38](//github.com/Netflix/ember-nf-graph/issues/38) Test on multiple Ember versions ### 1.0.0-beta.9 - FIX [#16](//github.com/Netflix/ember-nf-graph/issues/16) SVG classes not swapping when selection changed - FIX lock to rx-ember 0.2.5-1 - FIX [#24](//github.com/Netflix/ember-nf-graph/issues/24) SVG lines no longer complain when nf-vertical-line or nf-horizontal-line have null values or return a pixel value less than zero ### 1.0.0-beta.8 - [CRITICAL BUGFIX] Moved babel to `dependencies` so our addon is actually transpiled in host apps #34 ### 1.0.0-beta.7 - Do not use. ### 1.0.0-beta.6 - UPDATE [#4](//github.com/Netflix/ember-nf-graph/issues/4) add block params to axis components. - FIX [#29](//github.com/netflix/ember-nf-graph/issues/29) remove sad panda rename warning. ### 1.0.0-beta.5 - UPDATE name to ember-nf-graph - FIX [#28](//github.com/netflix/ember-nf-graph/issues/28) Remove a few additional prototype functions. But also I had to remove the addon that removed the prototype functions. (prototype functions are back for now). ### 1.0.0-beta.4 - DEPRECATE [#11](//github.com/netflix/ember-nf-graph/issues/11) Add warning message that name will be changing from ember-nf-graph to ember-nf-graph for next version - FIX [#8](//github.com/netflix/ember-nf-graph/issues/8): Removed prototype functions (e.g. `function() {}.property()`). - UPDATE [#3](//github.com/netflix/ember-nf-graph/issues/3): [Examples are now live](//netflix.github.io/ember-nf-graph-examples/dist) special thanks to [@jeff3dx](//github.com/jeff3dx) for all of his hard work! - FIX [#25](//github.com/netflix/ember-nf-graph/issues/25): removed tabs in favor of spaces - UPDATE rx-ember to 0.2.4, clean up bower.json - FIX [#17](//github.com/netflix/ember-nf-graph/pull/17): stop publishing tmp and dist to npm - FIX [#21](//github.com/netflix/ember-nf-graph/issues/21): remove leftover console.debug statement ### 1.0.0-beta.3 - FIX [#9](//github.com/netflix/ember-nf-graph/issues/9): Blueprints now properly named ### 1.0.0-beta.2 - FIX Update license - FIX updated documentation and removed document cruft - UPDATE: added a changelog :P - META: made meta joke in changelog with appropriate emoticon ### 1.0.0-beta.1 - UPDATE: just releasing to public ================================================ FILE: LICENSE.md ================================================ Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright 2015 Netflix, Inc. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. ================================================ FILE: OSSMETADATA ================================================ osslifecycle=active ================================================ FILE: README.md ================================================ [![Build Status](https://travis-ci.org/Netflix/ember-nf-graph.svg?branch=master)](https://travis-ci.org/Netflix/ember-nf-graph) [![npm version](https://badge.fury.io/js/ember-nf-graph.svg)](http://badge.fury.io/js/ember-nf-graph) # ember-nf-graph A Component-based DSL for creating graphs in your Ember app. The goal of the library is to create a set of components that allows application or component authors to build graphs in a compositional way. This includes components for templated axes, graph lines, areas, stacked areas, bar graphs, and much more. Check the [documentation](//netflix.github.io/ember-nf-graph/docs) for more information. - [Documentation](//netflix.github.io/ember-nf-graph/docs) - [Examples](//netflix.github.io/ember-nf-graph-examples/dist) A basic graph example is as follows: ```js export default Ember.Route.extend({ model() { return { myLineData: [ { x: 0, y: 12 }, { x: 1, y: 32 }, { x: 2, y: 42 }, // ... ], myAreaData: [ { x: 0, y: 43 }, { x: 1, y: 54 }, { x: 2, y: 13 }, // ... ] }; } }); ``` ```hbs {{#nf-graph width=500 height=300 as |nf|}} {{#nf.graph as |graph|}} {{graph.line data=model.myLineData}} {{graph.area data=model.myAreaData}} {{/nf.graph}} {{#nf.y-axis as |tick|}} {{tick.value}} {{/nf.y-axis}} {{#nf.x-axis as |tick|}} {{tick.value}} {{/nf.x-axis}} {{/nf-graph}} ``` ## Installation This set of Ember components requires [Ember-CLI](http://ember-cli.com) 0.2.0 or higher and [Ember](http://emberjs.com) 1.10.0 or higher. To install, simply run `ember install ember-nf-graph`, or `npm install -D ember-nf-graph` ## Documentation - Online at: [netflix.github.io/ember-nf-graph/docs](//netflix.github.io/ember-nf-graph/docs) (generated by [YUIDocs](http://yui.github.io/yuidoc/)) - In package: Documentation for these components is included in the package, and can be found under `node_modules/ember-nf-graph/docs/index.html` just open in any browser. ---- ## Contributing * `git clone` this repository * `npm install` ### Running * `ember server` * Visit your app at http://localhost:4200. ### Running Tests * `ember test` * `ember test --server` ### Building * `ember build` For more information on using ember-cli, visit [http://www.ember-cli.com/](http://www.ember-cli.com/). ### Generating Documentation This project uses YUIDoc to generate documentation. Once YUIDoc is installed run: ```sh yuidoc -c yuidoc.json ``` The documentation is located in `docs/`. ================================================ FILE: addon/.gitkeep ================================================ ================================================ FILE: addon/components/.gitignore ================================================ node_modules ================================================ FILE: addon/components/nf-area-stack.js ================================================ import { schedule } from '@ember/runloop'; import { A } from '@ember/array'; import { warn } from '@ember/debug'; import Component from '@ember/component'; import { computed } from '@ember/object'; import layout from 'ember-nf-graph/templates/components/nf-area-stack'; /** A component for grouping and stacking `nf-area` components in an `nf-graph`. This component looks at the order of the `nf-area` components underneath it and uses the ydata of the next sibling `nf-area` component to determine the bottom of each `nf-area` components path to be drawn. ### Example {{#nf-graph width=300 height=100}} {{#nf-graph-content}} {{#nf-area-stack}} {{nf-area data=myData xprop="time" yprop="high"}} {{nf-area data=myData xprop="time" yprop="med"}} {{nf-area data=myData xprop="time" yprop="low"}} {{/nf-area-stack}} {{/nf-graph-content}} {{/nf-graph}} @namespace components @class nf-area-stack */ export default Component.extend({ layout, tagName: 'g', /** The parent graph for a component. @property graph @type components.nf-graph @default null */ graph: null, /** Whether or not to add the values together to create the stacked area @property aggregate @type {boolean} @default false */ aggregate: computed({ get() { warn('nf-area-stack.aggregate must be set. Currently defaulting to `false` but will default to `true` in the future.'); return this._aggregate = false; }, set(key, value) { return this._aggregate = value; } }), /** The collection of `nf-area` components under this stack. @property areas @type Array @readonly */ areas: computed(function(){ return A(); }), /** Registers an area component with this stack. Also links areas to one another by setting `nextArea` on each area component. @method registerArea @param area {Ember.Component} The area component to register. */ registerArea: function(area) { let areas = this.get('areas'); let prev = areas[areas.length - 1]; schedule('afterRender', () => { if(prev) { prev.set('nextArea', area); area.set('prevArea', prev); } areas.pushObject(area); }); }, /** Unregisters an area component from this stack. Also updates next and previous links. @method unregisterArea @param area {Ember.Component} the area to unregister */ unregisterArea: function(area) { let prev = area.get('prevArea'); let next = area.get('nextArea'); schedule('afterRender', () => { if(next) { next.set('prevArea', prev); } if(prev) { prev.set('nextArea', next); } this.get('areas').removeObject(area); }); }, }); ================================================ FILE: addon/components/nf-area.js ================================================ import { computed } from '@ember/object'; import { on } from '@ember/object/evented'; import Component from '@ember/component'; import layout from 'ember-nf-graph/templates/components/nf-area'; import Selectable from 'ember-nf-graph/mixins/graph-selectable-graphic'; import RegisteredGraphic from 'ember-nf-graph/mixins/graph-registered-graphic'; import DataGraphic from 'ember-nf-graph/mixins/graph-data-graphic'; import AreaUtils from 'ember-nf-graph/mixins/graph-area-utils'; import GraphicWithTrackingDot from 'ember-nf-graph/mixins/graph-graphic-with-tracking-dot'; import RequireScaleSource from 'ember-nf-graph/mixins/graph-requires-scale-source'; import LineUtils from 'ember-nf-graph/mixins/graph-line-utils'; /** Adds an area graph to an `nf-graph` component. Optionally, if it's located within an `nf-area-stack` component, it will work with sibling `nf-area` components to create a stacked graph. @namespace components @class nf-area @extends Ember.Component @uses mixins.graph-area-utils @uses mixins.graph-selectable-graphic @uses mixins.graph-registered-graphic @uses mixins.graph-data-graphic @uses mixins.graph-graphic-with-tracking-dot @uses mixins.graph-requires-scale-source */ export default Component.extend(RegisteredGraphic, DataGraphic, Selectable, AreaUtils, GraphicWithTrackingDot, RequireScaleSource, LineUtils, { layout, tagName: 'g', classNameBindings: [':nf-area', 'selected', 'selectable'], /** The parent graph for a component. @property graph @type components.nf-graph @default null */ graph: null, /** The type of d3 interpolator to use to create the area @property interpolator @type String @default 'linear' */ interpolator: 'linear', /** The previous area in the stack, if this area is part of an `nf-area-stack` @property prevArea @type components.nf-area @default null */ prevArea: null, /** The next area in the stack, if this area is part of an `nf-area-stack` @property nextArea @type components.nf-area @default null */ nextArea: null, stack: null, init() { this._super(...arguments); let stack = this.get('stack'); if(stack) { stack.registerArea(this); this.set('stack', stack); } }, /** Override from `graph-data-graphic` mixin @method getActualTrackData */ getActualTrackData(renderX, renderY, data) { return { x: this.get('xPropFn')(data), y: this.get('yPropFn')(data) }; }, _unregisterArea: on('willDestroyElement', function(){ let stack = this.get('stack'); if(stack) { stack.unregisterArea(this); } }), /** The computed set of next y values to use for the "bottom" of the graphed area. If the area is part of a stack, this will be the "top" of the next area in the stack, otherwise it will return an array of values at the "bottom" of the graph domain. @property nextYData @type Array @readonly */ nextYData: computed('data.length', 'nextArea.data.[]', function(){ let data = this.get('data'); if(!Array.isArray(data)) { return []; } let nextData = this.get('nextArea.mappedData'); return data.map((d, i) => (nextData && nextData[i] && nextData[i][1]) || Number.MIN_VALUE); }), /** The current rendered data "zipped" together with the nextYData. @property mappedData @type Array @readonly */ mappedData: computed('data.[]', 'xPropFn', 'yPropFn', 'nextYData.[]', 'stack.aggregate', function() { let { data, xPropFn, yPropFn, nextYData } = this.getProperties('data', 'xPropFn', 'yPropFn', 'nextYData'); let aggregate = this.get('stack.aggregate'); if(Array.isArray(data)) { return data.map((d, i) => { let x = xPropFn(d); let y = yPropFn(d); let result = aggregate ? [x, y + nextYData[i], nextYData[i]] : [x, y, nextYData[i]]; result.data = d; return result; }); } else { return []; } }), areaFn: computed('xScale', 'yScale', 'interpolator', function(){ let { xScale, yScale, interpolator } = this.getProperties('xScale', 'yScale', 'interpolator'); return this.createAreaFn(xScale, yScale, interpolator); }), lineFn: computed('xScale', 'yScale', 'interpolator', function(){ let { xScale, yScale, interpolator } = this.getProperties('xScale', 'yScale', 'interpolator'); return this.createLineFn(xScale, yScale, interpolator); }), d: computed('renderedData', 'areaFn', function(){ let renderedData = this.get('renderedData'); return this.get('areaFn')(renderedData); }), dLine: computed('renderedData', 'lineFn', function(){ let renderedData = this.get('renderedData'); return this.get('lineFn')(renderedData); }), click: function(){ if(this.get('selectable')) { this.toggleProperty('selected'); } } }); ================================================ FILE: addon/components/nf-bars-group.js ================================================ import { schedule } from '@ember/runloop'; import { A } from '@ember/array'; import { computed } from '@ember/object'; import Component from '@ember/component'; import layout from 'ember-nf-graph/templates/components/nf-bars-group'; import RequiresScaleSource from 'ember-nf-graph/mixins/graph-requires-scale-source'; export default Component.extend(RequiresScaleSource, { layout, tagName: 'g', /** The parent graph for a component. @property graph @type components.nf-graph @default null */ graph: null, groupPadding: 0.1, groupOuterPadding: 0, // either b-arses or fat, stupid hobbitses barses: computed(function(){ return A(); }), registerBars: function(bars) { schedule('afterRender', () => { let barses = this.get('barses'); barses.pushObject(bars); bars.set('group', this); bars.set('groupIndex', barses.length - 1); }); }, unregisterBars: function(bars) { if(bars) { schedule('afterRender', () => { bars.set('group', undefined); bars.set('groupIndex', undefined); this.get('barses').removeObject(bars); }); } }, groupWidth: computed('xScale', function(){ let xScale = this.get('xScale'); return xScale && xScale.rangeBand ? xScale.rangeBand() : NaN; }), barsDomain: computed('barses.[]', function(){ let len = this.get('barses.length') || 0; return d3.range(len); }), barScale: computed( 'groupWidth', 'barsDomain.[]', 'groupPadding', 'groupOuterPadding', function(){ let barsDomain = this.get('barsDomain'); let groupWidth = this.get('groupWidth'); let groupPadding = this.get('groupPadding'); let groupOuterPadding = this.get('groupOuterPadding'); return d3.scale.ordinal() .domain(barsDomain) .rangeBands([0, groupWidth], groupPadding, groupOuterPadding); } ), barsWidth: function() { let scale = this.get('barScale'); return scale && scale.rangeBand ? scale.rangeBand() : NaN; }, }); ================================================ FILE: addon/components/nf-bars.js ================================================ import { isArray, A } from '@ember/array'; import { oneWay } from '@ember/object/computed'; import { computed } from '@ember/object'; import Component from '@ember/component'; import layout from 'ember-nf-graph/templates/components/nf-bars'; import DataGraphic from 'ember-nf-graph/mixins/graph-data-graphic'; import RegisteredGraphic from 'ember-nf-graph/mixins/graph-registered-graphic'; import parsePropExpr from 'ember-nf-graph/utils/parse-property-expression'; import RequireScaleSource from 'ember-nf-graph/mixins/graph-requires-scale-source'; import GraphicWithTrackingDot from 'ember-nf-graph/mixins/graph-graphic-with-tracking-dot'; import { normalizeScale } from 'ember-nf-graph/utils/nf/scale-utils'; import { getRectPath } from 'ember-nf-graph/utils/nf/svg-dom'; /** Adds a bar graph to an `nf-graph` component. **Requires the graph has `xScaleType === 'ordinal'`*** ** `showTrackingDot` defaults to `false` in this component ** @namespace components @class nf-bars @extends Ember.Component @uses mixins.graph-registered-graphic @uses mixins.graph-data-graphic @uses mixins.graph-requires-scale-source @uses mixins.graph-graphic-with-tracking-dot */ export default Component.extend(RegisteredGraphic, DataGraphic, RequireScaleSource, GraphicWithTrackingDot, { layout, tagName: 'g', classNames: ['nf-bars'], _showTrackingDot: false, /** The parent graph for a component. @property graph @type components.nf-graph @default null */ graph: null, /** The name of the property on each data item containing the className for the bar rectangle @property classprop @type String @default 'className' */ classprop: 'className', /** Gets the function to get the classname from each data item. @property getBarClass @readonly @private */ getBarClass: computed('classprop', function() { let classprop = this.get('classprop'); return classprop ? parsePropExpr(classprop) : null; }), /** The nf-bars-group this belongs to, if any. @property group @type components.nf-bars-group @default null */ group: null, /** The index of this component within the group, if any. @property groupIndex @type Number @default null */ groupIndex: null, /** The graph content height @property graphHeight @type Number @readonly */ graphHeight: oneWay('graph.graphHeight'), /** A scale provided by nf-bars-group to offset the bar rectangle output @property barScale @type d3.scale @readonly */ barScale: oneWay('group.barScale'), /** The width of each bar. @property barWidth @type Number @readonly */ barWidth: computed('xScale', 'barScale', function(){ let barScale = this.get('barScale'); if(barScale) { return barScale.rangeBand(); } let xScale = this.get('xScale'); return xScale && xScale.rangeBand ? xScale.rangeBand() : 0; }), groupOffsetX: computed('barScale', 'groupIndex', function(){ let barScale = this.get('barScale'); let groupIndex = this.get('groupIndex'); return normalizeScale(barScale, groupIndex); }), /** The bar models used to render the bars. @property bars @readonly */ bars: computed( 'xScale', 'yScale', 'renderedData.[]', 'graphHeight', 'getBarClass', 'barWidth', 'groupOffsetX', function(){ let { renderedData, xScale, yScale, barWidth, graphHeight, getBarClass, groupOffsetX } = this.getProperties('renderedData', 'xScale', 'yScale', 'graphHeight', 'getBarClass', 'groupOffsetX', 'barWidth'); let getRectPath = this._getRectPath; if(!xScale || !yScale || !isArray(renderedData)) { return null; } let w = barWidth; return A(renderedData.map(function(data) { let className = 'nf-bars-bar' + (getBarClass ? ' ' + getBarClass(data.data) : ''); let x = normalizeScale(xScale, data[0]) + groupOffsetX; let y = normalizeScale(yScale, data[1]); let h = graphHeight - y; let path = getRectPath(x, y, w, h); return { path, className, data }; })); } ), _getRectPath: getRectPath, /** The name of the action to fire when a bar is clicked. @property barClick @type String @default null */ barClick: null, init() { this._super(...arguments); let group = this.get('group'); if(group && group.registerBars) { group.registerBars(this); } }, actions: { nfBarClickBar: function(dataPoint) { if(this.get('barClick')) { this.sendAction('barClick', { data: dataPoint.data, x: dataPoint[0], y: dataPoint[1], source: this, graph: this.get('graph'), }); } } } }); ================================================ FILE: addon/components/nf-brush-selection.js ================================================ import { alias } from '@ember/object/computed'; import { scheduleOnce } from '@ember/runloop'; import { on } from '@ember/object/evented'; import { get, observer, computed } from '@ember/object'; import Component from '@ember/component'; import layout from 'ember-nf-graph/templates/components/nf-brush-selection'; import RequiresScaleSource from 'ember-nf-graph/mixins/graph-requires-scale-source'; export default Component.extend(RequiresScaleSource, { layout, tagName: 'g', /** The parent graph for a component. @property graph @type components.nf-graph @default null */ graph: null, left: undefined, right: undefined, formatter: null, textPadding: 3, autoWireUp: true, _autoBrushHandler: function(e) { this.set('left', get(e, 'left.x')); this.set('right', get(e, 'right.x')); }, _autoBrushEndHandler: function() { this.set('left', undefined); this.set('right', undefined); }, _wireToGraph: function(){ let graph = this.get('graph'); let auto = this.get('autoWireUp'); if(auto) { graph.on('didBrushStart', this, this._autoBrushHandler); graph.on('didBrush', this, this._autoBrushHandler); graph.on('didBrushEnd', this, this._autoBrushEndHandler); } else { graph.off('didBrushStart', this, this._autoBrushHandler); graph.off('didBrush', this, this._autoBrushHandler); graph.off('didBrushEnd', this, this._autoBrushEndHandler); } }, _autoWireUpChanged: on('didInsertElement', observer('autoWireUp', function(){ scheduleOnce('afterRender', this, this._wireToGraph); })), _updateLeftText: function(){ let root = d3.select(this.element); let g = root.select('.nf-brush-selection-left-display'); let text = g.select('.nf-brush-selection-left-text'); let bg = g.select('.nf-brush-selection-left-text-bg'); let display = this.get('leftDisplay'); if(!display) { g.attr('hidden', true); } else { g.attr('hidden', null); } text.text(display); let textPadding = this.get('textPadding'); let leftX = this.get('leftX'); let graphHeight = this.get('graphHeight'); let bbox = text[0][0].getBBox(); let doublePad = textPadding * 2; let width = bbox.width + doublePad; let height = bbox.height + doublePad; let x = Math.max(0, leftX - width); let y = graphHeight - height; g.attr('transform', `translate(${x} ${y})`); text.attr('x', textPadding). attr('y', textPadding); bg.attr('width', width). attr('height', height); }, _onLeftChange: on( 'didInsertElement', observer('left', 'graphHeight', 'textPadding', function(){ scheduleOnce('afterRender', this, this._updateLeftText); }) ), _updateRightText: function(){ let root = d3.select(this.element); let g = root.select('.nf-brush-selection-right-display'); let text = g.select('.nf-brush-selection-right-text'); let bg = g.select('.nf-brush-selection-right-text-bg'); let display = this.get('rightDisplay'); if(!display) { g.attr('hidden', true); } else { g.attr('hidden', null); } text.text(display); let textPadding = this.get('textPadding'); let rightX = this.get('rightX'); let graphHeight = this.get('graphHeight'); let graphWidth = this.get('graphWidth'); let bbox = text[0][0].getBBox(); let doublePad = textPadding * 2; let width = bbox.width + doublePad; let height = bbox.height + doublePad; let x = Math.min(graphWidth - width, rightX); let y = graphHeight - height; g.attr('transform', `translate(${x} ${y})`); text.attr('x', textPadding). attr('y', textPadding); bg.attr('width', width). attr('height', height); }, _onRightChange: on( 'didInsertElement', observer('right', 'graphHeight', 'graphWidth', 'textPadding', function(){ scheduleOnce('afterRender', this, this._updateRightText); }) ), leftDisplay: computed('left', 'formatter', function(){ let formatter = this.get('formatter'); let left = this.get('left'); return formatter ? formatter(left) : left; }), rightDisplay: computed('right', 'formatter', function(){ let formatter = this.get('formatter'); let right = this.get('right'); return formatter ? formatter(right) : right; }), isVisible: computed('left', 'right', function(){ let left = +this.get('left'); let right = +this.get('right'); return left === left && right === right; }), leftX: computed('xScale', 'left', function() { let left = this.get('left') || 0; let scale = this.get('xScale'); return scale ? scale(left) : 0; }), rightX: computed('xScale', 'right', function() { let right = this.get('right') || 0; let scale = this.get('xScale'); return scale ? scale(right) : 0; }), graphWidth: alias('graph.graphWidth'), graphHeight: alias('graph.graphHeight'), rightWidth: computed('rightX', 'graphWidth', function() { return Math.max(this.get('graphWidth') - this.get('rightX'), 0); }), }); ================================================ FILE: addon/components/nf-component.js ================================================ import Component from '@ember/component'; import { assert } from '@ember/debug'; import { isPresent } from '@ember/utils'; import layout from '../templates/components/nf-component'; /** Renders a custom component with the given component name. ## Example The following example will render a custom svg image component at (0, 50): {{#graph.component 'my-custom-svg-image' as |image|}} {{component image src="images/star.svg"}} {{/graph.component}} @namespace components @class nf-component @extends Ember.Component */ const NfComponent = Component.extend({ layout, tagName: '', /** The name of the component to be rendered. @property componentName @type String @default '' */ componentName: '', /** The parent graph for a component. @property graph @type components.nf-graph @default null */ graph: null, /** The scale source @property scaleSource @type d3.nf-graph @default graph */ scaleSource: null, init(){ this._super(...arguments); assert('[ember-nf-graph] A component name must be passed into nf-component.', isPresent(this.get('componentName'))); } }); NfComponent.reopenClass({ positionalParams: ['componentName'] }); export default NfComponent; ================================================ FILE: addon/components/nf-crosshairs.js ================================================ import { schedule } from '@ember/runloop'; import { alias } from '@ember/object/computed'; import Component from '@ember/component'; import { on } from '@ember/object/evented'; import { observer } from '@ember/object'; import layout from 'ember-nf-graph/templates/components/nf-crosshairs'; /** A component that adds "crosshairs" to an `nf-graph` that follows the mouse while it's hovering over the graph content. @namespace components @class nf-crosshair @extends Ember.Component @uses mixins.graph-has-graph-parent */ export default Component.extend({ layout, tagName: 'g', classNames: ['nf-crosshairs'], /** The parent graph for a component. @property graph @type components.nf-graph @default null */ graph: null, /** The height of the crosshair in pixels @property height @type Number @readonly */ height: alias('graph.graphHeight'), /** The width of the crosshair in pixels @property width @type Number @readonly */ width: alias('graph.graphWidth'), /** The x position of the crosshairs @property x @type Number @default 0 */ x: 0, /** The y position of the crosshairs @property y @type Number @default 0 */ y: 0, /** Whether to show the vertical line in the corsshairs @property vertical @type Boolean @default true */ vertical: true, /** Whether to show the horizontal line in the corsshairs @property horizontal @type Boolean @default true */ horizontal: true, /** The visibility of the component @property isVisible @type Boolean @default false */ isVisible: false, didContentHoverChange: function(e) { this.set('isVisible', true); this.set('x', e.get('mouseX')); this.set('y', e.get('mouseY')); }, didContentHoverEnd: function() { this.set('isVisible', false); }, _setupBindings: on('didInsertElement', observer('graph.content', function() { let content = this.get('graph.content'); if(content) { schedule('afterRender', () => { content.on('didHoverChange', this, this.didContentHoverChange); content.on('didHoverEnd', this, this.didContentHoverEnd); }); } })), }); ================================================ FILE: addon/components/nf-dot.js ================================================ import { computed } from '@ember/object'; import { notEmpty, and } from '@ember/object/computed'; import Component from '@ember/component'; import layout from 'ember-nf-graph/templates/components/nf-dot'; import RequireScaleSource from 'ember-nf-graph/mixins/graph-requires-scale-source'; /** Plots a circle at a given x and y domain value on an `nf-graph`. @namespace components @class nf-dot @extends Ember.Component @uses mixins.graph-requires-scale-source */ export default Component.extend(RequireScaleSource, { layout, tagName: 'circle', attributeBindings: ['r', 'cy', 'cx'], /** The parent graph for a component. @property graph @type components.nf-graph @default null */ graph: null, /** The x domain value at which to plot the circle @property x @type Number @default null */ x: null, /** The y domain value at which to plot the circle @property x @type Number @default null */ y: null, /** The radius of the circle plotted @property r @type Number @default 2.5 */ r: 2.5, hasX: notEmpty('x'), hasY: notEmpty('y'), /** The computed center x coordinate of the circle @property cx @type Number @private @readonly */ cx: computed('x', 'xScale', 'hasX', function(){ let x = this.get('x'); let xScale = this.get('xScale'); let hasX = this.get('hasX'); return hasX && xScale ? xScale(x) : -1; }), /** The computed center y coordinate of the circle @property cy @type Number @private @readonly */ cy: computed('y', 'yScale', 'hasY', function() { let y = this.get('y'); let yScale = this.get('yScale'); let hasY = this.get('hasY'); return hasY && yScale ? yScale(y) : -1; }), /** Toggles the visibility of the dot. If x or y are not numbers, will return false. @property isVisible @private @readonly */ isVisible: and('hasX', 'hasY'), }); ================================================ FILE: addon/components/nf-graph-content.js ================================================ import { schedule } from '@ember/runloop'; import { A } from '@ember/array'; import { alias } from '@ember/object/computed'; import { computed } from '@ember/object'; import Component from '@ember/component'; import layout from 'ember-nf-graph/templates/components/nf-graph-content'; import GraphMouseEvent from 'ember-nf-graph/utils/nf/graph-mouse-event'; /** Container component for graphics to display in `nf-graph`. Represents the area where the graphics, such as lines will display. Exists for layout purposes. @namespace components @class nf-graph-content */ export default Component.extend({ layout, tagName: 'g', classNames: ['nf-graph-content'], attributeBindings: ['transform', 'clip-path'], 'clip-path': computed('graph.contentClipPathId', function(){ let clipPathId = this.get('graph.contentClipPathId'); return `url('#${clipPathId}')`; }), /** The parent graph for a component. @property graph @type components.nf-graph @default null */ graph: null, /** The SVG transform for positioning the graph content @property transform @type String @readonly */ transform: computed('x', 'y', function(){ let x = this.get('x'); let y = this.get('y'); return `translate(${x} ${y})`; }), /** The x position of the graph content @property x @type Number @readonly */ x: alias('graph.graphX'), /** The calculated y position of the graph content @property y @type Number @readonly */ y: alias('graph.graphY'), /** The calculated width of the graph content @property width @type Number @readonly */ width: alias('graph.graphWidth'), /** The calculated height of the graph content. @property height @type Number @readonly */ height: alias('graph.graphHeight'), /** An array containing models to render the grid lanes @property gridLanes @type Array @readonly */ gridLanes: computed('graph.yAxis.ticks', 'width', 'height', function () { let ticks = this.get('graph.yAxis.ticks'); let width = this.get('width'); let height = this.get('height'); if(!ticks || ticks.length === 0) { return A(); } let sorted = ticks.slice().sort(function(a, b) { return a.y - b.y; }); if(sorted[0].y !== 0) { sorted.unshift({ y: 0 }); } let lanes = sorted.reduce(function(lanes, tick, i) { let y = tick.y; let next = sorted[i+1] || { y: height }; let h = Math.max(next.y - tick.y, 0); lanes.push({ x: 0, y: y, width: width, height: h }); return lanes; }, []); return A(lanes); }), /** The name of the hoverChange action to fire @property hoverChange @type String @default null */ hoverChange: null, mouseMove: function(e) { let context = GraphMouseEvent.create({ originalEvent: e, source: this, graphContentElement: this.element, }); this.trigger('didHoverChange', context); if(this.get('hoverChange')) { this.sendAction('hoverChange', context); } }, /** The name of the hoverEnd action to fire @property hoverEnd @type String @default null */ hoverEnd: null, mouseLeave: function(e) { let context = GraphMouseEvent.create({ originalEvent: e, source: this, graphContentElement: this.element }); this.trigger('didHoverEnd', context); if(this.get('hoverEnd')) { this.sendAction('hoverEnd', context); } }, /** An array containing models to render fret lines @property frets @type Array @readonly */ frets: alias('graph.xAxis.ticks'), init(){ this._super(...arguments); schedule('afterRender', () => { this.set('graph.content', this); }); }, }); ================================================ FILE: addon/components/nf-graph-yieldables.js ================================================ import Component from '@ember/component'; import layout from 'ember-nf-graph/templates/components/nf-graph-yieldables'; export default Component.extend({ layout, tagName: '', /** The parent graph for the components. @property graph @type components.nf-graph @default null */ graph: null, /** The scale source for the components @property scaleSource @default null */ scaleSource: null, }); ================================================ FILE: addon/components/nf-graph.js ================================================ import { bool, notEmpty } from '@ember/object/computed'; import $ from 'jquery'; import { on } from '@ember/object/evented'; import { warn } from '@ember/debug'; import { A } from '@ember/array'; import { scheduleOnce, schedule, run } from '@ember/runloop'; import Component from '@ember/component'; import { isPresent } from '@ember/utils'; import { computed, observer } from '@ember/object'; import layout from 'ember-nf-graph/templates/components/nf-graph'; import GraphPosition from 'ember-nf-graph/utils/nf/graph-position'; import { getMousePoint } from 'ember-nf-graph/utils/nf/svg-dom'; import { toArray } from 'ember-nf-graph/utils/nf/array-helpers'; const Observable = Rx.Observable; const computedBool = bool; let minProperty = function(axis, defaultTickCount){ let _DataExtent_ = axis + 'DataExtent'; let _MinMode_ = axis + 'MinMode'; let _Axis_tickCount_ = axis + 'Axis.tickCount'; let _ScaleFactory_ = axis + 'ScaleFactory'; let __Min_ = '_' + axis + 'Min'; let _prop_ = axis + 'Min'; let _autoScaleEvent_ = 'didAutoUpdateMin' + axis.toUpperCase(); return computed( _MinMode_, _DataExtent_, _Axis_tickCount_, _ScaleFactory_, 'graphHeight', 'graphWidth', { get() { let mode = this.get(_MinMode_); let ext; let change = val => { this.set(_prop_, val); this.trigger(_autoScaleEvent_); }; if(mode === 'auto') { change(this.get(_DataExtent_)[0] || 0); } else if(mode === 'push') { ext = this.get(_DataExtent_)[0]; if(!isNaN(ext) && ext < this[__Min_]) { change(ext); } } else if(mode === 'push-tick') { let extent = this.get(_DataExtent_); ext = extent[0]; if(!isNaN(ext) && ext < this[__Min_]) { let tickCount = this.get(_Axis_tickCount_) || defaultTickCount; let newDomain = this.get(_ScaleFactory_)().domain(extent).nice(tickCount).domain(); change(newDomain[0]); } } return this[__Min_]; }, set(key, value) { if (isPresent(value) && !isNaN(value)) { this[__Min_] = value; } return this[__Min_]; } } ); }; let maxProperty = function(axis, defaultTickCount) { let _DataExtent_ = axis + 'DataExtent'; let _Axis_tickCount_ = axis + 'Axis.tickCount'; let _ScaleFactory_ = axis + 'ScaleFactory'; let _MaxMode_ = axis + 'MaxMode'; let __Max_ = '_' + axis + 'Max'; let _prop_ = axis + 'Max'; let _autoScaleEvent_ = 'didAutoUpdateMax' + axis.toUpperCase(); return computed( _MaxMode_, _DataExtent_, _ScaleFactory_, _Axis_tickCount_, 'graphHeight', 'graphWidth', { get() { let mode = this.get(_MaxMode_); let ext; let change = val => { this.set(_prop_, val); this.trigger(_autoScaleEvent_); }; if(mode === 'auto') { change(this.get(_DataExtent_)[1] || 1); } else if(mode === 'push') { ext = this.get(_DataExtent_)[1]; if(!isNaN(ext) && this[__Max_] < ext) { change(ext); } } else if(mode === 'push-tick') { let extent = this.get(_DataExtent_); ext = extent[1]; if(!isNaN(ext) && this[__Max_] < ext) { let tickCount = this.get(_Axis_tickCount_) || defaultTickCount; let newDomain = this.get(_ScaleFactory_)().domain(extent).nice(tickCount).domain(); change(newDomain[1]); } } return this[__Max_]; }, set(key, value) { if (isPresent(value) && !isNaN(value)) { this[__Max_] = value; } return this[__Max_]; } } ); }; /** A container component for building complex Cartesian graphs. ## Minimal example {{#nf-graph width=100 height=50}} {{#nf-graph-content}} {{nf-line data=lineData xprop="foo" yprop="bar"}} {{/nf-graph-content}} {{/nf-graph}} The above will create a simple 100x50 graph, with no axes, and a single line plotting the data it finds on each object in the array `lineData` at properties `foo` and `bar` for x and y values respectively. ## More advanced example {{#nf-graph width=500 height=300}} {{#nf-x-axis height="50" as |tick|}} {{tick.value}} {{/nf-x-axis}} {{#nf-y-axis width="120" as |tick|}} {{tick.value}} {{/nf-y-axis}} {{#nf-graph-content}} {{nf-line data=lineData xprop="foo" yprop="bar"}} {{/nf-graph-content}} {{/nf-graph}} The above example will create a 500x300 graph with both axes visible. The graph will not render either axis unless its component is present. @namespace components @class nf-graph @extends Ember.Component */ export default Component.extend({ layout, tagName: 'div', /** The exponent to use for xScaleType "pow" or "power". @property xPowerExponent @type Number @default 3 */ xPowerExponent: 3, /** The exponent to use for yScaleType "pow" or "power". @property yPowerExponent @type Number @default 3 */ yPowerExponent: 3, /** The min value to use for xScaleType "log" if xMin <= 0 @property xLogMin @type Number @default 0.1 */ xLogMin: 0.1, /** The min value to use for yScaleType "log" if yMin <= 0 @property yLogMin @type Number @default 0.1 */ yLogMin: 0.1, /** @property hasRendered @private */ hasRendered: false, /** Gets or sets the whether or not multiple selectable graphics may be selected simultaneously. @property selectMultiple @type Boolean @default false */ selectMultiple: false, /** The width of the graph in pixels. @property width @type Number @default 300 */ width: 300, /** The height of the graph in pixels. @property height @type Number @default 100 */ height: 100, /** The padding at the top of the graph @property paddingTop @type Number @default 0 */ paddingTop: 0, /** The padding at the left of the graph @property paddingLeft @type Number @default 0 */ paddingLeft: 0, /** The padding at the right of the graph @property paddingRight @type Number @default 0 */ paddingRight: 0, /** The padding at the bottom of the graph @property paddingBottom @type Number @default 0 */ paddingBottom: 0, /** Determines whether to display "lanes" in the background of the graph. @property showLanes @type Boolean @default false */ showLanes: false, /** Determines whether to display "frets" in the background of the graph. @property showFrets @type Boolean @default false */ showFrets: false, /** The type of scale to use for x values. Possible Values: - `'linear'` - a standard linear scale - `'log'` - a logarithmic scale - `'power'` - a power-based scale (exponent = 3) - `'ordinal'` - an ordinal scale, used for ordinal data. required for bar graphs. @property xScaleType @type String @default 'linear' */ xScaleType: 'linear', /** The type of scale to use for y values. Possible Values: - `'linear'` - a standard linear scale - `'log'` - a logarithmic scale - `'power'` - a power-based scale (exponent = 3) - `'ordinal'` - an ordinal scale, used for ordinal data. required for bar graphs. @property yScaleType @type String @default 'linear' */ yScaleType: 'linear', /** The padding between value steps when `xScaleType` is `'ordinal'` @property xOrdinalPadding @type Number @default 0.1 */ xOrdinalPadding: 0.1, /** The padding at the ends of the domain data when `xScaleType` is `'ordinal'` @property xOrdinalOuterPadding @type Number @default 0.1 */ xOrdinalOuterPadding: 0.1, /** The padding between value steps when `xScaleType` is `'ordinal'` @property yOrdinalPadding @type Number @default 0.1 */ yOrdinalPadding: 0.1, /** The padding at the ends of the domain data when `yScaleType` is `'ordinal'` @property yOrdinalOuterPadding @type Number @default 0.1 */ yOrdinalOuterPadding: 0.1, /** the `nf-y-axis` component is registered here if there is one present @property yAxis @readonly @default null */ yAxis: null, /** The `nf-x-axis` component is registered here if there is one present @property xAxis @readonly @default null */ xAxis: null, /** Backing field for `xMin` @property _xMin @private */ _xMin: null, /** Backing field for `xMax` @property _xMax @private */ _xMax: null, /** Backing field for `yMin` @property _yMin @private */ _yMin: null, /** Backing field for `yMax` @property _yMax @private */ _yMax: null, /** Gets or sets the minimum x domain value to display on the graph. Behavior depends on `xMinMode`. @property xMin */ xMin: minProperty('x', 8), /** Gets or sets the maximum x domain value to display on the graph. Behavior depends on `xMaxMode`. @property xMax */ xMax: maxProperty('x', 8), /** Gets or sets the minimum y domain value to display on the graph. Behavior depends on `yMinMode`. @property yMin */ yMin: minProperty('y', 5), /** Gets or sets the maximum y domain value to display on the graph. Behavior depends on `yMaxMode`. @property yMax */ yMax: maxProperty('y', 5), /** Sets the behavior of `xMin` for the graph. ### Possible values: - 'auto': (default) xMin is always equal to the minimum domain value contained in the graphed data. Cannot be set. - 'fixed': xMin can be set to an exact value and will not change based on graphed data. - 'push': xMin can be set to a specific value, but will update if the minimum x value contained in the graph is less than what xMin is currently set to. - 'push-tick': xMin can be set to a specific value, but will update to next "nice" tick if the minimum x value contained in the graph is less than that xMin is set to. @property xMinMode @type String @default 'auto' */ xMinMode: 'auto', /** Sets the behavior of `xMax` for the graph. ### Possible values: - 'auto': (default) xMax is always equal to the maximum domain value contained in the graphed data. Cannot be set. - 'fixed': xMax can be set to an exact value and will not change based on graphed data. - 'push': xMax can be set to a specific value, but will update if the maximum x value contained in the graph is greater than what xMax is currently set to. - 'push-tick': xMax can be set to a specific value, but will update to next "nice" tick if the maximum x value contained in the graph is greater than that xMax is set to. @property xMaxMode @type String @default 'auto' */ xMaxMode: 'auto', /** Sets the behavior of `yMin` for the graph. ### Possible values: - 'auto': (default) yMin is always equal to the minimum domain value contained in the graphed data. Cannot be set. - 'fixed': yMin can be set to an exact value and will not change based on graphed data. - 'push': yMin can be set to a specific value, but will update if the minimum y value contained in the graph is less than what yMin is currently set to. - 'push-tick': yMin can be set to a specific value, but will update to next "nice" tick if the minimum y value contained in the graph is less than that yMin is set to. @property yMinMode @type String @default 'auto' */ yMinMode: 'auto', /** Sets the behavior of `yMax` for the graph. ### Possible values: - 'auto': (default) yMax is always equal to the maximum domain value contained in the graphed data. Cannot be set. - 'fixed': yMax can be set to an exact value and will not change based on graphed data. - 'push': yMax can be set to a specific value, but will update if the maximum y value contained in the graph is greater than what yMax is currently set to. - 'push-tick': yMax can be set to a specific value, but will update to next "nice" tick if the maximum y value contained in the graph is greater than that yMax is set to. @property yMaxMode @type String @default 'auto' */ yMaxMode: 'auto', /** The data extents for all data in the registered `graphics`. @property dataExtents @type {Object} @default { xMin: Number.MAX_VALUE, xMax: Number.MIN_VALUE, yMin: Number.MAX_VALUE, yMax: Number.MIN_VALUE } */ dataExtents: computed('graphics.@each.data', function(){ let graphics = this.get('graphics'); return graphics.reduce((c, x) => c.concat(x.get('mappedData')), []).reduce((extents, [x, y]) => { extents.xMin = extents.xMin < x ? extents.xMin : x; extents.xMax = extents.xMax > x ? extents.xMax : x; extents.yMin = extents.yMin < y ? extents.yMin : y; extents.yMax = extents.yMax > y ? extents.yMax : y; return extents; }, { xMin: Number.MAX_VALUE, xMax: Number.MIN_VALUE, yMin: Number.MAX_VALUE, yMax: Number.MIN_VALUE }); }), /** The action to trigger when the graph automatically updates the xScale due to an "auto" "push" or "push-tick" domainMode. sends the graph component instance value as the argument. @property autoScaleXAction @type {string} @default null */ autoScaleXAction: null, _sendAutoUpdateXAction() { this.sendAction('autoScaleXAction', this); }, _sendAutoUpdateYAction() { this.sendAction('autoScaleYAction', this); }, /** Event handler that is fired for the `didAutoUpdateMaxX` event @method didAutoUpdateMaxX */ didAutoUpdateMaxX() { scheduleOnce('afterRender', this, this._sendAutoUpdateXAction); }, /** Event handler that is fired for the `didAutoUpdateMinX` event @method didAutoUpdateMinX */ didAutoUpdateMinX() { scheduleOnce('afterRender', this, this._sendAutoUpdateXAction); }, /** Event handler that is fired for the `didAutoUpdateMaxY` event @method didAutoUpdateMaxY */ didAutoUpdateMaxY() { scheduleOnce('afterRender', this, this._sendAutoUpdateYAction); }, /** Event handler that is fired for the `didAutoUpdateMinY` event @method didAutoUpdateMinY */ didAutoUpdateMinY() { scheduleOnce('afterRender', this, this._sendAutoUpdateYAction); }, /** The action to trigger when the graph automatically updates the yScale due to an "auto" "push" or "push-tick" domainMode. Sends the graph component instance as the argument. @property autoScaleYAction @type {string} @default null */ autoScaleYAction: null, /** Gets the highest and lowest x values of the graphed data in a two element array. @property xDataExtent @type Array @readonly */ xDataExtent: computed('dataExtents', function(){ let { xMin, xMax } = this.get('dataExtents'); return [xMin, xMax]; }), /** Gets the highest and lowest y values of the graphed data in a two element array. @property yDataExtent @type Array @readonly */ yDataExtent: computed('dataExtents', function(){ let { yMin, yMax } = this.get('dataExtents'); return [yMin, yMax]; }), /** @property xUniqueData @type Array @readonly */ xUniqueData: computed('graphics.@each.mappedData', function(){ let graphics = this.get('graphics'); let uniq = graphics.reduce((uniq, graphic) => { return graphic.get('mappedData').reduce((uniq, d) => { if(!uniq.some(x => x === d[0])) { uniq.push(d[0]); } return uniq; }, uniq); }, []); return A(uniq); }), /** @property yUniqueData @type Array @readonly */ yUniqueData: computed('graphics.@each.mappedData', function(){ let graphics = this.get('graphics'); let uniq = graphics.reduce((uniq, graphic) => { return graphic.get('mappedData').reduce((uniq, d) => { if(!uniq.some(y => y === d[1])) { uniq.push(d[1]); } return uniq; }, uniq); }, []); return A(uniq); }), /** Gets the DOM id for the content clipPath element. @property contentClipPathId @type String @readonly @private */ contentClipPathId: computed('elementId', function(){ return this.get('elementId') + '-content-mask'; }), /** Registry of contained graphic elements such as `nf-line` or `nf-area` components. This registry is used to pool data for scaling purposes. @property graphics @type Array @readonly */ graphics: computed(function(){ return A(); }), /** An array of "selectable" graphics that have been selected within this graph. @property selected @type Array @readonly */ selected: computed(function() { return this.get('selectMultiple') ? A() : null; }), /** Computed property to show yAxis. Returns `true` if a yAxis is present. @property showYAxis @type Boolean @default false */ showYAxis: computedBool('yAxis'), /** Computed property to show xAxis. Returns `true` if an xAxis is present. @property showXAxis @type Boolean @default false */ showXAxis: computedBool('xAxis'), /** Gets a function to create the xScale @property xScaleFactory @readonly */ // xScaleFactory: scaleFactoryProperty('x'), xScaleFactory: computed(function() { return this._scaleFactoryFor('x'); }), _scheduleXScaleFactory: observer('xScaleType', 'xPowerExponent', function() { schedule('afterRender', () => { this.set('xScaleFactory', this._scaleFactoryFor('x')); }); }), /** Gets a function to create the yScale @property yScaleFactory @readonly */ // yScaleFactory: scaleFactoryProperty('y'), yScaleFactory: computed(function() { return this._scaleFactoryFor('y'); }), _scheduleYScaleFactory: observer('yScaleType', 'yPowerExponent', function() { schedule('afterRender', () => { this.set('yScaleFactory', this._scaleFactoryFor('y')); }); }), _scaleFactoryFor(axis) { let type = this.get(`${axis}ScaleType`); let powExp = this.get(`${axis}PowerExponent`); type = typeof type === 'string' ? type.toLowerCase() : ''; if(type === 'linear') { return d3.scale.linear; } else if(type === 'ordinal') { return function(){ let scale = d3.scale.ordinal(); // ordinal scales don't have an invert function, so we need to add one scale.invert = function(rv) { let [min, max] = d3.extent(scale.range()); let domain = scale.domain(); let i = Math.round((domain.length - 1) * (rv - min) / (max - min)); return domain[i]; }; return scale; }; } else if(type === 'power' || type === 'pow') { return function(){ return d3.scale.pow().exponent(powExp); }; } else if(type === 'log') { return d3.scale.log; } else { warn('unknown scale type: ' + type); return d3.scale.linear; } }, /** Gets the domain of x values. @property xDomain @type Array @readonly */ xDomain: computed(function() { return this._domainFor('x'); }), _scheduleXDomain: observer( 'xUniqueData.[]', 'xMin', 'xMax', 'xScaleType', 'xLogMin', function() { schedule('afterRender', () => { this.set('xDomain', this._domainFor('x')); }); } ), /** Gets the domain of y values. @property yDomain @type Array @readonly */ yDomain: computed(function() { return this._domainFor('y'); }), /* NOTE: Although this can be done in a CP, we must compute this value only `afterRender` to avoid double render deprecations. */ _scheduleYDomain: observer( 'yUniqueData.[]', 'yMin', 'yMax', 'yScaleType', 'yLogMin', function() { schedule('afterRender', () => { this.set('yDomain', this._domainFor('y')); }); } ), _domainFor(axis) { let data = this.get(`${axis}UniqueData`); let min = this.get(`${axis}Min`); let max = this.get(`${axis}Max`); let scaleType = this.get(`${axis}ScaleType`); let logMin = this.get(`${axis}LogMin`); let domain = null; if(scaleType === 'ordinal') { domain = data; } else { let extent = [min, max]; if(scaleType === 'log') { if (extent[0] <= 0) { extent[0] = logMin; } if (extent[1] <= 0) { extent[1] = logMin; } } domain = extent; } return domain; }, /** Gets the current xScale used to draw the graph. @property xScale @type Function @readonly */ xScale: computed(function() { return this._scaleFor('x'); }), /* NOTE: Although this can be done in a CP, we must compute this value only `afterRender` to avoid double render deprecations. */ _scheduleXScale: observer( 'xScaleFactory', 'xRange', 'xDomain', 'xScaleType', 'xOrdinalPadding', 'xOrdinalOuterPadding', function() { schedule('afterRender', () => { this.set('xScale', this._scaleFor('x')); }); } ), /** Gets the current yScale used to draw the graph. @property yScale @type Function @readonly */ yScale: computed(function() { return this._scaleFor('y'); }), /* NOTE: Although this can be done in a CP, we must compute this value only `afterRender` to avoid double render deprecations. */ _scheduleYScale: observer( 'yScaleFactory', 'yRange', 'yDomain', 'yScaleType', 'yOrdinalPadding', 'yOrdinalOuterPadding', function() { schedule('afterRender', () => { this.set('yScale', this._scaleFor('y')); }); } ), _scaleFor(axis) { let scaleFactory = this.get(`${axis}ScaleFactory`); let range = this.get(`${axis}Range`); let domain = this.get(`${axis}Domain`); let scaleType = this.get(`${axis}ScaleType`); let ordinalPadding = this.get(`${axis}OrdinalPadding`); let ordinalOuterPadding = this.get(`${axis}OrdinalOuterPadding`); let scale = scaleFactory(); if(scaleType === 'ordinal') { scale = scale.domain(domain).rangeBands(range, ordinalPadding, ordinalOuterPadding); } else { scale = scale.domain(domain).range(range).clamp(true); } return scale; }, /** Registers a graphic such as `nf-line` or `nf-area` components with the graph. @method registerGraphic @param graphic {Ember.Component} The component object to register */ registerGraphic: function (graphic) { schedule('afterRender', () => { let graphics = this.get('graphics'); graphic.on('hasData', this, this.updateExtents); graphics.pushObject(graphic); }); }, /** Unregisters a graphic such as an `nf-line` or `nf-area` from the graph. @method unregisterGraphic @param graphic {Ember.Component} The component to unregister */ unregisterGraphic: function(graphic) { schedule('afterRender', () => { let graphics = this.get('graphics'); graphic.off('hasData', this, this.updateExtents); graphics.removeObject(graphic); }); }, updateExtents() { this.get('xDataExtent'); this.get('yDataExtent'); }, /** The y range of the graph in pixels. The min and max pixel values in an array form. @property yRange @type Array @readonly */ yRange: computed('graphHeight', function(){ return [this.get('graphHeight'), 0]; }), /** The x range of the graph in pixels. The min and max pixel values in an array form. @property xRange @type Array @readonly */ xRange: computed('graphWidth', function(){ return [0, this.get('graphWidth')]; }), /** Returns `true` if the graph has data to render. Data is conveyed to the graph by registered graphics. @property hasData @type Boolean @default false @readonly */ hasData: notEmpty('graphics'), /** The x coordinate position of the graph content @property graphX @type Number @readonly */ graphX: computed('paddingLeft', 'yAxis.{orient,width}', function() { let paddingLeft = this.get('paddingLeft'); let yAxisWidth = this.get('yAxis.width') || 0; let yAxisOrient = this.get('yAxis.orient'); if(yAxisOrient === 'right') { return paddingLeft; } return paddingLeft + yAxisWidth; }), /** The y coordinate position of the graph content @property graphY @type Number @readonly */ graphY: computed('paddingTop', 'xAxis.{orient,height}', function(){ let paddingTop = this.get('paddingTop'); let xAxisOrient = this.get('xAxis.orient'); if(xAxisOrient === 'top') { let xAxisHeight = this.get('xAxis.height') || 0; return xAxisHeight + paddingTop; } return paddingTop; }), /** The width, in pixels, of the graph content @property graphWidth @type Number @readonly */ graphWidth: computed('width', 'paddingRight', 'paddingLeft', 'yAxis.width', function() { let paddingRight = this.get('paddingRight') || 0; let paddingLeft = this.get('paddingLeft') || 0; let yAxisWidth = this.get('yAxis.width') || 0; let width = this.get('width') || 0; return Math.max(0, width - paddingRight - paddingLeft - yAxisWidth); }), /** The height, in pixels, of the graph content @property graphHeight @type Number @readonly */ graphHeight: computed('height', 'paddingTop', 'paddingBottom', 'xAxis.height', function(){ let paddingTop = this.get('paddingTop') || 0; let paddingBottom = this.get('paddingBottom') || 0; let xAxisHeight = this.get('xAxis.height') || 0; let height = this.get('height') || 0; return Math.max(0, height - paddingTop - paddingBottom - xAxisHeight); }), /** An SVG transform to position the graph content @property graphTransform @type String @readonly */ graphTransform: computed('graphX', 'graphY', function(){ let graphX = this.get('graphX'); let graphY = this.get('graphY'); return `translate(${graphX} ${graphY})`; }), /** Sets `hasRendered` to `true` on `willInsertElement`. @method _notifyHasRendered @private */ _notifyHasRendered: on('willInsertElement', function () { schedule('afterRender', () => { this.set('hasRendered', true); }); }), /** Gets the mouse position relative to the container @method mousePoint @param container {SVGElement} the SVG element that contains the mouse event @param e {Object} the DOM mouse event @return {Array} an array of `[xMouseCoord, yMouseCoord]` */ mousePoint: function (container, e) { let svg = container.ownerSVGElement || container; if (svg.createSVGPoint) { let point = svg.createSVGPoint(); point.x = e.clientX; point.y = e.clientY; point = point.matrixTransform(container.getScreenCTM().inverse()); return [ point.x, point.y ]; } let rect = container.getBoundingClientRect(); return [ e.clientX - rect.left - container.clientLeft, e.clientY - rect.top - container.clientTop ]; }, /** Selects the graphic passed. If `selectMultiple` is false, it will deselect the currently selected graphic if it's different from the one passed. @method selectGraphic @param graphic {Ember.Component} the graph component to select within the graph. */ selectGraphic: function(graphic) { if(!graphic.get('selected')) { graphic.set('selected', true); } if(this.selectMultiple) { this.get('selected').pushObject(graphic); } else { let current = this.get('selected'); if(current && current !== graphic) { current.set('selected', false); } this.set('selected', graphic); } }, /** deselects the graphic passed. @method deselectGraphic @param graphic {Ember.Component} the graph child component to deselect. */ deselectGraphic: function(graphic) { graphic.set('selected', false); if(this.selectMultiple) { this.get('selected').removeObject(graphic); } else { let current = this.get('selected'); if(current && current === graphic) { this.set('selected', null); } } }, /** The amount of leeway, in pixels, to give before triggering a brush start. @property brushThreshold @type {Number} @default 7 */ brushThreshold: 7, /** The name of the action to trigger when brushing starts @property brushStartAction @type {String} @default null */ brushStartAction: null, /** The name of the action to trigger when brushing emits a new value @property brushAction @type {String} @default null */ brushAction: null, /** The name of the action to trigger when brushing ends @property brushEndAction @type {String} @default null */ brushEndAction: null, _setupBrushAction: on('didInsertElement', function(){ let content = this.$('.nf-graph-content'); let mouseMoves = Observable.fromEvent(content, 'mousemove'); let mouseDowns = Observable.fromEvent(content, 'mousedown'); let mouseUps = Observable.fromEvent($(document), 'mouseup'); let mouseLeaves = Observable.fromEvent(content, 'mouseleave'); this._brushDisposable = Observable.merge(mouseDowns, mouseMoves, mouseLeaves). // get a streams of mouse events that start on mouse down and end on mouse up window(mouseDowns, function() { return mouseUps; }) // filter out all of them if there are no brush actions registered // map the mouse event streams into brush event streams .map(x => this._toBrushEventStreams(x)). // flatten to a stream of action names and event objects flatMap(x => this._toComponentEventStream(x)). // HACK: this is fairly cosmetic, so skip errors. retry(). // subscribe and send the brush actions via Ember subscribe(x => { run(this, () => this._triggerComponentEvent(x)); }); }), _toBrushEventStreams: function(mouseEvents) { // get the starting mouse event return mouseEvents.take(1). // calculate it's mouse point and info map( this._getStartInfo ). // combine the start with the each subsequent mouse event combineLatest(mouseEvents.skip(1), toArray). // filter out everything until the brushThreshold is crossed filter(x => this._byBrushThreshold(x)). // create the brush event object map(x => this._toBrushEvent(x)); }, _triggerComponentEvent: function(d) { this.trigger(d[0], d[1]); }, _toComponentEventStream: function(events) { return Observable.merge( events.take(1).map(function(e) { return ['didBrushStart', e]; }), events.map(function(e) { return ['didBrush', e]; }), events.last().map(function(e) { return ['didBrushEnd', e]; }) ); }, didBrush: function(e) { if(this.get('brushAction')) { this.sendAction('brushAction', e); } }, didBrushStart: function(e) { document.body.style.setProperty('-webkit-user-select', 'none'); document.body.style.setProperty('-moz-user-select', 'none'); document.body.style.setProperty('user-select', 'none'); if(this.get('brushStartAction')) { this.sendAction('brushStartAction', e); } }, didBrushEnd: function(e) { document.body.style.removeProperty('-webkit-user-select'); document.body.style.removeProperty('-moz-user-select'); document.body.style.removeProperty('user-select'); if(this.get('brushEndAction')) { this.sendAction('brushEndAction', e); } }, _toBrushEvent: function(d) { let start = d[0]; let currentEvent = d[1]; let currentPoint = getMousePoint(currentEvent.currentTarget, d[1]); let startPosition = GraphPosition.create({ originalEvent: start.originalEvent, graph: this, graphX: start.mousePoint.x, graphY: start.mousePoint.y }); let currentPosition = GraphPosition.create({ originalEvent: currentEvent, graph: this, graphX: currentPoint.x, graphY: currentPoint.y }); let left = startPosition; let right = currentPosition; if(start.originalEvent.clientX > currentEvent.clientX) { left = currentPosition; right = startPosition; } return { start: startPosition, current: currentPosition, left: left, right: right }; }, _byBrushThreshold: function(d) { let startEvent = d[0].originalEvent; let currentEvent = d[1]; return Math.abs(currentEvent.clientX - startEvent.clientX) > this.get('brushThreshold'); }, _getStartInfo: function(e) { return { originalEvent: e, mousePoint: getMousePoint(e.currentTarget, e) }; }, willDestroyElement: function(){ this._super(...arguments); if(this._brushDisposable) { this._brushDisposable.dispose(); } }, }); ================================================ FILE: addon/components/nf-group.js ================================================ import Component from '@ember/component'; import layout from 'ember-nf-graph/templates/components/nf-group'; import RequireScaleSource from 'ember-nf-graph/mixins/graph-requires-scale-source'; import SelectableGraphic from 'ember-nf-graph/mixins/graph-selectable-graphic'; /** A grouping tag that provides zooming and offset functionality to it's children. ## Example The following example will show a line of `someData` with a 2x zoom, offset by 30px in both x and y directions: {{#nf-gg scaleZoomX="2" scaleZoomY="2" scaleOffsetX="30" scaleOffsetY="30"}} {{nf-line data=someData}} {{/nf-gg}} @namespace components @class nf-gg @extends Ember.Component @uses mixins.graph-require-scale-source @uses mixins.graph-selecteble-graphic */ export default Component.extend(RequireScaleSource, SelectableGraphic, { layout, tagName: 'g', classNameBindings: [':nf-group', 'selectable', 'selected'], /** The parent graph for a component. @property graph @type components.nf-graph @default null */ graph: null, click: function() { if(this.get('selectable')) { this.toggleProperty('selected'); } } }); ================================================ FILE: addon/components/nf-horizontal-line.js ================================================ import { alias } from '@ember/object/computed'; import { computed } from '@ember/object'; import Component from '@ember/component'; import layout from 'ember-nf-graph/templates/components/nf-horizontal-line'; import RequireScaleSource from 'ember-nf-graph/mixins/graph-requires-scale-source'; /** Draws a horizontal line on the graph at a given y domain value @namespace components @class nf-horizontal-line @extends Ember.Component @uses mixins.graph-requires-scale-source */ export default Component.extend(RequireScaleSource, { layout, tagName: 'line', attributeBindings: ['lineY:y1', 'lineY:y2', 'x1', 'x2'], classNames: ['nf-horizontal-line'], /** The parent graph for a component. @property graph @type components.nf-graph @default null */ graph: null, /** The y domain value at which to draw the horizontal line @property y @type Number @default null */ y: null, /** The computed y coordinate of the line to draw @property lineY @type Number @private @readonly */ lineY: computed('y', 'yScale', function(){ let y = this.get('y'); let yScale = this.get('yScale'); let py = yScale ? yScale(y) : -1; return py && py > 0 ? py : 0; }), /** The left x coordinate of the line @property x1 @type Number @default 0 @private */ x1: 0, /** The right x coordinate of the line @property x2 @type Number @private @readonly */ x2: alias('graph.graphWidth'), }); ================================================ FILE: addon/components/nf-line.js ================================================ import { on } from '@ember/object/evented'; import { computed } from '@ember/object'; import Component from '@ember/component'; import layout from 'ember-nf-graph/templates/components/nf-line'; import DataGraphic from 'ember-nf-graph/mixins/graph-data-graphic'; import LineUtils from 'ember-nf-graph/mixins/graph-line-utils'; import SelectableGraphic from 'ember-nf-graph/mixins/graph-selectable-graphic'; import RegisteredGraphic from 'ember-nf-graph/mixins/graph-registered-graphic'; import GraphicWithTrackingDot from 'ember-nf-graph/mixins/graph-graphic-with-tracking-dot'; import RequireScaleSource from 'ember-nf-graph/mixins/graph-requires-scale-source'; /** A line graphic for `nf-graph`. Displays a line for the data it's passed. @namespace components @class nf-line @extends Ember.Component @uses mixins.graph-line-utils @uses mixins.graph-selectable-graphic @uses mixins.graph-registered-graphic @uses mixins.graph-data-graphic @uses mixins.graph-graphic-with-tracking-dot @uses mixins.graph-requires-scale-source */ export default Component.extend(DataGraphic, SelectableGraphic, LineUtils, RegisteredGraphic, GraphicWithTrackingDot, RequireScaleSource, { layout, tagName: 'g', /** The parent graph for a component. @property graph @type components.nf-graph @default null */ graph: null, /** The type of D3 interpolator to use to create the line. @property interpolator @type String @default 'linear' */ interpolator: 'linear', classNameBindings: ['selected', 'selectable'], classNames: ['nf-line'], /** The d3 line function to create the line path. @method lineFn @param data {Array} the array of coordinate arrays to plot as an SVG path @private @return {String} an SVG path data string */ lineFn: computed('xScale', 'yScale', 'interpolator', function() { let xScale = this.get('xScale'); let yScale = this.get('yScale'); let interpolator = this.get('interpolator'); return this.createLineFn(xScale, yScale, interpolator); }), /** The SVG path data string to render the line @property d @type String @private @readonly */ d: computed('renderedData.[]', 'lineFn', function(){ let renderedData = this.get('renderedData'); let lineFn = this.get('lineFn'); return lineFn(renderedData); }), /** Event handler to toggle the `selected` property on click @method _toggleSelected @private */ _toggleSelected: on('click', function(){ if(this.get('selectable')) { this.toggleProperty('selected'); } }), }); ================================================ FILE: addon/components/nf-plot.js ================================================ import { computed } from '@ember/object'; import { notEmpty, and } from '@ember/object/computed'; import Component from '@ember/component'; import layout from 'ember-nf-graph/templates/components/nf-plot'; import RequireScaleSource from 'ember-nf-graph/mixins/graph-requires-scale-source'; import GraphEvent from 'ember-nf-graph/utils/nf/graph-event'; /** Plots a group tag on a graph at a given x and y domain coordinate. @namespace components @class nf-plot @extends Ember.Component @uses mixins.graph-requires-scale-source */ export default Component.extend(RequireScaleSource, { layout, tagName: 'g', attributeBindings: ['transform'], classNames: ['nf-plot'], /** The parent graph for a component. @property graph @type components.nf-graph @default null */ graph: null, /** The x domain value to set the plot at @property x @default null */ x: null, /** The y domain value to set the plot at @property x @default null */ y: null, /** True if an `x` value is present (defined, not null and non-empty) @property hasX @type Boolean @readonly */ hasX: notEmpty('x'), /** True if an `y` value is present (defined, not null and non-empty) @property hasY @type Boolean @readonly */ hasY: notEmpty('y'), /** The calculated visibility of the component @property isVisible @type Boolean @readonly */ isVisible: and('hasX', 'hasY'), /** The calculated x coordinate @property rangeX @type Number @readonly */ rangeX: computed('x', 'xScale', function(){ let xScale = this.get('xScale'); let x = this.get('x'); let hasX = this.get('hasX'); return (hasX && xScale ? xScale(x) : 0) || 0; }), /** The calculated y coordinate @property rangeY @type Number @readonly */ rangeY: computed('y', 'yScale', function(){ let yScale = this.get('yScale'); let y = this.get('y'); let hasY = this.get('hasY'); return (hasY && yScale ? yScale(y) : 0) || 0; }), /** The SVG transform of the component's `` tag. @property transform @type String @readonly */ transform: computed('rangeX', 'rangeY', function(){ let rangeX = this.get('rangeX'); let rangeY = this.get('rangeY'); return `translate(${rangeX} ${rangeY})`; }), data: null, click: function(e) { let context = GraphEvent.create({ x: this.get('x'), y: this.get('y'), data: this.get('data'), source: this, graph: this.get('graph'), originalEvent: e, }); this.sendAction('action', context); }, }); ================================================ FILE: addon/components/nf-plots.js ================================================ import { isArray, A } from '@ember/array'; import { computed } from '@ember/object'; import Component from '@ember/component'; import layout from 'ember-nf-graph/templates/components/nf-plots'; import DataGraphic from 'ember-nf-graph/mixins/graph-data-graphic'; import RequireScaleSource from 'ember-nf-graph/mixins/graph-requires-scale-source'; export default Component.extend(DataGraphic, RequireScaleSource, { layout, tagName: 'g', classNames: ['nf-plots'], /** The parent graph for a component. @property graph @type components.nf-graph @default null */ graph: null, /** The model for adding plots to the graph @property plotData @readonly @private */ plotData: computed('renderedData.[]', function(){ let renderedData = this.get('renderedData'); if(renderedData && isArray(renderedData)) { return A(renderedData.map(function(d) { return { x: d[0], y: d[1], data: d.data, }; })); } }), actions: { itemClicked: function(e) { this.sendAction('action', e); }, }, }); ================================================ FILE: addon/components/nf-range-marker.js ================================================ import { on } from '@ember/object/evented'; import { computed } from '@ember/object'; import Component from '@ember/component'; import layout from 'ember-nf-graph/templates/components/nf-range-marker'; import RequireScaleSource from 'ember-nf-graph/mixins/graph-requires-scale-source'; /** Draws a rectangular strip with a templated label on an `nf-graph`. Should always be used in conjunction with an `nf-range-markers` container component. @namespace components @class nf-range-marker @extends Ember.Component @uses mixins.graph-requires-scale-source */ export default Component.extend(RequireScaleSource, { layout, tagName: 'g', attributeBindings: ['transform'], classNames: ['nf-range-marker'], /** The parent graph for a component. @property graph @type components.nf-graph @default null */ graph: null, /** The parent `nf-range-markers` component. @property container @type {components.nf-range-markers} @default null */ container: null, /** The minimum domain value for the range to mark. @property xMin @default 0 */ xMin: 0, /** The maximum domain value for the range to mark. @property xMax @default 0 */ xMax: 0, /** The spacing above the range marker. @property marginTop @type Number @default 10 */ marginTop: 10, /** The spacing below the range marker. @property marginBottom @type Number @default 3 */ marginBottom: 3, /** The height of the range marker. @property height @type Number @default 10 */ height: 10, /** The computed x position of the range marker. @property x @type Number @readonly */ x: computed('xMin', 'xScale', function(){ let xScale = this.get('xScale'); let xMin = this.get('xMin'); return xScale(xMin); }), /** The computed width of the range marker. @property width @type Number @readonly */ width: computed('xScale', 'xMin', 'xMax', function() { let xScale = this.get('xScale'); let xMax = this.get('xMax'); let xMin = this.get('xMin'); return xScale(xMax) - xScale(xMin); }), /** The computed y position of the range marker. @property y @type Number @readonly */ y: computed( 'container.orient', 'prevMarker.{bottom,y}', 'graph.graphHeight', 'totalHeight', function() { let orient = this.get('container.orient'); let prevBottom = this.get('prevMarker.bottom'); let prevY = this.get('prevMarker.y'); let graphHeight = this.get('graph.graphHeight'); let totalHeight = this.get('totalHeight'); prevBottom = prevBottom || 0; if(orient === 'bottom') { return (prevY || graphHeight) - totalHeight; } if(orient === 'top') { return prevBottom; } } ), /** The computed total height of the range marker including its margins. @property totalHeight @type Number @readonly */ totalHeight: computed('height', 'marginTop', 'marginBottom', function() { let height = this.get('height'); let marginTop = this.get('marginTop'); let marginBottom = this.get('marginBottom'); return height + marginTop + marginBottom; }), /** The computed bottom of the range marker, not including the bottom margin. @property bottom @type Number @readonly */ bottom: computed('y', 'totalHeight', function(){ let y = this.get('y'); let totalHeight = this.get('totalHeight'); return y + totalHeight; }), /** The computed SVG transform of the range marker container @property transform @type String @readonly */ transform: computed('y', function(){ let y = this.get('y') || 0; return `translate(0 ${y})`; }), /** The computed SVG transform fo the range marker label container. @property labelTransform @type String @readonly */ labelTransform: computed('x', function(){ let x = this.get('x') || 0; return `translate(${x} 0)`; }), /** Initialization function that registers the range marker with its parent and populates the container property @method _setup @private */ init() { this._super(...arguments); let container = this.get('container'); container.registerMarker(this); }, /** Unregisters the range marker from its parent when the range marker is destroyed. @method _unregister @private */ _unregisterMarker: on('willDestroyElement', function() { this.get('container').unregisterMarker(this); }) }); ================================================ FILE: addon/components/nf-range-markers.js ================================================ import { schedule } from '@ember/runloop'; import { A } from '@ember/array'; import { computed } from '@ember/object'; import Component from '@ember/component'; import layout from 'ember-nf-graph/templates/components/nf-range-markers'; /** A container and manager for `nf-range-marker` components. Used to draw an association between `nf-range-marker` components so they can be laid out in a manner in which they don't collide. @namespace components @class nf-range-markers @extends Ember.Component */ export default Component.extend({ layout, tagName: 'g', /** The parent graph for a component. @property graph @type components.nf-graph @default null */ graph: null, /** Sets the orientation of the range markers. - `'bottom'` - Range markers start at the bottom and stack upward - `'top'` - Range markers start at the top and stack downward @property orient @type String @default 'bottom' */ orient: 'bottom', /** The margin, in pixels, between the markers @property markerMargin @type Number @default 10 */ markerMargin: 10, /** The marker components registered with this container @property markers @type Array @readonly */ markers: computed(function() { return A(); }), /** Adds the passed marker to the `markers` list, and sets the `prevMarker` and `nextMarker` properties on the marker component and it's neighbor. @method registerMarker @param marker {nf-range-marker} the range marker to register with this container */ registerMarker: function(marker) { let markers = this.get('markers'); let prevMarker = markers[markers.length - 1]; schedule('afterRender', () => { if(prevMarker) { marker.set('prevMarker', prevMarker); prevMarker.set('nextMarker', marker); } markers.pushObject(marker); }); }, /** Removes the marker from the `markers` list. Also updates the `nextMarker` and `prevMarker` properties of it's neighboring components. @method unregisterMarker @param marker {nf-range-marker} the range marker to remove from the `markers` list. */ unregisterMarker: function(marker) { if(marker) { schedule('afterRender', () => { let next = marker.nextMarker; let prev = marker.prevMarker; if(prev) { prev.set('nextMarker', next); } if(next) { next.set('prevMarker', prev); } this.get('markers').removeObject(marker); }); } }, }); ================================================ FILE: addon/components/nf-right-tick.js ================================================ import { scheduleOnce } from '@ember/runloop'; import { on } from '@ember/object/evented'; import { computed, observer } from '@ember/object'; import Component from '@ember/component'; import layout from 'ember-nf-graph/templates/components/nf-right-tick'; import RequireScaleSource from 'ember-nf-graph/mixins/graph-requires-scale-source'; /** Draws a line and a chevron at the specified domain value on the right side of an `nf-graph`. ### Tips - Adding `paddingRight` to `nf-graph` component will not affect `nf-right-tick`'s position. @namespace components @class nf-right-tick @extends Ember.Component @uses mixins.graph-requires-scale-source */ export default Component.extend(RequireScaleSource, { layout, tagName: 'g', classNames: ['nf-right-tick'], /** The parent graph for a component. @property graph @type components.nf-graph @default null */ graph: null, /** The transition duration in milliseconds @property duration @type Number @default 400 */ duration: 400, /** The domain value at which to place the tick @property value @type Number @default null */ value: null, /** Sets the visibility of the component. Returns false if `y` is not a numeric data type. @property isVisible @private @readonly */ isVisible: computed('y', function(){ return !isNaN(this.get('y')); }), /** The calculated y coordinate of the tick @property y @type Number @readonly */ y: computed('value', 'yScale', 'graph.paddingTop', function() { let value = this.get('value'); let yScale = this.get('yScale'); let paddingTop = this.get('graph.paddingTop'); let vy = 0; if(yScale) { vy = yScale(value) || 0; } return vy + paddingTop; }), /** The SVG transform used to render the tick @property transform @type String @private @readonly */ transform: computed('y', 'graph.width', function(){ let y = this.get('y'); let graphWidth = this.get('graph.width'); let x0 = graphWidth - 6; let y0 = y - 3; return `translate(${x0} ${y0})`; }), /** performs the D3 transition to move the tick to the proper position. @method _transitionalUpdate @private */ _transitionalUpdate: function(){ let transform = this.get('transform'); let path = this.get('path'); let duration = this.get('duration'); path.transition().duration(duration) .attr('transform', transform); }, /** Schedules the transition when `value` changes on on init. @method _triggerTransition @private */ _triggerTransition: on('init', observer('value', function(){ scheduleOnce('afterRender', this, this._transitionalUpdate); })), /** Updates the tick position without a transition. @method _nonTransitionalUpdate @private */ _nonTransitionalUpdate: function(){ let transform = this.get('transform'); let path = this.get('path'); path.attr('transform', transform); }, /** Schedules the update of non-transitional positions @method _triggerNonTransitionalUpdate @private */ _triggerNonTransitionalUpdate: observer('graph.width', function(){ scheduleOnce('afterRender', this, this._nonTransitionalUpdate); }), /** Gets the elements required to do the d3 transitions @method _getElements @private */ _getElements: on('didInsertElement', function(){ let g = d3.select(this.$()[0]); let path = g.selectAll('path').data([0]); this.set('path', path); }) }); ================================================ FILE: addon/components/nf-selection-box.js ================================================ import { on } from '@ember/object/evented'; import { once } from '@ember/runloop'; import { computed, observer } from '@ember/object'; import Component from '@ember/component'; import layout from 'ember-nf-graph/templates/components/nf-selection-box'; import RequireScaleSource from 'ember-nf-graph/mixins/graph-requires-scale-source'; import { normalizeScale } from 'ember-nf-graph/utils/nf/scale-utils'; /** Draws a rectangle on an `nf-graph` given domain values `xMin`, `xMax`, `yMin` and `yMax`. @namespace components @class nf-selection-box @extends Ember.Component @uses mixins.graph-requires-scale-source */ export default Component.extend(RequireScaleSource, { layout, tagName: 'g', /** The parent graph for a component. @property graph @type components.nf-graph @default null */ graph: null, /** The duration of the transition in ms @property duration @type Number @default 400 */ duration: 400, /** The minimum x domain value to encompass. @property xMin @default null */ xMin: null, /** The maximum x domain value to encompoass. @property xMax @default null */ xMax: null, /** The minimum y domain value to encompass. @property yMin @default null */ yMin: null, /** The maximum y domain value to encompass @property yMax @default null */ yMax: null, classNames: ['nf-selection-box'], /** The x pixel position of xMin @property x0 @type Number */ x0: computed('xMin', 'xScale', function(){ return normalizeScale(this.get('xScale'), this.get('xMin')); }), /** The x pixel position of xMax @property x1 @type Number */ x1: computed('xMax', 'xScale', function(){ return normalizeScale(this.get('xScale'), this.get('xMax')); }), /** The y pixel position of yMin @property y0 @type Number */ y0: computed('yMin', 'yScale', function(){ return normalizeScale(this.get('yScale'), this.get('yMin')); }), /** The y pixel position of yMax @property y1 @type Number */ y1: computed('yMax', 'yScale', function(){ return normalizeScale(this.get('yScale'), this.get('yMax')); }), /** The SVG path string for the box's rectangle. @property rectPath @type String */ rectPath: computed('x0', 'x1', 'y0', 'y1', function(){ let x0 = this.get('x0'); let x1 = this.get('x1'); let y0 = this.get('y0'); let y1 = this.get('y1'); return `M${x0},${y0} L${x0},${y1} L${x1},${y1} L${x1},${y0} L${x0},${y0}`; }), /** Updates the position of the box with a transition @method doUpdatePosition */ doUpdatePosition: function(){ let boxRect = this.get('boxRectElement'); let rectPath = this.get('rectPath'); let duration = this.get('duration'); boxRect.transition().duration(duration) .attr('d', rectPath); }, doUpdatePositionStatic: function(){ let boxRect = this.get('boxRectElement'); let rectPath = this.get('rectPath'); boxRect.attr('d', rectPath); }, /** Schedules an update to the position of the box after render. @method updatePosition @private */ updatePosition: observer('xMin', 'xMax', 'yMin', 'yMax', function(){ once(this, this.doUpdatePosition); }), staticPositionChange: on('didInsertElement', observer('xScale', 'yScale', function(){ once(this, this.doUpdatePositionStatic); })), /** Sets up the required d3 elements after component is inserted into the DOM @method didInsertElement */ didInsertElement: function(){ let element = this.get('element'); let g = d3.select(element); let boxRect = g.append('path') .attr('class', 'nf-selection-box-rect') .attr('d', this.get('rectPath')); this.set('boxRectElement', boxRect); }, }); ================================================ FILE: addon/components/nf-svg-image.js ================================================ import Component from '@ember/component'; import { computed } from '@ember/object'; import layout from 'ember-nf-graph/templates/components/nf-svg-image'; import RequiresScaleSource from 'ember-nf-graph/mixins/graph-requires-scale-source'; import { normalizeScale } from 'ember-nf-graph/utils/nf/scale-utils'; import SelectableGraphic from 'ember-nf-graph/mixins/graph-selectable-graphic'; /** An image to be displayed in a graph with that takes domain based measurements and uses the scale of the graph. Creates an `` SVG element. @namespace components @class nf-svg-image @extends Ember.Component @uses mixins.graph-requires-scale-source @uses mixins.graph-selectable-graphic */ export default Component.extend(RequiresScaleSource, SelectableGraphic, { layout, tagName: 'image', classNameBindings: [':nf-svg-image', 'selectable', 'selected'], attributeBindings: ['svgX:x', 'svgY:y', 'svgWidth:width', 'svgHeight:height', 'src:href'], click: function(){ if(this.get('selectable')) { this.toggleProperty('selected'); } }, /** The parent graph for a component. @property graph @type components.nf-graph @default null */ graph: null, /** The domain x value to place the image at. @property x @default null */ x: null, /** The domain y value to place the image at. @property y @default null */ y: null, _width: 0, /** The width as a domain value. Does not handle ordinal scales. To set a pixel value, set `svgWidth` directly. @property width @type Number @default 0 */ width: computed({ get() { return this._width; }, set(key, value) { return this._width = Math.max(0, +value) || 0; } }), _height: 0, /** The height as a domain value. Does not handle ordinal scales. To set a pixel value, just set `svgHeight` directly. @property height @default null */ height: computed({ get() { return this._height; }, set(key, value) { this._height = Math.max(0, +value) || 0; } }), /** The image source url @property src @type String */ src: '', x0: computed('x', 'xScale', function(){ return normalizeScale(this.get('xScale'), this.get('x')); }), y0: computed('y', 'yScale', function(){ return normalizeScale(this.get('yScale'), this.get('y')); }), x1: computed('xScale', 'width', 'x', function(){ let scale = this.get('xScale'); if(scale.rangeBands) { throw new Error('nf-image does not support ordinal scales'); } return normalizeScale(scale, this.get('width') + this.get('x')); }), y1: computed('yScale', 'height', 'y', function(){ let scale = this.get('yScale'); if(scale.rangeBands) { throw new Error('nf-image does not support ordinal scales'); } return normalizeScale(scale, this.get('height') + this.get('y')); }), /** The pixel value at which to plot the image. @property svgX @type Number */ svgX: computed('x0', 'x1', function(){ return Math.min(this.get('x0'), this.get('x1')); }), /** The pixel value at which to plot the image. @property svgY @type Number */ svgY: computed('y0', 'y1', function(){ return Math.min(this.get('y0'), this.get('y1')); }), /** The width, in pixels, of the image. @property svgWidth @type Number */ svgWidth: computed('x0', 'x1', function(){ return Math.abs(this.get('x0') - this.get('x1')); }), /** The height, in pixels of the image. @property svgHeight @type Number */ svgHeight: computed('y0', 'y1', function(){ return Math.abs(this.get('y0') - this.get('y1')); }), }); ================================================ FILE: addon/components/nf-svg-line.js ================================================ import { computed } from '@ember/object'; import Component from '@ember/component'; import layout from 'ember-nf-graph/templates/components/nf-svg-line'; import RequiresScaleSource from 'ember-nf-graph/mixins/graph-requires-scale-source'; import { normalizeScale } from 'ember-nf-graph/utils/nf/scale-utils'; import SelectableGraphic from 'ember-nf-graph/mixins/graph-selectable-graphic'; /** Draws a basic line between two points on the graph. @namespace components @class nf-svg-line @extends Ember.Component @uses mixins.graph-requires-scale-source @uses mixins.graph-selectable-graphic */ export default Component.extend(RequiresScaleSource, SelectableGraphic, { layout, tagName: 'line', classNameBindings: [':nf-svg-line', 'selectable', 'selected'], attributeBindings: ['svgX1:x1', 'svgX2:x2', 'svgY1:y1', 'svgY2:y2'], click: function(){ if(this.get('selectable')) { this.toggleProperty('selected'); } }, /** The parent graph for a component. @property graph @type components.nf-graph @default null */ graph: null, /** The domain value to plot the SVGLineElement's x1 at. @property x1 @default null */ x1: null, /** The domain value to plot the SVGLineElement's x2 at. @property x2 @default null */ x2: null, /** The domain value to plot the SVGLineElement's y1 at. @property y1 @default null */ y1: null, /** The domain value to plot the SVGLineElement's y2 at. @property y2 @default null */ y2: null, /** The pixel value to plot the SVGLineElement's x1 at. @property svgX1 @type Number */ svgX1: computed('x1', 'xScale', function(){ return normalizeScale(this.get('xScale'), this.get('x1')); }), /** The pixel value to plot the SVGLineElement's x2 at. @property svgX2 @type Number */ svgX2: computed('x2', 'xScale', function(){ return normalizeScale(this.get('xScale'), this.get('x2')); }), /** The pixel value to plot the SVGLineElement's y1 at. @property svgY1 @type Number */ svgY1: computed('y1', 'yScale', function(){ return normalizeScale(this.get('yScale'), this.get('y1')); }), /** The pixel value to plot the SVGLineElement's y2 at. @property svgY2 @type Number */ svgY2: computed('y2', 'yScale', function(){ return normalizeScale(this.get('yScale'), this.get('y2')); }), }); ================================================ FILE: addon/components/nf-svg-path.js ================================================ import { isArray } from '@ember/array'; import { computed } from '@ember/object'; import Component from '@ember/component'; import layout from 'ember-nf-graph/templates/components/nf-svg-path'; import RequiresScaleSource from 'ember-nf-graph/mixins/graph-requires-scale-source'; import { normalizeScale } from 'ember-nf-graph/utils/nf/scale-utils'; import SelectableGraphic from 'ember-nf-graph/mixins/graph-selectable-graphic'; /** An SVG path primitive that plots based on a graph's scale. @namespace components @class nf-svg-path @extends Ember.Component @uses mixins.graph-requires-scale-source @uses mixins.graph-selectable-graphic */ export default Component.extend(RequiresScaleSource, SelectableGraphic, { layout, type: 'path', classNameBindings: [':nf-svg-path', 'selectable', 'selected'], attributeBindings: ['d'], /** The parent graph for a component. @property graph @type components.nf-graph @default null */ graph: null, /** The array of points to use to plot the path. This is an array of arrays, in the following format: // specify path pen commands [ [50, 50, 'L'], [100, 100, 'L'] ] // or they will default to 'L' [ [50, 50], [100, 100] ] @property points @type Array */ points: null, /** The data points mapped to scale @property svgPoints @type Array */ svgPoints: computed('points.[]', 'xScale', 'yScale', function(){ let points = this.get('points'); let xScale = this.get('xScale'); let yScale = this.get('yScale'); if(isArray(points) && points.length > 0) { return points.map(function(v) { let dx = normalizeScale(xScale, v[0]); let dy = normalizeScale(yScale, v[1]); let c = v.length > 2 ? v[2] : 'L'; return [dx, dy, c]; }); } }), click: function(){ if(this.get('selectable')) { this.toggleProperty('selected'); } }, /** The raw svg path d attribute output @property d @type String */ d: computed('svgPoints', function(){ let svgPoints = this.get('svgPoints'); if(isArray(svgPoints) && svgPoints.length > 0) { return svgPoints.reduce(function(d, pt, i) { if(i === 0) { d += 'M' + pt[0] + ',' + pt[1]; } d += ' ' + pt[2] + pt[0] + ',' + pt[1]; return d; }, ''); } else { return 'M0,0'; } }), }); ================================================ FILE: addon/components/nf-svg-rect.js ================================================ import Component from '@ember/component'; import { computed } from '@ember/object'; import layout from 'ember-nf-graph/templates/components/nf-svg-rect'; import RequiresScaleSource from 'ember-nf-graph/mixins/graph-requires-scale-source'; import { normalizeScale } from 'ember-nf-graph/utils/nf/scale-utils'; import SelectableGraphic from 'ember-nf-graph/mixins/graph-selectable-graphic'; /** A rectangle that plots using domain values from the graph. Uses an SVGPathElement to plot the rectangle, to allow for rectangles with "negative" heights. @namespace components @class nf-svg-rect @extends Ember.Component @uses mixins.graph-requires-scale-source @uses mixins.graph-selectable-graphic */ export default Component.extend(RequiresScaleSource, SelectableGraphic, { layout, tagName: 'path', attributeBindings: ['d'], classNameBindings: [':nf-svg-rect', 'selectable', 'selected'], /** The parent graph for a component. @property graph @type components.nf-graph @default null */ graph: null, /** The domain x value to place the rect at. @property x @default null */ x: null, /** The domain y value to place the rect at. @property y @default null */ y: null, _width: 0, /** The width as a domain value. If xScale is ordinal, then this value is the indice offset to which to draw the rectangle. In other words, if it's `2`, then draw the rectangle to two ordinals past whatever `x` is set to. @property width @type Number @default 0 */ width: computed({ get() { return this._width; }, set(key, value) { return this._width = +value; } }), _height: 0, /** The height as a domain value. If the yScale is ordinal, this value is the indice offset to which to draw the rectangle. For example, if the height is `3` then draw the rectangle to two ordinals passed whatever `y` is set to. @property height @type Number @default 0 */ height: computed({ get() { return this._height; }, set(key, value) { return this._height = +value; } }), /** The x value of the bottom right corner of the rectangle. @property x1 @type Number */ x1: computed('width', 'x', 'xScale', function(){ let xScale = this.get('xScale'); let w = this.get('width'); let x = this.get('x'); if(xScale.rangeBands) { let domain = xScale.domain(); let fromIndex = domain.indexOf(x); let toIndex = fromIndex + w; return normalizeScale(xScale, domain[toIndex]); } else { x = +x || 0; return normalizeScale(xScale, w + x); } }), /** The y value of the bottom right corner of the rectangle @property y1 @type Number */ y1: computed('height', 'y', 'yScale', function(){ let yScale = this.get('yScale'); let h = this.get('height'); let y = this.get('y'); if(yScale.rangeBands) { let domain = yScale.domain(); let fromIndex = domain.indexOf(y); let toIndex = fromIndex + h; return normalizeScale(yScale, domain[toIndex]); } else { y = +y || 0; return normalizeScale(yScale, h + y); } }), /** The x value of the top right corner of the rectangle @property x0 @type Number */ x0: computed('x', 'xScale', function(){ return normalizeScale(this.get('xScale'), this.get('x')); }), /** The y value of the top right corner of the rectangle. @property y0 @type Number */ y0: computed('y', 'yScale', function() { return normalizeScale(this.get('yScale'), this.get('y')); }), /** The SVG path data for the rectangle @property d @type String */ d: computed('x0', 'y0', 'x1', 'y1', function(){ let x0 = this.get('x0'); let y0 = this.get('y0'); let x1 = this.get('x1'); let y1 = this.get('y1'); return `M${x0},${y0} L${x0},${y1} L${x1},${y1} L${x1},${y0} L${x0},${y0}`; }), /** Click event handler. Toggles selected if selectable. @method click */ click: function(){ if(this.get('selectable')) { this.toggleProperty('selected'); } } }); ================================================ FILE: addon/components/nf-tick-label.js ================================================ import { computed } from '@ember/object'; import Component from '@ember/component'; import layout from 'ember-nf-graph/templates/components/nf-tick-label'; export default Component.extend({ layout, tagName: 'g', attributeBindings: ['transform'], transform: computed('x', 'y', function(){ let x = this.get('x'); let y = this.get('y'); return `translate(${x} ${y})`; }), className: 'nf-tick-label' }); ================================================ FILE: addon/components/nf-tracker.js ================================================ import Component from '@ember/component'; import { computed } from '@ember/object'; import layout from 'ember-nf-graph/templates/components/nf-tracker'; import DataGraphic from 'ember-nf-graph/mixins/graph-data-graphic'; import RequiresScaleSource from 'ember-nf-graph/mixins/graph-requires-scale-source'; import GraphicWithTrackingDot from 'ember-nf-graph/mixins/graph-graphic-with-tracking-dot'; /** A tracking graphic component used to do things like create tracking dots for nf-area or nf-line. @namespace components @class nf-tracker @uses mixins.graph-data-graphic @uses mixins.graph-requires-scale-source @uses mixins.graph-graphic-with-tracking-dot */ export default Component.extend(DataGraphic, RequiresScaleSource, GraphicWithTrackingDot, { layout, tagName: 'g', classNameBindings: [':nf-tracker'], attributeBindings: ['transform'], /** The parent graph for a component. @property graph @type components.nf-graph @default null */ graph: null, transform: computed('trackedData.{x,y}', 'xScale', 'yScale', { get() { let xScale = this.get('xScale'); let yScale = this.get('yScale'); let x = xScale && xScale(this.get('trackedData.x') || 0); let y = yScale && yScale(this.get('trackedData.y') || 0); return 'translate(' + x + ',' + y + ')'; } }) }); ================================================ FILE: addon/components/nf-vertical-line.js ================================================ import { computed } from '@ember/object'; import { alias } from '@ember/object/computed'; import Component from '@ember/component'; import layout from 'ember-nf-graph/templates/components/nf-vertical-line'; import RequireScaleSource from 'ember-nf-graph/mixins/graph-requires-scale-source'; /** Draws a vertical line on a graph at a given x domain value @namespace components @class nf-vertical-line @extends Ember.Component @uses mixins.graph-requires-scale-source */ export default Component.extend(RequireScaleSource, { layout, tagName: 'line', classNames: ['nf-vertical-line'], attributeBindings: ['lineX:x1', 'lineX:x2', 'y1', 'y2'], /** The parent graph for a component. @property graph @type components.nf-graph @default null */ graph: null, /** The top y coordinate of the line @property y1 @type Number @default 0 @private */ y1: 0, /** The bottom y coordinate of the line @property y2 @type Number @private @readonly */ y2: alias('graph.graphHeight'), /** The x domain value at which to draw the vertical line on the graph @property x @type Number @default null */ x: null, /** The calculated x coordinate of the vertical line @property lineX @type Number @private @readonly */ lineX: computed('xScale', 'x', function(){ let xScale = this.get('xScale'); let x = this.get('x'); let px = xScale ? xScale(x) : -1; return px && px > 0 ? px : 0; }), }); ================================================ FILE: addon/components/nf-x-axis.js ================================================ import { alias, uniq } from '@ember/object/computed'; import { A } from '@ember/array'; import { schedule } from '@ember/runloop'; import Component from '@ember/component'; import { computed } from '@ember/object'; import layout from 'ember-nf-graph/templates/components/nf-x-axis'; import RequireScaleSource from 'ember-nf-graph/mixins/graph-requires-scale-source'; /** A component for adding a templated x axis to an `nf-graph` component. All items contained within this component are used to template each tick mark on the rendered graph. Tick values are supplied to the inner scope of this component on the view template via `tick`. ### Styling The main container will have a `nf-x-axis` class. A `orient-top` or `orient-bottom` container will be applied to the container depending on the `orient` setting. Ticks are positioned via a `` tag, that will contain whatever is passed into it via templating, along with the tick line. `` tags within tick templates do have some default styling applied to them to position them appropriately based off of orientation. ### Example {{#nf-graph width=500 height=300}} {{#nf-x-axis height=40 as |tick|}} x is {{tick.value}} {{/nf-x-axis}} {{/nf-graph}} @namespace components @class nf-x-axis @extends Ember.Component @uses mixins.graph-has-graph-parent @uses mixins.graph-requires-scale-source */ export default Component.extend(RequireScaleSource, { layout, tagName: 'g', attributeBindings: ['transform'], classNameBindings: ['orientClass'], classNames: ['nf-x-axis'], /** The parent graph for a component. @property graph @type components.nf-graph @default null */ graph: null, /** The height of the x axis in pixels. @property height @type Number @default 20 */ height: 20, /** The number of ticks to display @property tickCount @type Number @default 12 */ tickCount: 12, /** The length of the tick line (the small vertical line indicating the tick) @property tickLength @type Number @default 0 */ tickLength: 0, /** The spacing between the end of the tick line and the origin of the templated tick content @property tickPadding @type Number @default 5 */ tickPadding: 5, /** The orientation of the x axis. Value can be `'top'` or `'bottom'`. @property orient @type String @default 'bottom' */ orient: 'bottom', _tickFilter: null, /** An optional filtering function to allow more control over what tick marks are displayed. The function should have exactly the same signature as the function you'd use for an `Array.prototype.filter()`. @property tickFilter @type Function @default null @example {{#nf-x-axis tickFilter=myFilter as |tick|}} {{tick.value}} {{/nf-x-axis}} And on your controller: myFilter: function(tick, index, ticks) { return tick.value < 1000; }, The above example will filter down the set of ticks to only those that are less than 1000. */ tickFilter: alias('_tickFilter'), /** The class applied due to orientation (e.g. `'orient-top'`) @property orientClass @type String @readonly */ orientClass: computed('orient', function(){ return 'orient-' + this.get('orient'); }), /** The SVG Transform applied to this component's container. @property transform @type String @readonly */ transform: computed('x', 'y', function(){ let x = this.get('x') || 0; let y = this.get('y') || 0; return `translate(${x} ${y})`; }), /** The y position of this component's container. @property y @type Number @readonly */ y: computed( 'orient', 'graph.{paddingTop,paddingBottom,height}', 'height', function(){ let orient = this.get('orient'); let graphHeight = this.get('graph.height'); let height = this.get('height'); let paddingBottom = this.get('graph.paddingBottom'); let paddingTop = this.get('graph.paddingTop'); let y; if(orient === 'bottom') { y = graphHeight - paddingBottom - height; } else { y = paddingTop; } return y || 0; } ), /** This x position of this component's container @property x @type Number @readonly */ x: computed('graph.graphX', function(){ return this.get('graph.graphX') || 0; }), init() { this._super(...arguments); schedule('afterRender', () => { this.set('graph.xAxis', this); }); }, /** The width of the component @property width @type Number @readonly */ width: alias('graph.graphWidth'), /** A method to call to override the default behavior of how ticks are created. The function signature should match: // - scale: d3.Scale // - tickCount: number of ticks // - uniqueData: unique data points for the axis // - scaleType: string of "linear" or "ordinal" // returns: an array of tick values. function(scale, tickCount, uniqueData, scaleType) { return [100,200,300]; } @property tickFactory @type {Function} @default null */ tickFactory: null, tickData: computed('xScale', 'graph.xScaleType', 'uniqueXData', 'tickCount', 'tickFactory', function(){ let tickFactory = this.get('tickFactory'); let scale = this.get('xScale'); let uniqueData = this.get('uniqueXData'); let tickCount = this.get('tickCount'); let scaleType = this.get('graph.xScaleType'); if(tickFactory) { return tickFactory(scale, tickCount, uniqueData, scaleType); } else if(scaleType === 'ordinal') { return uniqueData; } else { return scale.ticks(tickCount); } }), /** A unique set of all x data on the graph @property uniqueXData @type Array @readonly */ uniqueXData: uniq('graph.xData'), /** The models for the ticks to display on the axis. @property ticks @type Array @readonly */ ticks: computed( 'xScale', 'tickPadding', 'tickLength', 'height', 'orient', 'tickFilter', 'tickData', 'graph.xScaleType', function(){ let xScale = this.get('xScale'); let xScaleType = this.get('graph.xScaleType'); let tickPadding = this.get('tickPadding'); let tickLength = this.get('tickLength'); let height = this.get('height'); let orient = this.get('orient'); let tickFilter = this.get('tickFilter'); let ticks = this.get('tickData'); let y1 = orient === 'top' ? height : 0; let y2 = y1 + tickLength; let labely = orient === 'top' ? (y1 - tickPadding) : (y1 + tickPadding); let halfBandWidth = (xScaleType === 'ordinal') ? xScale.rangeBand() / 2 : 0; let result = ticks.map(function(tick) { return { value: tick, x: xScale(tick) + halfBandWidth, y1: y1, y2: y2, labely: labely }; }); if(tickFilter) { result = result.filter(tickFilter); } return A(result); } ), /** The y position, in pixels, of the axis line @property axisLineY @type Number @readonly */ axisLineY: computed('orient', 'height', function(){ return this.get('orient') === 'top' ? this.get('height') : 0; }) }); ================================================ FILE: addon/components/nf-y-axis.js ================================================ import { alias, equal, uniq } from '@ember/object/computed'; import { A } from '@ember/array'; import { schedule } from '@ember/runloop'; import Component from '@ember/component'; import { computed } from '@ember/object'; import layout from 'ember-nf-graph/templates/components/nf-y-axis'; import RequireScaleSource from 'ember-nf-graph/mixins/graph-requires-scale-source'; /** A component for adding a templated y axis to an `nf-graph` component. All items contained within this component are used to template each tick mark on the rendered graph. Tick values are supplied to the inner scope of this component on the view template via `tick`. ### Styling The main container will have a `nf-y-axis` class. A `orient-left` or `orient-right` container will be applied to the container depending on the `orient` setting. Ticks are positioned via a `` tag, that will contain whatever is passed into it via templating, along with the tick line. `` tags within tick templates do have some default styling applied to them to position them appropriately based off of orientation. ### Example {{#nf-graph width=500 height=300}} {{#nf-y-axis width=40 as |tick|}} y is {{tick.value}} {{/nf-y-axis}} {{/nf-graph}} @namespace components @class nf-y-axis @uses mixins.graph-has-graph-parent @uses mixins.graph-requires-scale-source */ export default Component.extend(RequireScaleSource, { layout, tagName: 'g', /** The parent graph for a component. @property graph @type components.nf-graph @default null */ graph: null, /** The number of ticks to display @property tickCount @type Number @default 5 */ tickCount: 5, /** The length of the tick's accompanying line. @property tickLength @type Number @default 5 */ tickLength: 5, /** The distance between the tick line and the origin tick's templated output @property tickPadding @type Number @default 3 */ tickPadding: 3, /** The total width of the y axis @property width @type Number @default 40 */ width: 40, /** The orientation of the y axis. Possible values are `'left'` and `'right'` @property orient @type String @default 'left' */ orient: 'left', attributeBindings: ['transform'], classNameBindings: [':nf-y-axis', 'isOrientRight:orient-right:orient-left'], _tickFilter: null, /** An optional filtering function to allow more control over what tick marks are displayed. The function should have exactly the same signature as the function you'd use for an `Array.prototype.filter()`. @property tickFilter @type Function @default null @example {{#nf-y-axis tickFilter=myFilter as |tick|}} {{tick.value}} {{/nf-y-axis}} And on your controller: myFilter: function(tick, index, ticks) { return tick.value < 1000; }, The above example will filter down the set of ticks to only those that are less than 1000. */ tickFilter: alias('_tickFilter'), /** computed property. returns true if `orient` is equal to `'right'`. @property isOrientRight @type Boolean @readonly */ isOrientRight: equal('orient', 'right'), /** The SVG transform for positioning the component. @property transform @type String @readonly */ transform: computed('x', 'y', function(){ let x = this.get('x') || 0; let y = this.get('y') || 0; return `translate(${x} ${y})`; }), /** The x position of the component @property x @type Number @readonly */ x: computed( 'orient', 'width', 'graph.{paddingLeft,paddingRight,width}', function(){ let orient = this.get('orient'); if(orient !== 'left') { return this.get('graph.width') - this.get('width') - this.get('graph.paddingRight'); } return this.get('graph.paddingLeft'); } ), /** The y position of the component @property y @type Number @readonly */ y: alias('graph.graphY'), /** the height of the component @property height @type Number @readonly */ height: alias('graph.graphHeight'), init() { this._super(...arguments); schedule('afterRender', () => { this.set('graph.yAxis', this); }); }, /** A method to call to override the default behavior of how ticks are created. The function signature should match: // - scale: d3.Scale // - tickCount: number of ticks // - uniqueData: unique data points for the axis // - scaleType: string of "linear" or "ordinal" // returns: an array of tick values. function(scale, tickCount, uniqueData, scaleType) { return [100,200,300]; } @property tickFactory @type {Function} @default null */ tickFactory: null, tickData: computed('graph.yScaleType', 'uniqueYData', 'yScale', 'tickCount', 'tickFactory', function(){ let tickFactory = this.get('tickFactory'); let scale = this.get('yScale'); let uniqueData = this.get('uniqueYData'); let scaleType = this.get('graph.yScaleType'); let tickCount = this.get('tickCount'); if(tickFactory) { return tickFactory(scale, tickCount, uniqueData, scaleType); } else if(scaleType === 'ordinal') { return uniqueData; } else { let ticks = scale.ticks(tickCount); if (scaleType === 'log') { let step = Math.round(ticks.length / tickCount); ticks = ticks.filter(function (tick, i) { return i % step === 0; }); } return ticks; } }), /** All y data from the graph, filtered to unique values. @property uniqueYData @type Array @readonly */ uniqueYData: uniq('graph.yData'), /** The ticks to be displayed. @property ticks @type Array @readonly */ ticks: computed( 'yScale', 'tickPadding', 'axisLineX', 'tickLength', 'isOrientRight', 'tickFilter', 'tickData', function() { let yScale = this.get('yScale'); let tickPadding = this.get('tickPadding'); let axisLineX = this.get('axisLineX'); let tickLength = this.get('tickLength'); let isOrientRight = this.get('isOrientRight'); let tickFilter = this.get('tickFilter'); let ticks = this.get('tickData'); let x1 = isOrientRight ? axisLineX + tickLength : axisLineX - tickLength; let x2 = axisLineX; let labelx = isOrientRight ? (tickLength + tickPadding) : (axisLineX - tickLength - tickPadding); let result = ticks.map(function (tick) { return { value: tick, y: yScale(tick), x1: x1, x2: x2, labelx: labelx, }; }); if(tickFilter) { result = result.filter(tickFilter); } return A(result); } ), /** The x position of the axis line. @property axisLineX @type Number @readonly */ axisLineX: computed('isOrientRight', 'width', function(){ return this.get('isOrientRight') ? 0 : this.get('width'); }), }); ================================================ FILE: addon/components/nf-y-diff.js ================================================ import { on } from '@ember/object/evented'; import { once } from '@ember/runloop'; import { alias, gte, equal } from '@ember/object/computed'; import { computed, observer } from '@ember/object'; import Component from '@ember/component'; import layout from 'ember-nf-graph/templates/components/nf-y-diff'; import RequireScaleSource from 'ember-nf-graph/mixins/graph-requires-scale-source'; import { normalizeScale } from 'ember-nf-graph/utils/nf/scale-utils'; /** Draws a box underneath (or over) the y axis to between the given `a` and `b` domain values. Component content is used to template a label in that box. ## Tips - Should be outside of `nf-graph-content`. - Should be "above" `nf-y-axis` in the markup. - As a convenience, `` elements will automatically be positioned based on y-axis orientation due to default styling. @namespace components @class nf-y-diff @extends Ember.Component @uses mixins.graph-has-graph-parent @uses mixins.graph-requires-scale-source */ export default Component.extend(RequireScaleSource, { layout, tagName: 'g', attributeBindings: ['transform'], classNameBindings: [':nf-y-diff', 'isPositive:positive:negative', 'isOrientRight:orient-right:orient-left'], /** The parent graph for a component. @property graph @type components.nf-graph @default null */ graph: null, /** The starting domain value of the difference measurement. The subrahend of the difference calculation. @property a @type Number @default null */ a: null, /** The ending domain value of the difference measurement. The minuend of the difference calculation. @property b @type Number @default null */ b: null, /** The amount of padding, in pixels, between the edge of the difference "box" and the content container @property contentPadding @type Number @default 5 */ contentPadding: 5, /** The duration of the transition, in milliseconds, as the difference slides vertically @property duration @type Number @default 400 */ duration: 400, /** The calculated vertical center of the difference box, in pixels. @property yCenter @type Number @readonly */ yCenter: computed('yA', 'yB', function(){ let yA = +this.get('yA') || 0; let yB = +this.get('yB') || 0; return (yA + yB) / 2; }), /** The y pixel value of b. @property yB @type Number */ yB: computed('yScale', 'b', function(){ return normalizeScale(this.get('yScale'), this.get('b')); }), /** The y pixel value of a. @property yA @type Number */ yA: computed('yScale', 'a', function() { return normalizeScale(this.get('yScale'), this.get('a')); }), /** The SVG transformation of the component. @property transform @type String @private @readonly */ transform: alias('graph.yAxis.transform'), /** The calculated difference between `a` and `b`. @property diff @type Number @readonly */ diff: computed('a', 'b', function(){ return +this.get('b') - this.get('a'); }), /** Returns `true` if `diff` is a positive number @property isPositive @type Boolean @readonly */ isPositive: gte('diff', 0), /** Returns `true` if the graph's y-axis component is configured to orient right. @property isOrientRight @type Boolean @readonly */ isOrientRight: equal('graph.yAxis.orient', 'right'), /** The width of the difference box @property width @type Number @readonly */ width: alias('graph.yAxis.width'), /** The x pixel coordinate of the content container. @property contentX @type Number @readonly */ contentX: computed('isOrientRight', 'width', 'contentPadding', function(){ let contentPadding = this.get('contentPadding'); let width = this.get('width'); return this.get('isOrientRight') ? width - contentPadding : contentPadding; }), rectPath: computed('yA', 'yB', 'width', function(){ let x = 0; let w = +this.get('width') || 0; let x2 = x + w; let yA = +this.get('yA') || 0; let yB = +this.get('yB') || 0; return `M${x},${yA} L${x},${yB} L${x2},${yB} L${x2},${yA} L${x},${yA}`; }), /** The SVG transformation used to position the content container. @property contentTransform @type String @private @readonly */ contentTransform: computed('contentX', 'yCenter', function(){ let contentX = this.get('contentX'); let yCenter = this.get('yCenter'); return `translate(${contentX} ${yCenter})`; }), /** Sets up the d3 related elements when component is inserted into the DOM @method didInsertElement */ didInsertElement: function(){ let element = this.get('element'); let g = d3.select(element); let rectPath = this.get('rectPath'); let rect = g.insert('path', ':first-child') .attr('class', 'nf-y-diff-rect') .attr('d', rectPath); let contentTransform = this.get('contentTransform'); let content = g.select('.nf-y-diff-content'); content.attr('transform', contentTransform); this.set('rectElement', rect); this.set('contentElement', content); }, /** Performs the transition (animation) of the elements. @method doTransition */ doTransition: function(){ let duration = this.get('duration'); let rectElement = this.get('rectElement'); let contentElement = this.get('contentElement'); if(rectElement) { rectElement.transition().duration(duration) .attr('d', this.get('rectPath')); } if(contentElement) { contentElement.transition().duration(duration) .attr('transform', this.get('contentTransform')); } }, /** Schedules a transition once at afterRender. @method transition */ transition: observer('a', 'b', function(){ once(this, this.doTransition); }), /** Updates to d3 managed DOM elments that do not require transitioning, because they're width-related. @method doAdjustWidth */ doAdjustWidth: function(){ let contentElement = this.get('contentElement'); if(contentElement) { let contentTransform = this.get('contentTransform'); contentElement.attr('transform', contentTransform); } }, adjustGraphHeight: on('didInsertElement', observer('graph.graphHeight', function(){ let rectElement = this.get('rectElement'); let contentElement = this.get('contentElement'); if(rectElement) { rectElement.attr('d', this.get('rectPath')); } if(contentElement) { contentElement.attr('transform', this.get('contentTransform')); } })), /** Schedules a call to `doAdjustWidth` on afterRender @method adjustWidth */ adjustWidth: on( 'didInsertElement', observer('isOrientRight', 'width', 'contentPadding', function(){ once(this, this.doAdjustWidth); }) ), }); ================================================ FILE: addon/mixins/.gitignore ================================================ node_modules/ bower_components/ ================================================ FILE: addon/mixins/graph-area-utils.js ================================================ import Mixin from '@ember/object/mixin'; /** Utility functions for drawing an area. @namespace mixins @class graph-area-utils @extends Ember.Mixin */ export default Mixin.create({ /** Creates a d3 area function from a given set of scales and an interpolator @method createAreaFn @param xScale {Function} a d3 scale @param yScale {Function} a d3 scale @param interpolator {String} the name of the d3 interpolator to use. @return {Function} a function that when called will create SVG path data. */ createAreaFn: function(xScale, yScale, interpolator) { let interp = interpolator || 'linear'; let xMod = xScale.rangeBand ? xScale.rangeBand() / 2 : 0; let yMod = yScale.rangeBand ? yScale.rangeBand() / 2 : 0; return function(data) { if(!data || data.length === 0) { return 'M0,0'; } return d3.svg.area() .x(function (d) { return (xScale(d[0]) || 0) + xMod; }) .y0(function (d) { return (yScale(d[1]) || 0) + yMod; }) .y1(function (d) { return (yScale(d[2]) || 0) + yMod; }) .interpolate(interp)(data); }; } }); ================================================ FILE: addon/mixins/graph-data-graphic.js ================================================ import { scheduleOnce, schedule } from '@ember/runloop'; import { isArray } from '@ember/array'; import Mixin from '@ember/object/mixin'; import { on } from '@ember/object/evented'; import { computed, observer } from '@ember/object'; import parsePropertyExpr from '../utils/parse-property-expression'; import { nearestIndexTo } from '../utils/nf/array-helpers'; let noop = function(){}; /** This is mixed in to {{#crossLink components.nf-graph}}nf-graph{{/crossLink}} child components that need to register data with the graph. Includes methods for extracting, sorting and scrubbing data for use in graphing components. Requires {{#crossLink "mixins.graph-registered-graphic"}}{{/crossLink}} and {{#crossLink "mixins.graph-has-graph-parent"}}{{/crossLink}} @namespace mixins @class graph-data-graphic @extends Ember.Mixin */ export default Mixin.create({ /** Gets or sets the data used by the component to plot itself. @property data @type Array @default null */ data: null, mappedData: computed('data.[]', { get() { let yPropFn = this.get('yPropFn'); let xPropFn = this.get('xPropFn'); let data = this.get('data'); if(isArray(data)) { return data.map(function(d, i) { let item = [xPropFn(d), yPropFn(d)]; item.data = d; item.origIndex = i; return item; }); } return []; } }), _triggerHasData: on('init', observer('data.[]', function(){ scheduleOnce('afterRender', this, this._sendTriggerHasData); })), _sendTriggerHasData() { this.trigger('hasData', this.get('mappedData')); }, /** The path of the property on each object in {{#crossLink "mixins.graph-data-graphic/data:property"}}{{/crossLink}} to use as x data to plot on the graph. @property xprop @type String @default 'x' */ xprop: 'x', /** The path of the property on each object in {{#crossLink "mixins.graph-data-graphic/data:property"}}{{/crossLink}} to use as y data to plot on the graph. @property yprop @type String @default 'y' */ yprop: 'y', /** The function to get the x value from each {{#crossLink "mixins.graph-data-graphic/data:property"}}{{/crossLink}} object @property xPropFn @type Function @readonly */ xPropFn: computed('xprop', { get() { let xprop = this.get('xprop'); return xprop ? parsePropertyExpr(xprop) : noop; } }), /** The function to get the y value from each {{#crossLink "mixins.graph-data-graphic/data:property"}}{{/crossLink}} object @property yPropFn @type Function @readonly */ yPropFn: computed('yprop', { get() { let yprop = this.get('yprop'); return yprop ? parsePropertyExpr(yprop) : noop; } }), /** The list of data points from {{#crossLink "mixins.graph-data-graphc/mappedData:property"}}{{/crossLink}} that fits within the x domain, plus up to one data point outside of that domain in each direction. @property renderedData @type Array @readonly */ renderedData: computed(function() { return this._computeRenderedData(); }), _scheduleComputeRenderedData: observer('mappedData.[]', 'graph.xScaleType', 'graph.xMin', 'graph.xMax', function() { schedule('afterRender', () => { this.set('renderedData', this._computeRenderedData()); }); }), _computeRenderedData() { let mappedData = this.get('mappedData'); let graph = this.get('graph'); let xScaleType = graph.get('xScaleType'); let xMin = graph.get('xMin'); let xMax = graph.get('xMax'); if(!mappedData || mappedData.length === 0) { return []; } if(xScaleType === 'ordinal') { return mappedData; } return mappedData.filter(function(d, i) { let x = d[0]; let prev = mappedData[i-1]; let next = mappedData[i+1]; let prevX = prev ? prev[0] : null; let nextX = next ? next[0] : null; return between(x, xMin, xMax) || between(prevX, xMin, xMax) || between(nextX, xMin, xMax); }); }, /** The first element from {{#crossLink "mixins.graph-data-graphic/renderedData:property"}}{{/crossLink}} that is actually visible within the x domain. @property firstVisibleData @type {Object} @readonly */ firstVisibleData: computed('renderedData.[]', 'xMin', { get() { let { renderedData, xPropFn, yPropFn, xMin } = this.getProperties('renderedData', 'xPropFn', 'yPropFn', 'xMin'); let first = renderedData[0]; if(first && xMin > first[0] && renderedData.length > 1) { first = renderedData[1]; } return first ? { x: xPropFn(first.data), y: yPropFn(first.data), data: first.data, renderX: first[0], renderY: first[1] } : null; } }), /** The last element from {{#crossLink "mixins.graph-data-graphic/renderedData:property"}}{{/crossLink}} that is actually visible within the x domain. @property lastVisibleData @type {Object} @readonly */ lastVisibleData: computed('renderedData.[]', 'yPropFn', 'xPropFn', 'xMax', { get() { let { renderedData, xPropFn, yPropFn, xMax } = this.getProperties('renderedData', 'xPropFn', 'yPropFn', 'xMax'); let last = renderedData[renderedData.length - 1]; if(last && xMax < last[0] && renderedData.length > 1) { last = renderedData[renderedData.length - 2]; } return last ? { x: xPropFn(last.data), y: yPropFn(last.data), data: last.data, renderX: last[0], renderY: last[1] }: null; } }), _getRenderedDataNearXRange: function(rangeX) { let xScale = this.get('xScale'); let isLinear = xScale && xScale.invert; if(isLinear) { return this.getDataNearX(xScale.invert(rangeX)); } else { //ordinal let range = this.get('graph.xRange'); let v = Math.abs(rangeX - range[0]) / Math.abs(range[1] - range[0]); let renderedData = this.get('renderedData'); let i = Math.floor(v * renderedData.length); return renderedData[i]; } }, getDataNearXRange(rangeX) { let rendered = this._getRenderedDataNearXRange(rangeX); if(!rendered) { return null; } let renderX = rendered[0]; let renderY = rendered[1]; let data = rendered.data; let { x, y } = this.getActualTrackData(renderX, renderY, data); return { renderX, renderY, data, x, y }; }, /** Gets the actual data at a rendered tracking point passed to it. This is overridden in nf-area to account for stacking of data. @method getActualTrackData @param renderX {number} the x domain value the data is rendered at @param renderY {number} the y domain value the data is rendered at @param data {Object} the raw data from the point @return {Object} simple x, y point structure */ getActualTrackData(renderX, renderY, data) { return { x: renderX, y: renderY, data }; }, getDataNearX: function(x) { x = +x; if(x === x) { let renderedData = this.get('renderedData'); let index = nearestIndexTo(renderedData, x, function(d){ return d ? d[0] : null; }); return index !== -1 ? renderedData[index] : null; } }, }); function between(x, a, b) { return a <= x && x <= b; } ================================================ FILE: addon/mixins/graph-graphic-with-tracking-dot.js ================================================ import { schedule, scheduleOnce } from '@ember/runloop'; import Mixin from '@ember/object/mixin'; import { on } from '@ember/object/evented'; import { computed, observer } from '@ember/object'; import { getMousePoint } from '../utils/nf/svg-dom'; export default Mixin.create({ /** Gets or sets the tracking mode of the component. Possible values are: - 'none': no tracking behavior - 'hover': only track while mouse hover - 'snap-last': track while mouse hover, but snap to the last data element when not hovering - 'snap-first': track while mouse hover, but snap to the first data element when not hovering - 'selected-hover': The same as `'hover'` tracking mode, but only when the compononent is {{#crossLink "mixins.graph-selectable-graphic/selected:property"}}{{/crossLink}} - 'selected-snap-last': The same as `'snap-last'` tracking mode, but only when the compononent is {{#crossLink "mixins.graph-selectable-graphic/selected:property"}}{{/crossLink}} - 'selected-snap-first': The same as `'snap-first'` tracking mode, but only when the compononent is {{#crossLink "mixins.graph-selectable-graphic/selected:property"}}{{/crossLink}} @property trackingMode @type String @default 'none' */ trackingMode: 'none', /** The radius of the tracking dot in pixels @property trackingDotRadius @type {number} @default 2.5 */ trackingDotRadius: 2.5, /** The action to send on `didTrack`. @property didTrack @type String @default null */ didTrack: null, /** The value of the data that is being tracked by the component. @property trackedData @type {Object} an object with the following values: - point: an { x, y } pair for the exact px coordinates inside the graph-content - graphX: domain x value at mouse position - graphY: domain y value at mouse position - x: nearest x data value - y: nearest y data value - data: nearest raw data - renderX: domain x value to render a tracking dot at (stacked areas are offset) - renderY: domain x value to render a tracking dot at (stacked areas are offset) - mouseX: mouse x position in pixels - mouseY: mouse y position in pixels @default null */ trackedData: null, /** The value of the data that is being tracked by the component, ONLY if the graph-content is currently being hovered. @property hoverData @type {Object} an object with the following values: - point: an { x, y } pair for the exact px coordinates inside the graph-content - graphX: domain x value at mouse position - graphY: domain y value at mouse position - x: nearest x data value - y: nearest y data value - data: nearest raw data - renderX: domain x value to render a tracking dot at (stacked areas are offset) - renderY: domain x value to render a tracking dot at (stacked areas are offset) - mouseX: mouse x position in pixels - mouseY: mouse y position in pixels @default null */ hoverData: null, _showTrackingDot: true, /** Gets or sets whether the tracking dot should be shown at all. @property showTrackingDot @type {boolean} @default true */ showTrackingDot: computed('trackedData', { get() { return Boolean(this._showTrackingDot && this.get('trackedData')); }, set(value) { this._showTrackingDot = value; } }), /** Observes changes to tracked data and sends the didTrack action. @method _trackedDataChanged @private */ _trackedDataChanged: observer('trackedData', function(){ let trackedData = this.get('trackedData'); this.set('hoverData', this._hovered ? trackedData : null); if(this.get('didTrack') && trackedData) { this.sendAction('didTrack', { x: trackedData.x, y: trackedData.y, data: trackedData.data, source: this, graph: this.get('graph'), }); } }), _cleanup: function(){ if(this._onHoverCleanup) { this._onHoverCleanup(); } if(this._onEndCleanup) { this._onEndCleanup(); } }, _updateTrackingHandling() { let { trackingMode, selected } = this.getProperties('trackingMode', 'selected'); this._cleanup(); switch(trackingMode) { case 'hover': this._onHoverTrack(); this._onEndUntrack(); break; case 'snap-first': this._onHoverTrack(); this._onEndSnapFirst(); break; case 'snap-last': this._onHoverTrack(); this._onEndSnapLast(); break; case 'selected-hover': if(selected) { this._onHoverTrack(); this._onEndUntrack(); } break; case 'selected-snap-first': if(selected) { this._onHoverTrack(); this._onEndSnapFirst(); } break; case 'selected-snap-last': if(selected) { this._onHoverTrack(); this._onEndSnapLast(); } break; } }, _onHoverTrack() { let content = this._content; let mousemoveHandler = e => { schedule('afterRender', () => { this._hovered = true; let evt = this._getEventObject(e); this.set('trackedData', evt); }); }; content.on('mousemove', mousemoveHandler); this._onHoverCleanup = () => { content.off('mousemove', mousemoveHandler); }; }, _hovered: false, _onEndUntrack() { let content = this._content; let mouseoutHandler = () => { this.set('trackedData', null); }; content.on('mouseout', mouseoutHandler); this._onEndCleanup = () => { content.off('mouseout', mouseoutHandler); }; if(!this._hovered) { this.set('trackedData', null); } }, _onEndSnapLast() { let content = this._content; let mouseoutHandler = () => { schedule('afterRender', () => { this._hovered = false; this.set('trackedData', this.get('lastVisibleData')); }); }; let changeHandler = () => { if(!this._hovered) { schedule('afterRender', () => { this.set('trackedData', this.get('lastVisibleData')); }); } }; content.on('mouseout', mouseoutHandler); this.addObserver('lastVisibleData', this, changeHandler); this._onEndCleanup = () => { content.off('mouseout', mouseoutHandler); this.removeObserver('lastVisibleData', this, changeHandler); }; changeHandler(); }, _onEndSnapFirst() { let content = this._content; let mouseoutHandler = () => { this._hovered = false; this.set('trackedData', this.get('firstVisibleData')); }; let changeHandler = () => { if(!this._hovered) { this.set('trackedData', this.get('firstVisibleData')); } }; content.on('mouseout', mouseoutHandler); this.addObserver('firstVisibleData', this, changeHandler); this._onEndCleanup = () => { content.off('mouseout', mouseoutHandler); this.removeObserver('firstVisibleData', this, changeHandler); }; changeHandler(); }, _trackingModeChanged: on('init', observer('trackingMode', 'selected', function() { scheduleOnce('afterRender', this, this._updateTrackingHandling); })), _getEventObject(e) { let { xScale, yScale } = this.getProperties('xScale', 'yScale'); let content = this._content; let point = getMousePoint(content[0], e); let graphX = xScale.invert(point.x); let graphY = yScale.invert(point.y); let near = this.getDataNearXRange(point.x); if(!near) { return { point, graphX, graphY, mouseX: point.x, mouseY: point.y, }; } let { x, y, data, renderX, renderY } = near; return { point, graphX, graphY, x, y, data, renderX, renderY, mouseX: point.x, mouseY: point.y }; }, didInsertElement() { this._super.apply(arguments); this._content = this.$().parents('.nf-graph-content'); }, willDestroyElement() { this._super.apply(arguments); this._cleanup(); } }); ================================================ FILE: addon/mixins/graph-line-utils.js ================================================ import Mixin from '@ember/object/mixin'; /** @namespace mixins @class graph-line-utils @extends Ember.Mixin */ export default Mixin.create({ /** Create a d3 line function from a given scales and interpolation @method createLineFn @param xScale {Function} d3 scale function @param yScale {Function} d3 scale function @param interpolate {String} d3 interpolator name @return {Function} a d3 function that will create SVG path data from a given data set. */ createLineFn: function(xScale, yScale, interpolate){ let interp = interpolate || 'linear'; let xMod = xScale.rangeBand ? xScale.rangeBand() / 2 : 0; let yMod = yScale.rangeBand ? yScale.rangeBand() / 2 : 0; return function(data) { if(!data || data.length === 0) { return 'M0,0'; } return d3.svg.line() .x(function (d) { return (xScale(d[0]) || 0) + xMod; }) .y(function (d) { return (yScale(d[1]) || 0) + yMod; }) .interpolate(interp)(data); }; } }); ================================================ FILE: addon/mixins/graph-registered-graphic.js ================================================ import { on } from '@ember/object/evented'; import Mixin from '@ember/object/mixin'; /** @namespace mixins @class graph-registered-graphic @extends Ember.Mixin */ export default Mixin.create({ init() { this._super(...arguments); let graph = this.get('graph'); if (graph) { graph.registerGraphic(this); } }, /** calls {{#crossLink "components.nf-graph/unregisterGraphic"}}{{/crossLink}} on `didInsertElement`. @method _unregisterGraphic @private */ _unregisterGraphic: on('willDestroyElement', function(){ let graph = this.get('graph'); if (graph) { graph.unregisterGraphic(this); } }) }); ================================================ FILE: addon/mixins/graph-requires-scale-source.js ================================================ import Mixin from '@ember/object/mixin'; import { computed } from '@ember/object'; let scaleProperty = function(scaleKey, zoomKey, offsetKey){ return computed(scaleKey, zoomKey, offsetKey, { get() { // console.log('HERE'); let scale = this.get(scaleKey); let zoom = this.get(zoomKey); let offset = this.get(offsetKey); if(zoom === 1 && offset === 0) { return scale; } let copy = scale.copy(); let domain = copy.domain(); copy.domain([domain[0] / zoom, domain[1] / zoom]); let range = copy.range(); copy.range([range[0] - offset, range[1] - offset]); return copy; } }); }; /** Adds functionality to identify a parent control that will provide an x and y scale, then adds scaling properties to the component it's mixed in to. @namespace mixins @class graph-requires-scale-source */ export default Mixin.create({ /** The scale source @property scaleSource @type d3.nf-graph @default graph */ scaleSource: computed(function() { return this.get('graph'); }), /** The x scale used by this component @property xScale @type d3.scale @readonly */ xScale: scaleProperty('scaleSource.xScale', 'scaleZoomX', 'scaleOffsetX'), /** The y scale used by this component @property yScale @type d3.scale @readonly */ yScale: scaleProperty('scaleSource.yScale', 'scaleZoomY', 'scaleOffsetY'), _scaleOffsetX: 0, _scaleOffsetY: 0, _scaleZoomX: 1, _scaleZoomY: 1, /** The zoom multiplier for the x scale @property scaleZoomX @type Number @default 1 */ scaleZoomX: computed({ get() { return this._scaleZoomX || 1; }, set(key, value) { return this._scaleZoomX = +value || 1; } }), /** The zoom multiplier for the y scale @property scaleZoomY @type Number @default 1 */ scaleZoomY: computed({ get() { return this._scaleZoomY || 1; }, set(key, value) { return this._scaleZoomY = +value || 1; } }), /** The offset, in pixels, for the x scale @property scaleOffsetX @type Number @default 0 */ scaleOffsetX: computed({ get() { return this._scaleOffsetX || 0; }, set(key, value) { return this._scaleOffsetX = +value || 0; } }), /** The offset, in pixels, for the y scale @property scaleOffsetY @type Number @default 0 */ scaleOffsetY: computed({ get() { return this._scaleOffsetY || 0; }, set(key, value) { return this._scaleOffsetY = +value || 0; } }) }); ================================================ FILE: addon/mixins/graph-selectable-graphic.js ================================================ import { once } from '@ember/runloop'; import { observer } from '@ember/object'; import { on } from '@ember/object/evented'; import { alias } from '@ember/object/computed'; import Mixin from '@ember/object/mixin'; /** Adds functionality to a component to make it a selectable graphic within it's parent nf-graph. @namespace mixins @class graph-selectable-graphic @extends Ember.Mixin */ export default Mixin.create({ _selected: false, /** Gets or sets whether or not the graphic is "selectable". Meaning can be "selected" on the nf-graph via some action (usually click). The component will then show up in the nf-graph parent's selected property. @property selectable @type Boolean @default false */ selectable: false, /** Gets or sets whether or not the graphic is selected. @property selected @type Boolean @default false */ selected: false, /** Alias of selected @property isSelected @deprecated use `selected` */ isSelected: alias('selected'), /** Makes calls to the parent nf-graph to update it's `selected` property. Observes changes to `selected` and also fires on `didInsertElement`. @method _updateGraphSelected @private */ _updateGraphSelected: on('didInsertElement', observer('selected', function() { once(this, function(){ let selected = this.get('selected'); let graph = this.get('graph'); if(selected) { graph.selectGraphic(this); } else { graph.deselectGraphic(this); } }); })), }); ================================================ FILE: addon/styles/addon.css ================================================ .nf-graph-background { fill: #f5f6f7; } .nf-graph text { font-size: 10px; } .nf-graph * { -moz-user-select: none; -webkit-user-select: none; user-select: none; -moz-user-drag: none; -webkit-user-drag: none; user-drag: none; } .nf-graph-content-background { fill: #ffffff; } .nf-grid-lane:nth-child(even) { fill: #f5f6f7; } .nf-grid-lane:nth-child(odd) { fill: #ffffff; } .nf-grid-fret { stroke: #d3dbdd; stroke-width: .5; } .nf-x-axis-line { stroke: #d3dbdd; stroke-width: 1; } .nf-x-axis-tick text { dominant-baseline: text-before-edge; text-anchor: middle; } .nf-x-axis-tick-line { stroke: #d3dbdd; stroke-width: 1; } .nf-x-axis.orient-top .nf-x-axis-tick text { dominant-baseline: auto; } .nf-y-axis-line { stroke: #d3dbdd; stroke-width: 1; } .nf-y-axis-tick text { dominant-baseline: central; text-anchor: end; } .nf-y-axis-tick-line { stroke: #d3dbdd; stroke-width: 1; } .nf-y-axis.orient-right .nf-y-axis-tick text { text-anchor: start; } .nf-line-line { stroke-width: 1; fill: none; cursor: default; stroke: #ca0000; } .nf-line-interaction-mask { fill: none; stroke: transparent; stroke-width: 15; cursor: pointer; } .nf-line-tracking-dot { visibility: visible; cursor: default; } .nf-line.selectable .nf-line-tracking-dot { cursor: pointer; } .nf-line.selected .nf-line-line { stroke-width: 2; } .nf-area-area { fill: rgba(255, 0, 0, 0.5); stroke: none; stroke-width: 0; } .nf-area-line { stroke-width: 1px; stroke: red; fill: none; } .nf-area.selected .nf-area-line { stroke-width: 2px; stroke: blue; } .nf-area.selected .nf-area-area { fill: rgba(0, 0, 255, 0.5); } .nf-area.selectable { cursor: pointer; } .nf-area.selectable .nf-area-tracking-dot { cursor: pointer; } .nf-area-tracking-dot { visibility: visible; cursor: default; } .nf-y-diff.positive .nf-y-diff-rect { fill: lime; } .nf-y-diff.positive text { fill: black; } .nf-y-diff.negative .nf-y-diff-rect { fill: #ca0000; } .nf-y-diff.negative text { fill: white; } .nf-y-diff-content text { dominant-baseline: center; text-anchor: start; } .nf-y-diff.orient-right .nf-y-diff-content text { text-anchor: end; } .nf-right-tick-path { fill: white; stroke: #999999; stroke-width: 1; } .nf-right-tick-line { stroke: #999999; stroke-width: 1; } .nf-crosshair-vertical { stroke: #d3dbdd; stroke-width: 1px; visibility: visible; } .nf-crosshair-horizontal { stroke: #d3dbdd; stroke-width: 1px; visibility: visible; } .nf-selection-box-rect { fill: none; stroke: #999999; stroke-width: 1; } .nf-range-marker-marker { fill: #ca0000; } .nf-range-marker-label text { text-anchor: start; dominant-baseline: hanging; } .nf-vertical-line { stroke: #d3dbdd; stroke-width: 1px; } .nf-horizontal-line { stroke: #d3dbdd; stroke-width: 1px; } .nf-brush-selection-overlay { fill: rgba(153, 153, 153, 0.3); } .nf-brush-selection-line { stroke-width: 1px; stroke: #999999; } .nf-brush-selection-left-text-bg, .nf-brush-selection-right-text-bg { fill: white; } .nf-brush-selection-left-text { dominant-baseline: text-before-edge; } .nf-brush-selection-right-text { dominant-baseline: text-before-edge; } ================================================ FILE: addon/templates/components/nf-area-stack.hbs ================================================ {{yield (hash area=(component 'nf-area' stack=this graph=graph scaleSource=scaleSource ) ) }} ================================================ FILE: addon/templates/components/nf-area.hbs ================================================ {{#if showTrackingDot}} {{nf-dot class="nf-area-tracking-dot" graph=graph scaleSource=scaleSource x=trackedData.renderX y=trackedData.renderY r=trackingDotRadius}} {{/if}} ================================================ FILE: addon/templates/components/nf-bars-group.hbs ================================================ {{yield (hash area=(component 'nf-bars' graph=graph scaleSource=scaleSource group=this) ) }} ================================================ FILE: addon/templates/components/nf-bars.hbs ================================================ {{#each bars as |bar|}} {{/each}} {{#if showTrackingDot}} {{nf-dot graph=graph scaleSource=scaleSource x=trackedData.renderX y=trackedData.renderY r=trackingDotRadius}} {{/if}} ================================================ FILE: addon/templates/components/nf-brush-selection.hbs ================================================ ================================================ FILE: addon/templates/components/nf-component.hbs ================================================ {{yield (component componentName graph=graph scaleSource=scaleSource)}} ================================================ FILE: addon/templates/components/nf-crosshairs.hbs ================================================ {{#if vertical}} {{/if}} {{#if horizontal}} {{/if}} ================================================ FILE: addon/templates/components/nf-dot.hbs ================================================ {{yield}} ================================================ FILE: addon/templates/components/nf-graph-content.hbs ================================================ {{#if graph.hasData}} {{#if graph.showLanes}} {{#each gridLanes as |lane|}} {{/each}} {{/if}} {{#if graph.showFrets}} {{#each frets as |fret|}} {{/each}} {{/if}} {{/if}} {{#unless graph.hasData}} No data {{/unless}} {{#nf-graph-yieldables graph=graph scaleSource=graph as |yieldables|}} {{yield yieldables}} {{/nf-graph-yieldables}} ================================================ FILE: addon/templates/components/nf-graph-yieldables.hbs ================================================ {{yield (hash group=(component 'nf-group' graph=graph) component=(component 'nf-component' graph=graph scaleSource=scaleSource) crosshairs=(component 'nf-crosshairs' graph=graph) selection-box=(component 'nf-selection-box' graph=graph scaleSource=scaleSource) svg-image=(component 'nf-svg-image' graph=graph scaleSource=scaleSource) svg-line=(component 'nf-svg-line' graph=graph scaleSource=scaleSource) svg-path=(component 'nf-svg-path' graph=graph scaleSource=scaleSource) svg-rect=(component 'nf-svg-rect' graph=graph scaleSource=scaleSource) tracker=(component 'nf-tracker' graph=graph scaleSource=scaleSource) range-markers=(component 'nf-range-markers' graph=graph scaleSource=scaleSource) dot=(component 'nf-dot' graph=graph scaleSource=scaleSource) line=(component 'nf-line' graph=graph scaleSource=scaleSource) vertical-line=(component 'nf-vertical-line' graph=graph scaleSource=scaleSource) horizontal-line=(component 'nf-horizontal-line' graph=graph scaleSource=scaleSource) area=(component 'nf-area' graph=graph scaleSource=scaleSource) area-stack=(component 'nf-area-stack' graph=graph scaleSource=scaleSource) bars=(component 'nf-bars' graph=graph scaleSource=scaleSource) bars-group=(component 'nf-bars-group' graph=graph scaleSource=scaleSource) brush-selection=(component 'nf-brush-selection' graph=graph scaleSource=scaleSource) ) }} ================================================ FILE: addon/templates/components/nf-graph.hbs ================================================ {{yield (hash x-axis=(component 'nf-x-axis' graph=this scaleSource=this) y-axis=(component 'nf-y-axis' graph=this scaleSource=this) graph=(component 'nf-graph-content' graph=this) right-tick=(component 'nf-right-tick' graph=this scaleSource=this) y-diff=(component 'nf-right-tick' graph=this scaleSource=this) component=(component 'nf-component' graph=this scaleSource=this) ) }} {{#if debug}}
{{debugInfo}}
{{/if}} ================================================ FILE: addon/templates/components/nf-group.hbs ================================================ {{#nf-graph-yieldables graph=graph scaleSource=this as |yieldables|}} {{yield yieldables}} {{/nf-graph-yieldables}} ================================================ FILE: addon/templates/components/nf-horizontal-line.hbs ================================================ {{yield}} ================================================ FILE: addon/templates/components/nf-line.hbs ================================================ {{#if selectable}} {{/if}} {{#if showTrackingDot}} {{nf-dot class="nf-line-tracking-dot" graph=graph scaleSource=scaleSource x=trackedData.renderX y=trackedData.renderY r=trackingDotRadius}} {{/if}} ================================================ FILE: addon/templates/components/nf-plot.hbs ================================================ {{yield}} ================================================ FILE: addon/templates/components/nf-plots.hbs ================================================ {{#each plotData as |item|}} {{#nf-plot graph=graph scaleSource=scaleSource x=item.x y=item.y action='itemClicked' data=item.data multiplierY=multiplierY multiplierX=multiplierX}} {{yield}} {{/nf-plot}} {{/each}} ================================================ FILE: addon/templates/components/nf-range-marker.hbs ================================================ {{yield}} ================================================ FILE: addon/templates/components/nf-range-markers.hbs ================================================ {{yield (hash range-marker=(component 'nf-range-marker' container=this graph=graph scaleSource=scaleSource) ) }} ================================================ FILE: addon/templates/components/nf-right-tick.hbs ================================================ ================================================ FILE: addon/templates/components/nf-selection-box.hbs ================================================ {{yield}} ================================================ FILE: addon/templates/components/nf-svg-image.hbs ================================================ {{yield}} ================================================ FILE: addon/templates/components/nf-svg-line.hbs ================================================ {{yield}} ================================================ FILE: addon/templates/components/nf-svg-path.hbs ================================================ {{yield}} ================================================ FILE: addon/templates/components/nf-svg-rect.hbs ================================================ {{yield}} ================================================ FILE: addon/templates/components/nf-tick-label.hbs ================================================ {{yield}} ================================================ FILE: addon/templates/components/nf-tracker.hbs ================================================ {{yield trackedData}} ================================================ FILE: addon/templates/components/nf-vertical-line.hbs ================================================ {{yield}} ================================================ FILE: addon/templates/components/nf-x-axis.hbs ================================================ {{#each ticks as |tick|}} {{#if hasBlock}} {{#nf-tick-label x=tick.x y=tick.labely}} {{yield tick}} {{/nf-tick-label}} {{else}} {{#nf-tick-label x=tick.x y=tick.labely}} {{tick.value}} {{/nf-tick-label}} {{/if}} {{/each}} ================================================ FILE: addon/templates/components/nf-y-axis.hbs ================================================ {{#each ticks as |tick|}} {{#if hasBlock}} {{#nf-tick-label x=tick.labelx y=tick.y}} {{yield tick}} {{/nf-tick-label}} {{else}} {{#nf-tick-label x=tick.labelx y=tick.y}} {{tick.value}} {{/nf-tick-label}} {{/if}} {{/each}} ================================================ FILE: addon/templates/components/nf-y-diff.hbs ================================================ {{yield}} ================================================ FILE: addon/utils/nf/array-helpers.js ================================================ /** @module utils/nf/array-helpers */ /** returns whatever you pass into it. @method identity @param x {Any} @private @return {Any} x */ function identity(x) { return x; } /** Performs a binary search on the array and finds the nearest index to the value passed. @method nearestIndexTo @param arr {Array} the *sorted* array to search. @param val {Number} the value to find the nearest index to. @param mappingFn {Function} an optional function for pulling values out of the array items. */ export function nearestIndexTo(arr, val, mappingFn) { mappingFn = mappingFn || identity; let startIndex = 0; let stopIndex = arr.length - 1; let middle = (stopIndex + startIndex) / 2; let a = Math.floor(middle); let b = Math.floor(middle + 1); let getItem = function(i){ return mappingFn(arr[i]); }; let av = getItem(a); let bv = getItem(b); while(!(av <= val && val <= bv) && startIndex < stopIndex){ if (val < av){ stopIndex = middle - 1; } else if (val > av){ startIndex = middle + 1; } middle = (stopIndex + startIndex) / 2; a = Math.floor(middle); b = Math.floor(middle + 1); av = getItem(a); bv = getItem(b); } return (Math.abs(val - av) < Math.abs(val - bv)) ? a : b; } let NATURAL_SORT_REGEXP = /[+-]?\d+\.?\d*|\S+/g; /** breaks a string into an array of tokens in preparation for natural comparison and sorting. @method naturalTokenize @param item {String} the value to tokenize @return {Array} an array of tokens found in the item @private */ function naturalTokenize(item) { NATURAL_SORT_REGEXP.lastIndex = 0; let matches; let tokens = []; while(matches === NATURAL_SORT_REGEXP.exec(item)) { tokens.push(matches[0]); } return tokens; } /** A JavaScript sorting predicate for natural sorting. @method naturalCompare @param a {Any} the value to compare to b @param b {Any} the value to compare to a @return {Number} `-1`, `0` or `1` if a is less than, equal to, or greater than b, respectively. */ export function naturalCompare(a, b) { let aTokens = naturalTokenize(a); let bTokens = naturalTokenize(b); let i = 0, bx, ax, na, nb; while((ax = aTokens[i]) && (bx = bTokens[i++])) { na = +ax; nb = +bx; if(nb === nb && na === na) { if(na !== nb) { return na > nb ? 1 : -1; } else { if(ax.length !== bx.length) { return ax.length > bx.length ? 1 : -1; } } } if(ax !== bx) { return ax > bx ? 1 : -1; } } return 0; } /** Sorts the array "naturally". Meaning taking into account both alphabetical and numeric sorting within strings. @method natualSort @param arr {Array} the array to sort */ export function naturalSort(arr) { arr.sort(naturalCompare); } export function sliceArrayLike(arrayLike, from, to) { return Array.prototype.slice.call(arrayLike, from, to); } export function toArray() { return sliceArrayLike(arguments); } ================================================ FILE: addon/utils/nf/graph-event.js ================================================ import GraphPosition from './graph-position'; /** Event object for graph events @namespace utils.nf @class graph-event @extends graph-position */ export default GraphPosition.extend({ /** The original event that triggered this event or action @property originalEvent @type Event @default null */ originalEvent: null, /** A data value passed with the event @property data @type any @default null */ data: null, }); ================================================ FILE: addon/utils/nf/graph-mouse-event.js ================================================ import { reads } from '@ember/object/computed'; import { computed } from '@ember/object'; import GraphPosition from './graph-position'; import { getMousePoint } from './svg-dom'; /** An event context object generally returned by tracking events. Also used as `trackedData` in components such as `nf-line`, `nf-area` and `nf-bars`. @namespace utils.nf @class graph-mouse-event @extends graph-position */ export default GraphPosition.extend({ /** The original event that triggered the action or ember event @property originalEvent @type MouseEvent @default null */ originalEvent: null, /** Method used to get the mouse position relative to a container @method _getMousePoint @private */ _getMousePoint: getMousePoint, /** The coordinates of the mouse relative to eh nf-graph-content @property _mousePoint @type Object @readonly @private */ _mousePoint: computed('originalEvent', 'graphContentElement', { get() { return this._getMousePoint(this.get('graphContentElement'), this.get('originalEvent')); } }), /** The nf-graph-content element of the nf-graph @property graphContentElement @type SVGGElement @readonly */ graphContentElement: null, /** The mouse x position relative to the graph content @property mouseX @type Number @readonly */ mouseX: reads('_mousePoint.x'), /** The mouse y position relative to the graph content @property mouseY @type Number @readonly */ mouseY: reads('_mousePoint.y'), /** A positioning object for the mouse position @property mousePosition @type graph-position @readonly */ mousePosition: computed('mouseX', 'mouseY', 'source', 'graph', { get() { return GraphPosition.create({ graphX: this.get('mouseX'), graphY: this.get('mouseY'), source: this.get('source'), graphContentElement: this.get('graphContentElement'), }); } }), /** The raw data point nearest the mouse.graphX position @property nearestDataPoint @type Array @readonly */ nearestDataPoint: computed('source', 'mouse.graphX', { get() { let mouseX = this.get('mouseX'); let source = this.get('source'); return source ? source.getDataNearXRange(mouseX) : undefined; } }), /** The x domain value at the nearest data point to the mouse position along the x axis. @property x @readonly */ x: computed('nearestDataPoint', { get() { let nearestDataPoint = this.get('nearestDataPoint'); this._x = nearestDataPoint ? nearestDataPoint[0] : undefined; return this._x; } }), /** The y domain value at the nearest data point to the mouse position along the x axis. @property y @readonly */ y: computed('nearestDataPoint', { get() { let nearestDataPoint = this.get('nearestDataPoint'); this._y = nearestDataPoint ? nearestDataPoint[1] : undefined; return this._y; } }), /** The data carried by the nearest data point to the mouse position along the x axis. @property data @readonly */ data: reads('nearestDataPoint.data'), }); ================================================ FILE: addon/utils/nf/graph-position.js ================================================ import { reads } from '@ember/object/computed'; import EmberObject, { computed } from '@ember/object'; /** Position calculation class for nf-graph related events @namespace utils.nf @class graph-position @extends Ember.Object */ export default EmberObject.extend({ /** @property graph @type component.nf-graph @default null */ graph: null, /** @property source @type Ember.Component */ source: null, /** The x position relative to graph @property graphX @type Number */ graphX: computed('x', 'xScale', { get() { let scale = this.get('xScale'); if(scale) { let x = this.get('x'); this._graphX = scale(x); } return this._graphX || NaN; }, set(key, value) { return this._graphX = value || NaN; } }), /** The y position relative to graph @property graphY @type Number */ graphY: computed('y', 'yScale', { get() { let scale = this.get('yScale'); if(scale) { let y = this.get('y'); this._graphY = scale(y); } return this._graphY || NaN; }, set(key, value) { return this._graphY = value || NaN; } }), /** The x domain value @property x @type Number */ x: computed('graphX', 'xScale', { get() { let scale = this.get('xScale'); if (scale && scale.invert){ let graphX = this.get('graphX'); this._x = scale.invert(graphX); } return this._x || 0; }, set(key, value) { return this._x = value; } }), /** The y domain value @property y @type Number */ y: computed('graphY', 'yScale', { get() { let scale = this.get('yScale'); if (scale && scale.invert){ let graphY = this.get('graphY'); this._y = scale.invert(graphY); } return this._y || 0; }, set(key, value) { return this._y = value; } }), /** The x position relative to the document @property pageX @type Number */ pageX: computed('graphX', 'graphOffset', 'graphContentX', { get() { let offset = this.get('graphOffset'); if(offset) { let graphX = this.get('graphX') || 0; let graphContentX = this.get('graphContentX') || 0; return offset.left + graphX + graphContentX; } } }), /** The y position relative to the document @property pageY @type Number */ pageY: computed('graphY', 'graphOffset', 'graphContentY', { get() { let offset = this.get('graphOffset'); if(offset) { let graphY = this.get('graphY') || 0; let graphContentY = this.get('graphContentY') || 0; return offset.top + graphY + graphContentY; } } }), /** The x scale from either the source or graph used to calculate positions @property xScale @type d3.scale @readonly */ xScale: computed('graph.xScale', 'source.xScale', { get() { return this.get('source.xScale') || this.get('graph.xScale'); } }), /** The y scale from either the source or graph used to calculate positions @property yScale @type d3.scale @readonly */ yScale: computed('graph.yScale', 'source.yScale', { get() { return this.get('source.yScale') || this.get('graph.yScale'); } }), /** The JQuery offset of the graph element @property graphOffset @type Object @readonly */ graphOffset: computed('graph', { get() { let graph = this.get('graph'); if(graph) { let content = graph.$('.nf-graph-content'); return content ? content.offset() : undefined; } } }), /** The center point at x. Use in case of requiring a center point and using ordinal scale. @property centerX @type Number */ centerX: computed('xScale', 'graphX', { get() { let scale = this.get('xScale'); let graphX = this.get('graphX'); if(scale && scale.rangeBand) { let rangeBand = scale.rangeBand(); return graphX + (rangeBand / 2); } return graphX; } }), /** The center point at y. Use in case of requiring a center point and using ordinal scale. @property centerY @type Number */ centerY: computed('yScale', 'graphY', { get() { let scale = this.get('yScale'); let graphY = this.get('graphY'); if(scale && scale.rangeBand) { let rangeBand = scale.rangeBand(); return graphY + (rangeBand / 2); } return graphY; } }), /** The x position of the nf-graph-content within the nf-graph @property _graphContentX @type Number @private */ graphContentX: reads('graph.graphX'), /** The y position of the nf-graph-content within the nf-graph @property _graphContentY @type Number @private */ graphContentY: reads('graph.graphY'), }); ================================================ FILE: addon/utils/nf/scale-utils.js ================================================ /** utilities for dealing with d3 scales @namespace utils.nf @module scale-utils */ /** Ensures the output of a scale function is something palatable by SVG. @method normalizeScale @param scale {d3.scale} the scale to use to get the value @param val {any} the value to transform with the scale @return {Number} the output of the scale function, but if NaN, it will return 0. */ function normalizeScale(scale, val) { return (scale ? scale(val) : 0) || 0; } export { normalizeScale }; ================================================ FILE: addon/utils/nf/scroll-area-action-context.js ================================================ import EmberObject, { computed } from '@ember/object'; /** Action context event object for an nf-scroll-area scroll event. @namespace utils.nf @class scroll-area-action-context */ export default EmberObject.extend({ /** The scroll top in pixels. @property scrollTop @type Number @default 0 */ scrollTop: 0, /** The scroll height of the element. @property scrollHeight @type number @default 0 */ scrollHeight: 0, /** The outer height of the element @property outerHeight @type Number @default 0 */ outerHeight: 0, /** The scroll left in pixels. @property scrollLeft @type Number @default 0 */ scrollLeft: 0, /** The scroll width of the element. @property scrollWidth @type number @default 0 */ scrollWidth: 0, /** The outer width of the element @property outerWidth @type Number @default 0 */ outerWidth: 0, /** The calculated maximum value for scrollTop in pixels. @property scrollTopMax @type Number @readonly */ scrollTopMax: computed('outerHeight', 'scrollHeight', { get() { return this.get('scrollHeight') - this.get('outerHeight'); } }), /** The calculated percentage, in decimals, of content scrolled. @property scrollTopPercentage @type Number @readonly */ scrollTopPercentage: computed('scrollTop', 'scrollTopMax', { get() { return this.get('scrollTop') / this.get('scrollTopMax'); } }), /** The calculated maximum value for scrollTop in pixels. @property scrollLeftMax @type Number @readonly */ scrollLeftMax: computed('outerWidth', 'scrollWidth', { get() { return this.get('scrollWidth') - this.get('outerWidth'); } }), /** The calculated percentage, in decimals, of content scrolled. @property scrollLeftPercentage @type Number @readonly */ scrollLeftPercentage: computed('scrollLeft', 'scrollLeftMax', { get() { return this.get('scrollLeft') / this.get('scrollLeftMax'); } }), /** The component that fired the event @property source @type Ember.Component @default null */ source: null, /** The optional data to send with the action @property data @default null */ data: null, /** The original scroll event object @property originalEvent @type Event @default null */ originalEvent: null, }); ================================================ FILE: addon/utils/nf/svg-dom.js ================================================ /* globals getComputedStyle, Image, Blob, URL */ import { isPresent } from '@ember/utils'; /** Traverses an element and all of its descendants, setting their inline style property to whatever the computed style is. @method inlineAllStyles @param element {Element} the dom element to traverse. @private */ function inlineAllStyles(element) { let styles = getComputedStyle(element); for(let key in styles) { if(styles.hasOwnProperty(key)) { element.style[key] = styles[key]; } } for(let i = 0; i < element.childNodes.length; i++) { let node = element.childNodes[i]; if(node.nodeType === 1) { inlineAllStyles(node); } } } /** Renders an SVG element to a Base64 encoded data URI. @method svgToImageUrl @param svg {SVGSVGElement} the svg element to render */ export function svgToImageUrl(svg, callback) { let clone = svg.cloneNode(true); let parent = svg.parentElement; let canvas = document.createElement('canvas'); canvas.setAttribute('width', svg.getAttribute('width')); canvas.setAttribute('height', svg.getAttribute('height')); let context = canvas.getContext('2d'); parent.insertBefore(clone, svg); clone.setAttribute('xmlns', 'http://www.w3.org/2000/svg'); inlineAllStyles(clone); let img = new Image(); let blob = new Blob([clone.outerHTML], { type: 'image/svg+xml;charset=utf-8' }); clone.remove(); let url = URL.createObjectURL(blob); img.onload = function(){ context.drawImage(img, 0, 0); URL.revokeObjectURL(url); if(callback) { callback(canvas.toDataURL()); } canvas.remove(); }; img.src = url; } /** Triggers a download of an image rendered from the passed svg document @method downloadSvg @param svg {SVGSVGElement} the svg document to render */ export function downloadSvg(svg) { svgToImageUrl(svg, function(url) { let dlUrl = url.replace('image/png', 'image/octet-stream'); location.href = dlUrl; }); } /** @method getMousePoint @param container {SVGElement} the container reference to get the mouse position from @param e {MouseEvent} A DOM mouse event @return {Object} the {x, y} data of the mouse position relative to the container */ export function getMousePoint(container, e) { let x, y; if(e && isPresent(e.clientX) && isPresent(e.clientY)) { let svg = container.ownerSVGElement || container; if (svg.createSVGPoint) { let point = svg.createSVGPoint(); point.x = e.clientX; point.y = e.clientY; point = point.matrixTransform(container.getScreenCTM().inverse()); x = point.x; y = point.y; } else { let rect = container.getBoundingClientRect(); x = e.clientX - rect.left - container.clientLeft; y = e.clientY - rect.top - container.clientTop; } } return { x: x, y: y, }; } /** Creates an SVG path string for a rectangle @method getRectPath @param x the x position of the rectangle @param y {Number} the y position of the rectangle @param w {Number} the width of the rectangle @param h {Number} the height of the rectangle @return {String} the svg path string for the rectangle */ export function getRectPath(x, y, w, h) { x = +x || 0; y = +y || 0; w = +w || 0; h = +h || 0; let x2 = w + x; let y2 = h + y; return `M${x},${y} L${x},${y2} L${x2},${y2} L${x2},${y} L${x},${y}`; } ================================================ FILE: addon/utils/nf/tracked-array-property.js ================================================ import { keys } from '@ember/polyfills'; import { isArray, A } from '@ember/array'; import { computed, get, set } from '@ember/object'; function trackedArrayProperty(arraySourceProp, trackByProp, backingField) { let arraySourceDependency = arraySourceProp + '.[]'; backingField = backingField || '_%@_trackBy_%@'.fmt(arraySourceProp, trackByProp); return computed(arraySourceDependency, { get() { let array = this.get(backingField); if(!isArray(array)){ array = A(); } let trackBy = trackByProp ? this.get(trackByProp) : null; let keyFn = !trackBy ? function(d, i) { return i; } : function(d) { return get(d, trackBy); }; let source = this.get(arraySourceProp); if(!isArray(source) || source.length === 0) { array = A(); } else { let sourceKeys = []; source.forEach(function(d, i) { let key = keyFn(d, i); sourceKeys.pushObject(key); let found = array.find(function(x, i) { return keyFn(x, i) === key; }); set(d, '__meta__trackedKey', key); if(found) { keys(d).forEach(function(k) { let v = get(d, k); if(get(found, k) !== v) { set(found, k, v); } }); } else { array.pushObject(d); } }); let d, i; for(i = array.length - 1; i >= 0; i--) { d = array[i]; let key = keyFn(d, i); if(sourceKeys.indexOf(key) === -1) { array.removeObject(d); } } } this.set(backingField, array); return array; } }); } export default trackedArrayProperty; ================================================ FILE: addon/utils/parse-property-expression.js ================================================ /** A function that will parse a path expression into a "getter" function that can retrieve a value from that path off of any object when called. ### Example import parsePropertyExpr from 'utils/parse-property-expr'; let test = { foo: { bar: ['apple', 'banana'] } }; let getFooBar1 = parsePropertyExpr('foo.bar[1]'); let result = getFooBar1(test); console.log(result); // "banana" ### Notes Will return `undefined` if the nothing is at the end of the path, or the path cannot be reached. @namespace utils @class parse-property-expression */ /** @method default @param expr {String} the expression to parse @return {Function} a function that when called with an object, will locate the value at the end of the expressed path. */ export default function parsePropertyExpression(expr) { let c, i; let isIndex = false; let token = ''; let tokens = []; let addToken = function(){ if(token === '') { return; } if(isIndex) { token = +token; } tokens.push(token); token = ''; isIndex = c === '['; }; for(i = 0; i < expr.length; i++) { c = expr[i]; if('[].'.indexOf(c) >= 0) { addToken(); } else { token += c; } } addToken(); return function(obj){ let i, next; let result = obj[tokens[0]]; if(result) { for(i = 1; i < tokens.length; i++) { next = result[tokens[i]]; if(typeof next !== 'object') { return next; } result = next; } } return result; }; } ================================================ FILE: app/.gitkeep ================================================ ================================================ FILE: app/components/.gitignore ================================================ node_modules ================================================ FILE: app/components/nf-area-stack.js ================================================ export { default } from 'ember-nf-graph/components/nf-area-stack'; ================================================ FILE: app/components/nf-area.js ================================================ export { default } from 'ember-nf-graph/components/nf-area'; ================================================ FILE: app/components/nf-bars-group.js ================================================ export { default } from 'ember-nf-graph/components/nf-bars-group'; ================================================ FILE: app/components/nf-bars.js ================================================ export { default } from 'ember-nf-graph/components/nf-bars'; ================================================ FILE: app/components/nf-brush-selection.js ================================================ export { default } from 'ember-nf-graph/components/nf-brush-selection'; ================================================ FILE: app/components/nf-component.js ================================================ export { default } from 'ember-nf-graph/components/nf-component'; ================================================ FILE: app/components/nf-crosshairs.js ================================================ export { default } from 'ember-nf-graph/components/nf-crosshairs'; ================================================ FILE: app/components/nf-dot.js ================================================ export { default } from 'ember-nf-graph/components/nf-dot'; ================================================ FILE: app/components/nf-graph-content.js ================================================ export { default } from 'ember-nf-graph/components/nf-graph-content'; ================================================ FILE: app/components/nf-graph-yieldables.js ================================================ export { default } from 'ember-nf-graph/components/nf-graph-yieldables'; ================================================ FILE: app/components/nf-graph.js ================================================ export { default } from 'ember-nf-graph/components/nf-graph'; ================================================ FILE: app/components/nf-group.js ================================================ export { default } from 'ember-nf-graph/components/nf-group'; ================================================ FILE: app/components/nf-horizontal-line.js ================================================ export { default } from 'ember-nf-graph/components/nf-horizontal-line'; ================================================ FILE: app/components/nf-line.js ================================================ export { default } from 'ember-nf-graph/components/nf-line'; ================================================ FILE: app/components/nf-plot.js ================================================ export { default } from 'ember-nf-graph/components/nf-plot'; ================================================ FILE: app/components/nf-plots.js ================================================ export { default } from 'ember-nf-graph/components/nf-plots'; ================================================ FILE: app/components/nf-range-marker.js ================================================ export { default } from 'ember-nf-graph/components/nf-range-marker'; ================================================ FILE: app/components/nf-range-markers.js ================================================ export { default } from 'ember-nf-graph/components/nf-range-markers'; ================================================ FILE: app/components/nf-right-tick.js ================================================ export { default } from 'ember-nf-graph/components/nf-right-tick'; ================================================ FILE: app/components/nf-selection-box.js ================================================ export { default } from 'ember-nf-graph/components/nf-selection-box'; ================================================ FILE: app/components/nf-svg-image.js ================================================ export { default } from 'ember-nf-graph/components/nf-svg-image'; ================================================ FILE: app/components/nf-svg-line.js ================================================ export { default } from 'ember-nf-graph/components/nf-svg-line'; ================================================ FILE: app/components/nf-svg-path.js ================================================ export { default } from 'ember-nf-graph/components/nf-svg-path'; ================================================ FILE: app/components/nf-svg-rect.js ================================================ export { default } from 'ember-nf-graph/components/nf-svg-rect'; ================================================ FILE: app/components/nf-tick-label.js ================================================ export { default } from 'ember-nf-graph/components/nf-tick-label'; ================================================ FILE: app/components/nf-tracker.js ================================================ export { default } from 'ember-nf-graph/components/nf-tracker'; ================================================ FILE: app/components/nf-vertical-line.js ================================================ export { default } from 'ember-nf-graph/components/nf-vertical-line'; ================================================ FILE: app/components/nf-x-axis.js ================================================ export { default } from 'ember-nf-graph/components/nf-x-axis'; ================================================ FILE: app/components/nf-y-axis.js ================================================ export { default } from 'ember-nf-graph/components/nf-y-axis'; ================================================ FILE: app/components/nf-y-diff.js ================================================ export { default } from 'ember-nf-graph/components/nf-y-diff'; ================================================ FILE: config/ember-try.js ================================================ module.exports = { scenarios: [ { name: 'ember-lts-2.12', npm: { devDependencies: { 'ember-source': '~2.12.0' } } }, { name: 'ember-lts-2.16', npm: { devDependencies: { 'ember-source': '~2.16.0' } } }, { name: 'ember-release', bower: { dependencies: { 'ember': 'components/ember#release' }, resolutions: { 'ember': 'release' } }, npm: { devDependencies: { 'ember-source': null } } }, { name: 'ember-beta', bower: { dependencies: { 'ember': 'components/ember#beta' }, resolutions: { 'ember': 'beta' } }, npm: { devDependencies: { 'ember-source': null } } }, { name: 'ember-canary', bower: { dependencies: { 'ember': 'components/ember#canary' }, resolutions: { 'ember': 'canary' } }, npm: { devDependencies: { 'ember-source': null } } }, { name: 'ember-default', npm: { devDependencies: {} } } ] }; ================================================ FILE: config/environment.js ================================================ 'use strict'; module.exports = function(/* environment, appConfig */) { return { }; }; ================================================ FILE: docs/api.js ================================================ YUI.add("yuidoc-meta", function(Y) { Y.YUIDoc = { meta: { "classes": [ "components.nf-area", "components.nf-area-stack", "components.nf-bars", "components.nf-crosshair", "components.nf-dot", "components.nf-gg", "components.nf-graph", "components.nf-graph-content", "components.nf-horizontal-line", "components.nf-line", "components.nf-plot", "components.nf-range-marker", "components.nf-range-markers", "components.nf-right-tick", "components.nf-selection-box", "components.nf-svg-image", "components.nf-svg-line", "components.nf-svg-path", "components.nf-svg-rect", "components.nf-tracker", "components.nf-vertical-line", "components.nf-x-axis", "components.nf-y-axis", "components.nf-y-diff", "mixins.graph-area-utils", "mixins.graph-data-graphic", "mixins.graph-has-graph-parent", "mixins.graph-line-utils", "mixins.graph-registered-graphic", "mixins.graph-requires-scale-source", "mixins.graph-selectable-graphic", "utils.nf.graph-event", "utils.nf.graph-mouse-event", "utils.nf.graph-position", "utils.nf.scroll-area-action-context", "utils.parse-property-expression" ], "modules": [ "scale-utils", "utils_nf_array-helpers", "utils_nf_svg-dom" ], "allModules": [ { "displayName": "scale-utils", "name": "scale-utils", "description": "utilities for dealing with d3 scales" }, { "displayName": "utils/nf/array-helpers", "name": "utils_nf_array-helpers" }, { "displayName": "utils/nf/svg-dom", "name": "utils_nf_svg-dom" } ] } }; }); ================================================ FILE: docs/assets/css/main.css ================================================ /* Font sizes for all selectors other than the body are given in percentages, with 100% equal to 13px. To calculate a font size percentage, multiply the desired size in pixels by 7.6923076923. Here's a quick lookup table: 10px - 76.923% 11px - 84.615% 12px - 92.308% 13px - 100% 14px - 107.692% 15px - 115.385% 16px - 123.077% 17px - 130.769% 18px - 138.462% 19px - 146.154% 20px - 153.846% */ html { background: #fff; color: #333; overflow-y: scroll; } body { /*font: 13px/1.4 'Lucida Grande', 'Lucida Sans Unicode', 'DejaVu Sans', 'Bitstream Vera Sans', 'Helvetica', 'Arial', sans-serif;*/ font: 13px/1.4 'Helvetica', 'Arial', sans-serif; margin: 0; padding: 0; } /* -- Links ----------------------------------------------------------------- */ a { color: #356de4; text-decoration: none; } .hidden { display: none; } a:hover { text-decoration: underline; } /* "Jump to Table of Contents" link is shown to assistive tools, but hidden from sight until it's focused. */ .jump { position: absolute; padding: 3px 6px; left: -99999px; top: 0; } .jump:focus { left: 40%; } /* -- Paragraphs ------------------------------------------------------------ */ p { margin: 1.3em 0; } dd p, td p { margin-bottom: 0; } dd p:first-child, td p:first-child { margin-top: 0; } /* -- Headings -------------------------------------------------------------- */ h1, h2, h3, h4, h5, h6 { color: #D98527;/*was #f80*/ font-family: 'Trebuchet MS', sans-serif; font-weight: bold; line-height: 1.1; margin: 1.1em 0 0.5em; } h1 { font-size: 184.6%; color: #30418C; margin: 0.75em 0 0.5em; } h2 { font-size: 153.846%; color: #E48A2B; } h3 { font-size: 138.462%; } h4 { border-bottom: 1px solid #DBDFEA; color: #E48A2B; font-size: 115.385%; font-weight: normal; padding-bottom: 2px; } h5, h6 { font-size: 107.692%; } /* -- Code and examples ----------------------------------------------------- */ code, kbd, pre, samp { font-family: Menlo, Monaco, 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', 'Courier New', Courier, monospace; font-size: 92.308%; line-height: 1.35; } p code, p kbd, p samp, li code { background: #FCFBFA; border: 1px solid #EFEEED; padding: 0 3px; } a code, a kbd, a samp, pre code, pre kbd, pre samp, table code, table kbd, table samp, .intro code, .intro kbd, .intro samp, .toc code, .toc kbd, .toc samp { background: none; border: none; padding: 0; } pre.code, pre.terminal, pre.cmd { overflow-x: auto; *overflow-x: scroll; padding: 0.3em 0.6em; } pre.code { background: #FCFBFA; border: 1px solid #EFEEED; border-left-width: 5px; } pre.terminal, pre.cmd { background: #F0EFFC; border: 1px solid #D0CBFB; border-left: 5px solid #D0CBFB; } /* Don't reduce the font size of // elements inside
   blocks. */
pre code, pre kbd, pre samp { font-size: 100%; }

/* Used to denote text that shouldn't be selectable, such as line numbers or
   shell prompts. Guess which browser this doesn't work in. */
.noselect {
    -moz-user-select: -moz-none;
    -khtml-user-select: none;
    -webkit-user-select: none;
    -o-user-select: none;
    user-select: none;
}

/* -- Lists ----------------------------------------------------------------- */
dd { margin: 0.2em 0 0.7em 1em; }
dl { margin: 1em 0; }
dt { font-weight: bold; }

/* -- Tables ---------------------------------------------------------------- */
caption, th { text-align: left; }

table {
    border-collapse: collapse;
    width: 100%;
}

td, th {
    border: 1px solid #fff;
    padding: 5px 12px;
    vertical-align: top;
}

td { background: #E6E9F5; }
td dl { margin: 0; }
td dl dl { margin: 1em 0; }
td pre:first-child { margin-top: 0; }

th {
    background: #D2D7E6;/*#97A0BF*/
    border-bottom: none;
    border-top: none;
    color: #000;/*#FFF1D5*/
    font-family: 'Trebuchet MS', sans-serif;
    font-weight: bold;
    line-height: 1.3;
    white-space: nowrap;
}


/* -- Layout and Content ---------------------------------------------------- */
#doc {
    margin: auto;
    min-width: 1024px;
}

.content { padding: 0 20px 0 25px; }

.sidebar {
    padding: 0 15px 0 10px;
}
#bd {
    padding: 7px 0 130px;
    position: relative;
    width: 99%;
}

/* -- Table of Contents ----------------------------------------------------- */

/* The #toc id refers to the single global table of contents, while the .toc
   class refers to generic TOC lists that could be used throughout the page. */

.toc code, .toc kbd, .toc samp { font-size: 100%; }
.toc li { font-weight: bold; }
.toc li li { font-weight: normal; }

/* -- Intro and Example Boxes ----------------------------------------------- */
/*
.intro, .example { margin-bottom: 2em; }
.example {
    -moz-border-radius: 4px;
    -webkit-border-radius: 4px;
    border-radius: 4px;
    -moz-box-shadow: 0 0 5px #bfbfbf;
    -webkit-box-shadow: 0 0 5px #bfbfbf;
    box-shadow: 0 0 5px #bfbfbf;
    padding: 1em;
}
.intro {
    background: none repeat scroll 0 0 #F0F1F8; border: 1px solid #D4D8EB; padding: 0 1em;
}
*/

/* -- Other Styles ---------------------------------------------------------- */

/* These are probably YUI-specific, and should be moved out of Selleck's default
   theme. */

.button {
    border: 1px solid #dadada;
    -moz-border-radius: 3px;
    -webkit-border-radius: 3px;
    border-radius: 3px;
    color: #444;
    display: inline-block;
    font-family: Helvetica, Arial, sans-serif;
    font-size: 92.308%;
    font-weight: bold;
    padding: 4px 13px 3px;
    -moz-text-shadow: 1px 1px 0 #fff;
    -webkit-text-shadow: 1px 1px 0 #fff;
    text-shadow: 1px 1px 0 #fff;
    white-space: nowrap;

    background: #EFEFEF; /* old browsers */
    background: -moz-linear-gradient(top, #f5f5f5 0%, #efefef 50%, #e5e5e5 51%, #dfdfdf 100%); /* firefox */
    background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#f5f5f5), color-stop(50%,#efefef), color-stop(51%,#e5e5e5), color-stop(100%,#dfdfdf)); /* webkit */
    filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#f5f5f5', endColorstr='#dfdfdf',GradientType=0 ); /* ie */
}

.button:hover {
    border-color: #466899;
    color: #fff;
    text-decoration: none;
    -moz-text-shadow: 1px 1px 0 #222;
    -webkit-text-shadow: 1px 1px 0 #222;
    text-shadow: 1px 1px 0 #222;

    background: #6396D8; /* old browsers */
    background: -moz-linear-gradient(top, #6396D8 0%, #5A83BC 50%, #547AB7 51%, #466899 100%); /* firefox */
    background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#6396D8), color-stop(50%,#5A83BC), color-stop(51%,#547AB7), color-stop(100%,#466899)); /* webkit */
    filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#6396D8', endColorstr='#466899',GradientType=0 ); /* ie */
}

.newwindow { text-align: center; }

.header .version em {
    display: block;
    text-align: right;
}


#classdocs .item {
    border-bottom: 1px solid #466899;
    margin: 1em 0;
    padding: 1.5em;
}

#classdocs .item .params p,
    #classdocs .item .returns p,{
    display: inline;
}

#classdocs .item em code, #classdocs .item em.comment {
    color: green;
}

#classdocs .item em.comment a {
    color: green;
    text-decoration: underline;
}

#classdocs .foundat {
    font-size: 11px;
    font-style: normal;
}

.attrs .emits {
    margin-left: 2em;
    padding: .5em;
    border-left: 1px dashed #ccc;
}

abbr {
    border-bottom: 1px dashed #ccc;
    font-size: 80%;
    cursor: help;
}

.prettyprint li.L0, 
.prettyprint li.L1, 
.prettyprint li.L2, 
.prettyprint li.L3, 
.prettyprint li.L5, 
.prettyprint li.L6, 
.prettyprint li.L7, 
.prettyprint li.L8 {
    list-style: decimal;
}

ul li p {
    margin-top: 0;
}

.method .name {
    font-size: 110%;
}

.apidocs .methods .extends .method,
.apidocs .properties .extends .property,
.apidocs .attrs .extends .attr,
.apidocs .events .extends .event {
    font-weight: bold;
}

.apidocs .methods .extends .inherited,
.apidocs .properties .extends .inherited,
.apidocs .attrs .extends .inherited,
.apidocs .events .extends .inherited {
    font-weight: normal;
}

#hd {
    background: whiteSmoke;
    background: -moz-linear-gradient(top,#DCDBD9 0,#F6F5F3 100%);
    background: -webkit-gradient(linear,left top,left bottom,color-stop(0%,#DCDBD9),color-stop(100%,#F6F5F3));
    filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#dcdbd9',endColorstr='#F6F5F3',GradientType=0);
    border-bottom: 1px solid #DFDFDF;
    padding: 0 15px 1px 20px;
    margin-bottom: 15px;
}

#hd img {
    margin-right: 10px;
    vertical-align: middle;
}


/* -- API Docs CSS ---------------------------------------------------------- */

/*
This file is organized so that more generic styles are nearer the top, and more
specific styles are nearer the bottom of the file. This allows us to take full
advantage of the cascade to avoid redundant style rules. Please respect this
convention when making changes.
*/

/* -- Generic TabView styles ------------------------------------------------ */

/*
These styles apply to all API doc tabviews. To change styles only for a
specific tabview, see the other sections below.
*/

.yui3-js-enabled .apidocs .tabview {
    visibility: hidden; /* Hide until the TabView finishes rendering. */
    _visibility: visible;
}

.apidocs .tabview.yui3-tabview-content { visibility: visible; }
.apidocs .tabview .yui3-tabview-panel { background: #fff; }

/* -- Generic Content Styles ------------------------------------------------ */

/* Headings */
h2, h3, h4, h5, h6 {
    border: none;
    color: #30418C;
    font-weight: bold;
    text-decoration: none;
}

.link-docs {
    float: right;
    font-size: 15px;
    margin: 4px 4px 6px;
    padding: 6px 30px 5px;
}

.apidocs { zoom: 1; }

/* Generic box styles. */
.apidocs .box {
    border: 1px solid;
    border-radius: 3px;
    margin: 1em 0;
    padding: 0 1em;
}

/* A flag is a compact, capsule-like indicator of some kind. It's used to
   indicate private and protected items, item return types, etc. in an
   attractive and unobtrusive way. */
.apidocs .flag {
    background: #bababa;
    border-radius: 3px;
    color: #fff;
    font-size: 11px;
    margin: 0 0.5em;
    padding: 2px 4px 1px;
}

/* Class/module metadata such as "Uses", "Extends", "Defined in", etc. */
.apidocs .meta {
    background: #f9f9f9;
    border-color: #efefef;
    color: #555;
    font-size: 11px;
    padding: 3px 6px;
}

.apidocs .meta p { margin: 0; }

/* Deprecation warning. */
.apidocs .box.deprecated,
.apidocs .flag.deprecated {
    background: #fdac9f;
    border: 1px solid #fd7775;
}

.apidocs .box.deprecated p { margin: 0.5em 0; }
.apidocs .flag.deprecated { color: #333; }

/* Module/Class intro description. */
.apidocs .intro {
    background: #f0f1f8;
    border-color: #d4d8eb;
}

/* Loading spinners. */
#bd.loading .apidocs,
#api-list.loading .yui3-tabview-panel {
    background: #fff url(../img/spinner.gif) no-repeat center 70px;
    min-height: 150px;
}

#bd.loading .apidocs .content,
#api-list.loading .yui3-tabview-panel .apis {
    display: none;
}

.apidocs .no-visible-items { color: #666; }

/* Generic inline list. */
.apidocs ul.inline {
    display: inline;
    list-style: none;
    margin: 0;
    padding: 0;
}

.apidocs ul.inline li { display: inline; }

/* Comma-separated list. */
.apidocs ul.commas li:after { content: ','; }
.apidocs ul.commas li:last-child:after { content: ''; }

/* Keyboard shortcuts. */
kbd .cmd { font-family: Monaco, Helvetica; }

/* -- Generic Access Level styles ------------------------------------------- */
.apidocs .item.protected,
.apidocs .item.private,
.apidocs .index-item.protected,
.apidocs .index-item.deprecated,
.apidocs .index-item.private {
    display: none;
}

.show-deprecated .item.deprecated,
.show-deprecated .index-item.deprecated,
.show-protected .item.protected,
.show-protected .index-item.protected,
.show-private .item.private,
.show-private .index-item.private {
    display: block;
}

.hide-inherited .item.inherited,
.hide-inherited .index-item.inherited {
    display: none;
}

/* -- Generic Item Index styles --------------------------------------------- */
.apidocs .index { margin: 1.5em 0 3em; }

.apidocs .index h3 {
    border-bottom: 1px solid #efefef;
    color: #333;
    font-size: 13px;
    margin: 2em 0 0.6em;
    padding-bottom: 2px;
}

.apidocs .index .no-visible-items { margin-top: 2em; }

.apidocs .index-list {
    border-color: #efefef;
    font-size: 12px;
    list-style: none;
    margin: 0;
    padding: 0;
    -moz-column-count: 4;
    -moz-column-gap: 10px;
    -moz-column-width: 170px;
    -ms-column-count: 4;
    -ms-column-gap: 10px;
    -ms-column-width: 170px;
    -o-column-count: 4;
    -o-column-gap: 10px;
    -o-column-width: 170px;
    -webkit-column-count: 4;
    -webkit-column-gap: 10px;
    -webkit-column-width: 170px;
    column-count: 4;
    column-gap: 10px;
    column-width: 170px;
}

.apidocs .no-columns .index-list {
    -moz-column-count: 1;
    -ms-column-count: 1;
    -o-column-count: 1;
    -webkit-column-count: 1;
    column-count: 1;
}

.apidocs .index-item { white-space: nowrap; }

.apidocs .index-item .flag {
    background: none;
    border: none;
    color: #afafaf;
    display: inline;
    margin: 0 0 0 0.2em;
    padding: 0;
}

/* -- Generic API item styles ----------------------------------------------- */
.apidocs .args {
    display: inline;
    margin: 0 0.5em;
}

.apidocs .flag.chainable { background: #46ca3b; }
.apidocs .flag.protected { background: #9b86fc; }
.apidocs .flag.private { background: #fd6b1b; }
.apidocs .flag.async { background: #356de4; }
.apidocs .flag.required { background: #e60923; }

.apidocs .item {
    border-bottom: 1px solid #efefef;
    margin: 1.5em 0 2em;
    padding-bottom: 2em;
}

.apidocs .item h4,
.apidocs .item h5,
.apidocs .item h6 {
    color: #333;
    font-family: inherit;
    font-size: 100%;
}

.apidocs .item .description p,
.apidocs .item pre.code {
    margin: 1em 0 0;
}

.apidocs .item .meta {
    background: none;
    border: none;
    padding: 0;
}

.apidocs .item .name {
    display: inline;
    font-size: 14px;
}

.apidocs .item .type,
.apidocs .item .type a,
.apidocs .returns-inline {
    color: #555;
}

.apidocs .item .type,
.apidocs .returns-inline {
    font-size: 11px;
    margin: 0 0 0 0;
}

.apidocs .item .type a { border-bottom: 1px dotted #afafaf; }
.apidocs .item .type a:hover { border: none; }

/* -- Item Parameter List --------------------------------------------------- */
.apidocs .params-list {
    list-style: square;
    margin: 1em 0 0 2em;
    padding: 0;
}

.apidocs .param { margin-bottom: 1em; }

.apidocs .param .type,
.apidocs .param .type a {
    color: #666;
}

.apidocs .param .type {
    margin: 0 0 0 0.5em;
    *margin-left: 0.5em;
}

.apidocs .param-name { font-weight: bold; }

/* -- Item "Emits" block ---------------------------------------------------- */
.apidocs .item .emits {
    background: #f9f9f9;
    border-color: #eaeaea;
}

/* -- Item "Returns" block -------------------------------------------------- */
.apidocs .item .returns .type,
.apidocs .item .returns .type a {
    font-size: 100%;
    margin: 0;
}

/* -- Class Constructor block ----------------------------------------------- */
.apidocs .constructor .item {
    border: none;
    padding-bottom: 0;
}

/* -- File Source View ------------------------------------------------------ */
.apidocs .file pre.code,
#doc .apidocs .file pre.prettyprint {
    background: inherit;
    border: none;
    overflow: visible;
    padding: 0;
}

.apidocs .L0,
.apidocs .L1,
.apidocs .L2,
.apidocs .L3,
.apidocs .L4,
.apidocs .L5,
.apidocs .L6,
.apidocs .L7,
.apidocs .L8,
.apidocs .L9 {
    background: inherit;
}

/* -- Submodule List -------------------------------------------------------- */
.apidocs .module-submodule-description {
    font-size: 12px;
    margin: 0.3em 0 1em;
}

.apidocs .module-submodule-description p:first-child { margin-top: 0; }

/* -- Sidebar TabView ------------------------------------------------------- */
#api-tabview { margin-top: 0.6em; }

#api-tabview-filter,
#api-tabview-panel {
    border: 1px solid #dfdfdf;
}

#api-tabview-filter {
    border-bottom: none;
    border-top: none;
    padding: 0.6em 10px 0 10px;
}

#api-tabview-panel { border-top: none; }
#api-filter { width: 97%; }

/* -- Content TabView ------------------------------------------------------- */
#classdocs .yui3-tabview-panel { border: none; }

/* -- Source File Contents -------------------------------------------------- */
.prettyprint li.L0,
.prettyprint li.L1,
.prettyprint li.L2,
.prettyprint li.L3,
.prettyprint li.L5,
.prettyprint li.L6,
.prettyprint li.L7,
.prettyprint li.L8 {
    list-style: decimal;
}

/* -- API options ----------------------------------------------------------- */
#api-options {
    font-size: 11px;
    margin-top: 2.2em;
    position: absolute;
    right: 1.5em;
}

/*#api-options label { margin-right: 0.6em; }*/

/* -- API list -------------------------------------------------------------- */
#api-list {
    margin-top: 1.5em;
    *zoom: 1;
}

.apis {
    font-size: 12px;
    line-height: 1.4;
    list-style: none;
    margin: 0;
    padding: 0.5em 0 0.5em 0.4em;
}

.apis a {
    border: 1px solid transparent;
    display: block;
    margin: 0 0 0 -4px;
    padding: 1px 4px 0;
    text-decoration: none;
    _border: none;
    _display: inline;
}

.apis a:hover,
.apis a:focus {
    background: #E8EDFC;
    background: -moz-linear-gradient(top, #e8edfc 0%, #becef7 100%);
    background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#E8EDFC), color-stop(100%,#BECEF7));
    border-color: #AAC0FA;
    border-radius: 3px;
    color: #333;
    outline: none;
}

.api-list-item a:hover,
.api-list-item a:focus {
    font-weight: bold;
    text-shadow: 1px 1px 1px #fff;
}

.apis .message { color: #888; }
.apis .result a { padding: 3px 5px 2px; }

.apis .result .type {
    right: 4px;
    top: 7px;
}

.api-list-item .yui3-highlight {
    font-weight: bold;
}



================================================
FILE: docs/assets/index.html
================================================


    
        Redirector
        
    
    
        Click here to redirect
    



================================================
FILE: docs/assets/js/api-filter.js
================================================
YUI.add('api-filter', function (Y) {

Y.APIFilter = Y.Base.create('apiFilter', Y.Base, [Y.AutoCompleteBase], {
    // -- Initializer ----------------------------------------------------------
    initializer: function () {
        this._bindUIACBase();
        this._syncUIACBase();
    },
    getDisplayName: function(name) {

        Y.each(Y.YUIDoc.meta.allModules, function(i) {
            if (i.name === name && i.displayName) {
                name = i.displayName;
            }
        });

        return name;
    }

}, {
    // -- Attributes -----------------------------------------------------------
    ATTRS: {
        resultHighlighter: {
            value: 'phraseMatch'
        },

        // May be set to "classes" or "modules".
        queryType: {
            value: 'classes'
        },

        source: {
            valueFn: function() {
                var self = this;
                return function(q) {
                    var data = Y.YUIDoc.meta[self.get('queryType')],
                        out = [];
                    Y.each(data, function(v) {
                        if (v.toLowerCase().indexOf(q.toLowerCase()) > -1) {
                            out.push(v);
                        }
                    });
                    return out;
                };
            }
        }
    }
});

}, '3.4.0', {requires: [
    'autocomplete-base', 'autocomplete-highlighters', 'autocomplete-sources'
]});


================================================
FILE: docs/assets/js/api-list.js
================================================
YUI.add('api-list', function (Y) {

var Lang   = Y.Lang,
    YArray = Y.Array,

    APIList = Y.namespace('APIList'),

    classesNode    = Y.one('#api-classes'),
    inputNode      = Y.one('#api-filter'),
    modulesNode    = Y.one('#api-modules'),
    tabviewNode    = Y.one('#api-tabview'),

    tabs = APIList.tabs = {},

    filter = APIList.filter = new Y.APIFilter({
        inputNode : inputNode,
        maxResults: 1000,

        on: {
            results: onFilterResults
        }
    }),

    search = APIList.search = new Y.APISearch({
        inputNode : inputNode,
        maxResults: 100,

        on: {
            clear  : onSearchClear,
            results: onSearchResults
        }
    }),

    tabview = APIList.tabview = new Y.TabView({
        srcNode  : tabviewNode,
        panelNode: '#api-tabview-panel',
        render   : true,

        on: {
            selectionChange: onTabSelectionChange
        }
    }),

    focusManager = APIList.focusManager = tabviewNode.plug(Y.Plugin.NodeFocusManager, {
        circular   : true,
        descendants: '#api-filter, .yui3-tab-panel-selected .api-list-item a, .yui3-tab-panel-selected .result a',
        keys       : {next: 'down:40', previous: 'down:38'}
    }).focusManager,

    LIST_ITEM_TEMPLATE =
        '
  • ' + '{displayName}' + '
  • '; // -- Init --------------------------------------------------------------------- // Duckpunch FocusManager's key event handling to prevent it from handling key // events when a modifier is pressed. Y.before(function (e, activeDescendant) { if (e.altKey || e.ctrlKey || e.metaKey || e.shiftKey) { return new Y.Do.Prevent(); } }, focusManager, '_focusPrevious', focusManager); Y.before(function (e, activeDescendant) { if (e.altKey || e.ctrlKey || e.metaKey || e.shiftKey) { return new Y.Do.Prevent(); } }, focusManager, '_focusNext', focusManager); // Create a mapping of tabs in the tabview so we can refer to them easily later. tabview.each(function (tab, index) { var name = tab.get('label').toLowerCase(); tabs[name] = { index: index, name : name, tab : tab }; }); // Switch tabs on Ctrl/Cmd-Left/Right arrows. tabviewNode.on('key', onTabSwitchKey, 'down:37,39'); // Focus the filter input when the `/` key is pressed. Y.one(Y.config.doc).on('key', onSearchKey, 'down:83'); // Keep the Focus Manager up to date. inputNode.on('focus', function () { focusManager.set('activeDescendant', inputNode); }); // Update all tabview links to resolved URLs. tabview.get('panelNode').all('a').each(function (link) { link.setAttribute('href', link.get('href')); }); // -- Private Functions -------------------------------------------------------- function getFilterResultNode() { return filter.get('queryType') === 'classes' ? classesNode : modulesNode; } // -- Event Handlers ----------------------------------------------------------- function onFilterResults(e) { var frag = Y.one(Y.config.doc.createDocumentFragment()), resultNode = getFilterResultNode(), typePlural = filter.get('queryType'), typeSingular = typePlural === 'classes' ? 'class' : 'module'; if (e.results.length) { YArray.each(e.results, function (result) { frag.append(Lang.sub(LIST_ITEM_TEMPLATE, { rootPath : APIList.rootPath, displayName : filter.getDisplayName(result.highlighted), name : result.text, typePlural : typePlural, typeSingular: typeSingular })); }); } else { frag.append( '
  • ' + 'No ' + typePlural + ' found.' + '
  • ' ); } resultNode.empty(true); resultNode.append(frag); focusManager.refresh(); } function onSearchClear(e) { focusManager.refresh(); } function onSearchKey(e) { var target = e.target; if (target.test('input,select,textarea') || target.get('isContentEditable')) { return; } e.preventDefault(); inputNode.focus(); focusManager.refresh(); } function onSearchResults(e) { var frag = Y.one(Y.config.doc.createDocumentFragment()); if (e.results.length) { YArray.each(e.results, function (result) { frag.append(result.display); }); } else { frag.append( '
  • ' + 'No results found. Maybe you\'ll have better luck with a ' + 'different query?' + '
  • ' ); } focusManager.refresh(); } function onTabSelectionChange(e) { var tab = e.newVal, name = tab.get('label').toLowerCase(); tabs.selected = { index: tab.get('index'), name : name, tab : tab }; switch (name) { case 'classes': // fallthru case 'modules': filter.setAttrs({ minQueryLength: 0, queryType : name }); search.set('minQueryLength', -1); // Only send a request if this isn't the initially-selected tab. if (e.prevVal) { filter.sendRequest(filter.get('value')); } break; case 'everything': filter.set('minQueryLength', -1); search.set('minQueryLength', 1); if (search.get('value')) { search.sendRequest(search.get('value')); } else { inputNode.focus(); } break; default: // WTF? We shouldn't be here! filter.set('minQueryLength', -1); search.set('minQueryLength', -1); } if (focusManager) { setTimeout(function () { focusManager.refresh(); }, 1); } } function onTabSwitchKey(e) { var currentTabIndex = tabs.selected.index; if (!(e.ctrlKey || e.metaKey)) { return; } e.preventDefault(); switch (e.keyCode) { case 37: // left arrow if (currentTabIndex > 0) { tabview.selectChild(currentTabIndex - 1); inputNode.focus(); } break; case 39: // right arrow if (currentTabIndex < (Y.Object.size(tabs) - 2)) { tabview.selectChild(currentTabIndex + 1); inputNode.focus(); } break; } } }, '3.4.0', {requires: [ 'api-filter', 'api-search', 'event-key', 'node-focusmanager', 'tabview' ]}); ================================================ FILE: docs/assets/js/api-search.js ================================================ YUI.add('api-search', function (Y) { var Lang = Y.Lang, Node = Y.Node, YArray = Y.Array; Y.APISearch = Y.Base.create('apiSearch', Y.Base, [Y.AutoCompleteBase], { // -- Public Properties ---------------------------------------------------- RESULT_TEMPLATE: '
  • ' + '' + '

    {name}

    ' + '{resultType}' + '
    {description}
    ' + '{class}' + '
    ' + '
  • ', // -- Initializer ---------------------------------------------------------- initializer: function () { this._bindUIACBase(); this._syncUIACBase(); }, // -- Protected Methods ---------------------------------------------------- _apiResultFilter: function (query, results) { // Filter components out of the results. return YArray.filter(results, function (result) { return result.raw.resultType === 'component' ? false : result; }); }, _apiResultFormatter: function (query, results) { return YArray.map(results, function (result) { var raw = Y.merge(result.raw), // create a copy desc = raw.description || ''; // Convert description to text and truncate it if necessary. desc = Node.create('
    ' + desc + '
    ').get('text'); if (desc.length > 65) { desc = Y.Escape.html(desc.substr(0, 65)) + ' …'; } else { desc = Y.Escape.html(desc); } raw['class'] || (raw['class'] = ''); raw.description = desc; // Use the highlighted result name. raw.name = result.highlighted; return Lang.sub(this.RESULT_TEMPLATE, raw); }, this); }, _apiTextLocator: function (result) { return result.displayName || result.name; } }, { // -- Attributes ----------------------------------------------------------- ATTRS: { resultFormatter: { valueFn: function () { return this._apiResultFormatter; } }, resultFilters: { valueFn: function () { return this._apiResultFilter; } }, resultHighlighter: { value: 'phraseMatch' }, resultListLocator: { value: 'data.results' }, resultTextLocator: { valueFn: function () { return this._apiTextLocator; } }, source: { value: '/api/v1/search?q={query}&count={maxResults}' } } }); }, '3.4.0', {requires: [ 'autocomplete-base', 'autocomplete-highlighters', 'autocomplete-sources', 'escape' ]}); ================================================ FILE: docs/assets/js/apidocs.js ================================================ YUI().use( 'yuidoc-meta', 'api-list', 'history-hash', 'node-screen', 'node-style', 'pjax', function (Y) { var win = Y.config.win, localStorage = win.localStorage, bdNode = Y.one('#bd'), pjax, defaultRoute, classTabView, selectedTab; // Kill pjax functionality unless serving over HTTP. if (!Y.getLocation().protocol.match(/^https?\:/)) { Y.Router.html5 = false; } // Create the default route with middleware which enables syntax highlighting // on the loaded content. defaultRoute = Y.Pjax.defaultRoute.concat(function (req, res, next) { prettyPrint(); bdNode.removeClass('loading'); next(); }); pjax = new Y.Pjax({ container : '#docs-main', contentSelector: '#docs-main > .content', linkSelector : '#bd a', titleSelector : '#xhr-title', navigateOnHash: true, root : '/', routes : [ // -- / ---------------------------------------------------------------- { path : '/(index.html)?', callbacks: defaultRoute }, // -- /classes/* ------------------------------------------------------- { path : '/classes/:class.html*', callbacks: [defaultRoute, 'handleClasses'] }, // -- /files/* --------------------------------------------------------- { path : '/files/*file', callbacks: [defaultRoute, 'handleFiles'] }, // -- /modules/* ------------------------------------------------------- { path : '/modules/:module.html*', callbacks: defaultRoute } ] }); // -- Utility Functions -------------------------------------------------------- pjax.checkVisibility = function (tab) { tab || (tab = selectedTab); if (!tab) { return; } var panelNode = tab.get('panelNode'), visibleItems; // If no items are visible in the tab panel due to the current visibility // settings, display a message to that effect. visibleItems = panelNode.all('.item,.index-item').some(function (itemNode) { if (itemNode.getComputedStyle('display') !== 'none') { return true; } }); panelNode.all('.no-visible-items').remove(); if (!visibleItems) { if (Y.one('#index .index-item')) { panelNode.append( '
    ' + '

    ' + 'Some items are not shown due to the current visibility ' + 'settings. Use the checkboxes at the upper right of this ' + 'page to change the visibility settings.' + '

    ' + '
    ' ); } else { panelNode.append( '
    ' + '

    ' + 'This class doesn\'t provide any methods, properties, ' + 'attributes, or events.' + '

    ' + '
    ' ); } } // Hide index sections without any visible items. Y.all('.index-section').each(function (section) { var items = 0, visibleItems = 0; section.all('.index-item').each(function (itemNode) { items += 1; if (itemNode.getComputedStyle('display') !== 'none') { visibleItems += 1; } }); section.toggleClass('hidden', !visibleItems); section.toggleClass('no-columns', visibleItems < 4); }); }; pjax.initClassTabView = function () { if (!Y.all('#classdocs .api-class-tab').size()) { return; } if (classTabView) { classTabView.destroy(); selectedTab = null; } classTabView = new Y.TabView({ srcNode: '#classdocs', on: { selectionChange: pjax.onTabSelectionChange } }); pjax.updateTabState(); classTabView.render(); }; pjax.initLineNumbers = function () { var hash = win.location.hash.substring(1), container = pjax.get('container'), hasLines, node; // Add ids for each line number in the file source view. container.all('.linenums>li').each(function (lineNode, index) { lineNode.set('id', 'l' + (index + 1)); lineNode.addClass('file-line'); hasLines = true; }); // Scroll to the desired line. if (hasLines && /^l\d+$/.test(hash)) { if ((node = container.getById(hash))) { win.scroll(0, node.getY()); } } }; pjax.initRoot = function () { var terminators = /^(?:classes|files|modules)$/, parts = pjax._getPathRoot().split('/'), root = [], i, len, part; for (i = 0, len = parts.length; i < len; i += 1) { part = parts[i]; if (part.match(terminators)) { // Makes sure the path will end with a "/". root.push(''); break; } root.push(part); } pjax.set('root', root.join('/')); }; pjax.updateTabState = function (src) { var hash = win.location.hash.substring(1), defaultTab, node, tab, tabPanel; function scrollToNode() { if (node.hasClass('protected')) { Y.one('#api-show-protected').set('checked', true); pjax.updateVisibility(); } if (node.hasClass('private')) { Y.one('#api-show-private').set('checked', true); pjax.updateVisibility(); } setTimeout(function () { // For some reason, unless we re-get the node instance here, // getY() always returns 0. var node = Y.one('#classdocs').getById(hash); win.scrollTo(0, node.getY() - 70); }, 1); } if (!classTabView) { return; } if (src === 'hashchange' && !hash) { defaultTab = 'index'; } else { if (localStorage) { defaultTab = localStorage.getItem('tab_' + pjax.getPath()) || 'index'; } else { defaultTab = 'index'; } } if (hash && (node = Y.one('#classdocs').getById(hash))) { if ((tabPanel = node.ancestor('.api-class-tabpanel', true))) { if ((tab = Y.one('#classdocs .api-class-tab.' + tabPanel.get('id')))) { if (classTabView.get('rendered')) { Y.Widget.getByNode(tab).set('selected', 1); } else { tab.addClass('yui3-tab-selected'); } } } // Scroll to the desired element if this is a hash URL. if (node) { if (classTabView.get('rendered')) { scrollToNode(); } else { classTabView.once('renderedChange', scrollToNode); } } } else { tab = Y.one('#classdocs .api-class-tab.' + defaultTab); // When the `defaultTab` node isn't found, `localStorage` is stale. if (!tab && defaultTab !== 'index') { tab = Y.one('#classdocs .api-class-tab.index'); } if (classTabView.get('rendered')) { Y.Widget.getByNode(tab).set('selected', 1); } else { tab.addClass('yui3-tab-selected'); } } }; pjax.updateVisibility = function () { var container = pjax.get('container'); container.toggleClass('hide-inherited', !Y.one('#api-show-inherited').get('checked')); container.toggleClass('show-deprecated', Y.one('#api-show-deprecated').get('checked')); container.toggleClass('show-protected', Y.one('#api-show-protected').get('checked')); container.toggleClass('show-private', Y.one('#api-show-private').get('checked')); pjax.checkVisibility(); }; // -- Route Handlers ----------------------------------------------------------- pjax.handleClasses = function (req, res, next) { var status = res.ioResponse.status; // Handles success and local filesystem XHRs. if (res.ioResponse.readyState === 4 && (!status || (status >= 200 && status < 300))) { pjax.initClassTabView(); } next(); }; pjax.handleFiles = function (req, res, next) { var status = res.ioResponse.status; // Handles success and local filesystem XHRs. if (res.ioResponse.readyState === 4 && (!status || (status >= 200 && status < 300))) { pjax.initLineNumbers(); } next(); }; // -- Event Handlers ----------------------------------------------------------- pjax.onNavigate = function (e) { var hash = e.hash, originTarget = e.originEvent && e.originEvent.target, tab; if (hash) { tab = originTarget && originTarget.ancestor('.yui3-tab', true); if (hash === win.location.hash) { pjax.updateTabState('hashchange'); } else if (!tab) { win.location.hash = hash; } e.preventDefault(); return; } // Only scroll to the top of the page when the URL doesn't have a hash. this.set('scrollToTop', !e.url.match(/#.+$/)); bdNode.addClass('loading'); }; pjax.onOptionClick = function (e) { pjax.updateVisibility(); }; pjax.onTabSelectionChange = function (e) { var tab = e.newVal, tabId = tab.get('contentBox').getAttribute('href').substring(1); selectedTab = tab; // If switching from a previous tab (i.e., this is not the default tab), // replace the history entry with a hash URL that will cause this tab to // be selected if the user navigates away and then returns using the back // or forward buttons. if (e.prevVal && localStorage) { localStorage.setItem('tab_' + pjax.getPath(), tabId); } pjax.checkVisibility(tab); }; // -- Init --------------------------------------------------------------------- pjax.on('navigate', pjax.onNavigate); pjax.initRoot(); pjax.upgrade(); pjax.initClassTabView(); pjax.initLineNumbers(); pjax.updateVisibility(); Y.APIList.rootPath = pjax.get('root'); Y.one('#api-options').delegate('click', pjax.onOptionClick, 'input'); Y.on('hashchange', function (e) { pjax.updateTabState('hashchange'); }, win); }); ================================================ FILE: docs/assets/js/yui-prettify.js ================================================ YUI().use('node', function(Y) { var code = Y.all('.prettyprint.linenums'); if (code.size()) { code.each(function(c) { var lis = c.all('ol li'), l = 1; lis.each(function(n) { n.prepend(''); l++; }); }); var h = location.hash; location.hash = ''; h = h.replace('LINE_', 'LINENUM_'); location.hash = h; } }); ================================================ FILE: docs/assets/vendor/prettify/CHANGES.html ================================================ Change Log README

    Known Issues

    • Perl formatting is really crappy. Partly because the author is lazy and partly because Perl is hard to parse.
    • On some browsers, <code> elements with newlines in the text which use CSS to specify white-space:pre will have the newlines improperly stripped if the element is not attached to the document at the time the stripping is done. Also, on IE 6, all newlines will be stripped from <code> elements because of the way IE6 produces innerHTML. Workaround: use <pre> for code with newlines.

    Change Log

    29 March 2007

    • Added tests for PHP support to address issue 3.
    • Fixed bug: prettyPrintOne was not halting. This was not reachable through the normal entry point.
    • Fixed bug: recursing into a script block or PHP tag that was not properly closed would not silently drop the content. (test)
    • Fixed bug: was eating tabs (test)
    • Fixed entity handling so that the caveat

      Caveats: please properly escape less-thans. x&lt;y instead of x<y, and use " instead of &quot; for string delimiters.

      is no longer applicable.
    • Added noisefree's C# patch
    • Added a distribution that has comments and whitespace removed to reduce download size from 45.5kB to 12.8kB.

    4 Jul 2008

    • Added language specific formatters that are triggered by the presence of a lang-<language-file-extension>
    • Fixed bug: python handling of '''string'''
    • Fixed bug: / in regex [charsets] should not end regex

    5 Jul 2008

    • Defined language extensions for Lisp and Lua

    14 Jul 2008

    • Language handlers for F#, OCAML, SQL
    • Support for nocode spans to allow embedding of line numbers and code annotations which should not be styled or otherwise affect the tokenization of prettified code. See the issue 22 testcase.

    6 Jan 2009

    • Language handlers for Visual Basic, Haskell, CSS, and WikiText
    • Added .mxml extension to the markup style handler for Flex MXML files. See issue 37.
    • Added .m extension to the C style handler so that Objective C source files properly highlight. See issue 58.
    • Changed HTML lexer to use the same embedded source mechanism as the wiki language handler, and changed to use the registered CSS handler for STYLE element content.

    21 May 2009

    • Rewrote to improve performance on large files. See benchmarks.
    • Fixed bugs with highlighting of Haskell line comments, Lisp number literals, Lua strings, C preprocessor directives, newlines in Wiki code on Windows, and newlines in IE6.

    14 August 2009

    • Fixed prettifying of <code> blocks with embedded newlines.

    3 October 2009

    • Fixed prettifying of XML/HTML tags that contain uppercase letters.

    19 July 2010

    • Added support for line numbers. Bug 22
    • Added YAML support. Bug 123
    • Added VHDL support courtesy Le Poussin.
    • IE performance improvements. Bug 102 courtesy jacobly.
    • A variety of markup formatting fixes courtesy smain and thezbyg.
    • Fixed copy and paste in IE[678].
    • Changed output to use &#160; instead of &nbsp; so that the output works when embedded in XML. Bug 108.
    ================================================ FILE: docs/assets/vendor/prettify/COPYING ================================================ Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. ================================================ FILE: docs/assets/vendor/prettify/README.html ================================================ Javascript code prettifier Languages : CH

    Javascript code prettifier

    Setup

    1. Download a distribution
    2. Include the script and stylesheets in your document (you will need to make sure the css and js file are on your server, and adjust the paths in the script and link tag)
      <link href="prettify.css" type="text/css" rel="stylesheet" />
      <script type="text/javascript" src="prettify.js"></script>
    3. Add onload="prettyPrint()" to your document's body tag.
    4. Modify the stylesheet to get the coloring you prefer

    Usage

    Put code snippets in <pre class="prettyprint">...</pre> or <code class="prettyprint">...</code> and it will automatically be pretty printed.
    The original Prettier
    class Voila {
    public:
      // Voila
      static const string VOILA = "Voila";
    
      // will not interfere with embedded tags.
    }
    class Voila {
    public:
      // Voila
      static const string VOILA = "Voila";
    
      // will not interfere with embedded tags.
    }

    FAQ

    Which languages does it work for?

    The comments in prettify.js are authoritative but the lexer should work on a number of languages including C and friends, Java, Python, Bash, SQL, HTML, XML, CSS, Javascript, and Makefiles. It works passably on Ruby, PHP, VB, and Awk and a decent subset of Perl and Ruby, but, because of commenting conventions, doesn't work on Smalltalk, or CAML-like languages.

    LISPy languages are supported via an extension: lang-lisp.js.

    And similarly for CSS, Haskell, Lua, OCAML, SML, F#, Visual Basic, SQL, Protocol Buffers, and WikiText..

    If you'd like to add an extension for your favorite language, please look at src/lang-lisp.js and file an issue including your language extension, and a testcase.

    How do I specify which language my code is in?

    You don't need to specify the language since prettyprint() will guess. You can specify a language by specifying the language extension along with the prettyprint class like so:

    <pre class="prettyprint lang-html">
      The lang-* class specifies the language file extensions.
      File extensions supported by default include
        "bsh", "c", "cc", "cpp", "cs", "csh", "cyc", "cv", "htm", "html",
        "java", "js", "m", "mxml", "perl", "pl", "pm", "py", "rb", "sh",
        "xhtml", "xml", "xsl".
    </pre>

    It doesn't work on <obfuscated code sample>?

    Yes. Prettifying obfuscated code is like putting lipstick on a pig — i.e. outside the scope of this tool.

    Which browsers does it work with?

    It's been tested with IE 6, Firefox 1.5 & 2, and Safari 2.0.4. Look at the test page to see if it works in your browser.

    What's changed?

    See the change log

    Why doesn't Prettyprinting of strings work on WordPress?

    Apparently wordpress does "smart quoting" which changes close quotes. This causes end quotes to not match up with open quotes.

    This breaks prettifying as well as copying and pasting of code samples. See WordPress's help center for info on how to stop smart quoting of code snippets.

    How do I put line numbers in my code?

    You can use the linenums class to turn on line numbering. If your code doesn't start at line number 1, you can add a colon and a line number to the end of that class as in linenums:52.

    For example

    <pre class="prettyprint linenums:4"
    >// This is line 4.
    foo();
    bar();
    baz();
    boo();
    far();
    faz();
    <pre>
    produces
    // This is line 4.
    foo();
    bar();
    baz();
    boo();
    far();
    faz();
    

    How do I prevent a portion of markup from being marked as code?

    You can use the nocode class to identify a span of markup that is not code.

    <pre class=prettyprint>
    int x = foo();  /* This is a comment  <span class="nocode">This is not code</span>
      Continuation of comment */
    int y = bar();
    </pre>
    produces
    int x = foo();  /* This is a comment  This is not code
      Continuation of comment */
    int y = bar();
    

    For a more complete example see the issue22 testcase.

    I get an error message "a is not a function" or "opt_whenDone is not a function"

    If you are calling prettyPrint via an event handler, wrap it in a function. Instead of doing

    addEventListener('load', prettyPrint, false);
    wrap it in a closure like
    addEventListener('load', function (event) { prettyPrint() }, false);
    so that the browser does not pass an event object to prettyPrint which will confuse it.


    ================================================ FILE: docs/assets/vendor/prettify/prettify-min.css ================================================ .pln{color:#000}@media screen{.str{color:#080}.kwd{color:#008}.com{color:#800}.typ{color:#606}.lit{color:#066}.pun,.opn,.clo{color:#660}.tag{color:#008}.atn{color:#606}.atv{color:#080}.dec,.var{color:#606}.fun{color:red}}@media print,projection{.str{color:#060}.kwd{color:#006;font-weight:bold}.com{color:#600;font-style:italic}.typ{color:#404;font-weight:bold}.lit{color:#044}.pun,.opn,.clo{color:#440}.tag{color:#006;font-weight:bold}.atn{color:#404}.atv{color:#060}}pre.prettyprint{padding:2px;border:1px solid #888}ol.linenums{margin-top:0;margin-bottom:0}li.L0,li.L1,li.L2,li.L3,li.L5,li.L6,li.L7,li.L8{list-style-type:none}li.L1,li.L3,li.L5,li.L7,li.L9{background:#eee} ================================================ FILE: docs/assets/vendor/prettify/prettify-min.js ================================================ window.PR_SHOULD_USE_CONTINUATION=true;var prettyPrintOne;var prettyPrint;(function(){var O=window;var j=["break,continue,do,else,for,if,return,while"];var v=[j,"auto,case,char,const,default,double,enum,extern,float,goto,int,long,register,short,signed,sizeof,static,struct,switch,typedef,union,unsigned,void,volatile"];var q=[v,"catch,class,delete,false,import,new,operator,private,protected,public,this,throw,true,try,typeof"];var m=[q,"alignof,align_union,asm,axiom,bool,concept,concept_map,const_cast,constexpr,decltype,dynamic_cast,explicit,export,friend,inline,late_check,mutable,namespace,nullptr,reinterpret_cast,static_assert,static_cast,template,typeid,typename,using,virtual,where"];var y=[q,"abstract,boolean,byte,extends,final,finally,implements,import,instanceof,null,native,package,strictfp,super,synchronized,throws,transient"];var T=[y,"as,base,by,checked,decimal,delegate,descending,dynamic,event,fixed,foreach,from,group,implicit,in,interface,internal,into,is,let,lock,object,out,override,orderby,params,partial,readonly,ref,sbyte,sealed,stackalloc,string,select,uint,ulong,unchecked,unsafe,ushort,var,virtual,where"];var s="all,and,by,catch,class,else,extends,false,finally,for,if,in,is,isnt,loop,new,no,not,null,of,off,on,or,return,super,then,throw,true,try,unless,until,when,while,yes";var x=[q,"debugger,eval,export,function,get,null,set,undefined,var,with,Infinity,NaN"];var t="caller,delete,die,do,dump,elsif,eval,exit,foreach,for,goto,if,import,last,local,my,next,no,our,print,package,redo,require,sub,undef,unless,until,use,wantarray,while,BEGIN,END";var J=[j,"and,as,assert,class,def,del,elif,except,exec,finally,from,global,import,in,is,lambda,nonlocal,not,or,pass,print,raise,try,with,yield,False,True,None"];var g=[j,"alias,and,begin,case,class,def,defined,elsif,end,ensure,false,in,module,next,nil,not,or,redo,rescue,retry,self,super,then,true,undef,unless,until,when,yield,BEGIN,END"];var I=[j,"case,done,elif,esac,eval,fi,function,in,local,set,then,until"];var B=[m,T,x,t+J,g,I];var f=/^(DIR|FILE|vector|(de|priority_)?queue|list|stack|(const_)?iterator|(multi)?(set|map)|bitset|u?(int|float)\d*)\b/;var D="str";var A="kwd";var k="com";var Q="typ";var H="lit";var M="pun";var G="pln";var n="tag";var F="dec";var K="src";var R="atn";var o="atv";var P="nocode";var N="(?:^^\\.?|[+-]|[!=]=?=?|\\#|%=?|&&?=?|\\(|\\*=?|[+\\-]=|->|\\/=?|::?|<>?>?=?|,|;|\\?|@|\\[|~|{|\\^\\^?=?|\\|\\|?=?|break|case|continue|delete|do|else|finally|instanceof|return|throw|try|typeof)\\s*";function l(ab){var af=0;var U=false;var ae=false;for(var X=0,W=ab.length;X122)){if(!(am<65||ai>90)){ah.push([Math.max(65,ai)|32,Math.min(am,90)|32])}if(!(am<97||ai>122)){ah.push([Math.max(97,ai)&~32,Math.min(am,122)&~32])}}}}ah.sort(function(aw,av){return(aw[0]-av[0])||(av[1]-aw[1])});var ak=[];var aq=[];for(var at=0;atau[0]){if(au[1]+1>au[0]){ao.push("-")}ao.push(V(au[1]))}}ao.push("]");return ao.join("")}function Y(an){var al=an.source.match(new RegExp("(?:\\[(?:[^\\x5C\\x5D]|\\\\[\\s\\S])*\\]|\\\\u[A-Fa-f0-9]{4}|\\\\x[A-Fa-f0-9]{2}|\\\\[0-9]+|\\\\[^ux0-9]|\\(\\?[:!=]|[\\(\\)\\^]|[^\\x5B\\x5C\\(\\)\\^]+)","g"));var aj=al.length;var ap=[];for(var am=0,ao=0;am=2&&ak==="["){al[am]=Z(ai)}else{if(ak!=="\\"){al[am]=ai.replace(/[a-zA-Z]/g,function(aq){var ar=aq.charCodeAt(0);return"["+String.fromCharCode(ar&~32,ar|32)+"]"})}}}}return al.join("")}var ac=[];for(var X=0,W=ab.length;X=0;){U[ae.charAt(ag)]=aa}}var ah=aa[1];var ac=""+ah;if(!ai.hasOwnProperty(ac)){aj.push(ah);ai[ac]=null}}aj.push(/[\0-\uffff]/);X=l(aj)})();var Z=V.length;var Y=function(aj){var ab=aj.sourceCode,aa=aj.basePos;var af=[aa,G];var ah=0;var ap=ab.match(X)||[];var al={};for(var ag=0,at=ap.length;ag=5&&"lang-"===ar.substring(0,5);if(ao&&!(ak&&typeof ak[1]==="string")){ao=false;ar=K}if(!ao){al[ai]=ar}}var ad=ah;ah+=ai.length;if(!ao){af.push(aa+ad,ar)}else{var an=ak[1];var am=ai.indexOf(an);var ae=am+an.length;if(ak[2]){ae=ai.length-ak[2].length;am=ae-an.length}var au=ar.substring(5);C(aa+ad,ai.substring(0,am),Y,af);C(aa+ad+am,an,r(au,an),af);C(aa+ad+ae,ai.substring(ae),Y,af)}}aj.decorations=af};return Y}function i(V){var Y=[],U=[];if(V.tripleQuotedStrings){Y.push([D,/^(?:\'\'\'(?:[^\'\\]|\\[\s\S]|\'{1,2}(?=[^\']))*(?:\'\'\'|$)|\"\"\"(?:[^\"\\]|\\[\s\S]|\"{1,2}(?=[^\"]))*(?:\"\"\"|$)|\'(?:[^\\\']|\\[\s\S])*(?:\'|$)|\"(?:[^\\\"]|\\[\s\S])*(?:\"|$))/,null,"'\""])}else{if(V.multiLineStrings){Y.push([D,/^(?:\'(?:[^\\\']|\\[\s\S])*(?:\'|$)|\"(?:[^\\\"]|\\[\s\S])*(?:\"|$)|\`(?:[^\\\`]|\\[\s\S])*(?:\`|$))/,null,"'\"`"])}else{Y.push([D,/^(?:\'(?:[^\\\'\r\n]|\\.)*(?:\'|$)|\"(?:[^\\\"\r\n]|\\.)*(?:\"|$))/,null,"\"'"])}}if(V.verbatimStrings){U.push([D,/^@\"(?:[^\"]|\"\")*(?:\"|$)/,null])}var ab=V.hashComments;if(ab){if(V.cStyleComments){if(ab>1){Y.push([k,/^#(?:##(?:[^#]|#(?!##))*(?:###|$)|.*)/,null,"#"])}else{Y.push([k,/^#(?:(?:define|e(?:l|nd)if|else|error|ifn?def|include|line|pragma|undef|warning)\b|[^\r\n]*)/,null,"#"])}U.push([D,/^<(?:(?:(?:\.\.\/)*|\/?)(?:[\w-]+(?:\/[\w-]+)+)?[\w-]+\.h(?:h|pp|\+\+)?|[a-z]\w*)>/,null])}else{Y.push([k,/^#[^\r\n]*/,null,"#"])}}if(V.cStyleComments){U.push([k,/^\/\/[^\r\n]*/,null]);U.push([k,/^\/\*[\s\S]*?(?:\*\/|$)/,null])}if(V.regexLiterals){var aa=("/(?=[^/*])(?:[^/\\x5B\\x5C]|\\x5C[\\s\\S]|\\x5B(?:[^\\x5C\\x5D]|\\x5C[\\s\\S])*(?:\\x5D|$))+/");U.push(["lang-regex",new RegExp("^"+N+"("+aa+")")])}var X=V.types;if(X){U.push([Q,X])}var W=(""+V.keywords).replace(/^ | $/g,"");if(W.length){U.push([A,new RegExp("^(?:"+W.replace(/[\s,]+/g,"|")+")\\b"),null])}Y.push([G,/^\s+/,null," \r\n\t\xA0"]);var Z=/^.[^\s\w\.$@\'\"\`\/\\]*/;U.push([H,/^@[a-z_$][a-z_$@0-9]*/i,null],[Q,/^(?:[@_]?[A-Z]+[a-z][A-Za-z_$@0-9]*|\w+_t\b)/,null],[G,/^[a-z_$][a-z_$@0-9]*/i,null],[H,new RegExp("^(?:0x[a-f0-9]+|(?:\\d(?:_\\d+)*\\d*(?:\\.\\d*)?|\\.\\d\\+)(?:e[+\\-]?\\d+)?)[a-z]*","i"),null,"0123456789"],[G,/^\\[\s\S]?/,null],[M,Z,null]);return h(Y,U)}var L=i({keywords:B,hashComments:true,cStyleComments:true,multiLineStrings:true,regexLiterals:true});function S(W,ah,aa){var V=/(?:^|\s)nocode(?:\s|$)/;var ac=/\r\n?|\n/;var ad=W.ownerDocument;var ag=ad.createElement("li");while(W.firstChild){ag.appendChild(W.firstChild)}var X=[ag];function af(am){switch(am.nodeType){case 1:if(V.test(am.className)){break}if("br"===am.nodeName){ae(am);if(am.parentNode){am.parentNode.removeChild(am)}}else{for(var ao=am.firstChild;ao;ao=ao.nextSibling){af(ao)}}break;case 3:case 4:if(aa){var an=am.nodeValue;var ak=an.match(ac);if(ak){var aj=an.substring(0,ak.index);am.nodeValue=aj;var ai=an.substring(ak.index+ak[0].length);if(ai){var al=am.parentNode;al.insertBefore(ad.createTextNode(ai),am.nextSibling)}ae(am);if(!aj){am.parentNode.removeChild(am)}}}break}}function ae(al){while(!al.nextSibling){al=al.parentNode;if(!al){return}}function aj(am,at){var ar=at?am.cloneNode(false):am;var ap=am.parentNode;if(ap){var aq=aj(ap,1);var ao=am.nextSibling;aq.appendChild(ar);for(var an=ao;an;an=ao){ao=an.nextSibling;aq.appendChild(an)}}return ar}var ai=aj(al.nextSibling,0);for(var ak;(ak=ai.parentNode)&&ak.nodeType===1;){ai=ak}X.push(ai)}for(var Z=0;Z=U){aj+=2}if(Y>=ar){ac+=2}}}finally{if(au){au.style.display=ak}}}var u={};function d(W,X){for(var U=X.length;--U>=0;){var V=X[U];if(!u.hasOwnProperty(V)){u[V]=W}else{if(O.console){console.warn("cannot override language handler %s",V)}}}}function r(V,U){if(!(V&&u.hasOwnProperty(V))){V=/^\s*]*(?:>|$)/],[k,/^<\!--[\s\S]*?(?:-\->|$)/],["lang-",/^<\?([\s\S]+?)(?:\?>|$)/],["lang-",/^<%([\s\S]+?)(?:%>|$)/],[M,/^(?:<[%?]|[%?]>)/],["lang-",/^]*>([\s\S]+?)<\/xmp\b[^>]*>/i],["lang-js",/^]*>([\s\S]*?)(<\/script\b[^>]*>)/i],["lang-css",/^]*>([\s\S]*?)(<\/style\b[^>]*>)/i],["lang-in.tag",/^(<\/?[a-z][^<>]*>)/i]]),["default-markup","htm","html","mxml","xhtml","xml","xsl"]);d(h([[G,/^[\s]+/,null," \t\r\n"],[o,/^(?:\"[^\"]*\"?|\'[^\']*\'?)/,null,"\"'"]],[[n,/^^<\/?[a-z](?:[\w.:-]*\w)?|\/?>$/i],[R,/^(?!style[\s=]|on)[a-z](?:[\w:-]*\w)?/i],["lang-uq.val",/^=\s*([^>\'\"\s]*(?:[^>\'\"\s\/]|\/(?=\s)))/],[M,/^[=<>\/]+/],["lang-js",/^on\w+\s*=\s*\"([^\"]+)\"/i],["lang-js",/^on\w+\s*=\s*\'([^\']+)\'/i],["lang-js",/^on\w+\s*=\s*([^\"\'>\s]+)/i],["lang-css",/^style\s*=\s*\"([^\"]+)\"/i],["lang-css",/^style\s*=\s*\'([^\']+)\'/i],["lang-css",/^style\s*=\s*([^\"\'>\s]+)/i]]),["in.tag"]);d(h([],[[o,/^[\s\S]+/]]),["uq.val"]);d(i({keywords:m,hashComments:true,cStyleComments:true,types:f}),["c","cc","cpp","cxx","cyc","m"]);d(i({keywords:"null,true,false"}),["json"]);d(i({keywords:T,hashComments:true,cStyleComments:true,verbatimStrings:true,types:f}),["cs"]);d(i({keywords:y,cStyleComments:true}),["java"]);d(i({keywords:I,hashComments:true,multiLineStrings:true}),["bsh","csh","sh"]);d(i({keywords:J,hashComments:true,multiLineStrings:true,tripleQuotedStrings:true}),["cv","py"]);d(i({keywords:t,hashComments:true,multiLineStrings:true,regexLiterals:true}),["perl","pl","pm"]);d(i({keywords:g,hashComments:true,multiLineStrings:true,regexLiterals:true}),["rb"]);d(i({keywords:x,cStyleComments:true,regexLiterals:true}),["js"]);d(i({keywords:s,hashComments:3,cStyleComments:true,multilineStrings:true,tripleQuotedStrings:true,regexLiterals:true}),["coffee"]);d(h([],[[D,/^[\s\S]+/]]),["regex"]);function e(X){var W=X.langExtension;try{var U=b(X.sourceNode,X.pre);var V=U.sourceCode;X.sourceCode=V;X.spans=U.spans;X.basePos=0;r(W,V)(X);E(X)}catch(Y){if(O.console){console.log(Y&&Y.stack?Y.stack:Y)}}}function z(Y,X,W){var U=document.createElement("pre");U.innerHTML=Y;if(W){S(U,W,true)}var V={langExtension:X,numberLines:W,sourceNode:U,pre:1};e(V);return U.innerHTML}function c(aj){function ab(al){return document.getElementsByTagName(al)}var ah=[ab("pre"),ab("code"),ab("xmp")];var V=[];for(var ae=0;ae]*(?:>|$)/],[PR.PR_COMMENT,/^<\!--[\s\S]*?(?:-\->|$)/],[PR.PR_PUNCTUATION,/^(?:<[%?]|[%?]>)/],["lang-",/^<\?([\s\S]+?)(?:\?>|$)/],["lang-",/^<%([\s\S]+?)(?:%>|$)/],["lang-",/^]*>([\s\S]+?)<\/xmp\b[^>]*>/i],["lang-handlebars",/^]*type\s*=\s*['"]?text\/x-handlebars-template['"]?\b[^>]*>([\s\S]*?)(<\/script\b[^>]*>)/i],["lang-js",/^]*>([\s\S]*?)(<\/script\b[^>]*>)/i],["lang-css",/^]*>([\s\S]*?)(<\/style\b[^>]*>)/i],["lang-in.tag",/^(<\/?[a-z][^<>]*>)/i],[PR.PR_DECLARATION,/^{{[#^>/]?\s*[\w.][^}]*}}/],[PR.PR_DECLARATION,/^{{&?\s*[\w.][^}]*}}/],[PR.PR_DECLARATION,/^{{{>?\s*[\w.][^}]*}}}/],[PR.PR_COMMENT,/^{{![^}]*}}/]]),["handlebars","hbs"]);PR.registerLangHandler(PR.createSimpleLexer([[PR.PR_PLAIN,/^[ \t\r\n\f]+/,null," \t\r\n\f"]],[[PR.PR_STRING,/^\"(?:[^\n\r\f\\\"]|\\(?:\r\n?|\n|\f)|\\[\s\S])*\"/,null],[PR.PR_STRING,/^\'(?:[^\n\r\f\\\']|\\(?:\r\n?|\n|\f)|\\[\s\S])*\'/,null],["lang-css-str",/^url\(([^\)\"\']*)\)/i],[PR.PR_KEYWORD,/^(?:url|rgb|\!important|@import|@page|@media|@charset|inherit)(?=[^\-\w]|$)/i,null],["lang-css-kw",/^(-?(?:[_a-z]|(?:\\[0-9a-f]+ ?))(?:[_a-z0-9\-]|\\(?:\\[0-9a-f]+ ?))*)\s*:/i],[PR.PR_COMMENT,/^\/\*[^*]*\*+(?:[^\/*][^*]*\*+)*\//],[PR.PR_COMMENT,/^(?:)/],[PR.PR_LITERAL,/^(?:\d+|\d*\.\d+)(?:%|[a-z]+)?/i],[PR.PR_LITERAL,/^#(?:[0-9a-f]{3}){1,2}/i],[PR.PR_PLAIN,/^-?(?:[_a-z]|(?:\\[\da-f]+ ?))(?:[_a-z\d\-]|\\(?:\\[\da-f]+ ?))*/i],[PR.PR_PUNCTUATION,/^[^\s\w\'\"]+/]]),["css"]);PR.registerLangHandler(PR.createSimpleLexer([],[[PR.PR_KEYWORD,/^-?(?:[_a-z]|(?:\\[\da-f]+ ?))(?:[_a-z\d\-]|\\(?:\\[\da-f]+ ?))*/i]]),["css-kw"]);PR.registerLangHandler(PR.createSimpleLexer([],[[PR.PR_STRING,/^[^\)\"\']+/]]),["css-str"]); ================================================ FILE: docs/classes/components.nf-area-stack.html ================================================ components.nf-area-stack - ember-nf-graph

    API Docs for:
    Show:

    components.nf-area-stack Class

    A component for grouping and stacking nf-area components in an nf-graph.

    This component looks at the order of the nf-area components underneath it and uses the ydata of the next sibling nf-area component to determine the bottom of each nf-area components path to be drawn.

    Example

    {{#nf-graph width=300 height=100}}
      {{#nf-graph-content}}
        {{#nf-area-stack}}
          {{nf-area data=myData xprop="time" yprop="high"}}
          {{nf-area data=myData xprop="time" yprop="med"}}
          {{nf-area data=myData xprop="time" yprop="low"}}
        {{/nf-area-stack}}
      {{/nf-graph-content}}
    {{/nf-graph}}

    Item Index

    Methods

    registerArea

    (
    • area
    )

    Registers an area component with this stack. Also links areas to one another by setting nextArea on each area component.

    Parameters:

    • area Ember.Component

      The area component to register.

    unregisterArea

    (
    • area
    )

    Unregisters an area component from this stack. Also updates next and previous links.

    Parameters:

    • area Ember.Component

      the area to unregister

    Properties

    aggregate

    Boolean

    Whether or not to add the values together to create the stacked area

    Default: false

    areas

    Array

    The collection of nf-area components under this stack.

    isAreaStack

    Boolean

    Used by nf-area to identify an area stack parent

    Default: true

    ================================================ FILE: docs/classes/components.nf-area.html ================================================ components.nf-area - ember-nf-graph

    API Docs for:
    Show:

    components.nf-area Class

    Adds an area graph to an nf-graph component.

    Optionally, if it's located within an nf-area-stack component, it will work with sibling nf-area components to create a stacked graph.

    Methods

    _trackedDataChanged

    () private

    Observes changes to tracked data and sends the didTrack action.

    _unregisterGraphic

    () private

    calls unregisterGraphic on didInsertElement.

    _updateGraphSelected

    () private

    Makes calls to the parent nf-graph to update it's selected property. Observes changes to selected and also fires on didInsertElement.

    createAreaFn

    (
    • xScale
    • yScale
    • interpolator
    )
    Function

    Creates a d3 area function from a given set of scales and an interpolator

    Parameters:

    • xScale Function

      a d3 scale

    • yScale Function

      a d3 scale

    • interpolator String

      the name of the d3 interpolator to use.

    Returns:

    Function:

    a function that when called will create SVG path data.

    getActualTrackData

    ()

    Override from graph-data-graphic mixin

    init

    ()

    Initalization method that gets the nf-graph parent and assigns it to graph NOTE: all object that mixin and have init, must call super.init()

    Properties

    data

    Array

    Gets or sets the data used by the component to plot itself.

    Default: null

    didTrack

    String

    The action to send on didTrack.

    Default: null

    firstVisibleData

    Object

    The first element from renderedData that is actually visible within the x domain.

    graph

    components.nf-graph

    The parent graph for a component.

    Default: null

    hoverData

    Object an object with the following values: - point: an x, y pair for the exact px coordinates inside the graph-content - graphX: domain x value at mouse position - graphY: domain y value at mouse position - x: nearest x data value - y: nearest y data value - data: nearest raw data - renderX: domain x value to render a tracking dot at (stacked areas are offset) - renderY: domain x value to render a tracking dot at (stacked areas are offset) - mouseX: mouse x position in pixels - mouseY: mouse y position in pixels

    The value of the data that is being tracked by the component, ONLY if the graph-content is currently being hovered.

    Default: null

    interpolator

    String

    The type of d3 interpolator to use to create the area

    Default: 'linear'

    isSelected

    Unknown deprecated

    Alias of selected

    lastVisibleData

    Object

    The last element from renderedData that is actually visible within the x domain.

    mappedData

    Array

    The current rendered data "zipped" together with the nextYData.

    nextArea

    components.nf-area

    The next area in the stack, if this area is part of an nf-area-stack

    Default: null

    nextYData

    Array

    The computed set of next y values to use for the "bottom" of the graphed area. If the area is part of a stack, this will be the "top" of the next area in the stack, otherwise it will return an array of values at the "bottom" of the graph domain.

    prevArea

    components.nf-area

    The previous area in the stack, if this area is part of an nf-area-stack

    Default: null

    renderedData

    Array

    The list of data points from mixins.graph-data-graphc/mappedData:property that fits within the x domain, plus up to one data point outside of that domain in each direction.

    scaleOffsetX

    Number

    The offset, in pixels, for the x scale

    Default: 0

    scaleOffsetY

    Number

    The offset, in pixels, for the y scale

    Default: 0

    scaleZoomX

    Number

    The zoom multiplier for the x scale

    Default: 1

    scaleZoomY

    Number

    The zoom multiplier for the y scale

    Default: 1

    selectable

    Boolean

    Gets or sets whether or not the graphic is "selectable". Meaning can be "selected" on the nf-graph via some action (usually click). The component will then show up in the nf-graph parent's selected property.

    Default: false

    selected

    Boolean

    Gets or sets whether or not the graphic is selected.

    Default: false

    showTrackingDot

    Boolean

    Gets or sets whether the tracking dot should be shown at all.

    Default: true

    trackedData

    Object an object with the following values: - point: an x, y pair for the exact px coordinates inside the graph-content - graphX: domain x value at mouse position - graphY: domain y value at mouse position - x: nearest x data value - y: nearest y data value - data: nearest raw data - renderX: domain x value to render a tracking dot at (stacked areas are offset) - renderY: domain x value to render a tracking dot at (stacked areas are offset) - mouseX: mouse x position in pixels - mouseY: mouse y position in pixels

    The value of the data that is being tracked by the component.

    Default: null

    trackingDotRadius

    Number

    The radius of the tracking dot in pixels

    Default: 2.5

    trackingMode

    String

    Gets or sets the tracking mode of the component.

    Possible values are:

    • 'none': no tracking behavior
    • 'hover': only track while mouse hover
    • 'snap-last': track while mouse hover, but snap to the last data element when not hovering
    • 'snap-first': track while mouse hover, but snap to the first data element when not hovering
    • 'selected-hover': The same as 'hover' tracking mode, but only when the compononent is selected
    • 'selected-snap-last': The same as 'snap-last' tracking mode, but only when the compononent is selected
    • 'selected-snap-first': The same as 'snap-first' tracking mode, but only when the compononent is selected

    Default: 'none'

    xprop

    String

    The path of the property on each object in data to use as x data to plot on the graph.

    Default: 'x'

    xPropFn

    Function

    The function to get the x value from each data object

    xScale

    d3.scale

    The x scale used by this component

    yprop

    String

    The path of the property on each object in data to use as y data to plot on the graph.

    Default: 'y'

    yPropFn

    Function

    The function to get the y value from each data object

    yScale

    d3.scale

    The y scale used by this component

    ================================================ FILE: docs/classes/components.nf-bars.html ================================================ components.nf-bars - ember-nf-graph

    API Docs for:
    Show:

    components.nf-bars Class

    Adds a bar graph to an nf-graph component.

    Requires the graph has xScaleType === 'ordinal'*

    ** showTrackingDot defaults to false in this component **

    Methods

    _trackedDataChanged

    () private

    Observes changes to tracked data and sends the didTrack action.

    _unregisterGraphic

    () private

    calls unregisterGraphic on didInsertElement.

    getActualTrackData

    (
    • renderX
    • renderY
    • data
    )
    Object

    Gets the actual data at a rendered tracking point passed to it. This is overridden in nf-area to account for stacking of data.

    Parameters:

    • renderX Number

      the x domain value the data is rendered at

    • renderY Number

      the y domain value the data is rendered at

    • data Object

      the raw data from the point

    Returns:

    Object:

    simple x, y point structure

    init

    ()

    Initalization method that gets the nf-graph parent and assigns it to graph NOTE: all object that mixin and have init, must call super.init()

    Properties

    barClick

    String

    The name of the action to fire when a bar is clicked.

    Default: null

    bars

    Unknown

    The bar models used to render the bars.

    barScale

    d3.scale

    A scale provided by nf-bars-group to offset the bar rectangle output

    barWidth

    Number

    The width of each bar.

    classprop

    String

    The name of the property on each data item containing the className for the bar rectangle

    Default: 'className'

    data

    Array

    Gets or sets the data used by the component to plot itself.

    Default: null

    didTrack

    String

    The action to send on didTrack.

    Default: null

    firstVisibleData

    Object

    The first element from renderedData that is actually visible within the x domain.

    getBarClass

    Unknown private

    Gets the function to get the classname from each data item.

    graph

    components.nf-graph

    The parent graph for a component.

    Default: null

    graphHeight

    Number

    The graph content height

    group

    components.nf-bars-group

    The nf-bars-group this belongs to, if any.

    Default: null

    groupIndex

    Number

    The index of this component within the group, if any.

    Default: null

    hoverData

    Object an object with the following values: - point: an x, y pair for the exact px coordinates inside the graph-content - graphX: domain x value at mouse position - graphY: domain y value at mouse position - x: nearest x data value - y: nearest y data value - data: nearest raw data - renderX: domain x value to render a tracking dot at (stacked areas are offset) - renderY: domain x value to render a tracking dot at (stacked areas are offset) - mouseX: mouse x position in pixels - mouseY: mouse y position in pixels

    The value of the data that is being tracked by the component, ONLY if the graph-content is currently being hovered.

    Default: null

    lastVisibleData

    Object

    The last element from renderedData that is actually visible within the x domain.

    renderedData

    Array

    The list of data points from mixins.graph-data-graphc/mappedData:property that fits within the x domain, plus up to one data point outside of that domain in each direction.

    scaleOffsetX

    Number

    The offset, in pixels, for the x scale

    Default: 0

    scaleOffsetY

    Number

    The offset, in pixels, for the y scale

    Default: 0

    scaleZoomX

    Number

    The zoom multiplier for the x scale

    Default: 1

    scaleZoomY

    Number

    The zoom multiplier for the y scale

    Default: 1

    showTrackingDot

    Boolean

    Gets or sets whether the tracking dot should be shown at all.

    Default: true

    trackedData

    Object an object with the following values: - point: an x, y pair for the exact px coordinates inside the graph-content - graphX: domain x value at mouse position - graphY: domain y value at mouse position - x: nearest x data value - y: nearest y data value - data: nearest raw data - renderX: domain x value to render a tracking dot at (stacked areas are offset) - renderY: domain x value to render a tracking dot at (stacked areas are offset) - mouseX: mouse x position in pixels - mouseY: mouse y position in pixels

    The value of the data that is being tracked by the component.

    Default: null

    trackingDotRadius

    Number

    The radius of the tracking dot in pixels

    Default: 2.5

    trackingMode

    String

    Gets or sets the tracking mode of the component.

    Possible values are:

    • 'none': no tracking behavior
    • 'hover': only track while mouse hover
    • 'snap-last': track while mouse hover, but snap to the last data element when not hovering
    • 'snap-first': track while mouse hover, but snap to the first data element when not hovering
    • 'selected-hover': The same as 'hover' tracking mode, but only when the compononent is selected
    • 'selected-snap-last': The same as 'snap-last' tracking mode, but only when the compononent is selected
    • 'selected-snap-first': The same as 'snap-first' tracking mode, but only when the compononent is selected

    Default: 'none'

    xprop

    String

    The path of the property on each object in data to use as x data to plot on the graph.

    Default: 'x'

    xPropFn

    Function

    The function to get the x value from each data object

    xScale

    d3.scale

    The x scale used by this component

    yprop

    String

    The path of the property on each object in data to use as y data to plot on the graph.

    Default: 'y'

    yPropFn

    Function

    The function to get the y value from each data object

    yScale

    d3.scale

    The y scale used by this component

    ================================================ FILE: docs/classes/components.nf-crosshair.html ================================================ components.nf-crosshair - ember-nf-graph

    API Docs for:
    Show:

    components.nf-crosshair Class

    Extends Ember.Component
    Module: utils/nf/svg-dom

    A component that adds a "crosshair" to an nf-graph that follows the mouse while it's hovering over the graph content.

    Methods

    _trackedDataChanged

    () private

    Observes changes to tracked data and sends the didTrack action.

    init

    ()

    Initalization method that gets the nf-graph parent and assigns it to graph NOTE: all object that mixin and have init, must call super.init()

    Properties

    didTrack

    String

    The action to send on didTrack.

    Default: null

    graph

    components.nf-graph

    The parent graph for a component.

    Default: null

    height

    Number

    The height of the crosshair in pixels

    hoverData

    Object an object with the following values: - point: an x, y pair for the exact px coordinates inside the graph-content - graphX: domain x value at mouse position - graphY: domain y value at mouse position - x: nearest x data value - y: nearest y data value - data: nearest raw data - renderX: domain x value to render a tracking dot at (stacked areas are offset) - renderY: domain x value to render a tracking dot at (stacked areas are offset) - mouseX: mouse x position in pixels - mouseY: mouse y position in pixels

    The value of the data that is being tracked by the component, ONLY if the graph-content is currently being hovered.

    Default: null

    isVisible

    Boolean

    The visibility of the component

    Default: false

    showTrackingDot

    Boolean

    Gets or sets whether the tracking dot should be shown at all.

    Default: true

    trackedData

    Object an object with the following values: - point: an x, y pair for the exact px coordinates inside the graph-content - graphX: domain x value at mouse position - graphY: domain y value at mouse position - x: nearest x data value - y: nearest y data value - data: nearest raw data - renderX: domain x value to render a tracking dot at (stacked areas are offset) - renderY: domain x value to render a tracking dot at (stacked areas are offset) - mouseX: mouse x position in pixels - mouseY: mouse y position in pixels

    The value of the data that is being tracked by the component.

    Default: null

    trackingDotRadius

    Number

    The radius of the tracking dot in pixels

    Default: 2.5

    trackingMode

    String

    Gets or sets the tracking mode of the component.

    Possible values are:

    • 'none': no tracking behavior
    • 'hover': only track while mouse hover
    • 'snap-last': track while mouse hover, but snap to the last data element when not hovering
    • 'snap-first': track while mouse hover, but snap to the first data element when not hovering
    • 'selected-hover': The same as 'hover' tracking mode, but only when the compononent is selected
    • 'selected-snap-last': The same as 'snap-last' tracking mode, but only when the compononent is selected
    • 'selected-snap-first': The same as 'snap-first' tracking mode, but only when the compononent is selected

    Default: 'none'

    width

    Number

    The width of the crosshair in pixels

    x

    Number

    The x position of the crosshairs

    Default: 0

    y

    Number

    The y position of the crosshairs

    Default: 0

    ================================================ FILE: docs/classes/components.nf-dot.html ================================================ components.nf-dot - ember-nf-graph

    API Docs for:
    Show:

    components.nf-dot Class

    Plots a circle at a given x and y domain value on an nf-graph.

    Methods

    _trackedDataChanged

    () private

    Observes changes to tracked data and sends the didTrack action.

    init

    ()

    Initalization method that gets the nf-graph parent and assigns it to graph NOTE: all object that mixin and have init, must call super.init()

    Properties

    cx

    Number private

    The computed center x coordinate of the circle

    cy

    Number private

    The computed center y coordinate of the circle

    didTrack

    String

    The action to send on didTrack.

    Default: null

    graph

    components.nf-graph

    The parent graph for a component.

    Default: null

    hoverData

    Object an object with the following values: - point: an x, y pair for the exact px coordinates inside the graph-content - graphX: domain x value at mouse position - graphY: domain y value at mouse position - x: nearest x data value - y: nearest y data value - data: nearest raw data - renderX: domain x value to render a tracking dot at (stacked areas are offset) - renderY: domain x value to render a tracking dot at (stacked areas are offset) - mouseX: mouse x position in pixels - mouseY: mouse y position in pixels

    The value of the data that is being tracked by the component, ONLY if the graph-content is currently being hovered.

    Default: null

    isVisible

    Unknown private

    Toggles the visibility of the dot. If x or y are not numbers, will return false.

    r

    Number

    The radius of the circle plotted

    Default: 2.5

    scaleOffsetX

    Number

    The offset, in pixels, for the x scale

    Default: 0

    scaleOffsetY

    Number

    The offset, in pixels, for the y scale

    Default: 0

    scaleZoomX

    Number

    The zoom multiplier for the x scale

    Default: 1

    scaleZoomY

    Number

    The zoom multiplier for the y scale

    Default: 1

    showTrackingDot

    Boolean

    Gets or sets whether the tracking dot should be shown at all.

    Default: true

    trackedData

    Object an object with the following values: - point: an x, y pair for the exact px coordinates inside the graph-content - graphX: domain x value at mouse position - graphY: domain y value at mouse position - x: nearest x data value - y: nearest y data value - data: nearest raw data - renderX: domain x value to render a tracking dot at (stacked areas are offset) - renderY: domain x value to render a tracking dot at (stacked areas are offset) - mouseX: mouse x position in pixels - mouseY: mouse y position in pixels

    The value of the data that is being tracked by the component.

    Default: null

    trackingDotRadius

    Number

    The radius of the tracking dot in pixels

    Default: 2.5

    trackingMode

    String

    Gets or sets the tracking mode of the component.

    Possible values are:

    • 'none': no tracking behavior
    • 'hover': only track while mouse hover
    • 'snap-last': track while mouse hover, but snap to the last data element when not hovering
    • 'snap-first': track while mouse hover, but snap to the first data element when not hovering
    • 'selected-hover': The same as 'hover' tracking mode, but only when the compononent is selected
    • 'selected-snap-last': The same as 'snap-last' tracking mode, but only when the compononent is selected
    • 'selected-snap-first': The same as 'snap-first' tracking mode, but only when the compononent is selected

    Default: 'none'

    x

    Number

    The y domain value at which to plot the circle

    Default: null

    x

    Number

    The x domain value at which to plot the circle

    Default: null

    xScale

    d3.scale

    The x scale used by this component

    yScale

    d3.scale

    The y scale used by this component

    ================================================ FILE: docs/classes/components.nf-gg.html ================================================ components.nf-gg - ember-nf-graph

    API Docs for:
    Show:

    components.nf-gg Class

    A grouping tag that provides zooming and offset functionality to it's children.

    Example

    The following example will show a line of someData with a 2x zoom, offset by 30px in both x and y directions:

      {{#nf-gg scaleZoomX="2" scaleZoomY="2" scaleOffsetX="30" scaleOffsetY="30"}}
        {{nf-line data=someData}}
      {{/nf-gg}}

    Methods

    _trackedDataChanged

    () private

    Observes changes to tracked data and sends the didTrack action.

    init

    ()

    Initalization method that gets the nf-graph parent and assigns it to graph NOTE: all object that mixin and have init, must call super.init()

    Properties

    didTrack

    String

    The action to send on didTrack.

    Default: null

    graph

    components.nf-graph

    The parent graph for a component.

    Default: null

    hoverData

    Object an object with the following values: - point: an x, y pair for the exact px coordinates inside the graph-content - graphX: domain x value at mouse position - graphY: domain y value at mouse position - x: nearest x data value - y: nearest y data value - data: nearest raw data - renderX: domain x value to render a tracking dot at (stacked areas are offset) - renderY: domain x value to render a tracking dot at (stacked areas are offset) - mouseX: mouse x position in pixels - mouseY: mouse y position in pixels

    The value of the data that is being tracked by the component, ONLY if the graph-content is currently being hovered.

    Default: null

    showTrackingDot

    Boolean

    Gets or sets whether the tracking dot should be shown at all.

    Default: true

    trackedData

    Object an object with the following values: - point: an x, y pair for the exact px coordinates inside the graph-content - graphX: domain x value at mouse position - graphY: domain y value at mouse position - x: nearest x data value - y: nearest y data value - data: nearest raw data - renderX: domain x value to render a tracking dot at (stacked areas are offset) - renderY: domain x value to render a tracking dot at (stacked areas are offset) - mouseX: mouse x position in pixels - mouseY: mouse y position in pixels

    The value of the data that is being tracked by the component.

    Default: null

    trackingDotRadius

    Number

    The radius of the tracking dot in pixels

    Default: 2.5

    trackingMode

    String

    Gets or sets the tracking mode of the component.

    Possible values are:

    • 'none': no tracking behavior
    • 'hover': only track while mouse hover
    • 'snap-last': track while mouse hover, but snap to the last data element when not hovering
    • 'snap-first': track while mouse hover, but snap to the first data element when not hovering
    • 'selected-hover': The same as 'hover' tracking mode, but only when the compononent is selected
    • 'selected-snap-last': The same as 'snap-last' tracking mode, but only when the compononent is selected
    • 'selected-snap-first': The same as 'snap-first' tracking mode, but only when the compononent is selected

    Default: 'none'

    ================================================ FILE: docs/classes/components.nf-graph-content.html ================================================ components.nf-graph-content - ember-nf-graph

    API Docs for:
    Show:

    components.nf-graph-content Class

    Container component for graphics to display in nf-graph. Represents the area where the graphics, such as lines will display.

    Exists for layout purposes.

    Methods

    _trackedDataChanged

    () private

    Observes changes to tracked data and sends the didTrack action.

    init

    ()

    Initalization method that gets the nf-graph parent and assigns it to graph NOTE: all object that mixin and have init, must call super.init()

    Properties

    didTrack

    String

    The action to send on didTrack.

    Default: null

    frets

    Array

    An array containing models to render fret lines

    graph

    components.nf-graph

    The parent graph for a component.

    Default: null

    gridLanes

    Array

    An array containing models to render the grid lanes

    height

    Number

    The calculated height of the graph content.

    hoverChange

    String

    The name of the hoverChange action to fire

    Default: null

    hoverData

    Object an object with the following values: - point: an x, y pair for the exact px coordinates inside the graph-content - graphX: domain x value at mouse position - graphY: domain y value at mouse position - x: nearest x data value - y: nearest y data value - data: nearest raw data - renderX: domain x value to render a tracking dot at (stacked areas are offset) - renderY: domain x value to render a tracking dot at (stacked areas are offset) - mouseX: mouse x position in pixels - mouseY: mouse y position in pixels

    The value of the data that is being tracked by the component, ONLY if the graph-content is currently being hovered.

    Default: null

    hoverEnd

    String

    The name of the hoverEnd action to fire

    Default: null

    showTrackingDot

    Boolean

    Gets or sets whether the tracking dot should be shown at all.

    Default: true

    trackedData

    Object an object with the following values: - point: an x, y pair for the exact px coordinates inside the graph-content - graphX: domain x value at mouse position - graphY: domain y value at mouse position - x: nearest x data value - y: nearest y data value - data: nearest raw data - renderX: domain x value to render a tracking dot at (stacked areas are offset) - renderY: domain x value to render a tracking dot at (stacked areas are offset) - mouseX: mouse x position in pixels - mouseY: mouse y position in pixels

    The value of the data that is being tracked by the component.

    Default: null

    trackingDotRadius

    Number

    The radius of the tracking dot in pixels

    Default: 2.5

    trackingMode

    String

    Gets or sets the tracking mode of the component.

    Possible values are:

    • 'none': no tracking behavior
    • 'hover': only track while mouse hover
    • 'snap-last': track while mouse hover, but snap to the last data element when not hovering
    • 'snap-first': track while mouse hover, but snap to the first data element when not hovering
    • 'selected-hover': The same as 'hover' tracking mode, but only when the compononent is selected
    • 'selected-snap-last': The same as 'snap-last' tracking mode, but only when the compononent is selected
    • 'selected-snap-first': The same as 'snap-first' tracking mode, but only when the compononent is selected

    Default: 'none'

    transform

    String

    The SVG transform for positioning the graph content

    width

    Number

    The calculated width of the graph content

    x

    Number

    The x position of the graph content

    y

    Number

    The calculated y position of the graph content

    ================================================ FILE: docs/classes/components.nf-graph.html ================================================ components.nf-graph - ember-nf-graph

    API Docs for:
    Show:

    components.nf-graph Class

    Extends Ember.Component
    Module: utils/nf/svg-dom

    A container component for building complex Cartesian graphs.

    Minimal example

     {{#nf-graph width=100 height=50}}
       {{#nf-graph-content}}
         {{nf-line data=lineData xprop="foo" yprop="bar"}}
       {{/nf-graph-content}}
     {{/nf-graph}}
    

    The above will create a simple 100x50 graph, with no axes, and a single line plotting the data it finds on each object in the array lineData at properties foo and bar for x and y values respectively.

    More advanced example

     {{#nf-graph width=500 height=300}}
       {{#nf-x-axis height="50" as |tick|}}
         <text>{{tick.value}}</text>
       {{/nf-x-axis}}
    
       {{#nf-y-axis width="120" as |tick|}}
         <text>{{tick.value}}</text>
       {{/nf-y-axis}}
    
       {{#nf-graph-content}}
         {{nf-line data=lineData xprop="foo" yprop="bar"}}
       {{/nf-graph-content}}
     {{/nf-graph}}
    

    The above example will create a 500x300 graph with both axes visible. The graph will not render either axis unless its component is present.

    Methods

    _notifyHasRendered

    () private

    Sets hasRendered to true on willInsertElement.

    _setup

    () private

    The initialization method. Fired on init.

    deselectGraphic

    (
    • graphic
    )

    deselects the graphic passed.

    Parameters:

    • graphic Ember.Component

      the graph child component to deselect.

    didAutoUpdateMaxX

    ()

    Event handler that is fired for the didAutoUpdateMaxX event

    didAutoUpdateMaxY

    ()

    Event handler that is fired for the didAutoUpdateMaxY event

    didAutoUpdateMinX

    ()

    Event handler that is fired for the didAutoUpdateMinX event

    didAutoUpdateMinY

    ()

    Event handler that is fired for the didAutoUpdateMinY event

    mousePoint

    (
    • container
    • e
    )
    Array

    Gets the mouse position relative to the container

    Parameters:

    • container SVGElement

      the SVG element that contains the mouse event

    • e Object

      the DOM mouse event

    Returns:

    Array:

    an array of [xMouseCoord, yMouseCoord]

    registerGraphic

    (
    • graphic
    )

    Registers a graphic such as nf-line or nf-area components with the graph.

    Parameters:

    • graphic Ember.Component

      The component object to register

    selectGraphic

    (
    • graphic
    )

    Selects the graphic passed. If selectMultiple is false, it will deselect the currently selected graphic if it's different from the one passed.

    Parameters:

    • graphic Ember.Component

      the graph component to select within the graph.

    unregisterGraphic

    (
    • graphic
    )

    Unregisters a graphic such as an nf-line or nf-area from the graph.

    Parameters:

    • graphic Ember.Component

      The component to unregister

    Properties

    _xMax

    Unknown private

    Backing field for xMax

    _xMin

    Unknown private

    Backing field for xMin

    _yMax

    Unknown private

    Backing field for yMax

    _yMin

    Unknown private

    Backing field for yMin

    autoScaleXAction

    String

    The action to trigger when the graph automatically updates the xScale due to an "auto" "push" or "push-tick" domainMode.

    sends the graph component instance value as the argument.

    Default: null

    autoScaleYAction

    String

    The action to trigger when the graph automatically updates the yScale due to an "auto" "push" or "push-tick" domainMode.

    Sends the graph component instance as the argument.

    Default: null

    brushAction

    String

    The name of the action to trigger when brushing emits a new value

    Default: null

    brushEndAction

    String

    The name of the action to trigger when brushing ends

    Default: null

    brushStartAction

    String

    The name of the action to trigger when brushing starts

    Default: null

    brushThreshold

    Number

    The amount of leeway, in pixels, to give before triggering a brush start.

    Default: 7

    contentClipPathId

    String private

    Gets the DOM id for the content clipPath element.

    dataExtents

    Object

    The data extents for all data in the registered graphics.

    Default: { xMin: Number.MAX_VALUE, xMax: Number.MIN_VALUE, yMin: Number.MAX_VALUE, yMax: Number.MIN_VALUE }

    graphHeight

    Number

    The height, in pixels, of the graph content

    graphics

    Array

    Registry of contained graphic elements such as nf-line or nf-area components. This registry is used to pool data for scaling purposes.

    graphTransform

    String

    An SVG transform to position the graph content

    graphWidth

    Number

    The width, in pixels, of the graph content

    graphX

    Number

    The x coordinate position of the graph content

    graphY

    Number

    The y coordinate position of the graph content

    hasData

    Boolean

    Returns true if the graph has data to render. Data is conveyed to the graph by registered graphics.

    Default: false

    hasRendered

    Unknown private

    height

    Number

    The height of the graph in pixels.

    Default: 100

    isGraph

    Unknown private

    Allows child compoenents to identify graph parent.

    isScaleSource

    Unknown private

    Identifies this graph to its children as providing scales.

    paddingBottom

    Number

    The padding at the bottom of the graph

    Default: 0

    paddingLeft

    Number

    The padding at the left of the graph

    Default: 0

    paddingRight

    Number

    The padding at the right of the graph

    Default: 0

    paddingTop

    Number

    The padding at the top of the graph

    Default: 0

    parentController

    Ember.Controller

    A computed property returned the view's controller.

    selected

    Array

    An array of "selectable" graphics that have been selected within this graph.

    selectMultiple

    Boolean

    Gets or sets the whether or not multiple selectable graphics may be selected simultaneously.

    Default: false

    showFrets

    Boolean

    Determines whether to display "frets" in the background of the graph.

    Default: false

    showLanes

    Boolean

    Determines whether to display "lanes" in the background of the graph.

    Default: false

    showXAxis

    Boolean

    Computed property to show xAxis. Returns true if an xAxis is present.

    Default: false

    showYAxis

    Boolean

    Computed property to show yAxis. Returns true if a yAxis is present.

    Default: false

    width

    Number

    The width of the graph in pixels.

    Default: 300

    xAxis

    Unknown

    The nf-x-axis component is registered here if there is one present

    Default: null

    xDataExtent

    Array

    Gets the highest and lowest x values of the graphed data in a two element array.

    xDomain

    Array

    Gets the domain of x values.

    xLogMin

    Number

    The min value to use for xScaleType "log" if xMin <= 0

    Default: 0.1

    xMax

    Unknown

    Gets or sets the maximum x domain value to display on the graph. Behavior depends on xMaxMode.

    xMaxMode

    String

    Sets the behavior of xMax for the graph.

    Possible values:

    • 'auto': (default) xMax is always equal to the maximum domain value contained in the graphed data. Cannot be set.
    • 'fixed': xMax can be set to an exact value and will not change based on graphed data.
    • 'push': xMax can be set to a specific value, but will update if the maximum x value contained in the graph is greater than what xMax is currently set to.
    • 'push-tick': xMax can be set to a specific value, but will update to next "nice" tick if the maximum x value contained in the graph is greater than that xMax is set to.

    Default: 'auto'

    xMin

    Unknown

    Gets or sets the minimum x domain value to display on the graph. Behavior depends on xMinMode.

    xMinMode

    String

    Sets the behavior of xMin for the graph.

    Possible values:

    • 'auto': (default) xMin is always equal to the minimum domain value contained in the graphed data. Cannot be set.
    • 'fixed': xMin can be set to an exact value and will not change based on graphed data.
    • 'push': xMin can be set to a specific value, but will update if the minimum x value contained in the graph is less than what xMin is currently set to.
    • 'push-tick': xMin can be set to a specific value, but will update to next "nice" tick if the minimum x value contained in the graph is less than that xMin is set to.

    Default: 'auto'

    xOrdinalOuterPadding

    Number

    The padding at the ends of the domain data when xScaleType is 'ordinal'

    Default: 0.1

    xOrdinalPadding

    Number

    The padding between value steps when xScaleType is 'ordinal'

    Default: 0.1

    xPowerExponent

    Number

    The exponent to use for xScaleType "pow" or "power".

    Default: 3

    xRange

    Array

    The x range of the graph in pixels. The min and max pixel values in an array form.

    xScale

    Function

    Gets the current xScale used to draw the graph.

    xScaleFactory

    Unknown

    Gets a function to create the xScale

    xScaleType

    String

    The type of scale to use for x values.

    Possible Values:

    • 'linear' - a standard linear scale
    • 'log' - a logarithmic scale
    • 'power' - a power-based scale (exponent = 3)
    • 'ordinal' - an ordinal scale, used for ordinal data. required for bar graphs.

    Default: 'linear'

    xUniqueData

    Array

    yAxis

    Unknown

    the nf-y-axis component is registered here if there is one present

    Default: null

    yDataExtent

    Array

    Gets the highest and lowest y values of the graphed data in a two element array.

    yDomain

    Array

    Gets the domain of y values.

    yLogMin

    Number

    The min value to use for yScaleType "log" if yMin <= 0

    Default: 0.1

    yMax

    Unknown

    Gets or sets the maximum y domain value to display on the graph. Behavior depends on yMaxMode.

    yMaxMode

    String

    Sets the behavior of yMax for the graph.

    Possible values:

    • 'auto': (default) yMax is always equal to the maximum domain value contained in the graphed data. Cannot be set.
    • 'fixed': yMax can be set to an exact value and will not change based on graphed data.
    • 'push': yMax can be set to a specific value, but will update if the maximum y value contained in the graph is greater than what yMax is currently set to.
    • 'push-tick': yMax can be set to a specific value, but will update to next "nice" tick if the maximum y value contained in the graph is greater than that yMax is set to.

    Default: 'auto'

    yMin

    Unknown

    Gets or sets the minimum y domain value to display on the graph. Behavior depends on yMinMode.

    yMinMode

    String

    Sets the behavior of yMin for the graph.

    Possible values:

    • 'auto': (default) yMin is always equal to the minimum domain value contained in the graphed data. Cannot be set.
    • 'fixed': yMin can be set to an exact value and will not change based on graphed data.
    • 'push': yMin can be set to a specific value, but will update if the minimum y value contained in the graph is less than what yMin is currently set to.
    • 'push-tick': yMin can be set to a specific value, but will update to next "nice" tick if the minimum y value contained in the graph is less than that yMin is set to.

    Default: 'auto'

    yOrdinalOuterPadding

    Number

    The padding at the ends of the domain data when yScaleType is 'ordinal'

    Default: 0.1

    yOrdinalPadding

    Number

    The padding between value steps when xScaleType is 'ordinal'

    Default: 0.1

    yPowerExponent

    Number

    The exponent to use for yScaleType "pow" or "power".

    Default: 3

    yRange

    Array

    The y range of the graph in pixels. The min and max pixel values in an array form.

    yScale

    Function

    Gets the current yScale used to draw the graph.

    yScaleFactory

    Unknown

    Gets a function to create the yScale

    yScaleType

    String

    The type of scale to use for y values.

    Possible Values:

    • 'linear' - a standard linear scale
    • 'log' - a logarithmic scale
    • 'power' - a power-based scale (exponent = 3)
    • 'ordinal' - an ordinal scale, used for ordinal data. required for bar graphs.

    Default: 'linear'

    yUniqueData

    Array
    ================================================ FILE: docs/classes/components.nf-horizontal-line.html ================================================ components.nf-horizontal-line - ember-nf-graph

    API Docs for:
    Show:

    components.nf-horizontal-line Class

    Draws a horizontal line on the graph at a given y domain value

    Methods

    _trackedDataChanged

    () private

    Observes changes to tracked data and sends the didTrack action.

    init

    ()

    Initalization method that gets the nf-graph parent and assigns it to graph NOTE: all object that mixin and have init, must call super.init()

    Properties

    didTrack

    String

    The action to send on didTrack.

    Default: null

    graph

    components.nf-graph

    The parent graph for a component.

    Default: null

    hoverData

    Object an object with the following values: - point: an x, y pair for the exact px coordinates inside the graph-content - graphX: domain x value at mouse position - graphY: domain y value at mouse position - x: nearest x data value - y: nearest y data value - data: nearest raw data - renderX: domain x value to render a tracking dot at (stacked areas are offset) - renderY: domain x value to render a tracking dot at (stacked areas are offset) - mouseX: mouse x position in pixels - mouseY: mouse y position in pixels

    The value of the data that is being tracked by the component, ONLY if the graph-content is currently being hovered.

    Default: null

    lineY

    Number private

    The computed y coordinate of the line to draw

    scaleOffsetX

    Number

    The offset, in pixels, for the x scale

    Default: 0

    scaleOffsetY

    Number

    The offset, in pixels, for the y scale

    Default: 0

    scaleZoomX

    Number

    The zoom multiplier for the x scale

    Default: 1

    scaleZoomY

    Number

    The zoom multiplier for the y scale

    Default: 1

    showTrackingDot

    Boolean

    Gets or sets whether the tracking dot should be shown at all.

    Default: true

    trackedData

    Object an object with the following values: - point: an x, y pair for the exact px coordinates inside the graph-content - graphX: domain x value at mouse position - graphY: domain y value at mouse position - x: nearest x data value - y: nearest y data value - data: nearest raw data - renderX: domain x value to render a tracking dot at (stacked areas are offset) - renderY: domain x value to render a tracking dot at (stacked areas are offset) - mouseX: mouse x position in pixels - mouseY: mouse y position in pixels

    The value of the data that is being tracked by the component.

    Default: null

    trackingDotRadius

    Number

    The radius of the tracking dot in pixels

    Default: 2.5

    trackingMode

    String

    Gets or sets the tracking mode of the component.

    Possible values are:

    • 'none': no tracking behavior
    • 'hover': only track while mouse hover
    • 'snap-last': track while mouse hover, but snap to the last data element when not hovering
    • 'snap-first': track while mouse hover, but snap to the first data element when not hovering
    • 'selected-hover': The same as 'hover' tracking mode, but only when the compononent is selected
    • 'selected-snap-last': The same as 'snap-last' tracking mode, but only when the compononent is selected
    • 'selected-snap-first': The same as 'snap-first' tracking mode, but only when the compononent is selected

    Default: 'none'

    x1

    Number private

    The left x coordinate of the line

    Default: 0

    x2

    Number private

    The right x coordinate of the line

    xScale

    d3.scale

    The x scale used by this component

    y

    Number

    The y domain value at which to draw the horizontal line

    Default: null

    yScale

    d3.scale

    The y scale used by this component

    ================================================ FILE: docs/classes/components.nf-line.html ================================================ components.nf-line - ember-nf-graph

    API Docs for:
    Show:

    components.nf-line Class

    A line graphic for nf-graph. Displays a line for the data it's passed.

    Methods

    _toggleSelected

    () private

    Event handler to toggle the selected property on click

    _trackedDataChanged

    () private

    Observes changes to tracked data and sends the didTrack action.

    _unregisterGraphic

    () private

    calls unregisterGraphic on didInsertElement.

    _updateGraphSelected

    () private

    Makes calls to the parent nf-graph to update it's selected property. Observes changes to selected and also fires on didInsertElement.

    createLineFn

    (
    • xScale
    • yScale
    • interpolate
    )
    Function

    Create a d3 line function from a given scales and interpolation

    Parameters:

    • xScale Function

      d3 scale function

    • yScale Function

      d3 scale function

    • interpolate String

      d3 interpolator name

    Returns:

    Function:

    a d3 function that will create SVG path data from a given data set.

    getActualTrackData

    (
    • renderX
    • renderY
    • data
    )
    Object

    Gets the actual data at a rendered tracking point passed to it. This is overridden in nf-area to account for stacking of data.

    Parameters:

    • renderX Number

      the x domain value the data is rendered at

    • renderY Number

      the y domain value the data is rendered at

    • data Object

      the raw data from the point

    Returns:

    Object:

    simple x, y point structure

    init

    ()

    Initalization method that gets the nf-graph parent and assigns it to graph NOTE: all object that mixin and have init, must call super.init()

    lineFn

    (
    • data
    )
    String private

    The d3 line function to create the line path.

    Parameters:

    • data Array

      the array of coordinate arrays to plot as an SVG path

    Returns:

    String:

    an SVG path data string

    Properties

    d

    String private

    The SVG path data string to render the line

    data

    Array

    Gets or sets the data used by the component to plot itself.

    Default: null

    didTrack

    String

    The action to send on didTrack.

    Default: null

    firstVisibleData

    Object

    The first element from renderedData that is actually visible within the x domain.

    graph

    components.nf-graph

    The parent graph for a component.

    Default: null

    hoverData

    Object an object with the following values: - point: an x, y pair for the exact px coordinates inside the graph-content - graphX: domain x value at mouse position - graphY: domain y value at mouse position - x: nearest x data value - y: nearest y data value - data: nearest raw data - renderX: domain x value to render a tracking dot at (stacked areas are offset) - renderY: domain x value to render a tracking dot at (stacked areas are offset) - mouseX: mouse x position in pixels - mouseY: mouse y position in pixels

    The value of the data that is being tracked by the component, ONLY if the graph-content is currently being hovered.

    Default: null

    interpolator

    String

    The type of D3 interpolator to use to create the line.

    Default: 'linear'

    isSelected

    Unknown deprecated

    Alias of selected

    lastVisibleData

    Object

    The last element from renderedData that is actually visible within the x domain.

    renderedData

    Array

    The list of data points from mixins.graph-data-graphc/mappedData:property that fits within the x domain, plus up to one data point outside of that domain in each direction.

    scaleOffsetX

    Number

    The offset, in pixels, for the x scale

    Default: 0

    scaleOffsetY

    Number

    The offset, in pixels, for the y scale

    Default: 0

    scaleZoomX

    Number

    The zoom multiplier for the x scale

    Default: 1

    scaleZoomY

    Number

    The zoom multiplier for the y scale

    Default: 1

    selectable

    Boolean

    Gets or sets whether or not the graphic is "selectable". Meaning can be "selected" on the nf-graph via some action (usually click). The component will then show up in the nf-graph parent's selected property.

    Default: false

    selected

    Boolean

    Gets or sets whether or not the graphic is selected.

    Default: false

    showTrackingDot

    Boolean

    Gets or sets whether the tracking dot should be shown at all.

    Default: true

    trackedData

    Object an object with the following values: - point: an x, y pair for the exact px coordinates inside the graph-content - graphX: domain x value at mouse position - graphY: domain y value at mouse position - x: nearest x data value - y: nearest y data value - data: nearest raw data - renderX: domain x value to render a tracking dot at (stacked areas are offset) - renderY: domain x value to render a tracking dot at (stacked areas are offset) - mouseX: mouse x position in pixels - mouseY: mouse y position in pixels

    The value of the data that is being tracked by the component.

    Default: null

    trackingDotRadius

    Number

    The radius of the tracking dot in pixels

    Default: 2.5

    trackingMode

    String

    Gets or sets the tracking mode of the component.

    Possible values are:

    • 'none': no tracking behavior
    • 'hover': only track while mouse hover
    • 'snap-last': track while mouse hover, but snap to the last data element when not hovering
    • 'snap-first': track while mouse hover, but snap to the first data element when not hovering
    • 'selected-hover': The same as 'hover' tracking mode, but only when the compononent is selected
    • 'selected-snap-last': The same as 'snap-last' tracking mode, but only when the compononent is selected
    • 'selected-snap-first': The same as 'snap-first' tracking mode, but only when the compononent is selected

    Default: 'none'

    xprop

    String

    The path of the property on each object in data to use as x data to plot on the graph.

    Default: 'x'

    xPropFn

    Function

    The function to get the x value from each data object

    xScale

    d3.scale

    The x scale used by this component

    yprop

    String

    The path of the property on each object in data to use as y data to plot on the graph.

    Default: 'y'

    yPropFn

    Function

    The function to get the y value from each data object

    yScale

    d3.scale

    The y scale used by this component

    ================================================ FILE: docs/classes/components.nf-plot.html ================================================ components.nf-plot - ember-nf-graph

    API Docs for:
    Show:

    components.nf-plot Class

    Plots a group tag on a graph at a given x and y domain coordinate.

    Methods

    _trackedDataChanged

    () private

    Observes changes to tracked data and sends the didTrack action.

    init

    ()

    Initalization method that gets the nf-graph parent and assigns it to graph NOTE: all object that mixin and have init, must call super.init()

    Properties

    didTrack

    String

    The action to send on didTrack.

    Default: null

    graph

    components.nf-graph

    The parent graph for a component.

    Default: null

    hasX

    Boolean

    True if an x value is present (defined, not null and non-empty)

    hasY

    Boolean

    True if an y value is present (defined, not null and non-empty)

    hoverData

    Object an object with the following values: - point: an x, y pair for the exact px coordinates inside the graph-content - graphX: domain x value at mouse position - graphY: domain y value at mouse position - x: nearest x data value - y: nearest y data value - data: nearest raw data - renderX: domain x value to render a tracking dot at (stacked areas are offset) - renderY: domain x value to render a tracking dot at (stacked areas are offset) - mouseX: mouse x position in pixels - mouseY: mouse y position in pixels

    The value of the data that is being tracked by the component, ONLY if the graph-content is currently being hovered.

    Default: null

    isVisible

    Boolean

    The calculated visibility of the component

    rangeX

    Number

    The calculated x coordinate

    rangeY

    Number

    The calculated y coordinate

    scaleOffsetX

    Number

    The offset, in pixels, for the x scale

    Default: 0

    scaleOffsetY

    Number

    The offset, in pixels, for the y scale

    Default: 0

    scaleZoomX

    Number

    The zoom multiplier for the x scale

    Default: 1

    scaleZoomY

    Number

    The zoom multiplier for the y scale

    Default: 1

    showTrackingDot

    Boolean

    Gets or sets whether the tracking dot should be shown at all.

    Default: true

    trackedData

    Object an object with the following values: - point: an x, y pair for the exact px coordinates inside the graph-content - graphX: domain x value at mouse position - graphY: domain y value at mouse position - x: nearest x data value - y: nearest y data value - data: nearest raw data - renderX: domain x value to render a tracking dot at (stacked areas are offset) - renderY: domain x value to render a tracking dot at (stacked areas are offset) - mouseX: mouse x position in pixels - mouseY: mouse y position in pixels

    The value of the data that is being tracked by the component.

    Default: null

    trackingDotRadius

    Number

    The radius of the tracking dot in pixels

    Default: 2.5

    trackingMode

    String

    Gets or sets the tracking mode of the component.

    Possible values are:

    • 'none': no tracking behavior
    • 'hover': only track while mouse hover
    • 'snap-last': track while mouse hover, but snap to the last data element when not hovering
    • 'snap-first': track while mouse hover, but snap to the first data element when not hovering
    • 'selected-hover': The same as 'hover' tracking mode, but only when the compononent is selected
    • 'selected-snap-last': The same as 'snap-last' tracking mode, but only when the compononent is selected
    • 'selected-snap-first': The same as 'snap-first' tracking mode, but only when the compononent is selected

    Default: 'none'

    transform

    String

    The SVG transform of the component's <g> tag.

    x

    Unknown

    The y domain value to set the plot at

    Default: null

    x

    Unknown

    The x domain value to set the plot at

    Default: null

    xScale

    d3.scale

    The x scale used by this component

    yScale

    d3.scale

    The y scale used by this component

    ================================================ FILE: docs/classes/components.nf-range-marker.html ================================================ components.nf-range-marker - ember-nf-graph

    API Docs for:
    Show:

    components.nf-range-marker Class

    Draws a rectangular strip with a templated label on an nf-graph. Should always be used in conjunction with an nf-range-markers container component.

    Methods

    _setup

    () private

    Initialization function that registers the range marker with its parent and populates the container property

    _trackedDataChanged

    () private

    Observes changes to tracked data and sends the didTrack action.

    _unregister

    () private

    Unregisters the range marker from its parent when the range marker is destroyed.

    init

    ()

    Initalization method that gets the nf-graph parent and assigns it to graph NOTE: all object that mixin and have init, must call super.init()

    Properties

    bottom

    Number

    The computed bottom of the range marker, not including the bottom margin.

    container

    components.nf-range-markers

    The parent nf-range-markers component.

    Default: null

    didTrack

    String

    The action to send on didTrack.

    Default: null

    graph

    components.nf-graph

    The parent graph for a component.

    Default: null

    height

    Number

    The height of the range marker.

    Default: 10

    hoverData

    Object an object with the following values: - point: an x, y pair for the exact px coordinates inside the graph-content - graphX: domain x value at mouse position - graphY: domain y value at mouse position - x: nearest x data value - y: nearest y data value - data: nearest raw data - renderX: domain x value to render a tracking dot at (stacked areas are offset) - renderY: domain x value to render a tracking dot at (stacked areas are offset) - mouseX: mouse x position in pixels - mouseY: mouse y position in pixels

    The value of the data that is being tracked by the component, ONLY if the graph-content is currently being hovered.

    Default: null

    labelTransform

    String

    The computed SVG transform fo the range marker label container.

    marginBottom

    Number

    The spacing below the range marker.

    Default: 3

    marginTop

    Number

    The spacing above the range marker.

    Default: 10

    parentController

    Ember.Controller private

    The parent controller to use for template binding

    plotData

    Unknown private

    The model for adding plots to the graph

    scaleOffsetX

    Number

    The offset, in pixels, for the x scale

    Default: 0

    scaleOffsetY

    Number

    The offset, in pixels, for the y scale

    Default: 0

    scaleZoomX

    Number

    The zoom multiplier for the x scale

    Default: 1

    scaleZoomY

    Number

    The zoom multiplier for the y scale

    Default: 1

    showTrackingDot

    Boolean

    Gets or sets whether the tracking dot should be shown at all.

    Default: true

    totalHeight

    Number

    The computed total height of the range marker including its margins.

    trackedData

    Object an object with the following values: - point: an x, y pair for the exact px coordinates inside the graph-content - graphX: domain x value at mouse position - graphY: domain y value at mouse position - x: nearest x data value - y: nearest y data value - data: nearest raw data - renderX: domain x value to render a tracking dot at (stacked areas are offset) - renderY: domain x value to render a tracking dot at (stacked areas are offset) - mouseX: mouse x position in pixels - mouseY: mouse y position in pixels

    The value of the data that is being tracked by the component.

    Default: null

    trackingDotRadius

    Number

    The radius of the tracking dot in pixels

    Default: 2.5

    trackingMode

    String

    Gets or sets the tracking mode of the component.

    Possible values are:

    • 'none': no tracking behavior
    • 'hover': only track while mouse hover
    • 'snap-last': track while mouse hover, but snap to the last data element when not hovering
    • 'snap-first': track while mouse hover, but snap to the first data element when not hovering
    • 'selected-hover': The same as 'hover' tracking mode, but only when the compononent is selected
    • 'selected-snap-last': The same as 'snap-last' tracking mode, but only when the compononent is selected
    • 'selected-snap-first': The same as 'snap-first' tracking mode, but only when the compononent is selected

    Default: 'none'

    transform

    String

    The computed SVG transform of the range marker container

    width

    Number

    The computed width of the range marker.

    x

    Number

    The computed x position of the range marker.

    xMax

    Unknown

    The maximum domain value for the range to mark.

    Default: 0

    xMin

    Unknown

    The minimum domain value for the range to mark.

    Default: 0

    xScale

    d3.scale

    The x scale used by this component

    y

    Number

    The computed y position of the range marker.

    yScale

    d3.scale

    The y scale used by this component

    ================================================ FILE: docs/classes/components.nf-range-markers.html ================================================ components.nf-range-markers - ember-nf-graph

    API Docs for:
    Show:

    components.nf-range-markers Class

    A container and manager for nf-range-marker components. Used to draw an association between nf-range-marker components so they can be laid out in a manner in which they don't collide.

    Methods

    _trackedDataChanged

    () private

    Observes changes to tracked data and sends the didTrack action.

    init

    ()

    Initalization method that gets the nf-graph parent and assigns it to graph NOTE: all object that mixin and have init, must call super.init()

    registerMarker

    (
    • marker
    )

    Adds the passed marker to the markers list, and sets the prevMarker and nextMarker properties on the marker component and it's neighbor.

    Parameters:

    • marker Nf-range-marker

      the range marker to register with this container

    unregisterMarker

    (
    • marker
    )

    Removes the marker from the markers list. Also updates the nextMarker and prevMarker properties of it's neighboring components.

    Parameters:

    • marker Nf-range-marker

      the range marker to remove from the markers list.

    Properties

    didTrack

    String

    The action to send on didTrack.

    Default: null

    graph

    components.nf-graph

    The parent graph for a component.

    Default: null

    hoverData

    Object an object with the following values: - point: an x, y pair for the exact px coordinates inside the graph-content - graphX: domain x value at mouse position - graphY: domain y value at mouse position - x: nearest x data value - y: nearest y data value - data: nearest raw data - renderX: domain x value to render a tracking dot at (stacked areas are offset) - renderY: domain x value to render a tracking dot at (stacked areas are offset) - mouseX: mouse x position in pixels - mouseY: mouse y position in pixels

    The value of the data that is being tracked by the component, ONLY if the graph-content is currently being hovered.

    Default: null

    isRangeMarkerContainer

    Boolean

    Used by nf-range-marker to identify the nf-range-markers container

    Default: true

    markerMargin

    Number

    The margin, in pixels, between the markers

    Default: 10

    markers

    Array

    The marker components registered with this container

    orient

    String

    Sets the orientation of the range markers.

    • 'bottom' - Range markers start at the bottom and stack upward
    • 'top' - Range markers start at the top and stack downward

    Default: 'bottom'

    showTrackingDot

    Boolean

    Gets or sets whether the tracking dot should be shown at all.

    Default: true

    trackedData

    Object an object with the following values: - point: an x, y pair for the exact px coordinates inside the graph-content - graphX: domain x value at mouse position - graphY: domain y value at mouse position - x: nearest x data value - y: nearest y data value - data: nearest raw data - renderX: domain x value to render a tracking dot at (stacked areas are offset) - renderY: domain x value to render a tracking dot at (stacked areas are offset) - mouseX: mouse x position in pixels - mouseY: mouse y position in pixels

    The value of the data that is being tracked by the component.

    Default: null

    trackingDotRadius

    Number

    The radius of the tracking dot in pixels

    Default: 2.5

    trackingMode

    String

    Gets or sets the tracking mode of the component.

    Possible values are:

    • 'none': no tracking behavior
    • 'hover': only track while mouse hover
    • 'snap-last': track while mouse hover, but snap to the last data element when not hovering
    • 'snap-first': track while mouse hover, but snap to the first data element when not hovering
    • 'selected-hover': The same as 'hover' tracking mode, but only when the compononent is selected
    • 'selected-snap-last': The same as 'snap-last' tracking mode, but only when the compononent is selected
    • 'selected-snap-first': The same as 'snap-first' tracking mode, but only when the compononent is selected

    Default: 'none'

    ================================================ FILE: docs/classes/components.nf-right-tick.html ================================================ components.nf-right-tick - ember-nf-graph

    API Docs for:
    Show:

    components.nf-right-tick Class

    Draws a line and a chevron at the specified domain value on the right side of an nf-graph.

    Tips

    • Position outside of nf-graph-content component, but inside nf-graph.
    • Adding paddingRight to nf-graph component will not affect nf-right-tick's position.

    Methods

    _getElements

    () private

    Gets the elements required to do the d3 transitions

    _nonTransitionalUpdate

    () private

    Updates the tick position without a transition.

    _trackedDataChanged

    () private

    Observes changes to tracked data and sends the didTrack action.

    _transitionalUpdate

    () private

    performs the D3 transition to move the tick to the proper position.

    _triggerNonTransitionalUpdate

    () private

    Schedules the update of non-transitional positions

    _triggerTransition

    () private

    Schedules the transition when value changes on on init.

    init

    ()

    Initalization method that gets the nf-graph parent and assigns it to graph NOTE: all object that mixin and have init, must call super.init()

    Properties

    didTrack

    String

    The action to send on didTrack.

    Default: null

    duration

    Number

    The transition duration in milliseconds

    Default: 400

    graph

    components.nf-graph

    The parent graph for a component.

    Default: null

    hoverData

    Object an object with the following values: - point: an x, y pair for the exact px coordinates inside the graph-content - graphX: domain x value at mouse position - graphY: domain y value at mouse position - x: nearest x data value - y: nearest y data value - data: nearest raw data - renderX: domain x value to render a tracking dot at (stacked areas are offset) - renderY: domain x value to render a tracking dot at (stacked areas are offset) - mouseX: mouse x position in pixels - mouseY: mouse y position in pixels

    The value of the data that is being tracked by the component, ONLY if the graph-content is currently being hovered.

    Default: null

    isVisible

    Unknown private

    Sets the visibility of the component. Returns false if y is not a numeric data type.

    scaleOffsetX

    Number

    The offset, in pixels, for the x scale

    Default: 0

    scaleOffsetY

    Number

    The offset, in pixels, for the y scale

    Default: 0

    scaleZoomX

    Number

    The zoom multiplier for the x scale

    Default: 1

    scaleZoomY

    Number

    The zoom multiplier for the y scale

    Default: 1

    showTrackingDot

    Boolean

    Gets or sets whether the tracking dot should be shown at all.

    Default: true

    trackedData

    Object an object with the following values: - point: an x, y pair for the exact px coordinates inside the graph-content - graphX: domain x value at mouse position - graphY: domain y value at mouse position - x: nearest x data value - y: nearest y data value - data: nearest raw data - renderX: domain x value to render a tracking dot at (stacked areas are offset) - renderY: domain x value to render a tracking dot at (stacked areas are offset) - mouseX: mouse x position in pixels - mouseY: mouse y position in pixels

    The value of the data that is being tracked by the component.

    Default: null

    trackingDotRadius

    Number

    The radius of the tracking dot in pixels

    Default: 2.5

    trackingMode

    String

    Gets or sets the tracking mode of the component.

    Possible values are:

    • 'none': no tracking behavior
    • 'hover': only track while mouse hover
    • 'snap-last': track while mouse hover, but snap to the last data element when not hovering
    • 'snap-first': track while mouse hover, but snap to the first data element when not hovering
    • 'selected-hover': The same as 'hover' tracking mode, but only when the compononent is selected
    • 'selected-snap-last': The same as 'snap-last' tracking mode, but only when the compononent is selected
    • 'selected-snap-first': The same as 'snap-first' tracking mode, but only when the compononent is selected

    Default: 'none'

    transform

    String private

    The SVG transform used to render the tick

    value

    Number

    The domain value at which to place the tick

    Default: null

    xScale

    d3.scale

    The x scale used by this component

    y

    Number

    The calculated y coordinate of the tick

    yScale

    d3.scale

    The y scale used by this component

    ================================================ FILE: docs/classes/components.nf-selection-box.html ================================================ components.nf-selection-box - ember-nf-graph

    API Docs for:
    Show:

    components.nf-selection-box Class

    Draws a rectangle on an nf-graph given domain values xMin, xMax, yMin and yMax.

    Methods

    _trackedDataChanged

    () private

    Observes changes to tracked data and sends the didTrack action.

    didInsertElement

    ()

    Sets up the required d3 elements after component is inserted into the DOM

    doUpdatePosition

    ()

    Updates the position of the box with a transition

    init

    ()

    Initalization method that gets the nf-graph parent and assigns it to graph NOTE: all object that mixin and have init, must call super.init()

    updatePosition

    () private

    Schedules an update to the position of the box after render.

    Properties

    didTrack

    String

    The action to send on didTrack.

    Default: null

    duration

    Number

    The duration of the transition in ms

    Default: 400

    graph

    components.nf-graph

    The parent graph for a component.

    Default: null

    hoverData

    Object an object with the following values: - point: an x, y pair for the exact px coordinates inside the graph-content - graphX: domain x value at mouse position - graphY: domain y value at mouse position - x: nearest x data value - y: nearest y data value - data: nearest raw data - renderX: domain x value to render a tracking dot at (stacked areas are offset) - renderY: domain x value to render a tracking dot at (stacked areas are offset) - mouseX: mouse x position in pixels - mouseY: mouse y position in pixels

    The value of the data that is being tracked by the component, ONLY if the graph-content is currently being hovered.

    Default: null

    rectPath

    String

    The SVG path string for the box's rectangle.

    scaleOffsetX

    Number

    The offset, in pixels, for the x scale

    Default: 0

    scaleOffsetY

    Number

    The offset, in pixels, for the y scale

    Default: 0

    scaleZoomX

    Number

    The zoom multiplier for the x scale

    Default: 1

    scaleZoomY

    Number

    The zoom multiplier for the y scale

    Default: 1

    showTrackingDot

    Boolean

    Gets or sets whether the tracking dot should be shown at all.

    Default: true

    trackedData

    Object an object with the following values: - point: an x, y pair for the exact px coordinates inside the graph-content - graphX: domain x value at mouse position - graphY: domain y value at mouse position - x: nearest x data value - y: nearest y data value - data: nearest raw data - renderX: domain x value to render a tracking dot at (stacked areas are offset) - renderY: domain x value to render a tracking dot at (stacked areas are offset) - mouseX: mouse x position in pixels - mouseY: mouse y position in pixels

    The value of the data that is being tracked by the component.

    Default: null

    trackingDotRadius

    Number

    The radius of the tracking dot in pixels

    Default: 2.5

    trackingMode

    String

    Gets or sets the tracking mode of the component.

    Possible values are:

    • 'none': no tracking behavior
    • 'hover': only track while mouse hover
    • 'snap-last': track while mouse hover, but snap to the last data element when not hovering
    • 'snap-first': track while mouse hover, but snap to the first data element when not hovering
    • 'selected-hover': The same as 'hover' tracking mode, but only when the compononent is selected
    • 'selected-snap-last': The same as 'snap-last' tracking mode, but only when the compononent is selected
    • 'selected-snap-first': The same as 'snap-first' tracking mode, but only when the compononent is selected

    Default: 'none'

    x0

    Number

    The x pixel position of xMin

    x1

    Number

    The x pixel position of xMax

    xMax

    Unknown

    The maximum x domain value to encompoass.

    Default: null

    xMin

    Unknown

    The minimum x domain value to encompass.

    Default: null

    xScale

    d3.scale

    The x scale used by this component

    y0

    Number

    The y pixel position of yMin

    y1

    Number

    The y pixel position of yMax

    yMax

    Unknown

    The maximum y domain value to encompass

    Default: null

    yMin

    Unknown

    The minimum y domain value to encompass.

    Default: null

    yScale

    d3.scale

    The y scale used by this component

    ================================================ FILE: docs/classes/components.nf-svg-image.html ================================================ components.nf-svg-image - ember-nf-graph

    API Docs for:
    Show:

    components.nf-svg-image Class

    An image to be displayed in a graph with that takes domain based measurements and uses the scale of the graph. Creates an <image class="nf-image"/> SVG element.

    Methods

    _trackedDataChanged

    () private

    Observes changes to tracked data and sends the didTrack action.

    _updateGraphSelected

    () private

    Makes calls to the parent nf-graph to update it's selected property. Observes changes to selected and also fires on didInsertElement.

    init

    ()

    Initalization method that gets the nf-graph parent and assigns it to graph NOTE: all object that mixin and have init, must call super.init()

    Properties

    didTrack

    String

    The action to send on didTrack.

    Default: null

    graph

    components.nf-graph

    The parent graph for a component.

    Default: null

    height

    Unknown

    The height as a domain value. Does not handle ordinal scales. To set a pixel value, just set svgHeight directly.

    Default: null

    hoverData

    Object an object with the following values: - point: an x, y pair for the exact px coordinates inside the graph-content - graphX: domain x value at mouse position - graphY: domain y value at mouse position - x: nearest x data value - y: nearest y data value - data: nearest raw data - renderX: domain x value to render a tracking dot at (stacked areas are offset) - renderY: domain x value to render a tracking dot at (stacked areas are offset) - mouseX: mouse x position in pixels - mouseY: mouse y position in pixels

    The value of the data that is being tracked by the component, ONLY if the graph-content is currently being hovered.

    Default: null

    isSelected

    Unknown deprecated

    Alias of selected

    scaleOffsetX

    Number

    The offset, in pixels, for the x scale

    Default: 0

    scaleOffsetY

    Number

    The offset, in pixels, for the y scale

    Default: 0

    scaleZoomX

    Number

    The zoom multiplier for the x scale

    Default: 1

    scaleZoomY

    Number

    The zoom multiplier for the y scale

    Default: 1

    selectable

    Boolean

    Gets or sets whether or not the graphic is "selectable". Meaning can be "selected" on the nf-graph via some action (usually click). The component will then show up in the nf-graph parent's selected property.

    Default: false

    selected

    Boolean

    Gets or sets whether or not the graphic is selected.

    Default: false

    showTrackingDot

    Boolean

    Gets or sets whether the tracking dot should be shown at all.

    Default: true

    src

    String

    The image source url

    svgHeight

    Number

    The height, in pixels of the image.

    svgWidth

    Number

    The width, in pixels, of the image.

    svgX

    Number

    The pixel value at which to plot the image.

    svgY

    Number

    The pixel value at which to plot the image.

    trackedData

    Object an object with the following values: - point: an x, y pair for the exact px coordinates inside the graph-content - graphX: domain x value at mouse position - graphY: domain y value at mouse position - x: nearest x data value - y: nearest y data value - data: nearest raw data - renderX: domain x value to render a tracking dot at (stacked areas are offset) - renderY: domain x value to render a tracking dot at (stacked areas are offset) - mouseX: mouse x position in pixels - mouseY: mouse y position in pixels

    The value of the data that is being tracked by the component.

    Default: null

    trackingDotRadius

    Number

    The radius of the tracking dot in pixels

    Default: 2.5

    trackingMode

    String

    Gets or sets the tracking mode of the component.

    Possible values are:

    • 'none': no tracking behavior
    • 'hover': only track while mouse hover
    • 'snap-last': track while mouse hover, but snap to the last data element when not hovering
    • 'snap-first': track while mouse hover, but snap to the first data element when not hovering
    • 'selected-hover': The same as 'hover' tracking mode, but only when the compononent is selected
    • 'selected-snap-last': The same as 'snap-last' tracking mode, but only when the compononent is selected
    • 'selected-snap-first': The same as 'snap-first' tracking mode, but only when the compononent is selected

    Default: 'none'

    width

    Number

    The width as a domain value. Does not handle ordinal scales. To set a pixel value, set svgWidth directly.

    Default: 0

    x

    Unknown

    The domain x value to place the image at.

    Default: null

    xScale

    d3.scale

    The x scale used by this component

    y

    Unknown

    The domain y value to place the image at.

    Default: null

    yScale

    d3.scale

    The y scale used by this component

    ================================================ FILE: docs/classes/components.nf-svg-line.html ================================================ components.nf-svg-line - ember-nf-graph

    API Docs for:
    Show:

    components.nf-svg-line Class

    Draws a basic line between two points on the graph.

    Methods

    _trackedDataChanged

    () private

    Observes changes to tracked data and sends the didTrack action.

    _updateGraphSelected

    () private

    Makes calls to the parent nf-graph to update it's selected property. Observes changes to selected and also fires on didInsertElement.

    init

    ()

    Initalization method that gets the nf-graph parent and assigns it to graph NOTE: all object that mixin and have init, must call super.init()

    Properties

    didTrack

    String

    The action to send on didTrack.

    Default: null

    graph

    components.nf-graph

    The parent graph for a component.

    Default: null

    hoverData

    Object an object with the following values: - point: an x, y pair for the exact px coordinates inside the graph-content - graphX: domain x value at mouse position - graphY: domain y value at mouse position - x: nearest x data value - y: nearest y data value - data: nearest raw data - renderX: domain x value to render a tracking dot at (stacked areas are offset) - renderY: domain x value to render a tracking dot at (stacked areas are offset) - mouseX: mouse x position in pixels - mouseY: mouse y position in pixels

    The value of the data that is being tracked by the component, ONLY if the graph-content is currently being hovered.

    Default: null

    isSelected

    Unknown deprecated

    Alias of selected

    scaleOffsetX

    Number

    The offset, in pixels, for the x scale

    Default: 0

    scaleOffsetY

    Number

    The offset, in pixels, for the y scale

    Default: 0

    scaleZoomX

    Number

    The zoom multiplier for the x scale

    Default: 1

    scaleZoomY

    Number

    The zoom multiplier for the y scale

    Default: 1

    selectable

    Boolean

    Gets or sets whether or not the graphic is "selectable". Meaning can be "selected" on the nf-graph via some action (usually click). The component will then show up in the nf-graph parent's selected property.

    Default: false

    selected

    Boolean

    Gets or sets whether or not the graphic is selected.

    Default: false

    showTrackingDot

    Boolean

    Gets or sets whether the tracking dot should be shown at all.

    Default: true

    svgX1

    Number

    The pixel value to plot the SVGLineElement's x1 at.

    svgX2

    Number

    The pixel value to plot the SVGLineElement's x2 at.

    svgY1

    Number

    The pixel value to plot the SVGLineElement's y1 at.

    svgY2

    Number

    The pixel value to plot the SVGLineElement's y2 at.

    trackedData

    Object an object with the following values: - point: an x, y pair for the exact px coordinates inside the graph-content - graphX: domain x value at mouse position - graphY: domain y value at mouse position - x: nearest x data value - y: nearest y data value - data: nearest raw data - renderX: domain x value to render a tracking dot at (stacked areas are offset) - renderY: domain x value to render a tracking dot at (stacked areas are offset) - mouseX: mouse x position in pixels - mouseY: mouse y position in pixels

    The value of the data that is being tracked by the component.

    Default: null

    trackingDotRadius

    Number

    The radius of the tracking dot in pixels

    Default: 2.5

    trackingMode

    String

    Gets or sets the tracking mode of the component.

    Possible values are:

    • 'none': no tracking behavior
    • 'hover': only track while mouse hover
    • 'snap-last': track while mouse hover, but snap to the last data element when not hovering
    • 'snap-first': track while mouse hover, but snap to the first data element when not hovering
    • 'selected-hover': The same as 'hover' tracking mode, but only when the compononent is selected
    • 'selected-snap-last': The same as 'snap-last' tracking mode, but only when the compononent is selected
    • 'selected-snap-first': The same as 'snap-first' tracking mode, but only when the compononent is selected

    Default: 'none'

    x1

    Unknown

    The domain value to plot the SVGLineElement's x1 at.

    Default: null

    x2

    Unknown

    The domain value to plot the SVGLineElement's x2 at.

    Default: null

    xScale

    d3.scale

    The x scale used by this component

    y1

    Unknown

    The domain value to plot the SVGLineElement's y1 at.

    Default: null

    y2

    Unknown

    The domain value to plot the SVGLineElement's y2 at.

    Default: null

    yScale

    d3.scale

    The y scale used by this component

    ================================================ FILE: docs/classes/components.nf-svg-path.html ================================================ components.nf-svg-path - ember-nf-graph

    API Docs for:
    Show:

    components.nf-svg-path Class

    An SVG path primitive that plots based on a graph's scale.

    Methods

    _trackedDataChanged

    () private

    Observes changes to tracked data and sends the didTrack action.

    _updateGraphSelected

    () private

    Makes calls to the parent nf-graph to update it's selected property. Observes changes to selected and also fires on didInsertElement.

    init

    ()

    Initalization method that gets the nf-graph parent and assigns it to graph NOTE: all object that mixin and have init, must call super.init()

    Properties

    d

    String

    The raw svg path d attribute output

    didTrack

    String

    The action to send on didTrack.

    Default: null

    graph

    components.nf-graph

    The parent graph for a component.

    Default: null

    hoverData

    Object an object with the following values: - point: an x, y pair for the exact px coordinates inside the graph-content - graphX: domain x value at mouse position - graphY: domain y value at mouse position - x: nearest x data value - y: nearest y data value - data: nearest raw data - renderX: domain x value to render a tracking dot at (stacked areas are offset) - renderY: domain x value to render a tracking dot at (stacked areas are offset) - mouseX: mouse x position in pixels - mouseY: mouse y position in pixels

    The value of the data that is being tracked by the component, ONLY if the graph-content is currently being hovered.

    Default: null

    isSelected

    Unknown deprecated

    Alias of selected

    points

    Array

    The array of points to use to plot the path. This is an array of arrays, in the following format:

      // specify path pen commands
                          [
                            [50, 50, 'L'],
                            [100, 100, 'L']
                          ]
                        
                          // or they will default to 'L'
                          [
                            [50, 50],
                            [100, 100]
                          ]

    scaleOffsetX

    Number

    The offset, in pixels, for the x scale

    Default: 0

    scaleOffsetY

    Number

    The offset, in pixels, for the y scale

    Default: 0

    scaleZoomX

    Number

    The zoom multiplier for the x scale

    Default: 1

    scaleZoomY

    Number

    The zoom multiplier for the y scale

    Default: 1

    selectable

    Boolean

    Gets or sets whether or not the graphic is "selectable". Meaning can be "selected" on the nf-graph via some action (usually click). The component will then show up in the nf-graph parent's selected property.

    Default: false

    selected

    Boolean

    Gets or sets whether or not the graphic is selected.

    Default: false

    showTrackingDot

    Boolean

    Gets or sets whether the tracking dot should be shown at all.

    Default: true

    svgPoints

    Array

    The data points mapped to scale

    trackedData

    Object an object with the following values: - point: an x, y pair for the exact px coordinates inside the graph-content - graphX: domain x value at mouse position - graphY: domain y value at mouse position - x: nearest x data value - y: nearest y data value - data: nearest raw data - renderX: domain x value to render a tracking dot at (stacked areas are offset) - renderY: domain x value to render a tracking dot at (stacked areas are offset) - mouseX: mouse x position in pixels - mouseY: mouse y position in pixels

    The value of the data that is being tracked by the component.

    Default: null

    trackingDotRadius

    Number

    The radius of the tracking dot in pixels

    Default: 2.5

    trackingMode

    String

    Gets or sets the tracking mode of the component.

    Possible values are:

    • 'none': no tracking behavior
    • 'hover': only track while mouse hover
    • 'snap-last': track while mouse hover, but snap to the last data element when not hovering
    • 'snap-first': track while mouse hover, but snap to the first data element when not hovering
    • 'selected-hover': The same as 'hover' tracking mode, but only when the compononent is selected
    • 'selected-snap-last': The same as 'snap-last' tracking mode, but only when the compononent is selected
    • 'selected-snap-first': The same as 'snap-first' tracking mode, but only when the compononent is selected

    Default: 'none'

    xScale

    d3.scale

    The x scale used by this component

    yScale

    d3.scale

    The y scale used by this component

    ================================================ FILE: docs/classes/components.nf-svg-rect.html ================================================ components.nf-svg-rect - ember-nf-graph

    API Docs for:
    Show:

    components.nf-svg-rect Class

    A rectangle that plots using domain values from the graph. Uses an SVGPathElement to plot the rectangle, to allow for rectangles with "negative" heights.

    Methods

    _trackedDataChanged

    () private

    Observes changes to tracked data and sends the didTrack action.

    _updateGraphSelected

    () private

    Makes calls to the parent nf-graph to update it's selected property. Observes changes to selected and also fires on didInsertElement.

    click

    ()

    Click event handler. Toggles selected if selectable.

    init

    ()

    Initalization method that gets the nf-graph parent and assigns it to graph NOTE: all object that mixin and have init, must call super.init()

    Properties

    d

    String

    The SVG path data for the rectangle

    didTrack

    String

    The action to send on didTrack.

    Default: null

    graph

    components.nf-graph

    The parent graph for a component.

    Default: null

    height

    Number

    The height as a domain value. If the yScale is ordinal, this value is the indice offset to which to draw the rectangle. For example, if the height is 3 then draw the rectangle to two ordinals passed whatever y is set to.

    Default: 0

    hoverData

    Object an object with the following values: - point: an x, y pair for the exact px coordinates inside the graph-content - graphX: domain x value at mouse position - graphY: domain y value at mouse position - x: nearest x data value - y: nearest y data value - data: nearest raw data - renderX: domain x value to render a tracking dot at (stacked areas are offset) - renderY: domain x value to render a tracking dot at (stacked areas are offset) - mouseX: mouse x position in pixels - mouseY: mouse y position in pixels

    The value of the data that is being tracked by the component, ONLY if the graph-content is currently being hovered.

    Default: null

    isSelected

    Unknown deprecated

    Alias of selected

    scaleOffsetX

    Number

    The offset, in pixels, for the x scale

    Default: 0

    scaleOffsetY

    Number

    The offset, in pixels, for the y scale

    Default: 0

    scaleZoomX

    Number

    The zoom multiplier for the x scale

    Default: 1

    scaleZoomY

    Number

    The zoom multiplier for the y scale

    Default: 1

    selectable

    Boolean

    Gets or sets whether or not the graphic is "selectable". Meaning can be "selected" on the nf-graph via some action (usually click). The component will then show up in the nf-graph parent's selected property.

    Default: false

    selected

    Boolean

    Gets or sets whether or not the graphic is selected.

    Default: false

    showTrackingDot

    Boolean

    Gets or sets whether the tracking dot should be shown at all.

    Default: true

    trackedData

    Object an object with the following values: - point: an x, y pair for the exact px coordinates inside the graph-content - graphX: domain x value at mouse position - graphY: domain y value at mouse position - x: nearest x data value - y: nearest y data value - data: nearest raw data - renderX: domain x value to render a tracking dot at (stacked areas are offset) - renderY: domain x value to render a tracking dot at (stacked areas are offset) - mouseX: mouse x position in pixels - mouseY: mouse y position in pixels

    The value of the data that is being tracked by the component.

    Default: null

    trackingDotRadius

    Number

    The radius of the tracking dot in pixels

    Default: 2.5

    trackingMode

    String

    Gets or sets the tracking mode of the component.

    Possible values are:

    • 'none': no tracking behavior
    • 'hover': only track while mouse hover
    • 'snap-last': track while mouse hover, but snap to the last data element when not hovering
    • 'snap-first': track while mouse hover, but snap to the first data element when not hovering
    • 'selected-hover': The same as 'hover' tracking mode, but only when the compononent is selected
    • 'selected-snap-last': The same as 'snap-last' tracking mode, but only when the compononent is selected
    • 'selected-snap-first': The same as 'snap-first' tracking mode, but only when the compononent is selected

    Default: 'none'

    width

    Number

    The width as a domain value. If xScale is ordinal, then this value is the indice offset to which to draw the rectangle. In other words, if it's 2, then draw the rectangle to two ordinals past whatever x is set to.

    Default: 0

    x

    Unknown

    The domain x value to place the rect at.

    Default: null

    x0

    Number

    The x value of the top right corner of the rectangle

    x1

    Number

    The x value of the bottom right corner of the rectangle.

    xScale

    d3.scale

    The x scale used by this component

    y

    Unknown

    The domain y value to place the rect at.

    Default: null

    y0

    Number

    The y value of the top right corner of the rectangle.

    y1

    Number

    The y value of the bottom right corner of the rectangle

    yScale

    d3.scale

    The y scale used by this component

    ================================================ FILE: docs/classes/components.nf-tracker.html ================================================ components.nf-tracker - ember-nf-graph

    API Docs for:
    Show:

    components.nf-tracker Class

    A tracking graphic component used to do things like create tracking dots for nf-area or nf-line.

    Methods

    _trackedDataChanged

    () private

    Observes changes to tracked data and sends the didTrack action.

    getActualTrackData

    (
    • renderX
    • renderY
    • data
    )
    Object

    Gets the actual data at a rendered tracking point passed to it. This is overridden in nf-area to account for stacking of data.

    Parameters:

    • renderX Number

      the x domain value the data is rendered at

    • renderY Number

      the y domain value the data is rendered at

    • data Object

      the raw data from the point

    Returns:

    Object:

    simple x, y point structure

    init

    ()

    Initalization method that gets the nf-graph parent and assigns it to graph NOTE: all object that mixin and have init, must call super.init()

    Properties

    data

    Array

    Gets or sets the data used by the component to plot itself.

    Default: null

    didTrack

    String

    The action to send on didTrack.

    Default: null

    firstVisibleData

    Object

    The first element from renderedData that is actually visible within the x domain.

    graph

    components.nf-graph

    The parent graph for a component.

    Default: null

    hoverData

    Object an object with the following values: - point: an x, y pair for the exact px coordinates inside the graph-content - graphX: domain x value at mouse position - graphY: domain y value at mouse position - x: nearest x data value - y: nearest y data value - data: nearest raw data - renderX: domain x value to render a tracking dot at (stacked areas are offset) - renderY: domain x value to render a tracking dot at (stacked areas are offset) - mouseX: mouse x position in pixels - mouseY: mouse y position in pixels

    The value of the data that is being tracked by the component, ONLY if the graph-content is currently being hovered.

    Default: null

    lastVisibleData

    Object

    The last element from renderedData that is actually visible within the x domain.

    renderedData

    Array

    The list of data points from mixins.graph-data-graphc/mappedData:property that fits within the x domain, plus up to one data point outside of that domain in each direction.

    scaleOffsetX

    Number

    The offset, in pixels, for the x scale

    Default: 0

    scaleOffsetY

    Number

    The offset, in pixels, for the y scale

    Default: 0

    scaleZoomX

    Number

    The zoom multiplier for the x scale

    Default: 1

    scaleZoomY

    Number

    The zoom multiplier for the y scale

    Default: 1

    showTrackingDot

    Boolean

    Gets or sets whether the tracking dot should be shown at all.

    Default: true

    trackedData

    Object an object with the following values: - point: an x, y pair for the exact px coordinates inside the graph-content - graphX: domain x value at mouse position - graphY: domain y value at mouse position - x: nearest x data value - y: nearest y data value - data: nearest raw data - renderX: domain x value to render a tracking dot at (stacked areas are offset) - renderY: domain x value to render a tracking dot at (stacked areas are offset) - mouseX: mouse x position in pixels - mouseY: mouse y position in pixels

    The value of the data that is being tracked by the component.

    Default: null

    trackingDotRadius

    Number

    The radius of the tracking dot in pixels

    Default: 2.5

    trackingMode

    String

    Gets or sets the tracking mode of the component.

    Possible values are:

    • 'none': no tracking behavior
    • 'hover': only track while mouse hover
    • 'snap-last': track while mouse hover, but snap to the last data element when not hovering
    • 'snap-first': track while mouse hover, but snap to the first data element when not hovering
    • 'selected-hover': The same as 'hover' tracking mode, but only when the compononent is selected
    • 'selected-snap-last': The same as 'snap-last' tracking mode, but only when the compononent is selected
    • 'selected-snap-first': The same as 'snap-first' tracking mode, but only when the compononent is selected

    Default: 'none'

    xprop

    String

    The path of the property on each object in data to use as x data to plot on the graph.

    Default: 'x'

    xPropFn

    Function

    The function to get the x value from each data object

    xScale

    d3.scale

    The x scale used by this component

    yprop

    String

    The path of the property on each object in data to use as y data to plot on the graph.

    Default: 'y'

    yPropFn

    Function

    The function to get the y value from each data object

    yScale

    d3.scale

    The y scale used by this component

    ================================================ FILE: docs/classes/components.nf-vertical-line.html ================================================ components.nf-vertical-line - ember-nf-graph

    API Docs for:
    Show:

    components.nf-vertical-line Class

    Draws a vertical line on a graph at a given x domain value

    Methods

    _trackedDataChanged

    () private

    Observes changes to tracked data and sends the didTrack action.

    init

    ()

    Initalization method that gets the nf-graph parent and assigns it to graph NOTE: all object that mixin and have init, must call super.init()

    Properties

    didTrack

    String

    The action to send on didTrack.

    Default: null

    graph

    components.nf-graph

    The parent graph for a component.

    Default: null

    hoverData

    Object an object with the following values: - point: an x, y pair for the exact px coordinates inside the graph-content - graphX: domain x value at mouse position - graphY: domain y value at mouse position - x: nearest x data value - y: nearest y data value - data: nearest raw data - renderX: domain x value to render a tracking dot at (stacked areas are offset) - renderY: domain x value to render a tracking dot at (stacked areas are offset) - mouseX: mouse x position in pixels - mouseY: mouse y position in pixels

    The value of the data that is being tracked by the component, ONLY if the graph-content is currently being hovered.

    Default: null

    lineX

    Number private

    The calculated x coordinate of the vertical line

    scaleOffsetX

    Number

    The offset, in pixels, for the x scale

    Default: 0

    scaleOffsetY

    Number

    The offset, in pixels, for the y scale

    Default: 0

    scaleZoomX

    Number

    The zoom multiplier for the x scale

    Default: 1

    scaleZoomY

    Number

    The zoom multiplier for the y scale

    Default: 1

    showTrackingDot

    Boolean

    Gets or sets whether the tracking dot should be shown at all.

    Default: true

    trackedData

    Object an object with the following values: - point: an x, y pair for the exact px coordinates inside the graph-content - graphX: domain x value at mouse position - graphY: domain y value at mouse position - x: nearest x data value - y: nearest y data value - data: nearest raw data - renderX: domain x value to render a tracking dot at (stacked areas are offset) - renderY: domain x value to render a tracking dot at (stacked areas are offset) - mouseX: mouse x position in pixels - mouseY: mouse y position in pixels

    The value of the data that is being tracked by the component.

    Default: null

    trackingDotRadius

    Number

    The radius of the tracking dot in pixels

    Default: 2.5

    trackingMode

    String

    Gets or sets the tracking mode of the component.

    Possible values are:

    • 'none': no tracking behavior
    • 'hover': only track while mouse hover
    • 'snap-last': track while mouse hover, but snap to the last data element when not hovering
    • 'snap-first': track while mouse hover, but snap to the first data element when not hovering
    • 'selected-hover': The same as 'hover' tracking mode, but only when the compononent is selected
    • 'selected-snap-last': The same as 'snap-last' tracking mode, but only when the compononent is selected
    • 'selected-snap-first': The same as 'snap-first' tracking mode, but only when the compononent is selected

    Default: 'none'

    x

    Number

    The x domain value at which to draw the vertical line on the graph

    Default: null

    xScale

    d3.scale

    The x scale used by this component

    y1

    Number private

    The top y coordinate of the line

    Default: 0

    y2

    Number private

    The bottom y coordinate of the line

    yScale

    d3.scale

    The y scale used by this component

    ================================================ FILE: docs/classes/components.nf-x-axis.html ================================================ components.nf-x-axis - ember-nf-graph

    API Docs for:
    Show:

    components.nf-x-axis Class

    A component for adding a templated x axis to an nf-graph component. All items contained within this component are used to template each tick mark on the rendered graph. Tick values are supplied to the inner scope of this component on the view template via tick.

    Styling

    The main container will have a nf-x-axis class. A orient-top or orient-bottom container will be applied to the container depending on the orient setting.

    Ticks are positioned via a <g> tag, that will contain whatever is passed into it via templating, along with the tick line. <text> tags within tick templates do have some default styling applied to them to position them appropriately based off of orientation.

    Example

      {{#nf-graph width=500 height=300}}
        {{#nf-x-axis height=40 as |tick|}}
          <text>x is {{tick.value}}</text>
        {{/nf-x-axis}}
      {{/nf-graph}}

    Methods

    _trackedDataChanged

    () private

    Observes changes to tracked data and sends the didTrack action.

    init

    ()

    Initalization method that gets the nf-graph parent and assigns it to graph NOTE: all object that mixin and have init, must call super.init()

    Properties

    axisLineY

    Number

    The y position, in pixels, of the axis line

    didTrack

    String

    The action to send on didTrack.

    Default: null

    graph

    components.nf-graph

    The parent graph for a component.

    Default: null

    height

    Number

    The height of the x axis in pixels.

    Default: 20

    hoverData

    Object an object with the following values: - point: an x, y pair for the exact px coordinates inside the graph-content - graphX: domain x value at mouse position - graphY: domain y value at mouse position - x: nearest x data value - y: nearest y data value - data: nearest raw data - renderX: domain x value to render a tracking dot at (stacked areas are offset) - renderY: domain x value to render a tracking dot at (stacked areas are offset) - mouseX: mouse x position in pixels - mouseY: mouse y position in pixels

    The value of the data that is being tracked by the component, ONLY if the graph-content is currently being hovered.

    Default: null

    orient

    String

    The orientation of the x axis. Value can be 'top' or 'bottom'.

    Default: 'bottom'

    orientClass

    String

    The class applied due to orientation (e.g. 'orient-top')

    scaleOffsetX

    Number

    The offset, in pixels, for the x scale

    Default: 0

    scaleOffsetY

    Number

    The offset, in pixels, for the y scale

    Default: 0

    scaleZoomX

    Number

    The zoom multiplier for the x scale

    Default: 1

    scaleZoomY

    Number

    The zoom multiplier for the y scale

    Default: 1

    showTrackingDot

    Boolean

    Gets or sets whether the tracking dot should be shown at all.

    Default: true

    tickCount

    Number

    The number of ticks to display

    Default: 12

    tickFactory

    Function

    A method to call to override the default behavior of how ticks are created.

    The function signature should match:

      // - scale: d3.Scale
                          // - tickCount: number of ticks
                          // - uniqueData: unique data points for the axis
                          // - scaleType: string of "linear" or "ordinal"
                          // returns: an array of tick values.
                          function(scale, tickCount, uniqueData, scaleType) {
                            return [100,200,300];
                          }

    Default: null

    tickFilter

    Function

    An optional filtering function to allow more control over what tick marks are displayed. The function should have exactly the same signature as the function you'd use for an Array.prototype.filter().

    Default: null

    Example:

      {{#nf-x-axis tickFilter=myFilter as |tick|}}
                            <text>{{tick.value}}</text>
                          {{/nf-x-axis}}
                        

    And on your controller:

      myFilter: function(tick, index, ticks) {
                            return tick.value < 1000;
                          },
                        

    The above example will filter down the set of ticks to only those that are less than 1000.

    tickLength

    Number

    The length of the tick line (the small vertical line indicating the tick)

    Default: 0

    tickPadding

    Number

    The spacing between the end of the tick line and the origin of the templated tick content

    Default: 5

    ticks

    Array

    The models for the ticks to display on the axis.

    trackedData

    Object an object with the following values: - point: an x, y pair for the exact px coordinates inside the graph-content - graphX: domain x value at mouse position - graphY: domain y value at mouse position - x: nearest x data value - y: nearest y data value - data: nearest raw data - renderX: domain x value to render a tracking dot at (stacked areas are offset) - renderY: domain x value to render a tracking dot at (stacked areas are offset) - mouseX: mouse x position in pixels - mouseY: mouse y position in pixels

    The value of the data that is being tracked by the component.

    Default: null

    trackingDotRadius

    Number

    The radius of the tracking dot in pixels

    Default: 2.5

    trackingMode

    String

    Gets or sets the tracking mode of the component.

    Possible values are:

    • 'none': no tracking behavior
    • 'hover': only track while mouse hover
    • 'snap-last': track while mouse hover, but snap to the last data element when not hovering
    • 'snap-first': track while mouse hover, but snap to the first data element when not hovering
    • 'selected-hover': The same as 'hover' tracking mode, but only when the compononent is selected
    • 'selected-snap-last': The same as 'snap-last' tracking mode, but only when the compononent is selected
    • 'selected-snap-first': The same as 'snap-first' tracking mode, but only when the compononent is selected

    Default: 'none'

    transform

    String

    The SVG Transform applied to this component's container.

    uniqueXData

    Array

    A unique set of all x data on the graph

    width

    Number

    The width of the component

    x

    Number

    This x position of this component's container

    xScale

    d3.scale

    The x scale used by this component

    y

    Number

    The y position of this component's container.

    yScale

    d3.scale

    The y scale used by this component

    ================================================ FILE: docs/classes/components.nf-y-axis.html ================================================ components.nf-y-axis - ember-nf-graph

    API Docs for:
    Show:

    components.nf-y-axis Class

    A component for adding a templated y axis to an nf-graph component. All items contained within this component are used to template each tick mark on the rendered graph. Tick values are supplied to the inner scope of this component on the view template via tick.

    Styling

    The main container will have a nf-y-axis class. A orient-left or orient-right container will be applied to the container depending on the orient setting.

    Ticks are positioned via a <g> tag, that will contain whatever is passed into it via templating, along with the tick line. <text> tags within tick templates do have some default styling applied to them to position them appropriately based off of orientation.

    Example

      {{#nf-graph width=500 height=300}}
        {{#nf-y-axis width=40 as |tick|}}
          <text>y is {{tick.value}}</text>
        {{/nf-y-axis}}
      {{/nf-graph}}

    Methods

    _trackedDataChanged

    () private

    Observes changes to tracked data and sends the didTrack action.

    init

    ()

    Initalization method that gets the nf-graph parent and assigns it to graph NOTE: all object that mixin and have init, must call super.init()

    Properties

    axisLineX

    Number

    The x position of the axis line.

    didTrack

    String

    The action to send on didTrack.

    Default: null

    graph

    components.nf-graph

    The parent graph for a component.

    Default: null

    height

    Number

    the height of the component

    hoverData

    Object an object with the following values: - point: an x, y pair for the exact px coordinates inside the graph-content - graphX: domain x value at mouse position - graphY: domain y value at mouse position - x: nearest x data value - y: nearest y data value - data: nearest raw data - renderX: domain x value to render a tracking dot at (stacked areas are offset) - renderY: domain x value to render a tracking dot at (stacked areas are offset) - mouseX: mouse x position in pixels - mouseY: mouse y position in pixels

    The value of the data that is being tracked by the component, ONLY if the graph-content is currently being hovered.

    Default: null

    isOrientRight

    Boolean

    computed property. returns true if orient is equal to 'right'.

    orient

    String

    The orientation of the y axis. Possible values are 'left' and 'right'

    Default: 'left'

    scaleOffsetX

    Number

    The offset, in pixels, for the x scale

    Default: 0

    scaleOffsetY

    Number

    The offset, in pixels, for the y scale

    Default: 0

    scaleZoomX

    Number

    The zoom multiplier for the x scale

    Default: 1

    scaleZoomY

    Number

    The zoom multiplier for the y scale

    Default: 1

    showTrackingDot

    Boolean

    Gets or sets whether the tracking dot should be shown at all.

    Default: true

    tickCount

    Number

    The number of ticks to display

    Default: 5

    tickFactory

    Function

    A method to call to override the default behavior of how ticks are created.

    The function signature should match:

      // - scale: d3.Scale
                          // - tickCount: number of ticks
                          // - uniqueData: unique data points for the axis
                          // - scaleType: string of "linear" or "ordinal"
                          // returns: an array of tick values.
                          function(scale, tickCount, uniqueData, scaleType) {
                            return [100,200,300];
                          }

    Default: null

    tickFilter

    Function

    An optional filtering function to allow more control over what tick marks are displayed. The function should have exactly the same signature as the function you'd use for an Array.prototype.filter().

    Default: null

    Example:

      {{#nf-y-axis tickFilter=myFilter as |tick|}}
                            <text>{{tick.value}}</text>
                          {{/nf-y-axis}}
                        

    And on your controller:

      myFilter: function(tick, index, ticks) {
                            return tick.value < 1000;
                          },
                        

    The above example will filter down the set of ticks to only those that are less than 1000.

    tickLength

    Number

    The length of the tick's accompanying line.

    Default: 5

    tickPadding

    Number

    The distance between the tick line and the origin tick's templated output

    Default: 3

    ticks

    Array

    The ticks to be displayed.

    trackedData

    Object an object with the following values: - point: an x, y pair for the exact px coordinates inside the graph-content - graphX: domain x value at mouse position - graphY: domain y value at mouse position - x: nearest x data value - y: nearest y data value - data: nearest raw data - renderX: domain x value to render a tracking dot at (stacked areas are offset) - renderY: domain x value to render a tracking dot at (stacked areas are offset) - mouseX: mouse x position in pixels - mouseY: mouse y position in pixels

    The value of the data that is being tracked by the component.

    Default: null

    trackingDotRadius

    Number

    The radius of the tracking dot in pixels

    Default: 2.5

    trackingMode

    String

    Gets or sets the tracking mode of the component.

    Possible values are:

    • 'none': no tracking behavior
    • 'hover': only track while mouse hover
    • 'snap-last': track while mouse hover, but snap to the last data element when not hovering
    • 'snap-first': track while mouse hover, but snap to the first data element when not hovering
    • 'selected-hover': The same as 'hover' tracking mode, but only when the compononent is selected
    • 'selected-snap-last': The same as 'snap-last' tracking mode, but only when the compononent is selected
    • 'selected-snap-first': The same as 'snap-first' tracking mode, but only when the compononent is selected

    Default: 'none'

    transform

    String

    The SVG transform for positioning the component.

    uniqueYData

    Array

    All y data from the graph, filtered to unique values.

    width

    Number

    The total width of the y axis

    Default: 40

    x

    Number

    The x position of the component

    xScale

    d3.scale

    The x scale used by this component

    y

    Number

    The y position of the component

    yScale

    d3.scale

    The y scale used by this component

    ================================================ FILE: docs/classes/components.nf-y-diff.html ================================================ components.nf-y-diff - ember-nf-graph

    API Docs for:
    Show:

    components.nf-y-diff Class

    Draws a box underneath (or over) the y axis to between the given a and b domain values. Component content is used to template a label in that box.

    Tips

    • Should be outside of nf-graph-content.
    • Should be "above" nf-y-axis in the markup.
    • As a convenience, <text> elements will automatically be positioned based on y-axis orientation due to default styling.

    Methods

    _trackedDataChanged

    () private

    Observes changes to tracked data and sends the didTrack action.

    adjustWidth

    ()

    Schedules a call to doAdjustWidth on afterRender

    didInsertElement

    ()

    Sets up the d3 related elements when component is inserted into the DOM

    doAdjustWidth

    ()

    Updates to d3 managed DOM elments that do not require transitioning, because they're width-related.

    doTransition

    ()

    Performs the transition (animation) of the elements.

    init

    ()

    Initalization method that gets the nf-graph parent and assigns it to graph NOTE: all object that mixin and have init, must call super.init()

    transition

    ()

    Schedules a transition once at afterRender.

    Properties

    a

    Number

    The starting domain value of the difference measurement. The subrahend of the difference calculation.

    Default: null

    b

    Number

    The ending domain value of the difference measurement. The minuend of the difference calculation.

    Default: null

    contentPadding

    Number

    The amount of padding, in pixels, between the edge of the difference "box" and the content container

    Default: 5

    contentTransform

    String private

    The SVG transformation used to position the content container.

    contentX

    Number

    The x pixel coordinate of the content container.

    didTrack

    String

    The action to send on didTrack.

    Default: null

    diff

    Number

    The calculated difference between a and b.

    duration

    Number

    The duration of the transition, in milliseconds, as the difference slides vertically

    Default: 400

    graph

    components.nf-graph

    The parent graph for a component.

    Default: null

    hoverData

    Object an object with the following values: - point: an x, y pair for the exact px coordinates inside the graph-content - graphX: domain x value at mouse position - graphY: domain y value at mouse position - x: nearest x data value - y: nearest y data value - data: nearest raw data - renderX: domain x value to render a tracking dot at (stacked areas are offset) - renderY: domain x value to render a tracking dot at (stacked areas are offset) - mouseX: mouse x position in pixels - mouseY: mouse y position in pixels

    The value of the data that is being tracked by the component, ONLY if the graph-content is currently being hovered.

    Default: null

    isOrientRight

    Boolean

    Returns true if the graph's y-axis component is configured to orient right.

    isPositive

    Boolean

    Returns true if diff is a positive number

    parentController

    Ember.Controller private

    The view controller for the view this component is present in

    scaleOffsetX

    Number

    The offset, in pixels, for the x scale

    Default: 0

    scaleOffsetY

    Number

    The offset, in pixels, for the y scale

    Default: 0

    scaleZoomX

    Number

    The zoom multiplier for the x scale

    Default: 1

    scaleZoomY

    Number

    The zoom multiplier for the y scale

    Default: 1

    showTrackingDot

    Boolean

    Gets or sets whether the tracking dot should be shown at all.

    Default: true

    trackedData

    Object an object with the following values: - point: an x, y pair for the exact px coordinates inside the graph-content - graphX: domain x value at mouse position - graphY: domain y value at mouse position - x: nearest x data value - y: nearest y data value - data: nearest raw data - renderX: domain x value to render a tracking dot at (stacked areas are offset) - renderY: domain x value to render a tracking dot at (stacked areas are offset) - mouseX: mouse x position in pixels - mouseY: mouse y position in pixels

    The value of the data that is being tracked by the component.

    Default: null

    trackingDotRadius

    Number

    The radius of the tracking dot in pixels

    Default: 2.5

    trackingMode

    String

    Gets or sets the tracking mode of the component.

    Possible values are:

    • 'none': no tracking behavior
    • 'hover': only track while mouse hover
    • 'snap-last': track while mouse hover, but snap to the last data element when not hovering
    • 'snap-first': track while mouse hover, but snap to the first data element when not hovering
    • 'selected-hover': The same as 'hover' tracking mode, but only when the compononent is selected
    • 'selected-snap-last': The same as 'snap-last' tracking mode, but only when the compononent is selected
    • 'selected-snap-first': The same as 'snap-first' tracking mode, but only when the compononent is selected

    Default: 'none'

    transform

    String private

    The SVG transformation of the component.

    width

    Number

    The width of the difference box

    xScale

    d3.scale

    The x scale used by this component

    yA

    Number

    The y pixel value of a.

    yB

    Number

    The y pixel value of b.

    yCenter

    Number

    The calculated vertical center of the difference box, in pixels.

    yScale

    d3.scale

    The y scale used by this component

    ================================================ FILE: docs/classes/index.html ================================================ Redirector Click here to redirect ================================================ FILE: docs/classes/mixins.graph-area-utils.html ================================================ mixins.graph-area-utils - ember-nf-graph

    API Docs for:
    Show:

    mixins.graph-area-utils Class

    Extends Ember.Mixin
    Module: utils/nf/array-helpers

    Utility functions for drawing an area.

    Item Index

    Methods

    Methods

    createAreaFn

    (
    • xScale
    • yScale
    • interpolator
    )
    Function

    Creates a d3 area function from a given set of scales and an interpolator

    Parameters:

    • xScale Function

      a d3 scale

    • yScale Function

      a d3 scale

    • interpolator String

      the name of the d3 interpolator to use.

    Returns:

    Function:

    a function that when called will create SVG path data.

    ================================================ FILE: docs/classes/mixins.graph-data-graphic.html ================================================ mixins.graph-data-graphic - ember-nf-graph

    API Docs for:
    Show:

    mixins.graph-data-graphic Class

    Extends Ember.Mixin
    Module: utils/nf/array-helpers

    This is mixed in to child components that need to register data with the graph. Includes methods for extracting, sorting and scrubbing data for use in graphing components.

    Requires mixins.graph-registered-graphic and mixins.graph-has-graph-parent

    Methods

    getActualTrackData

    (
    • renderX
    • renderY
    • data
    )
    Object

    Gets the actual data at a rendered tracking point passed to it. This is overridden in nf-area to account for stacking of data.

    Parameters:

    • renderX Number

      the x domain value the data is rendered at

    • renderY Number

      the y domain value the data is rendered at

    • data Object

      the raw data from the point

    Returns:

    Object:

    simple x, y point structure

    Properties

    data

    Array

    Gets or sets the data used by the component to plot itself.

    Default: null

    firstVisibleData

    Object

    The first element from renderedData that is actually visible within the x domain.

    lastVisibleData

    Object

    The last element from renderedData that is actually visible within the x domain.

    renderedData

    Array

    The list of data points from mixins.graph-data-graphc/mappedData:property that fits within the x domain, plus up to one data point outside of that domain in each direction.

    xprop

    String

    The path of the property on each object in data to use as x data to plot on the graph.

    Default: 'x'

    xPropFn

    Function

    The function to get the x value from each data object

    yprop

    String

    The path of the property on each object in data to use as y data to plot on the graph.

    Default: 'y'

    yPropFn

    Function

    The function to get the y value from each data object

    ================================================ FILE: docs/classes/mixins.graph-has-graph-parent.html ================================================ mixins.graph-has-graph-parent - ember-nf-graph

    API Docs for:
    Show:

    mixins.graph-has-graph-parent Class

    Adds initialization code to graph the nf-graph parent to a component that is to be contained in an nf-graph.

    Methods

    _trackedDataChanged

    () private

    Observes changes to tracked data and sends the didTrack action.

    init

    ()

    Initalization method that gets the nf-graph parent and assigns it to graph NOTE: all object that mixin and have init, must call super.init()

    Properties

    didTrack

    String

    The action to send on didTrack.

    Default: null

    graph

    components.nf-graph

    The parent graph for a component.

    Default: null

    hoverData

    Object an object with the following values: - point: an x, y pair for the exact px coordinates inside the graph-content - graphX: domain x value at mouse position - graphY: domain y value at mouse position - x: nearest x data value - y: nearest y data value - data: nearest raw data - renderX: domain x value to render a tracking dot at (stacked areas are offset) - renderY: domain x value to render a tracking dot at (stacked areas are offset) - mouseX: mouse x position in pixels - mouseY: mouse y position in pixels

    The value of the data that is being tracked by the component, ONLY if the graph-content is currently being hovered.

    Default: null

    showTrackingDot

    Boolean

    Gets or sets whether the tracking dot should be shown at all.

    Default: true

    trackedData

    Object an object with the following values: - point: an x, y pair for the exact px coordinates inside the graph-content - graphX: domain x value at mouse position - graphY: domain y value at mouse position - x: nearest x data value - y: nearest y data value - data: nearest raw data - renderX: domain x value to render a tracking dot at (stacked areas are offset) - renderY: domain x value to render a tracking dot at (stacked areas are offset) - mouseX: mouse x position in pixels - mouseY: mouse y position in pixels

    The value of the data that is being tracked by the component.

    Default: null

    trackingDotRadius

    Number

    The radius of the tracking dot in pixels

    Default: 2.5

    trackingMode

    String

    Gets or sets the tracking mode of the component.

    Possible values are:

    • 'none': no tracking behavior
    • 'hover': only track while mouse hover
    • 'snap-last': track while mouse hover, but snap to the last data element when not hovering
    • 'snap-first': track while mouse hover, but snap to the first data element when not hovering
    • 'selected-hover': The same as 'hover' tracking mode, but only when the compononent is selected
    • 'selected-snap-last': The same as 'snap-last' tracking mode, but only when the compononent is selected
    • 'selected-snap-first': The same as 'snap-first' tracking mode, but only when the compononent is selected

    Default: 'none'

    ================================================ FILE: docs/classes/mixins.graph-line-utils.html ================================================ mixins.graph-line-utils - ember-nf-graph

    API Docs for:
    Show:

    mixins.graph-line-utils Class

    Extends Ember.Mixin
    Module: utils/nf/array-helpers

    Item Index

    Methods

    Methods

    createLineFn

    (
    • xScale
    • yScale
    • interpolate
    )
    Function

    Create a d3 line function from a given scales and interpolation

    Parameters:

    • xScale Function

      d3 scale function

    • yScale Function

      d3 scale function

    • interpolate String

      d3 interpolator name

    Returns:

    Function:

    a d3 function that will create SVG path data from a given data set.

    ================================================ FILE: docs/classes/mixins.graph-registered-graphic.html ================================================ mixins.graph-registered-graphic - ember-nf-graph ================================================ FILE: docs/classes/mixins.graph-requires-scale-source.html ================================================ mixins.graph-requires-scale-source - ember-nf-graph

    API Docs for:
    Show:

    mixins.graph-requires-scale-source Class

    Adds functionality to identify a parent control that will provide an x and y scale, then adds scaling properties to the component it's mixed in to.

    Properties

    scaleOffsetX

    Number

    The offset, in pixels, for the x scale

    Default: 0

    scaleOffsetY

    Number

    The offset, in pixels, for the y scale

    Default: 0

    scaleZoomX

    Number

    The zoom multiplier for the x scale

    Default: 1

    scaleZoomY

    Number

    The zoom multiplier for the y scale

    Default: 1

    xScale

    d3.scale

    The x scale used by this component

    yScale

    d3.scale

    The y scale used by this component

    ================================================ FILE: docs/classes/mixins.graph-selectable-graphic.html ================================================ mixins.graph-selectable-graphic - ember-nf-graph

    API Docs for:
    Show:

    mixins.graph-selectable-graphic Class

    Extends Ember.Mixin
    Module: utils/nf/array-helpers

    Adds functionality to a component to make it a selectable graphic within it's parent nf-graph.

    Item Index

    Properties

    Methods

    _updateGraphSelected

    () private

    Makes calls to the parent nf-graph to update it's selected property. Observes changes to selected and also fires on didInsertElement.

    Properties

    isSelected

    Unknown deprecated

    Defined in addon/mixins/graph-selectable-graphic.js:31

    Deprecated: use `selected`

    Alias of selected

    selectable

    Boolean

    Gets or sets whether or not the graphic is "selectable". Meaning can be "selected" on the nf-graph via some action (usually click). The component will then show up in the nf-graph parent's selected property.

    Default: false

    selected

    Boolean

    Gets or sets whether or not the graphic is selected.

    Default: false

    ================================================ FILE: docs/classes/utils.nf.graph-event.html ================================================ utils.nf.graph-event - ember-nf-graph

    API Docs for:
    Show:

    utils.nf.graph-event Class

    Extends Graph-position
    Module: utils/nf/array-helpers

    Event object for graph events

    Methods

    identity

    (
    • x
    )
    Any private

    returns whatever you pass into it.

    Parameters:

    • x Any

    Returns:

    Any:

    x

    natualSort

    (
    • arr
    )

    Sorts the array "naturally". Meaning taking into account both alphabetical and numeric sorting within strings.

    Parameters:

    • arr Array

      the array to sort

    naturalCompare

    (
    • a
    • b
    )
    Number

    A JavaScript sorting predicate for natural sorting.

    Parameters:

    • a Any

      the value to compare to b

    • b Any

      the value to compare to a

    Returns:

    Number:

    -1, 0 or 1 if a is less than, equal to, or greater than b, respectively.

    naturalTokenize

    (
    • item
    )
    Array private

    breaks a string into an array of tokens in preparation for natural comparison and sorting.

    Parameters:

    • item String

      the value to tokenize

    Returns:

    Array:

    an array of tokens found in the item

    nearestIndexTo

    (
    • arr
    • val
    • mappingFn
    )

    Performs a binary search on the array and finds the nearest index to the value passed.

    Parameters:

    • arr Array

      the sorted array to search.

    • val Number

      the value to find the nearest index to.

    • mappingFn Function

      an optional function for pulling values out of the array items.

    Properties

    data

    Any

    A data value passed with the event

    Default: null

    originalEvent

    Event

    The original event that triggered this event or action

    Default: null

    ================================================ FILE: docs/classes/utils.nf.graph-mouse-event.html ================================================ utils.nf.graph-mouse-event - ember-nf-graph

    API Docs for:
    Show:

    utils.nf.graph-mouse-event Class

    Extends Graph-position
    Module: utils/nf/array-helpers

    An event context object generally returned by tracking events. Also used as trackedData in components such as nf-line, nf-area and nf-bars.

    Methods

    _getMousePoint

    () private

    Method used to get the mouse position relative to a container

    Properties

    _mousePoint

    Object private

    The coordinates of the mouse relative to eh nf-graph-content

    data

    Unknown

    The data carried by the nearest data point to the mouse position along the x axis.

    graphContentElement

    SVGGElement

    The nf-graph-content element of the nf-graph

    mousePosition

    Graph-position

    A positioning object for the mouse position

    mouseX

    Number

    The mouse x position relative to the graph content

    mouseY

    Number

    The mouse y position relative to the graph content

    nearestDataPoint

    Array

    The raw data point nearest the mouse.graphX position

    originalEvent

    MouseEvent

    The original event that triggered the action or ember event

    Default: null

    x

    Unknown

    The x domain value at the nearest data point to the mouse position along the x axis.

    y

    Unknown

    The y domain value at the nearest data point to the mouse position along the x axis.

    ================================================ FILE: docs/classes/utils.nf.graph-position.html ================================================ utils.nf.graph-position - ember-nf-graph

    API Docs for:
    Show:

    utils.nf.graph-position Class

    Extends Ember.Object
    Module: utils/nf/array-helpers

    Position calculation class for nf-graph related events

    Properties

    _graphContentX

    Number private

    The x position of the nf-graph-content within the nf-graph

    _graphContentY

    Number private

    The y position of the nf-graph-content within the nf-graph

    centerX

    Number

    The center point at x. Use in case of requiring a center point and using ordinal scale.

    centerY

    Number

    The center point at y. Use in case of requiring a center point and using ordinal scale.

    graph

    component.nf-graph

    Default: null

    graphOffset

    Object

    The JQuery offset of the graph element

    graphX

    Number

    The x position relative to graph

    graphY

    Number

    The y position relative to graph

    pageX

    Number

    The x position relative to the document

    pageY

    Number

    The y position relative to the document

    source

    Ember.Component

    x

    Number

    The x domain value

    xScale

    d3.scale

    The x scale from either the source or graph used to calculate positions

    y

    Number

    The y domain value

    yScale

    d3.scale

    The y scale from either the source or graph used to calculate positions

    ================================================ FILE: docs/classes/utils.nf.scroll-area-action-context.html ================================================ utils.nf.scroll-area-action-context - ember-nf-graph

    API Docs for:
    Show:

    utils.nf.scroll-area-action-context Class

    Action context event object for an nf-scroll-area scroll event.

    Methods

    normalizeScale

    (
    • scale
    • val
    )
    Number

    Ensures the output of a scale function is something palatable by SVG.

    Parameters:

    • scale d3.scale

      the scale to use to get the value

    • val Any

      the value to transform with the scale

    Returns:

    Number:

    the output of the scale function, but if NaN, it will return 0.

    Properties

    data

    Unknown

    The optional data to send with the action

    Default: null

    originalEvent

    Event

    The original scroll event object

    Default: null

    outerHeight

    Number

    The outer height of the element

    Default: 0

    outerWidth

    Number

    The outer width of the element

    Default: 0

    scrollHeight

    Number

    The scroll height of the element.

    Default: 0

    scrollLeft

    Number

    The scroll left in pixels.

    Default: 0

    scrollLeftMax

    Number

    The calculated maximum value for scrollTop in pixels.

    scrollLeftPercentage

    Number

    The calculated percentage, in decimals, of content scrolled.

    scrollTop

    Number

    The scroll top in pixels.

    Default: 0

    scrollTopMax

    Number

    The calculated maximum value for scrollTop in pixels.

    scrollTopPercentage

    Number

    The calculated percentage, in decimals, of content scrolled.

    scrollWidth

    Number

    The scroll width of the element.

    Default: 0

    source

    Ember.Component

    The component that fired the event

    Default: null

    ================================================ FILE: docs/classes/utils.parse-property-expression.html ================================================ utils.parse-property-expression - ember-nf-graph

    API Docs for:
    Show:

    utils.parse-property-expression Class

    A function that will parse a path expression into a "getter" function that can retrieve a value from that path off of any object when called.

    Example

      import parsePropertyExpr from 'utils/parse-property-expr';
    
      var test = { foo: { bar: ['apple', 'banana'] } };
      var getFooBar1 = parsePropertyExpr('foo.bar[1]');
      var result = getFooBar1(test);
      console.log(result); // "banana"
    

    Notes

    Will return undefined if the nothing is at the end of the path, or the path cannot be reached.

    Methods

    default

    (
    • expr
    )
    Function

    Parameters:

    • expr String

      the expression to parse

    Returns:

    Function:

    a function that when called with an object, will locate the value at the end of the expressed path.

    downloadSvg

    (
    • svg
    )

    Triggers a download of an image rendered from the passed svg document

    Parameters:

    • svg SVGSVGElement

      the svg document to render

    getMousePoint

    (
    • container
    • e
    )
    Object

    Parameters:

    • container SVGElement

      the container reference to get the mouse position from

    • e MouseEvent

      A DOM mouse event

    Returns:

    Object:

    the {x, y} data of the mouse position relative to the container

    getRectPath

    (
    • x
    • y
    • w
    • h
    )
    String

    Creates an SVG path string for a rectangle

    Parameters:

    • x Object

      the x position of the rectangle

    • y Number

      the y position of the rectangle

    • w Number

      the width of the rectangle

    • h Number

      the height of the rectangle

    Returns:

    String:

    the svg path string for the rectangle

    inlineAllStyles

    (
    • element
    )
    private

    Traverses an element and all of its descendants, setting their inline style property to whatever the computed style is.

    Parameters:

    • element Element

      the dom element to traverse.

    svgToImageUrl

    (
    • svg
    )

    Renders an SVG element to a Base64 encoded data URI.

    Parameters:

    • svg SVGSVGElement

      the svg element to render

    ================================================ FILE: docs/data.json ================================================ { "project": { "name": "ember-nf-graph", "description": "A DSL for creating graphs with Ember" }, "files": { "addon/mixins/graph-area-utils.js": { "name": "addon/mixins/graph-area-utils.js", "modules": {}, "classes": { "mixins.graph-area-utils": 1 }, "fors": {}, "namespaces": { "mixins": 1 } }, "addon/mixins/graph-data-graphic.js": { "name": "addon/mixins/graph-data-graphic.js", "modules": {}, "classes": { "mixins.graph-data-graphic": 1 }, "fors": {}, "namespaces": { "mixins": 1 } }, "addon/mixins/graph-graphic-with-tracking-dot.js": { "name": "addon/mixins/graph-graphic-with-tracking-dot.js", "modules": {}, "classes": {}, "fors": {}, "namespaces": {} }, "addon/mixins/graph-has-graph-parent.js": { "name": "addon/mixins/graph-has-graph-parent.js", "modules": {}, "classes": { "mixins.graph-has-graph-parent": 1 }, "fors": {}, "namespaces": { "mixins": 1 } }, "addon/mixins/graph-line-utils.js": { "name": "addon/mixins/graph-line-utils.js", "modules": {}, "classes": { "mixins.graph-line-utils": 1 }, "fors": {}, "namespaces": { "mixins": 1 } }, "addon/mixins/graph-registered-graphic.js": { "name": "addon/mixins/graph-registered-graphic.js", "modules": {}, "classes": { "mixins.graph-registered-graphic": 1 }, "fors": {}, "namespaces": { "mixins": 1 } }, "addon/mixins/graph-requires-scale-source.js": { "name": "addon/mixins/graph-requires-scale-source.js", "modules": {}, "classes": { "mixins.graph-requires-scale-source": 1 }, "fors": {}, "namespaces": { "mixins": 1 } }, "addon/mixins/graph-selectable-graphic.js": { "name": "addon/mixins/graph-selectable-graphic.js", "modules": {}, "classes": { "mixins.graph-selectable-graphic": 1 }, "fors": {}, "namespaces": { "mixins": 1 } }, "addon/utils/nf/array-helpers.js": { "name": "addon/utils/nf/array-helpers.js", "modules": { "utils/nf/array-helpers": 1 }, "classes": {}, "fors": {}, "namespaces": {} }, "addon/utils/nf/graph-event.js": { "name": "addon/utils/nf/graph-event.js", "modules": {}, "classes": { "utils.nf.graph-event": 1 }, "fors": {}, "namespaces": { "utils.nf": 1 } }, "addon/utils/nf/graph-mouse-event.js": { "name": "addon/utils/nf/graph-mouse-event.js", "modules": {}, "classes": { "utils.nf.graph-mouse-event": 1 }, "fors": {}, "namespaces": { "utils.nf": 1 } }, "addon/utils/nf/graph-position.js": { "name": "addon/utils/nf/graph-position.js", "modules": {}, "classes": { "utils.nf.graph-position": 1 }, "fors": {}, "namespaces": { "utils.nf": 1 } }, "addon/utils/nf/scale-utils.js": { "name": "addon/utils/nf/scale-utils.js", "modules": { "scale-utils": 1 }, "classes": {}, "fors": {}, "namespaces": { "utils.nf": 1 } }, "addon/utils/nf/scroll-area-action-context.js": { "name": "addon/utils/nf/scroll-area-action-context.js", "modules": {}, "classes": { "utils.nf.scroll-area-action-context": 1 }, "fors": {}, "namespaces": { "utils.nf": 1 } }, "addon/utils/nf/svg-dom.js": { "name": "addon/utils/nf/svg-dom.js", "modules": { "utils/nf/svg-dom": 1 }, "classes": {}, "fors": {}, "namespaces": {} }, "addon/utils/parse-property-expression.js": { "name": "addon/utils/parse-property-expression.js", "modules": {}, "classes": { "utils.parse-property-expression": 1 }, "fors": {}, "namespaces": { "utils": 1 } }, "app/components/nf-area-stack.js": { "name": "app/components/nf-area-stack.js", "modules": {}, "classes": { "components.nf-area-stack": 1 }, "fors": {}, "namespaces": { "components": 1 } }, "app/components/nf-area.js": { "name": "app/components/nf-area.js", "modules": {}, "classes": { "components.nf-area": 1 }, "fors": {}, "namespaces": { "components": 1 } }, "app/components/nf-bars.js": { "name": "app/components/nf-bars.js", "modules": {}, "classes": { "components.nf-bars": 1 }, "fors": {}, "namespaces": { "components": 1 } }, "app/components/nf-crosshair.js": { "name": "app/components/nf-crosshair.js", "modules": {}, "classes": { "components.nf-crosshair": 1 }, "fors": {}, "namespaces": { "components": 1 } }, "app/components/nf-dot.js": { "name": "app/components/nf-dot.js", "modules": {}, "classes": { "components.nf-dot": 1 }, "fors": {}, "namespaces": { "components": 1 } }, "app/components/nf-gg.js": { "name": "app/components/nf-gg.js", "modules": {}, "classes": { "components.nf-gg": 1 }, "fors": {}, "namespaces": { "components": 1 } }, "app/components/nf-graph-content.js": { "name": "app/components/nf-graph-content.js", "modules": {}, "classes": { "components.nf-graph-content": 1 }, "fors": {}, "namespaces": { "components": 1 } }, "app/components/nf-graph.js": { "name": "app/components/nf-graph.js", "modules": {}, "classes": { "components.nf-graph": 1 }, "fors": {}, "namespaces": { "components": 1 } }, "app/components/nf-horizontal-line.js": { "name": "app/components/nf-horizontal-line.js", "modules": {}, "classes": { "components.nf-horizontal-line": 1 }, "fors": {}, "namespaces": { "components": 1 } }, "app/components/nf-line.js": { "name": "app/components/nf-line.js", "modules": {}, "classes": { "components.nf-line": 1 }, "fors": {}, "namespaces": { "components": 1 } }, "app/components/nf-plot.js": { "name": "app/components/nf-plot.js", "modules": {}, "classes": { "components.nf-plot": 1 }, "fors": {}, "namespaces": { "components": 1 } }, "app/components/nf-plots.js": { "name": "app/components/nf-plots.js", "modules": {}, "classes": {}, "fors": {}, "namespaces": {} }, "app/components/nf-range-marker.js": { "name": "app/components/nf-range-marker.js", "modules": {}, "classes": { "components.nf-range-marker": 1 }, "fors": {}, "namespaces": { "components": 1 } }, "app/components/nf-range-markers.js": { "name": "app/components/nf-range-markers.js", "modules": {}, "classes": { "components.nf-range-markers": 1 }, "fors": {}, "namespaces": { "components": 1 } }, "app/components/nf-right-tick.js": { "name": "app/components/nf-right-tick.js", "modules": {}, "classes": { "components.nf-right-tick": 1 }, "fors": {}, "namespaces": { "components": 1 } }, "app/components/nf-selection-box.js": { "name": "app/components/nf-selection-box.js", "modules": {}, "classes": { "components.nf-selection-box": 1 }, "fors": {}, "namespaces": { "components": 1 } }, "app/components/nf-svg-image.js": { "name": "app/components/nf-svg-image.js", "modules": {}, "classes": { "components.nf-svg-image": 1 }, "fors": {}, "namespaces": { "components": 1 } }, "app/components/nf-svg-line.js": { "name": "app/components/nf-svg-line.js", "modules": {}, "classes": { "components.nf-svg-line": 1 }, "fors": {}, "namespaces": { "components": 1 } }, "app/components/nf-svg-path.js": { "name": "app/components/nf-svg-path.js", "modules": {}, "classes": { "components.nf-svg-path": 1 }, "fors": {}, "namespaces": { "components": 1 } }, "app/components/nf-svg-rect.js": { "name": "app/components/nf-svg-rect.js", "modules": {}, "classes": { "components.nf-svg-rect": 1 }, "fors": {}, "namespaces": { "components": 1 } }, "app/components/nf-tracker.js": { "name": "app/components/nf-tracker.js", "modules": {}, "classes": { "components.nf-tracker": 1 }, "fors": {}, "namespaces": { "components": 1 } }, "app/components/nf-vertical-line.js": { "name": "app/components/nf-vertical-line.js", "modules": {}, "classes": { "components.nf-vertical-line": 1 }, "fors": {}, "namespaces": { "components": 1 } }, "app/components/nf-x-axis.js": { "name": "app/components/nf-x-axis.js", "modules": {}, "classes": { "components.nf-x-axis": 1 }, "fors": {}, "namespaces": { "components": 1 } }, "app/components/nf-y-axis.js": { "name": "app/components/nf-y-axis.js", "modules": {}, "classes": { "components.nf-y-axis": 1 }, "fors": {}, "namespaces": { "components": 1 } }, "app/components/nf-y-diff.js": { "name": "app/components/nf-y-diff.js", "modules": {}, "classes": { "components.nf-y-diff": 1 }, "fors": {}, "namespaces": { "components": 1 } } }, "modules": { "utils/nf/array-helpers": { "name": "utils/nf/array-helpers", "submodules": {}, "classes": { "mixins.graph-area-utils": 1, "mixins.graph-data-graphic": 1, "mixins.graph-has-graph-parent": 1, "mixins.graph-line-utils": 1, "mixins.graph-registered-graphic": 1, "mixins.graph-requires-scale-source": 1, "mixins.graph-selectable-graphic": 1, "utils.nf.graph-event": 1, "utils.nf.graph-mouse-event": 1, "utils.nf.graph-position": 1 }, "fors": {}, "namespaces": { "utils.nf": 1 }, "tag": "module", "file": "addon/utils/nf/graph-position.js", "line": 6 }, "scale-utils": { "name": "scale-utils", "submodules": {}, "classes": { "utils.nf.scroll-area-action-context": 1 }, "fors": {}, "namespaces": { "utils.nf": 1 }, "tag": "module", "file": "addon/utils/nf/scroll-area-action-context.js", "line": 4, "description": "utilities for dealing with d3 scales" }, "utils/nf/svg-dom": { "name": "utils/nf/svg-dom", "submodules": {}, "classes": { "utils.parse-property-expression": 1, "components.nf-area-stack": 1, "components.nf-area": 1, "components.nf-bars": 1, "components.nf-crosshair": 1, "components.nf-dot": 1, "components.nf-gg": 1, "components.nf-graph-content": 1, "components.nf-graph": 1, "components.nf-horizontal-line": 1, "components.nf-line": 1, "components.nf-plot": 1, "components.nf-range-marker": 1, "components.nf-range-markers": 1, "components.nf-right-tick": 1, "components.nf-selection-box": 1, "components.nf-svg-image": 1, "components.nf-svg-line": 1, "components.nf-svg-path": 1, "components.nf-svg-rect": 1, "components.nf-tracker": 1, "components.nf-vertical-line": 1, "components.nf-x-axis": 1, "components.nf-y-axis": 1, "components.nf-y-diff": 1 }, "fors": {}, "namespaces": { "utils": 1, "components": 1 }, "tag": "module", "file": "app/components/nf-y-diff.js", "line": 6 } }, "classes": { "mixins.graph-area-utils": { "name": "mixins.graph-area-utils", "shortname": "mixins.graph-area-utils", "classitems": [], "plugins": [], "extensions": [], "plugin_for": [], "extension_for": [ "components.nf-area" ], "module": "utils/nf/array-helpers", "namespace": "mixins", "file": "addon/mixins/graph-area-utils.js", "line": 3, "description": "Utility functions for drawing an area.", "extends": "Ember.Mixin" }, "mixins.graph-data-graphic": { "name": "mixins.graph-data-graphic", "shortname": "mixins.graph-data-graphic", "classitems": [], "plugins": [], "extensions": [], "plugin_for": [], "extension_for": [ "components.nf-area", "components.nf-bars", "components.nf-line", "components.nf-tracker" ], "module": "utils/nf/array-helpers", "namespace": "mixins", "file": "addon/mixins/graph-data-graphic.js", "line": 10, "description": "This is mixed in to {{#crossLink components.nf-graph}}nf-graph{{/crossLink}} child components that need to register data\nwith the graph. Includes methods for extracting, sorting and scrubbing data\nfor use in graphing components.\n\nRequires {{#crossLink \"mixins.graph-registered-graphic\"}}{{/crossLink}} and \n{{#crossLink \"mixins.graph-has-graph-parent\"}}{{/crossLink}}", "extends": "Ember.Mixin" }, "mixins.graph-has-graph-parent": { "name": "mixins.graph-has-graph-parent", "shortname": "mixins.graph-has-graph-parent", "classitems": [], "plugins": [], "extensions": [], "plugin_for": [], "extension_for": [ "components.nf-area", "components.nf-bars", "components.nf-crosshair", "components.nf-dot", "components.nf-gg", "components.nf-graph-content", "components.nf-horizontal-line", "components.nf-line", "components.nf-plot", "components.nf-range-marker", "components.nf-range-markers", "components.nf-right-tick", "components.nf-selection-box", "components.nf-svg-image", "components.nf-svg-line", "components.nf-svg-path", "components.nf-svg-rect", "components.nf-tracker", "components.nf-vertical-line", "components.nf-x-axis", "components.nf-y-axis", "components.nf-y-diff" ], "module": "utils/nf/array-helpers", "namespace": "mixins", "file": "addon/mixins/graph-has-graph-parent.js", "line": 3, "description": "Adds initialization code to graph the `nf-graph` parent\nto a component that is to be contained in an `nf-graph`." }, "mixins.graph-line-utils": { "name": "mixins.graph-line-utils", "shortname": "mixins.graph-line-utils", "classitems": [], "plugins": [], "extensions": [], "plugin_for": [], "extension_for": [ "components.nf-line" ], "module": "utils/nf/array-helpers", "namespace": "mixins", "file": "addon/mixins/graph-line-utils.js", "line": 3, "extends": "Ember.Mixin" }, "mixins.graph-registered-graphic": { "name": "mixins.graph-registered-graphic", "shortname": "mixins.graph-registered-graphic", "classitems": [], "plugins": [], "extensions": [], "plugin_for": [], "extension_for": [ "components.nf-area", "components.nf-bars", "components.nf-line" ], "module": "utils/nf/array-helpers", "namespace": "mixins", "file": "addon/mixins/graph-registered-graphic.js", "line": 3, "extends": "Ember.Mixin" }, "mixins.graph-requires-scale-source": { "name": "mixins.graph-requires-scale-source", "shortname": "mixins.graph-requires-scale-source", "classitems": [], "plugins": [], "extensions": [], "plugin_for": [], "extension_for": [ "components.nf-area", "components.nf-bars", "components.nf-dot", "components.nf-horizontal-line", "components.nf-line", "components.nf-plot", "components.nf-range-marker", "components.nf-right-tick", "components.nf-selection-box", "components.nf-svg-image", "components.nf-svg-line", "components.nf-svg-path", "components.nf-svg-rect", "components.nf-tracker", "components.nf-vertical-line", "components.nf-x-axis", "components.nf-y-axis", "components.nf-y-diff" ], "module": "utils/nf/array-helpers", "namespace": "mixins", "file": "addon/mixins/graph-requires-scale-source.js", "line": 27, "description": "Adds functionality to identify a parent control that will provide an x and\ny scale, then adds scaling properties to the component it's mixed in to." }, "mixins.graph-selectable-graphic": { "name": "mixins.graph-selectable-graphic", "shortname": "mixins.graph-selectable-graphic", "classitems": [], "plugins": [], "extensions": [], "plugin_for": [], "extension_for": [ "components.nf-area", "components.nf-line", "components.nf-svg-image", "components.nf-svg-line", "components.nf-svg-path", "components.nf-svg-rect" ], "module": "utils/nf/array-helpers", "namespace": "mixins", "file": "addon/mixins/graph-selectable-graphic.js", "line": 3, "description": "Adds functionality to a component to make it a selectable graphic\nwithin it's parent nf-graph.", "extends": "Ember.Mixin" }, "utils.nf.graph-event": { "name": "utils.nf.graph-event", "shortname": "utils.nf.graph-event", "classitems": [], "plugins": [], "extensions": [], "plugin_for": [], "extension_for": [], "module": "utils/nf/array-helpers", "namespace": "utils.nf", "file": "addon/utils/nf/graph-event.js", "line": 3, "description": "Event object for graph events", "extends": "graph-position" }, "utils.nf.graph-mouse-event": { "name": "utils.nf.graph-mouse-event", "shortname": "utils.nf.graph-mouse-event", "classitems": [], "plugins": [], "extensions": [], "plugin_for": [], "extension_for": [], "module": "utils/nf/array-helpers", "namespace": "utils.nf", "file": "addon/utils/nf/graph-mouse-event.js", "line": 8, "description": "An event context object generally returned by tracking events. Also used as\n`trackedData` in components such as `nf-line`, `nf-area` and `nf-bars`.", "extends": "graph-position" }, "utils.nf.graph-position": { "name": "utils.nf.graph-position", "shortname": "utils.nf.graph-position", "classitems": [], "plugins": [], "extensions": [], "plugin_for": [], "extension_for": [], "module": "utils/nf/array-helpers", "namespace": "utils.nf", "file": "addon/utils/nf/graph-position.js", "line": 6, "description": "Position calculation class for nf-graph related events", "extends": "Ember.Object" }, "utils.nf.scroll-area-action-context": { "name": "utils.nf.scroll-area-action-context", "shortname": "utils.nf.scroll-area-action-context", "classitems": [], "plugins": [], "extensions": [], "plugin_for": [], "extension_for": [], "module": "scale-utils", "namespace": "utils.nf", "file": "addon/utils/nf/scroll-area-action-context.js", "line": 4, "description": "Action context event object for an nf-scroll-area scroll event." }, "utils.parse-property-expression": { "name": "utils.parse-property-expression", "shortname": "utils.parse-property-expression", "classitems": [], "plugins": [], "extensions": [], "plugin_for": [], "extension_for": [], "module": "utils/nf/svg-dom", "namespace": "utils", "file": "addon/utils/parse-property-expression.js", "line": 1, "description": "A function that will parse a path expression into a \"getter\" function that\ncan retrieve a value from that path off of any object when called.\n\n### Example\n \n import parsePropertyExpr from 'utils/parse-property-expr';\n\n var test = { foo: { bar: ['apple', 'banana'] } };\n var getFooBar1 = parsePropertyExpr('foo.bar[1]');\n var result = getFooBar1(test);\n console.log(result); // \"banana\"\n\n### Notes\n\nWill return `undefined` if the nothing is at the end of the path, or the\npath cannot be reached." }, "components.nf-area-stack": { "name": "components.nf-area-stack", "shortname": "components.nf-area-stack", "classitems": [], "plugins": [], "extensions": [], "plugin_for": [], "extension_for": [], "module": "utils/nf/svg-dom", "namespace": "components", "file": "app/components/nf-area-stack.js", "line": 3, "description": "A component for grouping and stacking `nf-area` components in an `nf-graph`.\n\nThis component looks at the order of the `nf-area` components underneath it \nand uses the ydata of the next sibling `nf-area` component to determine the bottom \nof each `nf-area` components path to be drawn.\n\n### Example\n\n {{#nf-graph width=300 height=100}}\n {{#nf-graph-content}}\n {{#nf-area-stack}}\n {{nf-area data=myData xprop=\"time\" yprop=\"high\"}}\n {{nf-area data=myData xprop=\"time\" yprop=\"med\"}}\n {{nf-area data=myData xprop=\"time\" yprop=\"low\"}}\n {{/nf-area-stack}}\n {{/nf-graph-content}}\n {{/nf-graph}}" }, "components.nf-area": { "name": "components.nf-area", "shortname": "components.nf-area", "classitems": [], "plugins": [], "extensions": [], "plugin_for": [], "extension_for": [], "module": "utils/nf/svg-dom", "namespace": "components", "file": "app/components/nf-area.js", "line": 11, "description": "Adds an area graph to an `nf-graph` component.\n\nOptionally, if it's located within an `nf-area-stack` component, it will work with\nsibling `nf-area` components to create a stacked graph.", "extends": "Ember.Component", "uses": [ "mixins.graph-area-utils", "mixins.graph-has-graph-parent", "mixins.graph-selectable-graphic", "mixins.graph-registered-graphic", "mixins.graph-data-graphic", "mixins.graph-graphic-with-tracking-dot", "mixins.graph-requires-scale-source" ] }, "components.nf-bars": { "name": "components.nf-bars", "shortname": "components.nf-bars", "classitems": [], "plugins": [], "extensions": [], "plugin_for": [], "extension_for": [], "module": "utils/nf/svg-dom", "namespace": "components", "file": "app/components/nf-bars.js", "line": 11, "description": "Adds a bar graph to an `nf-graph` component.\n\n**Requires the graph has `xScaleType === 'ordinal'`***\n\n** `showTrackingDot` defaults to `false` in this component **", "extends": "Ember.Component", "uses": [ "mixins.graph-has-graph-parent", "mixins.graph-registered-graphic", "mixins.graph-data-graphic", "mixins.graph-requires-scale-source", "mixins.graph-graphic-with-tracking-dot" ] }, "components.nf-crosshair": { "name": "components.nf-crosshair", "shortname": "components.nf-crosshair", "classitems": [], "plugins": [], "extensions": [], "plugin_for": [], "extension_for": [], "module": "utils/nf/svg-dom", "namespace": "components", "file": "app/components/nf-crosshair.js", "line": 4, "description": "A component that adds a \"crosshair\" to an `nf-graph` that follows the mouse\nwhile it's hovering over the graph content.", "extends": "Ember.Component", "uses": [ "mixins.graph-has-graph-parent" ] }, "components.nf-dot": { "name": "components.nf-dot", "shortname": "components.nf-dot", "classitems": [], "plugins": [], "extensions": [], "plugin_for": [], "extension_for": [], "module": "utils/nf/svg-dom", "namespace": "components", "file": "app/components/nf-dot.js", "line": 5, "description": "Plots a circle at a given x and y domain value on an `nf-graph`.", "extends": "Ember.Component", "uses": [ "mixins.graph-has-graph-parent", "mixins.graph-requires-scale-source" ] }, "components.nf-gg": { "name": "components.nf-gg", "shortname": "components.nf-gg", "classitems": [], "plugins": [], "extensions": [], "plugin_for": [], "extension_for": [], "module": "utils/nf/svg-dom", "namespace": "components", "file": "app/components/nf-gg.js", "line": 6, "description": "A grouping tag that provides zooming and offset functionality to it's children.\n\n## Example\n\nThe following example will show a line of `someData` with a 2x zoom, offset by 30px in both x and y\ndirections:\n\n {{#nf-gg scaleZoomX=\"2\" scaleZoomY=\"2\" scaleOffsetX=\"30\" scaleOffsetY=\"30\"}}\n {{nf-line data=someData}}\n {{/nf-gg}}", "extends": "Ember.Component", "uses": [ "mixins.graph-has-graph-parent", "mixins.graph-require-scale-source", "mixins.graph-selecteble-graphic" ] }, "components.nf-graph-content": { "name": "components.nf-graph-content", "shortname": "components.nf-graph-content", "classitems": [], "plugins": [], "extensions": [], "plugin_for": [], "extension_for": [], "module": "utils/nf/svg-dom", "namespace": "components", "file": "app/components/nf-graph-content.js", "line": 5, "description": "Container component for graphics to display in `nf-graph`. Represents\nthe area where the graphics, such as lines will display.\n\nExists for layout purposes.", "uses": [ "mixins.graph-has-graph-parent" ] }, "components.nf-graph": { "name": "components.nf-graph", "shortname": "components.nf-graph", "classitems": [], "plugins": [], "extensions": [], "plugin_for": [], "extension_for": [], "module": "utils/nf/svg-dom", "namespace": "components", "file": "app/components/nf-graph.js", "line": 239, "description": "A container component for building complex Cartesian graphs.\n\n## Minimal example\n\n {{#nf-graph width=100 height=50}}\n {{#nf-graph-content}}\n {{nf-line data=lineData xprop=\"foo\" yprop=\"bar\"}}\n {{/nf-graph-content}}\n {{/nf-graph}}\n\nThe above will create a simple 100x50 graph, with no axes, and a single line\nplotting the data it finds on each object in the array `lineData` at properties\n`foo` and `bar` for x and y values respectively.\n\n## More advanced example\n\n {{#nf-graph width=500 height=300}}\n {{#nf-x-axis height=\"50\" as |tick|}}\n {{tick.value}}\n {{/nf-x-axis}}\n\n {{#nf-y-axis width=\"120\" as |tick|}}\n {{tick.value}}\n {{/nf-y-axis}}\n \n {{#nf-graph-content}}\n {{nf-line data=lineData xprop=\"foo\" yprop=\"bar\"}}\n {{/nf-graph-content}}\n {{/nf-graph}}\n\nThe above example will create a 500x300 graph with both axes visible. The graph will not \nrender either axis unless its component is present.", "extends": "Ember.Component" }, "components.nf-horizontal-line": { "name": "components.nf-horizontal-line", "shortname": "components.nf-horizontal-line", "classitems": [], "plugins": [], "extensions": [], "plugin_for": [], "extension_for": [], "module": "utils/nf/svg-dom", "namespace": "components", "file": "app/components/nf-horizontal-line.js", "line": 5, "description": "Draws a horizontal line on the graph at a given y domain value", "extends": "Ember.Component", "uses": [ "mixins.graph-has-graph-parent", "mixins.graph-requires-scale-source" ] }, "components.nf-line": { "name": "components.nf-line", "shortname": "components.nf-line", "classitems": [], "plugins": [], "extensions": [], "plugin_for": [], "extension_for": [], "module": "utils/nf/svg-dom", "namespace": "components", "file": "app/components/nf-line.js", "line": 10, "description": "A line graphic for `nf-graph`. Displays a line for the data it's passed.", "extends": "Ember.Component", "uses": [ "mixins.graph-line-utils", "mixins.graph-has-graph-parent", "mixins.graph-selectable-graphic", "mixins.graph-registered-graphic", "mixins.graph-data-graphic", "mixins.graph-graphic-with-tracking-dot", "mixins.graph-requires-scale-source" ] }, "components.nf-plot": { "name": "components.nf-plot", "shortname": "components.nf-plot", "classitems": [], "plugins": [], "extensions": [], "plugin_for": [], "extension_for": [], "module": "utils/nf/svg-dom", "namespace": "components", "file": "app/components/nf-plot.js", "line": 6, "description": "Plots a group tag on a graph at a given x and y domain coordinate.", "extends": "Ember.Component", "uses": [ "mixins.graph-has-graph-parent", "mixins.graph-requires-scale-source" ] }, "components.nf-range-marker": { "name": "components.nf-range-marker", "shortname": "components.nf-range-marker", "classitems": [], "plugins": [], "extensions": [], "plugin_for": [], "extension_for": [], "module": "utils/nf/svg-dom", "namespace": "components", "file": "app/components/nf-range-marker.js", "line": 5, "description": "Draws a rectangular strip with a templated label on an `nf-graph`.\nShould always be used in conjunction with an `nf-range-markers` container component.", "extends": "Ember.Component", "uses": [ "mixins.graph-has-graph-parent", "mixins.graph-requires-scale-source" ] }, "components.nf-range-markers": { "name": "components.nf-range-markers", "shortname": "components.nf-range-markers", "classitems": [], "plugins": [], "extensions": [], "plugin_for": [], "extension_for": [], "module": "utils/nf/svg-dom", "namespace": "components", "file": "app/components/nf-range-markers.js", "line": 4, "description": "A container and manager for `nf-range-marker` components.\nUsed to draw an association between `nf-range-marker` components so they \ncan be laid out in a manner in which they don't collide.", "extends": "Ember.Component", "uses": [ "mixins.graph-has-graph-parent" ] }, "components.nf-right-tick": { "name": "components.nf-right-tick", "shortname": "components.nf-right-tick", "classitems": [], "plugins": [], "extensions": [], "plugin_for": [], "extension_for": [], "module": "utils/nf/svg-dom", "namespace": "components", "file": "app/components/nf-right-tick.js", "line": 5, "description": "Draws a line and a chevron at the specified domain value \non the right side of an `nf-graph`. \n\n### Tips\n\n- Position outside of `nf-graph-content` component, but inside `nf-graph`.\n- Adding `paddingRight` to `nf-graph` component will not affect `nf-right-tick`'s position.", "extends": "Ember.Component", "uses": [ "mixins.graph-has-graph-parent", "mixins.graph-requires-scale-source" ] }, "components.nf-selection-box": { "name": "components.nf-selection-box", "shortname": "components.nf-selection-box", "classitems": [], "plugins": [], "extensions": [], "plugin_for": [], "extension_for": [], "module": "utils/nf/svg-dom", "namespace": "components", "file": "app/components/nf-selection-box.js", "line": 6, "description": "Draws a rectangle on an `nf-graph` given domain values `xMin`, `xMax`, `yMin` and `yMax`.", "extends": "Ember.Component", "uses": [ "mixins.graph-has-graph-parent", "mixins.graph-requires-scale-source" ] }, "components.nf-svg-image": { "name": "components.nf-svg-image", "shortname": "components.nf-svg-image", "classitems": [], "plugins": [], "extensions": [], "plugin_for": [], "extension_for": [], "module": "utils/nf/svg-dom", "namespace": "components", "file": "app/components/nf-svg-image.js", "line": 7, "description": "An image to be displayed in a graph with that takes domain based measurements and\nuses the scale of the graph. Creates an `` SVG element.", "extends": "Ember.Component", "uses": [ "mixins.graph-has-graph-parent", "mixins.graph-requires-scale-source", "mixins.graph-selectable-graphic" ] }, "components.nf-svg-line": { "name": "components.nf-svg-line", "shortname": "components.nf-svg-line", "classitems": [], "plugins": [], "extensions": [], "plugin_for": [], "extension_for": [], "module": "utils/nf/svg-dom", "namespace": "components", "file": "app/components/nf-svg-line.js", "line": 7, "description": "Draws a basic line between two points on the graph.", "extends": "Ember.Component", "uses": [ "mixins.graph-has-graph-parent", "mixins.graph-requires-scale-source", "mixins.graph-selectable-graphic" ] }, "components.nf-svg-path": { "name": "components.nf-svg-path", "shortname": "components.nf-svg-path", "classitems": [], "plugins": [], "extensions": [], "plugin_for": [], "extension_for": [], "module": "utils/nf/svg-dom", "namespace": "components", "file": "app/components/nf-svg-path.js", "line": 7, "description": "An SVG path primitive that plots based on a graph's scale.", "extends": "Ember.Component", "uses": [ "mixins.graph-has-graph-parent", "mixins.graph-requires-scale-source", "mixins.graph-selectable-graphic" ] }, "components.nf-svg-rect": { "name": "components.nf-svg-rect", "shortname": "components.nf-svg-rect", "classitems": [], "plugins": [], "extensions": [], "plugin_for": [], "extension_for": [], "module": "utils/nf/svg-dom", "namespace": "components", "file": "app/components/nf-svg-rect.js", "line": 7, "description": "A rectangle that plots using domain values from the graph. Uses an SVGPathElement\nto plot the rectangle, to allow for rectangles with \"negative\" heights.", "extends": "Ember.Component", "uses": [ "mixins.graph-has-graph-parent", "mixins.graph-requires-scale-source", "mixins.graph-selectable-graphic" ] }, "components.nf-tracker": { "name": "components.nf-tracker", "shortname": "components.nf-tracker", "classitems": [], "plugins": [], "extensions": [], "plugin_for": [], "extension_for": [], "module": "utils/nf/svg-dom", "namespace": "components", "file": "app/components/nf-tracker.js", "line": 9, "description": "A tracking graphic component used to do things like create tracking dots for nf-area or nf-line.", "uses": [ "mixins.graph-has-graph-parent", "mixins.graph-data-graphic", "mixins.graph-requires-scale-source", "mixins.graph-graphic-with-tracking-dot" ] }, "components.nf-vertical-line": { "name": "components.nf-vertical-line", "shortname": "components.nf-vertical-line", "classitems": [], "plugins": [], "extensions": [], "plugin_for": [], "extension_for": [], "module": "utils/nf/svg-dom", "namespace": "components", "file": "app/components/nf-vertical-line.js", "line": 5, "description": "Draws a vertical line on a graph at a given x domain value", "extends": "Ember.Component", "uses": [ "mixins.graph-has-graph-parent", "mixins.graph-requires-scale-source" ] }, "components.nf-x-axis": { "name": "components.nf-x-axis", "shortname": "components.nf-x-axis", "classitems": [], "plugins": [], "extensions": [], "plugin_for": [], "extension_for": [], "module": "utils/nf/svg-dom", "namespace": "components", "file": "app/components/nf-x-axis.js", "line": 7, "description": "A component for adding a templated x axis to an `nf-graph` component.\nAll items contained within this component are used to template each tick mark on the\nrendered graph. Tick values are supplied to the inner scope of this component on the\nview template via `tick`.\n\n### Styling\n\nThe main container will have a `nf-x-axis` class.\nA `orient-top` or `orient-bottom` container will be applied to the container\ndepending on the `orient` setting.\n\nTicks are positioned via a `` tag, that will contain whatever is passed into it via\ntemplating, along with the tick line. `` tags within tick templates do have some\ndefault styling applied to them to position them appropriately based off of orientation.\n\n### Example\n\n {{#nf-graph width=500 height=300}}\n {{#nf-x-axis height=40 as |tick|}}\n x is {{tick.value}}\n {{/nf-x-axis}}\n {{/nf-graph}}", "extends": "Ember.Component", "uses": [ "mixins.graph-has-graph-parent", "mixins.graph-requires-scale-source" ] }, "components.nf-y-axis": { "name": "components.nf-y-axis", "shortname": "components.nf-y-axis", "classitems": [], "plugins": [], "extensions": [], "plugin_for": [], "extension_for": [], "module": "utils/nf/svg-dom", "namespace": "components", "file": "app/components/nf-y-axis.js", "line": 7, "description": "A component for adding a templated y axis to an `nf-graph` component.\nAll items contained within this component are used to template each tick mark on the \nrendered graph. Tick values are supplied to the inner scope of this component on the\nview template via `tick`.\n\n### Styling\n\nThe main container will have a `nf-y-axis` class.\nA `orient-left` or `orient-right` container will be applied to the container\ndepending on the `orient` setting.\n\nTicks are positioned via a `` tag, that will contain whatever is passed into it via\ntemplating, along with the tick line. `` tags within tick templates do have some \ndefault styling applied to them to position them appropriately based off of orientation.\n\n### Example\n\n {{#nf-graph width=500 height=300}}\n {{#nf-y-axis width=40 as |tick|}}\n y is {{tick.value}}\n {{/nf-y-axis}}\n {{/nf-graph}}", "uses": [ "mixins.graph-has-graph-parent", "mixins.graph-requires-scale-source" ] }, "components.nf-y-diff": { "name": "components.nf-y-diff", "shortname": "components.nf-y-diff", "classitems": [], "plugins": [], "extensions": [], "plugin_for": [], "extension_for": [], "module": "utils/nf/svg-dom", "namespace": "components", "file": "app/components/nf-y-diff.js", "line": 6, "description": "Draws a box underneath (or over) the y axis to between the given `a` and `b`\ndomain values. Component content is used to template a label in that box.\n\n## Tips\n\n- Should be outside of `nf-graph-content`.\n- Should be \"above\" `nf-y-axis` in the markup.\n- As a convenience, `` elements will automatically be positioned based on y-axis orientation\n due to default styling.", "extends": "Ember.Component", "uses": [ "mixins.graph-has-graph-parent", "mixins.graph-requires-scale-source" ] } }, "classitems": [ { "file": "addon/mixins/graph-area-utils.js", "line": 12, "description": "Creates a d3 area function from a given set of scales and an interpolator", "itemtype": "method", "name": "createAreaFn", "params": [ { "name": "xScale", "description": "a d3 scale", "type": "Function" }, { "name": "yScale", "description": "a d3 scale", "type": "Function" }, { "name": "interpolator", "description": "the name of the d3 interpolator to use.", "type": "String" } ], "return": { "description": "a function that when called will create SVG path data.", "type": "Function" }, "class": "mixins.graph-area-utils", "namespace": "mixins" }, { "file": "addon/mixins/graph-data-graphic.js", "line": 25, "description": "Gets or sets the data used by the component to plot itself.", "itemtype": "property", "name": "data", "type": "Array", "default": "null", "class": "mixins.graph-data-graphic", "namespace": "mixins" }, { "file": "addon/mixins/graph-data-graphic.js", "line": 59, "description": "The path of the property on each object in \n{{#crossLink \"mixins.graph-data-graphic/data:property\"}}{{/crossLink}}\nto use as x data to plot on the graph.", "itemtype": "property", "name": "xprop", "type": "String", "default": "'x'", "class": "mixins.graph-data-graphic", "namespace": "mixins" }, { "file": "addon/mixins/graph-data-graphic.js", "line": 70, "description": "The path of the property on each object in \n{{#crossLink \"mixins.graph-data-graphic/data:property\"}}{{/crossLink}}\nto use as y data to plot on the graph.", "itemtype": "property", "name": "yprop", "type": "String", "default": "'y'", "class": "mixins.graph-data-graphic", "namespace": "mixins" }, { "file": "addon/mixins/graph-data-graphic.js", "line": 81, "description": "The function to get the x value from each \n{{#crossLink \"mixins.graph-data-graphic/data:property\"}}{{/crossLink}} object", "itemtype": "property", "name": "xPropFn", "type": "Function", "readonly": "", "class": "mixins.graph-data-graphic", "namespace": "mixins" }, { "file": "addon/mixins/graph-data-graphic.js", "line": 96, "description": "The function to get the y value from each \n{{#crossLink \"mixins.graph-data-graphic/data:property\"}}{{/crossLink}} object", "itemtype": "property", "name": "yPropFn", "type": "Function", "readonly": "", "class": "mixins.graph-data-graphic", "namespace": "mixins" }, { "file": "addon/mixins/graph-data-graphic.js", "line": 111, "description": "The list of data points from {{#crossLink \"mixins.graph-data-graphc/mappedData:property\"}}{{/crossLink}} that\nfits within the x domain, plus up to one data point outside of that domain in each direction.", "itemtype": "property", "name": "renderedData", "type": "Array", "readonly": "", "class": "mixins.graph-data-graphic", "namespace": "mixins" }, { "file": "addon/mixins/graph-data-graphic.js", "line": 152, "description": "The first element from {{#crossLink \"mixins.graph-data-graphic/renderedData:property\"}}{{/crossLink}}\nthat is actually visible within the x domain.", "itemtype": "property", "name": "firstVisibleData", "type": "{Object}", "readonly": "", "class": "mixins.graph-data-graphic", "namespace": "mixins" }, { "file": "addon/mixins/graph-data-graphic.js", "line": 179, "description": "The last element from {{#crossLink \"mixins.graph-data-graphic/renderedData:property\"}}{{/crossLink}}\nthat is actually visible within the x domain.", "itemtype": "property", "name": "lastVisibleData", "type": "{Object}", "readonly": "", "class": "mixins.graph-data-graphic", "namespace": "mixins" }, { "file": "addon/mixins/graph-data-graphic.js", "line": 235, "description": "Gets the actual data at a rendered tracking point passed to it.\nThis is overridden in nf-area to account for stacking of data.", "itemtype": "method", "name": "getActualTrackData", "params": [ { "name": "renderX", "description": "the x domain value the data is rendered at", "type": "Number" }, { "name": "renderY", "description": "the y domain value the data is rendered at", "type": "Number" }, { "name": "data", "description": "the raw data from the point", "type": "Object" } ], "return": { "description": "simple x, y point structure", "type": "Object" }, "class": "mixins.graph-data-graphic", "namespace": "mixins" }, { "file": "addon/mixins/graph-graphic-with-tracking-dot.js", "line": 8, "description": "Gets or sets the tracking mode of the component.\n\nPossible values are:\n\n- 'none': no tracking behavior\n- 'hover': only track while mouse hover\n- 'snap-last': track while mouse hover, but snap to the last data element when not hovering\n- 'snap-first': track while mouse hover, but snap to the first data element when not hovering\n- 'selected-hover': The same as `'hover'` tracking mode, but only when the compononent is \n{{#crossLink \"mixins.graph-selectable-graphic/selected:property\"}}{{/crossLink}}\n- 'selected-snap-last': The same as `'snap-last'` tracking mode, but only when the compononent is \n{{#crossLink \"mixins.graph-selectable-graphic/selected:property\"}}{{/crossLink}}\n- 'selected-snap-first': The same as `'snap-first'` tracking mode, but only when the compononent is \n{{#crossLink \"mixins.graph-selectable-graphic/selected:property\"}}{{/crossLink}}", "itemtype": "property", "name": "trackingMode", "type": "String", "default": "'none'", "class": "mixins.graph-has-graph-parent", "namespace": "mixins" }, { "file": "addon/mixins/graph-graphic-with-tracking-dot.js", "line": 30, "description": "The radius of the tracking dot in pixels", "itemtype": "property", "name": "trackingDotRadius", "type": "{number}", "default": "2.5", "class": "mixins.graph-has-graph-parent", "namespace": "mixins" }, { "file": "addon/mixins/graph-graphic-with-tracking-dot.js", "line": 38, "description": "The action to send on `didTrack`.", "itemtype": "property", "name": "didTrack", "type": "String", "default": "null", "class": "mixins.graph-has-graph-parent", "namespace": "mixins" }, { "file": "addon/mixins/graph-graphic-with-tracking-dot.js", "line": 46, "description": "The value of the data that is being tracked by the component.", "itemtype": "property", "name": "trackedData", "type": "{Object} an object with the following values: \n - point: an { x, y } pair for the exact px coordinates inside the graph-content\n - graphX: domain x value at mouse position\n - graphY: domain y value at mouse position\n - x: nearest x data value\n - y: nearest y data value\n - data: nearest raw data\n - renderX: domain x value to render a tracking dot at (stacked areas are offset)\n - renderY: domain x value to render a tracking dot at (stacked areas are offset)\n - mouseX: mouse x position in pixels\n - mouseY: mouse y position in pixels", "default": "null", "class": "mixins.graph-has-graph-parent", "namespace": "mixins" }, { "file": "addon/mixins/graph-graphic-with-tracking-dot.js", "line": 64, "description": "The value of the data that is being tracked by the component, ONLY if the \ngraph-content is currently being hovered.", "itemtype": "property", "name": "hoverData", "type": "{Object} an object with the following values: \n - point: an { x, y } pair for the exact px coordinates inside the graph-content\n - graphX: domain x value at mouse position\n - graphY: domain y value at mouse position\n - x: nearest x data value\n - y: nearest y data value\n - data: nearest raw data\n - renderX: domain x value to render a tracking dot at (stacked areas are offset)\n - renderY: domain x value to render a tracking dot at (stacked areas are offset)\n - mouseX: mouse x position in pixels\n - mouseY: mouse y position in pixels", "default": "null", "class": "mixins.graph-has-graph-parent", "namespace": "mixins" }, { "file": "addon/mixins/graph-graphic-with-tracking-dot.js", "line": 85, "description": "Gets or sets whether the tracking dot should be shown at all.", "itemtype": "property", "name": "showTrackingDot", "type": "{boolean}", "default": "true", "class": "mixins.graph-has-graph-parent", "namespace": "mixins" }, { "file": "addon/mixins/graph-graphic-with-tracking-dot.js", "line": 101, "description": "Observes changes to tracked data and sends the\ndidTrack action.", "itemtype": "method", "name": "_trackedDataChanged", "access": "private", "tagname": "", "class": "mixins.graph-has-graph-parent", "namespace": "mixins" }, { "file": "addon/mixins/graph-has-graph-parent.js", "line": 12, "description": "The parent graph for a component.", "itemtype": "property", "name": "graph", "type": "components.nf-graph", "default": "null", "class": "mixins.graph-has-graph-parent", "namespace": "mixins" }, { "file": "addon/mixins/graph-has-graph-parent.js", "line": 20, "description": "Initalization method that gets the `nf-graph` parent\nand assigns it to `graph`\nNOTE: all object that mixin and have init, must call super.init()", "itemtype": "method", "name": "init", "class": "mixins.graph-has-graph-parent", "namespace": "mixins" }, { "file": "addon/mixins/graph-line-utils.js", "line": 10, "description": "Create a d3 line function from a given scales and interpolation", "itemtype": "method", "name": "createLineFn", "params": [ { "name": "xScale", "description": "d3 scale function", "type": "Function" }, { "name": "yScale", "description": "d3 scale function", "type": "Function" }, { "name": "interpolate", "description": "d3 interpolator name", "type": "String" } ], "return": { "description": "a d3 function that will create SVG path data from a given data set.", "type": "Function" }, "class": "mixins.graph-line-utils", "namespace": "mixins" }, { "file": "addon/mixins/graph-registered-graphic.js", "line": 18, "description": "calls {{#crossLink \"components.nf-graph/unregisterGraphic\"}}{{/crossLink}} on\n`didInsertElement`.", "itemtype": "method", "name": "_unregisterGraphic", "access": "private", "tagname": "", "class": "mixins.graph-registered-graphic", "namespace": "mixins" }, { "file": "addon/mixins/graph-requires-scale-source.js", "line": 34, "description": "The x scale used by this component", "itemtype": "property", "name": "xScale", "type": "d3.scale", "readonly": "", "class": "mixins.graph-requires-scale-source", "namespace": "mixins" }, { "file": "addon/mixins/graph-requires-scale-source.js", "line": 42, "description": "The y scale used by this component", "itemtype": "property", "name": "yScale", "type": "d3.scale", "readonly": "", "class": "mixins.graph-requires-scale-source", "namespace": "mixins" }, { "file": "addon/mixins/graph-requires-scale-source.js", "line": 58, "description": "The zoom multiplier for the x scale", "itemtype": "property", "name": "scaleZoomX", "type": "Number", "default": "1", "class": "mixins.graph-requires-scale-source", "namespace": "mixins" }, { "file": "addon/mixins/graph-requires-scale-source.js", "line": 73, "description": "The zoom multiplier for the y scale", "itemtype": "property", "name": "scaleZoomY", "type": "Number", "default": "1", "class": "mixins.graph-requires-scale-source", "namespace": "mixins" }, { "file": "addon/mixins/graph-requires-scale-source.js", "line": 88, "description": "The offset, in pixels, for the x scale", "itemtype": "property", "name": "scaleOffsetX", "type": "Number", "default": "0", "class": "mixins.graph-requires-scale-source", "namespace": "mixins" }, { "file": "addon/mixins/graph-requires-scale-source.js", "line": 103, "description": "The offset, in pixels, for the y scale", "itemtype": "property", "name": "scaleOffsetY", "type": "Number", "default": "0", "class": "mixins.graph-requires-scale-source", "namespace": "mixins" }, { "file": "addon/mixins/graph-selectable-graphic.js", "line": 13, "description": "Gets or sets whether or not the graphic is \"selectable\". Meaning can be \"selected\" on the nf-graph \nvia some action (usually click). The component will then show up in the nf-graph parent's selected \nproperty.", "itemtype": "property", "name": "selectable", "type": "Boolean", "default": "false", "class": "mixins.graph-selectable-graphic", "namespace": "mixins" }, { "file": "addon/mixins/graph-selectable-graphic.js", "line": 23, "description": "Gets or sets whether or not the graphic is selected.", "itemtype": "property", "name": "selected", "type": "Boolean", "default": "false", "class": "mixins.graph-selectable-graphic", "namespace": "mixins" }, { "file": "addon/mixins/graph-selectable-graphic.js", "line": 31, "description": "Alias of selected", "itemtype": "property", "name": "isSelected", "deprecated": true, "deprecationMessage": "use `selected`", "class": "mixins.graph-selectable-graphic", "namespace": "mixins" }, { "file": "addon/mixins/graph-selectable-graphic.js", "line": 38, "description": "Makes calls to the parent nf-graph to update it's\n`selected` property. Observes changes to `selected` and also \nfires on `didInsertElement`.", "itemtype": "method", "name": "_updateGraphSelected", "access": "private", "tagname": "", "class": "mixins.graph-selectable-graphic", "namespace": "mixins" }, { "file": "addon/utils/nf/array-helpers.js", "line": 5, "description": "returns whatever you pass into it.", "itemtype": "method", "name": "identity", "params": [ { "name": "x", "description": "", "type": "Any" } ], "access": "private", "tagname": "", "return": { "description": "x", "type": "Any" }, "class": "utils.nf.graph-event", "module": "utils/nf/array-helpers" }, { "file": "addon/utils/nf/array-helpers.js", "line": 16, "description": "Performs a binary search on the array and finds the nearest index to the value passed.", "itemtype": "method", "name": "nearestIndexTo", "params": [ { "name": "arr", "description": "the *sorted* array to search.", "type": "Array" }, { "name": "val", "description": "the value to find the nearest index to.", "type": "Number" }, { "name": "mappingFn", "description": "an optional function for pulling values out of the \narray items.", "type": "Function" } ], "class": "utils.nf.graph-event", "module": "utils/nf/array-helpers" }, { "file": "addon/utils/nf/array-helpers.js", "line": 59, "description": "breaks a string into an array of tokens in preparation for natural\ncomparison and sorting.", "itemtype": "method", "name": "naturalTokenize", "params": [ { "name": "item", "description": "the value to tokenize", "type": "String" } ], "return": { "description": "an array of tokens found in the item", "type": "Array" }, "access": "private", "tagname": "", "class": "utils.nf.graph-event", "module": "utils/nf/array-helpers" }, { "file": "addon/utils/nf/array-helpers.js", "line": 77, "description": "A JavaScript sorting predicate for natural sorting.", "itemtype": "method", "name": "naturalCompare", "params": [ { "name": "a", "description": "the value to compare to b", "type": "Any" }, { "name": "b", "description": "the value to compare to a", "type": "Any" } ], "return": { "description": "`-1`, `0` or `1` if a is less than, equal to, or\n greater than b, respectively.", "type": "Number" }, "class": "utils.nf.graph-event", "module": "utils/nf/array-helpers" }, { "file": "addon/utils/nf/array-helpers.js", "line": 112, "description": "Sorts the array \"naturally\". Meaning taking into account both\nalphabetical and numeric sorting within strings.", "itemtype": "method", "name": "natualSort", "params": [ { "name": "arr", "description": "the array to sort", "type": "Array" } ], "class": "utils.nf.graph-event", "module": "utils/nf/array-helpers" }, { "file": "addon/utils/nf/graph-event.js", "line": 10, "description": "The original event that triggered this event or action", "itemtype": "property", "name": "originalEvent", "type": "Event", "default": "null", "class": "utils.nf.graph-event", "module": "utils/nf/array-helpers", "namespace": "utils.nf" }, { "file": "addon/utils/nf/graph-event.js", "line": 18, "description": "A data value passed with the event", "itemtype": "property", "name": "data", "type": "any", "default": "null", "class": "utils.nf.graph-event", "module": "utils/nf/array-helpers", "namespace": "utils.nf" }, { "file": "addon/utils/nf/graph-mouse-event.js", "line": 17, "description": "The original event that triggered the action or ember event", "itemtype": "property", "name": "originalEvent", "type": "MouseEvent", "default": "null", "class": "utils.nf.graph-mouse-event", "module": "utils/nf/array-helpers", "namespace": "utils.nf" }, { "file": "addon/utils/nf/graph-mouse-event.js", "line": 25, "description": "Method used to get the mouse position relative to a container", "itemtype": "method", "name": "_getMousePoint", "access": "private", "tagname": "", "class": "utils.nf.graph-mouse-event", "module": "utils/nf/array-helpers", "namespace": "utils.nf" }, { "file": "addon/utils/nf/graph-mouse-event.js", "line": 32, "description": "The coordinates of the mouse relative to eh nf-graph-content", "itemtype": "property", "name": "_mousePoint", "type": "Object", "readonly": "", "access": "private", "tagname": "", "class": "utils.nf.graph-mouse-event", "module": "utils/nf/array-helpers", "namespace": "utils.nf" }, { "file": "addon/utils/nf/graph-mouse-event.js", "line": 45, "description": "The nf-graph-content element of the nf-graph", "itemtype": "property", "name": "graphContentElement", "type": "SVGGElement", "readonly": "", "class": "utils.nf.graph-mouse-event", "module": "utils/nf/array-helpers", "namespace": "utils.nf" }, { "file": "addon/utils/nf/graph-mouse-event.js", "line": 53, "description": "The mouse x position relative to the graph content", "itemtype": "property", "name": "mouseX", "type": "Number", "readonly": "", "class": "utils.nf.graph-mouse-event", "module": "utils/nf/array-helpers", "namespace": "utils.nf" }, { "file": "addon/utils/nf/graph-mouse-event.js", "line": 61, "description": "The mouse y position relative to the graph content", "itemtype": "property", "name": "mouseY", "type": "Number", "readonly": "", "class": "utils.nf.graph-mouse-event", "module": "utils/nf/array-helpers", "namespace": "utils.nf" }, { "file": "addon/utils/nf/graph-mouse-event.js", "line": 69, "description": "A positioning object for the mouse position", "itemtype": "property", "name": "mousePosition", "type": "graph-position", "readonly": "", "class": "utils.nf.graph-mouse-event", "module": "utils/nf/array-helpers", "namespace": "utils.nf" }, { "file": "addon/utils/nf/graph-mouse-event.js", "line": 86, "description": "The raw data point nearest the mouse.graphX position", "itemtype": "property", "name": "nearestDataPoint", "type": "Array", "readonly": "", "class": "utils.nf.graph-mouse-event", "module": "utils/nf/array-helpers", "namespace": "utils.nf" }, { "file": "addon/utils/nf/graph-mouse-event.js", "line": 100, "description": "The x domain value at the nearest data point to the mouse position\nalong the x axis.", "itemtype": "property", "name": "x", "readonly": "", "class": "utils.nf.graph-mouse-event", "module": "utils/nf/array-helpers", "namespace": "utils.nf" }, { "file": "addon/utils/nf/graph-mouse-event.js", "line": 114, "description": "The y domain value at the nearest data point to the mouse position\nalong the x axis.", "itemtype": "property", "name": "y", "readonly": "", "class": "utils.nf.graph-mouse-event", "module": "utils/nf/array-helpers", "namespace": "utils.nf" }, { "file": "addon/utils/nf/graph-mouse-event.js", "line": 128, "description": "The data carried by the nearest data point to the mouse position\nalong the x axis.", "itemtype": "property", "name": "data", "readonly": "", "class": "utils.nf.graph-mouse-event", "module": "utils/nf/array-helpers", "namespace": "utils.nf" }, { "file": "addon/utils/nf/graph-position.js", "line": 13, "itemtype": "property", "name": "graph", "type": "component.nf-graph", "default": "null", "class": "utils.nf.graph-position", "module": "utils/nf/array-helpers", "namespace": "utils.nf" }, { "file": "addon/utils/nf/graph-position.js", "line": 20, "itemtype": "property", "name": "source", "type": "Ember.Component", "class": "utils.nf.graph-position", "module": "utils/nf/array-helpers", "namespace": "utils.nf" }, { "file": "addon/utils/nf/graph-position.js", "line": 26, "description": "The x position relative to graph", "itemtype": "property", "name": "graphX", "type": "Number", "class": "utils.nf.graph-position", "module": "utils/nf/array-helpers", "namespace": "utils.nf" }, { "file": "addon/utils/nf/graph-position.js", "line": 45, "description": "The y position relative to graph", "itemtype": "property", "name": "graphY", "type": "Number", "class": "utils.nf.graph-position", "module": "utils/nf/array-helpers", "namespace": "utils.nf" }, { "file": "addon/utils/nf/graph-position.js", "line": 64, "description": "The x domain value", "itemtype": "property", "name": "x", "type": "Number", "class": "utils.nf.graph-position", "module": "utils/nf/array-helpers", "namespace": "utils.nf" }, { "file": "addon/utils/nf/graph-position.js", "line": 83, "description": "The y domain value", "itemtype": "property", "name": "y", "type": "Number", "class": "utils.nf.graph-position", "module": "utils/nf/array-helpers", "namespace": "utils.nf" }, { "file": "addon/utils/nf/graph-position.js", "line": 102, "description": "The x position relative to the document", "itemtype": "property", "name": "pageX", "type": "Number", "class": "utils.nf.graph-position", "module": "utils/nf/array-helpers", "namespace": "utils.nf" }, { "file": "addon/utils/nf/graph-position.js", "line": 118, "description": "The y position relative to the document", "itemtype": "property", "name": "pageY", "type": "Number", "class": "utils.nf.graph-position", "module": "utils/nf/array-helpers", "namespace": "utils.nf" }, { "file": "addon/utils/nf/graph-position.js", "line": 134, "description": "The x scale from either the source or graph used to calculate positions", "itemtype": "property", "name": "xScale", "type": "d3.scale", "readonly": "", "class": "utils.nf.graph-position", "module": "utils/nf/array-helpers", "namespace": "utils.nf" }, { "file": "addon/utils/nf/graph-position.js", "line": 146, "description": "The y scale from either the source or graph used to calculate positions", "itemtype": "property", "name": "yScale", "type": "d3.scale", "readonly": "", "class": "utils.nf.graph-position", "module": "utils/nf/array-helpers", "namespace": "utils.nf" }, { "file": "addon/utils/nf/graph-position.js", "line": 158, "description": "The JQuery offset of the graph element", "itemtype": "property", "name": "graphOffset", "type": "Object", "readonly": "", "class": "utils.nf.graph-position", "module": "utils/nf/array-helpers", "namespace": "utils.nf" }, { "file": "addon/utils/nf/graph-position.js", "line": 174, "description": "The center point at x. Use in case of requiring a center point \nand using ordinal scale.", "itemtype": "property", "name": "centerX", "type": "Number", "class": "utils.nf.graph-position", "module": "utils/nf/array-helpers", "namespace": "utils.nf" }, { "file": "addon/utils/nf/graph-position.js", "line": 192, "description": "The center point at y. Use in case of requiring a center point \nand using ordinal scale.", "itemtype": "property", "name": "centerY", "type": "Number", "class": "utils.nf.graph-position", "module": "utils/nf/array-helpers", "namespace": "utils.nf" }, { "file": "addon/utils/nf/graph-position.js", "line": 210, "description": "The x position of the nf-graph-content within the nf-graph", "itemtype": "property", "name": "_graphContentX", "type": "Number", "access": "private", "tagname": "", "class": "utils.nf.graph-position", "module": "utils/nf/array-helpers", "namespace": "utils.nf" }, { "file": "addon/utils/nf/graph-position.js", "line": 218, "description": "The y position of the nf-graph-content within the nf-graph", "itemtype": "property", "name": "_graphContentY", "type": "Number", "access": "private", "tagname": "", "class": "utils.nf.graph-position", "module": "utils/nf/array-helpers", "namespace": "utils.nf" }, { "file": "addon/utils/nf/scale-utils.js", "line": 7, "description": "Ensures the output of a scale function is something palatable by SVG.", "itemtype": "method", "name": "normalizeScale", "params": [ { "name": "scale", "description": "the scale to use to get the value", "type": "d3.scale" }, { "name": "val", "description": "the value to transform with the scale", "type": "Any" } ], "return": { "description": "the output of the scale function, but if NaN, it will return 0.", "type": "Number" }, "class": "utils.nf.scroll-area-action-context", "module": "scale-utils" }, { "file": "addon/utils/nf/scroll-area-action-context.js", "line": 10, "description": "The scroll top in pixels.", "itemtype": "property", "name": "scrollTop", "type": "Number", "default": "0", "class": "utils.nf.scroll-area-action-context", "module": "scale-utils", "namespace": "utils.nf" }, { "file": "addon/utils/nf/scroll-area-action-context.js", "line": 18, "description": "The scroll height of the element.", "itemtype": "property", "name": "scrollHeight", "type": "number", "default": "0", "class": "utils.nf.scroll-area-action-context", "module": "scale-utils", "namespace": "utils.nf" }, { "file": "addon/utils/nf/scroll-area-action-context.js", "line": 26, "description": "The outer height of the element", "itemtype": "property", "name": "outerHeight", "type": "Number", "default": "0", "class": "utils.nf.scroll-area-action-context", "module": "scale-utils", "namespace": "utils.nf" }, { "file": "addon/utils/nf/scroll-area-action-context.js", "line": 34, "description": "The scroll left in pixels.", "itemtype": "property", "name": "scrollLeft", "type": "Number", "default": "0", "class": "utils.nf.scroll-area-action-context", "module": "scale-utils", "namespace": "utils.nf" }, { "file": "addon/utils/nf/scroll-area-action-context.js", "line": 42, "description": "The scroll width of the element.", "itemtype": "property", "name": "scrollWidth", "type": "number", "default": "0", "class": "utils.nf.scroll-area-action-context", "module": "scale-utils", "namespace": "utils.nf" }, { "file": "addon/utils/nf/scroll-area-action-context.js", "line": 50, "description": "The outer width of the element", "itemtype": "property", "name": "outerWidth", "type": "Number", "default": "0", "class": "utils.nf.scroll-area-action-context", "module": "scale-utils", "namespace": "utils.nf" }, { "file": "addon/utils/nf/scroll-area-action-context.js", "line": 58, "description": "The calculated maximum value for scrollTop in pixels.", "itemtype": "property", "name": "scrollTopMax", "type": "Number", "readonly": "", "class": "utils.nf.scroll-area-action-context", "module": "scale-utils", "namespace": "utils.nf" }, { "file": "addon/utils/nf/scroll-area-action-context.js", "line": 70, "description": "The calculated percentage, in decimals, of content scrolled.", "itemtype": "property", "name": "scrollTopPercentage", "type": "Number", "readonly": "", "class": "utils.nf.scroll-area-action-context", "module": "scale-utils", "namespace": "utils.nf" }, { "file": "addon/utils/nf/scroll-area-action-context.js", "line": 82, "description": "The calculated maximum value for scrollTop in pixels.", "itemtype": "property", "name": "scrollLeftMax", "type": "Number", "readonly": "", "class": "utils.nf.scroll-area-action-context", "module": "scale-utils", "namespace": "utils.nf" }, { "file": "addon/utils/nf/scroll-area-action-context.js", "line": 94, "description": "The calculated percentage, in decimals, of content scrolled.", "itemtype": "property", "name": "scrollLeftPercentage", "type": "Number", "readonly": "", "class": "utils.nf.scroll-area-action-context", "module": "scale-utils", "namespace": "utils.nf" }, { "file": "addon/utils/nf/scroll-area-action-context.js", "line": 106, "description": "The component that fired the event", "itemtype": "property", "name": "source", "type": "Ember.Component", "default": "null", "class": "utils.nf.scroll-area-action-context", "module": "scale-utils", "namespace": "utils.nf" }, { "file": "addon/utils/nf/scroll-area-action-context.js", "line": 114, "description": "The optional data to send with the action", "itemtype": "property", "name": "data", "default": "null", "class": "utils.nf.scroll-area-action-context", "module": "scale-utils", "namespace": "utils.nf" }, { "file": "addon/utils/nf/scroll-area-action-context.js", "line": 121, "description": "The original scroll event object", "itemtype": "property", "name": "originalEvent", "type": "Event", "default": "null", "class": "utils.nf.scroll-area-action-context", "module": "scale-utils", "namespace": "utils.nf" }, { "file": "addon/utils/nf/svg-dom.js", "line": 6, "description": "Traverses an element and all of its descendants, setting their\ninline style property to whatever the computed style is.", "itemtype": "method", "name": "inlineAllStyles", "params": [ { "name": "element", "description": "the dom element to traverse.", "type": "Element" } ], "access": "private", "tagname": "", "class": "utils.parse-property-expression", "module": "utils/nf/svg-dom" }, { "file": "addon/utils/nf/svg-dom.js", "line": 29, "description": "Renders an SVG element to a Base64 encoded data URI.", "itemtype": "method", "name": "svgToImageUrl", "params": [ { "name": "svg", "description": "the svg element to render", "type": "SVGSVGElement" } ], "class": "utils.parse-property-expression", "module": "utils/nf/svg-dom" }, { "file": "addon/utils/nf/svg-dom.js", "line": 65, "description": "Triggers a download of an image rendered from the passed svg document", "itemtype": "method", "name": "downloadSvg", "params": [ { "name": "svg", "description": "the svg document to render", "type": "SVGSVGElement" } ], "class": "utils.parse-property-expression", "module": "utils/nf/svg-dom" }, { "file": "addon/utils/nf/svg-dom.js", "line": 77, "itemtype": "method", "name": "getMousePoint", "params": [ { "name": "container", "description": "the container reference to get the mouse position from", "type": "SVGElement" }, { "name": "e", "description": "A DOM mouse event", "type": "MouseEvent" } ], "return": { "description": "the {x, y} data of the mouse position relative to the container", "type": "Object" }, "class": "utils.parse-property-expression", "module": "utils/nf/svg-dom" }, { "file": "addon/utils/nf/svg-dom.js", "line": 108, "description": "Creates an SVG path string for a rectangle", "itemtype": "method", "name": "getRectPath", "params": [ { "name": "x", "description": "the x position of the rectangle" }, { "name": "y", "description": "the y position of the rectangle", "type": "Number" }, { "name": "w", "description": "the width of the rectangle", "type": "Number" }, { "name": "h", "description": "the height of the rectangle", "type": "Number" } ], "return": { "description": "the svg path string for the rectangle", "type": "String" }, "class": "utils.parse-property-expression", "module": "utils/nf/svg-dom" }, { "file": "addon/utils/parse-property-expression.js", "line": 24, "itemtype": "method", "name": "default", "params": [ { "name": "expr", "description": "the expression to parse", "type": "String" } ], "return": { "description": "a function that when called with an object,\nwill locate the value at the end of the expressed path.", "type": "Function" }, "class": "utils.parse-property-expression", "module": "utils/nf/svg-dom", "namespace": "utils" }, { "file": "app/components/nf-area-stack.js", "line": 28, "description": "Used by `nf-area` to identify an area stack parent", "itemtype": "property", "name": "isAreaStack", "type": "Boolean", "default": "true", "readonly": "", "class": "components.nf-area-stack", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-area-stack.js", "line": 37, "description": "Whether or not to add the values together to create the stacked area", "itemtype": "property", "name": "aggregate", "type": "{boolean}", "default": "false", "class": "components.nf-area-stack", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-area-stack.js", "line": 53, "description": "The collection of `nf-area` components under this stack.", "itemtype": "property", "name": "areas", "type": "Array", "readonly": "", "class": "components.nf-area-stack", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-area-stack.js", "line": 63, "description": "Registers an area component with this stack. Also links areas to one\nanother by setting `nextArea` on each area component.", "itemtype": "method", "name": "registerArea", "params": [ { "name": "area", "description": "The area component to register.", "type": "Ember.Component" } ], "class": "components.nf-area-stack", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-area-stack.js", "line": 81, "description": "Unregisters an area component from this stack. Also updates next\nand previous links.", "itemtype": "method", "name": "unregisterArea", "params": [ { "name": "area", "description": "the area to unregister", "type": "Ember.Component" } ], "class": "components.nf-area-stack", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-area.js", "line": 34, "description": "The type of d3 interpolator to use to create the area", "itemtype": "property", "name": "interpolator", "type": "String", "default": "'linear'", "class": "components.nf-area", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-area.js", "line": 42, "description": "The previous area in the stack, if this area is part of an `nf-area-stack`", "itemtype": "property", "name": "prevArea", "type": "components.nf-area", "default": "null", "class": "components.nf-area", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-area.js", "line": 50, "description": "The next area in the stack, if this area is part of an `nf-area-stack`", "itemtype": "property", "name": "nextArea", "type": "components.nf-area", "default": "null", "class": "components.nf-area", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-area.js", "line": 67, "description": "Override from `graph-data-graphic` mixin", "itemtype": "method", "name": "getActualTrackData", "class": "components.nf-area", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-area.js", "line": 85, "description": "The computed set of next y values to use for the \"bottom\" of the graphed area.\nIf the area is part of a stack, this will be the \"top\" of the next area in the stack,\notherwise it will return an array of values at the \"bottom\" of the graph domain.", "itemtype": "property", "name": "nextYData", "type": "Array", "readonly": "", "class": "components.nf-area", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-area.js", "line": 102, "description": "The current rendered data \"zipped\" together with the nextYData.", "itemtype": "property", "name": "mappedData", "type": "Array", "readonly": "", "class": "components.nf-area", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-bars.js", "line": 34, "description": "The name of the property on each data item containing the className for the bar rectangle", "itemtype": "property", "name": "classprop", "type": "String", "default": "'className'", "class": "components.nf-bars", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-bars.js", "line": 42, "description": "Gets the function to get the classname from each data item.", "itemtype": "property", "name": "getBarClass", "readonly": "", "access": "private", "tagname": "", "class": "components.nf-bars", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-bars.js", "line": 53, "description": "The nf-bars-group this belongs to, if any.", "itemtype": "property", "name": "group", "type": "components.nf-bars-group", "default": "null", "class": "components.nf-bars", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-bars.js", "line": 61, "description": "The index of this component within the group, if any.", "itemtype": "property", "name": "groupIndex", "type": "Number", "default": "null", "class": "components.nf-bars", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-bars.js", "line": 69, "description": "The graph content height", "itemtype": "property", "name": "graphHeight", "type": "Number", "readonly": "", "class": "components.nf-bars", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-bars.js", "line": 77, "description": "A scale provided by nf-bars-group to offset the bar rectangle output", "itemtype": "property", "name": "barScale", "type": "d3.scale", "readonly": "", "class": "components.nf-bars", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-bars.js", "line": 85, "description": "The width of each bar.", "itemtype": "property", "name": "barWidth", "type": "Number", "readonly": "", "class": "components.nf-bars", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-bars.js", "line": 106, "description": "The bar models used to render the bars.", "itemtype": "property", "name": "bars", "readonly": "", "class": "components.nf-bars", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-bars.js", "line": 145, "description": "The name of the action to fire when a bar is clicked.", "itemtype": "property", "name": "barClick", "type": "String", "default": "null", "class": "components.nf-bars", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-crosshair.js", "line": 17, "description": "The height of the crosshair in pixels", "itemtype": "property", "name": "height", "type": "Number", "readonly": "", "class": "components.nf-crosshair", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-crosshair.js", "line": 25, "description": "The width of the crosshair in pixels", "itemtype": "property", "name": "width", "type": "Number", "readonly": "", "class": "components.nf-crosshair", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-crosshair.js", "line": 33, "description": "The x position of the crosshairs", "itemtype": "property", "name": "x", "type": "Number", "default": "0", "class": "components.nf-crosshair", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-crosshair.js", "line": 41, "description": "The y position of the crosshairs", "itemtype": "property", "name": "y", "type": "Number", "default": "0", "class": "components.nf-crosshair", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-crosshair.js", "line": 49, "description": "The visibility of the component", "itemtype": "property", "name": "isVisible", "type": "Boolean", "default": "false", "class": "components.nf-crosshair", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-dot.js", "line": 19, "description": "The x domain value at which to plot the circle", "itemtype": "property", "name": "x", "type": "Number", "default": "null", "class": "components.nf-dot", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-dot.js", "line": 27, "description": "The y domain value at which to plot the circle", "itemtype": "property", "name": "x", "type": "Number", "default": "null", "class": "components.nf-dot", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-dot.js", "line": 35, "description": "The radius of the circle plotted", "itemtype": "property", "name": "r", "type": "Number", "default": "2.5", "class": "components.nf-dot", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-dot.js", "line": 47, "description": "The computed center x coordinate of the circle", "itemtype": "property", "name": "cx", "type": "Number", "access": "private", "tagname": "", "readonly": "", "class": "components.nf-dot", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-dot.js", "line": 61, "description": "The computed center y coordinate of the circle", "itemtype": "property", "name": "cy", "type": "Number", "access": "private", "tagname": "", "readonly": "", "class": "components.nf-dot", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-dot.js", "line": 75, "description": "Toggles the visibility of the dot. If x or y are\nnot numbers, will return false.", "itemtype": "property", "name": "isVisible", "access": "private", "tagname": "", "readonly": "", "class": "components.nf-dot", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-graph-content.js", "line": 26, "description": "The SVG transform for positioning the graph content", "itemtype": "property", "name": "transform", "type": "String", "readonly": "", "class": "components.nf-graph-content", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-graph-content.js", "line": 38, "description": "The x position of the graph content", "itemtype": "property", "name": "x", "type": "Number", "readonly": "", "class": "components.nf-graph-content", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-graph-content.js", "line": 46, "description": "The calculated y position of the graph content", "itemtype": "property", "name": "y", "type": "Number", "readonly": "", "class": "components.nf-graph-content", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-graph-content.js", "line": 54, "description": "The calculated width of the graph content", "itemtype": "property", "name": "width", "type": "Number", "readonly": "", "class": "components.nf-graph-content", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-graph-content.js", "line": 62, "description": "The calculated height of the graph content.", "itemtype": "property", "name": "height", "type": "Number", "readonly": "", "class": "components.nf-graph-content", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-graph-content.js", "line": 71, "description": "An array containing models to render the grid lanes", "itemtype": "property", "name": "gridLanes", "type": "Array", "readonly": "", "class": "components.nf-graph-content", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-graph-content.js", "line": 110, "description": "The name of the hoverChange action to fire", "itemtype": "property", "name": "hoverChange", "type": "String", "default": "null", "class": "components.nf-graph-content", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-graph-content.js", "line": 132, "description": "The name of the hoverEnd action to fire", "itemtype": "property", "name": "hoverEnd", "type": "String", "default": "null", "class": "components.nf-graph-content", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-graph-content.js", "line": 153, "description": "An array containing models to render fret lines", "itemtype": "property", "name": "frets", "type": "Array", "readonly": "", "class": "components.nf-graph-content", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-graph.js", "line": 281, "description": "The exponent to use for xScaleType \"pow\" or \"power\".", "itemtype": "property", "name": "xPowerExponent", "type": "Number", "default": "3", "class": "components.nf-graph", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-graph.js", "line": 289, "description": "The exponent to use for yScaleType \"pow\" or \"power\".", "itemtype": "property", "name": "yPowerExponent", "type": "Number", "default": "3", "class": "components.nf-graph", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-graph.js", "line": 297, "description": "The min value to use for xScaleType \"log\" if xMin <= 0", "itemtype": "property", "name": "xLogMin", "type": "Number", "default": "0.1", "class": "components.nf-graph", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-graph.js", "line": 305, "description": "The min value to use for yScaleType \"log\" if yMin <= 0", "itemtype": "property", "name": "yLogMin", "type": "Number", "default": "0.1", "class": "components.nf-graph", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-graph.js", "line": 313, "description": "Allows child compoenents to identify graph parent.", "itemtype": "property", "name": "isGraph", "access": "private", "tagname": "", "class": "components.nf-graph", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-graph.js", "line": 320, "description": "Identifies this graph to its children as providing scales.", "itemtype": "property", "name": "isScaleSource", "access": "private", "tagname": "", "class": "components.nf-graph", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-graph.js", "line": 327, "itemtype": "property", "name": "hasRendered", "access": "private", "tagname": "", "class": "components.nf-graph", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-graph.js", "line": 333, "description": "Gets or sets the whether or not multiple selectable graphics may be\nselected simultaneously.", "itemtype": "property", "name": "selectMultiple", "type": "Boolean", "default": "false", "class": "components.nf-graph", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-graph.js", "line": 342, "description": "The width of the graph in pixels.", "itemtype": "property", "name": "width", "type": "Number", "default": "300", "class": "components.nf-graph", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-graph.js", "line": 350, "description": "The height of the graph in pixels.", "itemtype": "property", "name": "height", "type": "Number", "default": "100", "class": "components.nf-graph", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-graph.js", "line": 358, "description": "The padding at the top of the graph", "itemtype": "property", "name": "paddingTop", "type": "Number", "default": "0", "class": "components.nf-graph", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-graph.js", "line": 366, "description": "The padding at the left of the graph", "itemtype": "property", "name": "paddingLeft", "type": "Number", "default": "0", "class": "components.nf-graph", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-graph.js", "line": 374, "description": "The padding at the right of the graph", "itemtype": "property", "name": "paddingRight", "type": "Number", "default": "0", "class": "components.nf-graph", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-graph.js", "line": 382, "description": "The padding at the bottom of the graph", "itemtype": "property", "name": "paddingBottom", "type": "Number", "default": "0", "class": "components.nf-graph", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-graph.js", "line": 390, "description": "Determines whether to display \"lanes\" in the background of\nthe graph.", "itemtype": "property", "name": "showLanes", "type": "Boolean", "default": "false", "class": "components.nf-graph", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-graph.js", "line": 399, "description": "Determines whether to display \"frets\" in the background of\nthe graph.", "itemtype": "property", "name": "showFrets", "type": "Boolean", "default": "false", "class": "components.nf-graph", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-graph.js", "line": 408, "description": "The type of scale to use for x values.\n\nPossible Values:\n- `'linear'` - a standard linear scale\n- `'log'` - a logarithmic scale\n- `'power'` - a power-based scale (exponent = 3)\n- `'ordinal'` - an ordinal scale, used for ordinal data. required for bar graphs.", "itemtype": "property", "name": "xScaleType", "type": "String", "default": "'linear'", "class": "components.nf-graph", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-graph.js", "line": 423, "description": "The type of scale to use for y values.\n\nPossible Values:\n- `'linear'` - a standard linear scale\n- `'log'` - a logarithmic scale\n- `'power'` - a power-based scale (exponent = 3)\n- `'ordinal'` - an ordinal scale, used for ordinal data. required for bar graphs.", "itemtype": "property", "name": "yScaleType", "type": "String", "default": "'linear'", "class": "components.nf-graph", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-graph.js", "line": 438, "description": "The padding between value steps when `xScaleType` is `'ordinal'`", "itemtype": "property", "name": "xOrdinalPadding", "type": "Number", "default": "0.1", "class": "components.nf-graph", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-graph.js", "line": 446, "description": "The padding at the ends of the domain data when `xScaleType` is `'ordinal'`", "itemtype": "property", "name": "xOrdinalOuterPadding", "type": "Number", "default": "0.1", "class": "components.nf-graph", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-graph.js", "line": 454, "description": "The padding between value steps when `xScaleType` is `'ordinal'`", "itemtype": "property", "name": "yOrdinalPadding", "type": "Number", "default": "0.1", "class": "components.nf-graph", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-graph.js", "line": 462, "description": "The padding at the ends of the domain data when `yScaleType` is `'ordinal'`", "itemtype": "property", "name": "yOrdinalOuterPadding", "type": "Number", "default": "0.1", "class": "components.nf-graph", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-graph.js", "line": 470, "description": "the `nf-y-axis` component is registered here if there is one present", "itemtype": "property", "name": "yAxis", "readonly": "", "default": "null", "class": "components.nf-graph", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-graph.js", "line": 478, "description": "The `nf-x-axis` component is registered here if there is one present", "itemtype": "property", "name": "xAxis", "readonly": "", "default": "null", "class": "components.nf-graph", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-graph.js", "line": 486, "description": "Backing field for `xMin`", "itemtype": "property", "name": "_xMin", "access": "private", "tagname": "", "class": "components.nf-graph", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-graph.js", "line": 493, "description": "Backing field for `xMax`", "itemtype": "property", "name": "_xMax", "access": "private", "tagname": "", "class": "components.nf-graph", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-graph.js", "line": 500, "description": "Backing field for `yMin`", "itemtype": "property", "name": "_yMin", "access": "private", "tagname": "", "class": "components.nf-graph", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-graph.js", "line": 507, "description": "Backing field for `yMax`", "itemtype": "property", "name": "_yMax", "access": "private", "tagname": "", "class": "components.nf-graph", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-graph.js", "line": 514, "description": "Gets or sets the minimum x domain value to display on the graph.\nBehavior depends on `xMinMode`.", "itemtype": "property", "name": "xMin", "class": "components.nf-graph", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-graph.js", "line": 521, "description": "Gets or sets the maximum x domain value to display on the graph.\nBehavior depends on `xMaxMode`.", "itemtype": "property", "name": "xMax", "class": "components.nf-graph", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-graph.js", "line": 528, "description": "Gets or sets the minimum y domain value to display on the graph.\nBehavior depends on `yMinMode`.", "itemtype": "property", "name": "yMin", "class": "components.nf-graph", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-graph.js", "line": 535, "description": "Gets or sets the maximum y domain value to display on the graph.\nBehavior depends on `yMaxMode`.", "itemtype": "property", "name": "yMax", "class": "components.nf-graph", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-graph.js", "line": 543, "description": "Sets the behavior of `xMin` for the graph.\n\n### Possible values:\n\n- 'auto': (default) xMin is always equal to the minimum domain value contained in the graphed data. Cannot be set.\n- 'fixed': xMin can be set to an exact value and will not change based on graphed data.\n- 'push': xMin can be set to a specific value, but will update if the minimum x value contained in the graph is less than \n what xMin is currently set to.\n- 'push-tick': xMin can be set to a specific value, but will update to next \"nice\" tick if the minimum x value contained in\n the graph is less than that xMin is set to.", "itemtype": "property", "name": "xMinMode", "type": "String", "default": "'auto'", "class": "components.nf-graph", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-graph.js", "line": 561, "description": "Sets the behavior of `xMax` for the graph.\n\n### Possible values:\n\n- 'auto': (default) xMax is always equal to the maximum domain value contained in the graphed data. Cannot be set.\n- 'fixed': xMax can be set to an exact value and will not change based on graphed data.\n- 'push': xMax can be set to a specific value, but will update if the maximum x value contained in the graph is greater than \n what xMax is currently set to.\n- 'push-tick': xMax can be set to a specific value, but will update to next \"nice\" tick if the maximum x value contained in\n the graph is greater than that xMax is set to.", "itemtype": "property", "name": "xMaxMode", "type": "String", "default": "'auto'", "class": "components.nf-graph", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-graph.js", "line": 579, "description": "Sets the behavior of `yMin` for the graph.\n\n### Possible values:\n\n- 'auto': (default) yMin is always equal to the minimum domain value contained in the graphed data. Cannot be set.\n- 'fixed': yMin can be set to an exact value and will not change based on graphed data.\n- 'push': yMin can be set to a specific value, but will update if the minimum y value contained in the graph is less than \n what yMin is currently set to.\n- 'push-tick': yMin can be set to a specific value, but will update to next \"nice\" tick if the minimum y value contained in\n the graph is less than that yMin is set to.", "itemtype": "property", "name": "yMinMode", "type": "String", "default": "'auto'", "class": "components.nf-graph", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-graph.js", "line": 597, "description": "Sets the behavior of `yMax` for the graph.\n\n### Possible values:\n\n- 'auto': (default) yMax is always equal to the maximum domain value contained in the graphed data. Cannot be set.\n- 'fixed': yMax can be set to an exact value and will not change based on graphed data.\n- 'push': yMax can be set to a specific value, but will update if the maximum y value contained in the graph is greater than \n what yMax is currently set to.\n- 'push-tick': yMax can be set to a specific value, but will update to next \"nice\" tick if the maximum y value contained in\n the graph is greater than that yMax is set to.", "itemtype": "property", "name": "yMaxMode", "type": "String", "default": "'auto'", "class": "components.nf-graph", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-graph.js", "line": 615, "description": "The data extents for all data in the registered `graphics`.", "itemtype": "property", "name": "dataExtents", "type": "{Object}", "default": "{\n xMin: Number.MAX_VALUE,\n xMax: Number.MIN_VALUE,\n yMin: Number.MAX_VALUE,\n yMax: Number.MIN_VALUE\n}", "class": "components.nf-graph", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-graph.js", "line": 643, "description": "The action to trigger when the graph automatically updates the xScale \ndue to an \"auto\" \"push\" or \"push-tick\" domainMode.\n\nsends the graph component instance value as the argument.", "itemtype": "property", "name": "autoScaleXAction", "type": "{string}", "default": "null", "class": "components.nf-graph", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-graph.js", "line": 663, "description": "Event handler that is fired for the `didAutoUpdateMaxX` event", "itemtype": "method", "name": "didAutoUpdateMaxX", "class": "components.nf-graph", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-graph.js", "line": 671, "description": "Event handler that is fired for the `didAutoUpdateMinX` event", "itemtype": "method", "name": "didAutoUpdateMinX", "class": "components.nf-graph", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-graph.js", "line": 679, "description": "Event handler that is fired for the `didAutoUpdateMaxY` event", "itemtype": "method", "name": "didAutoUpdateMaxY", "class": "components.nf-graph", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-graph.js", "line": 687, "description": "Event handler that is fired for the `didAutoUpdateMinY` event", "itemtype": "method", "name": "didAutoUpdateMinY", "class": "components.nf-graph", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-graph.js", "line": 695, "description": "The action to trigger when the graph automatically updates the yScale \ndue to an \"auto\" \"push\" or \"push-tick\" domainMode.\n\nSends the graph component instance as the argument.", "itemtype": "property", "name": "autoScaleYAction", "type": "{string}", "default": "null", "class": "components.nf-graph", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-graph.js", "line": 707, "description": "Gets the highest and lowest x values of the graphed data in a two element array.", "itemtype": "property", "name": "xDataExtent", "type": "Array", "readonly": "", "class": "components.nf-graph", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-graph.js", "line": 718, "description": "Gets the highest and lowest y values of the graphed data in a two element array.", "itemtype": "property", "name": "yDataExtent", "type": "Array", "readonly": "", "class": "components.nf-graph", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-graph.js", "line": 729, "itemtype": "property", "name": "xUniqueData", "type": "Array", "readonly": "", "class": "components.nf-graph", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-graph.js", "line": 748, "itemtype": "property", "name": "yUniqueData", "type": "Array", "readonly": "", "class": "components.nf-graph", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-graph.js", "line": 766, "description": "Gets the DOM id for the content clipPath element.", "itemtype": "property", "name": "contentClipPathId", "type": "String", "readonly": "", "access": "private", "tagname": "", "class": "components.nf-graph", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-graph.js", "line": 777, "description": "Registry of contained graphic elements such as `nf-line` or `nf-area` components.\nThis registry is used to pool data for scaling purposes.", "itemtype": "property", "name": "graphics", "type": "Array", "readonly": "", "class": "components.nf-graph", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-graph.js", "line": 788, "description": "An array of \"selectable\" graphics that have been selected within this graph.", "itemtype": "property", "name": "selected", "type": "Array", "readonly": "", "class": "components.nf-graph", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-graph.js", "line": 796, "description": "Computed property to show yAxis. Returns `true` if a yAxis is present.", "itemtype": "property", "name": "showYAxis", "type": "Boolean", "default": "false", "class": "components.nf-graph", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-graph.js", "line": 804, "description": "Computed property to show xAxis. Returns `true` if an xAxis is present.", "itemtype": "property", "name": "showXAxis", "type": "Boolean", "default": "false", "class": "components.nf-graph", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-graph.js", "line": 812, "description": "Gets a function to create the xScale", "itemtype": "property", "name": "xScaleFactory", "readonly": "", "class": "components.nf-graph", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-graph.js", "line": 819, "description": "Gets a function to create the yScale", "itemtype": "property", "name": "yScaleFactory", "readonly": "", "class": "components.nf-graph", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-graph.js", "line": 826, "description": "Gets the domain of x values.", "itemtype": "property", "name": "xDomain", "type": "Array", "readonly": "", "class": "components.nf-graph", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-graph.js", "line": 834, "description": "Gets the domain of y values.", "itemtype": "property", "name": "yDomain", "type": "Array", "readonly": "", "class": "components.nf-graph", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-graph.js", "line": 842, "description": "Gets the current xScale used to draw the graph.", "itemtype": "property", "name": "xScale", "type": "Function", "readonly": "", "class": "components.nf-graph", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-graph.js", "line": 850, "description": "Gets the current yScale used to draw the graph.", "itemtype": "property", "name": "yScale", "type": "Function", "readonly": "", "class": "components.nf-graph", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-graph.js", "line": 858, "description": "Registers a graphic such as `nf-line` or `nf-area` components with the graph.", "itemtype": "method", "name": "registerGraphic", "params": [ { "name": "graphic", "description": "The component object to register", "type": "Ember.Component" } ], "class": "components.nf-graph", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-graph.js", "line": 869, "description": "Unregisters a graphic such as an `nf-line` or `nf-area` from the graph.", "itemtype": "method", "name": "unregisterGraphic", "params": [ { "name": "graphic", "description": "The component to unregister", "type": "Ember.Component" } ], "class": "components.nf-graph", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-graph.js", "line": 885, "description": "The y range of the graph in pixels. The min and max pixel values\nin an array form.", "itemtype": "property", "name": "yRange", "type": "Array", "readonly": "", "class": "components.nf-graph", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-graph.js", "line": 896, "description": "The x range of the graph in pixels. The min and max pixel values\nin an array form.", "itemtype": "property", "name": "xRange", "type": "Array", "readonly": "", "class": "components.nf-graph", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-graph.js", "line": 907, "description": "Returns `true` if the graph has data to render. Data is conveyed\nto the graph by registered graphics.", "itemtype": "property", "name": "hasData", "type": "Boolean", "default": "false", "readonly": "", "class": "components.nf-graph", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-graph.js", "line": 917, "description": "The x coordinate position of the graph content", "itemtype": "property", "name": "graphX", "type": "Number", "readonly": "", "class": "components.nf-graph", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-graph.js", "line": 933, "description": "The y coordinate position of the graph content", "itemtype": "property", "name": "graphY", "type": "Number", "readonly": "", "class": "components.nf-graph", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-graph.js", "line": 949, "description": "The width, in pixels, of the graph content", "itemtype": "property", "name": "graphWidth", "type": "Number", "readonly": "", "class": "components.nf-graph", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-graph.js", "line": 963, "description": "The height, in pixels, of the graph content", "itemtype": "property", "name": "graphHeight", "type": "Number", "readonly": "", "class": "components.nf-graph", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-graph.js", "line": 977, "description": "An SVG transform to position the graph content", "itemtype": "property", "name": "graphTransform", "type": "String", "readonly": "", "class": "components.nf-graph", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-graph.js", "line": 989, "description": "Sets `hasRendered` to `true` on `willInsertElement`.", "itemtype": "method", "name": "_notifyHasRendered", "access": "private", "tagname": "", "class": "components.nf-graph", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-graph.js", "line": 998, "description": "Gets the mouse position relative to the container", "itemtype": "method", "name": "mousePoint", "params": [ { "name": "container", "description": "the SVG element that contains the mouse event", "type": "SVGElement" }, { "name": "e", "description": "the DOM mouse event", "type": "Object" } ], "return": { "description": "an array of `[xMouseCoord, yMouseCoord]`", "type": "Array" }, "class": "components.nf-graph", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-graph.js", "line": 1018, "description": "A computed property returned the view's controller.", "itemtype": "property", "name": "parentController", "type": "Ember.Controller", "readonly": "", "class": "components.nf-graph", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-graph.js", "line": 1026, "description": "Selects the graphic passed. If `selectMultiple` is false, it will deselect the currently\nselected graphic if it's different from the one passed.", "itemtype": "method", "name": "selectGraphic", "params": [ { "name": "graphic", "description": "the graph component to select within the graph.", "type": "Ember.Component" } ], "class": "components.nf-graph", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-graph.js", "line": 1047, "description": "deselects the graphic passed.", "itemtype": "method", "name": "deselectGraphic", "params": [ { "name": "graphic", "description": "the graph child component to deselect.", "type": "Ember.Component" } ], "class": "components.nf-graph", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-graph.js", "line": 1064, "description": "The initialization method. Fired on `init`.", "itemtype": "method", "name": "_setup", "access": "private", "tagname": "", "class": "components.nf-graph", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-graph.js", "line": 1074, "description": "The amount of leeway, in pixels, to give before triggering a brush start.", "itemtype": "property", "name": "brushThreshold", "type": "{Number}", "default": "7", "class": "components.nf-graph", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-graph.js", "line": 1082, "description": "The name of the action to trigger when brushing starts", "itemtype": "property", "name": "brushStartAction", "type": "{String}", "default": "null", "class": "components.nf-graph", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-graph.js", "line": 1090, "description": "The name of the action to trigger when brushing emits a new value", "itemtype": "property", "name": "brushAction", "type": "{String}", "default": "null", "class": "components.nf-graph", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-graph.js", "line": 1098, "description": "The name of the action to trigger when brushing ends", "itemtype": "property", "name": "brushEndAction", "type": "{String}", "default": "null", "class": "components.nf-graph", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-horizontal-line.js", "line": 20, "description": "The y domain value at which to draw the horizontal line", "itemtype": "property", "name": "y", "type": "Number", "default": "null", "class": "components.nf-horizontal-line", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-horizontal-line.js", "line": 28, "description": "The computed y coordinate of the line to draw", "itemtype": "property", "name": "lineY", "type": "Number", "access": "private", "tagname": "", "readonly": "", "class": "components.nf-horizontal-line", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-horizontal-line.js", "line": 42, "description": "The left x coordinate of the line", "itemtype": "property", "name": "x1", "type": "Number", "default": "0", "access": "private", "tagname": "", "class": "components.nf-horizontal-line", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-horizontal-line.js", "line": 51, "description": "The right x coordinate of the line", "itemtype": "property", "name": "x2", "type": "Number", "access": "private", "tagname": "", "readonly": "", "class": "components.nf-horizontal-line", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-line.js", "line": 28, "description": "The type of D3 interpolator to use to create the line.", "itemtype": "property", "name": "interpolator", "type": "String", "default": "'linear'", "class": "components.nf-line", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-line.js", "line": 40, "description": "The d3 line function to create the line path.", "itemtype": "method", "name": "lineFn", "params": [ { "name": "data", "description": "the array of coordinate arrays to plot as an SVG path", "type": "Array" } ], "access": "private", "tagname": "", "return": { "description": "an SVG path data string", "type": "String" }, "class": "components.nf-line", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-line.js", "line": 54, "description": "The SVG path data string to render the line", "itemtype": "property", "name": "d", "type": "String", "access": "private", "tagname": "", "readonly": "", "class": "components.nf-line", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-line.js", "line": 67, "description": "Event handler to toggle the `selected` property on click", "itemtype": "method", "name": "_toggleSelected", "access": "private", "tagname": "", "class": "components.nf-line", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-plot.js", "line": 21, "description": "The x domain value to set the plot at", "itemtype": "property", "name": "x", "default": "null", "class": "components.nf-plot", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-plot.js", "line": 28, "description": "The y domain value to set the plot at", "itemtype": "property", "name": "x", "default": "null", "class": "components.nf-plot", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-plot.js", "line": 35, "description": "True if an `x` value is present (defined, not null and non-empty)", "itemtype": "property", "name": "hasX", "type": "Boolean", "readonly": "", "class": "components.nf-plot", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-plot.js", "line": 43, "description": "True if an `y` value is present (defined, not null and non-empty)", "itemtype": "property", "name": "hasY", "type": "Boolean", "readonly": "", "class": "components.nf-plot", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-plot.js", "line": 51, "description": "The calculated visibility of the component", "itemtype": "property", "name": "isVisible", "type": "Boolean", "readonly": "", "class": "components.nf-plot", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-plot.js", "line": 59, "description": "The calculated x coordinate", "itemtype": "property", "name": "rangeX", "type": "Number", "readonly": "", "class": "components.nf-plot", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-plot.js", "line": 72, "description": "The calculated y coordinate", "itemtype": "property", "name": "rangeY", "type": "Number", "readonly": "", "class": "components.nf-plot", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-plot.js", "line": 85, "description": "The SVG transform of the component's `` tag.", "itemtype": "property", "name": "transform", "type": "String", "readonly": "", "class": "components.nf-plot", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-plots.js", "line": 11, "description": "The parent controller to use for template binding", "itemtype": "property", "name": "parentController", "type": "Ember.Controller", "readonly": "", "access": "private", "tagname": "", "class": "components.nf-range-marker", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-plots.js", "line": 20, "description": "The model for adding plots to the graph", "itemtype": "property", "name": "plotData", "readonly": "", "access": "private", "tagname": "", "class": "components.nf-range-marker", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-range-marker.js", "line": 21, "description": "The parent `nf-range-markers` component.", "itemtype": "property", "name": "container", "type": "{components.nf-range-markers}", "default": "null", "class": "components.nf-range-marker", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-range-marker.js", "line": 29, "description": "The minimum domain value for the range to mark.", "itemtype": "property", "name": "xMin", "default": "0", "class": "components.nf-range-marker", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-range-marker.js", "line": 36, "description": "The maximum domain value for the range to mark.", "itemtype": "property", "name": "xMax", "default": "0", "class": "components.nf-range-marker", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-range-marker.js", "line": 43, "description": "The spacing above the range marker.", "itemtype": "property", "name": "marginTop", "type": "Number", "default": "10", "class": "components.nf-range-marker", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-range-marker.js", "line": 51, "description": "The spacing below the range marker.", "itemtype": "property", "name": "marginBottom", "type": "Number", "default": "3", "class": "components.nf-range-marker", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-range-marker.js", "line": 59, "description": "The height of the range marker.", "itemtype": "property", "name": "height", "type": "Number", "default": "10", "class": "components.nf-range-marker", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-range-marker.js", "line": 67, "description": "The computed x position of the range marker.", "itemtype": "property", "name": "x", "type": "Number", "readonly": "", "class": "components.nf-range-marker", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-range-marker.js", "line": 79, "description": "The computed width of the range marker.", "itemtype": "property", "name": "width", "type": "Number", "readonly": "", "class": "components.nf-range-marker", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-range-marker.js", "line": 92, "description": "The computed y position of the range marker.", "itemtype": "property", "name": "y", "type": "Number", "readonly": "", "class": "components.nf-range-marker", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-range-marker.js", "line": 123, "description": "The computed total height of the range marker including its margins.", "itemtype": "property", "name": "totalHeight", "type": "Number", "readonly": "", "class": "components.nf-range-marker", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-range-marker.js", "line": 136, "description": "The computed bottom of the range marker, not including the bottom margin.", "itemtype": "property", "name": "bottom", "type": "Number", "readonly": "", "class": "components.nf-range-marker", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-range-marker.js", "line": 148, "description": "The computed SVG transform of the range marker container", "itemtype": "property", "name": "transform", "type": "String", "readonly": "", "class": "components.nf-range-marker", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-range-marker.js", "line": 159, "description": "The computed SVG transform fo the range marker label container.", "itemtype": "property", "name": "labelTransform", "type": "String", "readonly": "", "class": "components.nf-range-marker", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-range-marker.js", "line": 170, "description": "Initialization function that registers the range marker with its parent \nand populates the container property", "itemtype": "method", "name": "_setup", "access": "private", "tagname": "", "class": "components.nf-range-marker", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-range-marker.js", "line": 183, "description": "Unregisters the range marker from its parent when the range marker is destroyed.", "itemtype": "method", "name": "_unregister", "access": "private", "tagname": "", "class": "components.nf-range-marker", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-range-markers.js", "line": 16, "description": "Used by `nf-range-marker` to identify the `nf-range-markers` container", "itemtype": "property", "name": "isRangeMarkerContainer", "type": "Boolean", "default": "true", "readonly": "", "class": "components.nf-range-markers", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-range-markers.js", "line": 25, "description": "Sets the orientation of the range markers.\n\n- `'bottom'` - Range markers start at the bottom and stack upward\n- `'top'` - Range markers start at the top and stack downward", "itemtype": "property", "name": "orient", "type": "String", "default": "'bottom'", "class": "components.nf-range-markers", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-range-markers.js", "line": 36, "description": "The margin, in pixels, between the markers", "itemtype": "property", "name": "markerMargin", "type": "Number", "default": "10", "class": "components.nf-range-markers", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-range-markers.js", "line": 44, "description": "The marker components registered with this container", "itemtype": "property", "name": "markers", "type": "Array", "readonly": "", "class": "components.nf-range-markers", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-range-markers.js", "line": 54, "description": "Adds the passed marker to the `markers` list, and sets the `prevMarker` and `nextMarker`\nproperties on the marker component and it's neighbor.", "itemtype": "method", "name": "registerMarker", "params": [ { "name": "marker", "description": "the range marker to register with this container", "type": "Nf-range-marker" } ], "class": "components.nf-range-markers", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-range-markers.js", "line": 72, "description": "Removes the marker from the `markers` list. Also updates the `nextMarker` and `prevMarker`\nproperties of it's neighboring components.", "itemtype": "method", "name": "unregisterMarker", "params": [ { "name": "marker", "description": "the range marker to remove from the `markers` list.", "type": "Nf-range-marker" } ], "class": "components.nf-range-markers", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-right-tick.js", "line": 25, "description": "The transition duration in milliseconds", "itemtype": "property", "name": "duration", "type": "Number", "default": "400", "class": "components.nf-right-tick", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-right-tick.js", "line": 33, "description": "The domain value at which to place the tick", "itemtype": "property", "name": "value", "type": "Number", "default": "null", "class": "components.nf-right-tick", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-right-tick.js", "line": 41, "description": "Sets the visibility of the component. Returns false if `y` is not \na numeric data type.", "itemtype": "property", "name": "isVisible", "access": "private", "tagname": "", "readonly": "", "class": "components.nf-right-tick", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-right-tick.js", "line": 52, "description": "The calculated y coordinate of the tick", "itemtype": "property", "name": "y", "type": "Number", "readonly": "", "class": "components.nf-right-tick", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-right-tick.js", "line": 69, "description": "The SVG transform used to render the tick", "itemtype": "property", "name": "transform", "type": "String", "access": "private", "tagname": "", "readonly": "", "class": "components.nf-right-tick", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-right-tick.js", "line": 84, "description": "performs the D3 transition to move the tick to the proper position.", "itemtype": "method", "name": "_transitionalUpdate", "access": "private", "tagname": "", "class": "components.nf-right-tick", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-right-tick.js", "line": 97, "description": "Schedules the transition when `value` changes on on init.", "itemtype": "method", "name": "_triggerTransition", "access": "private", "tagname": "", "class": "components.nf-right-tick", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-right-tick.js", "line": 106, "description": "Updates the tick position without a transition.", "itemtype": "method", "name": "_nonTransitionalUpdate", "access": "private", "tagname": "", "class": "components.nf-right-tick", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-right-tick.js", "line": 117, "description": "Schedules the update of non-transitional positions", "itemtype": "method", "name": "_triggerNonTransitionalUpdate", "access": "private", "tagname": "", "class": "components.nf-right-tick", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-right-tick.js", "line": 126, "description": "Gets the elements required to do the d3 transitions", "itemtype": "method", "name": "_getElements", "access": "private", "tagname": "", "class": "components.nf-right-tick", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-selection-box.js", "line": 17, "description": "The duration of the transition in ms", "itemtype": "property", "name": "duration", "type": "Number", "default": "400", "class": "components.nf-selection-box", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-selection-box.js", "line": 25, "description": "The minimum x domain value to encompass.", "itemtype": "property", "name": "xMin", "default": "null", "class": "components.nf-selection-box", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-selection-box.js", "line": 32, "description": "The maximum x domain value to encompoass.", "itemtype": "property", "name": "xMax", "default": "null", "class": "components.nf-selection-box", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-selection-box.js", "line": 39, "description": "The minimum y domain value to encompass.", "itemtype": "property", "name": "yMin", "default": "null", "class": "components.nf-selection-box", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-selection-box.js", "line": 46, "description": "The maximum y domain value to encompass", "itemtype": "property", "name": "yMax", "default": "null", "class": "components.nf-selection-box", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-selection-box.js", "line": 55, "description": "The x pixel position of xMin", "itemtype": "property", "name": "x0", "type": "Number", "class": "components.nf-selection-box", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-selection-box.js", "line": 64, "description": "The x pixel position of xMax", "itemtype": "property", "name": "x1", "type": "Number", "class": "components.nf-selection-box", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-selection-box.js", "line": 73, "description": "The y pixel position of yMin", "itemtype": "property", "name": "y0", "type": "Number", "class": "components.nf-selection-box", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-selection-box.js", "line": 82, "description": "The y pixel position of yMax", "itemtype": "property", "name": "y1", "type": "Number", "class": "components.nf-selection-box", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-selection-box.js", "line": 91, "description": "The SVG path string for the box's rectangle.", "itemtype": "property", "name": "rectPath", "type": "String", "class": "components.nf-selection-box", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-selection-box.js", "line": 104, "description": "Updates the position of the box with a transition", "itemtype": "method", "name": "doUpdatePosition", "class": "components.nf-selection-box", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-selection-box.js", "line": 124, "description": "Schedules an update to the position of the box after render.", "itemtype": "method", "name": "updatePosition", "access": "private", "tagname": "", "class": "components.nf-selection-box", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-selection-box.js", "line": 137, "description": "Sets up the required d3 elements after component\nis inserted into the DOM", "itemtype": "method", "name": "didInsertElement", "class": "components.nf-selection-box", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-svg-image.js", "line": 31, "description": "The domain x value to place the image at.", "itemtype": "property", "name": "x", "default": "null", "class": "components.nf-svg-image", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-svg-image.js", "line": 38, "description": "The domain y value to place the image at.", "itemtype": "property", "name": "y", "default": "null", "class": "components.nf-svg-image", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-svg-image.js", "line": 47, "description": "The width as a domain value. Does not handle ordinal\nscales. To set a pixel value, set `svgWidth` directly.", "itemtype": "property", "name": "width", "type": "Number", "default": "0", "class": "components.nf-svg-image", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-svg-image.js", "line": 63, "description": "The height as a domain value. Does not \nhandle ordinal scales. To set a pixel value, just\nset `svgHeight` directly.", "itemtype": "property", "name": "height", "default": "null", "class": "components.nf-svg-image", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-svg-image.js", "line": 77, "description": "The image source url", "itemtype": "property", "name": "src", "type": "String", "class": "components.nf-svg-image", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-svg-image.js", "line": 115, "description": "The pixel value at which to plot the image.", "itemtype": "property", "name": "svgX", "type": "Number", "class": "components.nf-svg-image", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-svg-image.js", "line": 124, "description": "The pixel value at which to plot the image.", "itemtype": "property", "name": "svgY", "type": "Number", "class": "components.nf-svg-image", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-svg-image.js", "line": 133, "description": "The width, in pixels, of the image.", "itemtype": "property", "name": "svgWidth", "type": "Number", "class": "components.nf-svg-image", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-svg-image.js", "line": 142, "description": "The height, in pixels of the image.", "itemtype": "property", "name": "svgHeight", "type": "Number", "class": "components.nf-svg-image", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-svg-line.js", "line": 29, "description": "The domain value to plot the SVGLineElement's x1 at.", "itemtype": "property", "name": "x1", "default": "null", "class": "components.nf-svg-line", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-svg-line.js", "line": 36, "description": "The domain value to plot the SVGLineElement's x2 at.", "itemtype": "property", "name": "x2", "default": "null", "class": "components.nf-svg-line", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-svg-line.js", "line": 43, "description": "The domain value to plot the SVGLineElement's y1 at.", "itemtype": "property", "name": "y1", "default": "null", "class": "components.nf-svg-line", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-svg-line.js", "line": 50, "description": "The domain value to plot the SVGLineElement's y2 at.", "itemtype": "property", "name": "y2", "default": "null", "class": "components.nf-svg-line", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-svg-line.js", "line": 57, "description": "The pixel value to plot the SVGLineElement's x1 at.", "itemtype": "property", "name": "svgX1", "type": "Number", "class": "components.nf-svg-line", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-svg-line.js", "line": 66, "description": "The pixel value to plot the SVGLineElement's x2 at.", "itemtype": "property", "name": "svgX2", "type": "Number", "class": "components.nf-svg-line", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-svg-line.js", "line": 75, "description": "The pixel value to plot the SVGLineElement's y1 at.", "itemtype": "property", "name": "svgY1", "type": "Number", "class": "components.nf-svg-line", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-svg-line.js", "line": 84, "description": "The pixel value to plot the SVGLineElement's y2 at.", "itemtype": "property", "name": "svgY2", "type": "Number", "class": "components.nf-svg-line", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-svg-path.js", "line": 23, "description": "The array of points to use to plot the path. This is an array of arrays, in the following format:\n\n // specify path pen commands\n [\n [50, 50, 'L'],\n [100, 100, 'L']\n ]\n\n // or they will default to 'L'\n [\n [50, 50],\n [100, 100]\n ]", "itemtype": "property", "name": "points", "type": "Array", "class": "components.nf-svg-path", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-svg-path.js", "line": 43, "description": "The data points mapped to scale", "itemtype": "property", "name": "svgPoints", "type": "Array", "class": "components.nf-svg-path", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-svg-path.js", "line": 68, "description": "The raw svg path d attribute output", "itemtype": "property", "name": "d", "type": "String", "class": "components.nf-svg-path", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-svg-rect.js", "line": 24, "description": "The domain x value to place the rect at.", "itemtype": "property", "name": "x", "default": "null", "class": "components.nf-svg-rect", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-svg-rect.js", "line": 31, "description": "The domain y value to place the rect at.", "itemtype": "property", "name": "y", "default": "null", "class": "components.nf-svg-rect", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-svg-rect.js", "line": 40, "description": "The width as a domain value. If xScale is ordinal, \nthen this value is the indice offset to which to draw the \nrectangle. In other words, if it's `2`, then draw the rectangle\nto two ordinals past whatever `x` is set to.", "itemtype": "property", "name": "width", "type": "Number", "default": "0", "class": "components.nf-svg-rect", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-svg-rect.js", "line": 58, "description": "The height as a domain value. If the yScale is ordinal,\nthis value is the indice offset to which to draw the rectangle.\nFor example, if the height is `3` then draw the rectangle\nto two ordinals passed whatever `y` is set to.", "itemtype": "property", "name": "height", "type": "Number", "default": "0", "class": "components.nf-svg-rect", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-svg-rect.js", "line": 74, "description": "The x value of the bottom right corner of the rectangle.", "itemtype": "property", "name": "x1", "type": "Number", "class": "components.nf-svg-rect", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-svg-rect.js", "line": 94, "description": "The y value of the bottom right corner of the rectangle", "itemtype": "property", "name": "y1", "type": "Number", "class": "components.nf-svg-rect", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-svg-rect.js", "line": 114, "description": "The x value of the top right corner of the rectangle", "itemtype": "property", "name": "x0", "type": "Number", "class": "components.nf-svg-rect", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-svg-rect.js", "line": 123, "description": "The y value of the top right corner of the rectangle.", "itemtype": "property", "name": "y0", "type": "Number", "class": "components.nf-svg-rect", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-svg-rect.js", "line": 132, "description": "The SVG path data for the rectangle", "itemtype": "property", "name": "d", "type": "String", "class": "components.nf-svg-rect", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-svg-rect.js", "line": 145, "description": "Click event handler. Toggles selected if selectable.", "itemtype": "method", "name": "click", "class": "components.nf-svg-rect", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-vertical-line.js", "line": 20, "description": "The top y coordinate of the line", "itemtype": "property", "name": "y1", "type": "Number", "default": "0", "access": "private", "tagname": "", "class": "components.nf-vertical-line", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-vertical-line.js", "line": 29, "description": "The bottom y coordinate of the line", "itemtype": "property", "name": "y2", "type": "Number", "access": "private", "tagname": "", "readonly": "", "class": "components.nf-vertical-line", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-vertical-line.js", "line": 38, "description": "The x domain value at which to draw the vertical line on the graph", "itemtype": "property", "name": "x", "type": "Number", "default": "null", "class": "components.nf-vertical-line", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-vertical-line.js", "line": 46, "description": "The calculated x coordinate of the vertical line", "itemtype": "property", "name": "lineX", "type": "Number", "access": "private", "tagname": "", "readonly": "", "class": "components.nf-vertical-line", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-x-axis.js", "line": 54, "description": "The height of the x axis in pixels.", "itemtype": "property", "name": "height", "type": "Number", "default": "20", "class": "components.nf-x-axis", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-x-axis.js", "line": 62, "description": "The number of ticks to display", "itemtype": "property", "name": "tickCount", "type": "Number", "default": "12", "class": "components.nf-x-axis", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-x-axis.js", "line": 70, "description": "The length of the tick line (the small vertical line indicating the tick)", "itemtype": "property", "name": "tickLength", "type": "Number", "default": "0", "class": "components.nf-x-axis", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-x-axis.js", "line": 78, "description": "The spacing between the end of the tick line and the origin of the templated\ntick content", "itemtype": "property", "name": "tickPadding", "type": "Number", "default": "5", "class": "components.nf-x-axis", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-x-axis.js", "line": 87, "description": "The orientation of the x axis. Value can be `'top'` or `'bottom'`.", "itemtype": "property", "name": "orient", "type": "String", "default": "'bottom'", "class": "components.nf-x-axis", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-x-axis.js", "line": 97, "description": "An optional filtering function to allow more control over what tick marks are displayed.\nThe function should have exactly the same signature as the function you'd use for an\n`Array.prototype.filter()`.", "itemtype": "property", "name": "tickFilter", "type": "Function", "default": "null", "example": [ "\n\n {{#nf-x-axis tickFilter=myFilter as |tick|}}\n {{tick.value}}\n {{/nf-x-axis}}\n\nAnd on your controller:\n\n myFilter: function(tick, index, ticks) {\n return tick.value < 1000;\n },\n\nThe above example will filter down the set of ticks to only those that are less than 1000." ], "class": "components.nf-x-axis", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-x-axis.js", "line": 121, "description": "The class applied due to orientation (e.g. `'orient-top'`)", "itemtype": "property", "name": "orientClass", "type": "String", "readonly": "", "class": "components.nf-x-axis", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-x-axis.js", "line": 131, "description": "The SVG Transform applied to this component's container.", "itemtype": "property", "name": "transform", "type": "String", "readonly": "", "class": "components.nf-x-axis", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-x-axis.js", "line": 143, "description": "The y position of this component's container.", "itemtype": "property", "name": "y", "type": "Number", "readonly": "", "class": "components.nf-x-axis", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-x-axis.js", "line": 173, "description": "This x position of this component's container", "itemtype": "property", "name": "x", "type": "Number", "readonly": "", "class": "components.nf-x-axis", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-x-axis.js", "line": 188, "description": "The width of the component", "itemtype": "property", "name": "width", "type": "Number", "readonly": "", "class": "components.nf-x-axis", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-x-axis.js", "line": 196, "description": "A method to call to override the default behavior of how ticks are created.\n\nThe function signature should match:\n\n // - scale: d3.Scale\n // - tickCount: number of ticks\n // - uniqueData: unique data points for the axis\n // - scaleType: string of \"linear\" or \"ordinal\"\n // returns: an array of tick values.\n function(scale, tickCount, uniqueData, scaleType) {\n return [100,200,300];\n }", "itemtype": "property", "name": "tickFactory", "type": "{Function}", "default": "null", "class": "components.nf-x-axis", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-x-axis.js", "line": 234, "description": "A unique set of all x data on the graph", "itemtype": "property", "name": "uniqueXData", "type": "Array", "readonly": "", "class": "components.nf-x-axis", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-x-axis.js", "line": 242, "description": "The models for the ticks to display on the axis.", "itemtype": "property", "name": "ticks", "type": "Array", "readonly": "", "class": "components.nf-x-axis", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-x-axis.js", "line": 288, "description": "The y position, in pixels, of the axis line", "itemtype": "property", "name": "axisLineY", "type": "Number", "readonly": "", "class": "components.nf-x-axis", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-y-axis.js", "line": 49, "description": "The number of ticks to display", "itemtype": "property", "name": "tickCount", "type": "Number", "default": "5", "class": "components.nf-y-axis", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-y-axis.js", "line": 57, "description": "The length of the tick's accompanying line.", "itemtype": "property", "name": "tickLength", "type": "Number", "default": "5", "class": "components.nf-y-axis", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-y-axis.js", "line": 65, "description": "The distance between the tick line and the origin tick's templated output", "itemtype": "property", "name": "tickPadding", "type": "Number", "default": "3", "class": "components.nf-y-axis", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-y-axis.js", "line": 73, "description": "The total width of the y axis", "itemtype": "property", "name": "width", "type": "Number", "default": "40", "class": "components.nf-y-axis", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-y-axis.js", "line": 81, "description": "The orientation of the y axis. Possible values are `'left'` and `'right'`", "itemtype": "property", "name": "orient", "type": "String", "default": "'left'", "class": "components.nf-y-axis", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-y-axis.js", "line": 95, "description": "An optional filtering function to allow more control over what tick marks are displayed.\nThe function should have exactly the same signature as the function you'd use for an\n`Array.prototype.filter()`.", "itemtype": "property", "name": "tickFilter", "type": "Function", "default": "null", "example": [ "\n\n {{#nf-y-axis tickFilter=myFilter as |tick|}}\n {{tick.value}}\n {{/nf-y-axis}}\n \nAnd on your controller:\n\n myFilter: function(tick, index, ticks) {\n return tick.value < 1000;\n },\n \nThe above example will filter down the set of ticks to only those that are less than 1000." ], "class": "components.nf-y-axis", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-y-axis.js", "line": 124, "description": "computed property. returns true if `orient` is equal to `'right'`.", "itemtype": "property", "name": "isOrientRight", "type": "Boolean", "readonly": "", "class": "components.nf-y-axis", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-y-axis.js", "line": 133, "description": "The SVG transform for positioning the component.", "itemtype": "property", "name": "transform", "type": "String", "readonly": "", "class": "components.nf-y-axis", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-y-axis.js", "line": 145, "description": "The x position of the component", "itemtype": "property", "name": "x", "type": "Number", "readonly": "", "class": "components.nf-y-axis", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-y-axis.js", "line": 166, "description": "The y position of the component", "itemtype": "property", "name": "y", "type": "Number", "readonly": "", "class": "components.nf-y-axis", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-y-axis.js", "line": 174, "description": "the height of the component", "itemtype": "property", "name": "height", "type": "Number", "readonly": "", "class": "components.nf-y-axis", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-y-axis.js", "line": 187, "description": "A method to call to override the default behavior of how ticks are created.\n\nThe function signature should match:\n\n // - scale: d3.Scale\n // - tickCount: number of ticks\n // - uniqueData: unique data points for the axis\n // - scaleType: string of \"linear\" or \"ordinal\"\n // returns: an array of tick values.\n function(scale, tickCount, uniqueData, scaleType) {\n return [100,200,300];\n }", "itemtype": "property", "name": "tickFactory", "type": "{Function}", "default": "null", "class": "components.nf-y-axis", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-y-axis.js", "line": 232, "description": "All y data from the graph, filtered to unique values.", "itemtype": "property", "name": "uniqueYData", "type": "Array", "readonly": "", "class": "components.nf-y-axis", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-y-axis.js", "line": 240, "description": "The ticks to be displayed.", "itemtype": "property", "name": "ticks", "type": "Array", "readonly": "", "class": "components.nf-y-axis", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-y-axis.js", "line": 284, "description": "The x position of the axis line.", "itemtype": "property", "name": "axisLineX", "type": "Number", "readonly": "", "class": "components.nf-y-axis", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-y-diff.js", "line": 30, "description": "The starting domain value of the difference measurement. The subrahend of the difference calculation.", "itemtype": "property", "name": "a", "type": "Number", "default": "null", "class": "components.nf-y-diff", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-y-diff.js", "line": 38, "description": "The ending domain value of the difference measurement. The minuend of the difference calculation.", "itemtype": "property", "name": "b", "type": "Number", "default": "null", "class": "components.nf-y-diff", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-y-diff.js", "line": 46, "description": "The amount of padding, in pixels, between the edge of the difference \"box\" and the content container", "itemtype": "property", "name": "contentPadding", "type": "Number", "default": "5", "class": "components.nf-y-diff", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-y-diff.js", "line": 54, "description": "The duration of the transition, in milliseconds, as the difference slides vertically", "itemtype": "property", "name": "duration", "type": "Number", "default": "400", "class": "components.nf-y-diff", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-y-diff.js", "line": 62, "description": "The calculated vertical center of the difference box, in pixels.", "itemtype": "property", "name": "yCenter", "type": "Number", "readonly": "", "class": "components.nf-y-diff", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-y-diff.js", "line": 74, "description": "The y pixel value of b.", "itemtype": "property", "name": "yB", "type": "Number", "class": "components.nf-y-diff", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-y-diff.js", "line": 83, "description": "The y pixel value of a.", "itemtype": "property", "name": "yA", "type": "Number", "class": "components.nf-y-diff", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-y-diff.js", "line": 92, "description": "The SVG transformation of the component.", "itemtype": "property", "name": "transform", "type": "String", "access": "private", "tagname": "", "readonly": "", "class": "components.nf-y-diff", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-y-diff.js", "line": 101, "description": "The calculated difference between `a` and `b`.", "itemtype": "property", "name": "diff", "type": "Number", "readonly": "", "class": "components.nf-y-diff", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-y-diff.js", "line": 111, "description": "Returns `true` if `diff` is a positive number", "itemtype": "property", "name": "isPositive", "type": "Boolean", "readonly": "", "class": "components.nf-y-diff", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-y-diff.js", "line": 119, "description": "Returns `true` if the graph's y-axis component is configured to orient right.", "itemtype": "property", "name": "isOrientRight", "type": "Boolean", "readonly": "", "class": "components.nf-y-diff", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-y-diff.js", "line": 127, "description": "The width of the difference box", "itemtype": "property", "name": "width", "type": "Number", "readonly": "", "class": "components.nf-y-diff", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-y-diff.js", "line": 135, "description": "The view controller for the view this component is present in", "itemtype": "property", "name": "parentController", "type": "Ember.Controller", "access": "private", "tagname": "", "readonly": "", "class": "components.nf-y-diff", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-y-diff.js", "line": 144, "description": "The x pixel coordinate of the content container.", "itemtype": "property", "name": "contentX", "type": "Number", "readonly": "", "class": "components.nf-y-diff", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-y-diff.js", "line": 165, "description": "The SVG transformation used to position the content container.", "itemtype": "property", "name": "contentTransform", "type": "String", "access": "private", "tagname": "", "readonly": "", "class": "components.nf-y-diff", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-y-diff.js", "line": 178, "description": "Sets up the d3 related elements when component is inserted \ninto the DOM", "itemtype": "method", "name": "didInsertElement", "class": "components.nf-y-diff", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-y-diff.js", "line": 200, "description": "Performs the transition (animation) of the elements.", "itemtype": "method", "name": "doTransition", "class": "components.nf-y-diff", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-y-diff.js", "line": 220, "description": "Schedules a transition once at afterRender.", "itemtype": "method", "name": "transition", "class": "components.nf-y-diff", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-y-diff.js", "line": 228, "description": "Updates to d3 managed DOM elments that do\nnot require transitioning, because they're width-related.", "itemtype": "method", "name": "doAdjustWidth", "class": "components.nf-y-diff", "module": "utils/nf/svg-dom", "namespace": "components" }, { "file": "app/components/nf-y-diff.js", "line": 254, "description": "Schedules a call to `doAdjustWidth` on afterRender", "itemtype": "method", "name": "adjustWidth", "class": "components.nf-y-diff", "module": "utils/nf/svg-dom", "namespace": "components" } ], "warnings": [] } ================================================ FILE: docs/files/addon_mixins_graph-area-utils.js.html ================================================ addon/mixins/graph-area-utils.js - ember-nf-graph

    API Docs for:
    Show:

    File: addon/mixins/graph-area-utils.js

    import Ember from 'ember';
    
    /**
      Utility functions for drawing an area.
      
      @namespace mixins
      @class graph-area-utils
      @extends Ember.Mixin
    */
    export default Ember.Mixin.create({
    
      /**
        Creates a d3 area function from a given set of scales and an interpolator
    
        @method createAreaFn
        @param xScale {Function} a d3 scale
        @param yScale {Function} a d3 scale
        @param interpolator {String} the name of the d3 interpolator to use.
        @return {Function} a function that when called will create SVG path data.
      */
      createAreaFn: function(xScale, yScale, interpolator) {
          var interp = interpolator || 'linear';
          var xMod = xScale.rangeBand ? xScale.rangeBand() / 2 : 0;
          var yMod = yScale.rangeBand ? yScale.rangeBand() / 2 : 0;
    
          return function(data) {
            if(!data || data.length === 0) {
              return 'M0,0';
            }
    
            return d3.svg.area()
              .x(function (d) {
                return (xScale(d[0]) || 0) + xMod;
              })
              .y0(function (d) {
                return (yScale(d[1]) || 0) + yMod;
              })
              .y1(function (d) {
                return (yScale(d[2]) || 0) + yMod;
              })
              .interpolate(interp)(data);
          };
      }
    });
        
    ================================================ FILE: docs/files/addon_mixins_graph-data-graphic.js.html ================================================ addon/mixins/graph-data-graphic.js - ember-nf-graph

    API Docs for:
    Show:

    File: addon/mixins/graph-data-graphic.js

    import Ember from 'ember';
    import parsePropertyExpr from '../utils/parse-property-expression';
    import { nearestIndexTo } from '../utils/nf/array-helpers';
    import computed from 'ember-new-computed';
    
    var { on, observer } = Ember;
    
    var noop = function(){};
    
    /**
      This is mixed in to {{#crossLink components.nf-graph}}nf-graph{{/crossLink}} child components that need to register data
      with the graph. Includes methods for extracting, sorting and scrubbing data
      for use in graphing components.
    
      Requires {{#crossLink "mixins.graph-registered-graphic"}}{{/crossLink}} and 
      {{#crossLink "mixins.graph-has-graph-parent"}}{{/crossLink}}
    
      @namespace mixins
      @class graph-data-graphic
      @extends Ember.Mixin
    */
    export default Ember.Mixin.create({
      isDataGraphic: true,
    
      /**
        Gets or sets the data used by the component to plot itself.
    
        @property data
        @type Array
        @default null
      */
      data: null,
    
      mappedData: computed('data.@each', {
        get() {
          var yPropFn = this.get('yPropFn');
          var xPropFn = this.get('xPropFn');
          var data = this.get('data');
          if(Ember.isArray(data)) {
            return data.map(function(d, i) {
              var item = [xPropFn(d), yPropFn(d)];
              item.data = d;
              item.origIndex = i;
              return item;
            });
          }
          return [];
        }
      }),
    
      _triggerHasData: on('init', observer('data.@each', function(){
        Ember.run.once(this, this._sendTriggerHasData);
      })),
    
      _sendTriggerHasData() {
        this.trigger('hasData', this.get('mappedData'));
      },
    
      /**
        The path of the property on each object in 
        {{#crossLink "mixins.graph-data-graphic/data:property"}}{{/crossLink}}
        to use as x data to plot on the graph.
    
        @property xprop
        @type String
        @default 'x'
      */
      xprop: 'x',
    
      /**
        The path of the property on each object in 
        {{#crossLink "mixins.graph-data-graphic/data:property"}}{{/crossLink}}
        to use as y data to plot on the graph.
    
        @property yprop
        @type String
        @default 'y'
      */
      yprop: 'y',
    
      /**
        The function to get the x value from each 
        {{#crossLink "mixins.graph-data-graphic/data:property"}}{{/crossLink}} object
    
        @property xPropFn
        @type Function
        @readonly
      */
      xPropFn: computed('xprop', {
        get() {
          var xprop = this.get('xprop');
          return xprop ? parsePropertyExpr(xprop) : noop;
        }
      }),
    
      /**
        The function to get the y value from each 
        {{#crossLink "mixins.graph-data-graphic/data:property"}}{{/crossLink}} object
    
        @property yPropFn
        @type Function
        @readonly
      */
      yPropFn: computed('yprop', {
        get() {
          var yprop = this.get('yprop');
          return yprop ? parsePropertyExpr(yprop) : noop;
        }
      }),
    
      /**
        The list of data points from {{#crossLink "mixins.graph-data-graphc/mappedData:property"}}{{/crossLink}} that
        fits within the x domain, plus up to one data point outside of that domain in each direction.
        @property renderedData
        @type Array
        @readonly
      */
      renderedData: computed(
        'mappedData.@each',
        'graph.xScaleType',
        'graph.xMin',
        'graph.xMax',
        {
          get() {
            var mappedData = this.get('mappedData');
            var graph = this.get('graph');
            var xScaleType = graph.get('xScaleType');
            var xMin = graph.get('xMin');
            var xMax = graph.get('xMax');
    
            if(!mappedData || mappedData.length === 0) {
              return [];
            }
    
            if(xScaleType === 'ordinal') {
              return mappedData;
            }
    
            return mappedData.filter(function(d, i) {
              var x = d[0];
              var prev = mappedData[i-1];
              var next = mappedData[i+1];
              var prevX = prev ? prev[0] : null;
              var nextX = next ? next[0] : null;
    
              return between(x, xMin, xMax) || between(prevX, xMin, xMax) || between(nextX, xMin, xMax);
            });
          }
        }
      ),
    
      /**
        The first element from {{#crossLink "mixins.graph-data-graphic/renderedData:property"}}{{/crossLink}}
        that is actually visible within the x domain.
        @property firstVisibleData
        @type {Object}
        @readonly
      */
      firstVisibleData: computed('renderedData.@each', 'xMin', {
        get() {
          var { renderedData, xPropFn, yPropFn, xMin } = this.getProperties('renderedData', 'xPropFn', 'yPropFn', 'xMin');
    
          var first = renderedData[0];
          if(first && xMin > first[0] && renderedData.length > 1) {
            first = renderedData[1];
          }
    
          return first ? {
            x: xPropFn(first.data),
            y: yPropFn(first.data),
            data: first.data,
            renderX: first[0],
            renderY: first[1]
          } : null;
        }
      }),
    
    
      /**
        The last element from {{#crossLink "mixins.graph-data-graphic/renderedData:property"}}{{/crossLink}}
        that is actually visible within the x domain.
        @property lastVisibleData
        @type {Object}
        @readonly
      */
      lastVisibleData: computed('renderedData.@each', 'yPropFn', 'xPropFn', 'xMax', {
        get() {
          var { renderedData, xPropFn, yPropFn, xMax } = this.getProperties('renderedData', 'xPropFn', 'yPropFn', 'xMax');
          var last = renderedData[renderedData.length - 1];
    
          if(last && xMax < last[0] && renderedData.length > 1) {
            last = renderedData[renderedData.length - 2];
          }
    
          return last ? {
            x: xPropFn(last.data),
            y: yPropFn(last.data),
            data: last.data,
            renderX: last[0],
            renderY: last[1]
          }: null;
        }
      }),
    
      _getRenderedDataNearXRange: function(rangeX) {
        var xScale = this.get('xScale');
        var isLinear = xScale && xScale.invert;
        if(isLinear) {
          return this.getDataNearX(xScale.invert(rangeX));
        } else {
          //ordinal
          var range = this.get('graph.xRange');
          var v = Math.abs(rangeX - range[0]) / Math.abs(range[1] - range[0]);
          var renderedData = this.get('renderedData');
          var i = Math.floor(v * renderedData.length);
          return renderedData[i];
        }
      },
    
      getDataNearXRange(rangeX) {
        var rendered = this._getRenderedDataNearXRange(rangeX);
    
        if(!rendered) { 
          return null;
        }
        
        var renderX = rendered[0];
        var renderY = rendered[1];
        var data = rendered.data;
        var { x, y } = this.getActualTrackData(renderX, renderY, data);
    
        return { renderX, renderY, data, x, y };
      },
    
      /** 
        Gets the actual data at a rendered tracking point passed to it.
        This is overridden in nf-area to account for stacking of data.
        @method getActualTrackData
        @param renderX {number} the x domain value the data is rendered at
        @param renderY {number} the y domain value the data is rendered at 
        @param data {Object} the raw data from the point 
        @return {Object} simple x, y point structure
      */
      getActualTrackData(renderX, renderY, data) {
        return { x: renderX, y: renderY, data };
      },
    
      getDataNearX: function(x) {
        x = +x;
        if(x === x) {
          var renderedData = this.get('renderedData');
          var index = nearestIndexTo(renderedData, x, function(d){
            return d ? d[0] : null;
          });
          return index !== -1 ? renderedData[index] : null;
        }
      },
    });
    
    function between(x, a, b) {
      return a <= x && x <= b;
    }
        
    ================================================ FILE: docs/files/addon_mixins_graph-graphic-with-tracking-dot.js.html ================================================ addon/mixins/graph-graphic-with-tracking-dot.js - ember-nf-graph

    API Docs for:
    Show:

    File: addon/mixins/graph-graphic-with-tracking-dot.js

    import Ember from 'ember';
    import { getMousePoint } from '../utils/nf/svg-dom';
    import computed from 'ember-new-computed';
    
    var { on, observer } = Ember;
    
    export default Ember.Mixin.create({
      /**
        Gets or sets the tracking mode of the component.
    
        Possible values are:
    
        - 'none': no tracking behavior
        - 'hover': only track while mouse hover
        - 'snap-last': track while mouse hover, but snap to the last data element when not hovering
        - 'snap-first': track while mouse hover, but snap to the first data element when not hovering
        - 'selected-hover': The same as `'hover'` tracking mode, but only when the compononent is 
        {{#crossLink "mixins.graph-selectable-graphic/selected:property"}}{{/crossLink}}
        - 'selected-snap-last': The same as `'snap-last'` tracking mode, but only when the compononent is 
        {{#crossLink "mixins.graph-selectable-graphic/selected:property"}}{{/crossLink}}
        - 'selected-snap-first': The same as `'snap-first'` tracking mode, but only when the compononent is 
        {{#crossLink "mixins.graph-selectable-graphic/selected:property"}}{{/crossLink}}
    
        @property trackingMode
        @type String
        @default 'none'
      */
      trackingMode: 'none',
    
      /**
        The radius of the tracking dot in pixels
        @property trackingDotRadius
        @type {number}
        @default 2.5
      */
      trackingDotRadius: 2.5,
    
      /**
        The action to send on `didTrack`.
        @property didTrack
        @type String
        @default null
      */
      didTrack: null,
    
      /**
        The value of the data that is being tracked by the component.
        @property trackedData
        @type {Object} an object with the following values:  
          - point: an { x, y } pair for the exact px coordinates inside the graph-content
          - graphX: domain x value at mouse position
          - graphY: domain y value at mouse position
          - x: nearest x data value
          - y: nearest y data value
          - data: nearest raw data
          - renderX: domain x value to render a tracking dot at (stacked areas are offset)
          - renderY: domain x value to render a tracking dot at (stacked areas are offset)
          - mouseX: mouse x position in pixels
          - mouseY: mouse y position in pixels
        @default null
      */
      trackedData: null,
    
      /**
        The value of the data that is being tracked by the component, ONLY if the 
        graph-content is currently being hovered.
        @property hoverData
        @type {Object} an object with the following values:  
          - point: an { x, y } pair for the exact px coordinates inside the graph-content
          - graphX: domain x value at mouse position
          - graphY: domain y value at mouse position
          - x: nearest x data value
          - y: nearest y data value
          - data: nearest raw data
          - renderX: domain x value to render a tracking dot at (stacked areas are offset)
          - renderY: domain x value to render a tracking dot at (stacked areas are offset)
          - mouseX: mouse x position in pixels
          - mouseY: mouse y position in pixels
        @default null
      */
      hoverData: null,
    
      _showTrackingDot: true,
    
      /**
        Gets or sets whether the tracking dot should be shown at all.
        @property showTrackingDot
        @type {boolean}
        @default true
      */
      showTrackingDot: computed('trackedData', {
        get() {
          return Boolean(this._showTrackingDot && this.get('trackedData'));
        },
    
        set(value) {
          this._showTrackingDot = value;
        }
      }),
    
      /**
        Observes changes to tracked data and sends the
        didTrack action.
        @method _trackedDataChanged
        @private
      */
      _trackedDataChanged: Ember.observer('trackedData', function(){
        var trackedData = this.get('trackedData');
        this.set('hoverData', this._hovered ? trackedData : null);
    
        if(this.get('didTrack')) {
          this.sendAction('didTrack', {
            x: trackedData.x,
            y: trackedData.y,
            data: trackedData.data,
            source: this,
            graph: this.get('graph'),
          });
        }
      }),
    
      _cleanup: function(){
        if(this._onHoverCleanup) {
          this._onHoverCleanup();
        }
        if(this._onEndCleanup) {
          this._onEndCleanup();
        }
      },
    
      _updateTrackingHandling() {
        var { trackingMode, selected } = this.getProperties('trackingMode', 'selected');
    
        this._cleanup();
    
        switch(trackingMode) {
          case 'hover':
            this._onHoverTrack();
            this._onEndUntrack();
            break;
          case 'snap-first':
            this._onHoverTrack();
            this._onEndSnapFirst();
            break;
          case 'snap-last':
            this._onHoverTrack();
            this._onEndSnapLast();
            break;
          case 'selected-hover':
            if(selected) {
              this._onHoverTrack();
              this._onEndUntrack();
            }
            break;
          case 'selected-snap-first':
            if(selected) {
              this._onHoverTrack();
              this._onEndSnapFirst();
            }
            break;
          case 'selected-snap-last':
            if(selected) {
              this._onHoverTrack();
              this._onEndSnapLast();
            }
            break;
        }
      },
    
      _onHoverTrack() {
        var content = this._content;
    
        var mousemoveHandler = e => {
          this._hovered = true;
          var evt = this._getEventObject(e);
          this.set('trackedData', evt);
        };
    
        content.on('mousemove', mousemoveHandler);
    
        this._onHoverCleanup = () => {
          content.off('mousemove', mousemoveHandler);
        };
      },
    
      _hovered: false,
    
      _onEndUntrack() {
        var content = this._content;
    
        var mouseoutHandler = () => {
          this.set('trackedData', null);
        };
    
        content.on('mouseout', mouseoutHandler);
    
        this._onEndCleanup = () => {
          content.off('mouseout', mouseoutHandler);
        };
    
        if(!this._hovered) {
          this.set('trackedData', null);
        }
      },
    
      _onEndSnapLast() {
        var content = this._content;
    
        var mouseoutHandler = () => {
          this._hovered = false;
          this.set('trackedData', this.get('lastVisibleData'));
        };
    
        var changeHandler = () => {
          if(!this._hovered) {
            this.set('trackedData', this.get('lastVisibleData'));
          }
        };
    
        content.on('mouseout', mouseoutHandler);
        this.addObserver('lastVisibleData', this, changeHandler);
    
        this._onEndCleanup = () => {
          content.off('mouseout', mouseoutHandler);
          this.removeObserver('lastVisibleData', this, changeHandler);
        };
    
        changeHandler();
      },
    
      _onEndSnapFirst() {
        var content = this._content;
    
        var mouseoutHandler = () => {
          this._hovered = false;
          this.set('trackedData', this.get('firstVisibleData'));
        };
    
        var changeHandler = () => {
          if(!this._hovered) {
            this.set('trackedData', this.get('firstVisibleData'));
          }
        };
    
        content.on('mouseout', mouseoutHandler);
        this.addObserver('firstVisibleData', this, changeHandler);
    
        this._onEndCleanup = () => {
          content.off('mouseout', mouseoutHandler);
          this.removeObserver('firstVisibleData', this, changeHandler);
        };
    
        changeHandler();
      },
    
      _trackingModeChanged: on('init', observer('trackingMode', 'selected', function() {
        Ember.run.once(this, this._updateTrackingHandling);
      })),
    
      _getEventObject(e) {
        var { xScale, yScale } = this.getProperties('xScale', 'yScale');
        var content = this._content;
        var point = getMousePoint(content[0], e);
        var graphX = xScale.invert(point.x);
        var graphY = yScale.invert(point.y);
        var near = this.getDataNearXRange(point.x);
    
        if(!near) {
          return {
            point,
            graphX,
            graphY,
            mouseX: point.x,
            mouseY: point.y,
          };
        }
    
        var { x, y, data, renderX, renderY } = near;
        return {
          point,
          graphX,
          graphY,
          x,
          y,
          data,
          renderX,
          renderY,
          mouseX: point.x,
          mouseY: point.y
        };
      },
    
      didInsertElement() {
        this._super.apply(arguments);
        this._content = this.$().parents('.nf-graph-content');
      },
    
      willDestroyElement() {
        this._super.apply(arguments);
        this._cleanup();
      }
    });
        
    ================================================ FILE: docs/files/addon_mixins_graph-has-graph-parent.js.html ================================================ addon/mixins/graph-has-graph-parent.js - ember-nf-graph

    API Docs for:
    Show:

    File: addon/mixins/graph-has-graph-parent.js

    import Ember from 'ember';
    
    /**
      Adds initialization code to graph the `nf-graph` parent
      to a component that is to be contained in an `nf-graph`.
    
      @namespace mixins
      @class graph-has-graph-parent
      */
    export default Ember.Mixin.create({
      
      /**
        The parent graph for a component.
        @property graph
        @type components.nf-graph
        @default null
        */
      graph: null,
    
      /**
        Initalization method that gets the `nf-graph` parent
        and assigns it to `graph`
        NOTE: all object that mixin and have init, must call super.init()
        @method init
        */
    
      init() {
        this._super(...arguments);
        var graph = this.nearestWithProperty('isGraph');
        this.set('graph', graph);
      }
    });
        
    ================================================ FILE: docs/files/addon_mixins_graph-line-utils.js.html ================================================ addon/mixins/graph-line-utils.js - ember-nf-graph

    API Docs for:
    Show:

    File: addon/mixins/graph-line-utils.js

      import Ember from 'ember';
    
      /**
        @namespace mixins
        @class graph-line-utils
        @extends Ember.Mixin
        */
      export default Ember.Mixin.create({
    
        /**
          Create a d3 line function from a given scales and interpolation
    
          @method createLineFn
          @param xScale {Function} d3 scale function
          @param yScale {Function} d3 scale function
          @param interpolate {String} d3 interpolator name
          @return {Function} a d3 function that will create SVG path data from a given data set.
          */
        createLineFn: function(xScale, yScale, interpolate){ 
          var interp = interpolate || 'linear';
    
          var xMod = xScale.rangeBand ? xScale.rangeBand() / 2 : 0;
          var yMod = yScale.rangeBand ? yScale.rangeBand() / 2 : 0;
    
          return function(data) {
            if(!data || data.length === 0) {
              return 'M0,0';
            }
    
            return d3.svg.line()
              .x(function (d) { return (xScale(d[0]) || 0) + xMod; })
              .y(function (d) { return (yScale(d[1]) || 0) + yMod; })
              .interpolate(interp)(data);
          };
        }
      });
        
    ================================================ FILE: docs/files/addon_mixins_graph-registered-graphic.js.html ================================================ addon/mixins/graph-registered-graphic.js - ember-nf-graph

    API Docs for:
    Show:

    File: addon/mixins/graph-registered-graphic.js

    import Ember from 'ember';
    
    /**
      @namespace mixins
      @class graph-registered-graphic
      @extends Ember.Mixin
    */
    export default Ember.Mixin.create({
    
      init() {
        this._super(...arguments);
        var graph = this.get('graph');
        if(graph) {
          graph.registerGraphic(this);
        }
      },
    
      /**
        calls {{#crossLink "components.nf-graph/unregisterGraphic"}}{{/crossLink}} on
        `didInsertElement`.
        @method _unregisterGraphic
        @private
      */
      _unregisterGraphic: Ember.on('willDestroyElement', function(){
        var graph = this.get('graph');
        if(graph) {
          graph.unregisterGraphic(this);
        }
      })
    });
        
    ================================================ FILE: docs/files/addon_mixins_graph-requires-scale-source.js.html ================================================ addon/mixins/graph-requires-scale-source.js - ember-nf-graph

    API Docs for:
    Show:

    File: addon/mixins/graph-requires-scale-source.js

    import Ember from 'ember';
    import computed from 'ember-new-computed';
    
    var scaleProperty = function(scaleKey, zoomKey, offsetKey){
      return computed(scaleKey, zoomKey, offsetKey, {
        get() {
          var scale = this.get(scaleKey);
          var zoom = this.get(zoomKey);
    
          var offset = this.get(offsetKey);
          if(zoom === 1 && offset === 0) {
            return scale;
          }
    
          var copy = scale.copy();
          var domain = copy.domain();
          copy.domain([domain[0] / zoom, domain[1] / zoom]);
    
          var range = copy.range();
          copy.range([range[0] - offset, range[1] - offset]);
    
          return copy;
        }
      });
    };
    
    /**
      Adds functionality to identify a parent control that will provide an x and
      y scale, then adds scaling properties to the component it's mixed in to.
      @namespace mixins
      @class graph-requires-scale-source
    */
    export default Ember.Mixin.create({
      /**
        The x scale used by this component
        @property xScale
        @type d3.scale
        @readonly
      */
      xScale: scaleProperty('scaleSource.xScale', 'scaleZoomX', 'scaleOffsetX'),
      
      /**
        The y scale used by this component
        @property yScale
        @type d3.scale
        @readonly
      */
      yScale: scaleProperty('scaleSource.yScale', 'scaleZoomY', 'scaleOffsetY'),
    
      _scaleOffsetX: 0,
    
      _scaleOffsetY: 0,
    
      _scaleZoomX: 1,
    
      _scaleZoomY: 1,
    
      /**
        The zoom multiplier for the x scale
        @property scaleZoomX
        @type Number
        @default 1
      */
      scaleZoomX: computed({
        get() {
          return this._scaleZoomX || 1;
        },
        set(key, value) {
          return this._scaleZoomX = +value || 1;
        }
      }),
    
      /**
        The zoom multiplier for the y scale
        @property scaleZoomY
        @type Number
        @default 1
      */
      scaleZoomY: computed({
        get() {
          return this._scaleZoomY || 1;
        },
        set(key, value) {
          return this._scaleZoomY = +value || 1;
        }
      }),
    
      /**
        The offset, in pixels, for the x scale
        @property scaleOffsetX
        @type Number
        @default 0
      */
      scaleOffsetX: computed({
        get() {
          return this._scaleOffsetX || 0;
        },
        set(key, value) {
          return this._scaleOffsetX = +value || 0;
        }
      }),
    
      /**
        The offset, in pixels, for the y scale
        @property scaleOffsetY
        @type Number
        @default 0
      */
      scaleOffsetY: computed({
        get() {
          return this._scaleOffsetY || 0;
        },
        set(key, value) {
          return this._scaleOffsetY = +value || 0;
        }
      }),
    
      init() {
        this._super(...arguments);
        var scaleSource = this.nearestWithProperty('isScaleSource');
        this.set('scaleSource', scaleSource);
      }
    });
        
    ================================================ FILE: docs/files/addon_mixins_graph-selectable-graphic.js.html ================================================ addon/mixins/graph-selectable-graphic.js - ember-nf-graph

    API Docs for:
    Show:

    File: addon/mixins/graph-selectable-graphic.js

    import Ember from 'ember';
    
    /**
      Adds functionality to a component to make it a selectable graphic
      within it's parent nf-graph.
      @namespace mixins
      @class graph-selectable-graphic
      @extends Ember.Mixin
    */
    export default Ember.Mixin.create({
      _selected: false,
    
      /**
        Gets or sets whether or not the graphic is "selectable". Meaning can be "selected" on the nf-graph 
        via some action (usually click). The component will then show up in the nf-graph parent's selected 
        property.
        @property selectable
        @type Boolean
        @default false
      */
      selectable: false,
    
      /**
        Gets or sets whether or not the graphic is selected.
        @property selected
        @type Boolean
        @default false
      */
      selected: false,
    
      /**
        Alias of selected
        @property isSelected
        @deprecated use `selected`
      */
      isSelected: Ember.computed.alias('selected'),
    
      /**
        Makes calls to the parent nf-graph to update it's
        `selected` property. Observes changes to `selected` and also 
        fires on `didInsertElement`.
        @method _updateGraphSelected
        @private
      */
      _updateGraphSelected: Ember.on('didInsertElement', Ember.observer('selected', function() {
        Ember.run.once(this, function(){
          var selected = this.get('selected');
          var graph = this.get('graph');
          if(selected) {
            graph.selectGraphic(this);
          } else {
            graph.deselectGraphic(this);
          }
        });
      })),
    });
        
    ================================================ FILE: docs/files/addon_utils_nf_array-helpers.js.html ================================================ addon/utils/nf/array-helpers.js - ember-nf-graph

    API Docs for:
    Show:

    File: addon/utils/nf/array-helpers.js

    /**
      @module utils/nf/array-helpers
    */
    
    /**
      returns whatever you pass into it.
      @method identity
      @param x {Any}
      @private
      @return {Any} x
    */
    function identity(x) {
      return x;
    }
    
    /**
      Performs a binary search on the array and finds the nearest index to the value passed.
      @method nearestIndexTo
      @param arr {Array} the *sorted* array to search.
      @param val {Number} the value to find the nearest index to.
      @param mappingFn {Function} an optional function for pulling values out of the 
      array items.
    */
    export function nearestIndexTo(arr, val, mappingFn) {
      mappingFn = mappingFn || identity;
      var startIndex  = 0;
      var stopIndex = arr.length - 1;
      var middle = (stopIndex + startIndex) / 2;
      var a = Math.floor(middle);
      var b = Math.floor(middle + 1);
    
      var getItem = function(i){
        return mappingFn(arr[i]);
      };
    
      var av = getItem(a);
      var bv = getItem(b);
    
      while(!(av <= val && val <= bv) && startIndex < stopIndex){
    
        if (val < av){
            stopIndex = middle - 1;
        } else if (val > av){
            startIndex = middle + 1;
        }
    
        middle = (stopIndex + startIndex) / 2;
        a = Math.floor(middle);
        b = Math.floor(middle + 1);
        av = getItem(a);
        bv = getItem(b);
      }
    
      return (Math.abs(val - av) < Math.abs(val - bv)) ? a : b;
    }
    
    var NATURAL_SORT_REGEXP = /[+-]?\d+\.?\d*|\S+/g;
    
    /**
      breaks a string into an array of tokens in preparation for natural
      comparison and sorting.
      @method naturalTokenize
      @param item {String} the value to tokenize
      @return {Array} an array of tokens found in the item
      @private
    */
    function naturalTokenize(item) {
      NATURAL_SORT_REGEXP.lastIndex = 0;
      var matches;
      var tokens = [];
      while(matches = NATURAL_SORT_REGEXP.exec(item)) {
        tokens.push(matches[0]);
      }
      return tokens;
    }
    
    /**
      A JavaScript sorting predicate for natural sorting.
      @method naturalCompare
      @param a {Any} the value to compare to b
      @param b {Any} the value to compare to a
      @return {Number} `-1`, `0` or `1` if a is less than, equal to, or
        greater than b, respectively.
    */
    export function naturalCompare(a, b) {
      var aTokens = naturalTokenize(a);
      var bTokens = naturalTokenize(b);
      var i = 0, bx, ax, na, nb;
    
      while((ax = aTokens[i]) && (bx = bTokens[i++])) {
        na = +ax;
        nb = +bx;
      
        if(nb === nb && na === na) {
          if(na !== nb) {
             return na > nb ? 1 : -1;
          } else {
            if(ax.length !== bx.length) {
              return ax.length > bx.length ? 1 : -1;
            }
          }
        }
      
        if(ax !== bx) {
          return ax > bx ? 1 : -1;
        }
      }
    
      return 0;
    }
    
    /**
      Sorts the array "naturally". Meaning taking into account both
      alphabetical and numeric sorting within strings.
    
      @method natualSort
      @param arr {Array} the array to sort
    */
    export function naturalSort(arr) {
      arr.sort(naturalCompare);
    }
    
    export function sliceArrayLike(arrayLike, from, to) {
      return Array.prototype.slice.call(arrayLike, from, to);
    }
    
    export function toArray() {
      return sliceArrayLike(arguments);
    }
        
    ================================================ FILE: docs/files/addon_utils_nf_graph-event.js.html ================================================ addon/utils/nf/graph-event.js - ember-nf-graph ================================================ FILE: docs/files/addon_utils_nf_graph-mouse-event.js.html ================================================ addon/utils/nf/graph-mouse-event.js - ember-nf-graph

    API Docs for:
    Show:

    File: addon/utils/nf/graph-mouse-event.js

    import Ember from 'ember';
    import GraphPosition from './graph-position';
    import { getMousePoint } from './svg-dom';
    import computed from 'ember-new-computed';
    
    const { reads } = Ember.computed;
    
    /**
      An event context object generally returned by tracking events. Also used as
      `trackedData` in components such as `nf-line`, `nf-area` and `nf-bars`.
      
      @namespace utils.nf
      @class graph-mouse-event
      @extends graph-position
    */
    export default GraphPosition.extend({
      /**
        The original event that triggered the action or ember event
        @property originalEvent
        @type MouseEvent
        @default null
      */
      originalEvent: null,
    
      /**
        Method used to get the mouse position relative to a container
        @method _getMousePoint
        @private
      */
      _getMousePoint: getMousePoint,
    
      /**
        The coordinates of the mouse relative to eh nf-graph-content
        @property _mousePoint
        @type Object
        @readonly
        @private
      */
      _mousePoint: computed('originalEvent', 'graphContentElement', {
        get() {
          return this._getMousePoint(this.get('graphContentElement'), this.get('originalEvent'));
        }
      }),
    
      /**
        The nf-graph-content element of the nf-graph
        @property graphContentElement
        @type SVGGElement
        @readonly
      */
      graphContentElement: null,
    
      /**
        The mouse x position relative to the graph content
        @property mouseX
        @type Number
        @readonly
      */
      mouseX: reads('_mousePoint.x'),
    
      /**
        The mouse y position relative to the graph content
        @property mouseY
        @type Number
        @readonly
      */
      mouseY: reads('_mousePoint.y'),
    
      /**
        A positioning object for the mouse position
        @property mousePosition
        @type graph-position
        @readonly
      */
      mousePosition: computed('mouseX', 'mouseY', 'source', 'graph', {
        get() {
          return GraphPosition.create({
            graphX: this.get('mouseX'),
            graphY: this.get('mouseY'),
            source: this.get('source'),
            graphContentElement: this.get('graphContentElement'),
          });
        }
      }),
    
      /**
        The raw data point nearest the mouse.graphX position
        @property nearestDataPoint
        @type Array
        @readonly
      */
      nearestDataPoint: computed('source', 'mouse.graphX', {
        get() {
          var mouseX = this.get('mouseX');
          var source = this.get('source');
          return source ? source.getDataNearXRange(mouseX) : undefined;
        }
      }),
    
      /**
        The x domain value at the nearest data point to the mouse position
        along the x axis.
        @property x
        @readonly
      */
      x: computed('nearestDataPoint', {
        get() {
          var nearestDataPoint = this.get('nearestDataPoint');
          this._x =  nearestDataPoint ? nearestDataPoint[0] : undefined;
          return this._x;
        }
      }),
    
      /**
        The y domain value at the nearest data point to the mouse position
        along the x axis.
        @property y
        @readonly
      */
      y: computed('nearestDataPoint', {
        get() {
          var nearestDataPoint = this.get('nearestDataPoint');
          this._y = nearestDataPoint ? nearestDataPoint[1] : undefined;
          return this._y;
        }
      }),
    
      /**
        The data carried by the nearest data point to the mouse position
        along the x axis.
        @property data
        @readonly
      */
      data: reads('nearestDataPoint.data'),
    });
        
    ================================================ FILE: docs/files/addon_utils_nf_graph-position.js.html ================================================ addon/utils/nf/graph-position.js - ember-nf-graph

    API Docs for:
    Show:

    File: addon/utils/nf/graph-position.js

    import Ember from 'ember';
    import computed from 'ember-new-computed';
    
    const { reads } = Ember.computed;
    
    /**
      Position calculation class for nf-graph related events
      @namespace utils.nf
      @class graph-position
      @extends Ember.Object
    */
    export default Ember.Object.extend({
      /**
        @property graph
        @type component.nf-graph
        @default null
      */
      graph: null,
    
      /**
        @property source
        @type Ember.Component
      */
      source: null,
    
      /**
        The x position relative to graph
        @property graphX
        @type Number
      */
      graphX: computed('x', 'xScale', {
        get() {
          var scale = this.get('xScale');
          if(scale) {
            var x = this.get('x');
            this._graphX = scale(x);
          }
          return this._graphX || NaN;
        },
        set(key, value) {
          return this._graphX = value || NaN;
        }
      }),
    
      /**
        The y position relative to graph
        @property graphY
        @type Number
      */
      graphY: computed('y', 'yScale', {
        get() {
          var scale = this.get('yScale');
          if(scale) {
            var y = this.get('y');
            this._graphY = scale(y);
          }
          return this._graphY || NaN;
        },
        set(key, value) {
          return this._graphY = value || NaN;
        }
      }),
    
      /**
        The x domain value
        @property x
        @type Number
      */
      x: computed('graphX', 'xScale', {
        get() {
          var scale = this.get('xScale');
          if (scale && scale.invert){
            var graphX = this.get('graphX');
            this._x = scale.invert(graphX);
          }
          return this._x || 0;
        },
        set(key, value) {
          return this._x = value;
        }
      }),
    
      /**
        The y domain value
        @property y
        @type Number
      */
      y: computed('graphY', 'yScale', {
        get() {
          var scale = this.get('yScale');
          if (scale && scale.invert){
            var graphY = this.get('graphY');
            this._y = scale.invert(graphY);
          }
          return this._y || 0;
        },
        set(key, value) {
          return this._y = value;
        }
      }),
    
      /**
        The x position relative to the document
        @property pageX
        @type Number
      */
      pageX: computed('graphX', 'graphOffset', 'graphContentX', {
        get() {
          var offset = this.get('graphOffset');
          if(offset) {
            var graphX = this.get('graphX') || 0;
            var graphContentX = this.get('graphContentX') || 0;
            return offset.left + graphX + graphContentX;
          }
        }
      }),
    
      /**
        The y position relative to the document
        @property pageY
        @type Number
      */
      pageY: computed('graphY', 'graphOffset', 'graphContentY', {
        get() {
          var offset = this.get('graphOffset');
          if(offset) {
            var graphY = this.get('graphY') || 0;
            var graphContentY = this.get('graphContentY') || 0;
            return offset.top + graphY + graphContentY;
          }
        }
      }),
    
      /**
        The x scale from either the source or graph used to calculate positions
        @property xScale
        @type d3.scale
        @readonly
      */
      xScale: computed('graph.xScale', 'source.xScale', {
        get() {
          return this.get('source.xScale') || this.get('graph.xScale');
        }
      }),
    
      /**
        The y scale from either the source or graph used to calculate positions
        @property yScale
        @type d3.scale
        @readonly
      */
      yScale: computed('graph.yScale', 'source.yScale', {
        get() {
          return this.get('source.yScale') || this.get('graph.yScale');
        }
      }),
    
      /**
        The JQuery offset of the graph element
        @property graphOffset
        @type Object
        @readonly
      */
      graphOffset: computed('graph', {
        get() {
          var graph = this.get('graph');
          if(graph) {
            var content = graph.$('.nf-graph-content');
            return content ? content.offset() : undefined;
          }
        }
      }),
    
      /**
        The center point at x. Use in case of requiring a center point 
        and using ordinal scale.
        @property centerX
        @type Number
      */
      centerX: computed('xScale', 'graphX', {
        get() {
          var scale = this.get('xScale');
          var graphX = this.get('graphX');
          if(scale && scale.rangeBand) {
            var rangeBand = scale.rangeBand();
            return graphX + (rangeBand / 2);
          }
          return graphX;
        }
      }),
    
      /**
        The center point at y. Use in case of requiring a center point 
        and using ordinal scale.
        @property centerY
        @type Number
      */
      centerY: computed('yScale', 'graphY', {
        get() {
          var scale = this.get('yScale');
          var graphY = this.get('graphY');
          if(scale && scale.rangeBand) {
            var rangeBand = scale.rangeBand();
            return graphY + (rangeBand / 2);
          }
          return graphY;
        }
      }),
    
      /**
        The x position of the nf-graph-content within the nf-graph
        @property _graphContentX
        @type Number
        @private
      */
      graphContentX: reads('graph.graphX'),
    
      /**
        The y position of the nf-graph-content within the nf-graph
        @property _graphContentY
        @type Number
        @private
      */
      graphContentY: reads('graph.graphY'),
    });
        
    ================================================ FILE: docs/files/addon_utils_nf_scale-utils.js.html ================================================ addon/utils/nf/scale-utils.js - ember-nf-graph

    API Docs for:
    Show:

    File: addon/utils/nf/scale-utils.js

    /**
      utilities for dealing with d3 scales
      @namespace utils.nf
      @module scale-utils
    */
    
    /**
      Ensures the output of a scale function is something palatable by SVG.
      @method normalizeScale
      @param scale {d3.scale} the scale to use to get the value
      @param val {any} the value to transform with the scale
      @return {Number} the output of the scale function, but if NaN, it will return 0.
    */
    function normalizeScale(scale, val) {
      return (scale ? scale(val) : 0) || 0;
    }
    
    export { normalizeScale };
        
    ================================================ FILE: docs/files/addon_utils_nf_scroll-area-action-context.js.html ================================================ addon/utils/nf/scroll-area-action-context.js - ember-nf-graph

    API Docs for:
    Show:

    File: addon/utils/nf/scroll-area-action-context.js

    import Ember from 'ember';
    import computed from 'ember-new-computed';
    
    /**
      Action context event object for an nf-scroll-area scroll event.
      @namespace utils.nf
      @class scroll-area-action-context
    */
    export default Ember.Object.extend({
      /**
        The scroll top in pixels.
        @property scrollTop
        @type Number
        @default 0
      */
      scrollTop: 0,
    
      /**
        The scroll height of the element.
        @property scrollHeight
        @type number
        @default 0
      */
      scrollHeight: 0,
    
      /**
        The outer height of the element
        @property outerHeight
        @type Number
        @default 0
      */
      outerHeight: 0,
    
      /**
        The scroll left in pixels.
        @property scrollLeft
        @type Number
        @default 0
      */
      scrollLeft: 0,
    
      /**
        The scroll width of the element.
        @property scrollWidth
        @type number
        @default 0
      */
      scrollWidth: 0,
    
      /**
        The outer width of the element
        @property outerWidth
        @type Number
        @default 0
      */
      outerWidth: 0,
    
      /**
        The calculated maximum value for scrollTop in pixels.
        @property scrollTopMax
        @type Number
        @readonly
      */
      scrollTopMax: computed('outerHeight', 'scrollHeight', {
        get() {
          return this.get('scrollHeight') - this.get('outerHeight');
        }
      }),
    
      /**
        The calculated percentage, in decimals, of content scrolled.
        @property scrollTopPercentage
        @type Number
        @readonly
      */
      scrollTopPercentage: computed('scrollTop', 'scrollTopMax', {
        get() {
          return this.get('scrollTop') / this.get('scrollTopMax');
        }
      }),
      
      /**
        The calculated maximum value for scrollTop in pixels.
        @property scrollLeftMax
        @type Number
        @readonly
      */
      scrollLeftMax: computed('outerWidth', 'scrollWidth', {
        get() {
          return this.get('scrollWidth') - this.get('outerWidth');
        }
      }),
    
      /**
        The calculated percentage, in decimals, of content scrolled.
        @property scrollLeftPercentage
        @type Number
        @readonly
      */
      scrollLeftPercentage: computed('scrollLeft', 'scrollLeftMax', {
        get() {
          return this.get('scrollLeft') / this.get('scrollLeftMax');
        }
      }),
    
      /**
        The component that fired the event
        @property source
        @type Ember.Component
        @default null
      */
      source: null,
    
      /**
        The optional data to send with the action
        @property data
        @default null
      */
      data: null,
    
      /**
        The original scroll event object
        @property originalEvent
        @type Event
        @default null
      */
      originalEvent: null,
    });
        
    ================================================ FILE: docs/files/addon_utils_nf_svg-dom.js.html ================================================ addon/utils/nf/svg-dom.js - ember-nf-graph

    API Docs for:
    Show:

    File: addon/utils/nf/svg-dom.js

    /* globals getComputedStyle, Image, Blob, URL */
    /**
      @module utils/nf/svg-dom
    */
    
    /**
      Traverses an element and all of its descendants, setting their
      inline style property to whatever the computed style is.
      @method inlineAllStyles
      @param element {Element} the dom element to traverse.
      @private
    */
    function inlineAllStyles(element) {
      var styles = getComputedStyle(element);
      for(var key in styles) {
        if(styles.hasOwnProperty(key)) {
          element.style[key] = styles[key];
        }
      }
    
      for(var i = 0; i < element.childNodes.length; i++) {
        var node = element.childNodes[i];
        if(node.nodeType === 1) {
          inlineAllStyles(node);
        }
      }
    }
    
    /**
      Renders an SVG element to a Base64 encoded data URI.
      @method svgToImageUrl
      @param svg {SVGSVGElement} the svg element to render
    */
    export function svgToImageUrl(svg, callback) {
      var clone = svg.cloneNode(true);
      var parent = svg.parentElement;
    
      var canvas = document.createElement('canvas');
      canvas.setAttribute('width', svg.getAttribute('width'));
      canvas.setAttribute('height', svg.getAttribute('height'));
      var context = canvas.getContext('2d');
    
      parent.insertBefore(clone, svg);
      clone.setAttribute('xmlns', 'http://www.w3.org/2000/svg');
    
      inlineAllStyles(clone);
    
      var img = new Image();
      var blob = new Blob([clone.outerHTML], { type: 'image/svg+xml;charset=utf-8' });
      clone.remove();
      var url = URL.createObjectURL(blob);
    
      img.onload = function(){
        context.drawImage(img, 0, 0);
        URL.revokeObjectURL(url);
        if(callback) {
          callback(canvas.toDataURL());
        }
        canvas.remove();
      };
    
      img.src = url;
    }
    
    /**
      Triggers a download of an image rendered from the passed svg document
      @method downloadSvg
      @param svg {SVGSVGElement} the svg document to render
    */
    export function downloadSvg(svg) {
      svgToImageUrl(svg, function(url) {
        var dlUrl = url.replace('image/png', 'image/octet-stream');
        location.href = dlUrl;
      });
    }
    
    /**
      @method getMousePoint
      @param container {SVGElement} the container reference to get the mouse position from
      @param e {MouseEvent} A DOM mouse event
      @return {Object} the {x, y} data of the mouse position relative to the container
    */
    export function getMousePoint(container, e) {
      var x, y;
    
      if(e && e.hasOwnProperty('clientX') && e.hasOwnProperty('clientY')) {
        var svg = container.ownerSVGElement || container;
        if (svg.createSVGPoint) {
          var point = svg.createSVGPoint();
          point.x = e.clientX;
          point.y = e.clientY;
          point = point.matrixTransform(container.getScreenCTM().inverse());
          x = point.x;
          y = point.y;
        } else {
          var rect = container.getBoundingClientRect();
          x = e.clientX - rect.left - container.clientLeft;
          y = e.clientY - rect.top - container.clientTop;
        }
      }
    
      return {
        x: x,
        y: y,
      };
    }
    
    /**
      Creates an SVG path string for a rectangle
      @method getRectPath
      @param x the x position of the rectangle
      @param y {Number} the y position of the rectangle
      @param w {Number} the width of the rectangle
      @param h {Number} the height of the rectangle
      @return {String} the svg path string for the rectangle
    */
    export function getRectPath(x, y, w, h) {
      x = +x || 0;
      y = +y || 0;
      w = +w || 0;
      h = +h || 0;
      var x2 = w + x;
      var y2 = h + y;
      return `M${x},${y} L${x},${y2} L${x2},${y2} L${x2},${y} L${x},${y}`;
    }
    
        
    ================================================ FILE: docs/files/addon_utils_parse-property-expression.js.html ================================================ addon/utils/parse-property-expression.js - ember-nf-graph

    API Docs for:
    Show:

    File: addon/utils/parse-property-expression.js

    /**
      A function that will parse a path expression into a "getter" function that
      can retrieve a value from that path off of any object when called.
    
      ### Example
            
            import parsePropertyExpr from 'utils/parse-property-expr';
    
            var test = { foo: { bar: ['apple', 'banana'] } };
            var getFooBar1 = parsePropertyExpr('foo.bar[1]');
            var result = getFooBar1(test);
            console.log(result); // "banana"
    
      ### Notes
    
      Will return `undefined` if the nothing is at the end of the path, or the
      path cannot be reached.
    
      @namespace utils
      @class parse-property-expression
    */
    
    
    /**  
      @method default
      @param expr {String} the expression to parse
      @return {Function} a function that when called with an object,
      will locate the value at the end of the expressed path.
    */
    export default function parsePropertyExpression(expr) {
      var c, i;
      var isIndex = false;
      var token = '';
      var tokens = [];
      var addToken = function(){
        if(token === '') {
          return;
        }
        if(isIndex) {
          token = +token;
        }
        tokens.push(token);
        token = '';
        isIndex = c === '[';    
      };
      
      for(i = 0; i < expr.length; i++) {
        c = expr[i];
        if('[].'.indexOf(c) >= 0) {
          addToken();
        } else {
          token += c;
        }
      }
      
      addToken();
      
      return function(obj){
        var i, next;
        var result = obj[tokens[0]];
        if(result) {
          for(i = 1; i < tokens.length; i++) {
            next = result[tokens[i]];
            if(typeof next !== 'object') {
              return next;
            }
            result = next;
          }
        }
        return result;
      };
    }
        
    ================================================ FILE: docs/files/app_components_nf-area-stack.js.html ================================================ app/components/nf-area-stack.js - ember-nf-graph

    API Docs for:
    Show:

    File: app/components/nf-area-stack.js

    import Ember from 'ember';
    
    /**
      A component for grouping and stacking `nf-area` components in an `nf-graph`.
      
      This component looks at the order of the `nf-area` components underneath it 
      and uses the ydata of the next sibling `nf-area` component to determine the bottom 
      of each `nf-area` components path to be drawn.
    
      ### Example
    
          {{#nf-graph width=300 height=100}}
            {{#nf-graph-content}}
              {{#nf-area-stack}}
                {{nf-area data=myData xprop="time" yprop="high"}}
                {{nf-area data=myData xprop="time" yprop="med"}}
                {{nf-area data=myData xprop="time" yprop="low"}}
              {{/nf-area-stack}}
            {{/nf-graph-content}}
          {{/nf-graph}}
    
      @namespace components
      @class nf-area-stack 
    */
    export default Ember.Component.extend({
      tagName: 'g',
    
      /**
        Used by `nf-area` to identify an area stack parent
        @property isAreaStack
        @type Boolean
        @default true
        @readonly
      */
      isAreaStack: true,
    
      /**
        Whether or not to add the values together to create the stacked area
        @property aggregate
        @type {boolean}
        @default false
      */
      aggregate: Ember.computed(function(key, value) {
        if(arguments.length > 1) {
          this._aggregate = value;
        } else if(typeof this._aggregate === 'undefined') {
          Ember.warn('nf-area-stack.aggregate must be set. Currently defaulting to `false` but will default to `true` in the future.')
          this._aggregate = false;
        }
        return this._aggregate;
      }),
    
      /**
        The collection of `nf-area` components under this stack.
        @property areas
        @type Array
        @readonly
      */
      areas: Ember.computed(function(){
        return Ember.A();
      }),
    
      /**
        Registers an area component with this stack. Also links areas to one
        another by setting `nextArea` on each area component.
        @method registerArea
        @param area {Ember.Component} The area component to register.
      */
      registerArea: function(area) {
        var areas = this.get('areas');
        var prev = areas[areas.length - 1];
        
        if(prev) {
          prev.set('nextArea', area);
          area.set('prevArea', prev);
        }
        
        areas.pushObject(area);
      },
    
      /**
        Unregisters an area component from this stack. Also updates next
        and previous links.
        @method unregisterArea
        @param area {Ember.Component} the area to unregister
      */
      unregisterArea: function(area) {
        var prev = area.get('prevArea');
        var next = area.get('nextArea');
    
        if(next) {
          next.set('prevArea', prev);
        }
        
        if(prev) {
          prev.set('nextArea', next);
        }
    
        this.get('areas').removeObject(area);
      },
    });
        
    ================================================ FILE: docs/files/app_components_nf-area.js.html ================================================ app/components/nf-area.js - ember-nf-graph

    API Docs for:
    Show:

    File: app/components/nf-area.js

    import Ember from 'ember';
    import Selectable from 'ember-nf-graph/mixins/graph-selectable-graphic';
    import HasGraphParent from 'ember-nf-graph/mixins/graph-has-graph-parent';
    import RegisteredGraphic from 'ember-nf-graph/mixins/graph-registered-graphic';
    import DataGraphic from 'ember-nf-graph/mixins/graph-data-graphic';
    import AreaUtils from 'ember-nf-graph/mixins/graph-area-utils';
    import GraphicWithTrackingDot from 'ember-nf-graph/mixins/graph-graphic-with-tracking-dot';
    import RequireScaleSource from 'ember-nf-graph/mixins/graph-requires-scale-source';
    import LineUtils from 'ember-nf-graph/mixins/graph-line-utils';
    
    /**
      Adds an area graph to an `nf-graph` component.
      
      Optionally, if it's located within an `nf-area-stack` component, it will work with
      sibling `nf-area` components to create a stacked graph.
      @namespace components
      @class nf-area
      @extends Ember.Component
      @uses mixins.graph-area-utils
      @uses mixins.graph-has-graph-parent
      @uses mixins.graph-selectable-graphic
      @uses mixins.graph-registered-graphic
      @uses mixins.graph-data-graphic
      @uses mixins.graph-graphic-with-tracking-dot
      @uses mixins.graph-requires-scale-source
    */
    export default Ember.Component.extend(HasGraphParent, RegisteredGraphic, DataGraphic, 
      Selectable, AreaUtils, GraphicWithTrackingDot, RequireScaleSource, LineUtils, {    
    
        tagName: 'g',
        
        classNameBindings: [':nf-area', 'selected', 'selectable'],
    
        /**
          The type of d3 interpolator to use to create the area
          @property interpolator
          @type String
          @default 'linear'
        */
        interpolator: 'linear',
    
        /**
          The previous area in the stack, if this area is part of an `nf-area-stack`
          @property prevArea
          @type components.nf-area
          @default null
        */
        prevArea: null,
    
        /**
          The next area in the stack, if this area is part of an `nf-area-stack`
          @property nextArea
          @type components.nf-area
          @default null
        */
        nextArea: null,
    
        init() {
          this._super(...arguments);
          var stack = this.nearestWithProperty('isAreaStack');
          if(stack) {
            stack.registerArea(this);
            this.set('stack', stack);
          }
        },
    
        /**
          Override from `graph-data-graphic` mixin
          @method getActualTrackData
        */
        getActualTrackData(renderX, renderY, data) {
          return {
            x: this.get('xPropFn')(data),
            y: this.get('yPropFn')(data)
          };
        },
    
        _unregister: Ember.on('willDestroyElement', function(){
          var stack = this.get('stack', stack);
          if(stack) {
            stack.unregisterArea(this);
          }
        }),
    
        /**
          The computed set of next y values to use for the "bottom" of the graphed area.
          If the area is part of a stack, this will be the "top" of the next area in the stack,
          otherwise it will return an array of values at the "bottom" of the graph domain.
          @property nextYData
          @type Array
          @readonly
        */
        nextYData: Ember.computed('data.length', 'nextArea.data.@each', function(){
          var data = this.get('data');
          if(!Array.isArray(data)) {
            return [];
          }
          var nextData = this.get('nextArea.mappedData');
          return data.map((d, i) => (nextData && nextData[i] && nextData[i][1]) || Number.MIN_VALUE);
        }),
    
        /**
          The current rendered data "zipped" together with the nextYData.
          @property mappedData
          @type Array
          @readonly
        */
        mappedData: Ember.computed('data.[]', 'xPropFn', 'yPropFn', 'nextYData.@each', 'stack.aggregate', function() {
          var { data, xPropFn, yPropFn, nextYData } = this.getProperties('data', 'xPropFn', 'yPropFn', 'nextYData');
          var aggregate = this.get('stack.aggregate');
          if(Array.isArray(data)) {
            return data.map((d, i) => {
              var x = xPropFn(d);
              var y = yPropFn(d);
              var result = aggregate ? [x, y + nextYData[i], nextYData[i]] : [x, y, nextYData[i]];
              result.data = d;
              return result;
            });
          } else {
            return [];
          }
        }),
    
        areaFn: Ember.computed('xScale', 'yScale', 'interpolator', function(){
          var { xScale, yScale, interpolator } = this.getProperties('xScale', 'yScale', 'interpolator');
          return this.createAreaFn(xScale, yScale, interpolator);
        }),
    
        lineFn: Ember.computed('xScale', 'yScale', 'interpolator', function(){
          var { xScale, yScale, interpolator } = this.getProperties('xScale', 'yScale', 'interpolator');
          return this.createLineFn(xScale, yScale, interpolator);
        }),
    
        d: Ember.computed('renderedData', 'areaFn', function(){
          var renderedData = this.get('renderedData');
          return this.get('areaFn')(renderedData);
        }),
    
        dLine: Ember.computed('renderedData', 'lineFn', function(){
          var renderedData = this.get('renderedData');
          return this.get('lineFn')(renderedData);
        }),
    
        click: function(){
          if(this.get('selectable')) {
            this.toggleProperty('selected');
          }
        }
      });
    
        
    ================================================ FILE: docs/files/app_components_nf-bars.js.html ================================================ app/components/nf-bars.js - ember-nf-graph

    API Docs for:
    Show:

    File: app/components/nf-bars.js

    import Ember from 'ember';
    import HasGraphParent from 'ember-nf-graph/mixins/graph-has-graph-parent';
    import DataGraphic from 'ember-nf-graph/mixins/graph-data-graphic';
    import RegisteredGraphic from 'ember-nf-graph/mixins/graph-registered-graphic';
    import parsePropExpr from 'ember-nf-graph/utils/parse-property-expression';
    import RequireScaleSource from 'ember-nf-graph/mixins/graph-requires-scale-source';
    import GraphicWithTrackingDot from 'ember-nf-graph/mixins/graph-graphic-with-tracking-dot';
    import { normalizeScale } from 'ember-nf-graph/utils/nf/scale-utils';
    import { getRectPath } from 'ember-nf-graph/utils/nf/svg-dom';
    
    /**
      Adds a bar graph to an `nf-graph` component.
    
      **Requires the graph has `xScaleType === 'ordinal'`***
    
      ** `showTrackingDot` defaults to `false` in this component **
    
      @namespace components
      @class nf-bars
      @extends Ember.Component
      @uses mixins.graph-has-graph-parent
      @uses mixins.graph-registered-graphic
      @uses mixins.graph-data-graphic
      @uses mixins.graph-requires-scale-source
      @uses mixins.graph-graphic-with-tracking-dot
    */
    export default Ember.Component.extend(HasGraphParent, RegisteredGraphic, DataGraphic, RequireScaleSource, GraphicWithTrackingDot, {
      tagName: 'g',
    
      classNames: ['nf-bars'],
    
      _showTrackingDot: false,
    
      /**
        The name of the property on each data item containing the className for the bar rectangle
        @property classprop
        @type String
        @default 'className'
      */
      classprop: 'className',
    
      /**
        Gets the function to get the classname from each data item.
        @property getBarClass
        @readonly
        @private
      */
      getBarClass: Ember.computed('classprop', function() {
        var classprop = this.get('classprop');
        return classprop ? parsePropExpr(classprop) : null;
      }),
    
      /**
        The nf-bars-group this belongs to, if any.
        @property group
        @type components.nf-bars-group
        @default null
      */
      group: null,
    
      /**
        The index of this component within the group, if any.
        @property groupIndex
        @type Number
        @default null
      */
      groupIndex: null,
    
      /**
        The graph content height
        @property graphHeight
        @type Number
        @readonly
      */
      graphHeight: Ember.computed.oneWay('graph.graphHeight'),
    
      /**
        A scale provided by nf-bars-group to offset the bar rectangle output
        @property barScale
        @type d3.scale
        @readonly
      */
      barScale: Ember.computed.oneWay('group.barScale'),
    
      /**
        The width of each bar.
        @property barWidth
        @type Number
        @readonly
      */
      barWidth: Ember.computed('xScale', 'barScale', function(){
        var barScale = this.get('barScale');
        if(barScale) {
          return barScale.rangeBand();
        }
        var xScale = this.get('xScale');
        return xScale && xScale.rangeBand ? xScale.rangeBand() : 0;
      }),
    
      groupOffsetX: Ember.computed('barScale', 'groupIndex', function(){
        var barScale = this.get('barScale');
        var groupIndex = this.get('groupIndex');
        return normalizeScale(barScale, groupIndex);
      }),
    
      /**
        The bar models used to render the bars.
        @property bars
        @readonly
      */
      bars: Ember.computed(
        'xScale',
        'yScale',
        'renderedData.@each',
        'graphHeight',
        'getBarClass',
        'barWidth',
        'groupOffsetX',
        function(){
          var { renderedData, xScale, yScale, barWidth, graphHeight, getBarClass, groupOffsetX } = 
            this.getProperties('renderedData', 'xScale', 'yScale', 'graphHeight', 'getBarClass', 'groupOffsetX', 'barWidth');
    
          var getRectPath = this._getRectPath;
    
          if(!xScale || !yScale || !Ember.isArray(renderedData)) {
            return null;
          }
    
          var w = barWidth;
    
          return Ember.A(renderedData.map(function(data) {
            var className = 'nf-bars-bar' + (getBarClass ? ' ' + getBarClass(data.data) : '');
            var x = normalizeScale(xScale, data[0]) + groupOffsetX;
            var y = normalizeScale(yScale, data[1]);
            var h = graphHeight - y;
            var path = getRectPath(x, y, w, h);
    
            return { path, className, data };
          }));
        }
      ),
    
      _getRectPath: getRectPath,
    
      /**
        The name of the action to fire when a bar is clicked.
        @property barClick
        @type String
        @default null
      */
      barClick: null,
    
      init() {
        this._super(...arguments);
        var group = this.nearestWithProperty('isBarsGroup');
        if(group && group.registerBars) {
          group.registerBars(this);
        }
      },
    
      actions: {
        nfBarClickBar: function(dataPoint) {
          if(this.get('barClick')) {
            this.sendAction('barClick', {
              data: dataPoint.data,
              x: dataPoint[0],
              y: dataPoint[1],
              source: this,
              graph: this.get('graph'),
            });
          }
        }
      }
    
    });
        
    ================================================ FILE: docs/files/app_components_nf-crosshair.js.html ================================================ app/components/nf-crosshair.js - ember-nf-graph

    API Docs for:
    Show:

    File: app/components/nf-crosshair.js

    import Ember from 'ember';
    import HasGraphParent from 'ember-nf-graph/mixins/graph-has-graph-parent';
    
    /**
      A component that adds a "crosshair" to an `nf-graph` that follows the mouse
      while it's hovering over the graph content.
      @namespace components
      @class nf-crosshair
      @extends Ember.Component
      @uses mixins.graph-has-graph-parent
    */
    export default Ember.Component.extend(HasGraphParent, {
      tagName: 'g',
    
      classNames: ['nf-crosshair'],
    
      /**
        The height of the crosshair in pixels
        @property height
        @type Number
        @readonly
      */
      height: Ember.computed.alias('graph.graphHeight'),
    
      /**
        The width of the crosshair in pixels
        @property width
        @type Number
        @readonly
      */
      width: Ember.computed.alias('graph.graphWidth'),
    
      /**
        The x position of the crosshairs
        @property x
        @type Number
        @default 0
      */
      x: 0,
    
      /**
        The y position of the crosshairs
        @property y
        @type Number
        @default 0
      */
      y: 0,
    
      /**
        The visibility of the component
        @property isVisible
        @type Boolean
        @default false
      */
      isVisible: false,
    
      didContentHoverChange: function(e) {
        this.set('isVisible', true);
        this.set('x', e.get('mouseX'));
        this.set('y', e.get('mouseY'));
      },
    
      didContentHoverEnd: function() {
        this.set('isVisible', false);
      },
    
      _setupBindings: Ember.observer('graph.content', function() {
        var content = this.get('graph.content');
        if(content) {
          content.on('didHoverChange', this, this.didContentHoverChange);
          content.on('didHoverEnd', this, this.didContentHoverEnd);
        }
      }),
    });
        
    ================================================ FILE: docs/files/app_components_nf-dot.js.html ================================================ app/components/nf-dot.js - ember-nf-graph

    API Docs for:
    Show:

    File: app/components/nf-dot.js

    import Ember from 'ember';
    import HasGraphParent from 'ember-nf-graph/mixins/graph-has-graph-parent';
    import RequireScaleSource from 'ember-nf-graph/mixins/graph-requires-scale-source';
    
    /**
      Plots a circle at a given x and y domain value on an `nf-graph`.
    
      @namespace components
      @class nf-dot
      @extends Ember.Component
      @uses mixins.graph-has-graph-parent
      @uses mixins.graph-requires-scale-source
    */
    export default Ember.Component.extend(HasGraphParent, RequireScaleSource, {
      tagName: 'circle',
    
      attributeBindings: ['r', 'cy', 'cx'],
    
      /**
        The x domain value at which to plot the circle
        @property x
        @type Number
        @default null
      */
      x: null,
      
      /**
        The y domain value at which to plot the circle
        @property x
        @type Number
        @default null
      */
      y: null,
      
      /**
        The radius of the circle plotted
        @property r
        @type Number
        @default 2.5
      */
      r: 2.5,
    
      hasX: Ember.computed.notEmpty('x'),
    
      hasY: Ember.computed.notEmpty('y'),
    
      /**
        The computed center x coordinate of the circle
        @property cx
        @type Number
        @private
        @readonly
      */
      cx: Ember.computed('x', 'xScale', 'hasX', function(){
        var x = this.get('x');
        var xScale = this.get('xScale');
        var hasX = this.get('hasX');
        return hasX && xScale ? xScale(x) : -1;
      }),
    
      /**
        The computed center y coordinate of the circle
        @property cy
        @type Number
        @private
        @readonly
      */
      cy: Ember.computed('y', 'yScale', 'hasY', function() {
        var y = this.get('y');
        var yScale = this.get('yScale');
        var hasY = this.get('hasY');
        return hasY && yScale ? yScale(y) : -1;
      }),
    
      /**
        Toggles the visibility of the dot. If x or y are
        not numbers, will return false.
        @property isVisible
        @private
        @readonly
      */
      isVisible: Ember.computed.and('hasX', 'hasY'),
    });
        
    ================================================ FILE: docs/files/app_components_nf-gg.js.html ================================================ app/components/nf-gg.js - ember-nf-graph

    API Docs for:
    Show:

    File: app/components/nf-gg.js

    import Ember from 'ember';
    import HasGraphParent from 'ember-nf-graph/mixins/graph-has-graph-parent';
    import RequireScaleSource from 'ember-nf-graph/mixins/graph-requires-scale-source';
    import SelectableGraphic from 'ember-nf-graph/mixins/graph-selectable-graphic';
    
    /**
      A grouping tag that provides zooming and offset functionality to it's children.
    
      ## Example
    
      The following example will show a line of `someData` with a 2x zoom, offset by 30px in both x and y
      directions:
    
            {{#nf-gg scaleZoomX="2" scaleZoomY="2" scaleOffsetX="30" scaleOffsetY="30"}}
              {{nf-line data=someData}}
            {{/nf-gg}}
    
      @namespace components
      @class nf-gg
      @extends Ember.Component
      @uses mixins.graph-has-graph-parent
      @uses mixins.graph-require-scale-source
      @uses mixins.graph-selecteble-graphic
    */
    export default Ember.Component.extend(HasGraphParent, RequireScaleSource, SelectableGraphic, {
      tagName: 'g',
      
      classNameBindings: [':nf-gg', 'selectable', 'selected'],
    
      isScaleSource: true,
    
      click: function() {
        if(this.get('selectable')) {
          this.toggleProperty('selected');
        }
      }
    });
        
    ================================================ FILE: docs/files/app_components_nf-graph-content.js.html ================================================ app/components/nf-graph-content.js - ember-nf-graph

    API Docs for:
    Show:

    File: app/components/nf-graph-content.js

    import Ember from 'ember';
    import HasGraphParent from 'ember-nf-graph/mixins/graph-has-graph-parent';
    import GraphMouseEvent from 'ember-nf-graph/utils/nf/graph-mouse-event';
    
    /**
      Container component for graphics to display in `nf-graph`. Represents
      the area where the graphics, such as lines will display.
      
      Exists for layout purposes.
      @namespace components
      @class nf-graph-content
      @uses mixins.graph-has-graph-parent
    */  
    export default Ember.Component.extend(HasGraphParent, {
      tagName: 'g',
      
      classNames: ['nf-graph-content'],
    
      attributeBindings: ['transform', 'clip-path'],
    
      'clip-path': Ember.computed('graph.contentClipPathId', function(){
        var clipPathId = this.get('graph.contentClipPathId');
        return  `url('#${clipPathId}')`;
      }),
    
      /**
        The SVG transform for positioning the graph content
        @property transform
        @type String
        @readonly
      */
      transform: Ember.computed('x', 'y', function(){
        var x = this.get('x');
        var y = this.get('y');
        return `translate(${x} ${y})`;
      }),
    
      /**
        The x position of the graph content
        @property x
        @type Number
        @readonly
      */
      x: Ember.computed.alias('graph.graphX'),
    
      /**
        The calculated y position of the graph content
        @property y
        @type Number
        @readonly
      */
      y: Ember.computed.alias('graph.graphY'),
    
      /**
        The calculated width of the graph content
        @property width
        @type Number
        @readonly
      */
      width: Ember.computed.alias('graph.graphWidth'),
    
      /**
        The calculated height of the graph content.
        @property height
        @type Number
        @readonly
      */
      height: Ember.computed.alias('graph.graphHeight'),
    
    
      /**
        An array containing models to render the grid lanes
        @property gridLanes
        @type Array
        @readonly
      */
      gridLanes: Ember.computed('graph.yAxis.ticks', 'width', 'height', function () {
        var ticks = this.get('graph.yAxis.ticks');
        var width = this.get('width');
        var height = this.get('height');
    
        if(!ticks || ticks.length === 0) {
          return Ember.A();
        }
    
        var sorted = ticks.slice().sort(function(a, b) {
          return a.y - b.y;
        });
    
        if(sorted[0].y !== 0) {
          sorted.unshift({ y: 0 });
        }
    
        var lanes = sorted.reduce(function(lanes, tick, i) {
          var y = tick.y;
          var next = sorted[i+1] || { y: height };
          var h = next.y - tick.y;
          lanes.push({
            x: 0,
            y: y,
            width: width,
            height: h
          });
          return lanes;
        }, []);
    
        return Ember.A(lanes);
      }),
    
      /**
        The name of the hoverChange action to fire
        @property hoverChange
        @type String
        @default null
      */
      hoverChange: null,
    
      mouseMove: function(e) {
        var context = GraphMouseEvent.create({
          originalEvent: e,
          source: this,
          graphContentElement: this.element,
        });
    
        this.trigger('didHoverChange', context);
    
        if(this.get('hoverChange')) {
          this.sendAction('hoverChange', context);
        }
      },
    
      /**
        The name of the hoverEnd action to fire
        @property hoverEnd
        @type String
        @default null
      */
      hoverEnd: null,
    
      mouseLeave: function(e) {
        var context = GraphMouseEvent.create({
          originalEvent: e,
          source: this,
          graphContentElement: this.element
        });
        this.trigger('didHoverEnd', context);
    
        if(this.get('hoverEnd')) {
          this.sendAction('hoverEnd', context);
        }
      },
    
      /**
        An array containing models to render fret lines
        @property frets
        @type Array
        @readonly
      */
      frets: Ember.computed.alias('graph.xAxis.ticks'),
    
      init(){
        this._super(...arguments);
        this.set('graph.content', this);
      },
    });
        
    ================================================ FILE: docs/files/app_components_nf-graph.js.html ================================================ app/components/nf-graph.js - ember-nf-graph

    API Docs for:
    Show:

    File: app/components/nf-graph.js

    import Ember from 'ember';
    import GraphPosition from 'ember-nf-graph/utils/nf/graph-position';
    import { getMousePoint } from 'ember-nf-graph/utils/nf/svg-dom';
    import { toArray } from 'ember-nf-graph/utils/nf/array-helpers';
    
    var Observable = Rx.Observable;
    
    var computedBool = Ember.computed.bool;
    
    var scaleFactoryProperty = function(axis) {
      var scaleTypeKey = axis + 'ScaleType';
      var powExponentKey = axis + 'PowerExponent';
    
      return Ember.computed(scaleTypeKey, powExponentKey, function(){
        var type = this.get(scaleTypeKey);
        var powExp = this.get(powExponentKey);
    
        type = typeof type === 'string' ? type.toLowerCase() : '';
        
        if(type === 'linear') {
          return d3.scale.linear;
        }
    
        else if(type === 'ordinal') {
          return function(){ 
            var scale = d3.scale.ordinal();
            // ordinal scales don't have an invert function, so we need to add one
            scale.invert = function(rv) {
              var [min, max] = d3.extent(scale.range());
              var domain = scale.domain();
              var i = Math.round((domain.length - 1) * (rv - min) / (max - min));
              return domain[i];
            };
            return scale;
          }
        }
        
        else if(type === 'power' || type === 'pow') {
          return function(){
            return d3.scale.pow().exponent(powExp);
          };
        }
        
        else if(type === 'log') {
          return d3.scale.log;
        }
        
        else {
          Ember.warn('unknown scale type: ' + type);
          return d3.scale.linear;
        }
      });
    };
    
    var domainProperty = function(axis) {
      var dataKey = axis + 'UniqueData';
      var minKey = axis + 'Min';
      var maxKey = axis + 'Max';
      var scaleTypeKey = axis + 'ScaleType';
      var logMinKey = axis + 'LogMin';
    
      return Ember.computed(dataKey + '.@each', minKey, maxKey, scaleTypeKey, logMinKey, function(){
        var data = this.get(dataKey);
        var min = this.get(minKey);
        var max = this.get(maxKey);
        var scaleType = this.get(scaleTypeKey);
        var logMin = this.get(logMinKey);
        var domain = null;
    
        if(scaleType === 'ordinal') {
          domain = data;
        } else {
          var extent = [min, max];
    
          if(scaleType === 'log') {
            if (extent[0] <= 0) {
              extent[0] = logMin;
            }
            if (extent[1] <= 0) {
              extent[1] = logMin;
            }
          }
    
          domain = extent;
        }
    
        return domain;
      });
    };
    
    var scaleProperty = function(axis) {
      var scaleFactoryKey = axis + 'ScaleFactory'; 
      var rangeKey = axis + 'Range'; 
      var domainKey = axis + 'Domain'; 
      var scaleTypeKey = axis + 'ScaleType';
      var ordinalPaddingKey = axis + 'OrdinalPadding'; 
      var ordinalOuterPaddingKey = axis + 'OrdinalOuterPadding';
    
      return Ember.computed(
        scaleFactoryKey,
        rangeKey,
        scaleTypeKey,
        ordinalPaddingKey,
        domainKey,
        ordinalOuterPaddingKey,
        function(){
          var scaleFactory = this.get(scaleFactoryKey);
          var range = this.get(rangeKey);
          var domain = this.get(domainKey);
          var scaleType = this.get(scaleTypeKey);
          var ordinalPadding = this.get(ordinalPaddingKey);
          var ordinalOuterPadding = this.get(ordinalOuterPaddingKey);
    
          var scale = scaleFactory();
    
          if(scaleType === 'ordinal') {
            scale = scale.domain(domain).rangeBands(range, ordinalPadding, ordinalOuterPadding);
          } else {        
            scale = scale.domain(domain).range(range).clamp(true);
          }
    
          return scale;
        }
      );
    };
    
    var minProperty = function(axis, defaultTickCount){
      var _DataExtent_ = axis + 'DataExtent';
      var _MinMode_ = axis + 'MinMode';
      var _Axis_tickCount_ = axis + 'Axis.tickCount';
      var _ScaleFactory_ = axis + 'ScaleFactory';
      var __Min_ = '_' + axis + 'Min';
      var _prop_ = axis + 'Min';
      var _autoScaleEvent_ = 'didAutoUpdateMin' + axis.toUpperCase();
    
      return Ember.computed(
        _MinMode_,
        _DataExtent_,
        _Axis_tickCount_,
        _ScaleFactory_,
        function(key, value) {
          var mode = this.get(_MinMode_);
          var ext;
    
          if(arguments.length > 1) {
            this[__Min_] = value;
          } else {
            var self = this;
    
            var change = function(val) {
              self.set(_prop_, val);
              self.trigger(_autoScaleEvent_);
            };
    
            if(mode === 'auto') {
              change(this.get(_DataExtent_)[0] || 0);
            }
    
            else if(mode === 'push') {
              ext = this.get(_DataExtent_)[0];
              if(!isNaN(ext) && ext < this[__Min_]) {
                change(ext);
              }
            }
    
            else if(mode === 'push-tick') {
              var extent = this.get(_DataExtent_);
              ext = extent[0];
    
              if(!isNaN(ext) && ext < this[__Min_]) {
                var tickCount = this.get(_Axis_tickCount_) || defaultTickCount;
                var newDomain = this.get(_ScaleFactory_)().domain(extent).nice(tickCount).domain();
                change(newDomain[0]);
              }
            }
          }
    
          return this[__Min_];
        }
      );
    };
    
    var maxProperty = function(axis, defaultTickCount) {
      var _DataExtent_ = axis + 'DataExtent';
      var _Axis_tickCount_ = axis + 'Axis.tickCount';
      var _ScaleFactory_ = axis + 'ScaleFactory';
      var _MaxMode_ = axis + 'MaxMode';
      var __Max_ = '_' + axis + 'Max';
      var _prop_ = axis + 'Max';
      var _autoScaleEvent_ = 'didAutoUpdateMax' + axis.toUpperCase();
    
      return Ember.computed(
        _MaxMode_,
        _DataExtent_,
        _ScaleFactory_,
        _Axis_tickCount_,
        function(key, value) {
          var mode = this.get(_MaxMode_);
          var ext;
    
          if(arguments.length > 1) {
            this[__Max_] = value;
          } else {
            var self = this;
    
            var change = function(val) {
              self.set(_prop_, val);
              self.trigger(_autoScaleEvent_);
            };
    
            if(mode === 'auto') {
              change(this.get(_DataExtent_)[1] || 1);
            }
    
            else if(mode === 'push') {
              ext = this.get(_DataExtent_)[1];
              if(!isNaN(ext) && this[__Max_] < ext) {
                change(ext);
              }
            }
    
            else if(mode === 'push-tick') {
              var extent = this.get(_DataExtent_);
              ext = extent[1];
    
              if(!isNaN(ext) && this[__Max_] < ext) {
                var tickCount = this.get(_Axis_tickCount_) || defaultTickCount;
                var newDomain = this.get(_ScaleFactory_)().domain(extent).nice(tickCount).domain();
                change(newDomain[1]);
              }
            }
          }
    
          return this[__Max_];
        }
      );
    };
    
    /**
      A container component for building complex Cartesian graphs.
    
      ## Minimal example
    
           {{#nf-graph width=100 height=50}}
             {{#nf-graph-content}}
               {{nf-line data=lineData xprop="foo" yprop="bar"}}
             {{/nf-graph-content}}
           {{/nf-graph}}
    
      The above will create a simple 100x50 graph, with no axes, and a single line
      plotting the data it finds on each object in the array `lineData` at properties
      `foo` and `bar` for x and y values respectively.
    
      ## More advanced example
    
           {{#nf-graph width=500 height=300}}
             {{#nf-x-axis height="50" as |tick|}}
               <text>{{tick.value}}</text>
             {{/nf-x-axis}}
    
             {{#nf-y-axis width="120" as |tick|}}
               <text>{{tick.value}}</text>
             {{/nf-y-axis}}
       
             {{#nf-graph-content}}
               {{nf-line data=lineData xprop="foo" yprop="bar"}}
             {{/nf-graph-content}}
           {{/nf-graph}}
    
      The above example will create a 500x300 graph with both axes visible. The graph will not 
      render either axis unless its component is present.
    
    
      @namespace components
      @class nf-graph
      @extends Ember.Component
    */
    export default Ember.Component.extend({
      tagName: 'div',  
    
      /**
        The exponent to use for xScaleType "pow" or "power".
        @property xPowerExponent
        @type Number
        @default 3
      */
      xPowerExponent: 3,
    
      /**
        The exponent to use for yScaleType "pow" or "power".
        @property yPowerExponent
        @type Number
        @default 3
      */
      yPowerExponent: 3,
    
      /**
        The min value to use for xScaleType "log" if xMin <= 0
        @property xLogMin
        @type Number
        @default 0.1
      */
      xLogMin: 0.1,
    
      /**
        The min value to use for yScaleType "log" if yMin <= 0
        @property yLogMin
        @type Number
        @default 0.1
      */
      yLogMin: 0.1,
    
      /** 
        Allows child compoenents to identify graph parent.
        @property isGraph
        @private
      */
      isGraph: true,
    
      /**
        Identifies this graph to its children as providing scales.
        @property isScaleSource
        @private
      */
      isScaleSource: true,
    
      /**
        @property hasRendered
        @private
      */
      hasRendered: false,
    
      /**
        Gets or sets the whether or not multiple selectable graphics may be
        selected simultaneously.
        @property selectMultiple
        @type Boolean
        @default false
      */
      selectMultiple: false,
    
      /**
        The width of the graph in pixels.
        @property width
        @type Number
        @default 300
      */
      width: 300,
    
      /**
        The height of the graph in pixels.
        @property height
        @type Number
        @default 100
      */
      height: 100,
    
      /**
        The padding at the top of the graph
        @property paddingTop
        @type Number
        @default 0
      */
      paddingTop: 0,
    
      /**
        The padding at the left of the graph
        @property paddingLeft
        @type Number
        @default 0
      */
      paddingLeft: 0,
    
      /**
        The padding at the right of the graph
        @property paddingRight
        @type Number
        @default 0
      */
      paddingRight: 0,
    
      /**
        The padding at the bottom of the graph
        @property paddingBottom
        @type Number
        @default 0
      */
      paddingBottom: 0,
    
      /**
        Determines whether to display "lanes" in the background of
        the graph.
        @property showLanes
        @type Boolean
        @default false
      */
      showLanes: false,
    
      /**
        Determines whether to display "frets" in the background of
        the graph.
        @property showFrets
        @type Boolean
        @default false 
      */
      showFrets: false,
    
      /**
        The type of scale to use for x values.
        
        Possible Values:
        - `'linear'` - a standard linear scale
        - `'log'` - a logarithmic scale
        - `'power'` - a power-based scale (exponent = 3)
        - `'ordinal'` - an ordinal scale, used for ordinal data. required for bar graphs.
        
        @property xScaleType
        @type String
        @default 'linear'
      */
      xScaleType: 'linear',
    
      /**
        The type of scale to use for y values.
        
        Possible Values:
        - `'linear'` - a standard linear scale
        - `'log'` - a logarithmic scale
        - `'power'` - a power-based scale (exponent = 3)
        - `'ordinal'` - an ordinal scale, used for ordinal data. required for bar graphs.
        
        @property yScaleType
        @type String
        @default 'linear'
      */
      yScaleType: 'linear',
      
      /**
        The padding between value steps when `xScaleType` is `'ordinal'`
        @property xOrdinalPadding
        @type Number
        @default 0.1
      */
      xOrdinalPadding: 0.1,
    
      /**
        The padding at the ends of the domain data when `xScaleType` is `'ordinal'`
        @property xOrdinalOuterPadding
        @type Number
        @default 0.1
      */
      xOrdinalOuterPadding: 0.1,
    
      /**
        The padding between value steps when `xScaleType` is `'ordinal'`
        @property yOrdinalPadding
        @type Number
        @default 0.1
      */
      yOrdinalPadding: 0.1,
    
      /**
        The padding at the ends of the domain data when `yScaleType` is `'ordinal'`
        @property yOrdinalOuterPadding
        @type Number
        @default 0.1
      */
      yOrdinalOuterPadding: 0.1,
    
      /**
        the `nf-y-axis` component is registered here if there is one present
        @property yAxis
        @readonly
        @default null
      */
      yAxis: null,
    
      /**
        The `nf-x-axis` component is registered here if there is one present
        @property xAxis
        @readonly
        @default null
      */
      xAxis: null,
    
      /**
        Backing field for `xMin`
        @property _xMin
        @private
      */
      _xMin: null,
    
      /**
        Backing field for `xMax`
        @property _xMax
        @private
      */
      _xMax: null,
    
      /**
        Backing field for `yMin`
        @property _yMin
        @private
      */
      _yMin: null,
    
      /**
        Backing field for `yMax`
        @property _yMax
        @private
      */
      _yMax: null,
    
      /**
        Gets or sets the minimum x domain value to display on the graph.
        Behavior depends on `xMinMode`.
        @property xMin
      */
      xMin: minProperty('x', 8),
    
      /**
        Gets or sets the maximum x domain value to display on the graph.
        Behavior depends on `xMaxMode`.
        @property xMax
      */
      xMax: maxProperty('x', 8),
    
      /**
        Gets or sets the minimum y domain value to display on the graph.
        Behavior depends on `yMinMode`.
        @property yMin
      */
      yMin: minProperty('y', 5),
    
      /**
        Gets or sets the maximum y domain value to display on the graph.
        Behavior depends on `yMaxMode`.
        @property yMax
      */
      yMax: maxProperty('y', 5),
      
    
      /**
        Sets the behavior of `xMin` for the graph.
    
        ### Possible values:
    
        - 'auto': (default) xMin is always equal to the minimum domain value contained in the graphed data. Cannot be set.
        - 'fixed': xMin can be set to an exact value and will not change based on graphed data.
        - 'push': xMin can be set to a specific value, but will update if the minimum x value contained in the graph is less than 
          what xMin is currently set to.
        - 'push-tick': xMin can be set to a specific value, but will update to next "nice" tick if the minimum x value contained in
          the graph is less than that xMin is set to.
    
        @property xMinMode
        @type String
        @default 'auto'
      */
      xMinMode: 'auto',
    
      /**
        Sets the behavior of `xMax` for the graph.
    
        ### Possible values:
    
        - 'auto': (default) xMax is always equal to the maximum domain value contained in the graphed data. Cannot be set.
        - 'fixed': xMax can be set to an exact value and will not change based on graphed data.
        - 'push': xMax can be set to a specific value, but will update if the maximum x value contained in the graph is greater than 
          what xMax is currently set to.
        - 'push-tick': xMax can be set to a specific value, but will update to next "nice" tick if the maximum x value contained in
          the graph is greater than that xMax is set to.
          
        @property xMaxMode
        @type String
        @default 'auto'
      */
      xMaxMode: 'auto',
    
      /**
        Sets the behavior of `yMin` for the graph.
    
        ### Possible values:
    
        - 'auto': (default) yMin is always equal to the minimum domain value contained in the graphed data. Cannot be set.
        - 'fixed': yMin can be set to an exact value and will not change based on graphed data.
        - 'push': yMin can be set to a specific value, but will update if the minimum y value contained in the graph is less than 
          what yMin is currently set to.
        - 'push-tick': yMin can be set to a specific value, but will update to next "nice" tick if the minimum y value contained in
          the graph is less than that yMin is set to.
    
        @property yMinMode
        @type String
        @default 'auto'
      */
      yMinMode: 'auto',
    
      /**
        Sets the behavior of `yMax` for the graph.
    
        ### Possible values:
    
        - 'auto': (default) yMax is always equal to the maximum domain value contained in the graphed data. Cannot be set.
        - 'fixed': yMax can be set to an exact value and will not change based on graphed data.
        - 'push': yMax can be set to a specific value, but will update if the maximum y value contained in the graph is greater than 
          what yMax is currently set to.
        - 'push-tick': yMax can be set to a specific value, but will update to next "nice" tick if the maximum y value contained in
          the graph is greater than that yMax is set to.
          
        @property yMaxMode
        @type String
        @default 'auto'
      */
      yMaxMode: 'auto',
    
      /**
        The data extents for all data in the registered `graphics`.
    
        @property dataExtents
        @type {Object}
        @default {
          xMin: Number.MAX_VALUE,
          xMax: Number.MIN_VALUE,
          yMin: Number.MAX_VALUE,
          yMax: Number.MIN_VALUE
        }
      */
      dataExtents: Ember.computed('graphics.@each.data', function(){
        var graphics = this.get('graphics');
        return graphics.reduce((c, x) => c.concat(x.get('mappedData')), []).reduce((extents, [x, y]) => {
          extents.xMin = extents.xMin < x ? extents.xMin : x;
          extents.xMax = extents.xMax > x ? extents.xMax : x;
          extents.yMin = extents.yMin < y ? extents.yMin : y;
          extents.yMax = extents.yMax > y ? extents.yMax : y;
          return extents;
        }, {
          xMin: Number.MAX_VALUE,
          xMax: Number.MIN_VALUE,
          yMin: Number.MAX_VALUE,
          yMax: Number.MIN_VALUE
        });
      }),
    
      /**
        The action to trigger when the graph automatically updates the xScale 
        due to an "auto" "push" or "push-tick" domainMode.
    
        sends the graph component instance value as the argument.
    
        @property autoScaleXAction
        @type {string}
        @default null
      */
      autoScaleXAction: null,
    
      _sendAutoUpdateXAction() {
        this.sendAction('autoScaleXAction', this);
      },
    
      _sendAutoUpdateYAction() {
        this.sendAction('autoScaleYAction', this);
      },
    
      /**
        Event handler that is fired for the `didAutoUpdateMaxX` event
        @method didAutoUpdateMaxX
      */
      didAutoUpdateMaxX() {
        Ember.run.once(this, this._sendAutoUpdateXAction);
      },
    
      /**
        Event handler that is fired for the `didAutoUpdateMinX` event
        @method didAutoUpdateMinX
      */
      didAutoUpdateMinX() {
        Ember.run.once(this, this._sendAutoUpdateXAction);
      },
    
      /**
        Event handler that is fired for the `didAutoUpdateMaxY` event
        @method didAutoUpdateMaxY
      */
      didAutoUpdateMaxY() {
        Ember.run.once(this, this._sendAutoUpdateYAction);
      },
    
      /**
        Event handler that is fired for the `didAutoUpdateMinY` event
        @method didAutoUpdateMinY
      */
      didAutoUpdateMinY() {
        Ember.run.once(this, this._sendAutoUpdateYAction);
      },
    
      /**
        The action to trigger when the graph automatically updates the yScale 
        due to an "auto" "push" or "push-tick" domainMode.
    
        Sends the graph component instance as the argument.
    
        @property autoScaleYAction
        @type {string}
        @default null
      */
      autoScaleYAction: null,
    
      /**
        Gets the highest and lowest x values of the graphed data in a two element array.
        @property xDataExtent
        @type Array
        @readonly
      */
      xDataExtent: Ember.computed('dataExtents', function(){
        var { xMin, xMax } = this.get('dataExtents');
        return [xMin, xMax];
      }),
    
      /**
        Gets the highest and lowest y values of the graphed data in a two element array.
        @property yDataExtent
        @type Array
        @readonly
      */
      yDataExtent: Ember.computed('dataExtents', function(){
        var { yMin, yMax } = this.get('dataExtents');
        return [yMin, yMax];
      }),
    
      /**
        @property xUniqueData
        @type Array
        @readonly
      */
      xUniqueData: Ember.computed('graphics.@each.mappedData', function(){
        var graphics = this.get('graphics');
        var uniq = graphics.reduce((uniq, graphic) => {
          return graphic.get('mappedData').reduce((uniq, d) => {
            if(!uniq.some(x => x === d[0])) {
              uniq.push(d[0]);
            }
            return uniq;
          }, uniq);
        }, []);
        return Ember.A(uniq);
      }),
    
    
      /**
        @property yUniqueData
        @type Array
        @readonly
      */
      yUniqueData: Ember.computed('graphics.@each.mappedData', function(){
        var graphics = this.get('graphics');
        var uniq = graphics.reduce((uniq, graphic) => {
          return graphic.get('mappedData').reduce((uniq, d) => {
            if(!uniq.some(y => y === d[1])) {
              uniq.push(d[1]);
            }
            return uniq;
          }, uniq);
        }, []);
        return Ember.A(uniq);
      }),
    
      /**
        Gets the DOM id for the content clipPath element.
        @property contentClipPathId
        @type String
        @readonly
        @private
      */
      contentClipPathId: Ember.computed('elementId', function(){
        return this.get('elementId') + '-content-mask';
      }),
    
      /**
        Registry of contained graphic elements such as `nf-line` or `nf-area` components.
        This registry is used to pool data for scaling purposes.
        @property graphics
        @type Array
        @readonly
       */
      graphics: Ember.computed(function(){
        return Ember.A();
      }),
    
      /**
        An array of "selectable" graphics that have been selected within this graph.
        @property selected
        @type Array
        @readonly
      */
      selected: null,
    
      /**
        Computed property to show yAxis. Returns `true` if a yAxis is present.
        @property showYAxis
        @type Boolean
        @default false
       */
      showYAxis: computedBool('yAxis'),
    
      /**
        Computed property to show xAxis. Returns `true` if an xAxis is present.
        @property showXAxis
        @type Boolean
        @default false
       */
      showXAxis: computedBool('xAxis'),
    
      /**
        Gets a function to create the xScale
        @property xScaleFactory
        @readonly
       */
      xScaleFactory: scaleFactoryProperty('x'),
    
      /**
        Gets a function to create the yScale
        @property yScaleFactory
        @readonly
       */
      yScaleFactory: scaleFactoryProperty('y'),
    
      /**
        Gets the domain of x values.
        @property xDomain
        @type Array
        @readonly
       */
      xDomain: domainProperty('x'),
    
      /**
        Gets the domain of y values.
        @property yDomain
        @type Array
        @readonly
       */
      yDomain: domainProperty('y'),
    
      /**
        Gets the current xScale used to draw the graph.
        @property xScale
        @type Function
        @readonly
       */
      xScale: scaleProperty('x'),
    
      /**
        Gets the current yScale used to draw the graph.
        @property yScale
        @type Function
        @readonly
       */
      yScale: scaleProperty('y'),
    
      /**
        Registers a graphic such as `nf-line` or `nf-area` components with the graph.
        @method registerGraphic
        @param graphic {Ember.Component} The component object to register
       */
      registerGraphic: function (graphic) {
        var graphics = this.get('graphics');
        graphics.pushObject(graphic);
        graphic.on('hasData', this, this.updateExtents);
      },
    
      /**
        Unregisters a graphic such as an `nf-line` or `nf-area` from the graph.
        @method unregisterGraphic
        @param graphic {Ember.Component} The component to unregister
       */
      unregisterGraphic: function(graphic) {
        graphic.off('hasData', this, this.updateExtents);
        var graphics = this.get('graphics');
        graphics.removeObject(graphic);
      },
      
      updateExtents() {
        this.get('xDataExtent');
        this.get('yDataExtent');
      },
    
      /**
        The y range of the graph in pixels. The min and max pixel values
        in an array form.
        @property yRange
        @type Array
        @readonly
       */
      yRange: Ember.computed('graphHeight', function(){ 
        return [this.get('graphHeight'), 0];
      }),
    
      /**
        The x range of the graph in pixels. The min and max pixel values
        in an array form.
        @property xRange
        @type Array
        @readonly
       */
      xRange: Ember.computed('graphWidth', function(){
        return [0, this.get('graphWidth')];
      }),
    
      /**
        Returns `true` if the graph has data to render. Data is conveyed
        to the graph by registered graphics.
        @property hasData
        @type Boolean
        @default false
        @readonly
       */
      hasData: Ember.computed.notEmpty('graphics'),
    
      /**
        The x coordinate position of the graph content
        @property graphX
        @type Number
        @readonly
       */
      graphX: Ember.computed('paddingLeft', 'yAxis.width', 'yAxis.orient', function() {
        var paddingLeft = this.get('paddingLeft');
        var yAxisWidth = this.get('yAxis.width') || 0;
        var yAxisOrient = this.get('yAxis.orient');
        if(yAxisOrient === 'right') {
          return paddingLeft;
        }
        return paddingLeft + yAxisWidth;
      }),
    
      /** 
        The y coordinate position of the graph content
        @property graphY
        @type Number
        @readonly
       */
      graphY: Ember.computed('paddingTop', 'xAxis.orient', 'xAxis.height', function(){
        var paddingTop = this.get('paddingTop');
        var xAxisOrient = this.get('xAxis.orient');
        if(xAxisOrient === 'top') {
          var xAxisHeight = this.get('xAxis.height') || 0;
          return xAxisHeight + paddingTop;
        }
        return paddingTop;
      }), 
    
      /**
        The width, in pixels, of the graph content
        @property graphWidth
        @type Number
        @readonly
       */
      graphWidth: Ember.computed('width', 'paddingRight', 'paddingLeft', 'yAxis.width', function() {
        var paddingRight = this.get('paddingRight') || 0;
        var paddingLeft = this.get('paddingLeft') || 0;
        var yAxisWidth = this.get('yAxis.width') || 0;
        var width = this.get('width') || 0;
        return Math.max(0, width - paddingRight - paddingLeft - yAxisWidth);
      }),
    
      /**
        The height, in pixels, of the graph content
        @property graphHeight
        @type Number
        @readonly
       */
      graphHeight: Ember.computed('height', 'paddingTop', 'paddingBottom', 'xAxis.height', function(){
        var paddingTop = this.get('paddingTop') || 0;
        var paddingBottom = this.get('paddingBottom') || 0;
        var xAxisHeight = this.get('xAxis.height') || 0;
        var height = this.get('height') || 0;
        return Math.max(0, height - paddingTop - paddingBottom - xAxisHeight);
      }),
    
      /**
        An SVG transform to position the graph content
        @property graphTransform
        @type String
        @readonly
       */
      graphTransform: Ember.computed('graphX', 'graphY', function(){
        var graphX = this.get('graphX');
        var graphY = this.get('graphY');
        return `translate(${graphX} ${graphY})`;
      }),
    
      /**
        Sets `hasRendered` to `true` on `willInsertElement`.
        @method _notifyHasRendered
        @private
      */
      _notifyHasRendered: Ember.on('willInsertElement', function () {
        this.set('hasRendered', true);
      }),
    
      /**
        Gets the mouse position relative to the container
        @method mousePoint
        @param container {SVGElement} the SVG element that contains the mouse event
        @param e {Object} the DOM mouse event
        @return {Array} an array of `[xMouseCoord, yMouseCoord]`
       */
      mousePoint: function (container, e) {
        var svg = container.ownerSVGElement || container;
        if (svg.createSVGPoint) {
          var point = svg.createSVGPoint();
          point.x = e.clientX;
          point.y = e.clientY;
          point = point.matrixTransform(container.getScreenCTM().inverse());
          return [ point.x, point.y ];
        }
        var rect = container.getBoundingClientRect();
        return [ e.clientX - rect.left - container.clientLeft, e.clientY - rect.top - container.clientTop ];
      },
    
      /**
        A computed property returned the view's controller.
        @property parentController
        @type Ember.Controller
        @readonly
      */
      parentController: Ember.computed.alias('templateData.view.controller'),
    
      /**
        Selects the graphic passed. If `selectMultiple` is false, it will deselect the currently
        selected graphic if it's different from the one passed.
        @method selectGraphic
        @param graphic {Ember.Component} the graph component to select within the graph.
      */
      selectGraphic: function(graphic) {
        if(!graphic.get('selected')) {
          graphic.set('selected', true);
        }
        if(this.selectMultiple) {
          this.get('selected').pushObject(graphic);
        } else {
          var current = this.get('selected');
          if(current && current !== graphic) {
            current.set('selected', false);
          }
          this.set('selected', graphic);
        }
      },
    
      /**
        deselects the graphic passed.
        @method deselectGraphic
        @param graphic {Ember.Component} the graph child component to deselect.
      */
      deselectGraphic: function(graphic) {
        graphic.set('selected', false);
        if(this.selectMultiple) {
          this.get('selected').removeObject(graphic);
        } else {
          var current = this.get('selected');
          if(current && current === graphic) {
            this.set('selected', null);
          }
        }
      },
    
      /**
        The initialization method. Fired on `init`.
        @method _setup
        @private
      */
      init() {
        this._super(...arguments);
        this.set('selected', this.selectMultiple ? Ember.A() : null);
      },
    
      /**
        The amount of leeway, in pixels, to give before triggering a brush start.
        @property brushThreshold
        @type {Number}
        @default 7
      */
      brushThreshold: 7,
    
      /**
        The name of the action to trigger when brushing starts
        @property brushStartAction
        @type {String}
        @default null
      */
      brushStartAction: null,
    
      /**
        The name of the action to trigger when brushing emits a new value
        @property brushAction
        @type {String}
        @default null
      */
      brushAction: null,
    
      /**
        The name of the action to trigger when brushing ends
        @property brushEndAction
        @type {String}
        @default null
      */
      brushEndAction: null,
    
      _setupBrushAction: Ember.on('didInsertElement', function(){
        var content = this.$('.nf-graph-content');
    
        var mouseMoves = Observable.fromEvent(content, 'mousemove');
        var mouseDowns = Observable.fromEvent(content, 'mousedown');
        var mouseUps = Observable.fromEvent(Ember.$(document), 'mouseup');
        var mouseLeaves = Observable.fromEvent(content, 'mouseleave');
    
        this._brushDisposable = Observable.merge(mouseDowns, mouseMoves, mouseLeaves).
          // get a streams of mouse events that start on mouse down and end on mouse up
          window(mouseDowns, function() { return mouseUps; })
          // filter out all of them if there are no brush actions registered
          // map the mouse event streams into brush event streams
          .map(x => this._toBrushEventStreams(x)).
          // flatten to a stream of action names and event objects
          flatMap(x => this._toComponentEventStream(x)).
          // HACK: this is fairly cosmetic, so skip errors.
          retry().
          // subscribe and send the brush actions via Ember
          subscribe(x => {
            Ember.run(this, () => this._triggerComponentEvent(x));
          });
      }),
    
      _toBrushEventStreams: function(mouseEvents) {
        // get the starting mouse event
        return mouseEvents.take(1).
          // calculate it's mouse point and info
          map( this._getStartInfo ).
          // combine the start with the each subsequent mouse event
          combineLatest(mouseEvents.skip(1), toArray).
          // filter out everything until the brushThreshold is crossed
          filter(x => this._byBrushThreshold(x)).
          // create the brush event object
          map(x => this._toBrushEvent(x));
      },
    
      _triggerComponentEvent: function(d) {
        this.trigger(d[0], d[1]);
      },
    
      _toComponentEventStream: function(events) {
        return Observable.merge(
          events.take(1).map(function(e) {
            return ['didBrushStart', e];
          }), events.map(function(e) {
            return ['didBrush', e];
          }), events.last().map(function(e) {
            return ['didBrushEnd', e];
          })
        );
      },
    
      didBrush: function(e) {
        if(this.get('brushAction')) {
          this.sendAction('brushAction', e);
        }
      },
    
      didBrushStart: function(e) {
        document.body.style.setProperty('-webkit-user-select', 'none');
        document.body.style.setProperty('-moz-user-select', 'none');
        document.body.style.setProperty('user-select', 'none');
        if(this.get('brushStartAction')) {
          this.sendAction('brushStartAction', e);
        }
      },
    
      didBrushEnd: function(e) {
        document.body.style.removeProperty('-webkit-user-select');
        document.body.style.removeProperty('-moz-user-select');
        document.body.style.removeProperty('user-select');
        if(this.get('brushEndAction')) {
          this.sendAction('brushEndAction', e);
        }
      },
    
      _toBrushEvent: function(d) {
        var start = d[0];
        var currentEvent =  d[1];
        var currentPoint = getMousePoint(currentEvent.currentTarget, d[1]);
    
        var startPosition = GraphPosition.create({
          originalEvent: start.originalEvent,
          graph: this,
          graphX: start.mousePoint.x,
          graphY: start.mousePoint.y
        });
    
        var currentPosition = GraphPosition.create({
          originalEvent: currentEvent,
          graph: this,
          graphX: currentPoint.x,
          graphY: currentPoint.y
        });
    
        var left = startPosition;
        var right = currentPosition;
    
        if(start.originalEvent.clientX > currentEvent.clientX) {
          left = currentPosition;
          right = startPosition;
        }
    
        return {
          start: startPosition,
          current: currentPosition,
          left: left,
          right: right
        }; 
      },
    
      _byBrushThreshold: function(d) {
        var startEvent = d[0].originalEvent;
        var currentEvent = d[1];
        return Math.abs(currentEvent.clientX - startEvent.clientX) > this.get('brushThreshold');
      },
    
      _getStartInfo: function(e) {
        return {
          originalEvent: e,
          mousePoint: getMousePoint(e.currentTarget, e)
        };
      },
    
      willDestroyElement: function(){
        if(this._brushDisposable) {
          this._brushDisposable.dispose();
        }
      },
    });
    
        
    ================================================ FILE: docs/files/app_components_nf-horizontal-line.js.html ================================================ app/components/nf-horizontal-line.js - ember-nf-graph

    API Docs for:
    Show:

    File: app/components/nf-horizontal-line.js

    import Ember from 'ember';
    import HasGraphParent from 'ember-nf-graph/mixins/graph-has-graph-parent';
    import RequireScaleSource from 'ember-nf-graph/mixins/graph-requires-scale-source';
    
    /**
      Draws a horizontal line on the graph at a given y domain value
      @namespace components
      @class nf-horizontal-line
      @extends Ember.Component
      @uses mixins.graph-has-graph-parent
      @uses mixins.graph-requires-scale-source
    */
    export default Ember.Component.extend(HasGraphParent, RequireScaleSource, {
      tagName: 'line',
    
      attributeBindings: ['lineY:y1', 'lineY:y2', 'x1', 'x2'],
    
      classNames: ['nf-horizontal-line'],
    
      /**
        The y domain value at which to draw the horizontal line
        @property y
        @type Number
        @default null
      */
      y: null,
    
      /**
        The computed y coordinate of the line to draw
        @property lineY
        @type Number
        @private
        @readonly
      */
      lineY: Ember.computed('y', 'yScale', function(){
        var y = this.get('y');
        var yScale = this.get('yScale');
        var py = yScale ? yScale(y) : -1;
        return py && py > 0 ? py : 0;
      }),
    
      /**
        The left x coordinate of the line
        @property x1
        @type Number
        @default 0
        @private
      */
      x1: 0,
    
      /**
        The right x coordinate of the line
        @property x2
        @type Number
        @private
        @readonly
      */
      x2: Ember.computed.alias('graph.graphWidth'),
    });
        
    ================================================ FILE: docs/files/app_components_nf-line.js.html ================================================ app/components/nf-line.js - ember-nf-graph

    API Docs for:
    Show:

    File: app/components/nf-line.js

    import Ember from 'ember';
    import HasGraphParent from 'ember-nf-graph/mixins/graph-has-graph-parent';
    import DataGraphic from 'ember-nf-graph/mixins/graph-data-graphic';
    import LineUtils from 'ember-nf-graph/mixins/graph-line-utils';
    import SelectableGraphic from 'ember-nf-graph/mixins/graph-selectable-graphic';
    import RegisteredGraphic from 'ember-nf-graph/mixins/graph-registered-graphic';
    import GraphicWithTrackingDot from 'ember-nf-graph/mixins/graph-graphic-with-tracking-dot';
    import RequireScaleSource from 'ember-nf-graph/mixins/graph-requires-scale-source';
    
    /**
      A line graphic for `nf-graph`. Displays a line for the data it's passed.
      @namespace components
      @class nf-line
      @extends Ember.Component
      @uses mixins.graph-line-utils
      @uses mixins.graph-has-graph-parent
      @uses mixins.graph-selectable-graphic
      @uses mixins.graph-registered-graphic
      @uses mixins.graph-data-graphic
      @uses mixins.graph-graphic-with-tracking-dot
      @uses mixins.graph-requires-scale-source
    */
    export default Ember.Component.extend(HasGraphParent, DataGraphic, SelectableGraphic, 
      LineUtils, RegisteredGraphic, GraphicWithTrackingDot, RequireScaleSource, {
        
      tagName: 'g',
      
      /**
        The type of D3 interpolator to use to create the line.
        @property interpolator
        @type String
        @default 'linear'
      */
      interpolator: 'linear',
      
      classNameBindings: ['selected', 'selectable'],
    
      classNames: ['nf-line'],
    
      /**
        The d3 line function to create the line path.
        @method lineFn
        @param data {Array} the array of coordinate arrays to plot as an SVG path
        @private
        @return {String} an SVG path data string
      */
      lineFn: Ember.computed('xScale', 'yScale', 'interpolator', function(){
        var xScale = this.get('xScale');
        var yScale = this.get('yScale');
        var interpolator = this.get('interpolator');
        return this.createLineFn(xScale, yScale, interpolator);
      }),
    
      /**
        The SVG path data string to render the line
        @property d
        @type String
        @private
        @readonly
      */
      d: Ember.computed('renderedData.@each', 'lineFn', function(){
        var renderedData = this.get('renderedData');
        var lineFn = this.get('lineFn');
        return lineFn(renderedData);
      }),
    
      /**
        Event handler to toggle the `selected` property on click
        @method _toggleSelected
        @private
      */
      _toggleSelected: Ember.on('click', function(){
        if(this.get('selectable')) {
          this.toggleProperty('selected');
        }
      }),
    });
        
    ================================================ FILE: docs/files/app_components_nf-plot.js.html ================================================ app/components/nf-plot.js - ember-nf-graph

    API Docs for:
    Show:

    File: app/components/nf-plot.js

    import Ember from 'ember';
    import HasGraphParent from 'ember-nf-graph/mixins/graph-has-graph-parent';
    import RequireScaleSource from 'ember-nf-graph/mixins/graph-requires-scale-source';
    import GraphEvent from 'ember-nf-graph/utils/nf/graph-event';
    
    /**
      Plots a group tag on a graph at a given x and y domain coordinate.
      @namespace components
      @class nf-plot
      @extends Ember.Component
      @uses mixins.graph-has-graph-parent
      @uses mixins.graph-requires-scale-source
    */
    export default Ember.Component.extend(HasGraphParent, RequireScaleSource, {
      tagName: 'g',
    
      attributeBindings: ['transform'],
    
      classNames: ['nf-plot'],
    
      /**
        The x domain value to set the plot at
        @property x
        @default null
      */
      x: null,
    
      /**
        The y domain value to set the plot at
        @property x
        @default null
      */
      y: null,
    
      /**
        True if an `x` value is present (defined, not null and non-empty)
        @property hasX
        @type Boolean
        @readonly
      */
      hasX: Ember.computed.notEmpty('x'),
    
      /**
        True if an `y` value is present (defined, not null and non-empty)
        @property hasY
        @type Boolean
        @readonly
      */
      hasY: Ember.computed.notEmpty('y'),
    
      /**
        The calculated visibility of the component
        @property isVisible
        @type Boolean
        @readonly
      */
      isVisible: Ember.computed.and('hasX', 'hasY'),
    
      /**
        The calculated x coordinate
        @property rangeX
        @type Number
        @readonly
      */
      rangeX: Ember.computed('x', 'xScale', function(){
        var xScale = this.get('xScale');
        var x = this.get('x');
        var hasX = this.get('hasX');
        return (hasX && xScale ? xScale(x) : 0) || 0;
      }),
    
      /**
        The calculated y coordinate
        @property rangeY
        @type Number
        @readonly
      */
      rangeY: Ember.computed('y', 'yScale', function(){
        var yScale = this.get('yScale');
        var y = this.get('y');
        var hasY = this.get('hasY');
        return (hasY && yScale ? yScale(y) : 0) || 0;
      }),
    
      /**
        The SVG transform of the component's `<g>` tag.
        @property transform
        @type String
        @readonly
      */
      transform: Ember.computed('rangeX', 'rangeY', function(){
        var rangeX = this.get('rangeX');
        var rangeY = this.get('rangeY');
        return `translate(${rangeX} ${rangeY})`;
      }),
    
      data: null,
    
      click: function(e) {
        var context = GraphEvent.create({
          x: this.get('x'),
          y: this.get('y'),
          data: this.get('data'),
          source: this,
          graph: this.get('graph'),
          originalEvent: e,
        });
        this.sendAction('action', context);
      },
    });
    
    
    
    
    
    
    
    
    
    
        
    ================================================ FILE: docs/files/app_components_nf-plots.js.html ================================================ app/components/nf-plots.js - ember-nf-graph

    API Docs for:
    Show:

    File: app/components/nf-plots.js

    import Ember from 'ember';
    import HasGraphParent from 'ember-nf-graph/mixins/graph-has-graph-parent';
    import DataGraphic from 'ember-nf-graph/mixins/graph-data-graphic';
    import RequireScaleSource from 'ember-nf-graph/mixins/graph-requires-scale-source';
    
    export default Ember.Component.extend(HasGraphParent, DataGraphic, RequireScaleSource, {
      tagName: 'g',
    
      classNames: ['nf-plots'],
      
      /**
        The parent controller to use for template binding
        @property parentController
        @type Ember.Controller
        @readonly
        @private
      */
      parentController: Ember.computed.alias('templateData.view.controller'),
    
      /**
        The model for adding plots to the graph
        @property plotData
        @readonly
        @private
      */
      plotData: Ember.computed('renderedData.@each', function(){
        var renderedData = this.get('renderedData');
        if(renderedData && Ember.isArray(renderedData)) {
          return Ember.A(renderedData.map(function(d) {
            return {
              x: d[0],
              y: d[1],
              data: d.data,
            };
          }));
        }
      }),
    
    
      actions: {
        itemClicked: function(e) {
          this.sendAction('action', e);
        },
      },
    });
        
    ================================================ FILE: docs/files/app_components_nf-range-marker.js.html ================================================ app/components/nf-range-marker.js - ember-nf-graph

    API Docs for:
    Show:

    File: app/components/nf-range-marker.js

    import Ember from 'ember';
    import HasGraphParent from 'ember-nf-graph/mixins/graph-has-graph-parent';
    import RequireScaleSource from 'ember-nf-graph/mixins/graph-requires-scale-source';
    
    /**
      Draws a rectangular strip with a templated label on an `nf-graph`.
      Should always be used in conjunction with an `nf-range-markers` container component.
      @namespace components
      @class nf-range-marker
      @extends Ember.Component
      @uses mixins.graph-has-graph-parent
      @uses mixins.graph-requires-scale-source
    */
    export default Ember.Component.extend(HasGraphParent, RequireScaleSource, {
      tagName: 'g',
    
      attributeBindings: ['transform'],
    
      classNames: ['nf-range-marker'],
    
      /**
        The parent `nf-range-markers` component.
        @property container
        @type {components.nf-range-markers}
        @default null
      */
      container: null,
    
      /**
        The minimum domain value for the range to mark.
        @property xMin
        @default 0
      */
      xMin: 0,
    
      /**
        The maximum domain value for the range to mark.
        @property xMax
        @default 0
      */
      xMax: 0,
    
      /**
        The spacing above the range marker.
        @property marginTop
        @type Number
        @default 10
      */
      marginTop: 10,
    
      /**
        The spacing below the range marker.
        @property marginBottom
        @type Number
        @default 3
      */
      marginBottom: 3,
    
      /**
        The height of the range marker.
        @property height
        @type Number
        @default 10
      */
      height: 10,
    
      /**
        The computed x position of the range marker.
        @property x
        @type Number
        @readonly
      */
      x: Ember.computed('xMin', 'xScale', function(){
        var xScale = this.get('xScale');
        var xMin = this.get('xMin');
        return xScale(xMin);
      }),
    
      /**
        The computed width of the range marker.
        @property width
        @type Number
        @readonly
      */
      width: Ember.computed('xScale', 'xMin', 'xMax', function() {
        var xScale = this.get('xScale');
        var xMax = this.get('xMax');
        var xMin = this.get('xMin');
        return xScale(xMax) - xScale(xMin);
      }),
    
      /**
        The computed y position of the range marker.
        @property y
        @type Number
        @readonly
      */
      y: Ember.computed(
        'container.orient',
        'prevMarker.bottom',
        'prevMarker.y',
        'graph.graphHeight',
        'totalHeight',
        function() {
          var orient = this.get('container.orient');
          var prevBottom = this.get('prevMarker.bottom');
          var prevY = this.get('prevMarker.y');
          var graphHeight = this.get('graph.graphHeight');
          var totalHeight = this.get('totalHeight');
    
          prevBottom = prevBottom || 0;
    
          if(orient === 'bottom') {
            return (prevY || graphHeight) - totalHeight;
          }
    
          if(orient === 'top') {
            return prevBottom;
          }
        }
      ),
    
      /**
        The computed total height of the range marker including its margins.
        @property totalHeight
        @type Number
        @readonly
      */
      totalHeight: Ember.computed('height', 'marginTop', 'marginBottom', function() {
        var height = this.get('height');
        var marginTop = this.get('marginTop');
        var marginBottom = this.get('marginBottom');
        return height + marginTop + marginBottom;
      }),
    
      /**
        The computed bottom of the range marker, not including the bottom margin.
        @property bottom
        @type Number
        @readonly
      */
      bottom: Ember.computed('y', 'totalHeight', function(){
        var y = this.get('y');
        var totalHeight = this.get('totalHeight');
        return y + totalHeight;
      }),
    
      /**
        The computed SVG transform of the range marker container
        @property transform
        @type String
        @readonly
      */
      transform: Ember.computed('y', function(){ 
        var y = this.get('y') || 0;
        return `translate(0 ${y})`;
      }),
    
      /**
        The computed SVG transform fo the range marker label container.
        @property labelTransform
        @type String
        @readonly
      */
      labelTransform: Ember.computed('x', function(){
        var x = this.get('x') || 0;
        return `translate(${x} 0)`;
      }),
    
      /**
        Initialization function that registers the range marker with its parent 
        and populates the container property
        @method _setup
        @private
      */
      init() {
        this._super(...arguments);
        var container = this.nearestWithProperty('isRangeMarkerContainer');
        container.registerMarker(this);
        this.set('container', container);
      },
    
      /**
        Unregisters the range marker from its parent when the range marker is destroyed.
        @method _unregister
        @private
      */
      _unregister: Ember.on('willDestroyElement', function() {
        this.get('container').unregisterMarker(this);
      })
    });
        
    ================================================ FILE: docs/files/app_components_nf-range-markers.js.html ================================================ app/components/nf-range-markers.js - ember-nf-graph

    API Docs for:
    Show:

    File: app/components/nf-range-markers.js

    import Ember from 'ember';
    import HasGraphParent from 'ember-nf-graph/mixins/graph-has-graph-parent';
    
    /**
      A container and manager for `nf-range-marker` components.
      Used to draw an association between `nf-range-marker` components so they 
      can be laid out in a manner in which they don't collide.
      @namespace components
      @class nf-range-markers
      @extends Ember.Component
      @uses mixins.graph-has-graph-parent
    */
    export default Ember.Component.extend(HasGraphParent, {
      tagName: 'g',
      
      /**
        Used by `nf-range-marker` to identify the `nf-range-markers` container
        @property isRangeMarkerContainer
        @type Boolean
        @default true
        @readonly
      */
      isRangeMarkerContainer: true,
    
      /**
        Sets the orientation of the range markers.
    
        - `'bottom'` - Range markers start at the bottom and stack upward
        - `'top'` - Range markers start at the top and stack downward
        @property orient
        @type String
        @default 'bottom'
      */
      orient: 'bottom',
    
      /**
        The margin, in pixels, between the markers
        @property markerMargin
        @type Number
        @default 10
      */
      markerMargin: 10,
    
      /**
        The marker components registered with this container
        @property markers
        @type Array
        @readonly
      */
      markers: Ember.computed(function() {
        return Ember.A();
      }),
    
      /**
        Adds the passed marker to the `markers` list, and sets the `prevMarker` and `nextMarker`
        properties on the marker component and it's neighbor.
        @method registerMarker
        @param marker {nf-range-marker} the range marker to register with this container
      */
      registerMarker: function(marker) {
        var markers = this.get('markers');
        var prevMarker = markers[markers.length - 1];
        
        if(prevMarker) {
          marker.set('prevMarker', prevMarker);
          prevMarker.set('nextMarker', marker);
        }
    
        markers.pushObject(marker);
      },
    
      /**
        Removes the marker from the `markers` list. Also updates the `nextMarker` and `prevMarker`
        properties of it's neighboring components.
        @method unregisterMarker
        @param marker {nf-range-marker} the range marker to remove from the `markers` list.
      */
      unregisterMarker: function(marker) {
        if(marker) {
          var next = marker.nextMarker;
          var prev = marker.prevMarker;
          if(prev) {
            prev.set('nextMarker', next);
          }
          if(next) {
            next.set('prevMarker', prev);
          }
          this.get('markers').removeObject(marker);
        }
      },
    });
        
    ================================================ FILE: docs/files/app_components_nf-right-tick.js.html ================================================ app/components/nf-right-tick.js - ember-nf-graph

    API Docs for:
    Show:

    File: app/components/nf-right-tick.js

    import Ember from 'ember';
    import HasGraphParent from 'ember-nf-graph/mixins/graph-has-graph-parent';
    import RequireScaleSource from 'ember-nf-graph/mixins/graph-requires-scale-source';
    
    /**
      Draws a line and a chevron at the specified domain value 
      on the right side of an `nf-graph`. 
      
      ### Tips
      
      - Position outside of `nf-graph-content` component, but inside `nf-graph`.
      - Adding `paddingRight` to `nf-graph` component will not affect `nf-right-tick`'s position.
      
      @namespace components
      @class nf-right-tick
      @extends Ember.Component
      @uses mixins.graph-has-graph-parent
      @uses mixins.graph-requires-scale-source
    */
    export default Ember.Component.extend(HasGraphParent, RequireScaleSource, {
      tagName: 'g',
    
      classNames: ['nf-right-tick'],
      
      /**
        The transition duration in milliseconds
        @property duration
        @type Number
        @default 400
      */
      duration: 400,
    
      /**
        The domain value at which to place the tick
        @property value
        @type Number
        @default null
      */
      value: null,
    
      /**
        Sets the visibility of the component. Returns false if `y` is not 
        a numeric data type.
        @property isVisible
        @private
        @readonly
      */
      isVisible: Ember.computed('y', function(){
        return !isNaN(this.get('y'));
      }),
    
      /**
        The calculated y coordinate of the tick
        @property y
        @type Number
        @readonly
      */
      y: Ember.computed('value', 'yScale', 'graph.paddingTop', function() {
        var value = this.get('value');
        var yScale = this.get('yScale');
        var paddingTop = this.get('graph.paddingTop');
        var vy = 0;
        if(yScale) {
          vy = yScale(value) || 0;
        }
        return vy + paddingTop;
      }),
    
      /**
        The SVG transform used to render the tick
        @property transform
        @type String
        @private
        @readonly
      */
      transform: Ember.computed('y', 'graph.width', function(){
        var y = this.get('y');
        var graphWidth = this.get('graph.width');
        var x0 = graphWidth - 6;
        var y0 = y - 3;
        return `translate(${x0} ${y0})`;
      }),
    
      /**
        performs the D3 transition to move the tick to the proper position.
        @method _transitionalUpdate
        @private
      */
      _transitionalUpdate: function(){
        var transform = this.get('transform');
        var path = this.get('path');
        var duration = this.get('duration');
        path.transition().duration(duration)
          .attr('transform', transform);
      },
    
      /**
        Schedules the transition when `value` changes on on init.
        @method _triggerTransition
        @private
      */
      _triggerTransition: Ember.on('init', Ember.observer('value', function(){
        Ember.run.scheduleOnce('afterRender', this, this._transitionalUpdate);
      })),
    
      /**
        Updates the tick position without a transition.
        @method _nonTransitionalUpdate
        @private
      */
      _nonTransitionalUpdate: function(){
        var transform = this.get('transform');
        var path = this.get('path');
        path.attr('transform', transform);
      },
    
      /**
        Schedules the update of non-transitional positions
        @method _triggerNonTransitionalUpdate
        @private
      */
      _triggerNonTransitionalUpdate: Ember.observer('graph.width', function(){
        Ember.run.scheduleOnce('afterRender', this, this._nonTransitionalUpdate);
      }),
    
      /**
        Gets the elements required to do the d3 transitions
        @method _getElements
        @private
      */
      _getElements: Ember.on('didInsertElement', function(){
        var g = d3.select(this.$()[0]);
        var path = g.selectAll('path').data([0]);
        this.set('path', path);
      })
    });
        
    ================================================ FILE: docs/files/app_components_nf-selection-box.js.html ================================================ app/components/nf-selection-box.js - ember-nf-graph

    API Docs for:
    Show:

    File: app/components/nf-selection-box.js

    import Ember from 'ember';
    import HasGraphParent from 'ember-nf-graph/mixins/graph-has-graph-parent';
    import RequireScaleSource from 'ember-nf-graph/mixins/graph-requires-scale-source';
    import { normalizeScale } from 'ember-nf-graph/utils/nf/scale-utils';
    
    /**
      Draws a rectangle on an `nf-graph` given domain values `xMin`, `xMax`, `yMin` and `yMax`.
      @namespace components
      @class nf-selection-box
      @extends Ember.Component
      @uses mixins.graph-has-graph-parent
      @uses mixins.graph-requires-scale-source
    */
    export default Ember.Component.extend(HasGraphParent, RequireScaleSource, {
      tagName: 'g', 
    
      /**
        The duration of the transition in ms
        @property duration
        @type Number
        @default 400
      */
      duration: 400,
    
      /**
        The minimum x domain value to encompass.
        @property xMin
        @default null
      */
      xMin: null,
    
      /**
        The maximum x domain value to encompoass.
        @property xMax
        @default null
      */
      xMax: null,
    
      /**
        The minimum y domain value to encompass.
        @property yMin
        @default null
      */
      yMin: null,
    
      /** 
        The maximum y domain value to encompass
        @property yMax
        @default null
      */
      yMax: null,
    
      classNames: ['nf-selection-box'],
    
      /**
        The x pixel position of xMin
        @property x0
        @type Number
      */
      x0: Ember.computed('xMin', 'xScale', function(){
        return normalizeScale(this.get('xScale'), this.get('xMin'));
      }),
    
      /**
        The x pixel position of xMax
        @property x1
        @type Number
      */
      x1: Ember.computed('xMax', 'xScale', function(){
        return normalizeScale(this.get('xScale'), this.get('xMax'));
      }),
    
      /**
        The y pixel position of yMin
        @property y0
        @type Number
      */
      y0: Ember.computed('yMin', 'yScale', function(){
        return normalizeScale(this.get('yScale'), this.get('yMin'));
      }),
    
      /**
        The y pixel position of yMax
        @property y1
        @type Number
      */
      y1: Ember.computed('yMax', 'yScale', function(){
        return normalizeScale(this.get('yScale'), this.get('yMax'));
      }),
    
      /**
        The SVG path string for the box's rectangle.
        @property rectPath
        @type String
      */
      rectPath: Ember.computed('x0', 'x1', 'y0', 'y1', function(){
        var x0 = this.get('x0');
        var x1 = this.get('x1');
        var y0 = this.get('y0');
        var y1 = this.get('y1');
        return `M${x0},${y0} L${x0},${y1} L${x1},${y1} L${x1},${y0} L${x0},${y0}`;
      }),
    
      /**
        Updates the position of the box with a transition
        @method doUpdatePosition
      */
      doUpdatePosition: function(){
        var boxRect = this.get('boxRectElement');
        var rectPath = this.get('rectPath');
        var duration = this.get('duration');
    
        boxRect.transition().duration(duration)
          .attr('d', rectPath);
      },
    
      doUpdatePositionStatic: function(){
        var boxRect = this.get('boxRectElement');
        var rectPath = this.get('rectPath');
    
        boxRect.attr('d', rectPath);
      },
    
      /**
        Schedules an update to the position of the box after render.
        @method updatePosition
        @private
      */
      updatePosition: Ember.observer('xMin', 'xMax', 'yMin', 'yMax', function(){
        Ember.run.once(this, this.doUpdatePosition);
      }),
    
      staticPositionChange: Ember.on('didInsertElement', Ember.observer('xScale', 'yScale', function(){
        Ember.run.once(this, this.doUpdatePositionStatic);
      })),
    
      /**
        Sets up the required d3 elements after component
        is inserted into the DOM
        @method didInsertElement
      */
      didInsertElement: function(){
        var element = this.get('element');
        var g = d3.select(element);
        var boxRect = g.append('path')
          .attr('class', 'nf-selection-box-rect')
          .attr('d', this.get('rectPath'));
    
        this.set('boxRectElement', boxRect);
      },
    });
        
    ================================================ FILE: docs/files/app_components_nf-svg-image.js.html ================================================ app/components/nf-svg-image.js - ember-nf-graph

    API Docs for:
    Show:

    File: app/components/nf-svg-image.js

    import Ember from 'ember';
    import HasGraphParent from 'ember-nf-graph/mixins/graph-has-graph-parent';
    import RequiresScaleSource from 'ember-nf-graph/mixins/graph-requires-scale-source';
    import { normalizeScale } from 'ember-nf-graph/utils/nf/scale-utils';
    import SelectableGraphic from 'ember-nf-graph/mixins/graph-selectable-graphic';
    
    /**
      An image to be displayed in a graph with that takes domain based measurements and
      uses the scale of the graph. Creates an `<image class="nf-image"/>` SVG element.
      @namespace components
      @class nf-svg-image
      @extends Ember.Component
      @uses mixins.graph-has-graph-parent
      @uses mixins.graph-requires-scale-source
      @uses mixins.graph-selectable-graphic
    */
    export default Ember.Component.extend(HasGraphParent, RequiresScaleSource, SelectableGraphic, {
      tagName: 'image',
    
      classNameBindings: [':nf-svg-image', 'selectable', 'selected'],
      
      //HACK: for now xlink:href needs to be bound elsewhere.
      attributeBindings: ['svgX:x', 'svgY:y', 'svgWidth:width', 'svgHeight:height'],
    
      click: function(){
        if(this.get('selectable')) {
          this.toggleProperty('selected');
        }
      },
    
      /**
        The domain x value to place the image at.
        @property x
        @default null
      */
      x: null,
    
      /**
        The domain y value to place the image at.
        @property y
        @default null
      */
      y: null,
    
      _width: 0,
    
      /**
        The width as a domain value. Does not handle ordinal
        scales. To set a pixel value, set `svgWidth` directly.
        @property width
        @type Number
        @default 0
      */
      width: Ember.computed(function(key, value) {
        if(arguments.length > 1) {
          this._width = Math.max(0, +value) || 0;
        }
        return this._width;
      }),
    
      _height: 0,
    
      /**
        The height as a domain value. Does not 
        handle ordinal scales. To set a pixel value, just
        set `svgHeight` directly.
        @property height
        @default null
      */
      height: Ember.computed(function(key, value) {
        if(arguments.length > 1) {
          this._height = Math.max(0, +value) || 0;
        }
        return this._height;
      }),
    
      /**
        The image source url
        @property src
        @type String
      */
      src: Ember.computed(function(key, value) {
        //HACK: because attributeBindings doesn't currently work with namespaced attributes.
        var $elem = this.$();
        if(arguments.length > 1) {
          $elem.attr('xlink:href', value);
        }
        return $elem.attr('xlink:href');
      }),
    
      x0: Ember.computed('x', 'xScale', function(){
        return normalizeScale(this.get('xScale'), this.get('x'));
      }),
    
      y0: Ember.computed('y', 'yScale', function(){
        return normalizeScale(this.get('yScale'), this.get('y'));
      }),
    
      x1: Ember.computed('xScale', 'width', 'x', function(){
        var scale = this.get('xScale');
        if(scale.rangeBands) {
          throw new Error('nf-image does not support ordinal scales');
        }
        return normalizeScale(scale, this.get('width') + this.get('x'));
      }),
    
      y1: Ember.computed('yScale', 'height', 'y', function(){
        var scale = this.get('yScale');
        if(scale.rangeBands) {
          throw new Error('nf-image does not support ordinal scales');
        }
        return normalizeScale(scale, this.get('height') + this.get('y'));
      }),
    
      /**
        The pixel value at which to plot the image.
        @property svgX
        @type Number
      */
      svgX: Ember.computed('x0', 'x1', function(){
        return Math.min(this.get('x0'), this.get('x1'));
      }),
    
      /**
        The pixel value at which to plot the image.
        @property svgY
        @type Number
      */
      svgY: Ember.computed('y0', 'y1', function(){
        return Math.min(this.get('y0'), this.get('y1'));
      }),
    
      /**
        The width, in pixels, of the image.
        @property svgWidth
        @type Number
      */
      svgWidth: Ember.computed('x0', 'x1', function(){
        return Math.abs(this.get('x0') - this.get('x1'));
      }),
    
      /**
        The height, in pixels of the image.
        @property svgHeight
        @type Number
      */
      svgHeight: Ember.computed('y0', 'y1', function(){
        return Math.abs(this.get('y0') - this.get('y1'));
      }),
    });
    
        
    ================================================ FILE: docs/files/app_components_nf-svg-line.js.html ================================================ app/components/nf-svg-line.js - ember-nf-graph

    API Docs for:
    Show:

    File: app/components/nf-svg-line.js

    import Ember from 'ember';
    import HasGraphParent from 'ember-nf-graph/mixins/graph-has-graph-parent';
    import RequiresScaleSource from 'ember-nf-graph/mixins/graph-requires-scale-source';
    import { normalizeScale } from 'ember-nf-graph/utils/nf/scale-utils';
    import SelectableGraphic from 'ember-nf-graph/mixins/graph-selectable-graphic';
    
    /**
      Draws a basic line between two points on the graph. 
      @namespace components
      @class nf-svg-line
      @extends Ember.Component
      @uses mixins.graph-has-graph-parent
      @uses mixins.graph-requires-scale-source
      @uses mixins.graph-selectable-graphic
    */
    export default Ember.Component.extend(HasGraphParent, RequiresScaleSource, SelectableGraphic, {
      tagName: 'line',
    
      classNameBindings: [':nf-svg-line', 'selectable', 'selected'],
    
      attributeBindings: ['svgX1:x1', 'svgX2:x2', 'svgY1:y1', 'svgY2:y2'],
    
      click: function(){
        if(this.get('selectable')) {
          this.toggleProperty('selected');
        }
      },
    
      /**
        The domain value to plot the SVGLineElement's x1 at.
        @property x1
        @default null
      */
      x1: null,
    
      /**
        The domain value to plot the SVGLineElement's x2 at.
        @property x2
        @default null
      */
      x2: null,
    
      /**
        The domain value to plot the SVGLineElement's y1 at.
        @property y1
        @default null
      */
      y1: null,
    
      /**
        The domain value to plot the SVGLineElement's y2 at.
        @property y2
        @default null
      */
      y2: null,
    
      /**
        The pixel value to plot the SVGLineElement's x1 at.
        @property svgX1
        @type Number
      */
      svgX1: Ember.computed('x1', 'xScale', function(){
        return normalizeScale(this.get('xScale'), this.get('x1'));
      }),
      
      /**
        The pixel value to plot the SVGLineElement's x2 at.
        @property svgX2
        @type Number
      */
      svgX2: Ember.computed('x2', 'xScale', function(){
        return normalizeScale(this.get('xScale'), this.get('x2'));
      }),
    
      /**
        The pixel value to plot the SVGLineElement's y1 at.
        @property svgY1
        @type Number
      */
      svgY1: Ember.computed('y1', 'yScale', function(){
        return normalizeScale(this.get('yScale'), this.get('y1'));
      }),
      
      /**
        The pixel value to plot the SVGLineElement's y2 at.
        @property svgY2
        @type Number
      */
      svgY2: Ember.computed('y2', 'yScale', function(){
        return normalizeScale(this.get('yScale'), this.get('y2'));
      }),
    });
    
        
    ================================================ FILE: docs/files/app_components_nf-svg-path.js.html ================================================ app/components/nf-svg-path.js - ember-nf-graph

    API Docs for:
    Show:

    File: app/components/nf-svg-path.js

    import Ember from 'ember';
    import HasGraphParent from 'ember-nf-graph/mixins/graph-has-graph-parent';
    import RequiresScaleSource from 'ember-nf-graph/mixins/graph-requires-scale-source';
    import { normalizeScale } from 'ember-nf-graph/utils/nf/scale-utils';
    import SelectableGraphic from 'ember-nf-graph/mixins/graph-selectable-graphic';
    
    /**
      An SVG path primitive that plots based on a graph's scale.
      @namespace components
      @class nf-svg-path
      @extends Ember.Component
      @uses mixins.graph-has-graph-parent
      @uses mixins.graph-requires-scale-source
      @uses mixins.graph-selectable-graphic
    */
    export default Ember.Component.extend(HasGraphParent, RequiresScaleSource, SelectableGraphic, {
      type: 'path',
    
      classNameBindings: [':nf-svg-path', 'selectable', 'selected'],
    
      attributeBindings: ['d'],
    
      /**
        The array of points to use to plot the path. This is an array of arrays, in the following format:
    
              // specify path pen commands
              [
                [50, 50, 'L'],
                [100, 100, 'L']
              ]
    
              // or they will default to 'L'
              [
                [50, 50],
                [100, 100]
              ]
    
      @property points
      @type Array
      */
      points: null,
    
      /**
        The data points mapped to scale
        @property svgPoints
        @type Array
      */
      svgPoints: Ember.computed('points.[]', 'xScale', 'yScale', function(){
        var points = this.get('points');
        var xScale = this.get('xScale');
        var yScale = this.get('yScale');
        if(Ember.isArray(points) && points.length > 0) {
          return points.map(function(v) {
            var dx = normalizeScale(xScale, v[0]);
            var dy = normalizeScale(yScale, v[1]);
            var c = v.length > 2 ? v[2] : 'L';
            return [dx, dy, c];
          });
        } 
      }),
    
      click: function(){
        if(this.get('selectable')) {
          this.toggleProperty('selected');
        }
      },
    
      /**
        The raw svg path d attribute output
        @property d
        @type String
      */
      d: Ember.computed('svgPoints', function(){
        var svgPoints = this.get('svgPoints');
        if(Ember.isArray(svgPoints) && svgPoints.length > 0) {
          return svgPoints.reduce(function(d, pt, i) {
            if(i === 0) {
              d += 'M' + pt[0] + ',' + pt[1];
            }
            d += ' ' + pt[2] + pt[0] + ',' + pt[1];
            return d;
          }, '');
        } else {
          return 'M0,0';
        }
      }),
    });
        
    ================================================ FILE: docs/files/app_components_nf-svg-rect.js.html ================================================ app/components/nf-svg-rect.js - ember-nf-graph

    API Docs for:
    Show:

    File: app/components/nf-svg-rect.js

    import Ember from 'ember';
    import HasGraphParent from 'ember-nf-graph/mixins/graph-has-graph-parent';
    import RequiresScaleSource from 'ember-nf-graph/mixins/graph-requires-scale-source';
    import { normalizeScale } from 'ember-nf-graph/utils/nf/scale-utils';
    import SelectableGraphic from 'ember-nf-graph/mixins/graph-selectable-graphic';
    
    /**
      A rectangle that plots using domain values from the graph. Uses an SVGPathElement
      to plot the rectangle, to allow for rectangles with "negative" heights.
      @namespace components
      @class nf-svg-rect
      @extends Ember.Component
      @uses mixins.graph-has-graph-parent
      @uses mixins.graph-requires-scale-source
      @uses mixins.graph-selectable-graphic
    */
    export default Ember.Component.extend(HasGraphParent, RequiresScaleSource, SelectableGraphic, {
      tagName: 'path',
    
      attributeBindings: ['d'],
    
      classNameBindings: [':nf-svg-rect', 'selectable', 'selected'],
    
      /**
        The domain x value to place the rect at.
        @property x
        @default null
      */
      x: null,
    
      /**
        The domain y value to place the rect at.
        @property y
        @default null
      */
      y: null,
    
      _width: 0,
    
      /**
        The width as a domain value. If xScale is ordinal, 
        then this value is the indice offset to which to draw the 
        rectangle. In other words, if it's `2`, then draw the rectangle
        to two ordinals past whatever `x` is set to.
        @property width
        @type Number
        @default 0
      */
      width: Ember.computed(function(key, value) {
        if(arguments.length > 1) {
          this._width = +value;
        }
        return this._width;
      }),
    
      _height: 0,
    
      /**
        The height as a domain value. If the yScale is ordinal,
        this value is the indice offset to which to draw the rectangle.
        For example, if the height is `3` then draw the rectangle
        to two ordinals passed whatever `y` is set to.
        @property height
        @type Number
        @default 0
      */
      height: Ember.computed(function(key, value) {
        if(arguments.length > 1) {
          this._height = +value;
        }
        return this._height;
      }),
    
      /**
        The x value of the bottom right corner of the rectangle.
        @property x1
        @type Number
      */
      x1: Ember.computed('width', 'x', 'xScale', function(){
        var xScale = this.get('xScale');
        var w = this.get('width');
        var x = this.get('x');
        if(xScale.rangeBands) {
          var domain = xScale.domain();
          var fromIndex = domain.indexOf(x);
          var toIndex = fromIndex + w;
          return normalizeScale(xScale, domain[toIndex]);
        } else {
          x = +x || 0;
          return normalizeScale(xScale, w + x);
        }
      }),
    
      /**
        The y value of the bottom right corner of the rectangle
        @property y1
        @type Number
      */
      y1: Ember.computed('height', 'y', 'yScale', function(){
        var yScale = this.get('yScale');
        var h = this.get('height');
        var y = this.get('y');
        if(yScale.rangeBands) {
          var domain = yScale.domain();
          var fromIndex = domain.indexOf(y);
          var toIndex = fromIndex + h;
          return normalizeScale(yScale, domain[toIndex]);
        } else {
          y = +y || 0;
          return normalizeScale(yScale, h + y);
        }
      }),
    
      /**
        The x value of the top right corner of the rectangle
        @property x0
        @type Number
      */
      x0: Ember.computed('x', 'xScale', function(){
        return normalizeScale(this.get('xScale'), this.get('x'));
      }),
    
      /**
        The y value of the top right corner of the rectangle.
        @property y0
        @type Number
      */
      y0: Ember.computed('y', 'yScale', function() {
        return normalizeScale(this.get('yScale'), this.get('y'));
      }),
    
      /**
        The SVG path data for the rectangle
        @property d
        @type String
      */
      d: Ember.computed('x0', 'y0', 'x1', 'y1', function(){
        var x0 = this.get('x0');
        var y0 = this.get('y0');
        var x1 = this.get('x1');
        var y1 = this.get('y1');
        return `M${x0},${y0} L${x0},${y1} L${x1},${y1} L${x1},${y0} L${x0},${y0}`;
      }),
    
      /**
        Click event handler. Toggles selected if selectable.
        @method click
      */
      click: function(){
        if(this.get('selectable')) {
          this.toggleProperty('selected');
        }
      }
    });
        
    ================================================ FILE: docs/files/app_components_nf-tracker.js.html ================================================ app/components/nf-tracker.js - ember-nf-graph

    API Docs for:
    Show:

    File: app/components/nf-tracker.js

    import Ember from 'ember';
    import DataGraphic from 'ember-nf-graph/mixins/graph-data-graphic';
    import RequiresScaleSource from 'ember-nf-graph/mixins/graph-requires-scale-source';
    import HasGraphParent from 'ember-nf-graph/mixins/graph-has-graph-parent';
    import GraphicWithTrackingDot from 'ember-nf-graph/mixins/graph-graphic-with-tracking-dot';
    import computed from 'ember-new-computed';
    
    
    /**
      A tracking graphic component used to do things like create tracking dots for nf-area or nf-line.
      @namespace components
      @class nf-tracker
      @uses mixins.graph-has-graph-parent
      @uses mixins.graph-data-graphic
      @uses mixins.graph-requires-scale-source
      @uses mixins.graph-graphic-with-tracking-dot
      */
    export default Ember.Component.extend(HasGraphParent, DataGraphic, RequiresScaleSource, GraphicWithTrackingDot, {
      tagName: 'g',
    
      classNameBindings: [':nf-tracker'],
    
      attributeBindings: ['transform'],
    
      transform: computed('trackedData.x', 'trackedData.y', 'xScale', 'yScale', {
        get() {
          var xScale = this.get('xScale');
          var yScale = this.get('yScale');
          var x = xScale && xScale(this.get('trackedData.x') || 0);
          var y = yScale && yScale(this.get('trackedData.y') || 0);
          return 'translate(' + x + ',' + y + ')';
        }
      })
    });
        
    ================================================ FILE: docs/files/app_components_nf-vertical-line.js.html ================================================ app/components/nf-vertical-line.js - ember-nf-graph

    API Docs for:
    Show:

    File: app/components/nf-vertical-line.js

    import Ember from 'ember';
    import HasGraphParent from 'ember-nf-graph/mixins/graph-has-graph-parent';
    import RequireScaleSource from 'ember-nf-graph/mixins/graph-requires-scale-source';
    
    /**
      Draws a vertical line on a graph at a given x domain value
      @namespace components
      @class nf-vertical-line
      @extends Ember.Component
      @uses mixins.graph-has-graph-parent
      @uses mixins.graph-requires-scale-source
    */
    export default Ember.Component.extend(HasGraphParent, RequireScaleSource, {
      tagName: 'line',
    
      classNames: ['nf-vertical-line'],
    
      attributeBindings: ['lineX:x1', 'lineX:x2', 'y1', 'y2'],
    
      /**
        The top y coordinate of the line
        @property y1
        @type Number
        @default 0
        @private
      */
      y1: 0,
    
      /**
        The bottom y coordinate of the line
        @property y2
        @type Number
        @private
        @readonly
      */
      y2: Ember.computed.alias('graph.graphHeight'),
    
      /**
        The x domain value at which to draw the vertical line on the graph
        @property x
        @type Number
        @default null
      */
      x: null,
    
      /**
        The calculated x coordinate of the vertical line
        @property lineX
        @type Number
        @private
        @readonly
      */
      lineX: Ember.computed('xScale', 'x', function(){
        var xScale = this.get('xScale');
        var x = this.get('x');
        var px = xScale ? xScale(x) : -1;
        return px && px > 0 ? px : 0;
      }),
    });
        
    ================================================ FILE: docs/files/app_components_nf-x-axis.js.html ================================================ app/components/nf-x-axis.js - ember-nf-graph

    API Docs for:
    Show:

    File: app/components/nf-x-axis.js

    import Ember from 'ember';
    import HasGraphParent from 'ember-nf-graph/mixins/graph-has-graph-parent';
    import RequireScaleSource from 'ember-nf-graph/mixins/graph-requires-scale-source';
    
    import layout from '../templates/components/nf-x-axis';
    
    /**
      A component for adding a templated x axis to an `nf-graph` component.
      All items contained within this component are used to template each tick mark on the
      rendered graph. Tick values are supplied to the inner scope of this component on the
      view template via `tick`.
    
      ### Styling
    
      The main container will have a `nf-x-axis` class.
      A `orient-top` or `orient-bottom` container will be applied to the container
      depending on the `orient` setting.
    
      Ticks are positioned via a `<g>` tag, that will contain whatever is passed into it via
      templating, along with the tick line. `<text>` tags within tick templates do have some
      default styling applied to them to position them appropriately based off of orientation.
    
      ### Example
    
            {{#nf-graph width=500 height=300}}
              {{#nf-x-axis height=40 as |tick|}}
                <text>x is {{tick.value}}</text>
              {{/nf-x-axis}}
            {{/nf-graph}}
    
    
      @namespace components
      @class nf-x-axis
      @extends Ember.Component
      @uses mixins.graph-has-graph-parent
      @uses mixins.graph-requires-scale-source
    */
    export default Ember.Component.extend(HasGraphParent, RequireScaleSource, {
      tagName: 'g',
    
      layout: layout,
      template: null,
    
      useTemplate: Ember.computed('hasBlock', 'template.blockParams', 'hasBlockParams', function(){
        var preGlimmerCheck = this.get('template.blockParams');
        var postGlimmerCheck = this.get('hasBlock') && this.get('hasBlockParams');
        return Boolean(postGlimmerCheck || preGlimmerCheck);
      }),
    
      attributeBindings: ['transform'],
      classNameBindings: ['orientClass'],
      classNames: ['nf-x-axis'],
    
      /**
        The height of the x axis in pixels.
        @property height
        @type Number
        @default 20
      */
      height: 20,
    
      /**
        The number of ticks to display
        @property tickCount
        @type Number
        @default 12
      */
      tickCount: 12,
    
      /**
        The length of the tick line (the small vertical line indicating the tick)
        @property tickLength
        @type Number
        @default 0
      */
      tickLength: 0,
    
      /**
        The spacing between the end of the tick line and the origin of the templated
        tick content
        @property tickPadding
        @type Number
        @default 5
      */
      tickPadding: 5,
    
      /**
        The orientation of the x axis. Value can be `'top'` or `'bottom'`.
        @property orient
        @type String
        @default 'bottom'
      */
      orient: 'bottom',
    
      _tickFilter: null,
    
      /**
        An optional filtering function to allow more control over what tick marks are displayed.
        The function should have exactly the same signature as the function you'd use for an
        `Array.prototype.filter()`.
    
        @property tickFilter
        @type Function
        @default null
        @example
    
              {{#nf-x-axis tickFilter=myFilter as |tick|}}
                <text>{{tick.value}}</text>
              {{/nf-x-axis}}
    
        And on your controller:
    
              myFilter: function(tick, index, ticks) {
                return tick.value < 1000;
              },
    
        The above example will filter down the set of ticks to only those that are less than 1000.
      */
      tickFilter: Ember.computed.alias('_tickFilter'),
    
      /**
        The class applied due to orientation (e.g. `'orient-top'`)
        @property orientClass
        @type String
        @readonly
      */
      orientClass: Ember.computed('orient', function(){
        return 'orient-' + this.get('orient');
      }),
    
      /**
        The SVG Transform applied to this component's container.
        @property transform
        @type String
        @readonly
      */
      transform: Ember.computed('x', 'y', function(){
        var x = this.get('x') || 0;
        var y = this.get('y') || 0;
        return `translate(${x} ${y})`;
      }),
    
      /**
        The y position of this component's container.
        @property y
        @type Number
        @readonly
      */
      y: Ember.computed(
        'orient',
        'graph.paddingTop',
        'graph.paddingBottom',
        'graph.height',
        'height',
        function(){
          var orient = this.get('orient');
          var graphHeight = this.get('graph.height');
          var height = this.get('height');
          var paddingBottom = this.get('graph.paddingBottom');
          var paddingTop = this.get('graph.paddingTop');
          var y;
    
          if(orient === 'bottom') {
            y = graphHeight - paddingBottom - height;
          } else {
            y = paddingTop;
          }
    
          return y || 0;
        }
      ),
    
      /**
        This x position of this component's container
        @property x
        @type Number
        @readonly
      */
      x: Ember.computed('graph.graphX', function(){
        return this.get('graph.graphX') || 0;
      }),
    
      init() {
        this._super(...arguments);
        this.set('graph.xAxis', this);
      },
    
      /**
        The width of the component
        @property width
        @type Number
        @readonly
      */
      width: Ember.computed.alias('graph.graphWidth'),
    
      /**
        A method to call to override the default behavior of how ticks are created.
    
        The function signature should match:
    
              // - scale: d3.Scale
              // - tickCount: number of ticks
              // - uniqueData: unique data points for the axis
              // - scaleType: string of "linear" or "ordinal"
              // returns: an array of tick values.
              function(scale, tickCount, uniqueData, scaleType) {
                return [100,200,300];
              }
    
        @property tickFactory
        @type {Function}
        @default null
      */
      tickFactory: null,
    
      tickData: Ember.computed('xScale', 'graph.xScaleType', 'uniqueXData', 'tickCount', 'tickFactory', function(){
        var tickFactory = this.get('tickFactory');
        var scale = this.get('xScale');
        var uniqueData = this.get('uniqueXData');
        var tickCount = this.get('tickCount');
        var scaleType = this.get('graph.xScaleType');
    
        if(tickFactory) {
          return tickFactory(scale, tickCount, uniqueData, scaleType);
        }
        else if(scaleType === 'ordinal') {
          return uniqueData;
        } 
        else {
          return scale.ticks(tickCount);
        }
      }),
    
      /**
        A unique set of all x data on the graph
        @property uniqueXData
        @type Array
        @readonly
      */
      uniqueXData: Ember.computed.uniq('graph.xData'),
    
      /**
        The models for the ticks to display on the axis.
        @property ticks
        @type Array
        @readonly
      */
      ticks: Ember.computed(
        'xScale',
        'tickPadding',
        'tickLength',
        'height',
        'orient',
        'tickFilter',
        'tickData',
        'graph.xScaleType',
        function(){
          var xScale = this.get('xScale');
          var xScaleType = this.get('graph.xScaleType');
          var tickPadding = this.get('tickPadding');
          var tickLength = this.get('tickLength');
          var height = this.get('height');
          var orient = this.get('orient');
          var tickFilter = this.get('tickFilter');
          var ticks = this.get('tickData');
          var y1 = orient === 'top' ? height : 0;
          var y2 = y1 + tickLength;
          var labely = orient === 'top' ? (y1 - tickPadding) : (y1 + tickPadding);
          var halfBandWidth = (xScaleType === 'ordinal') ? xScale.rangeBand() / 2 : 0;
          var result = ticks.map(function(tick) {
            return {
              value: tick,
              x: xScale(tick) + halfBandWidth,
              y1: y1,
              y2: y2,
              labely: labely
            };
          });
    
          if(tickFilter) {
            result = result.filter(tickFilter);
          }
    
          return Ember.A(result);
        }
      ),
    
      /**
        The y position, in pixels, of the axis line
        @property axisLineY
        @type Number
        @readonly
      */
      axisLineY: Ember.computed('orient', 'height', function(){
        var orient = this.get('orient');
        var height = this.get('height');
        return orient === 'top' ? height : 0;
      })
    
    });
    
        
    ================================================ FILE: docs/files/app_components_nf-y-axis.js.html ================================================ app/components/nf-y-axis.js - ember-nf-graph

    API Docs for:
    Show:

    File: app/components/nf-y-axis.js

    import Ember from 'ember';
    import HasGraphParent  from 'ember-nf-graph/mixins/graph-has-graph-parent';
    import RequireScaleSource from 'ember-nf-graph/mixins/graph-requires-scale-source';
    
    import layout from '../templates/components/nf-y-axis';
    
    /**
      A component for adding a templated y axis to an `nf-graph` component.
      All items contained within this component are used to template each tick mark on the 
      rendered graph. Tick values are supplied to the inner scope of this component on the
      view template via `tick`.
      
      ### Styling
      
      The main container will have a `nf-y-axis` class.
      A `orient-left` or `orient-right` container will be applied to the container
      depending on the `orient` setting.
    
      Ticks are positioned via a `<g>` tag, that will contain whatever is passed into it via
      templating, along with the tick line. `<text>` tags within tick templates do have some 
      default styling applied to them to position them appropriately based off of orientation.
    
      ### Example
    
            {{#nf-graph width=500 height=300}}
              {{#nf-y-axis width=40 as |tick|}}
                <text>y is {{tick.value}}</text>
              {{/nf-y-axis}}
            {{/nf-graph}}
    
    
      @namespace components
      @class nf-y-axis
      @uses mixins.graph-has-graph-parent
      @uses mixins.graph-requires-scale-source
    */
    export default Ember.Component.extend(HasGraphParent, RequireScaleSource, {
      tagName: 'g',
    
      layout: layout,
      template: null,
    
      useTemplate: Ember.computed(function(){
        var preGlimmerCheck = this.get('template.blockParams');
        var postGlimmerCheck = this.get('hasBlock') && this.get('hasBlockParams');
        return Boolean(postGlimmerCheck || preGlimmerCheck);
      }),
    
      /**
        The number of ticks to display
        @property tickCount
        @type Number
        @default 5
      */
      tickCount: 5,
    
      /**
        The length of the tick's accompanying line.
        @property tickLength
        @type Number
        @default 5
      */
      tickLength: 5,
    
      /**
        The distance between the tick line and the origin tick's templated output
        @property tickPadding
        @type Number
        @default 3
      */
      tickPadding: 3,
    
      /**
        The total width of the y axis
        @property width
        @type Number
        @default 40
      */
      width: 40,
    
      /**
        The orientation of the y axis. Possible values are `'left'` and `'right'`
        @property orient
        @type String
        @default 'left'
      */
      orient: 'left',
    
      attributeBindings: ['transform'],
    
      classNameBindings: [':nf-y-axis', 'isOrientRight:orient-right:orient-left'],
      
      _tickFilter: null,
    
      /**
        An optional filtering function to allow more control over what tick marks are displayed.
        The function should have exactly the same signature as the function you'd use for an
        `Array.prototype.filter()`.
      
        @property tickFilter
        @type Function
        @default null
        @example
    
              {{#nf-y-axis tickFilter=myFilter as |tick|}}
                <text>{{tick.value}}</text>
              {{/nf-y-axis}}
      
        And on your controller:
        
              myFilter: function(tick, index, ticks) {
                return tick.value < 1000;
              },
      
        The above example will filter down the set of ticks to only those that are less than 1000.
      */
      tickFilter: Ember.computed(function(name, value) {
        if(arguments.length > 1) {
          this._tickFilter = value;
        }
        return this._tickFilter;
      }),
    
      /**
        computed property. returns true if `orient` is equal to `'right'`.
        @property isOrientRight
        @type Boolean
        @readonly
      */
      isOrientRight: Ember.computed.equal('orient', 'right'),
    
    
      /**
        The SVG transform for positioning the component.
        @property transform
        @type String
        @readonly
      */
      transform: Ember.computed('x', 'y', function(){
        var x = this.get('x');
        var y = this.get('y');
        return `translate(${x} ${y})`;
      }),
    
      /**
        The x position of the component
        @property x
        @type Number
        @readonly
      */
      x: Ember.computed(
        'orient',
        'graph.width',
        'width',
        'graph.paddingLeft',
        'graph.paddingRight',
        function(){
          var orient = this.get('orient');
          if(orient !== 'left') {
            return this.get('graph.width') - this.get('width') - this.get('graph.paddingRight');
          }
          return this.get('graph.paddingLeft');
        }
      ),
    
      /**
        The y position of the component
        @property y
        @type Number
        @readonly
      */
      y: Ember.computed.alias('graph.graphY'),
    
      /** 
        the height of the component
        @property height
        @type Number
        @readonly
      */
      height: Ember.computed.alias('graph.height'),
    
      init() {
        this._super(...arguments);
        this.set('graph.yAxis', this);
      },
    
      /**
        A method to call to override the default behavior of how ticks are created.
    
        The function signature should match:
    
              // - scale: d3.Scale
              // - tickCount: number of ticks
              // - uniqueData: unique data points for the axis
              // - scaleType: string of "linear" or "ordinal"
              // returns: an array of tick values.
              function(scale, tickCount, uniqueData, scaleType) {
                return [100,200,300];
              }
    
        @property tickFactory
        @type {Function}
        @default null
      */
      tickFactory: null,
    
      tickData: Ember.computed('graph.yScaleType', 'uniqueYData', 'yScale', 'tickCount', function(){
        var tickFactory = this.get('tickFactory');
        var scale = this.get('yScale');
        var uniqueData = this.get('uniqueYData');
        var scaleType = this.get('graph.yScaleType');
        var tickCount = this.get('tickCount');
    
        if(tickFactory) {
          return tickFactory(scale, tickCount, uniqueData, scaleType);
        }
        else if(scaleType === 'ordinal') {
          return uniqueData;
        } 
        else {
          var ticks = scale.ticks(tickCount);
          if (scaleType === 'log') {
            var step = Math.round(ticks.length / tickCount);
            ticks = ticks.filter(function (tick, i) {
              return i % step === 0;
            });
          }
          return ticks;
        }
      }),
    
      /**
        All y data from the graph, filtered to unique values.
        @property uniqueYData
        @type Array
        @readonly
      */
      uniqueYData: Ember.computed.uniq('graph.yData'),
    
      /** 
        The ticks to be displayed.
        @property ticks
        @type Array
        @readonly
      */
      ticks: Ember.computed(
        'yScale',
        'tickPadding',
        'axisLineX',
        'tickLength',
        'isOrientRight',
        'tickFilter',
        function(){
          var yScale = this.get('yScale');
          var tickPadding = this.get('tickPadding');
          var axisLineX = this.get('axisLineX');
          var tickLength = this.get('tickLength');
          var isOrientRight = this.get('isOrientRight');
          var tickFilter = this.get('tickFilter');
          var ticks = this.get('tickData');
          var x1 = isOrientRight ? axisLineX + tickLength : axisLineX - tickLength;
          var x2 = axisLineX;
          var labelx = isOrientRight ? (tickLength + tickPadding) : (axisLineX - tickLength - tickPadding);
    
          var result = ticks.map(function (tick) {
            return {
              value: tick,
              y: yScale(tick),
              x1: x1,
              x2: x2,
              labelx: labelx,
            };
          });
    
          if(tickFilter) {
            result = result.filter(tickFilter);
          }
    
          return Ember.A(result);
        }
      ),
    
    
      /**
        The x position of the axis line.
        @property axisLineX
        @type Number
        @readonly
      */
      axisLineX: Ember.computed('isOrientRight', 'width', function(){
        return this.get('isOrientRight') ? 0 : this.get('width');
      }),
    });
    
        
    ================================================ FILE: docs/files/app_components_nf-y-diff.js.html ================================================ app/components/nf-y-diff.js - ember-nf-graph

    API Docs for:
    Show:

    File: app/components/nf-y-diff.js

    import Ember from 'ember';
    import HasGraphParent from 'ember-nf-graph/mixins/graph-has-graph-parent';
    import RequireScaleSource from 'ember-nf-graph/mixins/graph-requires-scale-source';
    import { normalizeScale } from 'ember-nf-graph/utils/nf/scale-utils';
    
    /**
      Draws a box underneath (or over) the y axis to between the given `a` and `b`
      domain values. Component content is used to template a label in that box.
    
      ## Tips
    
      - Should be outside of `nf-graph-content`.
      - Should be "above" `nf-y-axis` in the markup.
      - As a convenience, `<text>` elements will automatically be positioned based on y-axis orientation
        due to default styling.
    
      @namespace components
      @class nf-y-diff
      @extends Ember.Component
      @uses mixins.graph-has-graph-parent
      @uses mixins.graph-requires-scale-source
    */
    export default Ember.Component.extend(HasGraphParent, RequireScaleSource, {
      tagName: 'g',
    
      attributeBindings: ['transform'],
    
      classNameBindings: [':nf-y-diff', 'isPositive:positive:negative', 'isOrientRight:orient-right:orient-left'],
    
      /**
        The starting domain value of the difference measurement. The subrahend of the difference calculation.
        @property a
        @type Number
        @default null
      */
      a: null,
      
      /**
        The ending domain value of the difference measurement. The minuend of the difference calculation.
        @property b
        @type Number
        @default null
      */
      b: null,
      
      /**
        The amount of padding, in pixels, between the edge of the difference "box" and the content container
        @property contentPadding
        @type Number
        @default 5
      */
      contentPadding: 5,
      
      /**
        The duration of the transition, in milliseconds, as the difference slides vertically
        @property duration
        @type Number
        @default 400
      */
      duration: 400,
    
      /**
        The calculated vertical center of the difference box, in pixels.
        @property yCenter
        @type Number
        @readonly
      */
      yCenter: Ember.computed('yA', 'yB', function(){
        var yA = +this.get('yA') || 0;
        var yB = +this.get('yB') || 0;
        return (yA + yB) / 2;
      }),
    
      /**
        The y pixel value of b.
        @property yB
        @type Number
      */
      yB: Ember.computed('yScale', 'b', function(){
        return normalizeScale(this.get('yScale'), this.get('b'));
      }),
    
      /**
        The y pixel value of a.
        @property yA
        @type Number
      */
      yA: Ember.computed('yScale', 'a', function() {
        return normalizeScale(this.get('yScale'), this.get('a'));
      }),
    
      /**
        The SVG transformation of the component.
        @property transform
        @type String
        @private
        @readonly
      */
      transform: Ember.computed.alias('graph.yAxis.transform'),
    
      /**
        The calculated difference between `a` and `b`.
        @property diff
        @type Number
        @readonly
      */
      diff: Ember.computed('a', 'b', function(){
        return +this.get('b') - this.get('a');
      }),
    
      /**
        Returns `true` if `diff` is a positive number
        @property isPositive
        @type Boolean
        @readonly
      */
      isPositive: Ember.computed.gte('diff', 0),
      
      /**
        Returns `true` if the graph's y-axis component is configured to orient right.
        @property isOrientRight
        @type Boolean
        @readonly
      */
      isOrientRight: Ember.computed.equal('graph.yAxis.orient', 'right'),
    
      /**
        The width of the difference box
        @property width
        @type Number
        @readonly
      */
      width: Ember.computed.alias('graph.yAxis.width'),
    
      /**
        The view controller for the view this component is present in
        @property parentController
        @type Ember.Controller
        @private
        @readonly
      */
      parentController: Ember.computed.alias('templateData.view.controller'),
    
      /**
        The x pixel coordinate of the content container.
        @property contentX
        @type Number
        @readonly
      */
      contentX: Ember.computed('isOrientRight', 'width', 'contentPadding', function(){
        var contentPadding = this.get('contentPadding');
        var width = this.get('width');
        return this.get('isOrientRight') ? width - contentPadding : contentPadding;
      }),
    
      rectPath: Ember.computed('yA', 'yB', 'width', function(){
        var x = 0;
        var w = +this.get('width') || 0;
        var x2 = x + w;
        var yA = +this.get('yA') || 0;
        var yB = +this.get('yB') || 0;
        return `M${x},${yA} L${x},${yB} L${x2},${yB} L${x2},${yA} L${x},${yA}`;
      }),
    
      /**
        The SVG transformation used to position the content container.
        @property contentTransform
        @type String
        @private
        @readonly
      */
      contentTransform: Ember.computed('contentX', 'yCenter', function(){
        var contentX = this.get('contentX');
        var yCenter = this.get('yCenter');
        return `translate(${contentX} ${yCenter})`;
      }),
    
      /**
        Sets up the d3 related elements when component is inserted 
        into the DOM
        @method didInsertElement
      */
      didInsertElement: function(){
        var element = this.get('element');
        var g = d3.select(element);
        
        var rectPath = this.get('rectPath');
        var rect = g.insert('path', ':first-child')
          .attr('class', 'nf-y-diff-rect')
          .attr('d', rectPath);
    
        var contentTransform = this.get('contentTransform');
        var content = g.select('.nf-y-diff-content');
        content.attr('transform', contentTransform);
    
        this.set('rectElement', rect);
        this.set('contentElement', content);
      },
    
      /**
        Performs the transition (animation) of the elements.
        @method doTransition
      */
      doTransition: function(){
        var duration = this.get('duration');
        var rectElement = this.get('rectElement');
        var contentElement = this.get('contentElement');
    
        if(rectElement) {
          rectElement.transition().duration(duration)
            .attr('d', this.get('rectPath'));
        }
    
        if(contentElement) {
          contentElement.transition().duration(duration)
            .attr('transform', this.get('contentTransform'));
        }
      },
    
      /**
        Schedules a transition once at afterRender.
        @method transition
      */
      transition: Ember.observer('a', 'b', function(){
        Ember.run.once(this, this.doTransition);
      }),
    
      /**
        Updates to d3 managed DOM elments that do
        not require transitioning, because they're width-related.
        @method doAdjustWidth
      */
      doAdjustWidth: function(){
        var contentElement = this.get('contentElement');
        if(contentElement) {
          var contentTransform = this.get('contentTransform');
          contentElement.attr('transform', contentTransform);
        }
      },
    
      adjustGraphHeight: Ember.on('didInsertElement', Ember.observer('graph.graphHeight', function(){
        var rectElement = this.get('rectElement');
        var contentElement = this.get('contentElement');
    
        if(rectElement) {
          rectElement.attr('d', this.get('rectPath'));
        }
    
        if(contentElement) {
          contentElement.attr('transform', this.get('contentTransform'));
        }
      })),
    
      /**
        Schedules a call to `doAdjustWidth` on afterRender
        @method adjustWidth
      */
      adjustWidth: Ember.on(
        'didInsertElement',
        Ember.observer('isOrientRight', 'width', 'contentPadding', function(){
          Ember.run.once(this, this.doAdjustWidth);
        })
      ),
    });
    
    
    
    
        
    ================================================ FILE: docs/files/index.html ================================================ Redirector Click here to redirect ================================================ FILE: docs/index.html ================================================ ember-nf-graph ================================================ FILE: docs/modules/index.html ================================================ Redirector Click here to redirect ================================================ FILE: docs/modules/scale-utils.html ================================================ scale-utils - ember-nf-graph ================================================ FILE: docs/modules/utils_nf_array-helpers.html ================================================ utils/nf/array-helpers - ember-nf-graph ================================================ FILE: docs/modules/utils_nf_svg-dom.html ================================================ utils/nf/svg-dom - ember-nf-graph

    API Docs for:
    ================================================ FILE: ember-cli-build.js ================================================ 'use strict'; const EmberAddon = require('ember-cli/lib/broccoli/ember-addon'); module.exports = function(defaults) { let app = new EmberAddon(defaults, { // Add options here }); /* This build file specifies the options for the dummy test app of this addon, located in `/tests/dummy` This build file does *not* influence how the addon or the app using it behave. You most likely want to be modifying `./index.js` or app's build file */ return app.toTree(); }; ================================================ FILE: index.js ================================================ 'use strict'; module.exports = { name: 'ember-nf-graph', options: { nodeAssets: { d3: { vendor: ['d3.js'] }, rx: { vendor: ['dist/rx.all.js'] } } }, included: function(app) { this._super.included.apply(this, arguments); // see: https://github.com/ember-cli/ember-cli/issues/3718 if (typeof app.import !== 'function' && app.app) { app = app.app; } app.import('vendor/d3/d3.js'); app.import('vendor/rx/dist/rx.all.js'); } }; ================================================ FILE: package.json ================================================ { "name": "ember-nf-graph", "version": "2.0.0-beta.1", "description": "A graphing/charting DSL for Ember.js", "files": [ "LICENSE.md", "README.md", "addon/", "app/", "blueprints/", "index.js", "vendor/" ], "directories": { "doc": "doc", "test": "tests" }, "scripts": { "build": "ember build", "lint:js": "eslint ./*.js addon addon-test-support app config lib server test-support tests", "start": "ember serve", "test": "ember try:each" }, "repository": "https://github.com/netflix/ember-nf-graph.git", "engines": { "node": "^4.5 || 6.* || >= 7.*" }, "author": "Ben Lesh and contributors", "license": "Apache-2.0", "dependencies": { "d3": "~3.5.17", "ember-cli-babel": "^6.6.0", "ember-cli-htmlbars": "^1.1.1", "ember-cli-update": "^0.13.2", "ember-cli-node-assets": "^0.2.2", "rx": "~4.1.0" }, "devDependencies": { "benchpress": "^2.0.0-alpha.16", "broccoli-asset-rev": "^2.4.5", "ember-cli": "~2.18.0", "ember-cli-app-version": "^1.0.0", "ember-cli-dependency-checker": "^2.0.0", "ember-cli-eslint": "^4.2.1", "ember-cli-htmlbars-inline-precompile": "^1.0.0", "ember-cli-inject-live-reload": "^1.4.1", "ember-cli-qunit": "^4.1.1", "ember-cli-release": "0.2.8", "ember-cli-shims": "^1.2.0", "ember-cli-sri": "^2.1.0", "ember-cli-uglify": "^2.0.0", "ember-disable-prototype-extensions": "^1.1.2", "ember-export-application-global": "^2.0.0", "ember-load-initializers": "^1.0.0", "ember-resolver": "^4.0.0", "ember-source": "~2.18.0", "eslint-plugin-ember": "^5.0.0", "eslint-plugin-node": "^5.2.1", "loader.js": "^4.2.3" }, "keywords": [ "ember-addon" ], "ember-addon": { "configPath": "tests/dummy/config", "demoURL": "https://netflix.github.io/ember-nf-graph-examples/dist/" } } ================================================ FILE: protractor.conf.js ================================================ exports.config = { directConnect: true, capabilities: { browserName: 'chrome', chromeOptions: { //Important for benchpress to get timeline data from the browser 'args': ['--js-flags=--expose-gc'], 'perfLoggingPrefs': { 'traceCategories': 'blink.console,disabled-by-default-devtools.timeline' } }, loggingPrefs: { performance: 'ALL' } }, specs: ['tests/perf/**/*.spec.js'], framework: 'jasmine2', // onCleanUp: function() { // console.log("KILLED"); // emberProcess.kill(); // }, // onPrepare: function() { // // open a new browser for every benchmark // var originalBrowser = browser; // var _tmpBrowser; // beforeEach(function() { // global.browser = originalBrowser.forkNewDriverInstance(); // global.element = global.browser.element; // global.$ = global.browser.$; // global.$$ = global.browser.$$; // }); // afterEach(function() { // global.browser.quit(); // global.browser = originalBrowser; // }); // }, restartBrowserBetweenTests: true, jasmineNodeOpts: { showColors: true, defaultTimeoutInterval: 30000 }, }; ================================================ FILE: testem.js ================================================ module.exports = { test_page: 'tests/index.html?hidepassed', disable_watching: true, launch_in_ci: [ 'Chrome' ], launch_in_dev: [ 'Chrome' ], browser_args: { Chrome: { mode: 'ci', args: [ '--disable-gpu', '--headless', '--remote-debugging-port=0', '--window-size=1440,900' ] } } }; ================================================ FILE: tests/dummy/app/app.js ================================================ import Application from '@ember/application'; import Resolver from './resolver'; import loadInitializers from 'ember-load-initializers'; import config from './config/environment'; const App = Application.extend({ modulePrefix: config.modulePrefix, podModulePrefix: config.podModulePrefix, Resolver }); loadInitializers(App, config.modulePrefix); export default App; ================================================ FILE: tests/dummy/app/components/.gitkeep ================================================ ================================================ FILE: tests/dummy/app/components/bars-with-line.js ================================================ import Component from '@ember/component'; import { computed } from '@ember/object'; import { dataGenerator } from '../services/data-generator'; export default Component.extend({ classNames: ['bars-with-line'], barData: computed(function() { return dataGenerator.simpleOrdinalData(); }), lineData: computed(function() { return dataGenerator.simpleOrdinalData(); }), }); ================================================ FILE: tests/dummy/app/components/basic-area-graph.js ================================================ import Component from '@ember/component'; import { computed } from '@ember/object'; import { dataGenerator } from '../services/data-generator'; export default Component.extend({ graphData: computed(function() { return dataGenerator.simpleTimeSeries(); }) }); ================================================ FILE: tests/dummy/app/components/basic-bar-graph.js ================================================ import Component from '@ember/component'; import { computed } from '@ember/object'; import { dataGenerator } from '../services/data-generator'; export default Component.extend({ graphData: computed(function() { return dataGenerator.simpleOrdinalData(); }) }); ================================================ FILE: tests/dummy/app/components/basic-line-graph.js ================================================ import Component from '@ember/component'; import { computed } from '@ember/object'; import { dataGenerator } from '../services/data-generator'; export default Component.extend({ graphData: computed(function() { return dataGenerator.simpleTimeSeries(); }) }); ================================================ FILE: tests/dummy/app/components/brush-select-zoom.js ================================================ import { computed, get } from '@ember/object'; import Component from '@ember/component'; import { dataGenerator } from '../services/data-generator'; import { format } from '../helpers/format-hour-minute'; export default Component.extend({ // Start and end dates for filtering the graph data. // These are the initial values and will change when brush actions // are executed below startTime: 0, endTime: Number.MAX_VALUE, // Domain values for right and left brush markers. These are modified // when the user drags with the mouse. selectLeft: undefined, selectRight: undefined, // Original graph data (no zoom or filter) graphData: computed(function() { return dataGenerator.simpleTimeSeries(); }), // Graph data filtered by zoom extents. Filtered to include only data points // falling within the zoom start and end dates zoomData: computed('graphData', 'startTime', 'endTime', function() { var self = this; return this.get('graphData').filter(function(d) { return d.x >= self.get('startTime') && d.x <= self.get('endTime'); }); }), // Formats the text shown on the brush selection markers. // This is using the format code imported from helper:format-hour-minute selectionDisplayFormatter: function(ms) { return format([ ms ]); }, actions: { brushEnd: function(e) { // Now that the brush drag is finished set new // zoom values for filtering the main graph data this.set('startTime', get(e, 'left.x')); this.set('endTime', get(e, 'right.x')); }, reset: function() { // Reset teh zoom extents this.set("startTime", 0); this.set("endTime", Number.MAX_VALUE); } }, }); ================================================ FILE: tests/dummy/app/components/detailed-line-graph.js ================================================ import Component from '@ember/component'; import { computed } from '@ember/object'; import { dataGenerator } from '../services/data-generator'; export default Component.extend({ graphData: computed(function() { return dataGenerator.simpleTimeSeries(); }) }); ================================================ FILE: tests/dummy/app/components/graph-primitives.js ================================================ import Component from '@ember/component'; import { computed } from '@ember/object'; import { dataGenerator } from '../services/data-generator'; import { min, max } from '../services/utility'; export default Component.extend({ barHeight: 1, graphData: computed(function() { return dataGenerator.simpleTimeSeries(); }), extent: computed('graphData', function() { var data = this.get('graphData'); return { xMin: min(data.map(d => d.start)), xMax: max(data.map(d => d.start)), yMin: min(data.map(d => d.index)), yMax: max(data.map(d => d.index)), }; }), }); ================================================ FILE: tests/dummy/app/components/mouse-tracking-data.js ================================================ import Component from '@ember/component'; import { computed } from '@ember/object'; import { dataGenerator } from '../services/data-generator'; export default Component.extend({ graphData: computed(function() { return dataGenerator.threeMetricTimeSeries(); }) }); ================================================ FILE: tests/dummy/app/components/mouse-tracking.js ================================================ import Component from '@ember/component'; import { computed } from '@ember/object'; import { dataGenerator } from '../services/data-generator'; export default Component.extend({ graphData: computed(function() { return dataGenerator.threeMetricTimeSeries(); }) }); ================================================ FILE: tests/dummy/app/components/stacked-area-graph.js ================================================ import Component from '@ember/component'; import { computed } from '@ember/object'; import { dataGenerator } from '../services/data-generator'; export default Component.extend({ graphData: computed(function() { return dataGenerator.threeMetricTimeSeries(); }) }); ================================================ FILE: tests/dummy/app/controllers/.gitkeep ================================================ ================================================ FILE: tests/dummy/app/controllers/nf-graph/index.js ================================================ import Controller from '@ember/controller'; import { A } from '@ember/array'; import $ from 'jquery'; import Ember from 'ember'; const { Logger } = Ember; export function generateLineData(xStart, yMin, yMax, variance, count, yStart){ var p = yStart || 0; return A( range(count).map(function(d, i) { var y = p + (Math.random() * variance) - (variance / 2); y = Math.min(yMax, Math.max(yMin, y)); p = y; return { x: xStart + i, y: y }; }) ); } function range(count) { var output = A(); var i = 0; while(i < count) { output.push(i++); } return output; } export default Controller.extend({ graphWidth: 400, graphHeight: 300, diffA: 100, diffB: 200, queryParams: A(['graphWidth' , 'graphHeight']), init(){ this._super(...arguments); this.send('updateLine'); }, xTickFilter: function() { return true; }, xTickFactory: function() { var ticks = A([1, 10, 30, 50, 80, 99]); return ticks; }, actions: { updateAreas() { this.set('model.area1', generateLineData(0, 0, 50, 20, 10)); this.set('model.area2', generateLineData(0, 51, 100, 20, 10)); this.set('model.area3', generateLineData(0, 101, 150, 20, 10)); }, updateLine: function(){ this.set('lineData', generateLineData(0, 0, 200, 50, 10, 10)); }, brushStart: function(e) { Logger.debug('brush start', e.left.get('x'), e.right.get('x')); this.set('brushLeft', e.left.get('x')); this.set('brushRight', e.right.get('x')); }, brush: function(e) { Logger.debug('brush ', e.left.get('x'), e.right.get('x')); this.set('brushLeft', e.left.get('x')); this.set('brushRight', e.right.get('x')); }, brushEnd: function(e) { Logger.debug('brush end', e.left.get('x'), e.right.get('x')); this.set('brushLeft', undefined); this.set('brushRight', undefined); }, test: function(){ Logger.log('test!'); }, appendAreaData: function(area) { var last = area[area.length - 1]; area.pushObject({ x: last.x + 1, y: last.y }); }, showData: function(e) { $('.test-div').remove(); var testDiv = $('
    '); testDiv.css({ width: 'auto', height: 'auto', padding: '10px', background: 'white', position: 'absolute', top: e.get('pagePositionY') + 'px', left: e.get('pagePositionX') + 'px', }); testDiv.text(e.data.y); testDiv.appendTo('body'); Logger.log('showData', e); }, } }); ================================================ FILE: tests/dummy/app/controllers/nf-graph/nf-bars.js ================================================ /* eslint-disable no-console */ import Controller from '@ember/controller'; export default Controller.extend({ actions: { barClicked: function(barData) { console.log('barData', barData); }, } }); ================================================ FILE: tests/dummy/app/helpers/.gitkeep ================================================ ================================================ FILE: tests/dummy/app/helpers/format-hour-minute.js ================================================ /* exported format */ import { helper } from '@ember/component/helper'; import { isPresent } from '@ember/utils'; export function format([ ms ]) { if(isNaN(ms) || !isPresent(ms)) { return ""; } var date = new Date(ms); var h = date.getHours(); var m = date.getMinutes(); if(h < 10) { h = "0" + h; } if(m < 10) { m = "0" + m; } return h + ":" + m; } export default helper(format); ================================================ FILE: tests/dummy/app/index.html ================================================ Dummy {{content-for "head"}} {{content-for "head-footer"}} {{content-for "body"}} {{content-for "body-footer"}} ================================================ FILE: tests/dummy/app/models/.gitkeep ================================================ ================================================ FILE: tests/dummy/app/resolver.js ================================================ import Resolver from 'ember-resolver'; export default Resolver; ================================================ FILE: tests/dummy/app/router.js ================================================ import EmberRouter from '@ember/routing/router'; import config from './config/environment'; const Router = EmberRouter.extend({ location: config.locationType, rootURL: config.rootURL }); Router.map(function() { this.route('nf-graph', function(){ this.route('/'); this.route('nf-bars'); }); this.route('examples'); }); export default Router; ================================================ FILE: tests/dummy/app/routes/.gitkeep ================================================ ================================================ FILE: tests/dummy/app/routes/index.js ================================================ import Route from '@ember/routing/route'; export default Route.extend({ redirect() { this.replaceWith('nf-graph'); } }); ================================================ FILE: tests/dummy/app/routes/nf-graph/index.js ================================================ import { A } from '@ember/array'; import Route from '@ember/routing/route'; export default Route.extend({ model: function() { return { lineData: generateLineData(0, 0, 2000, 200, 240, 500), lineData2: generateLineData(0, 100, 1000, 100, 500), area1: generateLineData(0, 0, 50, 20, 10), area2: generateLineData(0, 51, 100, 20, 11), area3: generateLineData(0, 101, 150, 20, 10) }; } }); export function generateLineData(xStart, yMin, yMax, variance, count, yStart){ var p = yStart || 0; return A( range(count).map(function(d, i) { var y = p + (Math.random() * variance) - (variance / 2); y = Math.min(yMax, Math.max(yMin, y)); p = y; return { x: xStart + i, y: y }; }) ); } function range(count) { var output = A(); var i = 0; while(i < count) { output.push(i++); } return output; } ================================================ FILE: tests/dummy/app/routes/nf-graph/nf-bars.js ================================================ import Route from '@ember/routing/route'; export default Route.extend({ model() { return { menuItemStockCount: [ { x: 0, y: 200 }, { x: 1, y: 154 }, { x: 2, y: 130 }, { x: 3, y: 300 } ] }; } }); ================================================ FILE: tests/dummy/app/services/data-generator.js ================================================ var minutes = function(n) { return n * 60000; }; var random = function(min, max) { return Math.floor(Math.random() * (max - min + 1) + min); }; var dataGenerator = { simpleTimeSeries: function() { const count = 24; var now = Date.now(); var data = []; for(var i=1; i<=count; i++) { let y = random(0, 10); let x = now - minutes((count * 2) - (i * 2)); data.push({ x: x, y: y }); } return data; }, threeMetricTimeSeries: function() { const count = 24; var now = Date.now(); var data = []; for(var i=1; i<=count; i++) { let x = now - minutes((count * 2) - (i * 2)); let y1 = random(0, 9); let y2 = random(10, 19); let y3 = random(20, 29); data.push({ date: x, low: y1, medium: y2, high: y3 }); } return data; }, simpleOrdinalData: function() { const count = 10; var data = []; for(var i=0; i !isNaN(item)); var result = Math.max.apply(null, test); return result; }; export var min = function(array) { if(!Array.isArray(array)) { return array; } var test = array.filter(item => !isNaN(item)); var result = Math.min.apply(null, test); return result; }; ================================================ FILE: tests/dummy/app/styles/app.css ================================================ html, body { margin: 20px; } ================================================ FILE: tests/dummy/app/templates/application.hbs ================================================ {{outlet}} ================================================ FILE: tests/dummy/app/templates/components/bars-with-line.hbs ================================================ {{#nf-graph xScaleType="ordinal" yMinMode="fixed" yMin=0 as |nf|}} {{#nf.graph as |graph|}} {{graph.bars data=barData}} {{graph.line data=lineData class="dashed"}} {{/nf.graph}} {{/nf-graph}}

    Template

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    
    {{#nf-graph
        xScaleType="ordinal"
        yMinMode="fixed"
        yMin=0}}
    
       {{#nf-graph-content}}
    
         {{nf-bars data=barData}}
         {{nf-line data=lineData class="dashed"}}
    
       {{/nf-graph-content}}
    {{/nf-graph}}

    Lines, areas, and bars can be combined in one graph. nf-graph will account for the domain data within each graph elemen to determine axis and scales. In this example a bar graph is superimposed with a line plot.

    Component JavaScript

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    
    import Ember from 'ember';
    import { dataGenerator } from '../services/data-generator';
    
    export default Ember.Component.extend({
      classNames: ['bars-with-line'],
    
      barData: function() {
        return dataGenerator.simpleOrdinalData();
      }.property(),
    
      lineData: function() {
        return dataGenerator.simpleOrdinalData();
      }.property()
    
    });
    ================================================ FILE: tests/dummy/app/templates/components/basic-area-graph.hbs ================================================ {{#nf-graph as |nf|}} {{#nf.graph as |graph|}} {{graph.area data=graphData}} {{/nf.graph}} {{/nf-graph}}

    Template

    1
    2
    3
    4
    5
    6
    7
    
    {{#nf-graph}}
      {{#nf-graph-content}}
    
        {{nf-area data=graphData}}
    
      {{/nf-graph-content}}
    {{/nf-graph}}

    \{{#nf-graph}} is the main container.

    \{{#nf-graph-content}} is the container for elements that should appear inside the graph's plot area.

    \{{#nf-area}} adds an area plot to the graph. "data=graphData" assigns an array of data to the line.

    By default \{{nf-area}} will look for properties "x" and "y" on each element in the data array. "y" defines the top curve of the area. \{{nf-area}} also accepts a second y value "y1" to defind the bottom of the area curve. If "y1" is not provided as in this example it defaults to zero and plotted to fill the bottom of the graph.

    Component JavaScript

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    
    import Ember from 'ember';
    import { dataGenerator } from '../services/data-generator';
    
    export default Ember.Component.extend({
    
      graphData: function() {
        return dataGenerator.simpleTimeSeries();
      }.property()
    
    });
    ================================================ FILE: tests/dummy/app/templates/components/basic-bar-graph.hbs ================================================ {{#nf-graph xScaleType="ordinal" yMinMode="fixed" yMin=0 as |nf|}} {{#nf.graph as |graph|}} {{graph.bars data=graphData}} {{/nf.graph}} {{/nf-graph}}

    Template

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    
    {{#nf-graph
        xScaleType="ordinal"
        yMinMode="fixed"
        yMin=0}}
    
       {{#nf-graph-content}}
    
         {{nf-bars data=graphData}}
    
       {{/nf-graph-content}}
    {{/nf-graph}}

    \{{#nf-graph}} is the main container. xScaleType="ordinal" is required for bar graphs and causes bars to be evenly spaced based on ordinal position. yMinMode="fixed" and yMin=0 causes the Y Axis to always start at zero regardless of the minimum data value among the data array elements (works with any graph type).

    \{{#nf-graph-content}} is the container for elements that should appear inside the graph's plot area.

    \{{#nf-bars}} adds a set of bars the graph. "data=graphData" assigns an array of data to the line. One bar is drawn for each element in the array.

    By default \{{nf-bars}} will look for properties "x" and "y" on each element in the data array. "x" defines the ordinal position of each bar and is often a simple index. "y" defines the height of each bar. Bar heights are draw relative to each other based on the minimum and maximum y values among all the data elements.

    Component JavaScript

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    
    import Ember from 'ember';
    import { dataGenerator } from '../services/data-generator';
    
    export default Ember.Component.extend({
    
      graphData: function() {
        return dataGenerator.simpleOrdinalData();
      }.property()
    
    });
    
    ================================================ FILE: tests/dummy/app/templates/components/basic-line-graph.hbs ================================================ {{#nf-graph as |nf|}} {{#nf.graph as |graph|}} {{graph.line data=graphData}} {{/nf.graph}} {{/nf-graph}}

    Template

    1
    2
    3
    4
    5
    6
    7
    
    {{#nf-graph}}
       {{#nf-graph-content}}
    
         {{nf-line data=graphData}}
    
       {{/nf-graph-content}}
    {{/nf-graph}}

    \{{#nf-graph}} is the main container.

    \{{#nf-graph-content}} is the container for elements that should appear inside the graph's plot area.

    \{{#nf-line}} adds a line plot to the graph. "data=graphData" assigns an array of data to the line. By default \{{nf-line}} will look for properties "x" and "y" on each element in the data array.

    Component JavaScript

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    
    import Ember from 'ember';
    import { dataGenerator } from '../services/data-generator';
    
    export default Ember.Component.extend({
    
      graphData: function() {
        return dataGenerator.simpleTimeSeries();
      }.property()
    
    });
    ================================================ FILE: tests/dummy/app/templates/components/brush-select-zoom.hbs ================================================ {{#nf-graph yMaxMode="push-tick" brushEndAction="brushEnd" as |nf|}} {{#nf.graph as |graph|}} {{graph.line data=zoomData interpolator="monotone"}} {{graph.brush-selection right=selectRight left=selectLeft formatter=selectionDisplayFormatter}} {{/nf.graph}} {{/nf-graph}}

    Template

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    
    {{#nf-graph
        yMaxMode="push-tick"
        brushEndAction="brushEnd"}}
    
        {{#nf-graph-content}}
    
        {{nf-line data=zoomData interpolator="monotone"}}
        {{nf-brush-selection right=selectRight left=selectLeft formatter=selectionDisplayFormatter}}
    
        {{/nf-graph-content}}
    
        {{/nf-graph}}
      
    13
    14
    
    
    <button \{{action "reset"}}>Reset Zoom</button>
    

    Brush selection allows a segment of the graph's plot area to be selected by click-and-drag with the mouse. It is up to the developer to decide what to do with the selection results. This example shows how to use the selection results to zoom in.

    yMaxMode="push-tick" causes the Y Axis to auto-resize to the next larger tick value when necessary as graph data changes. In this example graph data will change by filtering the data). nf-graph will redraw any line plots when data changes. "push-tick" also prevents the axis from shrinking which is what we want while zooming to prevent the user from being disoriented by drastically changing axis ranges while zooming.

    brushEndAction specifies what action to execute on the component when the brush gesture ends.

    \{{nf-brush-selection}} captures mouse click-and-drag and emits the graph positions as actions. It also draws selection markers on the graph plot area. Properties right and left are bound to component properties used to filter the data.

    In this example mouse click-and-drag causes the brush enbd action to be fired. When the brush action ends JavaScript code updates data filter properties so that the graph displays only data within the new zoom extents. Clicking the reset button resets the filter properties to include all data (unfiltered or zoomed).

    Component JavaScript

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    
    import Ember from 'ember';
    import { dataGenerator } from '../services/data-generator';
    import { format } from '../helpers/format-hour-minute';
    
    export default Ember.Component.extend({
    
      // Start and end dates for filtering the graph data.
      // These are the initial values and will change when brush actions
      // are executed below
      startTime: 0,
      endTime: Number.MAX_VALUE,
    
    
      // Domain values for right and left brush markers. These are modified
      // when the user drags with the mouse.
      selectLeft: undefined,
      selectRight: undefined,
    
    
      // Original graph data (no zoom or filter)
      graphData: function() {
        return dataGenerator.simpleTimeSeries();
      }.property(),
    
    
      // Graph data filtered by zoom extents. Filtered to include only data points
      // falling within the zoom start and end dates
      zoomData: function() {
        var self = this;
    
        return this.get('graphData').filter(function(d) {
          return d.x >= self.get('startTime') && d.x <= self.get('endTime');
        });
      }.property('graphData', 'startTime', 'endTime'),
    
    
      // Formats the text shown on the brush selection markers.
      // This is using the format code imported from helper:format-hour-minute
      selectionDisplayFormatter: function(ms) {
        return format(ms);
      },
    
    
      actions: {
    
        brushEnd: function(e) {
          // Now that the brush drag is finished set new
          // zoom values for filtering the main graph data
          this.set('startTime', Ember.get(e, 'left.x'));
          this.set('endTime', Ember.get(e, 'right.x'));
    
        },
    
        reset: function() {
          // Reset teh zoom extents
          this.set("startTime", 0);
          this.set("endTime", Number.MAX_VALUE);
        }
      },
    
    });
    ================================================ FILE: tests/dummy/app/templates/components/detailed-line-graph.hbs ================================================ {{#nf-graph width=400 height=150 showLanes=true showFrets=true paddingTop=10 paddingRight=10 as |nf|}} {{#nf.x-axis tickCount=5 as |tick|}} {{format-hour-minute tick.value}} {{/nf.x-axis}} {{#nf.y-axis as |tick|}} {{tick.value}} {{/nf.y-axis}} {{#nf.graph as |graph|}} {{graph.line data=graphData xprop="x" yprop="y" interpolator="monotone"}} {{/nf.graph}} {{/nf-graph}}

    Template

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    
    {{#nf-graph
        width=400
        height=150
        showLanes=true
        showFrets=true
        paddingTop=10
        paddingRight=10}}
    
      {{#nf-x-axis tickCount=5}}
        <text>{{format-hour-minute tick.value}}</text>
      {{/nf-x-axis}}
    
      {{#nf-y-axis}}
        <text>{{tick.value}}</text>
      {{/nf-y-axis}}
    
      {{#nf-graph-content}}
        {{nf-line
            data=graphData
            xprop="x"
            yprop="y"
            interpolator="monotone"}}
      {{/nf-graph-content}}
    
    {{/nf-graph}}

    width=400 and height=150 define the pixel size of the entire graph including axis and padding. showLanes=true causes horizontal swim lanes to be shaded in the background. showFrets=true causes vertical lines to be draw in the background for each tick on the X Axis. paddingRight and paddingType define padding space between the graph plot area and the absolute border of the entire graph.

    \{{#nf-x-axis}} draws the X Axis. tickCount=5 will produce approximately 5 evenly spaced "nice" ticks on the axis (the actual count may be one more or less depending where "nice" ticks fall on the axis). {{format-hour-minute tick.value}} is the X Axis tick template and defines the text that appears on each tick. tick.value is the domain value of each tick.

    \{{#nf-y-axis}} draws the Y Axis and has a text template similar to nf-x-axis above.

    \{{#nf-graph-content}} is the container for elements that should be drawn within the graph plot area.

    \{{#nf-line}} draws a line plot. data=graphData specifies to get this line's data from the component's graphData property. xprop defines which property represents the x value on each data element. yprop defines which property represents the y value on each data element. interpolator="monotone" specifies drawing the line with a smooth curve. Other interpolator values can be found here.

    Component JavaScript

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    
    import Ember from 'ember';
    import { dataGenerator } from '../services/data-generator';
    
    export default Ember.Component.extend({
    
      graphData: function() {
        return dataGenerator.simpleTimeSeries();
      }.property()
    
    });
    ================================================ FILE: tests/dummy/app/templates/components/graph-primitives.hbs ================================================ {{#nf-graph as |nf|}} {{#nf.graph as |graph|}} {{graph.line data=graphData}} {{#each graphData as |item|}} {{graph.svg-image src="images/star.svg" x=item.x y=item.y svgWidth=20 svgHeight=20}} {{/each}} {{/nf.graph}} {{/nf-graph}} ================================================ FILE: tests/dummy/app/templates/components/mouse-tracking-data.hbs ================================================ {{#nf-graph selected=selectedLine width=400 height=150 showFrets=true paddingTop=10 paddingRight=10 as |nf|}} {{#nf.x-axis tickCount=5 as |tick|}} {{format-hour-minute tick.value}} {{/nf.x-axis}} {{#nf.y-axis as |tick|}} {{tick.value}} {{/nf.y-axis}} {{#nf.graph as |graph|}} {{graph.vertical-line x=selectedLine.hoverData.x}} {{graph.horizontal-line y=selectedLine.hoverData.y}} {{graph.line data=graphData xprop="date" yprop="low" trackingMode="snap-last" selectable=true interpolator="monotone"}} {{graph.line data=graphData xprop="date" yprop="medium" trackingMode="snap-last" selectable=true selected=true interpolator="monotone"}} {{graph.line data=graphData xprop="date" yprop="high" trackingMode="snap-last" selectable=true interpolator="monotone"}} {{/nf.graph}} {{/nf-graph}}
    Selected Time: {{format-hour-minute selectedLine.hoverData.x}} Value: {{selectedLine.hoverData.y}}

    Template

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    
    {{#nf-graph
        selected=selectedLine
        width=400
        height=150
        showFrets=true
        paddingTop=10
        paddingRight=10}}
    
      {{#nf-x-axis tickCount=5}}
        <text>{{format-hour-minute tick.value}}</text>
      {{/nf-x-axis}}
    
      {{#nf-y-axis}}
        <text>{{tick.value}}</text>
      {{/nf-y-axis}}
    
    
      {{#nf-graph-content}}
        {{nf-vertical-line x=selectedLine.hoverData.x}}
        {{nf-horizontal-line y=selectedLine.hoverData.y}}
    
        {{nf-line data=graphData xprop="date" yprop="low" trackingMode="snap-last" selectable=true interpolator="monotone"}}
        {{nf-line data=graphData xprop="date" yprop="medium" trackingMode="snap-last" selectable=true selected=true interpolator="monotone"}}
        {{nf-line data=graphData xprop="date" yprop="high" trackingMode="snap-last" selectable=true interpolator="monotone"}}
      {{/nf-graph-content}}
    
    {{/nf-graph}}
    28
    29
    30
    
    <div>
      <span>Selected Time: \{{format-hour-minute selectedLine.hoverData.x}}</span><span> Value: \{{selectedLine.hoverData.y}}</span>
    </div>

    \{{#nf-graph}} is the main graph container. nf-graph has built-in element selection by clicking or setting a property. selected=selectedLine causes property "selectedLine" to be set to the current selected element. width= and height= set the absolute pixel size of the entire graph, including axis and padding. showFrets= causes each tick on the X Axis to display a vertical line in the background. paddingTop and paddingRight define padding size between the plot area and the absolute border of the entire graph.

    \{{#nf-x-axis}} draws the X Axis. tickCount=5 will produce approximately 5 evenly spaced "nice" ticks on the axis (the actual count may be one more or less depending where "nice" ticks fall on the axis). {{format-hour-minute tick.value}} is the X Axis tick template and defines the text that appears on each tick. tick.value is the domain value of each tick.

    \{{#nf-y-axis}} draws the Y Axis and has a text template similar to nf-x-axis above.

    nf-graph child elements have built in mouse tracking features. Also child elements support being selected by clicking, or by setting a property. Lines and areas provide a "hoverData" property which contains data about the data point nearest to the mouse pointer. By using the "hoverData" of the "selected" element other graph elements can react to mouse tracking on the selected element.

    \{{nf-vertical-line}} draws a vertical line in the graph plot area which is being used along with nf-horizontal-line to draw a mouse crosshair. x=selectedLine.hoverData.x causes the horizontal position of the line to be dependent of the the selected line's hoverData.x value. Therefore mouse tracking will causes the vertical line to follow the mouse pointer and snap to the nearest data point on the selected line.

    {{nf-horizontal-line}} draws a horizontal line in the graph plot area and behaves similar the nf-vertical-line above.

    interpolator="monotone" specifies drawing the area with a smooth curve. Other interpolator values can be found here.

    Display the mouse-tracked values within a div: \{{format-hour-minute selectedLine.hoverData.x}} displays the x value nearest to the mouse pointer on the current selected line. Because of data binding this value will change as the mouse pointer moves around. format-hour-minute is an Ember helper defined in this example project.

    Component JavaScript

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    
    import Ember from 'ember';
    import { dataGenerator } from '../services/data-generator';
    
    export default Ember.Component.extend({
    
      graphData: function() {
        return dataGenerator.threeMetricTimeSeries();
      }.property()
    
    });
    ================================================ FILE: tests/dummy/app/templates/components/mouse-tracking.hbs ================================================ {{#nf-graph selected=selectedLine as |nf|}} {{#nf.graph as |graph|}} {{graph.vertical-line x=selectedLine.hoverData.x}} {{graph.horizontal-line y=selectedLine.hoverData.y}} {{graph.line data=graphData xprop="date" yprop="low" trackingMode="hover" selectable=true interpolator="monotone"}} {{graph.line data=graphData xprop="date" yprop="medium" trackingMode="hover" selectable=true selected=true interpolator="monotone"}} {{graph.line data=graphData xprop="date" yprop="high" trackingMode="hover" selectable=true interpolator="monotone"}} {{/nf.graph}} {{/nf-graph}}

    Template

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    {{#nf-graph selected=selectedLine}}
    
      {{#nf-graph-content}}
    
        {{nf-vertical-line x=selectedLine.hoverData.x}}
        {{nf-horizontal-line y=selectedLine.hoverData.y}}
    
        {{nf-line data=graphData xprop="date" yprop="low" trackingMode="hover" selectable=true interpolator="monotone"}}
        {{nf-line data=graphData xprop="date" yprop="medium" trackingMode="hover" selectable=true selected=true interpolator="monotone"}}
        {{nf-line data=graphData xprop="date" yprop="high" trackingMode="hover" selectable=true interpolator="monotone"}}
    
       {{/nf-graph-content}}
    {{/nf-graph}}

    \{{#nf-graph}} is the main graph container. nf-graph has built-in element selection by clicking or setting a property. selected=selectedLine causes property "selectedLine" to be set to the current selected element.

    nf-graph child elements have built in mouse tracking features. Also child elements support being selected by clicking, or by setting a property. Lines and areas provide a "hoverData" property which contains data about the data point nearest to the mouse pointer. By using the "hoverData" of the "selected" element other graph elements can react to mouse tracking on the selected element.

    The hoverData property of each graph element is an Ember property that can be data-bound as the source for properties on nearby graph elements, other Ember components, or other HTML attibutes for a wide range of effects.

    trackingMode="hover" specifies the behavior of nearest data point. "hover" mean populate hoverData with an object only while the mouse is hovering. Otherwise return null. Other values are "snap-first" and "snap-last" which cause hoverData to represent the first or last data point on the element when the mouse is NOT hovering.

    \{{nf-vertical-line}} draws a vertical line in the graph plot area which is being used along with nf-horizontal-line to draw a mouse crosshair. x=selectedLine.hoverData.x causes the horizontal position of the line to be dependent of the the selected line's hoverData.x value. Therefore mouse tracking will causes the vertical line to follow the mouse pointer and snap to the nearest data point on the selected line.

    {{nf-horizontal-line}} draws a horizontal line in the graph plot area and behaves similar the nf-vertical-line above.

    interpolator="monotone" specifies drawing the area with a smooth curve. Other interpolator values can be found here.

    Component JavaScript

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    
    import Ember from 'ember';
    import { dataGenerator } from '../services/data-generator';
    
    export default Ember.Component.extend({
    
      graphData: function() {
        return dataGenerator.threeMetricTimeSeries();
      }.property()
    
    });
    
    ================================================ FILE: tests/dummy/app/templates/components/stacked-area-graph.hbs ================================================ {{#nf-graph yMinMode="fixed" yMin=0 as |nf|}} {{#nf.graph as |graph|}} {{#graph.area-stack}} {{graph.area data=graphData xprop="date" yprop="high" class="high" interpolator="monotone"}} {{graph.area data=graphData xprop="date" yprop="medium" class="medium" interpolator="monotone"}} {{graph.area data=graphData xprop="date" yprop="low" class="low" interpolator="monotone"}} {{/graph.area-stack}} {{/nf.graph}} {{/nf-graph}}

    Template

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    {{#nf-graph
        yMinMode="fixed"
        yMin=0}}
    
      {{#nf-graph-content}}
    
        {{#nf-area-stack}}
          {{nf-area data=graphData xprop="date" yprop="high" class="high" interpolator="monotone"}}
          {{nf-area data=graphData xprop="date" yprop="medium" class="medium" interpolator="monotone"}}
          {{nf-area data=graphData xprop="date" yprop="low" class="low" interpolator="monotone"}}
        {{/nf-area-stack}}
    
      {{/nf-graph-content}}
    {{/nf-graph}}

    \{{#nf-area-stack}} groups several nf-area elements into a "stack" so that areas are visually contoured to fit together. Each area will appear as a band of color that can be styled. The data array should defind the y value for the top curve of each area, but the bottom curve will be set aumatically by using the adjacent nf-area. Adjacent areas are determined by the order that nf-area elements are listed in the template.

    yprop specifies which property on each data element represents the y value for the area.

    class can be defined to apply a CSS class to the area.

    interpolator="monotone" specifies drawing the area with a smooth curve. Other interpolator values can be found here.

    Component JavaScript

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    import Ember from 'ember';
    import { dataGenerator } from '../services/data-generator';
    
    export default Ember.Component.extend({
    
      graphData: function() {
        return dataGenerator.threeMetricTimeSeries();
      }.property()
    
    });
    ================================================ FILE: tests/dummy/app/templates/examples.hbs ================================================

    ember-cli-nf-graph examples

    Resources

    Contents

    Basic Line Graph

    {{basic-line-graph}}

    Basic Area Graph

    {{basic-area-graph}}

    Basic Bar Graph

    {{basic-bar-graph}}

    Detailed Line Graph

    {{detailed-line-graph}}

    Stacked Area Graph

    {{stacked-area-graph}}

    Mouse Tracking

    {{mouse-tracking}}

    Mouse Tracking Data

    {{mouse-tracking-data}}

    Brush Select to Zoom

    {{brush-select-zoom}}

    Bar Graph with Line

    {{bars-with-line}}

    Graph Primitives

    {{graph-primitives}}
    ================================================ FILE: tests/dummy/app/templates/nf-graph/index.hbs ================================================

    Graph - Basics

    {{graphWidth}}px
    {{graphHeight}}px
    {{diffA}}
    {{diffB}}
    {{multiY}}


    {{graphWidth}}px X {{graphHeight}}px {{#nf-graph yMaxMode="push-tick" xLink=groupX selectMultiple=true brushStartAction=(action "brushStart") brushAction=(action "brush") brushEndAction=(action "brushEnd") width=graphWidth height=graphHeight showFrets=true showLanes=true paddingTop=50 paddingLeft=20 as |nf|}} {{#nf.graph as |graph|}} {{#graph.area-stack aggregate=1 as |stack|}} {{stack.area class="area3" interpolator="linear" data=model.area3 trackingMode="snap-last"}} {{stack.area class="area2" interpolator="linear" data=model.area2 trackingMode="snap-last" trackedData=(mut tracked2)}} {{stack.area class="area1" interpolator="linear" data=model.area1 trackingMode="snap-last"}} {{/graph.area-stack}} {{#graph.group scaleZoomX="2" scaleZoomY="2" as |group|}} {{group.line data=lineData class="line1" trackingMode="snap-last"}} {{/graph.group}} {{graph.brush-selection left=(mut brushLeft) right=(mut brushRight)}} {{graph.crosshairs}} {{/nf.graph}} {{#nf.x-axis as |tick|}} {{tick.value}} {{/nf.x-axis}} {{#nf.y-axis orient="right" as |tick|}} {{tick.value}} {{/nf.y-axis}} {{/nf-graph}}
    Tracked Data {{tracked2.y}} {{tracked2.renderY}}
    ================================================ FILE: tests/dummy/app/templates/nf-graph/nf-bars.hbs ================================================ {{#nf-graph width=500 height=300 paddingRight=10 paddingTop=10 xScaleType="ordinal" yMinMode="fixed" yMin=0 showLanes=true showFrets=true as |nf| }} {{#nf.graph as |graph|}} {{graph.bars data=model.menuItemStockCount trackingMode="snap-last" trackedData=tracked}} {{/nf.graph}} {{#nf.y-axis as |tick|}} {{tick.value}} {{/nf.y-axis}} {{#nf.x-axis as |tick|}} {{tick.value}} {{/nf.x-axis}} {{/nf-graph}} {{tracked.x}} {{tracked.y}} ================================================ FILE: tests/dummy/config/environment.js ================================================ 'use strict'; module.exports = function(environment) { let ENV = { modulePrefix: 'dummy', environment, rootURL: '/', locationType: 'auto', EmberENV: { FEATURES: { // Here you can enable experimental features on an ember canary build // e.g. 'with-controller': true }, EXTEND_PROTOTYPES: { // Prevent Ember Data from overriding Date.parse. Date: false } }, APP: { // Here you can pass flags/options to your application instance // when it is created } }; if (environment === 'development') { // ENV.APP.LOG_RESOLVER = true; // ENV.APP.LOG_ACTIVE_GENERATION = true; // ENV.APP.LOG_TRANSITIONS = true; // ENV.APP.LOG_TRANSITIONS_INTERNAL = true; // ENV.APP.LOG_VIEW_LOOKUPS = true; } if (environment === 'test') { // Testem prefers this... ENV.locationType = 'none'; // keep test console output quieter ENV.APP.LOG_ACTIVE_GENERATION = false; ENV.APP.LOG_VIEW_LOOKUPS = false; ENV.APP.rootElement = '#ember-testing'; ENV.APP.autoboot = false; } if (environment === 'production') { // here you can enable a production-specific feature } return ENV; }; ================================================ FILE: tests/dummy/config/targets.js ================================================ module.exports = { browsers: [ 'ie 9', 'last 1 Chrome versions', 'last 1 Firefox versions', 'last 1 Safari versions' ] }; ================================================ FILE: tests/dummy/public/.gitkeep ================================================ ================================================ FILE: tests/dummy/public/robots.txt ================================================ # http://www.robotstxt.org User-agent: * Disallow: ================================================ FILE: tests/helpers/destroy-app.js ================================================ import { run } from '@ember/runloop'; export default function destroyApp(application) { run(application, 'destroy'); } ================================================ FILE: tests/helpers/module-for-acceptance.js ================================================ import { module } from 'qunit'; import { resolve } from 'rsvp'; import startApp from '../helpers/start-app'; import destroyApp from '../helpers/destroy-app'; export default function(name, options = {}) { module(name, { beforeEach() { this.application = startApp(); if (options.beforeEach) { return options.beforeEach.apply(this, arguments); } }, afterEach() { let afterEach = options.afterEach && options.afterEach.apply(this, arguments); return resolve(afterEach).then(() => destroyApp(this.application)); } }); } ================================================ FILE: tests/helpers/start-app.js ================================================ import Application from '../../app'; import config from '../../config/environment'; import { merge } from '@ember/polyfills'; import { run } from '@ember/runloop'; export default function startApp(attrs) { let attributes = merge({}, config.APP); attributes.autoboot = true; attributes = merge(attributes, attrs); // use defaults, but you can override; return run(() => { let application = Application.create(attributes); application.setupForTesting(); application.injectTestHelpers(); return application; }); } ================================================ FILE: tests/index.html ================================================ Dummy Tests {{content-for "head"}} {{content-for "test-head"}} {{content-for "head-footer"}} {{content-for "test-head-footer"}} {{content-for "body"}} {{content-for "test-body"}} {{content-for "body-footer"}} {{content-for "test-body-footer"}} ================================================ FILE: tests/perf/first.spec.js ================================================ var benchpress = require('benchpress'); var runner = new benchpress.Runner([ //use protractor as Webdriver client benchpress.SeleniumWebDriverAdapter.PROTRACTOR_BINDINGS, //use RegressionSlopeValidator to validate samples benchpress.Validator.bindTo(benchpress.RegressionSlopeValidator), //use 10 samples to calculate slope regression // benchpress.bind(benchpress.RegressionSlopeValidator.SAMPLE_SIZE).toValue(20), //use the script metric to calculate slope regression benchpress.bind(benchpress.RegressionSlopeValidator.METRIC).toValue('scriptTime'), benchpress.bind(benchpress.Options.FORCE_GC).toValue(true) ]); describe('deep tree baseline', function() { it('should be fast!', function(done) { //Tells protractor this isn't an Angular 1 application browser.ignoreSynchronization = true; //Load the benchmark, with a tree depth of 9 browser.get('http://localhost:4200/nf-graph?graphWidth=900').then(function(){ // browser.get('http://localhost:8080/tree.html?depth='+depth); /* * Tell benchpress to click the buttons to destroy and re-create the tree for each sample. * Benchpress will log the collected metrics after each sample is collected, and will stop * sampling as soon as the calculated regression slope for last 20 samples is stable. */ runner.sample({ params: { name: 'graphWidth', value: 900, scale: 'sqrt' }, id: 'deep-tree', execute: function() { /* * Will call querySelector in the browser, but benchpress is smart enough to ignore injected * script. */ $('#loadNewData').click(); }, bindings: [ // benchpress.bind(benchpress.Options.SAMPLE_DESCRIPTION).toValue({ // depth: depth // }) ] }).then(done, done.fail); }); }); }); ================================================ FILE: tests/test-helper.js ================================================ import Application from '../app'; import config from '../config/environment'; import { setApplication } from '@ember/test-helpers'; import { start } from 'ember-qunit'; setApplication(Application.create(config.APP)); start(); ================================================ FILE: tests/unit/.gitkeep ================================================ ================================================ FILE: tests/unit/addon/mixins/graph-data-graphic-test.js ================================================ import EmberObject from '@ember/object'; import { run } from '@ember/runloop'; import Evented from '@ember/object/evented'; import GraphDataGraphic from 'ember-nf-graph/mixins/graph-data-graphic'; import { module, test } from 'qunit'; module('addon/mixins/graph-data-graphic'); test('renderedData should narrow sortedData down to only what is between xMin and xMax if non-ordinal xScaleType, PLUS one point to either side', assert => { var Foo = EmberObject.extend(GraphDataGraphic, Evented); run(() => { var foo = Foo.create({ mappedData: [[1,1], [75, 2], [100, 3], [101, 4], [150, 5], [199, 6], [200, 7], [225, 8], [300, 9]], graph: EmberObject.create({ xScaleType: 'linear', xMin: 100, xMax: 200 }) }); var renderedData = foo.get('renderedData'); assert.deepEqual(renderedData, [[75, 2], [100, 3], [101, 4], [150, 5], [199, 6], [200, 7], [225, 8]]); }); }); test('renderedData should return the whole sortedData array if xScaleType is "ordinal"', assert => { var Foo = EmberObject.extend(GraphDataGraphic, Evented); run(() => { var foo = Foo.create({ mappedData: [[1,1], [75, 2], [100, 3], [101, 4], [150, 5], [199, 6], [200, 7], [225, 8], [300, 9]], graph: EmberObject.create({ xScaleType: 'ordinal', xMin: 100, xMax: 200 }) }); var renderedData = foo.get('renderedData'); assert.deepEqual(renderedData, [[1,1], [75, 2], [100, 3], [101, 4], [150, 5], [199, 6], [200, 7], [225, 8], [300, 9]]); }); }); test('firstVisibleData returns the first item of renderedData that is actually visible if renderedData includes a value off-graph', assert => { var Foo = EmberObject.extend(GraphDataGraphic, Evented); var first = [2,2]; first.data = [111, 222]; run(() => { var foo = Foo.create({ renderedData: [[1,1],first,[3,3],[4,4],[5,5]], xMin: 1.4, yPropFn: x => x[1], xPropFn: x => x[0] }); var firstVisibleData = foo.get('firstVisibleData'); assert.deepEqual(firstVisibleData, { x: 111, y: 222, data: first.data, renderX: 2, renderY: 2 }); }); }); test('firstVisibleData returns the first item of renderedData if it is at the xMin exactly', assert => { var Foo = EmberObject.extend(GraphDataGraphic, Evented); run(() => { var first = [1,1]; first.data = [111,222]; var foo = Foo.create({ renderedData: [first,[2,2],[3,3],[4,4],[5,5]], xMin: 1, yPropFn: x => x[1], xPropFn: x => x[0] }); var firstVisibleData = foo.get('firstVisibleData'); assert.deepEqual(firstVisibleData, { x: 111, y: 222, data: first.data, renderX: 1, renderY: 1 }); }); }); test('lastVisibleData returns the last item of renderedData that is actually visible if renderedData includes a value off-graph', assert => { var Foo = EmberObject.extend(GraphDataGraphic, Evented); var last = [4,4]; last.data = [111,222]; run(() => { var foo = Foo.create({ renderedData: [[1,1],[2,2],[3,3],last,[5,5]], xMax: 4.4, yPropFn: x => x[1], xPropFn: x => x[0] }); var lastVisibleData = foo.get('lastVisibleData'); assert.deepEqual(lastVisibleData, { x: 111, y: 222, data: last.data, renderX: 4, renderY: 4 }); }); }); test('lastVisibleData returns the last item of renderedData if it is at the xMax exactly', assert => { var Foo = EmberObject.extend(GraphDataGraphic, Evented); var last = [5,5]; last.data = [111,222]; run(() => { var foo = Foo.create({ renderedData: [[1,1],[2,2],[3,3],[4,4],last], xMax: 5, yPropFn: x => x[1], xPropFn: x => x[0] }); var lastVisibleData = foo.get('lastVisibleData'); assert.deepEqual(lastVisibleData, { x: 111, y: 222, data: last.data, renderX: 5, renderY: 5 }); }); }); test('getDataNearX() should return the data point closest to the x domain value passed', assert => { var Foo = EmberObject.extend(GraphDataGraphic, Evented); run(() => { var foo = Foo.create({ renderedData: [[1,1],[2,2],[3,3],[4,4],[5,5]] }); var data = foo.getDataNearX(3.6); assert.deepEqual(data, [4,4]); var data2 = foo.getDataNearX(3.3); assert.deepEqual(data2, [3,3]); }); }); test('xPropFn should be a function that gets the value specified by xprop', assert => { var Foo = EmberObject.extend(GraphDataGraphic, Evented); run(() => { var foo = Foo.create({ xprop: 'foo.bar' }); var fn = foo.get('xPropFn'); assert.equal(fn({ foo: { bar: 'wokka wokka' } }), 'wokka wokka'); }); }); test('xPropFn should work if xprop uses an array index like so: foo[2]', assert => { var Foo = EmberObject.extend(GraphDataGraphic, Evented); run(() => { var foo = Foo.create({ xprop: 'foo[2]' }); var fn = foo.get('xPropFn'); assert.equal(fn({ foo: ['apple', 'orange', 'banana'] }), 'banana'); }); }); test('yPropFn should be a function that gets the value specified by yprop', assert => { var Foo = EmberObject.extend(GraphDataGraphic, Evented); run(() => { var foo = Foo.create({ yprop: 'foo.bar' }); var fn = foo.get('yPropFn'); assert.equal(fn({ foo: { bar: 'wokka wokka' } }), 'wokka wokka'); }); }); test('yPropFn should work if yprop uses an array index like so: foo[2]', assert => { var Foo = EmberObject.extend(GraphDataGraphic, Evented); run(() => { var foo = Foo.create({ yprop: 'foo[2]' }); var fn = foo.get('yPropFn'); assert.equal(fn({ foo: ['apple', 'orange', 'banana'] }), 'banana'); }); }); ================================================ FILE: tests/unit/app/components/nf-bars-test.js ================================================ import { run } from '@ember/runloop'; import { moduleForComponent, test } from 'ember-qunit'; moduleForComponent('nf-bars', { // specify the other units that are required for this test needs: ['component:nf-graph', 'component:nf-graph-content'] }); test('bars layout', function(assert) { var bars; run(() => { var nfBars = this.subject({ xScale: x => { switch(x) { case 'a': return 0; case 'b': return 10; case 'c': return 20; } }, yScale: x => x, renderedData: [ ['a', 10], ['b', 5], ['c', 1] ], graphHeight: 10, getBarClass: () => 'testClass', barWidth: 10, groupOffsetX: 30, _getRectPath: (...args) => args }); bars = nfBars.get('bars'); }); assert.deepEqual(bars, [{ path: [30, 10, 10, 0], className: 'nf-bars-bar testClass', data: ['a',10] }, { path: [40, 5, 10, 5], className: 'nf-bars-bar testClass', data: ['b', 5] }, { path: [50, 1, 10, 9], className: 'nf-bars-bar testClass', data: ['c', 1] }]); }); ================================================ FILE: tests/unit/app/components/nf-graph-test.js ================================================ import { run } from '@ember/runloop'; import { moduleForComponent, test } from 'ember-qunit'; moduleForComponent('nf-graph', {}); ['push', 'auto', 'push-tick'].forEach((mode) => test('changing xDataExtent[0] with xMinMode = "' + mode + '" should trigger didAutoUpdateMinX()', function(assert) { assert.expect(1); var graph = this.subject({ xMinMode: mode, xMin: 0, xMax: 100, didAutoUpdateMinX() { assert.ok(true); } }); run(() => { graph.set('xDataExtent', [-1, 100]); graph.get('xMin'); }); }) ); test('changing xDataExtent[0] with xMinMode = "fixed" should NOT trigger didAutoUpdateMinX()', function(assert) { assert.expect(0); var graph = this.subject({ xMinMode: 'fixed', xMin: 0, xMax: 100, didAutoUpdateMinX() { assert.ok(false); } }); run(() => { graph.set('xDataExtent', [-1, 100]); graph.get('xMin'); }); }); ['push', 'auto', 'push-tick'].forEach((mode) => test('changing xDataExtent[0] with xMaxMode = "' + mode + '" should trigger didAutoUpdateMaxX()', function(assert) { assert.expect(1); var graph = this.subject({ xMaxMode: mode, xMin: 0, xMax: 100, didAutoUpdateMaxX() { assert.ok(true); } }); run(() => { graph.set('xDataExtent', [0, 101]); graph.get('xMax'); }); }) ); test('changing xDataExtent[0] with xMaxMode = "fixed" should trigger NOT didAutoUpdateMaxX()', function(assert) { assert.expect(0); var graph = this.subject({ xMaxMode: 'fixed', xMin: 0, xMax: 100, didAutoUpdateMaxX() { assert.ok(false); } }); run(() => { graph.set('xDataExtent', [0, 101]); graph.get('xMax'); }); }); test('calling didAutoUpdateMaxX() should send the graph instance over autoScaleXAction', function(assert){ assert.expect(1); var calledWith; var graph = this.subject({ xDataExtent: [1,2], sendAction() { calledWith = [].slice.call(arguments); } }); run(() => { graph.didAutoUpdateMaxX(); }); assert.deepEqual(calledWith, ['autoScaleXAction', graph]); }); test('calling didAutoUpdateMinX() should send the graph instance over autoScaleXAction', function(assert){ assert.expect(1); var calledWith; var graph = this.subject({ xDataExtent: [1,2], sendAction() { calledWith = [].slice.call(arguments); } }); run(() => { graph.didAutoUpdateMinX(); }); assert.deepEqual(calledWith, ['autoScaleXAction', graph]); }); //----- test('calling didAutoUpdateMinY() should send the graph instance over autoScaleYAction', function(assert){ assert.expect(1); var calledWith; var graph = this.subject({ yDataExtent: [1,2], sendAction() { calledWith = [].slice.call(arguments); } }); run(() => { graph.didAutoUpdateMinY(); }); assert.deepEqual(calledWith, ['autoScaleYAction', graph]); }); test('calling didAutoUpdateMaxY() should send yDataExtent over autoScaleYAction', function(assert){ assert.expect(1); var calledWith; var graph = this.subject({ yDataExtent: [1,2], sendAction() { calledWith = [].slice.call(arguments); } }); run(() => { graph.didAutoUpdateMaxY(); }); assert.deepEqual(calledWith, ['autoScaleYAction', graph]); }); ================================================ FILE: tests/unit/app/components/nf-horizontal-line-test.js ================================================ import { run } from '@ember/runloop'; import { moduleForComponent, test } from 'ember-qunit'; moduleForComponent('nf-horizontal-line', { // specify the other units that are required for this test // needs: ['component:foo', 'helper:bar'] }); test('it renders', function(assert) { assert.expect(2); // creates the component instance var component = this.subject(); assert.equal(component._state, 'preRender'); // renders the component to the page this.render(); assert.equal(component._state, 'inDOM'); }); test('lineY pins to zero', function(assert) { var component = this.subject(); run(() => { component.set('yScale', function() { return -99; }); component.set('y', 0); }); assert.equal(component.get('lineY'), 0); }); ================================================ FILE: tests/unit/app/components/nf-vertical-line-test.js ================================================ import { run } from '@ember/runloop'; import { moduleForComponent, test } from 'ember-qunit'; moduleForComponent('nf-vertical-line', { // specify the other units that are required for this test // needs: ['component:foo', 'helper:bar'] }); test('it renders', function(assert) { assert.expect(2); // creates the component instance var component = this.subject(); assert.equal(component._state, 'preRender'); // renders the component to the page this.render(); assert.equal(component._state, 'inDOM'); }); test('lineX pins to zero', function(assert) { var component = this.subject(); run(() => { component.set('xScale', function() { return -99; }); component.set('x', 0); }); assert.equal(component.get('lineX'), 0); }); ================================================ FILE: tests/unit/app/components/nf-x-axis-test.js ================================================ import { moduleForComponent, test } from 'ember-qunit'; import { run } from '@ember/runloop'; moduleForComponent('nf-x-axis', { unit: true, needs: ['component:nf-graph'], }); test('nf-x-axis tickData should call tickFactory if available', function(assert) { var args; run(() => { var axis = this.subject({ xScale: 'xScale', tickCount: 42, graph: { xScaleType: 'xScaleType', xData: [1,2,3,4,5] }, tickFactory() { args = [].slice.call(arguments); return 'expected result'; } }); var tickData = axis.get('tickData'); assert.equal(tickData, 'expected result'); assert.deepEqual(args, ['xScale', 42, [1,2,3,4,5], 'xScaleType']); }); }); ================================================ FILE: tests/unit/app/components/nf-y-axis-test.js ================================================ import { moduleForComponent, test } from 'ember-qunit'; import { run } from '@ember/runloop'; moduleForComponent('nf-y-axis', { unit: true, needs: ['component:nf-graph'] }); test('nf-y-axis tickData should call tickFactory if available', function(assert) { var args; run(() => { var axis = this.subject({ yScale: 'yScale', graph: { yScaleType: 'yScaleType', yData: [1,2,3,4,5] }, tickCount: 42, tickFactory() { args = [].slice.call(arguments); return 'expected result'; } }); var tickData = axis.get('tickData'); assert.equal(tickData, 'expected result'); assert.deepEqual(args, ['yScale', 42, [1,2,3,4,5], 'yScaleType']); }); }); ================================================ FILE: vendor/.gitkeep ================================================ ================================================ FILE: yuidoc.json ================================================ { "name": "ember-nf-graph", "description": "A DSL for creating graphs with Ember", "options": { "outdir": "./docs", "paths": ["addon/", "app/"] } }