Spaces:
Running
Running
// // Scott Hale (Oxford Internet Institute) | |
// // Requires sigma.js and jquery to be loaded | |
// // based on parseGexf from Mathieu Jacomy @ Sciences Po M�dialab & WebAtlas | |
var isSafari = /^((?!chrome|android).)*safari/i.test(navigator.userAgent); | |
// Regular implementation for Chrome and other browsers | |
sigma.publicPrototype.parseJson = function(gzippedJsonPath, callback) { | |
var sigmaInstance = this; | |
// Use XMLHttpRequest for binary data | |
var xhr = new XMLHttpRequest(); | |
xhr.open('GET', gzippedJsonPath, true); | |
xhr.responseType = 'arraybuffer'; | |
xhr.onload = function() { | |
if (xhr.status === 200) { | |
try { | |
// Decompress the gzipped data using pako | |
var inflatedData = pako.inflate(new Uint8Array(xhr.response)); | |
// Convert binary data to string | |
var jsonString = new TextDecoder('utf-8').decode(inflatedData); | |
// Parse the JSON | |
var jsonData = JSON.parse(jsonString); | |
// Process nodes | |
for (var i = 0; i < jsonData.nodes.length; i++) { | |
var id = jsonData.nodes[i].id; | |
sigmaInstance.addNode(id, jsonData.nodes[i]); | |
} | |
// Process edges | |
for (var j = 0; j < jsonData.edges.length; j++) { | |
var edgeNode = jsonData.edges[j]; | |
var source = edgeNode.source; | |
var target = edgeNode.target; | |
var label = edgeNode.label; | |
var eid = edgeNode.id; | |
sigmaInstance.addEdge(eid, source, target, edgeNode); | |
} | |
// Call the callback function if provided | |
if (callback) { | |
callback.call(sigmaInstance); | |
} | |
} catch (error) { | |
console.error("Error processing gzipped JSON:", error); | |
} | |
} else { | |
console.error("Error fetching gzipped JSON. Status:", xhr.status); | |
} | |
}; | |
xhr.onerror = function() { | |
console.error("Network error while fetching gzipped JSON"); | |
}; | |
xhr.send(); | |
}; | |
// Create a new function specifically for loading gzipped data safely | |
// This avoids sigma initialization issues by loading data first | |
var loadGzippedGraphData = function(gzippedJsonPath, callback) { | |
// Use XMLHttpRequest for binary data | |
var xhr = new XMLHttpRequest(); | |
xhr.open('GET', gzippedJsonPath, true); | |
xhr.responseType = 'arraybuffer'; | |
xhr.onload = function() { | |
if (xhr.status === 200) { | |
try { | |
// Decompress the gzipped data using pako | |
var inflatedData = pako.inflate(new Uint8Array(xhr.response)); | |
// Convert binary data to string | |
var jsonString; | |
try { | |
jsonString = new TextDecoder('utf-8').decode(inflatedData); | |
} catch (e) { | |
// Fallback for older browsers | |
jsonString = ""; | |
var array = inflatedData; | |
var i = 0, len = array.length; | |
var c, char2, char3; | |
while (i < len) { | |
c = array[i++]; | |
switch (c >> 4) { | |
case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7: | |
// 0xxxxxxx | |
jsonString += String.fromCharCode(c); | |
break; | |
case 12: case 13: | |
// 110x xxxx 10xx xxxx | |
char2 = array[i++]; | |
jsonString += String.fromCharCode(((c & 0x1F) << 6) | (char2 & 0x3F)); | |
break; | |
case 14: | |
// 1110 xxxx 10xx xxxx 10xx xxxx | |
char2 = array[i++]; | |
char3 = array[i++]; | |
jsonString += String.fromCharCode(((c & 0x0F) << 12) | | |
((char2 & 0x3F) << 6) | | |
((char3 & 0x3F) << 0)); | |
break; | |
} | |
} | |
} | |
// Parse the JSON | |
var jsonData = JSON.parse(jsonString); | |
// Return the parsed data to the callback | |
if (callback) { | |
callback(jsonData); | |
} | |
} catch (error) { | |
console.error("Error processing gzipped JSON:", error); | |
if (callback) { | |
callback(null, error); | |
} | |
} | |
} else { | |
console.error("Error fetching gzipped JSON. Status:", xhr.status); | |
if (callback) { | |
callback(null, new Error("HTTP status: " + xhr.status)); | |
} | |
} | |
}; | |
xhr.onerror = function() { | |
console.error("Network error while fetching gzipped JSON"); | |
if (callback) { | |
callback(null, new Error("Network error")); | |
} | |
}; | |
xhr.send(); | |
}; | |
// Safe initialization for Safari | |
function initSigmaWithGzippedData(containerId, gzippedJsonPath, options, callbackFn) { | |
// Make options parameter optional | |
if (typeof options === 'function') { | |
callbackFn = options; | |
options = {}; | |
} | |
options = options || {}; | |
// For Safari, use a completely different approach | |
if (isSafari) { | |
// First, load the data | |
loadGzippedGraphData(gzippedJsonPath, function(data, error) { | |
if (error || !data) { | |
console.error("Failed to load graph data:", error); | |
return; | |
} | |
// Wait for DOM to be completely ready | |
jQuery(document).ready(function() { | |
// Make sure container is ready with dimensions | |
var container = document.getElementById(containerId); | |
if (!container) { | |
console.error("Container not found:", containerId); | |
return; | |
} | |
// Ensure container has dimensions | |
if (!container.offsetWidth || !container.offsetHeight) { | |
container.style.width = container.style.width || "100%"; | |
container.style.height = container.style.height || "500px"; | |
container.style.display = "block"; | |
} | |
// Wait for next animation frame to ensure DOM updates | |
requestAnimationFrame(function() { | |
// Create settings with explicit container reference | |
var sigmaSettings = Object.assign({}, options); | |
// Wait a bit more for Safari | |
setTimeout(function() { | |
try { | |
// Initialize sigma with empty graph first | |
var sigmaInstance = new sigma(containerId); | |
// Add nodes and edges manually | |
for (var i = 0; i < data.nodes.length; i++) { | |
var id = data.nodes[i].id; | |
sigmaInstance.addNode(id, data.nodes[i]); | |
} | |
for (var j = 0; j < data.edges.length; j++) { | |
var edgeNode = data.edges[j]; | |
var source = edgeNode.source; | |
var target = edgeNode.target; | |
var label = edgeNode.label || ""; | |
var eid = edgeNode.id; | |
sigmaInstance.addEdge(eid, source, target, edgeNode); | |
} | |
// Refresh the graph | |
sigmaInstance.refresh(); | |
// Call user callback if provided | |
if (callbackFn) { | |
callbackFn(sigmaInstance); | |
} | |
} catch (e) { | |
console.error("Error initializing sigma:", e); | |
} | |
}, 300); // Longer delay for Safari | |
}); | |
}); | |
}); | |
} else { | |
// For Chrome and others, use a more standard approach | |
jQuery(document).ready(function() { | |
try { | |
var sigmaInstance = new sigma(containerId); | |
sigmaInstance.parseGzippedJson(gzippedJsonPath, function() { | |
this.refresh(); | |
if (callbackFn) callbackFn(this); | |
}); | |
} catch (e) { | |
console.error("Error initializing sigma:", e); | |
} | |
}); | |
} | |
} |