File size: 7,689 Bytes
7e48311
 
 
27e7d8e
 
932fbc6
 
 
7e48311
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
932fbc6
 
 
7e48311
 
 
 
 
 
 
 
 
 
 
 
 
932fbc6
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
// // 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);
      }
    });
  }
}