Spaces:
Running
Running
Added handling of gzipped data in safari
Browse files- js/sigma/sigma.parseJson.js +183 -2
js/sigma/sigma.parseJson.js
CHANGED
@@ -3,6 +3,9 @@
|
|
3 |
// // based on parseGexf from Mathieu Jacomy @ Sciences Po M�dialab & WebAtlas
|
4 |
|
5 |
|
|
|
|
|
|
|
6 |
sigma.publicPrototype.parseJson = function(gzippedJsonPath, callback) {
|
7 |
var sigmaInstance = this;
|
8 |
|
@@ -41,7 +44,9 @@ sigma.publicPrototype.parseJson = function(gzippedJsonPath, callback) {
|
|
41 |
}
|
42 |
|
43 |
// Call the callback function if provided
|
44 |
-
if (callback)
|
|
|
|
|
45 |
} catch (error) {
|
46 |
console.error("Error processing gzipped JSON:", error);
|
47 |
}
|
@@ -55,4 +60,180 @@ sigma.publicPrototype.parseJson = function(gzippedJsonPath, callback) {
|
|
55 |
};
|
56 |
|
57 |
xhr.send();
|
58 |
-
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
3 |
// // based on parseGexf from Mathieu Jacomy @ Sciences Po M�dialab & WebAtlas
|
4 |
|
5 |
|
6 |
+
var isSafari = /^((?!chrome|android).)*safari/i.test(navigator.userAgent);
|
7 |
+
|
8 |
+
// Regular implementation for Chrome and other browsers
|
9 |
sigma.publicPrototype.parseJson = function(gzippedJsonPath, callback) {
|
10 |
var sigmaInstance = this;
|
11 |
|
|
|
44 |
}
|
45 |
|
46 |
// Call the callback function if provided
|
47 |
+
if (callback) {
|
48 |
+
callback.call(sigmaInstance);
|
49 |
+
}
|
50 |
} catch (error) {
|
51 |
console.error("Error processing gzipped JSON:", error);
|
52 |
}
|
|
|
60 |
};
|
61 |
|
62 |
xhr.send();
|
63 |
+
};
|
64 |
+
|
65 |
+
|
66 |
+
// Create a new function specifically for loading gzipped data safely
|
67 |
+
// This avoids sigma initialization issues by loading data first
|
68 |
+
var loadGzippedGraphData = function(gzippedJsonPath, callback) {
|
69 |
+
// Use XMLHttpRequest for binary data
|
70 |
+
var xhr = new XMLHttpRequest();
|
71 |
+
xhr.open('GET', gzippedJsonPath, true);
|
72 |
+
xhr.responseType = 'arraybuffer';
|
73 |
+
|
74 |
+
xhr.onload = function() {
|
75 |
+
if (xhr.status === 200) {
|
76 |
+
try {
|
77 |
+
// Decompress the gzipped data using pako
|
78 |
+
var inflatedData = pako.inflate(new Uint8Array(xhr.response));
|
79 |
+
|
80 |
+
// Convert binary data to string
|
81 |
+
var jsonString;
|
82 |
+
try {
|
83 |
+
jsonString = new TextDecoder('utf-8').decode(inflatedData);
|
84 |
+
} catch (e) {
|
85 |
+
// Fallback for older browsers
|
86 |
+
jsonString = "";
|
87 |
+
var array = inflatedData;
|
88 |
+
var i = 0, len = array.length;
|
89 |
+
var c, char2, char3;
|
90 |
+
|
91 |
+
while (i < len) {
|
92 |
+
c = array[i++];
|
93 |
+
switch (c >> 4) {
|
94 |
+
case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7:
|
95 |
+
// 0xxxxxxx
|
96 |
+
jsonString += String.fromCharCode(c);
|
97 |
+
break;
|
98 |
+
case 12: case 13:
|
99 |
+
// 110x xxxx 10xx xxxx
|
100 |
+
char2 = array[i++];
|
101 |
+
jsonString += String.fromCharCode(((c & 0x1F) << 6) | (char2 & 0x3F));
|
102 |
+
break;
|
103 |
+
case 14:
|
104 |
+
// 1110 xxxx 10xx xxxx 10xx xxxx
|
105 |
+
char2 = array[i++];
|
106 |
+
char3 = array[i++];
|
107 |
+
jsonString += String.fromCharCode(((c & 0x0F) << 12) |
|
108 |
+
((char2 & 0x3F) << 6) |
|
109 |
+
((char3 & 0x3F) << 0));
|
110 |
+
break;
|
111 |
+
}
|
112 |
+
}
|
113 |
+
}
|
114 |
+
|
115 |
+
// Parse the JSON
|
116 |
+
var jsonData = JSON.parse(jsonString);
|
117 |
+
|
118 |
+
// Return the parsed data to the callback
|
119 |
+
if (callback) {
|
120 |
+
callback(jsonData);
|
121 |
+
}
|
122 |
+
} catch (error) {
|
123 |
+
console.error("Error processing gzipped JSON:", error);
|
124 |
+
if (callback) {
|
125 |
+
callback(null, error);
|
126 |
+
}
|
127 |
+
}
|
128 |
+
} else {
|
129 |
+
console.error("Error fetching gzipped JSON. Status:", xhr.status);
|
130 |
+
if (callback) {
|
131 |
+
callback(null, new Error("HTTP status: " + xhr.status));
|
132 |
+
}
|
133 |
+
}
|
134 |
+
};
|
135 |
+
|
136 |
+
xhr.onerror = function() {
|
137 |
+
console.error("Network error while fetching gzipped JSON");
|
138 |
+
if (callback) {
|
139 |
+
callback(null, new Error("Network error"));
|
140 |
+
}
|
141 |
+
};
|
142 |
+
|
143 |
+
xhr.send();
|
144 |
+
};
|
145 |
+
|
146 |
+
|
147 |
+
|
148 |
+
|
149 |
+
// Safe initialization for Safari
|
150 |
+
function initSigmaWithGzippedData(containerId, gzippedJsonPath, options, callbackFn) {
|
151 |
+
// Make options parameter optional
|
152 |
+
if (typeof options === 'function') {
|
153 |
+
callbackFn = options;
|
154 |
+
options = {};
|
155 |
+
}
|
156 |
+
|
157 |
+
options = options || {};
|
158 |
+
|
159 |
+
// For Safari, use a completely different approach
|
160 |
+
if (isSafari) {
|
161 |
+
// First, load the data
|
162 |
+
loadGzippedGraphData(gzippedJsonPath, function(data, error) {
|
163 |
+
if (error || !data) {
|
164 |
+
console.error("Failed to load graph data:", error);
|
165 |
+
return;
|
166 |
+
}
|
167 |
+
|
168 |
+
// Wait for DOM to be completely ready
|
169 |
+
jQuery(document).ready(function() {
|
170 |
+
// Make sure container is ready with dimensions
|
171 |
+
var container = document.getElementById(containerId);
|
172 |
+
if (!container) {
|
173 |
+
console.error("Container not found:", containerId);
|
174 |
+
return;
|
175 |
+
}
|
176 |
+
|
177 |
+
// Ensure container has dimensions
|
178 |
+
if (!container.offsetWidth || !container.offsetHeight) {
|
179 |
+
container.style.width = container.style.width || "100%";
|
180 |
+
container.style.height = container.style.height || "500px";
|
181 |
+
container.style.display = "block";
|
182 |
+
}
|
183 |
+
|
184 |
+
// Wait for next animation frame to ensure DOM updates
|
185 |
+
requestAnimationFrame(function() {
|
186 |
+
// Create settings with explicit container reference
|
187 |
+
var sigmaSettings = Object.assign({}, options);
|
188 |
+
|
189 |
+
// Wait a bit more for Safari
|
190 |
+
setTimeout(function() {
|
191 |
+
try {
|
192 |
+
// Initialize sigma with empty graph first
|
193 |
+
var sigmaInstance = new sigma(containerId);
|
194 |
+
|
195 |
+
// Add nodes and edges manually
|
196 |
+
for (var i = 0; i < data.nodes.length; i++) {
|
197 |
+
var id = data.nodes[i].id;
|
198 |
+
sigmaInstance.addNode(id, data.nodes[i]);
|
199 |
+
}
|
200 |
+
|
201 |
+
for (var j = 0; j < data.edges.length; j++) {
|
202 |
+
var edgeNode = data.edges[j];
|
203 |
+
var source = edgeNode.source;
|
204 |
+
var target = edgeNode.target;
|
205 |
+
var label = edgeNode.label || "";
|
206 |
+
var eid = edgeNode.id;
|
207 |
+
|
208 |
+
sigmaInstance.addEdge(eid, source, target, edgeNode);
|
209 |
+
}
|
210 |
+
|
211 |
+
// Refresh the graph
|
212 |
+
sigmaInstance.refresh();
|
213 |
+
|
214 |
+
// Call user callback if provided
|
215 |
+
if (callbackFn) {
|
216 |
+
callbackFn(sigmaInstance);
|
217 |
+
}
|
218 |
+
} catch (e) {
|
219 |
+
console.error("Error initializing sigma:", e);
|
220 |
+
}
|
221 |
+
}, 300); // Longer delay for Safari
|
222 |
+
});
|
223 |
+
});
|
224 |
+
});
|
225 |
+
} else {
|
226 |
+
// For Chrome and others, use a more standard approach
|
227 |
+
jQuery(document).ready(function() {
|
228 |
+
try {
|
229 |
+
var sigmaInstance = new sigma(containerId);
|
230 |
+
sigmaInstance.parseGzippedJson(gzippedJsonPath, function() {
|
231 |
+
this.refresh();
|
232 |
+
if (callbackFn) callbackFn(this);
|
233 |
+
});
|
234 |
+
} catch (e) {
|
235 |
+
console.error("Error initializing sigma:", e);
|
236 |
+
}
|
237 |
+
});
|
238 |
+
}
|
239 |
+
}
|