├── src ├── tasks │ ├── transformations │ │ ├── layouts │ │ │ └── StarLayout.js │ │ ├── familyTransformations │ │ │ ├── FamilyBalanceItem.js │ │ │ ├── BaseTransformer.js │ │ │ └── UserDefinedPrimaryParents.js │ │ ├── selection │ │ │ ├── DummyCombinedNormalVisibilityItemsTask.js │ │ │ ├── HighlightItemTask.js │ │ │ ├── CursorItemTask.js │ │ │ ├── OrgCursorNeighboursTask.js │ │ │ └── SelectedItemsTask.js │ │ ├── CombinedContextsTask.js │ │ ├── PaletteManagerTask.js │ │ ├── OrgExtractNestedLayoutsTask.js │ │ ├── visualTreeBuilder │ │ │ ├── enums.js │ │ │ ├── NodeTypeSorter.js │ │ │ ├── NavigationalFamily.js │ │ │ └── NodeGroupSorter.js │ │ ├── UserDefinedNodesOrderTask.js │ │ ├── HideGrandParentsConnectorsTask.js │ │ └── LogicalFamilyTask.js │ ├── options │ │ ├── OptionsTask.js │ │ ├── LayoutOptionsTask.js │ │ ├── FamVisualTreeOptionTask.js │ │ ├── HideGrandParentsConnectorsOptionTask.js │ │ ├── OrientationOptionTask.js │ │ ├── selection │ │ │ ├── NeighboursSelectionModeOptionTask.js │ │ │ ├── CursorSelectionPathModeOptionTask.js │ │ │ ├── SelectedItemsOptionTask.js │ │ │ ├── CursorItemOptionTask.js │ │ │ └── HighlightItemOptionTask.js │ │ ├── ScaleOptionTask.js │ │ ├── NormalizeOptionTask.js │ │ ├── LevelTitlePlacementOptionTask.js │ │ ├── MinimumVisibleLevelsOptionTask.js │ │ ├── annotations │ │ │ ├── LabelAnnotationTemplateOptionTask.js │ │ │ └── LabelAnnotationPlacementOptionTask.js │ │ ├── LinePaletteOptionTask.js │ │ ├── FamItemsOptionTask.js │ │ ├── MinimizedItemsOptionTask.js │ │ └── ExtractNestedLayoutsOptionTask.js │ ├── templates │ │ ├── CombinedTemplateParamsTask.js │ │ ├── ButtonsTemplateTask.js │ │ ├── AnnotationLabelTemplateTask.js │ │ ├── CheckBoxTemplateTask.js │ │ ├── GroupTitleTemplateTask.js │ │ ├── EndPointTemplateTask.js │ │ ├── LabelAnnotationTemplateParamsTask.js │ │ └── ActiveItemsTask.js │ ├── layout │ │ ├── DummyCurrentControlSizeTask.js │ │ ├── CurrentScrollPositionTask.js │ │ ├── VerticalOffsetTask.js │ │ └── CreateTransformTask.js │ └── renders │ │ └── offsetResolver │ │ └── ConnectorAnnotationOffsetResolver.js ├── graphics │ ├── Layer.js │ ├── __image_snapshots__ │ │ ├── Graphics - Draw shape-snap.png │ │ ├── Graphics - Merge single rectangle-snap.png │ │ └── Graphics - Draw shape having island-snap.png │ ├── shapes │ │ ├── __image_snapshots__ │ │ │ ├── MergedRectangles-Window-snap.png │ │ │ ├── MergedRectangles-Window 2-snap.png │ │ │ └── MergedRectangles-Merge 5 rectangles-snap.png │ │ └── MergedRectangles.js │ ├── structs │ │ ├── Matrix.test.js │ │ ├── Interval.test.js │ │ ├── __image_snapshots__ │ │ │ ├── Polyline.getOffsetPolyine - Offset square 2-snap.png │ │ │ ├── Polyline.getOffsetPolyine - Offset square 3-snap.png │ │ │ ├── Polyline.getOffsetPolyine - Offset square-snap.png │ │ │ ├── Polyline.getOffsetPolyine - Offset cubic segment-snap.png │ │ │ ├── Polyline.getOffsetPolyine - Offset square angle-snap.png │ │ │ ├── Polyline.getOffsetPolyine - Offset quadratic segment-snap.png │ │ │ ├── Polyline.getOffsetPolyine - Simple vertical segment-snap.png │ │ │ └── Polyline.getOffsetPolyine - Offset quadratic segment 2-snap.png │ │ ├── DotSegment.js │ │ ├── Label.js │ │ ├── Matrix.js │ │ ├── LineSegment.js │ │ ├── Size.test.js │ │ ├── MoveSegment.js │ │ ├── PaletteItem.js │ │ └── Rect.test.js │ ├── Placeholder.js │ ├── createGraphics.js │ └── EnumValues.js ├── configs │ ├── FamConfig.test.js │ ├── OrgConfig.test.js │ ├── FamItemConfig.test.js │ ├── OrgItemConfig.test.js │ ├── TemplateConfig.test.js │ ├── PaletteItemConfig.test.js │ ├── LabelAnnotationConfig.test.js │ ├── ShapeAnnotationConfig.test.js │ ├── ConnectorAnnotationConfig.test.js │ ├── BackgroundAnnotationConfig.test.js │ ├── HighlightPathAnnotationConfig.test.js │ └── PaletteItemConfig.js ├── models │ ├── LevelVisibility.js │ ├── TreeLevelConnectorStackSize.js │ ├── TemplateParams.js │ ├── Template.js │ ├── EdgeItem.js │ ├── TreeItem.js │ ├── FamilyItem.js │ ├── EdgeItem.test.js │ ├── Slot.js │ └── TreeItemPosition.js ├── algorithms │ ├── __image_snapshots__ │ │ ├── FamilyAlignment-Cycle 2-snap.png │ │ ├── getMergedRectangles-Window-snap.png │ │ ├── FamilyAlignment-Fance layout-snap.png │ │ ├── FamilyAlignment-Wave layout-snap.png │ │ ├── SpatialIndex-BoundedRectangle-snap.png │ │ ├── SpatialIndex-TouchedRectangle-snap.png │ │ ├── getCrossingRectangles-Window-snap.png │ │ ├── getMergedRectangles-Dumbbell-snap.png │ │ ├── getMergedRectangles-Window 2-snap.png │ │ ├── FamilyAlignment-Large sandclock-snap.png │ │ ├── SpatialIndex-BoundingRectangle-snap.png │ │ ├── getCrossingRectangles-Dumbbell-snap.png │ │ ├── getCrossingRectangles-Window 2-snap.png │ │ ├── FamilyAlignment-Left spiral layout-snap.png │ │ ├── SpatialIndex-Matrix nesting test-snap.png │ │ ├── SpatialIndex-Multi-layer test case-snap.png │ │ ├── getCrossingRectangles-5 rectangles-snap.png │ │ ├── FamilyAlignment-Empty family layout-snap.png │ │ ├── FamilyAlignment-Right spiral layout-snap.png │ │ ├── FamilyAlignment-Skewed rombus layout-snap.png │ │ ├── FamilyAlignment-Internal orphan family-snap.png │ │ ├── FamilyAlignment-Side by side families-snap.png │ │ ├── QuadTree-NW to SE diagonal points test-snap.png │ │ ├── QuadTree-SW to NE diagonal points test-snap.png │ │ ├── QuadTree-W to E horizontal points test-snap.png │ │ ├── getCrossingRectangles-Single rectangle-snap.png │ │ ├── getCrossingRectangles-Vertical overlay-snap.png │ │ ├── getMinimumCrossingRows-Basic test case-snap.png │ │ ├── FamilyAlignment-Single node family layout-snap.png │ │ ├── getCrossingRectangles-Horizontal overlay-snap.png │ │ ├── getMergedRectangles-Merge 5 rectangles 2-snap.png │ │ ├── FamilyAlignment-Regular tree family layout-snap.png │ │ ├── FamilyAlignment-Skipped Members Test Layout-snap.png │ │ ├── FamilyAlignment-Small Rombus family layout-snap.png │ │ ├── getMergedRectangles-Merge E shape rectangles-snap.png │ │ ├── getMergedRectangles-Merge single rectangle-snap.png │ │ ├── getMinimumCrossingRows-Multi-layer test case-snap.png │ │ ├── FamilyAlignment-3 Cross Relations Test Layout-snap.png │ │ ├── FamilyAlignment-Small Sand clock family layout-snap.png │ │ ├── FamilyAlignment-Upside-down tree family layout-snap.png │ │ ├── getMergedRectangles-Merge E shape rectangles 2-snap.png │ │ ├── getMinimumCrossingRows-Nested block test case-snap.png │ │ ├── getCrossingRectangles-E shape rectangles on left-snap.png │ │ ├── getCrossingRectangles-E shape rectangles on right-snap.png │ │ ├── getCrossingRectangles-Two disconnected rectangles-snap.png │ │ ├── getCrossingRectangles-Two overlapping rectangles-snap.png │ │ ├── getCrossingRectangles-Two overlapping rectangles 2-snap.png │ │ ├── FamilyAlignment-2 Cross Relations Demo family layout-snap.png │ │ ├── FamilyAlignment-Family diagram large rombus alignment-snap.png │ │ ├── FamilyAlignment-Side by side and upside-down families-snap.png │ │ ├── getMergedRectangles-Merge two disconnected rectangles-snap.png │ │ ├── getMergedRectangles-Merge two overlapping rectangles 2-snap.png │ │ ├── getMergedRectangles-Merge two overlapping rectangles-snap.png │ │ ├── FamilyAlignment-Alignment of items having variable width-snap.png │ │ ├── SpatialIndex-Should not return non overlapping rectangle-snap.png │ │ ├── FamilyAlignment-Family unit overlaps node between children-snap.png │ │ ├── FamilyAlignment-Family unit overlaps node between parents-snap.png │ │ ├── getCrossingRectangles-Two aligned disconnected rectangles 2-snap.png │ │ ├── getCrossingRectangles-Two aligned disconnected rectangles-snap.png │ │ ├── getMergedRectangles-Merge two aligned disconnected rectangles-snap.png │ │ ├── getMergedRectangles-Merge two aligned disconnected rectangles 2-snap.png │ │ ├── FamilyAlignment-Family diagram horizontal alignment with multiple cycles-snap.png │ │ └── FamilyAlignment-Side by side 2 families where the left one starts one generation below-snap.png │ ├── getLiniarBreaks.test.js │ ├── binarySearch.test.js │ ├── getMinimumCrossingRows.js │ ├── LCA.js │ ├── LCA.test.js │ └── Family.loopNeighbours.test.js ├── templates │ ├── html │ │ ├── ButtonsTemplate.test.js │ │ ├── CheckBoxTemplate.test.js │ │ ├── AnnotationLabelTemplate.test.js │ │ ├── ItemTemplate.test.js │ │ ├── UserTemplate.test.js │ │ ├── CursorTemplate.test.js │ │ ├── HighlightTemplate.test.js │ │ ├── DotHighlightTemplate.test.js │ │ ├── CustomRenderTemplate.js │ │ ├── LabelAnnotationTemplate.js │ │ ├── ButtonsTemplate.js │ │ ├── HighlightTemplate.js │ │ ├── GroupTitleTemplate.test.js │ │ ├── CursorTemplate.js │ │ ├── AnnotationLabelTemplate.js │ │ ├── EndPointTemplate.js │ │ ├── LevelBackgroundTemplate.js │ │ ├── CheckBoxTemplate.js │ │ └── DotHighlightTemplate.js │ └── pdf │ │ ├── DummyTemplate.js │ │ ├── CustomRenderTemplate.js │ │ ├── EndPointTemplate.js │ │ ├── UserTemplate.js │ │ ├── CursorTemplate.js │ │ ├── HighlightTemplate.js │ │ ├── LabelAnnotationTemplate.js │ │ ├── AnnotationLabelTemplate.js │ │ └── GroupTitleTemplate.js ├── enums.test.js ├── common │ └── colors.test.js ├── readers │ ├── FunctionReader.js │ ├── EnumerationReader.js │ ├── ObjectReader.js │ └── ValueReader.js ├── getFamTasksDiagram.js ├── getOrgTasksDiagram.js ├── getFamPdfkitTasksDiagram.js ├── getOrgPdfkitTasksDiagram.js ├── managers │ ├── DependencyManager.js │ └── TaskManager.test.js ├── events │ ├── OrgEventArgs.js │ ├── FamEventArgs.js │ └── RenderEventArgs.js └── OrgEventArgsFactory.js ├── .gitignore ├── license.pdf ├── babel.config.js ├── samples ├── images │ ├── cbp88.png │ ├── photos │ │ ├── a.png │ │ ├── b.png │ │ ├── c.png │ │ ├── d.png │ │ ├── e.png │ │ ├── f.png │ │ ├── g.png │ │ ├── h.png │ │ ├── i.png │ │ ├── j.png │ │ ├── k.png │ │ ├── l.png │ │ ├── m.png │ │ ├── n.png │ │ ├── o.png │ │ ├── p.png │ │ ├── q.png │ │ ├── r.png │ │ ├── s.png │ │ ├── t.png │ │ ├── u.png │ │ ├── v.png │ │ ├── w.png │ │ ├── x.png │ │ ├── y.png │ │ └── z.png │ ├── cbp88bundled.png │ ├── shapes │ │ ├── circle.png │ │ ├── rhombus.png │ │ └── rectangle.png │ ├── cbp88everyparent.png │ └── sparse_data_problem.pdf ├── javascript.controls │ ├── __image_snapshots__ │ │ ├── CasePERTChart-snap.png │ │ ├── CaseShowFrame-snap.png │ │ ├── CaseButtonsPanel-snap.png │ │ ├── CaseItemTemplate-snap.png │ │ ├── CaseCursorTemplate-snap.png │ │ ├── CaseInactiveItems-snap.png │ │ ├── CaseSelectedItems-snap.png │ │ ├── CaseSkippedLevels-snap.png │ │ ├── CaseFirstFamilyChart-snap.png │ │ ├── CaseHighlightTemplate-snap.png │ │ ├── CaseItemTemplateLabel-snap.png │ │ ├── CaseLevelAnnotation-snap.png │ │ ├── CaseSelectionPathMode-snap.png │ │ ├── CaseShapeAnnotation-snap.png │ │ ├── CaseConnectorAnnotation-snap.png │ │ ├── CaseInactiveFamilyItems-snap.png │ │ ├── CaseLoopsInFamilyChart-snap.png │ │ ├── CaseSelectingCursorItem-snap.png │ │ ├── CaseAdviserPartnerItemType-snap.png │ │ ├── CaseChildrenPlacementType-snap.png │ │ ├── CaseCrossBranchAlignment-snap.png │ │ ├── CaseFamilyChartRelations-snap.png │ │ ├── CaseGeneralPartnerItemType-snap.png │ │ ├── CaseLimitedPartnerItemType-snap.png │ │ ├── CaseSelectingHighlightItem-snap.png │ │ ├── CaseSpousesInFamilyLayout-snap.png │ │ ├── CaseAddingLinkToItemTemplate-snap.png │ │ ├── CaseFamilyChartItemsOrdering-snap.png │ │ ├── CaseFamilyChartMatrixLayout-snap.png │ │ ├── CaseFamilyChartPrimaryParent-snap.png │ │ ├── CaseFirstOrganizationalChart-snap.png │ │ ├── CaseHighlightPathAnnotation-snap.png │ │ ├── CaseItemAndGroupTitleColors-snap.png │ │ ├── CaseLevelAnnotationTemplate-snap.png │ │ ├── CaseMultipleFamiliesOrdering-snap.png │ │ ├── CaseMultipleRootItemsInChart-snap.png │ │ ├── CaseLabelsCascadesInFamilyChart-snap.png │ │ ├── CaseLabelsNMatrixInFamilyChart-snap.png │ │ ├── CaseMatrixGroupsInFamilyChart-snap.png │ │ ├── CaseMatrixLayoutInFamilyChart-snap.png │ │ ├── CasePlaceAdvisersAboveChildren-snap.png │ │ ├── CaseAdviserAndAssistantItemTypes-snap.png │ │ ├── CasePlaceAssistantsAboveChildren-snap.png │ │ ├── CaseCustomLayoutWithInvisibleItems-snap.png │ │ ├── CaseFamilyChartGrandParentsRelations-snap.png │ │ ├── CaseSelectionCheckboxInItemTemplate-snap.png │ │ ├── CaseFamilyHideGrandParentsConnections-snap.png │ │ ├── CaseSubAdviserAndSubAssistantItemTypes-snap.png │ │ ├── CaseFamilyChartHiddenGrandParentsRelations-snap.png │ │ └── CaseMatrixLayoutOfMultipleRootItemsInChart-snap.png │ ├── common │ │ ├── PanelConfig.js │ │ ├── enums.js │ │ ├── index.js │ │ ├── Caption.js │ │ ├── tests.js │ │ ├── CheckBox.js │ │ └── TextBox.js │ ├── css │ │ └── styles.css │ ├── CaseFirstOrganizationalChart.html │ └── CaseMatrixLayoutOfMultipleRootItemsInChart.html ├── PopupDialog.md ├── LoopsInFamily.md ├── pdfkit.plugins │ └── index.js ├── Buttons.md ├── ZoomWithCSSScaleTransform.md ├── HighlightTemplate.md ├── ItemAndGroupTitleColors.md ├── CrossBranchAlignment.md ├── ItemTemplateLabel.md ├── MatrixLayoutInFamilyChart.md ├── InactiveItems.md ├── SelectionPathMode.md ├── ShapeAndBackgroundAnnotations.md ├── ZoomWithItemTemplate.md ├── InactiveFamilyItems.md ├── LabelsCascadesInFamilyChart.md ├── MultipleRootItemsInChart.md ├── ConnectorAnnotation.md └── LevelAnnotation.md ├── .dockerignore ├── css └── images │ ├── ui-bg_flat_10_000000_40x100.png │ ├── ui-bg_glass_100_f6f6f6_1x400.png │ ├── ui-bg_glass_100_fdf5ce_1x400.png │ ├── ui-bg_glass_65_ffffff_1x400.png │ ├── ui-bg_gloss-wave_35_f6a828_500x100.png │ ├── ui-bg_highlight-soft_100_eeeeee_1x100.png │ └── ui-bg_highlight-soft_75_ffe45c_1x100.png ├── .npmignore └── apireference.json /src/tasks/transformations/layouts/StarLayout.js: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | dist 3 | .vscode 4 | debug.log -------------------------------------------------------------------------------- /license.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BasicPrimitives/javascript/HEAD/license.pdf -------------------------------------------------------------------------------- /babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: [['@babel/preset-env', {targets: {node: 'current'}}]], 3 | }; -------------------------------------------------------------------------------- /samples/images/cbp88.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BasicPrimitives/javascript/HEAD/samples/images/cbp88.png -------------------------------------------------------------------------------- /samples/images/photos/a.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BasicPrimitives/javascript/HEAD/samples/images/photos/a.png -------------------------------------------------------------------------------- /samples/images/photos/b.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BasicPrimitives/javascript/HEAD/samples/images/photos/b.png -------------------------------------------------------------------------------- /samples/images/photos/c.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BasicPrimitives/javascript/HEAD/samples/images/photos/c.png -------------------------------------------------------------------------------- /samples/images/photos/d.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BasicPrimitives/javascript/HEAD/samples/images/photos/d.png -------------------------------------------------------------------------------- /samples/images/photos/e.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BasicPrimitives/javascript/HEAD/samples/images/photos/e.png -------------------------------------------------------------------------------- /samples/images/photos/f.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BasicPrimitives/javascript/HEAD/samples/images/photos/f.png -------------------------------------------------------------------------------- /samples/images/photos/g.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BasicPrimitives/javascript/HEAD/samples/images/photos/g.png -------------------------------------------------------------------------------- /samples/images/photos/h.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BasicPrimitives/javascript/HEAD/samples/images/photos/h.png -------------------------------------------------------------------------------- /samples/images/photos/i.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BasicPrimitives/javascript/HEAD/samples/images/photos/i.png -------------------------------------------------------------------------------- /samples/images/photos/j.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BasicPrimitives/javascript/HEAD/samples/images/photos/j.png -------------------------------------------------------------------------------- /samples/images/photos/k.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BasicPrimitives/javascript/HEAD/samples/images/photos/k.png -------------------------------------------------------------------------------- /samples/images/photos/l.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BasicPrimitives/javascript/HEAD/samples/images/photos/l.png -------------------------------------------------------------------------------- /samples/images/photos/m.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BasicPrimitives/javascript/HEAD/samples/images/photos/m.png -------------------------------------------------------------------------------- /samples/images/photos/n.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BasicPrimitives/javascript/HEAD/samples/images/photos/n.png -------------------------------------------------------------------------------- /samples/images/photos/o.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BasicPrimitives/javascript/HEAD/samples/images/photos/o.png -------------------------------------------------------------------------------- /samples/images/photos/p.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BasicPrimitives/javascript/HEAD/samples/images/photos/p.png -------------------------------------------------------------------------------- /samples/images/photos/q.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BasicPrimitives/javascript/HEAD/samples/images/photos/q.png -------------------------------------------------------------------------------- /samples/images/photos/r.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BasicPrimitives/javascript/HEAD/samples/images/photos/r.png -------------------------------------------------------------------------------- /samples/images/photos/s.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BasicPrimitives/javascript/HEAD/samples/images/photos/s.png -------------------------------------------------------------------------------- /samples/images/photos/t.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BasicPrimitives/javascript/HEAD/samples/images/photos/t.png -------------------------------------------------------------------------------- /samples/images/photos/u.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BasicPrimitives/javascript/HEAD/samples/images/photos/u.png -------------------------------------------------------------------------------- /samples/images/photos/v.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BasicPrimitives/javascript/HEAD/samples/images/photos/v.png -------------------------------------------------------------------------------- /samples/images/photos/w.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BasicPrimitives/javascript/HEAD/samples/images/photos/w.png -------------------------------------------------------------------------------- /samples/images/photos/x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BasicPrimitives/javascript/HEAD/samples/images/photos/x.png -------------------------------------------------------------------------------- /samples/images/photos/y.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BasicPrimitives/javascript/HEAD/samples/images/photos/y.png -------------------------------------------------------------------------------- /samples/images/photos/z.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BasicPrimitives/javascript/HEAD/samples/images/photos/z.png -------------------------------------------------------------------------------- /.dockerignore: -------------------------------------------------------------------------------- 1 | .git 2 | .vscode 3 | .npmignore 4 | .gitignore 5 | .dockerignore 6 | node_modules 7 | build 8 | yarn-error.log -------------------------------------------------------------------------------- /samples/images/cbp88bundled.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BasicPrimitives/javascript/HEAD/samples/images/cbp88bundled.png -------------------------------------------------------------------------------- /samples/images/shapes/circle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BasicPrimitives/javascript/HEAD/samples/images/shapes/circle.png -------------------------------------------------------------------------------- /samples/images/shapes/rhombus.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BasicPrimitives/javascript/HEAD/samples/images/shapes/rhombus.png -------------------------------------------------------------------------------- /samples/images/cbp88everyparent.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BasicPrimitives/javascript/HEAD/samples/images/cbp88everyparent.png -------------------------------------------------------------------------------- /samples/images/shapes/rectangle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BasicPrimitives/javascript/HEAD/samples/images/shapes/rectangle.png -------------------------------------------------------------------------------- /samples/images/sparse_data_problem.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BasicPrimitives/javascript/HEAD/samples/images/sparse_data_problem.pdf -------------------------------------------------------------------------------- /css/images/ui-bg_flat_10_000000_40x100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BasicPrimitives/javascript/HEAD/css/images/ui-bg_flat_10_000000_40x100.png -------------------------------------------------------------------------------- /css/images/ui-bg_glass_100_f6f6f6_1x400.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BasicPrimitives/javascript/HEAD/css/images/ui-bg_glass_100_f6f6f6_1x400.png -------------------------------------------------------------------------------- /css/images/ui-bg_glass_100_fdf5ce_1x400.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BasicPrimitives/javascript/HEAD/css/images/ui-bg_glass_100_fdf5ce_1x400.png -------------------------------------------------------------------------------- /css/images/ui-bg_glass_65_ffffff_1x400.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BasicPrimitives/javascript/HEAD/css/images/ui-bg_glass_65_ffffff_1x400.png -------------------------------------------------------------------------------- /src/graphics/Layer.js: -------------------------------------------------------------------------------- 1 | export default function Layer(name) { 2 | this.name = name; 3 | 4 | this.canvas = null; 5 | 6 | this.svgcanvas = null; 7 | }; -------------------------------------------------------------------------------- /css/images/ui-bg_gloss-wave_35_f6a828_500x100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BasicPrimitives/javascript/HEAD/css/images/ui-bg_gloss-wave_35_f6a828_500x100.png -------------------------------------------------------------------------------- /src/configs/FamConfig.test.js: -------------------------------------------------------------------------------- 1 | import FamConfig from './FamConfig'; 2 | 3 | test('FamConfig', () => { 4 | expect(new FamConfig() != null).toBe(true); 5 | }); -------------------------------------------------------------------------------- /src/configs/OrgConfig.test.js: -------------------------------------------------------------------------------- 1 | import OrgConfig from './OrgConfig'; 2 | 3 | test('OrgConfig', () => { 4 | expect(new OrgConfig() != null).toBe(true); 5 | }); -------------------------------------------------------------------------------- /css/images/ui-bg_highlight-soft_100_eeeeee_1x100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BasicPrimitives/javascript/HEAD/css/images/ui-bg_highlight-soft_100_eeeeee_1x100.png -------------------------------------------------------------------------------- /css/images/ui-bg_highlight-soft_75_ffe45c_1x100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BasicPrimitives/javascript/HEAD/css/images/ui-bg_highlight-soft_75_ffe45c_1x100.png -------------------------------------------------------------------------------- /src/configs/FamItemConfig.test.js: -------------------------------------------------------------------------------- 1 | import FamItemConfig from './FamItemConfig'; 2 | 3 | test('FamItemConfig', () => { 4 | expect(new FamItemConfig() != null).toBe(true); 5 | }); -------------------------------------------------------------------------------- /src/configs/OrgItemConfig.test.js: -------------------------------------------------------------------------------- 1 | import OrgItemConfig from './OrgItemConfig'; 2 | 3 | test('OrgItemConfig', () => { 4 | expect(new OrgItemConfig() != null).toBe(true); 5 | }); -------------------------------------------------------------------------------- /src/configs/TemplateConfig.test.js: -------------------------------------------------------------------------------- 1 | import TemplateConfig from './TemplateConfig'; 2 | 3 | test('TemplateConfig', () => { 4 | expect(new TemplateConfig() != null).toBe(true); 5 | }); -------------------------------------------------------------------------------- /src/graphics/__image_snapshots__/Graphics - Draw shape-snap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BasicPrimitives/javascript/HEAD/src/graphics/__image_snapshots__/Graphics - Draw shape-snap.png -------------------------------------------------------------------------------- /src/models/LevelVisibility.js: -------------------------------------------------------------------------------- 1 | export default function LevelVisibility(level, currentvisibility) { 2 | this.level = level; 3 | this.currentvisibility = currentvisibility; 4 | }; 5 | -------------------------------------------------------------------------------- /src/algorithms/__image_snapshots__/FamilyAlignment-Cycle 2-snap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BasicPrimitives/javascript/HEAD/src/algorithms/__image_snapshots__/FamilyAlignment-Cycle 2-snap.png -------------------------------------------------------------------------------- /src/templates/html/ButtonsTemplate.test.js: -------------------------------------------------------------------------------- 1 | import ButtonsTemplate from './ButtonsTemplate'; 2 | 3 | test('ButtonsTemplate', () => { 4 | expect(new ButtonsTemplate() != null).toBe(true); 5 | }); -------------------------------------------------------------------------------- /samples/javascript.controls/__image_snapshots__/CasePERTChart-snap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BasicPrimitives/javascript/HEAD/samples/javascript.controls/__image_snapshots__/CasePERTChart-snap.png -------------------------------------------------------------------------------- /samples/javascript.controls/__image_snapshots__/CaseShowFrame-snap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BasicPrimitives/javascript/HEAD/samples/javascript.controls/__image_snapshots__/CaseShowFrame-snap.png -------------------------------------------------------------------------------- /src/algorithms/__image_snapshots__/getMergedRectangles-Window-snap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BasicPrimitives/javascript/HEAD/src/algorithms/__image_snapshots__/getMergedRectangles-Window-snap.png -------------------------------------------------------------------------------- /src/configs/PaletteItemConfig.test.js: -------------------------------------------------------------------------------- 1 | import PaletteItemConfig from './PaletteItemConfig'; 2 | 3 | test('PaletteItemConfig', () => { 4 | expect(new PaletteItemConfig() != null).toBe(true); 5 | }); -------------------------------------------------------------------------------- /src/templates/html/CheckBoxTemplate.test.js: -------------------------------------------------------------------------------- 1 | import CheckBoxTemplate from './CheckBoxTemplate'; 2 | 3 | test('CheckBoxTemplate', () => { 4 | expect(new CheckBoxTemplate() != null).toBe(true); 5 | }); -------------------------------------------------------------------------------- /samples/javascript.controls/__image_snapshots__/CaseButtonsPanel-snap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BasicPrimitives/javascript/HEAD/samples/javascript.controls/__image_snapshots__/CaseButtonsPanel-snap.png -------------------------------------------------------------------------------- /samples/javascript.controls/__image_snapshots__/CaseItemTemplate-snap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BasicPrimitives/javascript/HEAD/samples/javascript.controls/__image_snapshots__/CaseItemTemplate-snap.png -------------------------------------------------------------------------------- /src/algorithms/__image_snapshots__/FamilyAlignment-Fance layout-snap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BasicPrimitives/javascript/HEAD/src/algorithms/__image_snapshots__/FamilyAlignment-Fance layout-snap.png -------------------------------------------------------------------------------- /src/algorithms/__image_snapshots__/FamilyAlignment-Wave layout-snap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BasicPrimitives/javascript/HEAD/src/algorithms/__image_snapshots__/FamilyAlignment-Wave layout-snap.png -------------------------------------------------------------------------------- /src/algorithms/__image_snapshots__/SpatialIndex-BoundedRectangle-snap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BasicPrimitives/javascript/HEAD/src/algorithms/__image_snapshots__/SpatialIndex-BoundedRectangle-snap.png -------------------------------------------------------------------------------- /src/algorithms/__image_snapshots__/SpatialIndex-TouchedRectangle-snap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BasicPrimitives/javascript/HEAD/src/algorithms/__image_snapshots__/SpatialIndex-TouchedRectangle-snap.png -------------------------------------------------------------------------------- /src/algorithms/__image_snapshots__/getCrossingRectangles-Window-snap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BasicPrimitives/javascript/HEAD/src/algorithms/__image_snapshots__/getCrossingRectangles-Window-snap.png -------------------------------------------------------------------------------- /src/algorithms/__image_snapshots__/getMergedRectangles-Dumbbell-snap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BasicPrimitives/javascript/HEAD/src/algorithms/__image_snapshots__/getMergedRectangles-Dumbbell-snap.png -------------------------------------------------------------------------------- /src/algorithms/__image_snapshots__/getMergedRectangles-Window 2-snap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BasicPrimitives/javascript/HEAD/src/algorithms/__image_snapshots__/getMergedRectangles-Window 2-snap.png -------------------------------------------------------------------------------- /src/graphics/shapes/__image_snapshots__/MergedRectangles-Window-snap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BasicPrimitives/javascript/HEAD/src/graphics/shapes/__image_snapshots__/MergedRectangles-Window-snap.png -------------------------------------------------------------------------------- /src/graphics/structs/Matrix.test.js: -------------------------------------------------------------------------------- 1 | import Matrix from './Matrix'; 2 | 3 | test('Matrix - 2 by 2 matrix', () => { 4 | var m = new Matrix(6, 2, 5, 3); 5 | 6 | expect(m.determinant()).toBe(8); 7 | }); -------------------------------------------------------------------------------- /samples/javascript.controls/__image_snapshots__/CaseCursorTemplate-snap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BasicPrimitives/javascript/HEAD/samples/javascript.controls/__image_snapshots__/CaseCursorTemplate-snap.png -------------------------------------------------------------------------------- /samples/javascript.controls/__image_snapshots__/CaseInactiveItems-snap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BasicPrimitives/javascript/HEAD/samples/javascript.controls/__image_snapshots__/CaseInactiveItems-snap.png -------------------------------------------------------------------------------- /samples/javascript.controls/__image_snapshots__/CaseSelectedItems-snap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BasicPrimitives/javascript/HEAD/samples/javascript.controls/__image_snapshots__/CaseSelectedItems-snap.png -------------------------------------------------------------------------------- /samples/javascript.controls/__image_snapshots__/CaseSkippedLevels-snap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BasicPrimitives/javascript/HEAD/samples/javascript.controls/__image_snapshots__/CaseSkippedLevels-snap.png -------------------------------------------------------------------------------- /src/algorithms/__image_snapshots__/FamilyAlignment-Large sandclock-snap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BasicPrimitives/javascript/HEAD/src/algorithms/__image_snapshots__/FamilyAlignment-Large sandclock-snap.png -------------------------------------------------------------------------------- /src/algorithms/__image_snapshots__/SpatialIndex-BoundingRectangle-snap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BasicPrimitives/javascript/HEAD/src/algorithms/__image_snapshots__/SpatialIndex-BoundingRectangle-snap.png -------------------------------------------------------------------------------- /src/algorithms/__image_snapshots__/getCrossingRectangles-Dumbbell-snap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BasicPrimitives/javascript/HEAD/src/algorithms/__image_snapshots__/getCrossingRectangles-Dumbbell-snap.png -------------------------------------------------------------------------------- /src/algorithms/__image_snapshots__/getCrossingRectangles-Window 2-snap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BasicPrimitives/javascript/HEAD/src/algorithms/__image_snapshots__/getCrossingRectangles-Window 2-snap.png -------------------------------------------------------------------------------- /src/graphics/__image_snapshots__/Graphics - Merge single rectangle-snap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BasicPrimitives/javascript/HEAD/src/graphics/__image_snapshots__/Graphics - Merge single rectangle-snap.png -------------------------------------------------------------------------------- /src/graphics/shapes/__image_snapshots__/MergedRectangles-Window 2-snap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BasicPrimitives/javascript/HEAD/src/graphics/shapes/__image_snapshots__/MergedRectangles-Window 2-snap.png -------------------------------------------------------------------------------- /samples/javascript.controls/__image_snapshots__/CaseFirstFamilyChart-snap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BasicPrimitives/javascript/HEAD/samples/javascript.controls/__image_snapshots__/CaseFirstFamilyChart-snap.png -------------------------------------------------------------------------------- /samples/javascript.controls/__image_snapshots__/CaseHighlightTemplate-snap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BasicPrimitives/javascript/HEAD/samples/javascript.controls/__image_snapshots__/CaseHighlightTemplate-snap.png -------------------------------------------------------------------------------- /samples/javascript.controls/__image_snapshots__/CaseItemTemplateLabel-snap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BasicPrimitives/javascript/HEAD/samples/javascript.controls/__image_snapshots__/CaseItemTemplateLabel-snap.png -------------------------------------------------------------------------------- /samples/javascript.controls/__image_snapshots__/CaseLevelAnnotation-snap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BasicPrimitives/javascript/HEAD/samples/javascript.controls/__image_snapshots__/CaseLevelAnnotation-snap.png -------------------------------------------------------------------------------- /samples/javascript.controls/__image_snapshots__/CaseSelectionPathMode-snap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BasicPrimitives/javascript/HEAD/samples/javascript.controls/__image_snapshots__/CaseSelectionPathMode-snap.png -------------------------------------------------------------------------------- /samples/javascript.controls/__image_snapshots__/CaseShapeAnnotation-snap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BasicPrimitives/javascript/HEAD/samples/javascript.controls/__image_snapshots__/CaseShapeAnnotation-snap.png -------------------------------------------------------------------------------- /samples/javascript.controls/common/PanelConfig.js: -------------------------------------------------------------------------------- 1 | export default function PanelConfig(caption, items, namespace) { 2 | this.caption = caption; 3 | this.items = items; 4 | this.namespace = namespace; 5 | }; -------------------------------------------------------------------------------- /src/algorithms/__image_snapshots__/FamilyAlignment-Left spiral layout-snap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BasicPrimitives/javascript/HEAD/src/algorithms/__image_snapshots__/FamilyAlignment-Left spiral layout-snap.png -------------------------------------------------------------------------------- /src/algorithms/__image_snapshots__/SpatialIndex-Matrix nesting test-snap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BasicPrimitives/javascript/HEAD/src/algorithms/__image_snapshots__/SpatialIndex-Matrix nesting test-snap.png -------------------------------------------------------------------------------- /src/algorithms/__image_snapshots__/SpatialIndex-Multi-layer test case-snap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BasicPrimitives/javascript/HEAD/src/algorithms/__image_snapshots__/SpatialIndex-Multi-layer test case-snap.png -------------------------------------------------------------------------------- /src/algorithms/__image_snapshots__/getCrossingRectangles-5 rectangles-snap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BasicPrimitives/javascript/HEAD/src/algorithms/__image_snapshots__/getCrossingRectangles-5 rectangles-snap.png -------------------------------------------------------------------------------- /src/graphics/__image_snapshots__/Graphics - Draw shape having island-snap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BasicPrimitives/javascript/HEAD/src/graphics/__image_snapshots__/Graphics - Draw shape having island-snap.png -------------------------------------------------------------------------------- /src/graphics/structs/Interval.test.js: -------------------------------------------------------------------------------- 1 | import Interval from './Interval'; 2 | 3 | test('Interval - width', () => { 4 | var interval = new Interval(10, 40); 5 | 6 | expect(interval.width()).toBe(30); 7 | }); 8 | -------------------------------------------------------------------------------- /src/models/TreeLevelConnectorStackSize.js: -------------------------------------------------------------------------------- 1 | export default function TreeLevelConnectorStackSize() { 2 | this.parentsStackSize = 0; /* number of overlapping horiontal connection lines between partners in level */ 3 | }; -------------------------------------------------------------------------------- /samples/javascript.controls/__image_snapshots__/CaseConnectorAnnotation-snap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BasicPrimitives/javascript/HEAD/samples/javascript.controls/__image_snapshots__/CaseConnectorAnnotation-snap.png -------------------------------------------------------------------------------- /samples/javascript.controls/__image_snapshots__/CaseInactiveFamilyItems-snap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BasicPrimitives/javascript/HEAD/samples/javascript.controls/__image_snapshots__/CaseInactiveFamilyItems-snap.png -------------------------------------------------------------------------------- /samples/javascript.controls/__image_snapshots__/CaseLoopsInFamilyChart-snap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BasicPrimitives/javascript/HEAD/samples/javascript.controls/__image_snapshots__/CaseLoopsInFamilyChart-snap.png -------------------------------------------------------------------------------- /samples/javascript.controls/__image_snapshots__/CaseSelectingCursorItem-snap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BasicPrimitives/javascript/HEAD/samples/javascript.controls/__image_snapshots__/CaseSelectingCursorItem-snap.png -------------------------------------------------------------------------------- /src/algorithms/__image_snapshots__/FamilyAlignment-Empty family layout-snap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BasicPrimitives/javascript/HEAD/src/algorithms/__image_snapshots__/FamilyAlignment-Empty family layout-snap.png -------------------------------------------------------------------------------- /src/algorithms/__image_snapshots__/FamilyAlignment-Right spiral layout-snap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BasicPrimitives/javascript/HEAD/src/algorithms/__image_snapshots__/FamilyAlignment-Right spiral layout-snap.png -------------------------------------------------------------------------------- /src/algorithms/__image_snapshots__/FamilyAlignment-Skewed rombus layout-snap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BasicPrimitives/javascript/HEAD/src/algorithms/__image_snapshots__/FamilyAlignment-Skewed rombus layout-snap.png -------------------------------------------------------------------------------- /src/configs/LabelAnnotationConfig.test.js: -------------------------------------------------------------------------------- 1 | import LabelAnnotationConfig from './LabelAnnotationConfig'; 2 | 3 | test('LabelAnnotationConfig', () => { 4 | expect(new LabelAnnotationConfig() != null).toBe(true); 5 | }); -------------------------------------------------------------------------------- /src/configs/ShapeAnnotationConfig.test.js: -------------------------------------------------------------------------------- 1 | import ShapeAnnotationConfig from './ShapeAnnotationConfig'; 2 | 3 | test('ShapeAnnotationConfig', () => { 4 | expect(new ShapeAnnotationConfig() != null).toBe(true); 5 | }); -------------------------------------------------------------------------------- /samples/javascript.controls/__image_snapshots__/CaseAdviserPartnerItemType-snap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BasicPrimitives/javascript/HEAD/samples/javascript.controls/__image_snapshots__/CaseAdviserPartnerItemType-snap.png -------------------------------------------------------------------------------- /samples/javascript.controls/__image_snapshots__/CaseChildrenPlacementType-snap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BasicPrimitives/javascript/HEAD/samples/javascript.controls/__image_snapshots__/CaseChildrenPlacementType-snap.png -------------------------------------------------------------------------------- /samples/javascript.controls/__image_snapshots__/CaseCrossBranchAlignment-snap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BasicPrimitives/javascript/HEAD/samples/javascript.controls/__image_snapshots__/CaseCrossBranchAlignment-snap.png -------------------------------------------------------------------------------- /samples/javascript.controls/__image_snapshots__/CaseFamilyChartRelations-snap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BasicPrimitives/javascript/HEAD/samples/javascript.controls/__image_snapshots__/CaseFamilyChartRelations-snap.png -------------------------------------------------------------------------------- /samples/javascript.controls/__image_snapshots__/CaseGeneralPartnerItemType-snap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BasicPrimitives/javascript/HEAD/samples/javascript.controls/__image_snapshots__/CaseGeneralPartnerItemType-snap.png -------------------------------------------------------------------------------- /samples/javascript.controls/__image_snapshots__/CaseLimitedPartnerItemType-snap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BasicPrimitives/javascript/HEAD/samples/javascript.controls/__image_snapshots__/CaseLimitedPartnerItemType-snap.png -------------------------------------------------------------------------------- /samples/javascript.controls/__image_snapshots__/CaseSelectingHighlightItem-snap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BasicPrimitives/javascript/HEAD/samples/javascript.controls/__image_snapshots__/CaseSelectingHighlightItem-snap.png -------------------------------------------------------------------------------- /samples/javascript.controls/__image_snapshots__/CaseSpousesInFamilyLayout-snap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BasicPrimitives/javascript/HEAD/samples/javascript.controls/__image_snapshots__/CaseSpousesInFamilyLayout-snap.png -------------------------------------------------------------------------------- /src/algorithms/__image_snapshots__/FamilyAlignment-Internal orphan family-snap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BasicPrimitives/javascript/HEAD/src/algorithms/__image_snapshots__/FamilyAlignment-Internal orphan family-snap.png -------------------------------------------------------------------------------- /src/algorithms/__image_snapshots__/FamilyAlignment-Side by side families-snap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BasicPrimitives/javascript/HEAD/src/algorithms/__image_snapshots__/FamilyAlignment-Side by side families-snap.png -------------------------------------------------------------------------------- /src/algorithms/__image_snapshots__/QuadTree-NW to SE diagonal points test-snap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BasicPrimitives/javascript/HEAD/src/algorithms/__image_snapshots__/QuadTree-NW to SE diagonal points test-snap.png -------------------------------------------------------------------------------- /src/algorithms/__image_snapshots__/QuadTree-SW to NE diagonal points test-snap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BasicPrimitives/javascript/HEAD/src/algorithms/__image_snapshots__/QuadTree-SW to NE diagonal points test-snap.png -------------------------------------------------------------------------------- /src/algorithms/__image_snapshots__/QuadTree-W to E horizontal points test-snap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BasicPrimitives/javascript/HEAD/src/algorithms/__image_snapshots__/QuadTree-W to E horizontal points test-snap.png -------------------------------------------------------------------------------- /src/algorithms/__image_snapshots__/getCrossingRectangles-Single rectangle-snap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BasicPrimitives/javascript/HEAD/src/algorithms/__image_snapshots__/getCrossingRectangles-Single rectangle-snap.png -------------------------------------------------------------------------------- /src/algorithms/__image_snapshots__/getCrossingRectangles-Vertical overlay-snap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BasicPrimitives/javascript/HEAD/src/algorithms/__image_snapshots__/getCrossingRectangles-Vertical overlay-snap.png -------------------------------------------------------------------------------- /src/algorithms/__image_snapshots__/getMinimumCrossingRows-Basic test case-snap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BasicPrimitives/javascript/HEAD/src/algorithms/__image_snapshots__/getMinimumCrossingRows-Basic test case-snap.png -------------------------------------------------------------------------------- /samples/javascript.controls/__image_snapshots__/CaseAddingLinkToItemTemplate-snap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BasicPrimitives/javascript/HEAD/samples/javascript.controls/__image_snapshots__/CaseAddingLinkToItemTemplate-snap.png -------------------------------------------------------------------------------- /samples/javascript.controls/__image_snapshots__/CaseFamilyChartItemsOrdering-snap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BasicPrimitives/javascript/HEAD/samples/javascript.controls/__image_snapshots__/CaseFamilyChartItemsOrdering-snap.png -------------------------------------------------------------------------------- /samples/javascript.controls/__image_snapshots__/CaseFamilyChartMatrixLayout-snap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BasicPrimitives/javascript/HEAD/samples/javascript.controls/__image_snapshots__/CaseFamilyChartMatrixLayout-snap.png -------------------------------------------------------------------------------- /samples/javascript.controls/__image_snapshots__/CaseFamilyChartPrimaryParent-snap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BasicPrimitives/javascript/HEAD/samples/javascript.controls/__image_snapshots__/CaseFamilyChartPrimaryParent-snap.png -------------------------------------------------------------------------------- /samples/javascript.controls/__image_snapshots__/CaseFirstOrganizationalChart-snap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BasicPrimitives/javascript/HEAD/samples/javascript.controls/__image_snapshots__/CaseFirstOrganizationalChart-snap.png -------------------------------------------------------------------------------- /samples/javascript.controls/__image_snapshots__/CaseHighlightPathAnnotation-snap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BasicPrimitives/javascript/HEAD/samples/javascript.controls/__image_snapshots__/CaseHighlightPathAnnotation-snap.png -------------------------------------------------------------------------------- /samples/javascript.controls/__image_snapshots__/CaseItemAndGroupTitleColors-snap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BasicPrimitives/javascript/HEAD/samples/javascript.controls/__image_snapshots__/CaseItemAndGroupTitleColors-snap.png -------------------------------------------------------------------------------- /samples/javascript.controls/__image_snapshots__/CaseLevelAnnotationTemplate-snap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BasicPrimitives/javascript/HEAD/samples/javascript.controls/__image_snapshots__/CaseLevelAnnotationTemplate-snap.png -------------------------------------------------------------------------------- /samples/javascript.controls/__image_snapshots__/CaseMultipleFamiliesOrdering-snap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BasicPrimitives/javascript/HEAD/samples/javascript.controls/__image_snapshots__/CaseMultipleFamiliesOrdering-snap.png -------------------------------------------------------------------------------- /samples/javascript.controls/__image_snapshots__/CaseMultipleRootItemsInChart-snap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BasicPrimitives/javascript/HEAD/samples/javascript.controls/__image_snapshots__/CaseMultipleRootItemsInChart-snap.png -------------------------------------------------------------------------------- /src/algorithms/__image_snapshots__/FamilyAlignment-Single node family layout-snap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BasicPrimitives/javascript/HEAD/src/algorithms/__image_snapshots__/FamilyAlignment-Single node family layout-snap.png -------------------------------------------------------------------------------- /src/algorithms/__image_snapshots__/getCrossingRectangles-Horizontal overlay-snap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BasicPrimitives/javascript/HEAD/src/algorithms/__image_snapshots__/getCrossingRectangles-Horizontal overlay-snap.png -------------------------------------------------------------------------------- /src/algorithms/__image_snapshots__/getMergedRectangles-Merge 5 rectangles 2-snap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BasicPrimitives/javascript/HEAD/src/algorithms/__image_snapshots__/getMergedRectangles-Merge 5 rectangles 2-snap.png -------------------------------------------------------------------------------- /src/enums.test.js: -------------------------------------------------------------------------------- 1 | import { Colors, AnnotationType } from './enums'; 2 | 3 | test('Enumeration is readable by name', () => { 4 | expect(Colors.Aqua).toEqual("#00ffff"); 5 | expect(AnnotationType.Background).toEqual(4); 6 | }); -------------------------------------------------------------------------------- /src/graphics/shapes/__image_snapshots__/MergedRectangles-Merge 5 rectangles-snap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BasicPrimitives/javascript/HEAD/src/graphics/shapes/__image_snapshots__/MergedRectangles-Merge 5 rectangles-snap.png -------------------------------------------------------------------------------- /samples/javascript.controls/__image_snapshots__/CaseLabelsCascadesInFamilyChart-snap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BasicPrimitives/javascript/HEAD/samples/javascript.controls/__image_snapshots__/CaseLabelsCascadesInFamilyChart-snap.png -------------------------------------------------------------------------------- /samples/javascript.controls/__image_snapshots__/CaseLabelsNMatrixInFamilyChart-snap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BasicPrimitives/javascript/HEAD/samples/javascript.controls/__image_snapshots__/CaseLabelsNMatrixInFamilyChart-snap.png -------------------------------------------------------------------------------- /samples/javascript.controls/__image_snapshots__/CaseMatrixGroupsInFamilyChart-snap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BasicPrimitives/javascript/HEAD/samples/javascript.controls/__image_snapshots__/CaseMatrixGroupsInFamilyChart-snap.png -------------------------------------------------------------------------------- /samples/javascript.controls/__image_snapshots__/CaseMatrixLayoutInFamilyChart-snap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BasicPrimitives/javascript/HEAD/samples/javascript.controls/__image_snapshots__/CaseMatrixLayoutInFamilyChart-snap.png -------------------------------------------------------------------------------- /samples/javascript.controls/__image_snapshots__/CasePlaceAdvisersAboveChildren-snap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BasicPrimitives/javascript/HEAD/samples/javascript.controls/__image_snapshots__/CasePlaceAdvisersAboveChildren-snap.png -------------------------------------------------------------------------------- /src/algorithms/__image_snapshots__/FamilyAlignment-Regular tree family layout-snap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BasicPrimitives/javascript/HEAD/src/algorithms/__image_snapshots__/FamilyAlignment-Regular tree family layout-snap.png -------------------------------------------------------------------------------- /src/algorithms/__image_snapshots__/FamilyAlignment-Skipped Members Test Layout-snap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BasicPrimitives/javascript/HEAD/src/algorithms/__image_snapshots__/FamilyAlignment-Skipped Members Test Layout-snap.png -------------------------------------------------------------------------------- /src/algorithms/__image_snapshots__/FamilyAlignment-Small Rombus family layout-snap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BasicPrimitives/javascript/HEAD/src/algorithms/__image_snapshots__/FamilyAlignment-Small Rombus family layout-snap.png -------------------------------------------------------------------------------- /src/algorithms/__image_snapshots__/getMergedRectangles-Merge E shape rectangles-snap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BasicPrimitives/javascript/HEAD/src/algorithms/__image_snapshots__/getMergedRectangles-Merge E shape rectangles-snap.png -------------------------------------------------------------------------------- /src/algorithms/__image_snapshots__/getMergedRectangles-Merge single rectangle-snap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BasicPrimitives/javascript/HEAD/src/algorithms/__image_snapshots__/getMergedRectangles-Merge single rectangle-snap.png -------------------------------------------------------------------------------- /src/algorithms/__image_snapshots__/getMinimumCrossingRows-Multi-layer test case-snap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BasicPrimitives/javascript/HEAD/src/algorithms/__image_snapshots__/getMinimumCrossingRows-Multi-layer test case-snap.png -------------------------------------------------------------------------------- /src/templates/html/AnnotationLabelTemplate.test.js: -------------------------------------------------------------------------------- 1 | import AnnotationLabelTemplate from './AnnotationLabelTemplate'; 2 | 3 | test('AnnotationLabelTemplate', () => { 4 | expect(new AnnotationLabelTemplate() != null).toBe(true); 5 | }); -------------------------------------------------------------------------------- /samples/javascript.controls/__image_snapshots__/CaseAdviserAndAssistantItemTypes-snap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BasicPrimitives/javascript/HEAD/samples/javascript.controls/__image_snapshots__/CaseAdviserAndAssistantItemTypes-snap.png -------------------------------------------------------------------------------- /samples/javascript.controls/__image_snapshots__/CasePlaceAssistantsAboveChildren-snap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BasicPrimitives/javascript/HEAD/samples/javascript.controls/__image_snapshots__/CasePlaceAssistantsAboveChildren-snap.png -------------------------------------------------------------------------------- /src/algorithms/__image_snapshots__/FamilyAlignment-3 Cross Relations Test Layout-snap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BasicPrimitives/javascript/HEAD/src/algorithms/__image_snapshots__/FamilyAlignment-3 Cross Relations Test Layout-snap.png -------------------------------------------------------------------------------- /src/algorithms/__image_snapshots__/FamilyAlignment-Small Sand clock family layout-snap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BasicPrimitives/javascript/HEAD/src/algorithms/__image_snapshots__/FamilyAlignment-Small Sand clock family layout-snap.png -------------------------------------------------------------------------------- /src/algorithms/__image_snapshots__/FamilyAlignment-Upside-down tree family layout-snap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BasicPrimitives/javascript/HEAD/src/algorithms/__image_snapshots__/FamilyAlignment-Upside-down tree family layout-snap.png -------------------------------------------------------------------------------- /src/algorithms/__image_snapshots__/getMergedRectangles-Merge E shape rectangles 2-snap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BasicPrimitives/javascript/HEAD/src/algorithms/__image_snapshots__/getMergedRectangles-Merge E shape rectangles 2-snap.png -------------------------------------------------------------------------------- /src/algorithms/__image_snapshots__/getMinimumCrossingRows-Nested block test case-snap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BasicPrimitives/javascript/HEAD/src/algorithms/__image_snapshots__/getMinimumCrossingRows-Nested block test case-snap.png -------------------------------------------------------------------------------- /src/configs/ConnectorAnnotationConfig.test.js: -------------------------------------------------------------------------------- 1 | import ConnectorAnnotationConfig from './ConnectorAnnotationConfig'; 2 | 3 | test('ConnectorAnnotationConfig', () => { 4 | expect(new ConnectorAnnotationConfig() != null).toBe(true); 5 | }); -------------------------------------------------------------------------------- /src/tasks/transformations/familyTransformations/FamilyBalanceItem.js: -------------------------------------------------------------------------------- 1 | export default function FamilyBalanceItem(id, familyId, level) { 2 | this.id = id; 3 | this.familyId = familyId; 4 | this.level = level; 5 | this.childIndex = 0; 6 | } -------------------------------------------------------------------------------- /samples/javascript.controls/__image_snapshots__/CaseCustomLayoutWithInvisibleItems-snap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BasicPrimitives/javascript/HEAD/samples/javascript.controls/__image_snapshots__/CaseCustomLayoutWithInvisibleItems-snap.png -------------------------------------------------------------------------------- /samples/javascript.controls/__image_snapshots__/CaseFamilyChartGrandParentsRelations-snap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BasicPrimitives/javascript/HEAD/samples/javascript.controls/__image_snapshots__/CaseFamilyChartGrandParentsRelations-snap.png -------------------------------------------------------------------------------- /samples/javascript.controls/__image_snapshots__/CaseSelectionCheckboxInItemTemplate-snap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BasicPrimitives/javascript/HEAD/samples/javascript.controls/__image_snapshots__/CaseSelectionCheckboxInItemTemplate-snap.png -------------------------------------------------------------------------------- /src/algorithms/__image_snapshots__/getCrossingRectangles-E shape rectangles on left-snap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BasicPrimitives/javascript/HEAD/src/algorithms/__image_snapshots__/getCrossingRectangles-E shape rectangles on left-snap.png -------------------------------------------------------------------------------- /src/algorithms/__image_snapshots__/getCrossingRectangles-E shape rectangles on right-snap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BasicPrimitives/javascript/HEAD/src/algorithms/__image_snapshots__/getCrossingRectangles-E shape rectangles on right-snap.png -------------------------------------------------------------------------------- /src/algorithms/__image_snapshots__/getCrossingRectangles-Two disconnected rectangles-snap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BasicPrimitives/javascript/HEAD/src/algorithms/__image_snapshots__/getCrossingRectangles-Two disconnected rectangles-snap.png -------------------------------------------------------------------------------- /src/algorithms/__image_snapshots__/getCrossingRectangles-Two overlapping rectangles-snap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BasicPrimitives/javascript/HEAD/src/algorithms/__image_snapshots__/getCrossingRectangles-Two overlapping rectangles-snap.png -------------------------------------------------------------------------------- /src/configs/BackgroundAnnotationConfig.test.js: -------------------------------------------------------------------------------- 1 | import BackgroundAnnotationConfig from './BackgroundAnnotationConfig'; 2 | 3 | test('BackgroundAnnotationConfig', () => { 4 | expect(new BackgroundAnnotationConfig() != null).toBe(true); 5 | }); -------------------------------------------------------------------------------- /src/graphics/structs/__image_snapshots__/Polyline.getOffsetPolyine - Offset square 2-snap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BasicPrimitives/javascript/HEAD/src/graphics/structs/__image_snapshots__/Polyline.getOffsetPolyine - Offset square 2-snap.png -------------------------------------------------------------------------------- /src/graphics/structs/__image_snapshots__/Polyline.getOffsetPolyine - Offset square 3-snap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BasicPrimitives/javascript/HEAD/src/graphics/structs/__image_snapshots__/Polyline.getOffsetPolyine - Offset square 3-snap.png -------------------------------------------------------------------------------- /src/graphics/structs/__image_snapshots__/Polyline.getOffsetPolyine - Offset square-snap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BasicPrimitives/javascript/HEAD/src/graphics/structs/__image_snapshots__/Polyline.getOffsetPolyine - Offset square-snap.png -------------------------------------------------------------------------------- /samples/javascript.controls/__image_snapshots__/CaseFamilyHideGrandParentsConnections-snap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BasicPrimitives/javascript/HEAD/samples/javascript.controls/__image_snapshots__/CaseFamilyHideGrandParentsConnections-snap.png -------------------------------------------------------------------------------- /samples/javascript.controls/__image_snapshots__/CaseSubAdviserAndSubAssistantItemTypes-snap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BasicPrimitives/javascript/HEAD/samples/javascript.controls/__image_snapshots__/CaseSubAdviserAndSubAssistantItemTypes-snap.png -------------------------------------------------------------------------------- /src/algorithms/__image_snapshots__/getCrossingRectangles-Two overlapping rectangles 2-snap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BasicPrimitives/javascript/HEAD/src/algorithms/__image_snapshots__/getCrossingRectangles-Two overlapping rectangles 2-snap.png -------------------------------------------------------------------------------- /src/common/colors.test.js: -------------------------------------------------------------------------------- 1 | import { highestContrast } from './colors'; 2 | 3 | test('highestContrast - White on black has higher contrast than yellow on black', () => { 4 | expect(highestContrast("black", "white", "yellow")).toBe("white"); 5 | }); -------------------------------------------------------------------------------- /src/graphics/Placeholder.js: -------------------------------------------------------------------------------- 1 | export default function Placeholder(name) { 2 | this.name = name; 3 | 4 | this.layers = {}; 5 | this.activeLayer = null; 6 | 7 | this.size = null; 8 | this.rect = null; 9 | 10 | this.div = null; 11 | }; -------------------------------------------------------------------------------- /src/algorithms/__image_snapshots__/FamilyAlignment-2 Cross Relations Demo family layout-snap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BasicPrimitives/javascript/HEAD/src/algorithms/__image_snapshots__/FamilyAlignment-2 Cross Relations Demo family layout-snap.png -------------------------------------------------------------------------------- /src/algorithms/__image_snapshots__/FamilyAlignment-Family diagram large rombus alignment-snap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BasicPrimitives/javascript/HEAD/src/algorithms/__image_snapshots__/FamilyAlignment-Family diagram large rombus alignment-snap.png -------------------------------------------------------------------------------- /src/algorithms/__image_snapshots__/FamilyAlignment-Side by side and upside-down families-snap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BasicPrimitives/javascript/HEAD/src/algorithms/__image_snapshots__/FamilyAlignment-Side by side and upside-down families-snap.png -------------------------------------------------------------------------------- /src/algorithms/__image_snapshots__/getMergedRectangles-Merge two disconnected rectangles-snap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BasicPrimitives/javascript/HEAD/src/algorithms/__image_snapshots__/getMergedRectangles-Merge two disconnected rectangles-snap.png -------------------------------------------------------------------------------- /src/algorithms/__image_snapshots__/getMergedRectangles-Merge two overlapping rectangles 2-snap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BasicPrimitives/javascript/HEAD/src/algorithms/__image_snapshots__/getMergedRectangles-Merge two overlapping rectangles 2-snap.png -------------------------------------------------------------------------------- /src/algorithms/__image_snapshots__/getMergedRectangles-Merge two overlapping rectangles-snap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BasicPrimitives/javascript/HEAD/src/algorithms/__image_snapshots__/getMergedRectangles-Merge two overlapping rectangles-snap.png -------------------------------------------------------------------------------- /src/graphics/structs/__image_snapshots__/Polyline.getOffsetPolyine - Offset cubic segment-snap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BasicPrimitives/javascript/HEAD/src/graphics/structs/__image_snapshots__/Polyline.getOffsetPolyine - Offset cubic segment-snap.png -------------------------------------------------------------------------------- /src/graphics/structs/__image_snapshots__/Polyline.getOffsetPolyine - Offset square angle-snap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BasicPrimitives/javascript/HEAD/src/graphics/structs/__image_snapshots__/Polyline.getOffsetPolyine - Offset square angle-snap.png -------------------------------------------------------------------------------- /samples/javascript.controls/__image_snapshots__/CaseFamilyChartHiddenGrandParentsRelations-snap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BasicPrimitives/javascript/HEAD/samples/javascript.controls/__image_snapshots__/CaseFamilyChartHiddenGrandParentsRelations-snap.png -------------------------------------------------------------------------------- /samples/javascript.controls/__image_snapshots__/CaseMatrixLayoutOfMultipleRootItemsInChart-snap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BasicPrimitives/javascript/HEAD/samples/javascript.controls/__image_snapshots__/CaseMatrixLayoutOfMultipleRootItemsInChart-snap.png -------------------------------------------------------------------------------- /src/algorithms/__image_snapshots__/FamilyAlignment-Alignment of items having variable width-snap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BasicPrimitives/javascript/HEAD/src/algorithms/__image_snapshots__/FamilyAlignment-Alignment of items having variable width-snap.png -------------------------------------------------------------------------------- /src/algorithms/__image_snapshots__/SpatialIndex-Should not return non overlapping rectangle-snap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BasicPrimitives/javascript/HEAD/src/algorithms/__image_snapshots__/SpatialIndex-Should not return non overlapping rectangle-snap.png -------------------------------------------------------------------------------- /src/configs/HighlightPathAnnotationConfig.test.js: -------------------------------------------------------------------------------- 1 | import HighlightPathAnnotationConfig from './HighlightPathAnnotationConfig'; 2 | 3 | test('HighlightPathAnnotationConfig', () => { 4 | expect(new HighlightPathAnnotationConfig() != null).toBe(true); 5 | }); -------------------------------------------------------------------------------- /src/algorithms/__image_snapshots__/FamilyAlignment-Family unit overlaps node between children-snap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BasicPrimitives/javascript/HEAD/src/algorithms/__image_snapshots__/FamilyAlignment-Family unit overlaps node between children-snap.png -------------------------------------------------------------------------------- /src/algorithms/__image_snapshots__/FamilyAlignment-Family unit overlaps node between parents-snap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BasicPrimitives/javascript/HEAD/src/algorithms/__image_snapshots__/FamilyAlignment-Family unit overlaps node between parents-snap.png -------------------------------------------------------------------------------- /src/algorithms/__image_snapshots__/getCrossingRectangles-Two aligned disconnected rectangles 2-snap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BasicPrimitives/javascript/HEAD/src/algorithms/__image_snapshots__/getCrossingRectangles-Two aligned disconnected rectangles 2-snap.png -------------------------------------------------------------------------------- /src/algorithms/__image_snapshots__/getCrossingRectangles-Two aligned disconnected rectangles-snap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BasicPrimitives/javascript/HEAD/src/algorithms/__image_snapshots__/getCrossingRectangles-Two aligned disconnected rectangles-snap.png -------------------------------------------------------------------------------- /src/graphics/structs/__image_snapshots__/Polyline.getOffsetPolyine - Offset quadratic segment-snap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BasicPrimitives/javascript/HEAD/src/graphics/structs/__image_snapshots__/Polyline.getOffsetPolyine - Offset quadratic segment-snap.png -------------------------------------------------------------------------------- /src/graphics/structs/__image_snapshots__/Polyline.getOffsetPolyine - Simple vertical segment-snap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BasicPrimitives/javascript/HEAD/src/graphics/structs/__image_snapshots__/Polyline.getOffsetPolyine - Simple vertical segment-snap.png -------------------------------------------------------------------------------- /src/algorithms/__image_snapshots__/getMergedRectangles-Merge two aligned disconnected rectangles-snap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BasicPrimitives/javascript/HEAD/src/algorithms/__image_snapshots__/getMergedRectangles-Merge two aligned disconnected rectangles-snap.png -------------------------------------------------------------------------------- /src/graphics/structs/__image_snapshots__/Polyline.getOffsetPolyine - Offset quadratic segment 2-snap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BasicPrimitives/javascript/HEAD/src/graphics/structs/__image_snapshots__/Polyline.getOffsetPolyine - Offset quadratic segment 2-snap.png -------------------------------------------------------------------------------- /src/algorithms/__image_snapshots__/getMergedRectangles-Merge two aligned disconnected rectangles 2-snap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BasicPrimitives/javascript/HEAD/src/algorithms/__image_snapshots__/getMergedRectangles-Merge two aligned disconnected rectangles 2-snap.png -------------------------------------------------------------------------------- /src/models/TemplateParams.js: -------------------------------------------------------------------------------- 1 | export default function TemplateParams() { 2 | this.template = null; 3 | this.isActive = false; 4 | this.hasSelectorCheckbox = false; 5 | this.hasButtons = false; 6 | this.hasGroupTitle = false; 7 | this.onButtonsRender = null; 8 | }; -------------------------------------------------------------------------------- /src/templates/html/ItemTemplate.test.js: -------------------------------------------------------------------------------- 1 | import ItemTemplate from './ItemTemplate'; 2 | import ItemtemplateConfig from '../../configs/TemplateConfig'; 3 | 4 | test('ItemTemplate', () => { 5 | expect(new ItemTemplate(null, new ItemtemplateConfig()) != null).toBe(true); 6 | }); -------------------------------------------------------------------------------- /src/templates/html/UserTemplate.test.js: -------------------------------------------------------------------------------- 1 | import UserTemplate from './UserTemplate'; 2 | import ItemtemplateConfig from '../../configs/TemplateConfig'; 3 | 4 | test('UserTemplate', () => { 5 | expect(new UserTemplate(null, new ItemtemplateConfig()) != null).toBe(true); 6 | }); -------------------------------------------------------------------------------- /src/tasks/options/OptionsTask.js: -------------------------------------------------------------------------------- 1 | export default function OptionsTask(getOptions) { 2 | 3 | function process() { 4 | return true; 5 | } 6 | 7 | return { 8 | process: process, 9 | getOptions: getOptions, 10 | description: "Raw options." 11 | }; 12 | }; -------------------------------------------------------------------------------- /src/templates/html/CursorTemplate.test.js: -------------------------------------------------------------------------------- 1 | import CursorTemplate from './CursorTemplate'; 2 | import ItemtemplateConfig from '../../configs/TemplateConfig'; 3 | 4 | test('CursorTemplate', () => { 5 | expect(new CursorTemplate(null, new ItemtemplateConfig()) != null).toBe(true); 6 | }); -------------------------------------------------------------------------------- /src/algorithms/__image_snapshots__/FamilyAlignment-Family diagram horizontal alignment with multiple cycles-snap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BasicPrimitives/javascript/HEAD/src/algorithms/__image_snapshots__/FamilyAlignment-Family diagram horizontal alignment with multiple cycles-snap.png -------------------------------------------------------------------------------- /src/templates/html/HighlightTemplate.test.js: -------------------------------------------------------------------------------- 1 | import HighlightTemplate from './HighlightTemplate'; 2 | import ItemtemplateConfig from '../../configs/TemplateConfig'; 3 | 4 | test('HighlightTemplate', () => { 5 | expect(new HighlightTemplate(null, new ItemtemplateConfig()) != null).toBe(true); 6 | }); -------------------------------------------------------------------------------- /src/readers/FunctionReader.js: -------------------------------------------------------------------------------- 1 | export default function FunctionReader() { 2 | 3 | }; 4 | 5 | FunctionReader.prototype.read = function (target, source, path, context) { 6 | var result = null; 7 | 8 | result = (typeof source == "function") ? source : null; 9 | 10 | return result; 11 | }; 12 | -------------------------------------------------------------------------------- /src/algorithms/__image_snapshots__/FamilyAlignment-Side by side 2 families where the left one starts one generation below-snap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BasicPrimitives/javascript/HEAD/src/algorithms/__image_snapshots__/FamilyAlignment-Side by side 2 families where the left one starts one generation below-snap.png -------------------------------------------------------------------------------- /src/getFamTasksDiagram.js: -------------------------------------------------------------------------------- 1 | import FamTaskManagerFactory from './FamTaskManagerFactory'; 2 | 3 | export default function getFamTasksDiagram() { 4 | var dummyFunction = function () { }; 5 | var tasks = FamTaskManagerFactory(dummyFunction, dummyFunction, dummyFunction); 6 | return tasks.getProcessDiagramConfig(); 7 | }; -------------------------------------------------------------------------------- /src/getOrgTasksDiagram.js: -------------------------------------------------------------------------------- 1 | import OrgTaskManagerFactory from './OrgTaskManagerFactory'; 2 | 3 | export default function getOrgTasksDiagram() { 4 | var dummyFunction = function () { }; 5 | var tasks = OrgTaskManagerFactory(dummyFunction, dummyFunction, dummyFunction); 6 | return tasks.getProcessDiagramConfig(); 7 | }; -------------------------------------------------------------------------------- /src/templates/html/DotHighlightTemplate.test.js: -------------------------------------------------------------------------------- 1 | import DotHighlightTemplate from './DotHighlightTemplate'; 2 | import ItemtemplateConfig from '../../configs/TemplateConfig'; 3 | 4 | test('DotHighlightTemplate', () => { 5 | expect(new DotHighlightTemplate(null, new ItemtemplateConfig()) != null).toBe(true); 6 | }); -------------------------------------------------------------------------------- /src/getFamPdfkitTasksDiagram.js: -------------------------------------------------------------------------------- 1 | import FamPdfkitTaskManagerFactory from './FamPdfkitTaskManagerFactory'; 2 | 3 | export default function getFamTasksDiagram() { 4 | var dummyFunction = function () { }; 5 | var tasks = FamPdfkitTaskManagerFactory(dummyFunction, dummyFunction, dummyFunction); 6 | return tasks.getProcessDiagramConfig(); 7 | }; -------------------------------------------------------------------------------- /src/getOrgPdfkitTasksDiagram.js: -------------------------------------------------------------------------------- 1 | import OrgPdfkitTaskManagerFactory from './OrgPdfkitTaskManagerFactory'; 2 | 3 | export default function getOrgTasksDiagram() { 4 | var dummyFunction = function () { }; 5 | var tasks = OrgPdfkitTaskManagerFactory(dummyFunction, dummyFunction, dummyFunction); 6 | return tasks.getProcessDiagramConfig(); 7 | }; -------------------------------------------------------------------------------- /src/graphics/structs/DotSegment.js: -------------------------------------------------------------------------------- 1 | import { SegmentType } from '../../enums'; 2 | 3 | export default function DotSegment(x, y, width, height, cornerRadius) { 4 | this.segmentType = SegmentType.Dot; 5 | 6 | this.x = x; 7 | this.y = y; 8 | this.width = width; 9 | this.height = height; 10 | this.cornerRadius = cornerRadius; 11 | }; 12 | -------------------------------------------------------------------------------- /src/templates/pdf/DummyTemplate.js: -------------------------------------------------------------------------------- 1 | export default function DummyTemplate() { 2 | function template() { 3 | return {}; 4 | } 5 | 6 | function getHashCode() { 7 | return 0; 8 | } 9 | 10 | function render() { } 11 | 12 | return { 13 | template: template, 14 | getHashCode: getHashCode, 15 | render: render 16 | }; 17 | }; -------------------------------------------------------------------------------- /src/models/Template.js: -------------------------------------------------------------------------------- 1 | export default function Template(templateConfig, itemTemplate, highlightTemplate, dotHighlightTemplate, cursorTemplate) { 2 | this.templateConfig = templateConfig; 3 | this.itemTemplate = itemTemplate; 4 | this.highlightTemplate = highlightTemplate; 5 | this.dotHighlightTemplate = dotHighlightTemplate; 6 | this.cursorTemplate = cursorTemplate; 7 | }; 8 | -------------------------------------------------------------------------------- /src/tasks/transformations/selection/DummyCombinedNormalVisibilityItemsTask.js: -------------------------------------------------------------------------------- 1 | export default function DummyCombinedNormalVisibilityItemsTask(optionsTask) { 2 | function process() { 3 | return true; 4 | } 5 | 6 | function isItemSelected(treeItem) { 7 | return false; 8 | } 9 | 10 | return { 11 | process: process, 12 | isItemSelected: isItemSelected 13 | }; 14 | }; -------------------------------------------------------------------------------- /src/tasks/transformations/CombinedContextsTask.js: -------------------------------------------------------------------------------- 1 | export default function CombinedContextsTask(task1, task2) { 2 | function process() { 3 | return true; 4 | } 5 | 6 | function getConfig(itemId) { 7 | return task1.getConfig(itemId) || (task2 != null && task2.getConfig(itemId)); 8 | } 9 | 10 | return { 11 | process: process, 12 | getConfig: getConfig 13 | }; 14 | }; -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | apireference 2 | node_modules 3 | .vscode 4 | samples 5 | .gitignore 6 | apireference.js 7 | apireference.json 8 | babel.config.js 9 | index.html 10 | webpack.config.js 11 | yarn.lock 12 | dist/interactivetests.js 13 | dist/interactivetests.js.map 14 | dist/javascriptsamples.js 15 | dist/javascriptsamples.js.map 16 | dist/pdfkitsamples.js 17 | dist/pdfkitsamples.js.map 18 | __image_snapshots__ 19 | 20 | -------------------------------------------------------------------------------- /src/tasks/options/LayoutOptionsTask.js: -------------------------------------------------------------------------------- 1 | export default function LayoutOptionsTask(getLayout, optionsTask) { 2 | var _data = {}; 3 | 4 | function process() { 5 | _data = getLayout(); 6 | 7 | return true; 8 | } 9 | 10 | function getOptions() { 11 | return _data; 12 | } 13 | 14 | return { 15 | process: process, 16 | getOptions: getOptions, 17 | description: "Raw layout options." 18 | }; 19 | }; -------------------------------------------------------------------------------- /samples/PopupDialog.md: -------------------------------------------------------------------------------- 1 | ## Organizational Chart inside Bootstrap [Popup](https://getbootstrap.com/docs/4.0/components/modal/) Dialog 2 | 3 | This sample is a general compatibility test on how the control works inside the Bootstrap Popup dialog. The example demonstrates selecting multiple organizational chat items inside Bootstrap Popup Dialog and returning them to the application. 4 | 5 | [JavaScript](javascript.controls/CasePopupDialog.html) -------------------------------------------------------------------------------- /samples/LoopsInFamily.md: -------------------------------------------------------------------------------- 1 | # Optimization of loops in layered graph visualization 2 | 3 | If relations between nodes form loops, the control tries to find a layout minimizing the number of links going in the opposite direction. 4 | 5 | [JavaScript](javascript.controls/CaseLoopsInFamilyChart.html) 6 | [PDFKit](pdfkit.plugins/LoopsInFamilyChart.html) 7 | 8 |  9 | -------------------------------------------------------------------------------- /samples/javascript.controls/common/enums.js: -------------------------------------------------------------------------------- 1 | export const ValueType = { 2 | Integer: 0, 3 | String: 1, 4 | Number: 2, 5 | Boolean: 3, 6 | Size: 4, 7 | Thickness: 5, 8 | Color: 6, 9 | Range: 7 10 | }; 11 | 12 | export const ControlType = { 13 | Caption: 0, 14 | RadioBox: 1, 15 | CheckBox: 2, 16 | DropDownBox: 3, 17 | SizeBox: 4, 18 | TextBox: 5, 19 | ColorPicker: 6, 20 | Range: 7, 21 | Thickness: 8 22 | }; -------------------------------------------------------------------------------- /src/templates/pdf/CustomRenderTemplate.js: -------------------------------------------------------------------------------- 1 | export default function CustomRenderTemplate(options, onRender) { 2 | function template() { 3 | return {}; 4 | } 5 | 6 | function getHashCode() { 7 | return 0; 8 | } 9 | 10 | function render(doc, position, data) { 11 | if (onRender != null) { 12 | onRender(doc, position, data); 13 | } 14 | } 15 | 16 | return { 17 | template: template, 18 | getHashCode: getHashCode, 19 | render: render 20 | }; 21 | }; 22 | 23 | -------------------------------------------------------------------------------- /src/tasks/templates/CombinedTemplateParamsTask.js: -------------------------------------------------------------------------------- 1 | export default function CombinedTemplateParamsTask(itemTemplateParamsTask, labelAnnotationTemplateParamsTask) { 2 | function process() { 3 | return true; 4 | } 5 | 6 | function getTemplateParams(itemId) { 7 | return itemTemplateParamsTask.getTemplateParams(itemId) || labelAnnotationTemplateParamsTask.getTemplateParams(itemId); 8 | } 9 | 10 | return { 11 | process: process, 12 | getTemplateParams: getTemplateParams 13 | }; 14 | }; -------------------------------------------------------------------------------- /src/tasks/templates/ButtonsTemplateTask.js: -------------------------------------------------------------------------------- 1 | export default function ButtonsTemplateTask(itemsSizesOptionTask, templates) { 2 | var _data = { 3 | template: null 4 | }; 5 | 6 | function process() { 7 | return false; 8 | } 9 | 10 | function getTemplate() { 11 | if (_data.template == null) { 12 | _data.template = new templates.ButtonsTemplate; 13 | } 14 | return _data.template; 15 | } 16 | 17 | return { 18 | process: process, 19 | getTemplate: getTemplate 20 | }; 21 | }; -------------------------------------------------------------------------------- /samples/javascript.controls/common/index.js: -------------------------------------------------------------------------------- 1 | export * from './panels'; 2 | export { ValueType } from './enums'; 3 | export { default as PanelConfig } from './PanelConfig'; 4 | export { CaptionConfig } from './Caption'; 5 | export { RadioBoxConfig } from './RadioBox'; 6 | export { RangeConfig } from './Range'; 7 | export { ColorConfig } from './Color'; 8 | export { SizeConfig } from './Size'; 9 | export { CheckBoxConfig } from './CheckBox'; 10 | export { DropDownBoxConfig } from './DropDownBox'; 11 | export { default as Render } from './Render'; -------------------------------------------------------------------------------- /src/tasks/layout/DummyCurrentControlSizeTask.js: -------------------------------------------------------------------------------- 1 | import Size from '../../graphics/structs/Size'; 2 | 3 | export default function DummyCurrentControlSizeTask(optionsTask) { 4 | function process() { 5 | return true; 6 | } 7 | 8 | function getOptions() { 9 | return { 10 | scrollPanelSize: new Size(800, 600), 11 | optimalPanelSize: new Size(800 - 25, 600 - 25), 12 | hasFrame: true, 13 | hasLevelTitles: true 14 | } 15 | } 16 | 17 | return { 18 | process: process, 19 | getOptions: getOptions 20 | }; 21 | }; 22 | -------------------------------------------------------------------------------- /samples/pdfkit.plugins/index.js: -------------------------------------------------------------------------------- 1 | export {default as PDFDocument} from 'pdfkit-nodejs-webpack'; 2 | export {default as blobStream} from 'blob-stream'; 3 | export {default as saveAs } from 'file-saver'; 4 | export {default as photos } from './photos/photos'; 5 | export {default as PdfGraphics} from '../../src/graphics/PdfGraphics'; 6 | export {default as Marker} from '../../src/graphics/shapes/Marker'; 7 | export { default as PolylinesBuffer } from '../../src/graphics/structs/PolylinesBuffer'; 8 | export { default as PaletteItem } from '../../src/graphics/structs/PaletteItem'; -------------------------------------------------------------------------------- /samples/Buttons.md: -------------------------------------------------------------------------------- 1 | # Buttons panel 2 | 3 | The organizational chart provides API to create a custom context buttons panel. The option `OrgConfig.hasButtons` allows making context panel visible only for the current cursor item or for all visible nodes in the diagram. The same properties exist in `TemplateConfig.hasButtons` and `OrgItemConfig.hasButtons`. They allow setting buttons panel visibility for individual items and templates. 4 | 5 | [JavaScript](javascript.controls/CaseButtonsPanel.html) 6 | 7 |  -------------------------------------------------------------------------------- /src/tasks/templates/AnnotationLabelTemplateTask.js: -------------------------------------------------------------------------------- 1 | export default function AnnotationLabelTemplateTask(itemsSizesOptionTask /* changes in items update layout anyway */, templates) { 2 | var _data = { 3 | labelTemplate: null 4 | }; 5 | 6 | function process() { 7 | return false; 8 | } 9 | 10 | function getTemplate() { 11 | if (_data.labelTemplate == null) { 12 | _data.labelTemplate = new templates.AnnotationLabelTemplate(); 13 | } 14 | return _data.labelTemplate; 15 | } 16 | 17 | return { 18 | process: process, 19 | getTemplate: getTemplate 20 | }; 21 | }; -------------------------------------------------------------------------------- /src/algorithms/getLiniarBreaks.test.js: -------------------------------------------------------------------------------- 1 | import getLiniarBreaks from './getLiniarBreaks' 2 | 3 | test('Liniar breaks for 3 sequences havin 10x and 100x difference', () => { 4 | expect(getLiniarBreaks([1, 2, 3, 4, 5, 6, 7, 8, 9, 200, 300, 400, 9900, 10000])).toEqual([8, 11, 13]); 5 | }); 6 | 7 | test('Liniar breaks for 3 distinct numbers', () => { 8 | expect(getLiniarBreaks([1, 2, 3, 4, 5, 6, 7, 8, 9])).toEqual([2, 5, 8]); 9 | }); 10 | 11 | test('Liniar breaks for 2 sequences having 10x difference', () => { 12 | expect(getLiniarBreaks([1, 2, 3, 4, 5, 6, 7, 8, 9, 100, 200, 300])).toEqual([3, 8, 11]); 13 | }); -------------------------------------------------------------------------------- /src/templates/html/CustomRenderTemplate.js: -------------------------------------------------------------------------------- 1 | export default function CustomRenderTemplate(options, onRender) { 2 | var _template = ["div", { 3 | "style": { 4 | position: "absolute" 5 | } 6 | } 7 | ]; 8 | 9 | function template() { 10 | return _template; 11 | } 12 | 13 | function getHashCode() { 14 | return "customRenderTemplate"; 15 | } 16 | 17 | function render(event, data) { 18 | if(onRender != null) { 19 | onRender(data); 20 | } 21 | } 22 | 23 | return { 24 | template: template, 25 | getHashCode: getHashCode, 26 | render: render 27 | }; 28 | }; 29 | 30 | -------------------------------------------------------------------------------- /src/templates/html/LabelAnnotationTemplate.js: -------------------------------------------------------------------------------- 1 | export default function LabelAnnotationTemplate() { 2 | var _template = ["div", 3 | { 4 | "class": ["bp-item", "bp-label-annotation"] 5 | } 6 | ]; 7 | 8 | function template() { 9 | return _template; 10 | } 11 | 12 | function getHashCode() { 13 | return "defaultLabelAnnotationTemplate"; 14 | } 15 | 16 | function render(event, data) { 17 | var itemConfig = data.context; 18 | data.element.innerHTML = itemConfig.title; 19 | } 20 | 21 | return { 22 | template: template, 23 | getHashCode: getHashCode, 24 | render: render 25 | }; 26 | }; -------------------------------------------------------------------------------- /apireference.json: -------------------------------------------------------------------------------- 1 | { 2 | "destination": "apireference/", 3 | "source": "./src/index.js", 4 | "orgdiagram.md": [ 5 | "OrgConfig", 6 | "OrgItemConfig", 7 | "OrgEventArgs" 8 | ], 9 | "famdiagram.md": [ 10 | "FamConfig", 11 | "FamItemConfig", 12 | "FamEventArgs" 13 | ], 14 | "auxiliary.md": [ 15 | "ConnectorAnnotationControl", 16 | "ConnectorAnnotationControlConfig", 17 | "ShapeAnnotationControl", 18 | "ShapeAnnotationControlConfig", 19 | "CalloutAnnotationControl", 20 | "CalloutAnnotationControlConfig", 21 | "RotatedTextControl", 22 | "RotatedTextControlConfig" 23 | ] 24 | } 25 | -------------------------------------------------------------------------------- /src/tasks/templates/CheckBoxTemplateTask.js: -------------------------------------------------------------------------------- 1 | export default function CheckBoxTemplateTask(itemsSizesOptionTask, templates) { 2 | var _data = { 3 | template: null 4 | }; 5 | 6 | function process() { 7 | _data.template = null; 8 | return true; 9 | } 10 | 11 | function getTemplate() { 12 | var options; 13 | if (_data.template == null) { 14 | options = itemsSizesOptionTask.getOptions(); 15 | _data.template = new templates.CheckBoxTemplate(options.selectCheckBoxLabel); 16 | } 17 | return _data.template; 18 | } 19 | 20 | return { 21 | process: process, 22 | getTemplate: getTemplate 23 | }; 24 | }; -------------------------------------------------------------------------------- /src/templates/pdf/EndPointTemplate.js: -------------------------------------------------------------------------------- 1 | export default function EndPointTemplate(options) { 2 | 3 | function template() { 4 | return {}; 5 | } 6 | 7 | function getHashCode() { 8 | return 0; 9 | } 10 | 11 | function render(doc, position, _data) { 12 | doc.save(); 13 | 14 | /* border */ 15 | doc.roundedRect(position.x, position.y, position.width, position.height, options.endPointCornerRadius) 16 | .lineWidth(0) 17 | .fill(options.endPointFillColor); 18 | 19 | doc.restore(); 20 | } 21 | 22 | return { 23 | template: template, 24 | getHashCode: getHashCode, 25 | render: render 26 | }; 27 | }; -------------------------------------------------------------------------------- /src/tasks/options/FamVisualTreeOptionTask.js: -------------------------------------------------------------------------------- 1 | import { ChildrenPlacementType, HorizontalAlignmentType } from '../../enums'; 2 | export default function FamVisualTreeOptionTask(optionsTask) { 3 | var _data = { 4 | leavesPlacementType: ChildrenPlacementType.Horizontal, 5 | childrenPlacementType: ChildrenPlacementType.Horizontal, 6 | maximumColumnsInMatrix: 6, 7 | horizontalAlignment: HorizontalAlignmentType.Center 8 | }; 9 | 10 | function process() { 11 | return false; 12 | } 13 | 14 | function getOptions() { 15 | return _data; 16 | } 17 | 18 | return { 19 | process: process, 20 | getOptions: getOptions 21 | }; 22 | }; -------------------------------------------------------------------------------- /src/templates/html/ButtonsTemplate.js: -------------------------------------------------------------------------------- 1 | export default function ButtonsTemplate(options) { 2 | var _template = ["div", { 3 | "style": { 4 | position: "absolute" 5 | } 6 | } 7 | ]; 8 | 9 | function template() { 10 | return _template; 11 | } 12 | 13 | function getHashCode() { 14 | return "defaultButtonsTemplate"; 15 | } 16 | 17 | function render(event, data) { 18 | var onButtonsRender = data.onButtonsRender; 19 | if(onButtonsRender != null) { 20 | onButtonsRender(data); 21 | } 22 | } 23 | 24 | return { 25 | template: template, 26 | getHashCode: getHashCode, 27 | render: render 28 | }; 29 | }; 30 | 31 | -------------------------------------------------------------------------------- /samples/javascript.controls/common/Caption.js: -------------------------------------------------------------------------------- 1 | import { ControlType } from './enums'; 2 | 3 | export function CaptionConfig(caption, isBig, id) { 4 | this.controlType = ControlType.Caption; 5 | this.caption = caption; 6 | this.isBig = isBig; 7 | this.id = id; 8 | }; 9 | 10 | export function CaptionRender() { 11 | this.render = function (config, namespace) { 12 | var tagName = config.isBig ? "h5" : "p"; 13 | var element = [tagName]; 14 | if (config.id !== "") { 15 | element.push({ 16 | id: namespace + config.id 17 | }); 18 | } 19 | element.push(config.caption); 20 | 21 | return element; 22 | }; 23 | }; -------------------------------------------------------------------------------- /src/templates/pdf/UserTemplate.js: -------------------------------------------------------------------------------- 1 | import ItemTemplate from './ItemTemplate'; 2 | 3 | export default function UserTemplate(options, itemTemplateConfig, onRender) { 4 | function template() { 5 | return {}; 6 | } 7 | 8 | function getHashCode() { 9 | return 0; 10 | } 11 | 12 | function render(doc, position, data) { 13 | if (onRender != null) { 14 | onRender(doc, position, data); 15 | } else { 16 | var itemTemplate = ItemTemplate(options, itemTemplateConfig); 17 | itemTemplate.render(doc, position, data); 18 | } 19 | } 20 | 21 | return { 22 | template: template, 23 | getHashCode: getHashCode, 24 | render: render 25 | }; 26 | }; -------------------------------------------------------------------------------- /src/templates/pdf/CursorTemplate.js: -------------------------------------------------------------------------------- 1 | export default function CursorTemplate(options, itemTemplateConfig) { 2 | var _config = itemTemplateConfig; 3 | 4 | function template() { 5 | return {}; 6 | } 7 | 8 | function getHashCode() { 9 | return 0; 10 | } 11 | 12 | function render(doc, position, data) { 13 | doc.save(); 14 | 15 | /* item border */ 16 | doc.roundedRect(position.x, position.y, position.width, position.height, 4) 17 | .lineWidth(_config.cursorBorderWidth) 18 | .stroke('#fbd850'); 19 | 20 | doc.restore(); 21 | } 22 | 23 | return { 24 | template: template, 25 | getHashCode: getHashCode, 26 | render: render 27 | }; 28 | }; -------------------------------------------------------------------------------- /src/templates/pdf/HighlightTemplate.js: -------------------------------------------------------------------------------- 1 | export default function HighlightTemplate(options, itemTemplateConfig) { 2 | var _config = itemTemplateConfig; 3 | 4 | function template() { 5 | return {}; 6 | } 7 | 8 | function getHashCode() { 9 | return 0; 10 | } 11 | 12 | function render(doc, position, _data) { 13 | doc.save(); 14 | 15 | /* border */ 16 | doc.roundedRect(position.x, position.y, position.width, position.height, 4) 17 | .lineWidth(_config.highlightBorderWidth) 18 | .stroke('#fbcb09'); 19 | 20 | doc.restore(); 21 | } 22 | 23 | return { 24 | template: template, 25 | getHashCode: getHashCode, 26 | render: render 27 | }; 28 | }; -------------------------------------------------------------------------------- /src/templates/pdf/LabelAnnotationTemplate.js: -------------------------------------------------------------------------------- 1 | export default function LabelAnnotationTemplate() { 2 | function template() { 3 | return {}; 4 | } 5 | 6 | function getHashCode() { 7 | return 0; 8 | } 9 | 10 | function render(doc, position, data) { 11 | var itemConfig = data.context; 12 | 13 | doc.save(); 14 | 15 | doc.font('Helvetica', 12) 16 | .text(itemConfig.title, position.x, position.y, { 17 | width: position.width, 18 | height: position.height, 19 | align: 'center' 20 | }); 21 | 22 | doc.restore(); 23 | } 24 | 25 | return { 26 | template: template, 27 | getHashCode: getHashCode, 28 | render: render 29 | }; 30 | }; -------------------------------------------------------------------------------- /src/models/EdgeItem.js: -------------------------------------------------------------------------------- 1 | export default function EdgeItem(key0, val0, key1, val1) { 2 | this.values = [val0, val1]; 3 | this[key0] = 0; 4 | this[key1] = 1; 5 | }; 6 | 7 | EdgeItem.prototype.getNear = function (key) { 8 | return this.values[this[key]]; 9 | }; 10 | 11 | EdgeItem.prototype.getFar = function (key) { 12 | return this.values[Math.abs(this[key] - 1)]; 13 | }; 14 | 15 | EdgeItem.prototype.setNear = function (key, value) { 16 | this.values[this[key]] = value; 17 | }; 18 | 19 | EdgeItem.prototype.setFar = function (key, value) { 20 | this.values[Math.abs(this[key] - 1)] = value; 21 | }; 22 | 23 | EdgeItem.prototype.toString = function () { 24 | return this.parent + ',' + this.child; 25 | }; -------------------------------------------------------------------------------- /samples/ZoomWithCSSScaleTransform.md: -------------------------------------------------------------------------------- 1 | # Zoom using CSS scale transform 2 | 3 | The control supports scale option setting CSS scale transform of the control's content. It scales everything except scroll bars and correctly handles mouse event coordinates. 4 | 5 | CSS scale transform produces unreadable text and corrupts graphics lines in some desktop browsers. It looks good on mobile devices. We suggest testing your diagram on various devices to ensure a consistent user experience. 6 | 7 | Use custom item templates for various zoom levels, so your application would be responsive regardless of available screen space and scale. 8 | 9 | [JavaScript](javascript.controls/CaseZoomWithCSSScaleTransform.html) 10 | -------------------------------------------------------------------------------- /src/graphics/structs/Label.js: -------------------------------------------------------------------------------- 1 | import Rect from './Rect'; 2 | import { LabelType, TextOrientationType, HorizontalAlignmentType, VerticalAlignmentType } from '../../enums'; 3 | 4 | export default function Label() { 5 | this.text = null; 6 | this.position = null; // Rect 7 | this.weight = 0; 8 | 9 | this.isActive = true; 10 | this.labelType = LabelType.Regular; 11 | 12 | this.labelOrientation = TextOrientationType.Horizontal; 13 | this.horizontalAlignmentType = HorizontalAlignmentType.Center; 14 | this.verticalAlignmentType = VerticalAlignmentType.Bottom; 15 | 16 | this.parent = Rect.prototype; 17 | this.parent.constructor.apply(this, arguments); 18 | }; 19 | 20 | Label.prototype = new Rect(); 21 | -------------------------------------------------------------------------------- /samples/HighlightTemplate.md: -------------------------------------------------------------------------------- 1 | # Highlight template 2 | 3 | The component can customize the highlight frame as well. By default, it is a regular `div` element sized and placed into position, having custom properties. Use the `highlightTemplate` property of the `TemplateConfig` configuration class. The control calls the `onHighlightRender` event every time it renders the highlight template. You get the reference to the DOM element and the highlighted item of the diagram to populate them with context specific data. See the example and reference for details about event arguments. 4 | 5 | [JavaScript](javascript.controls/CaseHighlightTemplate.html) 6 | 7 |  -------------------------------------------------------------------------------- /src/tasks/transformations/PaletteManagerTask.js: -------------------------------------------------------------------------------- 1 | import PaletteManager from '../../graphics/structs/PaletteManager'; 2 | 3 | export default function PaletteManagerTask(connectorsOptionTask, linePaletteOptionTask) { 4 | var _paletteManager; 5 | 6 | function process() { 7 | var linesPalette = []; 8 | if (linePaletteOptionTask != null) { 9 | linesPalette = linePaletteOptionTask.getOptions().linesPalette; 10 | } 11 | _paletteManager = new PaletteManager(connectorsOptionTask.getOptions(), linesPalette); 12 | 13 | return true; 14 | } 15 | 16 | function getPaletteManager() { 17 | return _paletteManager; 18 | } 19 | 20 | return { 21 | process: process, 22 | getPaletteManager: getPaletteManager 23 | }; 24 | }; -------------------------------------------------------------------------------- /src/tasks/transformations/selection/HighlightItemTask.js: -------------------------------------------------------------------------------- 1 | export default function HighlightItemTask(highlightItemOptionTask, activeItemsTask) { 2 | var _data = { 3 | highlightTreeItemId: null 4 | }; 5 | 6 | function process() { 7 | var treeItemId = highlightItemOptionTask.getHighlightItem(), 8 | activeItems = (activeItemsTask != null) ? activeItemsTask.getActiveItems() : {}; 9 | 10 | _data.highlightTreeItemId = (treeItemId != null && activeItems.hasOwnProperty(treeItemId)) ? treeItemId : null; 11 | 12 | return true; 13 | } 14 | 15 | function getHighlightTreeItem() { 16 | return _data.highlightTreeItemId; 17 | } 18 | 19 | return { 20 | process: process, 21 | getHighlightTreeItem: getHighlightTreeItem 22 | }; 23 | }; -------------------------------------------------------------------------------- /src/templates/pdf/AnnotationLabelTemplate.js: -------------------------------------------------------------------------------- 1 | /* jshint latedef: true, unused: false */ 2 | export default function AnnotationLabelTemplate() { 3 | function template() { 4 | return {}; 5 | } 6 | 7 | function getHashCode() { 8 | return 0; 9 | } 10 | 11 | function render(doc, position, data) { 12 | var annotationConfig = data.context; 13 | 14 | doc.save(); 15 | 16 | doc.font('Helvetica', 12) 17 | .text(annotationConfig.label, position.x, position.y, { 18 | width: position.width, 19 | height: position.height, 20 | align: 'center' 21 | }); 22 | 23 | doc.restore(); 24 | } 25 | 26 | return { 27 | template: template, 28 | getHashCode: getHashCode, 29 | render: render 30 | }; 31 | }; -------------------------------------------------------------------------------- /src/templates/html/HighlightTemplate.js: -------------------------------------------------------------------------------- 1 | export default function HighlightTemplate(options, itemTemplateConfig) { 2 | var _template = create(itemTemplateConfig); 3 | 4 | function create(config) { 5 | return ["div", 6 | { 7 | "style": { 8 | "borderWidth": config.highlightBorderWidth + "px" 9 | }, 10 | "class": ["bp-item", "bp-corner-all", "bp-highlight-frame"] 11 | } 12 | ]; 13 | } 14 | 15 | function template() { 16 | return _template; 17 | } 18 | 19 | function getHashCode() { 20 | return "defaultHighlightTemplate"; 21 | } 22 | 23 | function render(event, data) { 24 | 25 | } 26 | 27 | return { 28 | template: template, 29 | getHashCode: getHashCode, 30 | render: render 31 | }; 32 | }; -------------------------------------------------------------------------------- /src/graphics/createGraphics.js: -------------------------------------------------------------------------------- 1 | import SvgGraphics from './SvgGraphics'; 2 | 3 | /** 4 | * Checks if browser is Chrome. 5 | * 6 | * @returns {boolean} Returns true if browser is chrome. 7 | * @ignore 8 | */ 9 | export function isChrome () { 10 | if (navigator != null) { //ignore jslint 11 | return /Chrome/.test(navigator.userAgent) && /Google Inc/.test(navigator.vendor); //ignore jslint 12 | } 13 | return false; 14 | }; 15 | 16 | /** 17 | * Creates graphics object for chart rendering 18 | * 19 | * @param {object} element Reference to dom element the graphics object is created for 20 | * @returns {Graphics} Returns graphics object 21 | * @ignore 22 | */ 23 | export default function createGraphics(element) { 24 | return new SvgGraphics(element); 25 | }; -------------------------------------------------------------------------------- /src/templates/html/GroupTitleTemplate.test.js: -------------------------------------------------------------------------------- 1 | import GroupTitleTemplate from './GroupTitleTemplate'; 2 | import { TextOrientationType, VerticalAlignmentType, Colors, HorizontalAlignmentType } from '../../enums'; 3 | 4 | test('GroupTitleTemplate', () => { 5 | var options = { 6 | groupTitleOrientation: TextOrientationType.Horizontal, 7 | groupTitleHorizontalAlignment: HorizontalAlignmentType.Center, 8 | groupTitleVerticalAlignment: VerticalAlignmentType.Middle, 9 | groupTitleFontSize: "12px", 10 | groupTitleFontFamily: "Arial", 11 | groupTitleColor: Colors.RoyalBlue, 12 | groupTitleFontWeight: "normal", 13 | groupTitleFontStyle: "normal" 14 | } 15 | expect(new GroupTitleTemplate(options) != null).toBe(true); 16 | }); -------------------------------------------------------------------------------- /src/tasks/renders/offsetResolver/ConnectorAnnotationOffsetResolver.js: -------------------------------------------------------------------------------- 1 | import CollinearVectorBundle from './CollinearVectorBundle'; 2 | 3 | export default function ConnectorAnnotationOffsetResolver() { 4 | var _bundles = {}; 5 | 6 | function getOffset(vector, callback) { 7 | var key = vector.getLineKey(); 8 | 9 | if (!_bundles.hasOwnProperty(key)) { 10 | _bundles[key] = new CollinearVectorBundle(); 11 | } 12 | 13 | _bundles[key].addVector(vector, callback); 14 | } 15 | 16 | function resolve() { 17 | for (var key in _bundles) { 18 | if (_bundles.hasOwnProperty(key)) { 19 | var bundle = _bundles[key]; 20 | bundle.resolve(); 21 | } 22 | } 23 | } 24 | 25 | return { 26 | getOffset: getOffset, 27 | resolve: resolve 28 | }; 29 | }; -------------------------------------------------------------------------------- /src/managers/DependencyManager.js: -------------------------------------------------------------------------------- 1 | export default function DependencyManager() { 2 | var hash = {}; 3 | 4 | function register(key, value) { 5 | hash[key] = value; 6 | 7 | return value; 8 | } 9 | 10 | function resolve() { 11 | var args = [], 12 | deps = arguments[0], 13 | func = arguments[1], 14 | scope = arguments[2] || {}; 15 | return function () { 16 | var a = Array.prototype.slice.call(arguments, 0); 17 | for (var i = 0; i < deps.length; i += 1) { 18 | var d = deps[i]; 19 | args.push(hash.hasOwnProperty(d) && d !== '' ? hash[d] : a.shift()); 20 | } 21 | args = args.concat(a); 22 | return func.apply(scope || {}, args); 23 | }; 24 | } 25 | 26 | return { 27 | register: register, 28 | resolve: resolve 29 | }; 30 | }; -------------------------------------------------------------------------------- /src/tasks/transformations/OrgExtractNestedLayoutsTask.js: -------------------------------------------------------------------------------- 1 | export default function OrgExtractNestedLayoutsTask(extractNestedLayoutsOptionTask, bindFamilyConnectorsTask) { 2 | function process(debug) { 3 | return false; 4 | } 5 | 6 | function getNestedLayoutParentConnectorIds() { 7 | return {}; 8 | } 9 | 10 | function getNestedLayoutBottomConnectorIds() { 11 | return {}; 12 | } 13 | 14 | function getBundles() { 15 | return []; 16 | } 17 | 18 | function getLayouts() { 19 | return {}; 20 | } 21 | 22 | return { 23 | process: process, 24 | getNestedLayoutParentConnectorIds: getNestedLayoutParentConnectorIds, 25 | getNestedLayoutBottomConnectorIds: getNestedLayoutBottomConnectorIds, 26 | getBundles: getBundles, 27 | getLayouts: getLayouts 28 | }; 29 | }; 30 | -------------------------------------------------------------------------------- /src/models/TreeItem.js: -------------------------------------------------------------------------------- 1 | import { Visibility } from '../enums'; 2 | 3 | /* This is model class used to define visual structure of the chart */ 4 | export default function TreeItem() { 5 | /* auto generated internal item id */ 6 | this.id = null; 7 | 8 | /* Visual child id which is supposed to be straight under it */ 9 | this.visualAggregatorId = null; 10 | 11 | this.partners = []; /* nodes connected with bottom line together into one family, family is group of items having common set of children */ 12 | 13 | this.visibility = Visibility.Normal; 14 | 15 | this.actualItemType = null; // ItemType 16 | this.connectorPlacement = 0; // SideFlag 17 | this.gravity = 0; // HorizontalAlignmentType.Center 18 | 19 | /* This value is used to increase space on the left side of the item */ 20 | this.relationDegree = 0; 21 | }; -------------------------------------------------------------------------------- /src/readers/EnumerationReader.js: -------------------------------------------------------------------------------- 1 | export default function EnumerationReader(enumeration, isNullable, defaultValue) { 2 | this.enumeration = enumeration; 3 | this.isNullable = isNullable; 4 | this.defaultValue = defaultValue; 5 | 6 | this.hash = {}; 7 | 8 | /* collect valid enumeration values */ 9 | for (var key in enumeration) { 10 | this.hash[enumeration[key]] = key; 11 | } 12 | }; 13 | 14 | EnumerationReader.prototype.read = function (target, source, path, context) { 15 | var result = null; 16 | 17 | if (source === null || typeof source == "undefined" || !this.hash.hasOwnProperty(source)) { 18 | source = this.isNullable ? null : this.defaultValue; 19 | } 20 | 21 | result = source; 22 | 23 | if (target !== source) { 24 | context.isChanged = true; 25 | } 26 | 27 | return result; 28 | }; 29 | -------------------------------------------------------------------------------- /src/tasks/templates/GroupTitleTemplateTask.js: -------------------------------------------------------------------------------- 1 | export default function GroupTitleTemplateTask(templatesOptionTask, templates) { 2 | var _data = { 3 | template: null 4 | }; 5 | 6 | function process() { 7 | _data.template = null; 8 | return true; 9 | } 10 | 11 | function getTemplate() { 12 | var options; 13 | if (_data.template == null) { 14 | options = templatesOptionTask.getOptions(); 15 | var { onGroupTitleRender } = options; 16 | if(onGroupTitleRender != null) { 17 | _data.template = new templates.CustomRenderTemplate(options, onGroupTitleRender); 18 | } else { 19 | _data.template = new templates.GroupTitleTemplate(options); 20 | } 21 | } 22 | return _data.template; 23 | } 24 | 25 | return { 26 | process: process, 27 | getTemplate: getTemplate 28 | }; 29 | }; -------------------------------------------------------------------------------- /samples/ItemAndGroupTitleColors.md: -------------------------------------------------------------------------------- 1 | # Item & group title colors 2 | 3 | Item's title background color may be used for indicating the group of nodes in the diagram and may vary in a wide range of colors. At the same time, the title font color should always be readable on every background. So taking these considerations into account, the control has two options setting font color for node titles: `itemTitleFirstFontColor` and `itemTitleSecondFontColor`. The control selects the most readable font color using the `highestContrast` function. It returns the highest contrast color from two on the given background color. See functions reference. 4 | 5 | [JavaScript](javascript.controls/CaseItemAndGroupTitleColors.html) 6 | [PDFKit](pdfkit.plugins/ItemAndGroupTitleColors.html) 7 | 8 |  -------------------------------------------------------------------------------- /src/tasks/transformations/familyTransformations/BaseTransformer.js: -------------------------------------------------------------------------------- 1 | export default function BaseTransformer(debug) { 2 | this.debug = debug; 3 | }; 4 | 5 | BaseTransformer.prototype.validate = function (logicalFamily, strongValidate) { 6 | /* test consistency of references in family tree */ 7 | if (!logicalFamily.validate()) { 8 | throw "Family structure failed to pass validation!"; 9 | } 10 | 11 | logicalFamily.loop(this, function (famItemId, famItem) { 12 | 13 | logicalFamily.loopChildren(this, famItemId, function (childid, child, level) { 14 | if (child.level === null || famItem.level === null || (strongValidate ? child.level != famItem.level + 1 : child.level <= famItem.level)) { 15 | throw "Family tree is broken. Children/Parents or levels mismatch!"; 16 | } 17 | return logicalFamily.SKIP; 18 | }); 19 | }); 20 | }; 21 | -------------------------------------------------------------------------------- /src/tasks/transformations/selection/CursorItemTask.js: -------------------------------------------------------------------------------- 1 | export default function CursorItemTask(cursorItemOptionTask, activeItemsTask) { 2 | var _data = { 3 | cursorTreeItemId: null 4 | }; 5 | 6 | function process() { 7 | var treeItemId = cursorItemOptionTask.getCursorItem(), 8 | activeItems = activeItemsTask != null ? activeItemsTask.getActiveItems() : {}; 9 | 10 | _data.cursorTreeItemId = (treeItemId != null && activeItems.hasOwnProperty(treeItemId)) ? treeItemId : null; 11 | 12 | return true; 13 | } 14 | 15 | function getCursorTreeItem() { 16 | return _data.cursorTreeItemId; 17 | } 18 | 19 | function getItems() { 20 | return (_data.cursorTreeItemId != null) ? [_data.cursorTreeItemId] : []; 21 | } 22 | 23 | return { 24 | process: process, 25 | getCursorTreeItem: getCursorTreeItem, 26 | getItems: getItems 27 | }; 28 | }; -------------------------------------------------------------------------------- /src/tasks/transformations/visualTreeBuilder/enums.js: -------------------------------------------------------------------------------- 1 | export var GroupType = { 2 | Items: 0, 3 | Assistants: 1, 4 | RowChildren: 2, 5 | Children: 3 6 | }; 7 | 8 | export var RowType = { 9 | Items: 0, 10 | Advisers: 1, 11 | SubAdvisers: 2, 12 | Assistants: 3, 13 | SubAssistants: 4, 14 | RowChildren: 5, 15 | Children: 6 16 | }; 17 | 18 | export var RowTypeToGroupTypeMap = {}; 19 | RowTypeToGroupTypeMap[RowType.Items] = GroupType.Items; 20 | RowTypeToGroupTypeMap[RowType.Advisers] = GroupType.Items; 21 | RowTypeToGroupTypeMap[RowType.SubAdvisers] = GroupType.Items; 22 | RowTypeToGroupTypeMap[RowType.Assistants] = GroupType.Assistants; 23 | RowTypeToGroupTypeMap[RowType.SubAssistants] = GroupType.Assistants; 24 | RowTypeToGroupTypeMap[RowType.RowChildren] = GroupType.RowChildren; 25 | RowTypeToGroupTypeMap[RowType.Children] = GroupType.Children; -------------------------------------------------------------------------------- /src/events/OrgEventArgs.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @class EventArgs 3 | * 4 | * Context object 5 | */ 6 | export default function OrgEventArgs() { 7 | /** 8 | * Current item 9 | * 10 | * @type {string} 11 | */ 12 | this.oldContext = null; 13 | 14 | /** 15 | * New item 16 | * 17 | * @type {string} 18 | */ 19 | this.context = null; 20 | 21 | /** 22 | * Parent item 23 | * 24 | * @type {string} 25 | * @ignore 26 | */ 27 | this.parentItem = null; 28 | 29 | /** 30 | * Node position on the diagram. 31 | * 32 | * @type {Rect} 33 | */ 34 | this.position = null; 35 | 36 | /** 37 | * Relative object name. 38 | * 39 | * @type {string} 40 | */ 41 | this.name = null; 42 | 43 | /** 44 | * If true cancels subsequent event and layout update. 45 | * 46 | * @type {boolean} 47 | */ 48 | this.cancel = false; 49 | }; -------------------------------------------------------------------------------- /src/tasks/options/HideGrandParentsConnectorsOptionTask.js: -------------------------------------------------------------------------------- 1 | import ValueReader from '../../readers/ValueReader'; 2 | import ObjectReader from '../../readers/ObjectReader'; 3 | 4 | export default function HideGrandParentsConnectorsOptionTask(optionsTask, defaultConfig) { 5 | var _data = {}, 6 | _hash = {}; 7 | 8 | var _dataTemplate = new ObjectReader({ 9 | hideGrandParentsConnectors: new ValueReader(["boolean"], false, defaultConfig.hideGrandParentsConnectors) 10 | }); 11 | 12 | function process() { 13 | var context = { 14 | isChanged: false, 15 | hash: _hash 16 | }; 17 | 18 | _data = _dataTemplate.read(_data, optionsTask.getOptions(), "options", context); 19 | 20 | return context.isChanged; 21 | } 22 | 23 | function getOptions() { 24 | return _data; 25 | } 26 | 27 | return { 28 | process: process, 29 | getOptions: getOptions 30 | }; 31 | }; -------------------------------------------------------------------------------- /src/managers/TaskManager.test.js: -------------------------------------------------------------------------------- 1 | import TaskManager from './TaskManager'; 2 | 3 | test('Task manager processed all dependencies', () => { 4 | var taskManager = TaskManager(); 5 | taskManager.addDependency('options', { value: 12 }); 6 | taskManager.addTask('add', ['options'], function (options) { 7 | var result = 0; 8 | return { 9 | process: function () { result = options.value + 1; return true; }, 10 | getValue: function () { return options.value + 1; } 11 | } 12 | }); 13 | taskManager.addTask('multiply', ['add'], function (add) { 14 | var result = 0; 15 | return { 16 | process: function () { result = add.getValue() * 2; return true; }, 17 | getValue: function () { return result; } 18 | } 19 | }); 20 | 21 | taskManager.process('add', false); 22 | 23 | var result = taskManager.getTask('multiply'); 24 | 25 | expect(result.getValue()).toBe(26); 26 | }); 27 | -------------------------------------------------------------------------------- /src/models/FamilyItem.js: -------------------------------------------------------------------------------- 1 | import { GroupByType } from '../enums'; 2 | 3 | export default function FamilyItem(arg0) { 4 | var property; 5 | 6 | this.id = null; 7 | this.familyId = null; 8 | this.itemConfig = null; 9 | 10 | this.isVisible = true; 11 | this.isActive = true; // item is clickable 12 | this.isLevelNeutral = false; // This option allows to place fake item in between of original item levels 13 | 14 | this.level = null; 15 | this.levelGravity = GroupByType.None; // If item can be moved between its parent and children levels in diagram, this option defines preference 16 | this.hideParentConnection = false; 17 | this.hideChildrenConnection = false; 18 | 19 | switch (arguments.length) { 20 | case 1: 21 | for (property in arg0) { 22 | if (arg0.hasOwnProperty(property)) { 23 | this[property] = arg0[property]; 24 | } 25 | } 26 | break; 27 | } 28 | }; -------------------------------------------------------------------------------- /src/tasks/templates/EndPointTemplateTask.js: -------------------------------------------------------------------------------- 1 | export default function EndPointTemplateTask(endPointsOptionTask /* changes in items update layout anyway */, templates) { 2 | var _data = { 3 | endPointTemplate: null, 4 | }; 5 | 6 | function process() { 7 | _data.template = null; 8 | return false; 9 | } 10 | 11 | function getTemplate() { 12 | var options; 13 | if (_data.endPointTemplate == null) { 14 | options = endPointsOptionTask.getOptions(); 15 | var { onEndPointRender } = options; 16 | if( onEndPointRender != null ) { 17 | _data.endPointTemplate = new templates.CustomRenderTemplate(options, onEndPointRender); 18 | } else { 19 | _data.endPointTemplate = new templates.EndPointTemplate(options); 20 | } 21 | } 22 | return _data.endPointTemplate; 23 | } 24 | 25 | return { 26 | process: process, 27 | getTemplate: getTemplate 28 | }; 29 | }; -------------------------------------------------------------------------------- /src/models/EdgeItem.test.js: -------------------------------------------------------------------------------- 1 | import EdgeItem from './EdgeItem'; 2 | 3 | test("[1]: 1, [2]: 2", () => { 4 | var edge = new EdgeItem(1, 1, 2, 2); 5 | expect(edge.getNear(1)).toBe(1); 6 | expect(edge.getNear(2)).toBe(2); 7 | expect(edge.getFar(1)).toBe(2); 8 | expect(edge.getFar(2)).toBe(1); 9 | }); 10 | 11 | test("setNear, setFar", () => { 12 | var edge = new EdgeItem(1, 1, 2, 2); 13 | edge.setNear(1, 100); 14 | edge.setFar(1, 200); 15 | expect(edge.getNear(1)).toBe(100); 16 | expect(edge.getNear(2)).toBe(200); 17 | expect(edge.getFar(1)).toBe(200); 18 | expect(edge.getFar(2)).toBe(100); 19 | }); 20 | 21 | test("setNear, setFar (2)", () => { 22 | var edge = new EdgeItem(1, 1, 2, 2); 23 | edge.setNear(2, 2000); 24 | edge.setFar(2, 1000); 25 | 26 | expect(edge.getNear(1)).toBe(1000); 27 | expect(edge.getNear(2)).toBe(2000); 28 | expect(edge.getFar(1)).toBe(2000); 29 | expect(edge.getFar(2)).toBe(1000); 30 | }); -------------------------------------------------------------------------------- /src/templates/html/CursorTemplate.js: -------------------------------------------------------------------------------- 1 | export default function CursorTemplate(options, itemTemplateConfig) { 2 | var _template = create(itemTemplateConfig); 3 | 4 | function create(config) { 5 | return ["div", 6 | { 7 | "style": { 8 | width: (config.itemSize.width + config.cursorPadding.left + config.cursorPadding.right) + "px", 9 | height: (config.itemSize.height + config.cursorPadding.top + config.cursorPadding.bottom) + "px", 10 | "borderWidth": config.cursorBorderWidth + "px" 11 | }, 12 | "class": ["bp-item", "bp-corner-all", "bp-cursor-frame"] 13 | } 14 | ]; 15 | } 16 | 17 | function template() { 18 | return _template; 19 | } 20 | 21 | function getHashCode() { 22 | return "defaultCursorTemplate"; 23 | } 24 | 25 | function render(event, data) { 26 | 27 | } 28 | 29 | return { 30 | template: template, 31 | getHashCode: getHashCode, 32 | render: render 33 | }; 34 | }; -------------------------------------------------------------------------------- /src/tasks/options/OrientationOptionTask.js: -------------------------------------------------------------------------------- 1 | import ObjectReader from '../../readers/ObjectReader'; 2 | import EnumerationReader from '../../readers/EnumerationReader'; 3 | import { OrientationType } from '../../enums'; 4 | 5 | 6 | export default function OrientationOptionTask(optionsTask, defaultConfig) { 7 | var _data = {}, 8 | _hash = {}; 9 | 10 | var _dataTemplate = new ObjectReader({ 11 | orientationType: new EnumerationReader(OrientationType, false, defaultConfig.orientationType) 12 | }); 13 | 14 | function process() { 15 | var context = { 16 | isChanged: false, 17 | hash: _hash 18 | }; 19 | 20 | _data = _dataTemplate.read(_data, optionsTask.getOptions(), "options", context); 21 | 22 | return context.isChanged; 23 | } 24 | 25 | function getOptions() { 26 | return _data; 27 | } 28 | 29 | return { 30 | process: process, 31 | getOptions: getOptions, 32 | description: "Checks diagram orientation options." 33 | }; 34 | }; -------------------------------------------------------------------------------- /src/tasks/transformations/UserDefinedNodesOrderTask.js: -------------------------------------------------------------------------------- 1 | import UserDefinedNodesOrder from './familyTransformations/UserDefinedNodesOrder'; 2 | 3 | export default function UserDefinedNodesOrderTask(orderFamilyNodesOptionTask) { 4 | var _data = { 5 | position: null, /* hash[itemid] = position*/ 6 | group: null /* hash[itemid] = root itemid */ 7 | }, 8 | _userDefinedNodesOrder = new UserDefinedNodesOrder(); 9 | 10 | function process() { 11 | var options = orderFamilyNodesOptionTask.getOptions(); 12 | var result = _userDefinedNodesOrder.getUserDefinedPositions(options.items); 13 | 14 | _data.position = result.position; 15 | _data.group = result.group; 16 | 17 | return true; 18 | } 19 | 20 | function getPositions() { 21 | return _data.position; 22 | } 23 | 24 | function getGroups() { 25 | return _data.group; 26 | } 27 | 28 | return { 29 | process: process, 30 | getPositions: getPositions, 31 | getGroups: getGroups 32 | }; 33 | }; -------------------------------------------------------------------------------- /src/events/FamEventArgs.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @class EventArgs 3 | * 4 | * Context object 5 | */ 6 | export default function FamEventArgs() { 7 | /** 8 | * Current item 9 | * 10 | * @type {string} 11 | */ 12 | this.oldContext = null; 13 | 14 | /** 15 | * New item 16 | * 17 | * @type {string} 18 | */ 19 | this.context = null; 20 | 21 | /** 22 | * Parent items 23 | * 24 | * @type {string[]} 25 | * @ignore 26 | */ 27 | this.parentItems = []; 28 | 29 | /** 30 | * Child items 31 | * 32 | * @type {string[]} 33 | * @ignore 34 | */ 35 | this.childrenItems = []; 36 | 37 | 38 | /** 39 | * Node position on the diagram. 40 | * 41 | * @type {Rect} 42 | */ 43 | this.position = null; 44 | 45 | /** 46 | * Relative object name. 47 | * 48 | * @type {string} 49 | */ 50 | this.name = null; 51 | 52 | /** 53 | * If true cancels subsequent event and layout update. 54 | * 55 | * @type {boolean} 56 | */ 57 | this.cancel = false; 58 | }; -------------------------------------------------------------------------------- /src/tasks/options/selection/NeighboursSelectionModeOptionTask.js: -------------------------------------------------------------------------------- 1 | import ObjectReader from '../../../readers/ObjectReader'; 2 | import EnumerationReader from '../../../readers/EnumerationReader'; 3 | import {NeighboursSelectionMode} from '../../../enums'; 4 | 5 | export default function NeighboursSelectionModeOptionTask(optionsTask, defaultConfig) { 6 | var _data = {}; 7 | 8 | var _dataTemplate = new ObjectReader({ 9 | neighboursSelectionMode: new EnumerationReader(NeighboursSelectionMode, false, defaultConfig.neighboursSelectionMode) 10 | }); 11 | 12 | function process() { 13 | var context = { 14 | isChanged: false 15 | }; 16 | 17 | _data = _dataTemplate.read(_data, optionsTask.getOptions(), "options", context); 18 | 19 | return context.isChanged; 20 | } 21 | 22 | function getNeighboursSelectionMode() { 23 | return _data.neighboursSelectionMode; 24 | } 25 | 26 | return { 27 | process: process, 28 | getNeighboursSelectionMode: getNeighboursSelectionMode 29 | }; 30 | }; -------------------------------------------------------------------------------- /src/templates/html/AnnotationLabelTemplate.js: -------------------------------------------------------------------------------- 1 | import JsonML from '../../common/jsonml-html'; 2 | 3 | /* jshint latedef: true, unused: false */ 4 | export default function AnnotationLabelTemplate() { 5 | var _template = ["div", 6 | { 7 | "type": "checkbox", 8 | "name": "checkbox", 9 | "class": ["bp-item", "bp-corner-all", "bp-connector-label"] 10 | } 11 | ]; 12 | 13 | function template() { 14 | return _template; 15 | } 16 | 17 | function getHashCode() { 18 | return "defaultAnnotationLabelTemplate"; 19 | } 20 | 21 | function render(event, data) { 22 | var annotationConfig = data.context; 23 | if (Array.isArray(annotationConfig.label)) { 24 | data.element.innerHTML = ""; 25 | data.element.appendChild(JsonML.toHTML(annotationConfig.label)); 26 | } else { 27 | data.element.innerHTML = annotationConfig.label; 28 | } 29 | } 30 | 31 | return { 32 | template: template, 33 | getHashCode: getHashCode, 34 | render: render 35 | }; 36 | }; -------------------------------------------------------------------------------- /src/tasks/options/ScaleOptionTask.js: -------------------------------------------------------------------------------- 1 | import ValueReader from '../../readers/ValueReader'; 2 | import ObjectReader from '../../readers/ObjectReader'; 3 | 4 | export default function ScaleOptionTask(optionsTask, defaultConfig) { 5 | var _data = {}, 6 | _hash = {}; 7 | 8 | var _dataTemplate = new ObjectReader({ 9 | scale: new ValueReader(["number"], false, defaultConfig.scale), 10 | minimumScale: new ValueReader(["number"], false, defaultConfig.minimumScale), 11 | maximumScale: new ValueReader(["number"], false, defaultConfig.maximumScale) 12 | }); 13 | function process() { 14 | var context = { 15 | isChanged: false, 16 | hash: _hash 17 | }; 18 | 19 | _data = _dataTemplate.read(_data, optionsTask.getOptions(), "options", context); 20 | 21 | return context.isChanged; 22 | } 23 | 24 | function getOptions() { 25 | return _data; 26 | } 27 | 28 | return { 29 | process: process, 30 | getOptions: getOptions, 31 | description: "Checks control scale options." 32 | }; 33 | }; -------------------------------------------------------------------------------- /src/tasks/options/selection/CursorSelectionPathModeOptionTask.js: -------------------------------------------------------------------------------- 1 | import ObjectReader from '../../../readers/ObjectReader'; 2 | import EnumerationReader from '../../../readers/EnumerationReader'; 3 | import { SelectionPathMode } from '../../../enums'; 4 | 5 | export default function CursorSelectionPathModeOptionTask(optionsTask, defaultConfig) { 6 | var _data = {}; 7 | 8 | var _dataTemplate = new ObjectReader({ 9 | selectionPathMode: new EnumerationReader(SelectionPathMode, false, defaultConfig.selectionPathMode) 10 | }); 11 | 12 | function process() { 13 | var context = { 14 | isChanged: false 15 | }; 16 | 17 | _data = _dataTemplate.read(_data, optionsTask.getOptions(), "options", context); 18 | 19 | return context.isChanged; 20 | } 21 | 22 | function getSelectionPathMode() { 23 | return _data.selectionPathMode; 24 | } 25 | 26 | return { 27 | process: process, 28 | getSelectionPathMode: getSelectionPathMode, 29 | description: "Checks cursor selection path option." 30 | }; 31 | }; -------------------------------------------------------------------------------- /src/tasks/layout/CurrentScrollPositionTask.js: -------------------------------------------------------------------------------- 1 | import ObjectReader from '../../readers/ObjectReader'; 2 | import ValueReader from '../../readers/ValueReader'; 3 | 4 | export default function CurrentScrollPositionTask(layoutOptionsTask) { 5 | var _data = { 6 | placeholderOffset: null 7 | }, 8 | _hash = {}, 9 | _dataTemplate = new ObjectReader({ 10 | placeholderOffset: new ObjectReader({ 11 | x: new ValueReader(["number"], true), 12 | y: new ValueReader(["number"], true) 13 | }, true) 14 | }); 15 | 16 | function process() { 17 | var context = { 18 | isChanged: false, 19 | hash: _hash 20 | }, 21 | layoutOptions = layoutOptionsTask.getOptions(); 22 | _data = _dataTemplate.read(_data, layoutOptions, "layout", context); 23 | 24 | return context.isChanged; 25 | } 26 | 27 | function getPlaceholderOffset() { 28 | return _data.placeholderOffset; 29 | } 30 | 31 | return { 32 | process: process, 33 | getPlaceholderOffset: getPlaceholderOffset 34 | }; 35 | }; -------------------------------------------------------------------------------- /src/tasks/options/NormalizeOptionTask.js: -------------------------------------------------------------------------------- 1 | import ValueReader from '../../readers/ValueReader'; 2 | import ObjectReader from '../../readers/ObjectReader'; 3 | import EnumerationReader from '../../readers/EnumerationReader'; 4 | import { GroupByType } from '../../enums'; 5 | 6 | export default function NormalizeOptionTask(optionsTask, defaultConfig) { 7 | var _data = {}, 8 | _hash = {}; 9 | 10 | var _dataTemplate = new ObjectReader({ 11 | groupByType: new EnumerationReader(GroupByType, false, defaultConfig.groupByType), 12 | alignBylevels: new ValueReader(["boolean"], false, defaultConfig.alignBylevels) 13 | }); 14 | 15 | function process() { 16 | var context = { 17 | isChanged: false, 18 | hash: _hash 19 | }; 20 | 21 | _data = _dataTemplate.read(_data, optionsTask.getOptions(), "options", context); 22 | 23 | return context.isChanged; 24 | } 25 | 26 | function getOptions() { 27 | return _data; 28 | } 29 | 30 | return { 31 | process: process, 32 | getOptions: getOptions 33 | }; 34 | }; -------------------------------------------------------------------------------- /src/templates/html/EndPointTemplate.js: -------------------------------------------------------------------------------- 1 | export default function EndPointTemplate(options) { 2 | var _template = create(options); 3 | 4 | function create(options) { 5 | var radius = options.endPointCornerRadius; 6 | return ["div", 7 | { 8 | "style": { 9 | "MozBorderRadius": radius + "px", 10 | "WebkitBorderRadius": radius + "px", 11 | "-khtml-border-radius": radius + "px", 12 | "borderRadius": radius + "px", 13 | "background": options.endPointFillColor, 14 | "opacity": options.endPointOpacity, 15 | "border": "0px" 16 | }, 17 | "class": ["bp-item", "bp-endpoint-dot-frame"] 18 | } 19 | ]; 20 | } 21 | 22 | function template() { 23 | return _template; 24 | } 25 | 26 | function getHashCode() { 27 | return "defaultEndPointTemplate"; 28 | } 29 | 30 | function render(event, data) { 31 | 32 | } 33 | 34 | return { 35 | template: template, 36 | getHashCode: getHashCode, 37 | render: render 38 | }; 39 | }; -------------------------------------------------------------------------------- /src/events/RenderEventArgs.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @class RenderEventArgs 3 | * @classdesc The render event arguments contains parameters of rendering callback function 4 | */ 5 | export default function RenderEventArgs() { 6 | /** 7 | * Node id 8 | * @type {string} 9 | */ 10 | this.id = null; 11 | 12 | /** 13 | * Reference to DOM element. 14 | * @type {object} 15 | */ 16 | this.element = null; 17 | 18 | /** 19 | * Context object of the node 20 | * @type {object} 21 | */ 22 | this.context = null; 23 | 24 | /** 25 | * Node template name 26 | * @type {string} 27 | */ 28 | this.templateName = null; 29 | 30 | /** 31 | * This option indicates current template state. 32 | * @type {RenderingMode} 33 | */ 34 | this.renderingMode = null; 35 | 36 | /** 37 | * The rendered item is current diagram cursor item 38 | * @type {boolean} 39 | */ 40 | this.isCursor = false; 41 | 42 | /** 43 | * The rendered item is selected 44 | * @type {boolean} 45 | */ 46 | this.isSelected = false; 47 | }; -------------------------------------------------------------------------------- /src/tasks/options/selection/SelectedItemsOptionTask.js: -------------------------------------------------------------------------------- 1 | import ValueReader from '../../../readers/ValueReader'; 2 | import ObjectReader from '../../../readers/ObjectReader'; 3 | import ArrayReader from '../../../readers/ArrayReader'; 4 | 5 | export default function SelectedItemsOptionTask(optionsTask) { 6 | var _data = {}, 7 | _hash = {}; 8 | 9 | var _dataTemplate = new ObjectReader({ 10 | selectedItems: new ArrayReader( 11 | new ValueReader(["string", "number"], true), 12 | true 13 | ) 14 | }); 15 | 16 | function process() { 17 | var context = { 18 | isChanged: false, 19 | hash: _hash 20 | }, 21 | options = optionsTask.getOptions(); 22 | 23 | _data = _dataTemplate.read(_data, options, "options", context); 24 | return context.isChanged; 25 | } 26 | 27 | function getSelectedItems() { 28 | return _data.selectedItems; 29 | } 30 | 31 | return { 32 | process: process, 33 | getSelectedItems: getSelectedItems, 34 | description: "Checks user selected items option." 35 | }; 36 | }; -------------------------------------------------------------------------------- /src/tasks/transformations/visualTreeBuilder/NodeTypeSorter.js: -------------------------------------------------------------------------------- 1 | import { ItemType } from "../../../enums"; 2 | 3 | function NodeTypeSorter() { 4 | var _rows = []; 5 | 6 | function getRow(itemType, index) { 7 | return (_rows[itemType] || [])[index || 0] || []; 8 | } 9 | 10 | function getRows(itemType) { 11 | return _rows[itemType] || []; 12 | } 13 | 14 | function addChild(itemType, levelOffset, orgItem) { 15 | switch (itemType) { 16 | case ItemType.SubAssistant: 17 | case ItemType.Assistant: 18 | levelOffset = levelOffset < 0 || levelOffset == null ? 0 : levelOffset; 19 | break; 20 | default: 21 | levelOffset = 0; 22 | break; 23 | } 24 | _rows[itemType] = _rows[itemType] || []; 25 | var groups = _rows[itemType]; 26 | groups[levelOffset] = groups[levelOffset] || []; 27 | groups[levelOffset].push(orgItem); 28 | } 29 | 30 | return { 31 | addChild: addChild, 32 | getRow: getRow, 33 | getRows: getRows, 34 | }; 35 | } 36 | 37 | export default NodeTypeSorter; 38 | -------------------------------------------------------------------------------- /samples/CrossBranchAlignment.md: -------------------------------------------------------------------------------- 1 | # Cross-Branch children alignment 2 | In the Organizational Chart layout, the number of rows occupied by the immediate children depends on the number of assistants, advisers, and levels of children of the node. So nodes at the same logical level in the organizational chart hierarchy require visual alignment during visualization. 3 | As expected, the control aligns regular horizontally placed children across branches of the hierarchy. But we support the alignment of Assistants, SubAssistants, Advisers, and SubAdvisers hierarchies and child nodes in vertical and matrix formations across departments. 4 | The following options control cross-branch nodes alignment: 5 | * `alignBranches` - property enables alignment 6 | * `placeAdvisersAboveChildren` - if this property is disabled, then advisers' children are placed at the same level and aligned to the children of the parent's node. 7 | 8 | [JavaScript](javascript.controls/CaseCrossBranchAlignment.html) 9 | 10 |  11 | -------------------------------------------------------------------------------- /src/graphics/structs/Matrix.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @class Matrix 3 | * @classdesc Square matrix having 2 rows and 2 columns. 4 | * 5 | * @param {Matrix} arg0 Matrix to clone 6 | * 7 | * @param {number} arg0 A1 - top left. 8 | * @param {number} arg1 B1 - top right. 9 | * @param {number} arg2 A2 - bottom left. 10 | * @param {number} arg3 B2 - bottom right. 11 | */ 12 | export default function Matrix(arg0, arg1, arg2, arg3) { 13 | 14 | this.a1 = null; 15 | this.b1 = null; 16 | this.a2 = null; 17 | this.b2 = null; 18 | 19 | switch (arguments.length) { 20 | case 1: 21 | this.a1 = arg0.a1; 22 | this.b1 = arg0.b1; 23 | this.a2 = arg0.a2; 24 | this.b2 = arg0.b2; 25 | break; 26 | case 4: 27 | this.a1 = arg0; 28 | this.b1 = arg1; 29 | this.a2 = arg2; 30 | this.b2 = arg3; 31 | break; 32 | default: 33 | break; 34 | } 35 | }; 36 | 37 | /** 38 | * Finds matrix determinant 39 | * 40 | * @returns {number} Returns matrix determinant 41 | */ 42 | Matrix.prototype.determinant = function () { 43 | return this.a1 * this.b2 - this.b1 * this.a2; 44 | }; -------------------------------------------------------------------------------- /src/tasks/transformations/selection/OrgCursorNeighboursTask.js: -------------------------------------------------------------------------------- 1 | import { Visibility } from '../../../enums'; 2 | 3 | export default function OrgCursorNeighboursTask(cursorItemTask, navigationFamilyTask) { 4 | var _data = { 5 | items: [] 6 | }; 7 | 8 | function process() { 9 | var navigationFamily = navigationFamilyTask.getLogicalFamily(), 10 | cursorTreeItemId = cursorItemTask.getCursorTreeItem(); 11 | 12 | _data.items = getCursorNeighbours(cursorTreeItemId, navigationFamily); 13 | 14 | return true; 15 | } 16 | 17 | function getCursorNeighbours(cursorTreeItemId, navigationFamily) { 18 | var result = []; 19 | if (cursorTreeItemId !== null) { 20 | navigationFamily.loopNeighbours(this, cursorTreeItemId, function (treeItemId, treeItem, distance) { 21 | if (treeItem.isVisible) { 22 | result.push(treeItemId); 23 | } 24 | return true; 25 | }); 26 | } 27 | return result; 28 | } 29 | 30 | function getItems() { 31 | return _data.items; 32 | } 33 | 34 | return { 35 | process: process, 36 | getItems: getItems 37 | }; 38 | }; -------------------------------------------------------------------------------- /src/models/Slot.js: -------------------------------------------------------------------------------- 1 | export default function Slot(itemid) { 2 | this.itemId = itemid; /* if itemId is null then this slot is empty */ 3 | this.position = null; 4 | this.balance = 0; 5 | 6 | this.left = {}; /* total number of children at the level on the left side of this slot */ 7 | this.right = {}; /* total number of children at the level on the right side of this slot */ 8 | this.crossings = {}; /* number of connections crossing this slot from side to side at the level */ 9 | }; 10 | 11 | Slot.prototype.clone = function (itemid) { 12 | var result = new Slot(itemid), 13 | level; 14 | 15 | for (level in this.left) { 16 | if (this.left.hasOwnProperty(level)) { 17 | result.left[level] = this.left[level]; 18 | } 19 | } 20 | for (level in this.right) { 21 | if (this.right.hasOwnProperty(level)) { 22 | result.right[level] = this.right[level]; 23 | } 24 | } 25 | for (level in this.crossings) { 26 | if (this.crossings.hasOwnProperty(level)) { 27 | result.crossings[level] = this.crossings[level]; 28 | } 29 | } 30 | 31 | result.itemid = itemid; 32 | return result; 33 | }; -------------------------------------------------------------------------------- /src/readers/ObjectReader.js: -------------------------------------------------------------------------------- 1 | import { isObject } from '../common'; 2 | 3 | export default function ObjectReader(dataTemplate, isNullable, defaultValue) { 4 | this.dataTemplate = dataTemplate; 5 | this.isNullable = isNullable; 6 | this.defaultValue = defaultValue; 7 | }; 8 | 9 | ObjectReader.prototype.read = function (target, source, path, context) { 10 | var result = null, 11 | isTargetObject = isObject(target), 12 | property, 13 | propertyDataTemplate; 14 | 15 | if (!source) { 16 | source = this.isNullable ? null : this.defaultValue; 17 | } 18 | 19 | if (isObject(source)) { 20 | result = {}; 21 | 22 | for (property in this.dataTemplate) { 23 | if (this.dataTemplate.hasOwnProperty(property)) { 24 | propertyDataTemplate = this.dataTemplate[property]; 25 | 26 | result[property] = propertyDataTemplate.read(isTargetObject ? target[property] : null, source[property], path + "-" + property, context); 27 | } 28 | } 29 | } else { 30 | result = source; 31 | 32 | if (target !== source) { 33 | context.isChanged = true; 34 | } 35 | } 36 | return result; 37 | }; -------------------------------------------------------------------------------- /src/graphics/structs/LineSegment.js: -------------------------------------------------------------------------------- 1 | import Point from './Point'; 2 | import MoveSegment from './MoveSegment'; 3 | import { SegmentType } from '../../enums'; 4 | 5 | export default function LineSegment() { 6 | this.parent = MoveSegment.prototype; 7 | this.parent.constructor.apply(this, arguments); 8 | 9 | this.segmentType = SegmentType.Line; 10 | }; 11 | 12 | LineSegment.prototype = new MoveSegment(); 13 | 14 | LineSegment.prototype.clone = function () { 15 | return new LineSegment(this); 16 | }; 17 | 18 | LineSegment.prototype.trim = function (prevEndPoint, offset) { 19 | var endPoint = this.offsetPoint(this, prevEndPoint, offset); 20 | this.x = endPoint.x; 21 | this.y = endPoint.y; 22 | 23 | return this; 24 | }; 25 | 26 | LineSegment.prototype.offsetPoint = function (first, second, offset) { 27 | var result = null, 28 | distance = first.distanceTo(second); 29 | 30 | if (distance === 0 || offset === 0) { 31 | result = new Point(first); 32 | } else { 33 | result = new Point(first.x + (second.x - first.x) / distance * offset, first.y + (second.y - first.y) / distance * offset); 34 | } 35 | return result; 36 | }; -------------------------------------------------------------------------------- /src/templates/html/LevelBackgroundTemplate.js: -------------------------------------------------------------------------------- 1 | import JsonML from '../../common/jsonml-html'; 2 | import { getBorderStyle } from '../../graphics/EnumValues'; 3 | 4 | export default function LevelBackgroundTemplate(options, levelAnnotationConfig) { 5 | var _template = create(levelAnnotationConfig); 6 | 7 | function create(config) { 8 | return ["div"]; 9 | } 10 | 11 | function template() { 12 | return _template; 13 | } 14 | 15 | function getHashCode() { 16 | return "levelAnnotationBackgroundTemplate"; 17 | } 18 | 19 | function render(event, data) { 20 | var annotationConfig = data.context; 21 | var style = { 22 | opacity: annotationConfig.opacity, 23 | borderColor: annotationConfig.borderColor, 24 | backgroundColor: annotationConfig.fillColor, 25 | borderWidth: annotationConfig.lineWidth.toString(), 26 | borderStyle: getBorderStyle(annotationConfig.lineType) 27 | } 28 | var container = data.element; 29 | JsonML.applyStyles(container, style); 30 | } 31 | 32 | return { 33 | template: template, 34 | getHashCode: getHashCode, 35 | render: render 36 | }; 37 | }; -------------------------------------------------------------------------------- /src/graphics/structs/Size.test.js: -------------------------------------------------------------------------------- 1 | import Size from './Size'; 2 | import Thickness from './Thickness'; 3 | 4 | test('Size - Square size', () => { 5 | var size = new Size(10, 20); 6 | 7 | expect(size.space()).toBe(200); 8 | }); 9 | 10 | test('Size - Size conversion to width and hight CSS properties', () => { 11 | var size = new Size(10, 20); 12 | 13 | expect(size.getCSS()).toEqual({"width": "10px", "height": "20px"}); 14 | }); 15 | 16 | test('Size - Maximum size', () => { 17 | var size1 = new Size(10, 40); 18 | var size2 = new Size(50, 30); 19 | size1.maxSize(size2); 20 | 21 | expect(size1.width).toBe(50); 22 | expect(size1.height).toBe(40); 23 | }); 24 | 25 | test('Size - Added padding', () => { 26 | var size1 = new Size(10, 40); 27 | var thickness = new Thickness(1, 2, 3, 4); 28 | size1.addThickness(thickness); 29 | 30 | expect(size1.width).toBe(14); 31 | expect(size1.height).toBe(46); 32 | }); 33 | 34 | test('Size - Removed padding', () => { 35 | var size1 = new Size(10, 40); 36 | var thickness = new Thickness(1, 2, 3, 4); 37 | size1.removeThickness(thickness); 38 | 39 | expect(size1.width).toBe(6); 40 | expect(size1.height).toBe(34); 41 | }); 42 | -------------------------------------------------------------------------------- /src/graphics/structs/MoveSegment.js: -------------------------------------------------------------------------------- 1 | import Point from './Point'; 2 | import { SegmentType } from '../../enums'; 3 | 4 | export default function MoveSegment() { 5 | this.parent = Point.prototype; 6 | this.parent.constructor.apply(this, arguments); 7 | this.segmentType = SegmentType.Move; 8 | }; 9 | 10 | MoveSegment.prototype = new Point(); 11 | 12 | MoveSegment.prototype.clone = function () { 13 | return new MoveSegment(this); 14 | }; 15 | 16 | MoveSegment.prototype.loop = function (thisArg, onItem) { 17 | if (onItem != null) { 18 | onItem.call(thisArg, this.x, this.y, 0); 19 | } 20 | }; 21 | 22 | MoveSegment.prototype.setPoint = function (point, index) { 23 | this.x = point.x; 24 | this.y = point.y; 25 | }; 26 | 27 | MoveSegment.prototype.getEndPoint = function () { 28 | return this; 29 | }; 30 | 31 | MoveSegment.prototype.invert = function (endPoint) { 32 | this.x = endPoint.x; 33 | this.y = endPoint.y; 34 | }; 35 | 36 | MoveSegment.prototype.transform = function (transform, forward) { 37 | var self = this; 38 | transform.transformPoint(self.x, self.y, forward, self, function (x, y) { 39 | self.x = x; 40 | self.y = y; 41 | });//ignore jslint 42 | }; 43 | -------------------------------------------------------------------------------- /src/templates/html/CheckBoxTemplate.js: -------------------------------------------------------------------------------- 1 | export default function CheckBoxTemplate(selectCheckBoxLabel) { 2 | var _template = ["div", 3 | ["label", 4 | ["nobr", 5 | ["input", 6 | { 7 | "type": "checkbox", 8 | "name": "checkbox", 9 | "class": "bp-selectioncheckbox" 10 | } 11 | ], 12 | '\xa0', 13 | ["span", 14 | { 15 | "name": "selectiontext", 16 | "class": "bp-selectiontext" 17 | }, 18 | selectCheckBoxLabel 19 | ] 20 | ] 21 | ] 22 | ]; 23 | 24 | function template() { 25 | return _template; 26 | } 27 | 28 | function getHashCode() { 29 | return "defaultCheckBoxTemplate"; 30 | } 31 | 32 | function render(event, data) { 33 | var checkBox = data.element.firstChild.firstChild.firstChild; 34 | checkBox.checked = data.isSelected; 35 | checkBox.setAttribute("data-id", data.id); 36 | var label = data.element.firstChild.firstChild.childNodes[2]; 37 | label.setAttribute("data-id", data.id); 38 | } 39 | 40 | return { 41 | template: template, 42 | getHashCode: getHashCode, 43 | render: render 44 | }; 45 | }; -------------------------------------------------------------------------------- /samples/ItemTemplateLabel.md: -------------------------------------------------------------------------------- 1 | # Labels 2 | The chart provides options to draw labels for nodes. It draws them for minimized nodes into markers only. Use the following options on the diagram configuration object to control labels styling and placement: 3 | * `showLabels` 4 | * `labelSize` 5 | * `labelOffset` 6 | * `labelOrientation` 7 | * `labelPlacement` 8 | 9 | See the reference for more details. 10 | 11 | The `ItemConfig` configuration object has properties `label`, `showLabel` etc. They let you customize labels per item. That is needed because markers have no templates for labels customization. 12 | 13 | If we need labels for the regular visible items, we can add them to the custom template. The templates consist of HTML fragments, so it possible to place labels outside node boundaries. For that, you need to override the default CSS `overflow` attribute from `hidden` to `visible`. See `bp-item` class in the `primitives.css` file. 14 | 15 | The following example demonstrates how to add an extra property showing percent value over nodes connection lines. 16 | 17 | [JavaScript](javascript.controls/CaseItemTemplateLabel.html) 18 | 19 |  -------------------------------------------------------------------------------- /samples/MatrixLayoutInFamilyChart.md: -------------------------------------------------------------------------------- 1 | # Matrix layout in family chart 2 | The option `enableMatrixLayout` enables automatic matrix layout for nodes sharing the same set of parents and children in the diagram. The matrix forms a square shape. If the matrix outgrows the screen width, it makes diagram navigation complicated. The `maximumColumnsInMatrix` option limits the maximum number of columns and forces the matrix to grow vertically instead of horizontally. The option `minimumMatrixSize` sets the minimum number of nodes needed to be shaped into matrix formation. 3 | 4 | [JavaScript](javascript.controls/CaseMatrixLayoutInFamilyChart.html) 5 | 6 |  7 | 8 | 9 | # Grouping nodes into multiple matrixes 10 | The family diagram provides options to control grouping nodes into matrixes per node. The option `addToMatrix` lets you explicitly prohibit adding nodes into any group of matrixed nodes. And the `matrixId` option allows you to group nodes into multiple matrixes. 11 | 12 | [JavaScript](javascript.controls/CaseMatrixGroupsInFamilyChart.html) 13 | 14 |  15 | -------------------------------------------------------------------------------- /src/algorithms/binarySearch.test.js: -------------------------------------------------------------------------------- 1 | import binarySearch from './binarySearch'; 2 | 3 | var items = [ 4 | { x: 10, y: 10 }, 5 | { x: 15, y: 10 }, 6 | { x: 16, y: 10 }, 7 | { x: 20, y: 10 }, 8 | { x: 50, y: 10 }, 9 | { x: 100, y: 10 }, 10 | { x: 140, y: 10 } 11 | ]; 12 | 13 | test('Search for item beyound left boundary of the collection should return leftmost item.', () => { 14 | const result = binarySearch(items, function (item, offset) { 15 | return 4 - item.x; 16 | }); 17 | expect(result.item.x).toBe(10); 18 | }); 19 | 20 | test('Search for item beyound right boundary of the collection should return the rightmost item.', () => { 21 | const result = binarySearch(items, function (item, offset) { 22 | return 200 - item.x; 23 | }); 24 | expect(result.item.x).toBe(140); 25 | }); 26 | 27 | test('Function should find item nearest to 60', () => { 28 | const result = binarySearch(items, function (item, offset) { 29 | return 60 - item.x; 30 | }); 31 | expect(result.item.x).toBe(50); 32 | }); 33 | 34 | test('Function should item nearest 90', () => { 35 | const result = binarySearch(items, function (item, offset) { 36 | return 90 - item.x; 37 | }); 38 | expect(result.item.x).toBe(100); 39 | }); 40 | -------------------------------------------------------------------------------- /samples/InactiveItems.md: -------------------------------------------------------------------------------- 1 | # Inactive items 2 | Inactive items are regular items excluded from the navigation and deprived of interactivity. For example, we can add department titles into hierarchy or terminator items, indicating the number of available items for dynamic adding into the structure. 3 | 4 | Chart's API provides two ways to set make items inactive. The first one is the `isActive` option of the ItemConfig options class and the second way is via template configuration. In most scenarios, the inactive items are supposed to have a custom item template, so deactivating user interaction via template is the most appropriate for application design. 5 | 6 | See following configuration classes: 7 | 8 | * `OrgItemConfig` 9 | * `TemplateConfig` 10 | 11 | They have the following option: 12 | 13 | * `isActive` - Setting it to false makes items inactive in diagram layout, so they become irresponsive to mouse and keyboard navigation events. 14 | 15 | If you need to disable controls interactivity, it provides global scope options to disable mouse highlights and cursor navigation. 16 | 17 | [JavaScript](javascript.controls/CaseInactiveItems.html) 18 | 19 |  -------------------------------------------------------------------------------- /samples/javascript.controls/css/styles.css: -------------------------------------------------------------------------------- 1 | .mediaPlaceholder { 2 | height: 350px; 3 | border-width: 1px; 4 | border-style: dotted; 5 | } 6 | 7 | @media screen and (min-height: 600px) { 8 | .mediaPlaceholder { 9 | height: 500px; } } 10 | 11 | @media screen and (min-height: 700px) { 12 | .mediaPlaceholder { 13 | height: 600px; } } 14 | 15 | @media screen and (min-height: 800px) { 16 | .mediaPlaceholder { 17 | height: 700px; } } 18 | 19 | @media screen and (min-height: 900px) { 20 | .mediaPlaceholder { 21 | height: 800px; } } 22 | 23 | @media screen and (min-height: 1000px) { 24 | .mediaPlaceholder { 25 | height: 900px; } } 26 | 27 | @media screen and (min-height: 1100px) { 28 | .mediaPlaceholder { 29 | height: 1000px; } } 30 | 31 | @media screen and (min-height: 1200px) { 32 | .mediaPlaceholder { 33 | height: 1100px; } } 34 | 35 | @media screen and (min-height: 1300px) { 36 | .mediaPlaceholder { 37 | height: 1200px; } } 38 | 39 | @media screen and (min-height: 1400px) { 40 | .mediaPlaceholder { 41 | height: 1300px; } } 42 | 43 | @media screen and (min-height: 1500px) { 44 | .mediaPlaceholder { 45 | height: 1400px; } } -------------------------------------------------------------------------------- /src/tasks/templates/LabelAnnotationTemplateParamsTask.js: -------------------------------------------------------------------------------- 1 | import TemplateParams from '../../models/TemplateParams'; 2 | 3 | export default function LabelAnnotationTemplateParamsTask(itemsSizesOptionTask, labelAnnotationTemplateOptionTask, readTemplatesTask) { 4 | var _data = { 5 | items: {} // TemplateParams 6 | }; 7 | 8 | function process() { 9 | var itemsSizesOptions = itemsSizesOptionTask.getOptions(), 10 | items = labelAnnotationTemplateOptionTask.getAnnotations(), 11 | index, len; 12 | 13 | _data.items = {}; 14 | 15 | for (index = 0, len = items.length; index < len; index += 1) { 16 | var annotation = items[index], 17 | templateParams = new TemplateParams(), 18 | template = readTemplatesTask.getTemplate(annotation.templateName, itemsSizesOptions.defaultLabelAnnotationTemplate, readTemplatesTask.DefaultWidgetLabelAnnotationTemplateName); 19 | 20 | templateParams.template = template; 21 | 22 | _data.items[annotation.id] = templateParams; 23 | } 24 | 25 | return true; 26 | } 27 | 28 | function getTemplateParams(itemId) { 29 | return _data.items[itemId]; 30 | } 31 | 32 | return { 33 | process: process, 34 | getTemplateParams: getTemplateParams 35 | }; 36 | }; -------------------------------------------------------------------------------- /src/tasks/layout/VerticalOffsetTask.js: -------------------------------------------------------------------------------- 1 | import Interval from '../../graphics/structs/Interval'; 2 | import Rect from '../../graphics/structs/Rect'; 3 | import ObjectReader from '../../readers/ObjectReader'; 4 | import ValueReader from '../../readers/ValueReader'; 5 | 6 | export default function VerticalOffsetTask(viewPortPlacementTask) { 7 | var _data = {}, 8 | _hash = {}; 9 | 10 | var _dataTemplate = new ObjectReader({ 11 | verticalOffset: new ObjectReader({ 12 | from: new ValueReader(["number"], false, 0), 13 | to: new ValueReader(["number"], false, 0) 14 | }, false, new Interval(0, 0)) 15 | }); 16 | 17 | function process() { 18 | var context = { 19 | isChanged: false, 20 | hash: _hash 21 | }; 22 | 23 | _data = _dataTemplate.read(_data, getOffset(), "options", context); 24 | 25 | return context.isChanged; 26 | } 27 | 28 | function getOffset() { 29 | var viewPortPosition = new Rect(viewPortPlacementTask.getViewPortPosition()); 30 | return { verticalOffset: viewPortPosition.verticalInterval() }; 31 | } 32 | 33 | function getVerticalOffset() { 34 | return _data.verticalOffset; 35 | } 36 | 37 | return { 38 | process: process, 39 | getVerticalOffset: getVerticalOffset 40 | }; 41 | }; -------------------------------------------------------------------------------- /src/tasks/options/LevelTitlePlacementOptionTask.js: -------------------------------------------------------------------------------- 1 | import ValueReader from '../../readers/ValueReader'; 2 | import ObjectReader from '../../readers/ObjectReader'; 3 | import EnumerationReader from '../../readers/EnumerationReader'; 4 | import { AdviserPlacementType } from '../../enums'; 5 | 6 | export default function LevelTitlePlacementOptionTask(optionsTask, defaultConfig) { 7 | var _data = {}, 8 | _hash = {}; 9 | 10 | var _dataTemplate = new ObjectReader({ 11 | levelTitlePlaceInside: new ValueReader(["boolean"], false, defaultConfig.levelTitlePlaceInside), 12 | levelTitlePanelSize: new ValueReader(["number"], false, defaultConfig.levelTitlePanelSize), 13 | levelTitlePlacementType: new EnumerationReader(AdviserPlacementType, false, defaultConfig.levelTitlePlacementType) 14 | }); 15 | function process() { 16 | var context = { 17 | isChanged: false, 18 | hash: _hash 19 | }; 20 | 21 | _data = _dataTemplate.read(_data, optionsTask.getOptions(), "options", context); 22 | 23 | return context.isChanged; 24 | } 25 | 26 | function getOptions() { 27 | return _data; 28 | } 29 | 30 | return { 31 | process: process, 32 | getOptions: getOptions, 33 | description: "Level annotation title placement options." 34 | }; 35 | }; 36 | -------------------------------------------------------------------------------- /src/tasks/options/MinimumVisibleLevelsOptionTask.js: -------------------------------------------------------------------------------- 1 | import ValueReader from '../../readers/ValueReader'; 2 | import ObjectReader from '../../readers/ObjectReader'; 3 | import EnumerationReader from '../../readers/EnumerationReader'; 4 | import { PageFitMode, Visibility } from '../../enums'; 5 | 6 | export default function MinimumVisibleLevelsOptionTask(optionsTask, defaultConfig) { 7 | var _data = {}, 8 | _hash = {}; 9 | 10 | var _dataTemplate = new ObjectReader({ 11 | /* items visibility */ 12 | pageFitMode: new EnumerationReader(PageFitMode, false, defaultConfig.pageFitMode), 13 | minimalVisibility: new EnumerationReader(Visibility, false, defaultConfig.minimalVisibility), 14 | minimumVisibleLevels: new ValueReader(["number"], false, defaultConfig.minimumVisibleLevels), 15 | }); 16 | 17 | function process() { 18 | var context = { 19 | isChanged: false, 20 | hash: _hash 21 | }; 22 | 23 | _data = _dataTemplate.read(_data, optionsTask.getOptions(), "options", context); 24 | 25 | return context.isChanged; 26 | } 27 | 28 | function getOptions() { 29 | return _data; 30 | } 31 | 32 | return { 33 | process: process, 34 | getOptions: getOptions, 35 | description: "Checks minimum visible levels options." 36 | }; 37 | }; -------------------------------------------------------------------------------- /src/graphics/EnumValues.js: -------------------------------------------------------------------------------- 1 | import { VerticalAlignmentType, HorizontalAlignmentType, LineType } from '../enums'; 2 | 3 | export function getTextAlign(alignment) { 4 | var result = null; 5 | switch (alignment) { 6 | case HorizontalAlignmentType.Center: 7 | result = "center"; 8 | break; 9 | case HorizontalAlignmentType.Left: 10 | result = "left"; 11 | break; 12 | case HorizontalAlignmentType.Right: 13 | result = "right"; 14 | break; 15 | } 16 | return result; 17 | } 18 | 19 | export function getVerticalAlignment(alignment) { 20 | var result = null; 21 | switch (alignment) { 22 | case VerticalAlignmentType.Middle: 23 | result = "middle"; 24 | break; 25 | case VerticalAlignmentType.Top: 26 | result = "top"; 27 | break; 28 | case VerticalAlignmentType.Bottom: 29 | result = "bottom"; 30 | break; 31 | } 32 | return result; 33 | } 34 | 35 | export function getBorderStyle(lineType) { 36 | var result = null; 37 | switch (lineType) { 38 | case LineType.Solid: 39 | result = "solid"; 40 | break; 41 | case LineType.Dotted: 42 | result = "dotted"; 43 | break; 44 | case LineType.Dashed: 45 | result = "dashed"; 46 | break; 47 | } 48 | return result; 49 | } -------------------------------------------------------------------------------- /src/tasks/transformations/HideGrandParentsConnectorsTask.js: -------------------------------------------------------------------------------- 1 | /* This task optionally eliminates direct connections to grand parents */ 2 | export default function HideGrandParentsConnectorsTask(hideGrandParentsConnectorsOptionTask, removeLoopsTask) { 3 | var _data = { 4 | maximumId: null, /* maximum of OrgItem.id */ 5 | logicalFamily: null 6 | } 7 | 8 | function process(debug) { 9 | var logicalFamily = removeLoopsTask.getLogicalFamily(), 10 | maximumId = removeLoopsTask.getMaximumId(); 11 | 12 | var options = hideGrandParentsConnectorsOptionTask.getOptions(); 13 | 14 | if (options.hideGrandParentsConnectors == true) { 15 | /* optionally eliminate grand parents connectors */ 16 | logicalFamily = logicalFamily.getFamilyWithoutGrandParentsRelations(); 17 | } else { 18 | logicalFamily = logicalFamily.clone(); 19 | } 20 | 21 | _data.logicalFamily = logicalFamily; 22 | _data.maximumId = maximumId; 23 | 24 | return true; 25 | } 26 | 27 | function getLogicalFamily() { 28 | return _data.logicalFamily; 29 | } 30 | 31 | function getMaximumId() { 32 | return _data.maximumId; 33 | } 34 | 35 | return { 36 | process: process, 37 | getLogicalFamily: getLogicalFamily, 38 | getMaximumId: getMaximumId 39 | }; 40 | }; 41 | -------------------------------------------------------------------------------- /src/tasks/options/annotations/LabelAnnotationTemplateOptionTask.js: -------------------------------------------------------------------------------- 1 | import ArrayReader from '../../../readers/ArrayReader'; 2 | import ValueReader from '../../../readers/ValueReader'; 3 | import ObjectReader from '../../../readers/ObjectReader'; 4 | 5 | export default function LabelAnnotationTemplateOptionTask(labelAnnotationOptionTask, defaultLabelAnnotationConfig) { 6 | var _data = { 7 | annotations: [] 8 | }, 9 | _hash = {}; 10 | 11 | var _dataTemplate = new ArrayReader( 12 | new ObjectReader({ 13 | id: new ValueReader(["number"], true), 14 | title: new ValueReader(["string"], true), 15 | itemTitleColor: new ValueReader(["string"], false, defaultLabelAnnotationConfig.itemTitleColor), 16 | templateName: new ValueReader(["string"], true) 17 | }), 18 | true, 19 | "id" 20 | ); 21 | 22 | 23 | function process() { 24 | var context = { 25 | isChanged: false, 26 | hash: _hash 27 | }; 28 | 29 | _data.annotations = _dataTemplate.read(_data.annotations, labelAnnotationOptionTask.getAnnotations(), "annotations", context); 30 | 31 | return context.isChanged; 32 | } 33 | 34 | function getAnnotations() { 35 | return _data.annotations; 36 | } 37 | 38 | return { 39 | process: process, 40 | getAnnotations: getAnnotations 41 | }; 42 | }; -------------------------------------------------------------------------------- /src/tasks/options/LinePaletteOptionTask.js: -------------------------------------------------------------------------------- 1 | import ValueReader from '../../readers/ValueReader'; 2 | import ObjectReader from '../../readers/ObjectReader'; 3 | import ArrayReader from '../../readers/ArrayReader'; 4 | import EnumerationReader from '../../readers/EnumerationReader'; 5 | import { LineType } from '../../enums'; 6 | 7 | export default function LinePaletteOptionTask(optionsTask, defaultPaletteItemConfig) { 8 | var _data = {}, 9 | _hash = {}; 10 | 11 | var _dataTemplate = new ObjectReader({ 12 | linesPalette: new ArrayReader( 13 | new ObjectReader({ 14 | lineColor: new ValueReader(["string"], false, defaultPaletteItemConfig.lineColor), 15 | lineWidth: new ValueReader(["number"], false, defaultPaletteItemConfig.lineWidth), 16 | lineType: new EnumerationReader(LineType, false, defaultPaletteItemConfig.lineType) 17 | }), 18 | false 19 | ) 20 | }); 21 | 22 | function process() { 23 | var context = { 24 | isChanged: false, 25 | hash: _hash 26 | }; 27 | 28 | _data = _dataTemplate.read(_data, optionsTask.getOptions(), "options", context); 29 | 30 | return context.isChanged; 31 | } 32 | 33 | function getOptions() { 34 | return _data; 35 | } 36 | 37 | return { 38 | process: process, 39 | getOptions: getOptions 40 | }; 41 | }; -------------------------------------------------------------------------------- /src/models/TreeItemPosition.js: -------------------------------------------------------------------------------- 1 | import Rect from '../graphics/structs/Rect'; 2 | import { Visibility } from '../enums'; 3 | 4 | export default function TreeItemPosition(source) { 5 | this.level = null; 6 | 7 | this.actualVisibility = Visibility.Normal; 8 | this.actualSize = null; 9 | this.actualPosition = null; 10 | this.contentPosition = null; 11 | 12 | this.horizontalConnectorsShift = null; 13 | this.topConnectorShift = null; 14 | this.topConnectorInterval = 0; 15 | this.bottomConnectorShift = null; 16 | this.bottomConnectorInterval = 0; 17 | 18 | /* following properties are being used in matrix layout to draw connector lines */ 19 | this.leftMedianOffset = null; /* this property is position of vertical connector lines going between columns of nodes in matrix layout on left side of the node */ 20 | this.rightMedianOffset = null; /* the same but on the right side */ 21 | 22 | if (source != null) { 23 | for (var property in source) { 24 | if (source.hasOwnProperty(property)) { 25 | switch (property) { 26 | case 'actualPosition': 27 | this.actualPosition = new Rect(source.actualPosition); 28 | break; 29 | default: 30 | this[property] = source[property]; 31 | break; 32 | } 33 | 34 | } 35 | } 36 | } 37 | }; 38 | -------------------------------------------------------------------------------- /src/templates/html/DotHighlightTemplate.js: -------------------------------------------------------------------------------- 1 | export default function DotHighlightTemplate(options, itemTemplateConfig) { 2 | var _template = create(itemTemplateConfig); 3 | 4 | function create(config) { 5 | var radius = config.minimizedItemCornerRadius; 6 | if (radius == null) { 7 | radius = Math.max( 8 | config.highlightPadding.left + config.minimizedItemSize.width + config.highlightPadding.right, 9 | config.highlightPadding.top + config.minimizedItemSize.height + config.highlightPadding.bottom 10 | ) + config.highlightBorderWidth; 11 | } 12 | return ["div", 13 | { 14 | "style": { 15 | "borderWidth": config.highlightBorderWidth + "px", 16 | "MozBorderRadius": radius + "px", 17 | "WebkitBorderRadius": radius + "px", 18 | "-khtml-border-radius": radius + "px", 19 | "borderRadius": radius + "px" 20 | }, 21 | "class": ["bp-item", "bp-highlight-dot-frame"] 22 | } 23 | ]; 24 | } 25 | 26 | function template() { 27 | return _template; 28 | } 29 | 30 | function getHashCode() { 31 | return "defaultDotHighlightTemplate"; 32 | } 33 | 34 | function render(event, data) { 35 | 36 | } 37 | 38 | return { 39 | template: template, 40 | getHashCode: getHashCode, 41 | render: render 42 | }; 43 | }; -------------------------------------------------------------------------------- /src/tasks/options/selection/CursorItemOptionTask.js: -------------------------------------------------------------------------------- 1 | import ValueReader from '../../../readers/ValueReader'; 2 | import ObjectReader from '../../../readers/ObjectReader'; 3 | import EnumerationReader from '../../../readers/EnumerationReader'; 4 | import {NavigationMode} from '../../../enums'; 5 | 6 | export default function CursorItemOptionTask(optionsTask, defaultConfig) { 7 | var _data = {}; 8 | 9 | var _dataTemplate = new ObjectReader({ 10 | cursorItem: new ValueReader(["string", "number"], true), 11 | navigationMode: new EnumerationReader(NavigationMode, false, defaultConfig.navigationMode) 12 | }); 13 | 14 | function process() { 15 | var context = { 16 | isChanged: false 17 | }; 18 | 19 | _data = _dataTemplate.read(_data, optionsTask.getOptions(), "options", context); 20 | 21 | return context.isChanged; 22 | } 23 | 24 | function getCursorItem() { 25 | return _data.cursorItem; 26 | } 27 | 28 | function hasCursorEnabled() { 29 | switch (_data.navigationMode) { 30 | case NavigationMode.Default: 31 | case NavigationMode.CursorOnly: 32 | return true; 33 | } 34 | return false; 35 | } 36 | 37 | return { 38 | process: process, 39 | getCursorItem: getCursorItem, 40 | hasCursorEnabled: hasCursorEnabled, 41 | description: "Checks currenct cursor item option." 42 | }; 43 | }; -------------------------------------------------------------------------------- /src/graphics/structs/PaletteItem.js: -------------------------------------------------------------------------------- 1 | import { Colors, LineType } from '../../enums'; 2 | import { isNullOrEmpty } from '../../common'; 3 | 4 | export default function PaletteItem(options) { 5 | this.lineColor = Colors.Silver; 6 | this.lineWidth = 1; 7 | this.lineType = LineType.Solid; 8 | this.fillColor = null; 9 | this.opacity = null; 10 | 11 | this._key = ""; 12 | 13 | var property, properties, 14 | index, len; 15 | 16 | properties = ['lineColor', 'lineWidth', 'lineType', 'fillColor', 'opacity']; 17 | 18 | for (index = 0, len = properties.length; index < len; index += 1) { 19 | property = properties[index]; 20 | 21 | if (options != null && options.hasOwnProperty(property)) { 22 | this[property] = options[property]; 23 | } 24 | this._key += (!isNullOrEmpty(this._key) ? ", " : "") + property + ":" + this[property]; 25 | } 26 | }; 27 | 28 | PaletteItem.prototype.toAttr = function () { 29 | var attr = { 30 | "lineWidth": this.lineWidth, 31 | "lineType": this.lineType 32 | }; 33 | if (this.fillColor !== null) { 34 | attr.fillColor = this.fillColor; 35 | } 36 | if (this.opacity !== null) { 37 | attr.opacity = this.opacity; 38 | } 39 | if (this.lineColor !== null) { 40 | attr.borderColor = this.lineColor; 41 | } 42 | return attr; 43 | }; 44 | 45 | PaletteItem.prototype.toString = function () { 46 | return this._key; 47 | }; -------------------------------------------------------------------------------- /samples/javascript.controls/common/tests.js: -------------------------------------------------------------------------------- 1 | export { default as RenderEventArgs } from '../../../src/events/RenderEventArgs'; 2 | export { default as PolylinesBuffer } from '../../../src/graphics/structs/PolylinesBuffer'; 3 | export { default as PaletteItem } from '../../../src/graphics/structs/PaletteItem'; 4 | export { default as SvgGraphics } from '../../../src/graphics/SvgGraphics'; 5 | export { default as Callout } from '../../../src/graphics/shapes/Callout'; 6 | export { default as Shape } from '../../../src/graphics/shapes/Shape'; 7 | export { default as ConnectorStraight } from '../../../src/graphics/shapes/ConnectorStraight'; 8 | export { default as ConnectorOffbeat } from '../../../src/graphics/shapes/ConnectorOffbeat'; 9 | export { default as ConnectorAnnotationOffsetResolver } from '../../../src/tasks/renders/offsetResolver/ConnectorAnnotationOffsetResolver'; 10 | export * from '../../../src/enums'; 11 | export { default as createGraphics } from '../../../src/graphics/createGraphics'; 12 | export { getElementOffset } from '../../../src/graphics/dom'; 13 | export { default as getOrgTasksDiagram } from '../../../src/getOrgTasksDiagram'; 14 | export { default as getFamTasksDiagram } from '../../../src/getFamTasksDiagram'; 15 | export { default as getOrgPdfkitTasksDiagram } from '../../../src/getOrgPdfkitTasksDiagram'; 16 | export { default as getFamPdfkitTasksDiagram } from '../../../src/getFamPdfkitTasksDiagram'; -------------------------------------------------------------------------------- /src/tasks/layout/CreateTransformTask.js: -------------------------------------------------------------------------------- 1 | import Transform from '../../graphics/Transform'; 2 | import Size from '../../graphics/structs/Size'; 3 | 4 | export default function CreateTransformTask(orientationOptionTask, scaleOptionTask, alignDiagramTask) { 5 | var _data = { 6 | transform: null 7 | }; 8 | 9 | function process() { 10 | var orientationOptions = orientationOptionTask.getOptions(); 11 | 12 | var panelSize = new Size(alignDiagramTask.getContentSize()); 13 | 14 | _data.transform = new Transform(); 15 | _data.transform.setOrientation(orientationOptions.orientationType); 16 | _data.transform.size = new Size(panelSize); 17 | 18 | return true; 19 | } 20 | 21 | function getTreeItemForMousePosition(x, y, gravityRadius) { 22 | var result = null, 23 | { scale } = scaleOptionTask.getOptions(); 24 | 25 | x = x / scale; 26 | y = y / scale; 27 | 28 | _data.transform.transformPoint(x, y, false, this, function (x, y) { 29 | result = alignDiagramTask.getTreeItemForMousePosition(x, y, gravityRadius); 30 | }); 31 | return result; 32 | } 33 | 34 | function getTransform() { 35 | return _data.transform; 36 | } 37 | 38 | return { 39 | process: process, 40 | getTransform: getTransform, 41 | getTreeItemForMousePosition: getTreeItemForMousePosition, 42 | description: "Create coordinate system transformation object." 43 | }; 44 | }; -------------------------------------------------------------------------------- /src/templates/pdf/GroupTitleTemplate.js: -------------------------------------------------------------------------------- 1 | import { highestContrast } from '../../common/colors'; 2 | import { renderRotatedText } from './RotatedText'; 3 | 4 | export default function GroupTitleTemplate(options) { 5 | var { 6 | groupTitleFontSize, 7 | groupTitleFontFamily: fontFamily, 8 | groupTitleFontWeight: fontWeight, 9 | groupTitleFontStyle: fontStyle, 10 | groupTitleOrientation: textOrientation, 11 | groupTitleHorizontalAlignment: horizontalAlignment, 12 | groupTitleVerticalAlignment: verticalAlignment, 13 | groupTitleColor, 14 | itemTitleFirstFontColor, 15 | itemTitleSecondFontColor 16 | } = options; 17 | function template() { 18 | return {}; 19 | } 20 | 21 | function getHashCode() { 22 | return 0; 23 | } 24 | 25 | function render(doc, position, data) { 26 | var itemConfig = data.context, 27 | titleColor = itemConfig.groupTitleColor || groupTitleColor, 28 | fontColor = highestContrast(titleColor, itemTitleSecondFontColor, itemTitleFirstFontColor), 29 | label = itemConfig.groupTitle; 30 | 31 | var fontSize = parseInt(groupTitleFontSize, 10); 32 | 33 | renderRotatedText({doc, textOrientation, label, fontSize, fontColor, position, titleColor, horizontalAlignment, verticalAlignment }); 34 | } 35 | 36 | return { 37 | template: template, 38 | getHashCode: getHashCode, 39 | render: render 40 | }; 41 | }; 42 | 43 | -------------------------------------------------------------------------------- /src/tasks/options/FamItemsOptionTask.js: -------------------------------------------------------------------------------- 1 | import ArrayReader from '../../readers/ArrayReader'; 2 | import ValueReader from '../../readers/ValueReader'; 3 | import ObjectReader from '../../readers/ObjectReader'; 4 | 5 | export default function FamItemsOptionTask(optionsTask, defaultItemConfig) { 6 | var _data = {}, 7 | _hash = {}, 8 | _sourceHash = {}; 9 | 10 | var _dataTemplate = new ObjectReader({ 11 | items: new ArrayReader( 12 | new ObjectReader({ 13 | id: new ValueReader(["string", "number"], true), 14 | parents: new ArrayReader( 15 | new ValueReader(["string", "number"], true), 16 | true 17 | ), 18 | isActive: new ValueReader(["boolean"], false, defaultItemConfig.isActive) 19 | }), 20 | true, 21 | "id", 22 | true 23 | ) 24 | }); 25 | 26 | function process() { 27 | var context = { 28 | isChanged: false, 29 | hash: _hash, 30 | sourceHash: _sourceHash 31 | }; 32 | 33 | _data = _dataTemplate.read(_data, optionsTask.getOptions(), "options", context); 34 | 35 | return context.isChanged; 36 | } 37 | 38 | function getItems() { 39 | return _data.items; 40 | } 41 | 42 | function getConfig(itemId) { 43 | return _sourceHash["options-items"][itemId]; 44 | } 45 | 46 | return { 47 | process: process, 48 | getItems: getItems, 49 | getConfig: getConfig 50 | }; 51 | }; -------------------------------------------------------------------------------- /src/tasks/options/annotations/LabelAnnotationPlacementOptionTask.js: -------------------------------------------------------------------------------- 1 | import ArrayReader from '../../../readers/ArrayReader'; 2 | import ValueReader from '../../../readers/ValueReader'; 3 | import ObjectReader from '../../../readers/ObjectReader'; 4 | 5 | export default function LabelAnnotationPlacementOptionTask(labelAnnotationOptionTask, defaultLabelAnnotationConfig) { 6 | var _data = { 7 | annotations: [] 8 | }, 9 | _hash = {}; 10 | 11 | var _dataTemplate = new ArrayReader( 12 | new ObjectReader({ 13 | id: new ValueReader(["number"], true), 14 | fromItem: new ValueReader(["string", "number"], true), 15 | toItems: new ArrayReader( 16 | new ValueReader(["string", "number"], true), 17 | true 18 | ) 19 | }), 20 | true, 21 | "id" 22 | ); 23 | 24 | function process() { 25 | var context = { 26 | isChanged: false, 27 | hash: _hash 28 | }; 29 | 30 | _data.annotations = _dataTemplate.read(_data.annotations, labelAnnotationOptionTask.getAnnotations(), "annotations", context); 31 | 32 | return context.isChanged; 33 | } 34 | 35 | function getAnnotations() { 36 | return _data.annotations; 37 | } 38 | 39 | function getMaximumId() { 40 | return labelAnnotationOptionTask.getMaximumId(); 41 | } 42 | 43 | return { 44 | process: process, 45 | getAnnotations: getAnnotations, 46 | getMaximumId: getMaximumId 47 | }; 48 | }; -------------------------------------------------------------------------------- /src/algorithms/getMinimumCrossingRows.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Callback for iterating rows 3 | * 4 | * @callback onRowCallback 5 | * @param {number} row The y coordinate of the horizontal line 6 | */ 7 | 8 | /** 9 | * Finds minimum number of horizontal lines crossing all rectangles 10 | * 11 | * @param {Object} thisArg The callback function invocation context 12 | * @param {React[]} rectangles Collection of rectangles 13 | * @param {onRowCallback} onItem Callback function to call for every found row 14 | */ 15 | export default function getMinimumCrossingRows(thisArg, rectangles, onItem) { 16 | var from = null; 17 | var to = null; 18 | if (onItem != null) { 19 | rectangles.sort(function (a, b) { 20 | return a.y - b.y; 21 | }); 22 | 23 | for (var index = 0; index < rectangles.length; index += 1) { 24 | var rect = rectangles[index]; 25 | var bottom = rect.bottom(); 26 | if (from === null) { 27 | from = rect.y; 28 | to = bottom; 29 | } else { 30 | if (rect.y >= to) { 31 | onItem.call(thisArg, from); 32 | from = rect.y; 33 | to = bottom; 34 | } else { 35 | if (rect.y > from) { 36 | from = rect.y; 37 | } 38 | 39 | if (bottom < to) { 40 | to = bottom; 41 | } 42 | } 43 | } 44 | } 45 | if (from !== null) { 46 | onItem.call(thisArg, from); 47 | } 48 | } 49 | }; 50 | 51 | -------------------------------------------------------------------------------- /samples/SelectionPathMode.md: -------------------------------------------------------------------------------- 1 | # Selection Path Mode 2 | Suppose the total square size of items exceeds the available screen size. There is no possibility to show all of them, and the chart should use various strategies to display the essential information. By default organizational chart shows the current cursor item and all its children and parents up to the root of the hierarchy. The same rule applies to the list of selected items. All other less essential nodes, chart is allowed to display in the form of markers and lines. 3 | 4 | The selection path is a collection of parents between any node and the root of the hierarchy. The control can show the selection path for the current cursor node and selected nodes as well. If you need to show selection path nodes, set the option `primitives.OrgConfig.selectionPathMode` to `primitives.SelectionPathMode.FullStack` or hide them to markers with `primitives.SelectionPathMode.None` option. 5 | 6 | When we need to compare two or three selected items in the organizational chart, it is essential to show their selection paths. It gives you context for nodes comparison: immediate managers, departments, and relative levels in the organization. In the case of many selected items, it is better to hide selection paths to save valuable space and fit the chart into the screen. 7 | 8 | [JavaScript](javascript.controls/CaseSelectionPathMode.html) 9 | 10 |  -------------------------------------------------------------------------------- /src/tasks/options/MinimizedItemsOptionTask.js: -------------------------------------------------------------------------------- 1 | import ObjectReader from '../../readers/ObjectReader'; 2 | import EnumerationReader from '../../readers/EnumerationReader'; 3 | import ArrayReader from '../../readers/ArrayReader'; 4 | import ValueReader from '../../readers/ValueReader'; 5 | import { ShapeType } from '../../enums'; 6 | 7 | export default function MinimizedItemsOptionTask(optionsTask) { 8 | var _data = {}, 9 | _hash = {}; 10 | 11 | var _dataTemplate = new ObjectReader({ 12 | minimizedItemShapeType: new EnumerationReader(ShapeType, true), 13 | items: new ArrayReader( 14 | new ObjectReader({ 15 | id: new ValueReader(["string", "number"], true), 16 | minimizedItemShapeType: new EnumerationReader(ShapeType, true), 17 | itemTitleColor: new ValueReader(["string"], true) 18 | }), 19 | true, 20 | "id" 21 | ) 22 | }); 23 | 24 | function process() { 25 | var context = { 26 | isChanged: false, 27 | hash: _hash 28 | }; 29 | 30 | _data = _dataTemplate.read(_data, optionsTask.getOptions(), "options", context); 31 | 32 | return context.isChanged; 33 | } 34 | 35 | function getItemOptions(itemid) { 36 | return _hash["options-items"][itemid]; 37 | } 38 | 39 | function getOptions() { 40 | return _data; 41 | } 42 | 43 | return { 44 | process: process, 45 | getItemOptions: getItemOptions, 46 | getOptions: getOptions, 47 | description: "Checks minimized items drawing options." 48 | }; 49 | }; -------------------------------------------------------------------------------- /samples/javascript.controls/common/CheckBox.js: -------------------------------------------------------------------------------- 1 | import { ControlType } from './enums'; 2 | 3 | export function CheckBoxConfig(id, defaultValue, caption, onUpdate) { 4 | this.controlType = ControlType.CheckBox; 5 | this.id = id; 6 | this.defaultValue = defaultValue; 7 | this.caption = caption; 8 | this.onUpdate = onUpdate; 9 | }; 10 | 11 | export function CheckBoxRender() { 12 | 13 | this.render = function (config, namespace, defaultValue) { 14 | var properties = { 15 | "class": "form-check-input", 16 | "name": namespace + config.id, 17 | "id": namespace + config.id, 18 | "type": 'checkbox', 19 | "$": function (element) { 20 | element.addEventListener('change', function () { 21 | config.onUpdate(element, config); 22 | }); 23 | } 24 | }; 25 | if (defaultValue == true) { 26 | properties["checked"] = "checked"; 27 | } 28 | var controlBody = ["div", 29 | { 30 | "class": "form-check form-switch" 31 | }, 32 | ["input", 33 | properties, 34 | ], 35 | ["label", 36 | { 37 | "class": "form-check-label", 38 | "for": namespace + config.id 39 | }, 40 | config.caption 41 | ], 42 | ["br"] 43 | ]; 44 | return controlBody; 45 | }; 46 | 47 | this.getValue = function (item, namespace, formatters) { 48 | var checkbox = document.getElementsByName(namespace + item.id)[0]; 49 | return checkbox.checked; 50 | }; 51 | }; 52 | 53 | -------------------------------------------------------------------------------- /src/OrgEventArgsFactory.js: -------------------------------------------------------------------------------- 1 | import OrgEventArgs from './events/OrgEventArgs'; 2 | import Rect from './graphics/structs/Rect'; 3 | import { getElementOffset } from './graphics/dom'; 4 | 5 | export default function EventArgsFactory(data, oldTreeItemId, newTreeItemId, name) { 6 | var result = new OrgEventArgs(), 7 | combinedContextsTask = data.tasks.getTask("CombinedContextsTask"), 8 | alignDiagramTask = data.tasks.getTask("AlignDiagramTask"), 9 | oldItemConfig = combinedContextsTask.getConfig(oldTreeItemId), 10 | newItemConfig = combinedContextsTask.getConfig(newTreeItemId), 11 | itemPosition, 12 | actualPosition, 13 | offset, 14 | panelOffset; 15 | 16 | if (oldItemConfig && oldItemConfig.id != null) { 17 | result.oldContext = oldItemConfig; 18 | } 19 | 20 | if (newItemConfig && newItemConfig.id != null) { 21 | result.context = newItemConfig; 22 | 23 | if (newItemConfig.parent !== null) { 24 | result.parentItem = combinedContextsTask.getConfig(newItemConfig.parent); 25 | } 26 | 27 | panelOffset = getElementOffset(data.layout.mousePanel); 28 | offset = getElementOffset(data.layout.element); 29 | itemPosition = alignDiagramTask.getItemPosition(newTreeItemId), 30 | result.position = new Rect(itemPosition.actualPosition) 31 | .translate(panelOffset.left, panelOffset.top) 32 | .translate(-offset.left, -offset.top); 33 | } 34 | 35 | if (name != null) { 36 | result.name = name; 37 | } 38 | 39 | return result; 40 | }; 41 | -------------------------------------------------------------------------------- /src/readers/ValueReader.js: -------------------------------------------------------------------------------- 1 | export default function ValueReader(acceptedTypes, isNullable, defaultValue) { 2 | this.acceptedTypes = acceptedTypes; 3 | this.isNullable = isNullable; 4 | this.defaultValue = defaultValue; 5 | 6 | this.hash = {}; 7 | 8 | /* collect valid enumeration values */ 9 | for (var index = 0; index < acceptedTypes.length; index += 1) { 10 | var acceptedType = acceptedTypes[index]; 11 | this.hash[acceptedType] = true; 12 | } 13 | }; 14 | 15 | ValueReader.prototype.stringify = function (target) { 16 | if (this.hash["object"] == true) { 17 | var processed = []; 18 | var result = JSON.stringify(target, function (key, value) { 19 | if (key[0] === '_') { 20 | return null; 21 | } 22 | if (value !== null && typeof value == "object") { 23 | if (processed.indexOf(value) == -1) { 24 | processed.push(value); 25 | return value; 26 | } 27 | return null; 28 | } 29 | return value; 30 | }); 31 | return result; 32 | } 33 | return target; 34 | } 35 | 36 | ValueReader.prototype.read = function (target, source, path, context) { 37 | var result = null; 38 | 39 | if (source === null || typeof source == "undefined" || !this.hash.hasOwnProperty(typeof source)) { 40 | source = this.isNullable ? null : this.defaultValue; 41 | } 42 | 43 | result = source; 44 | 45 | if (this.stringify(target) !== this.stringify(source)) { 46 | context.isChanged = true; 47 | } 48 | 49 | return result; 50 | }; -------------------------------------------------------------------------------- /src/tasks/transformations/familyTransformations/UserDefinedPrimaryParents.js: -------------------------------------------------------------------------------- 1 | export default function UserDefinedPrimaryParents() { 2 | 3 | }; 4 | 5 | UserDefinedPrimaryParents.prototype.getUserDefinedPrimaryParents = function (items, family) { 6 | var result = {}, 7 | index, len; 8 | 9 | var primaryParents = {}; 10 | for (index = 0, len = items.length; index < len; index += 1) { 11 | var item = items[index]; 12 | if (item.primaryParent != null) { 13 | primaryParents[item.id] = item.primaryParent; 14 | } 15 | } 16 | 17 | for (var nodeid in primaryParents) { 18 | var primaryParent = primaryParents[nodeid]; 19 | var trace = {} 20 | 21 | var nodes = [nodeid]; 22 | while (nodes.length > 0) { 23 | var tempNodes = []; 24 | for (index = 0, len = nodes.length; index < len; index += 1) { 25 | nodeid = nodes[index]; 26 | family.loopParents(this, nodeid, function (parentid, parent) { 27 | trace[parentid] = nodeid; 28 | if (parentid == primaryParent) { 29 | while (trace[parentid] != null) { 30 | result[trace[parentid]] = parentid; 31 | parentid = trace[parentid]; 32 | } 33 | tempNodes = []; 34 | return family.BREAK; 35 | } 36 | if (parent.isVisible == false) { 37 | tempNodes.push(parentid); 38 | } 39 | return family.SKIP; 40 | }) 41 | } 42 | nodes = tempNodes; 43 | } 44 | } 45 | return result; 46 | } 47 | -------------------------------------------------------------------------------- /src/tasks/transformations/visualTreeBuilder/NavigationalFamily.js: -------------------------------------------------------------------------------- 1 | import Family from "../../../algorithms/Family"; 2 | 3 | export default function NavigationalFamily(activeItems) { 4 | var _activeItems = activeItems, 5 | _navigationFamily = Family(); 6 | 7 | function define(parentItem, treeItem, skipFirstParent) { 8 | var parents = []; 9 | /* take parentItem when it is visible or collect all visible immediate parents of the parentItem */ 10 | if ( 11 | skipFirstParent || 12 | !parentItem.isVisible || 13 | !_activeItems.hasOwnProperty(parentItem.id) 14 | ) { 15 | if (!skipFirstParent && parentItem.isVisible) { 16 | parents.push(parentItem.id); 17 | } 18 | _navigationFamily.loopParents( 19 | this, 20 | parentItem.id, 21 | function (parentId, parent, level) { 22 | if (parent.isVisible) { 23 | parents.push(parentId); 24 | if (_activeItems.hasOwnProperty(parentId)) { 25 | return _navigationFamily.SKIP; 26 | } 27 | } 28 | } 29 | ); 30 | } else { 31 | parents.push(parentItem.id); 32 | } 33 | if (_navigationFamily.node(treeItem.id) != null) { 34 | _navigationFamily.adopt(parents, treeItem.id); 35 | } else { 36 | _navigationFamily.add(parents, treeItem.id, treeItem); 37 | } 38 | } 39 | 40 | function getFamily() { 41 | return _navigationFamily; 42 | } 43 | 44 | return { 45 | define: define, 46 | getFamily: getFamily, 47 | }; 48 | } 49 | -------------------------------------------------------------------------------- /src/algorithms/LCA.js: -------------------------------------------------------------------------------- 1 | import RMQ from './RMQ'; 2 | 3 | /** 4 | * Creates Lowest Common Ancestor Structure for the given tree 5 | * @class LCA 6 | * 7 | * @param {Tree} tree The tree structure 8 | * @returns {LCA} Returns Lowest Common Ancestor Structure 9 | */ 10 | export default function LCA(tree) { 11 | var _eulerSequence = []; 12 | var _levels = []; 13 | var _fai = {}; 14 | var _rmq; 15 | 16 | 17 | preprocess(); 18 | 19 | function preprocess() { 20 | var counter = 0; 21 | tree.loopEulerWalk(this, function (nodeid, node, level) { 22 | _eulerSequence.push(nodeid); 23 | _levels.push(level); 24 | 25 | if (!_fai.hasOwnProperty(nodeid)) { 26 | _fai[nodeid] = counter; 27 | } 28 | counter += 1; 29 | }); 30 | _rmq = RMQ(_levels); 31 | } 32 | 33 | /** 34 | * Returns lowest common ancestor for the given pair of tree nodes 35 | * @param {string} from The first tree node id 36 | * @param {string} to The second tree node id 37 | * @returns {string} Returns the lowest common ancestor tree node id 38 | */ 39 | function getLowestCommonAncestor(from, to) { 40 | var fromIndex = _fai[from], 41 | toIndex = _fai[to], 42 | index; 43 | 44 | if (fromIndex < toIndex) { 45 | index = _rmq.getRangeMinimumIndex(fromIndex, toIndex); 46 | } else { 47 | index = _rmq.getRangeMinimumIndex(toIndex, fromIndex); 48 | } 49 | 50 | return _eulerSequence[index]; 51 | } 52 | 53 | return { 54 | getLowestCommonAncestor: getLowestCommonAncestor 55 | }; 56 | }; -------------------------------------------------------------------------------- /src/graphics/shapes/MergedRectangles.js: -------------------------------------------------------------------------------- 1 | import BaseShape from './BaseShape'; 2 | import Polyline from '../structs/Polyline'; 3 | import PaletteItem from '../structs/PaletteItem'; 4 | import MoveSegment from '../structs/MoveSegment'; 5 | import LineSegment from '../structs/LineSegment'; 6 | import { LineType } from '../../enums'; 7 | import getMergedRectangles from '../../algorithms/getMergedRectangles'; 8 | 9 | export default function MergedRectangles(graphics) { 10 | this.graphics = graphics; 11 | this.transform = null; 12 | 13 | this.lineWidth = 1; 14 | this.opacity = 1; 15 | this.fillColor = null; 16 | this.lineType = LineType.Solid; 17 | this.borderColor = null; 18 | }; 19 | 20 | MergedRectangles.prototype = new BaseShape(); 21 | 22 | MergedRectangles.prototype.draw = function (rects) { 23 | var paletteItem = new PaletteItem({ 24 | lineColor: this.borderColor, 25 | lineWidth: this.lineWidth, 26 | fillColor: this.fillColor, 27 | lineType: this.lineType, 28 | opacity: this.opacity 29 | }), 30 | polyline = new Polyline(paletteItem); 31 | 32 | getMergedRectangles(this, rects, function (points) { 33 | for (var index = 0, len = points.length; index < len; index += 1) { 34 | var point = points[index]; 35 | if (index == 0) { 36 | polyline.addSegment(new MoveSegment(point.x, point.y)); 37 | } else { 38 | polyline.addSegment(new LineSegment(point.x, point.y)); 39 | } 40 | } 41 | }); 42 | 43 | polyline.transform(this.transform, true); 44 | 45 | this.graphics.polyline(polyline); 46 | }; -------------------------------------------------------------------------------- /samples/ShapeAndBackgroundAnnotations.md: -------------------------------------------------------------------------------- 1 | # Shape & Background Annotations 2 | ## Shape 3 | Diagrams support on-screen annotations for visualization of non - hierarchical relations between nodes. Components use SVG elements to render geometrical figures. If you need some specific custom shapes, you have to make changes to the source code or use images and custom items templates. Shape annotation supports the following figures: 4 | * Rounded Rectangle 5 | * Oval 6 | * Triangle 7 | * Cross Out 8 | * Circle 9 | * Rhombus 10 | 11 | If you define multiple nodes, then annotation draws one large shape on top of them. If you need numerous individual figures for a list of nodes, you have to create shape annotation for every node. If you don't define background or borderline color, then they are not drawn. Annotation can render a text label on the side of the geometrical figure. 12 | 13 | ## Background Annotation 14 | This visual is a common background area having borderline and fill color. When we render the same background annotation for multiple items, control automatically blends them into a single continuous shape. Increase background offset around nodes if they don't merge. Merging annotations improves visualization and minimizes visual clutter in the diagram. Use `includeChildren` option to expand the background around the item down to all of its descendants. 15 | 16 | [JavaScript](javascript.controls/CaseShapeAnnotation.html) 17 | [PDFKit](pdfkit.plugins/ShapeAnnotation.html) 18 | 19 |  -------------------------------------------------------------------------------- /src/graphics/structs/Rect.test.js: -------------------------------------------------------------------------------- 1 | import Rect from './Rect'; 2 | 3 | test('getProjectionPoint - Projection is not found', () => { 4 | var rect = new Rect(10, 20, 40, 20); 5 | 6 | expect(rect.getProjectionPoint({x:11, y:21})).toBe(null); 7 | }); 8 | 9 | test('getProjectionPoint - Center of the top edge', () => { 10 | var rect = new Rect(10, 20, 40, 20); 11 | 12 | expect(rect.getProjectionPoint({x:30, y:0})).toEqual({context: null, x: 30, y: 20}); 13 | }); 14 | 15 | test('getProjectionPoint - Center of the right edge', () => { 16 | var rect = new Rect(10, 20, 40, 20); 17 | 18 | expect(rect.getProjectionPoint({x:60, y:30})).toEqual({context: null, x: 50, y: 30}); 19 | }); 20 | 21 | test('getProjectionPoint - Center of the bottom edge', () => { 22 | var rect = new Rect(10, 20, 40, 20); 23 | 24 | expect(rect.getProjectionPoint({x:30, y:50})).toEqual({context: null, x: 30, y: 40}); 25 | }); 26 | 27 | test('getProjectionPoint - Center of the left edge', () => { 28 | var rect = new Rect(10, 20, 40, 20); 29 | 30 | expect(rect.getProjectionPoint({x:0, y:30})).toEqual({context: null, x: 10, y: 30}); 31 | }); 32 | 33 | test('getProjectionPoint - Bottom right corner', () => { 34 | var rect = new Rect(10, 20, 40, 20); 35 | 36 | expect(rect.getProjectionPoint({x:70, y:50})).toEqual({context: null, x: 50, y: 40}); 37 | }); 38 | 39 | test('getProjectionPoint - Bottom edge point', () => { 40 | var rect = new Rect(10, 20, 40, 20); 41 | 42 | expect(rect.getProjectionPoint({x:50, y:70})).toEqual({context: null, x: 35, y: 40}); 43 | }); 44 | 45 | 46 | -------------------------------------------------------------------------------- /samples/ZoomWithItemTemplate.md: -------------------------------------------------------------------------------- 1 | # Zoom using Item template 2 | When we scale our diagram, the primary objective is to enlarge or downsize nodes to fit the chart into available screen space and overview its layout. 3 | We design our components primarily for business applications, where usability requirements constrain text size. If the text is too small and unreadable, it is a UI bug. When we design our nodes templates for various zoom levels, we can change their size, but we have to keep minimal font size unchanged, so nodes become small and contain less text. The same happens when we increase nodes in size, we don't increase fonts endlessly. It is not needed. Instead, we pack more content into the template, so our nodes become more informative. 4 | Usage of custom node templates for various scales guarantees that users see node content, regardless of the zoom level. You design, tune and test templates for every zoom level individually. 5 | You protect yourself against UX support tickets caused by misuse of the zoom. Users may accidentally scroll the mouse over the diagram and zoom it out into a meaningless graphics element. The user would not comprehend that it is the diagram on the screen anymore. 6 | Scaling diagrams with custom templates is very similar to developing responsive web applications for desktop and mobile. The screen space is so different that desktop application is not readable on mobile phone screen without adjustments. 7 | 8 | See item template use case for more details about templates usage. 9 | 10 | [JavaScript](javascript.controls/CaseZoomWithItemTemplate.html) -------------------------------------------------------------------------------- /src/configs/PaletteItemConfig.js: -------------------------------------------------------------------------------- 1 | import { LineType, Colors } from '../enums'; 2 | /** 3 | * @class PaletteItemConfig 4 | * @classdesc Palette Item configuration object defines cross-family 5 | * connections lines styles. Multi-parent diagrams may have a lot of 6 | * parallel lines, so to make their visual tracing easier, the component 7 | * supports multiple line styles and evenly distributes them. It is a similar 8 | * approach as for visualization of regular line charts. If we have numerous 9 | * lines in the chart area, it makes sense to style every line individually. 10 | * 11 | * @param {PaletteItemConfig} arg0 Palette properties object. 12 | * 13 | * @param {string} arg0 Line color 14 | * @param {number} arg1 Line width 15 | * @param {LineType} arg2 Line type 16 | */ 17 | export default function PaletteItemConfig(arg0, arg1, arg2) { 18 | var property; 19 | 20 | /** 21 | * Line color 22 | * 23 | * @type {string} 24 | */ 25 | this.lineColor = Colors.Silver; 26 | 27 | /** 28 | * Line width 29 | * 30 | * @type {number} 31 | */ 32 | this.lineWidth = 1; 33 | 34 | /** 35 | * Line type 36 | * 37 | * @type {LineType} 38 | */ 39 | this.lineType = LineType.Solid; 40 | 41 | switch (arguments.length) { 42 | case 1: 43 | for (property in arg0) { 44 | if (arg0.hasOwnProperty(property)) { 45 | this[property] = arg0[property]; 46 | } 47 | } 48 | break; 49 | case 3: 50 | this.lineColor = arg0; 51 | this.lineWidth = arg1; 52 | this.lineType = arg2; 53 | break; 54 | } 55 | }; 56 | -------------------------------------------------------------------------------- /samples/InactiveFamilyItems.md: -------------------------------------------------------------------------------- 1 | # Inactive family items 2 | Inactive items are regular items excluded from the navigation. End-user cannot click on them and move the cursor to them. In the auto fit mode, selecting the neighboring node next to the inactive item makes all nodes of the inactive item visible. The inactive items play a role in layout annotations having no user interaction and templated with HTML the same way as other diagram nodes. For example, we can add titles into family diagram layout to separate groups of nodes. We can add inactive terminator items indicating that the diagram would load extra nodes into the structure upon reaching them. 3 | 4 | Control provides two ways to make nodes inactive. The first one is to set the `isActive` property of the node to false. The other one is more generic. It is where we make all nodes having some particular template inactive. An adequately structured application should have some item templates, so making stationery items with template options is the most appropriate. 5 | 6 | See following configuration classes: 7 | 8 | * `FamItemConfig` 9 | * `TemplateConfig` 10 | 11 | They have the following option: 12 | 13 | * `isActive` - Setting it to false makes items inactive in diagram layout, so they become irresponsive to mouse and keyboard navigation events. 14 | 15 | If you need to disable controls interactivity, it provides global scope options to disable mouse highlights and cursor navigation. 16 | 17 | [JavaScript](javascript.controls/CaseInactiveFamilyItems.html) 18 | 19 |  -------------------------------------------------------------------------------- /samples/javascript.controls/common/TextBox.js: -------------------------------------------------------------------------------- 1 | import { ControlType } from './enums'; 2 | 3 | export function TextBoxConfig(id, defaultItem, caption, valueType, onUpdate) { 4 | this.controlType = ControlType.TextBox; 5 | this.id = id; 6 | this.defaultItem = defaultItem; 7 | this.caption = caption; 8 | this.valueType = valueType; 9 | this.onUpdate = onUpdate; 10 | }; 11 | 12 | export function TextBoxRender() { 13 | this.render = function (config, namespace, defaultValue) { 14 | var controlBody = ["span", 15 | ["br"], 16 | ["label", 17 | { 18 | "title": config.id, 19 | "for": namespace + config.id 20 | }, 21 | config.caption 22 | ], 23 | '\xa0', 24 | ["input", 25 | { 26 | "type": "text", 27 | "name=": namespace + config.id, 28 | "class": ["text", "ui-widget-content", "ui-corner-all"], 29 | "value": (defaultValue != null ? defaultValue : ""), 30 | "$": function (element) { 31 | element.addEventListener('change', function () { 32 | config.onUpdate(element, config); 33 | }); 34 | } 35 | } 36 | ] 37 | ]; 38 | 39 | return controlBody; 40 | }; 41 | 42 | this.getValue = function (item, namespace, formatters) { 43 | var formatter = formatters[item.valueType], 44 | element = document.getElementsByName(namespace + item.id)[0], 45 | result = formatter(element.value); 46 | return result; 47 | }; 48 | }; -------------------------------------------------------------------------------- /samples/LabelsCascadesInFamilyChart.md: -------------------------------------------------------------------------------- 1 | # Labels cascades over connection lines in family chart 2 | Label annotations are family diagram specific annotations. Label annotations are placed inside the diagram layout between nodes so they don't overlap nodes, can occupy relatively large space. Still, they require the control to rerender nodes when we add label annotations to the diagram. 3 | 4 | Label annotations can bind multiple nodes together, so visually label annotation can define aggregate value for several nodes bundled together. In the following example, we create a cascade of labels from the common parent down to its children. If two labels create mutually exclusive bundles, the first label wins. 5 | 6 | See primitives.LabelAnnotationConfig for details. By default, label annotations display regular text labels, but we can use node templates to define their content. So from this perspective, they are regular diagram nodes, having complex placement logic in the diagram. See templateName option of LabelAnnotationConfig and defaultLabelAnnotationTemplate of primitives.FamConfig class. 7 | 8 | [JavaScript](javascript.controls/CaseLabelsCascadesInFamilyChart.html) 9 | 10 |  11 | 12 | 13 | # Labels over connection lines in matrix-shaped family chart 14 | The following sample demonstrates how control shows labels around matrix of nodes. 15 | 16 | [JavaScript](javascript.controls/CaseLabelsNMatrixInFamilyChart.html) 17 | 18 |  19 | -------------------------------------------------------------------------------- /src/tasks/options/selection/HighlightItemOptionTask.js: -------------------------------------------------------------------------------- 1 | import ValueReader from '../../../readers/ValueReader'; 2 | import ObjectReader from '../../../readers/ObjectReader'; 3 | import EnumerationReader from '../../../readers/EnumerationReader'; 4 | import {NavigationMode } from '../../../enums'; 5 | 6 | export default function HighlightItemOptionTask(optionsTask, defaultConfig) { 7 | var _data = {}; 8 | 9 | var _dataTemplate = new ObjectReader({ 10 | highlightItem: new ValueReader(["string", "number"], true), 11 | navigationMode: new EnumerationReader(NavigationMode, false, defaultConfig.navigationMode), 12 | highlightGravityRadius: new ValueReader(["number"], false, defaultConfig.highlightGravityRadius) 13 | }); 14 | 15 | function process() { 16 | var context = { 17 | isChanged: false 18 | }; 19 | 20 | _data = _dataTemplate.read(_data, optionsTask.getOptions(), "options", context); 21 | 22 | return context.isChanged; 23 | } 24 | 25 | function getHighlightItem() { 26 | return _data.highlightItem; 27 | } 28 | 29 | function getGravityRadius() { 30 | return _data.highlightGravityRadius; 31 | } 32 | 33 | function hasHighlightEnabled() { 34 | switch (_data.navigationMode) { 35 | case NavigationMode.Default: 36 | case NavigationMode.HighlightOnly: 37 | return true; 38 | } 39 | return false; 40 | } 41 | 42 | return { 43 | process: process, 44 | getHighlightItem: getHighlightItem, 45 | hasHighlightEnabled: hasHighlightEnabled, 46 | getGravityRadius: getGravityRadius, 47 | description: "Checks highlight item option." 48 | }; 49 | }; -------------------------------------------------------------------------------- /src/tasks/options/ExtractNestedLayoutsOptionTask.js: -------------------------------------------------------------------------------- 1 | import ValueReader from '../../readers/ValueReader'; 2 | import ObjectReader from '../../readers/ObjectReader'; 3 | import ArrayReader from '../../readers/ArrayReader'; 4 | 5 | export default function ExtractNestedLayoutsOptionTask(optionsTask, defaultConfig, defaultItemConfig) { 6 | var _data = {}, 7 | _hash = {}; 8 | 9 | var _dataTemplate = new ObjectReader({ 10 | enableMatrixLayout: new ValueReader(["boolean"], false, defaultConfig.enableMatrixLayout), 11 | minimumMatrixSize: new ValueReader(["number"], false, defaultConfig.minimumMatrixSize), 12 | maximumColumnsInMatrix: new ValueReader(["number"], false, defaultConfig.maximumColumnsInMatrix), 13 | items: new ArrayReader( 14 | new ObjectReader({ 15 | id: new ValueReader(["string", "number"], true), 16 | matrixId: new ValueReader(["string", "number"], false, defaultItemConfig.matrixId), 17 | addToMatrix: new ValueReader(["boolean"], false, defaultItemConfig.addToMatrix), 18 | }), 19 | true, 20 | "id" 21 | ) 22 | }); 23 | 24 | function process() { 25 | var context = { 26 | isChanged: false, 27 | hash: _hash 28 | }; 29 | 30 | _data = _dataTemplate.read(_data, optionsTask.getOptions(), "options", context); 31 | 32 | return context.isChanged; 33 | } 34 | 35 | function getOptions() { 36 | return _data; 37 | } 38 | 39 | function getConfig(itemId) { 40 | return _hash["options-items"][itemId]; 41 | } 42 | 43 | return { 44 | process: process, 45 | getOptions: getOptions, 46 | getConfig: getConfig 47 | }; 48 | }; -------------------------------------------------------------------------------- /src/tasks/templates/ActiveItemsTask.js: -------------------------------------------------------------------------------- 1 | import ArrayReader from '../../readers/ArrayReader'; 2 | import ValueReader from '../../readers/ValueReader'; 3 | 4 | export default function ActiveItemsTask(itemsSizesOptionTask, readTemplatesTask) { 5 | var _data = { 6 | items: [] 7 | }, 8 | _hash = {}; 9 | 10 | var _dataTemplate = new ArrayReader( 11 | new ValueReader(["string", "number"], true), 12 | true 13 | ); 14 | 15 | function process() { 16 | var context = { 17 | isChanged: false, 18 | hash: _hash 19 | }, 20 | itemsSizesOptions = itemsSizesOptionTask.getOptions(), 21 | items = itemsSizesOptions.items; 22 | 23 | _data.items = _dataTemplate.read(_data.items, collectActiveItems(itemsSizesOptions, items), "items", context); 24 | 25 | return context.isChanged; 26 | } 27 | 28 | function collectActiveItems(itemsSizesOptions, items) { 29 | var result = [], 30 | index, len; 31 | for (index = 0, len = items.length; index < len; index += 1) { 32 | var itemConfig = items[index], 33 | template = readTemplatesTask.getTemplate(itemConfig.templateName, itemsSizesOptions.defaultTemplateName, readTemplatesTask.DefaultWidgetTemplateName), 34 | templateConfig = template.templateConfig, 35 | isActive = itemConfig.isActive && templateConfig.isActive; 36 | 37 | if (isActive) { 38 | result.push(itemConfig.id); 39 | } 40 | } 41 | return result; 42 | } 43 | 44 | function getActiveItems() { 45 | return _hash.items; 46 | } 47 | 48 | return { 49 | process: process, 50 | getActiveItems: getActiveItems 51 | }; 52 | }; -------------------------------------------------------------------------------- /samples/MultipleRootItemsInChart.md: -------------------------------------------------------------------------------- 1 | # Multiple root items in the chart 2 | 3 | Multiple root items are convenient to display tree structure having missing parent relations for some nodes. The control would render such hierarchy using multiple tree fragments placed side by side in the diagram. 4 | 5 | Following example shows two disconnected hierarchies: 6 | 7 | [JavaScript](javascript.controls/CaseMultipleRootItemsInChart.html) 8 | 9 |  10 | 11 | ## Matrix layout of multiple root items 12 | It is an extreme example when nodes don't have parent relations at all. So the control displays them in the form of a long horizontal list of nodes. It isn't easy to scroll and manage them. The suggested solution is to shape root items into the matrixed formation, so our fragments take less space and fit into the available screen space. 13 | The matrixed formation works best when we use drag and drop to merge nodes back to the tree structure, so we need to place our nodes close to each other. 14 | In the following example, we create an invisible root item and use it as a parent node for all our parentless nodes in the structure. Then we set its `childrenPlacementType` option to `primitives.ChildrenPlacementType.Matrix`, so our nine nodes form compact 3 * 3 matrix formation. 15 | 16 | 17 | See Children Layout example to place fragments vertically or horizontally. 18 | 19 | [JavaScript](javascript.controls/CaseMatrixLayoutOfMultipleRootItemsInChart.html) 20 | 21 |  22 | -------------------------------------------------------------------------------- /samples/javascript.controls/CaseFirstOrganizationalChart.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 | 5 |