forked from Chuqiaoo/foamtree
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcarrotsearch.foamtree.util.loading.js
162 lines (147 loc) · 5.62 KB
/
carrotsearch.foamtree.util.loading.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
/**
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
* Copyright 2002-2017, Carrot Search s.c, All Rights Reserved.
*
*
* A simple utility for attaching showing and hiding a
* data loading and preparation progress indicator. The utility
* will create and attach all the necessary HTML to the page.
*
* Please see demos/loading.html for the usage example.
*
* @param foamtree the FoamTree instance whose loading and
* layout preparation progress should be monitored
* @param indicatorHtml the HTML representing the loading message
*/
window.CarrotSearchFoamTree.loader = function(foamtree, indicatorHtml) {
var deferDataObjectChange = false, dataObjectToSet = undefined;
var dataObjectToSetProvided = false;
// Duration of the loading element CSS transition. You may
// need to modify this value if you modified the default CSS transitions.
var duration = 350;
// On Webkit CSS transitions seem to continue running during JS processing.
// Other browsers need to wait for the transition to complete.
var waitForTransition = !/chrome|webkit/.test(navigator.userAgent.toLowerCase());
// Create the indicator element
var indicator = document.createElement("div");
indicator.className = "visualization-loading fadeout";
indicator.innerHTML = indicatorHtml;
foamtree.get("element").appendChild(indicator);
// Hide the indicator when rollout starts
foamtree.on("rolloutStart", hideIndicator);
return {
/**
* Call this method before data loading is initiated to
* show the loading indicator.
*
* If FoamTree is set to perform a pullback animation,
* the loading indicator will show after pullback is complete.
*/
started: function() {
dataObjectToSetProvided = false;
if (isPullbackEnabled()) {
// We'll defer setting of the new data object
// until pullback completes. FoamTree does that
// internally too, but we need to show the indicator
// before we set the new data object. If we didn't
// do that, the element would actually show after
// the diagram computation completes, which wouldn't
// make much sense.
deferDataObjectChange = true;
once("modelChanged", showIndicatorAndSetDataObject);
// Set an empty data object to trigger a pullback
foamtree.set("dataObject", null);
} else {
deferDataObjectChange = false;
showIndicator();
}
},
/**
* Call this method when data loading completes. This method
* will take care of setting the new data object on FoamTree
* and hiding the indicator when the diagram is ready to show.
*
* @param dataObject new data object to set
*/
complete: function (dataObject) {
dataObjectToSetProvided = true;
if (deferDataObjectChange) {
// Just remember the new data object, we'll set it
// after the pullback completes and the loading indicator
// is made visible.
dataObjectToSet = dataObject;
} else {
// Defer the update to give the browser a chance
// to show the loading indicator.
setTimeout(function() {
foamtree.set("dataObject", dataObject);
hideIndicatorIfDataObjectEmpty(dataObjectToSet);
}, 1 + (waitForTransition ? duration + 50 : 1));
}
}
};
function showIndicatorAndSetDataObject() {
showIndicator();
if (dataObjectToSetProvided && deferDataObjectChange) {
// Defer the update to give the browser a chance
// to show the loading indicator.
setTimeout(function() {
foamtree.set("dataObject", dataObjectToSet);
hideIndicatorIfDataObjectEmpty(dataObjectToSet);
}, 5 + (waitForTransition ? duration + 50 : 1));
}
deferDataObjectChange = false;
}
function hideIndicatorIfDataObjectEmpty(dataObject) {
if (!dataObject || !dataObject.groups || dataObject.groups.length == 0) {
hideIndicator();
}
}
function hideIndicator() {
addClass(indicator, "fadeout");
}
function showIndicator() {
// It would be good to defer showing of the indicator a bit
// so that it's not shown when the loading process completes
// very quickly. However, it's not currently possible to implement
// because FoamTree diagram computation is performed in one
// go and blocks until the computation completes. In the future,
// it would be good to split the computation into chunks between
// which FoamTree would yield to the UI thread to redraw the
// DOM updates.
removeClass(indicator, "fadeout");
}
function addClass(element, clazz) {
var classes = element.className.split(/\s+/);
if (classes.indexOf(clazz) < 0) {
classes.push(clazz);
element.className = classes.join(" ");
}
}
function removeClass(element, clazz) {
element.className = element.className.split(/\s+/).filter(function (c) {
return c != clazz;
}).join(" ");
}
function isPullbackEnabled() {
return foamtree.get("pullbackDuration") > 0 || foamtree.get("fadeDuration") > 0;
}
function once(event, fn) {
foamtree.on(event, function() {
foamtree.off(event);
fn();
});
}
};