UNPKG

2.38 kBJavaScriptView Raw
1import { select, selection } from "d3-selection";
2import slice from "../utils/slice";
3import warn from "../utils/warn";
4import getdirs from "./getdirs";
5
6// Extend selection prototype with new methods
7selection.prototype.mount = mount;
8selection.prototype.view = view;
9selection.prototype.model = model;
10selection.prototype.directives = directives;
11
12function directives(vm) {
13 const node = this.node();
14 let dirs = node.__d3_directives__;
15 if (dirs === undefined) {
16 dirs = getdirs(node, vm);
17 // no point in storing the directive object if there are no directives or the node is not a component
18 node.__d3_directives__ =
19 dirs.size() || getComponent(node, vm) ? dirs : null;
20 }
21 return dirs ? dirs : getdirs(node);
22}
23
24function model() {
25 var vm = this.view();
26 return vm ? vm.model : null;
27}
28
29function view(value) {
30 if (arguments.length) {
31 return this.property("__d3_view__", value);
32 } else {
33 var element = this.node(),
34 view = element ? element.__d3_view__ : null,
35 parent = element ? element.parentNode : null;
36
37 while (parent && !view) {
38 view = parent.__d3_view__;
39 parent = parent.parentNode;
40 }
41 return view;
42 }
43}
44
45//
46// mount function on a d3 selection
47// Use this function to mount the selection
48// This method returns nothing or a promise
49function mount(data) {
50 var promises = [];
51 this.each(function() {
52 var view = select(this).view();
53 if (view) promises.push(mountElement(this, view, data));
54 else warn("Cannot mount, no view object available to mount to");
55 });
56 return Promise.all(promises);
57}
58
59// INTERNALS
60
61// mount an element into a given model
62const mountElement = (element, vm, data) => {
63 if (!element || !element.tagName) return;
64
65 var component = getComponent(element, vm),
66 directives = select(element).directives(vm),
67 preMount = directives.preMount();
68
69 if (preMount) return preMount.execute(vm.model);
70 else {
71 if (component) {
72 return component({ parent: vm })
73 .mount(element, data)
74 .then(cm => {
75 directives.execute(cm.model);
76 return cm;
77 });
78 } else {
79 directives.execute(vm.model);
80 return Promise.all(
81 slice(element.children).map(c => mountElement(c, vm, data))
82 );
83 }
84 }
85};
86
87const getComponent = (element, vm) => {
88 return vm.components.get(element.tagName.toLowerCase());
89};