genoverse 3.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (148) hide show
  1. package/.eslintrc.js +197 -0
  2. package/.github/workflows/test.yml +24 -0
  3. package/LICENSE.TXT +24 -0
  4. package/README.md +11 -0
  5. package/css/controlPanel.css +200 -0
  6. package/css/fileDrop.css +22 -0
  7. package/css/font-awesome.css +3 -0
  8. package/css/fullscreen.css +19 -0
  9. package/css/genoverse.css +466 -0
  10. package/css/karyotype.css +85 -0
  11. package/css/resizer.css +36 -0
  12. package/css/tooltips.css +26 -0
  13. package/css/trackControls.css +111 -0
  14. package/expanded.html +120 -0
  15. package/fontawesome/css/fontawesome.min.css +5 -0
  16. package/fontawesome/css/regular.min.css +5 -0
  17. package/fontawesome/css/solid.min.css +5 -0
  18. package/fontawesome/webfonts/fa-brands-400.ttf +0 -0
  19. package/fontawesome/webfonts/fa-brands-400.woff +0 -0
  20. package/fontawesome/webfonts/fa-brands-400.woff2 +0 -0
  21. package/fontawesome/webfonts/fa-regular-400.ttf +0 -0
  22. package/fontawesome/webfonts/fa-regular-400.woff +0 -0
  23. package/fontawesome/webfonts/fa-regular-400.woff2 +0 -0
  24. package/fontawesome/webfonts/fa-solid-900.ttf +0 -0
  25. package/fontawesome/webfonts/fa-solid-900.woff +0 -0
  26. package/fontawesome/webfonts/fa-solid-900.woff2 +0 -0
  27. package/help.pdf +0 -0
  28. package/i/sort_handle.png +0 -0
  29. package/index.html +68 -0
  30. package/index.js +83 -0
  31. package/jest.config.js +4 -0
  32. package/js/Genoverse.js +1681 -0
  33. package/js/Track/Controller/Sequence.js +17 -0
  34. package/js/Track/Controller/Stranded.js +73 -0
  35. package/js/Track/Controller.js +620 -0
  36. package/js/Track/Model/File/BAM.js +44 -0
  37. package/js/Track/Model/File/BED.js +116 -0
  38. package/js/Track/Model/File/GFF.js +40 -0
  39. package/js/Track/Model/File/VCF.js +101 -0
  40. package/js/Track/Model/File/WIG.js +67 -0
  41. package/js/Track/Model/File.js +36 -0
  42. package/js/Track/Model/Gene/Ensembl.js +22 -0
  43. package/js/Track/Model/Gene.js +5 -0
  44. package/js/Track/Model/Sequence/Ensembl.js +4 -0
  45. package/js/Track/Model/Sequence/Fasta.js +60 -0
  46. package/js/Track/Model/Sequence.js +50 -0
  47. package/js/Track/Model/SequenceVariation.js +41 -0
  48. package/js/Track/Model/Stranded.js +28 -0
  49. package/js/Track/Model/Transcript/Ensembl.js +67 -0
  50. package/js/Track/Model/Transcript.js +5 -0
  51. package/js/Track/Model.js +303 -0
  52. package/js/Track/View/Gene/Ensembl.js +46 -0
  53. package/js/Track/View/Gene.js +6 -0
  54. package/js/Track/View/Sequence/Variation.js +115 -0
  55. package/js/Track/View/Sequence.js +63 -0
  56. package/js/Track/View/Transcript/Ensembl.js +12 -0
  57. package/js/Track/View/Transcript.js +28 -0
  58. package/js/Track/View.js +566 -0
  59. package/js/Track/library/Chromosome.js +145 -0
  60. package/js/Track/library/File/BAM.js +30 -0
  61. package/js/Track/library/File/BED.js +24 -0
  62. package/js/Track/library/File/BIGBED.js +47 -0
  63. package/js/Track/library/File/BIGWIG.js +52 -0
  64. package/js/Track/library/File/GFF.js +9 -0
  65. package/js/Track/library/File/VCF.js +71 -0
  66. package/js/Track/library/File/WIG.js +5 -0
  67. package/js/Track/library/File.js +10 -0
  68. package/js/Track/library/Gene.js +37 -0
  69. package/js/Track/library/Graph/Bar.js +235 -0
  70. package/js/Track/library/Graph/Line.js +296 -0
  71. package/js/Track/library/Graph.js +355 -0
  72. package/js/Track/library/HighlightRegion.js +292 -0
  73. package/js/Track/library/Legend.js +224 -0
  74. package/js/Track/library/Scalebar.js +227 -0
  75. package/js/Track/library/Scaleline.js +91 -0
  76. package/js/Track/library/Static.js +78 -0
  77. package/js/Track/library/dbSNP.js +142 -0
  78. package/js/Track.js +632 -0
  79. package/js/genomes/grch37.js +990 -0
  80. package/js/genomes/grch38.js +990 -0
  81. package/js/genoverse.min.js +2 -0
  82. package/js/genoverse.min.js.map +1 -0
  83. package/js/lib/BWReader.js +578 -0
  84. package/js/lib/Base.js +145 -0
  85. package/js/lib/VCFReader.js +286 -0
  86. package/js/lib/dalliance/js/bam.js +494 -0
  87. package/js/lib/dalliance/js/bin.js +185 -0
  88. package/js/lib/dalliance/js/das.js +749 -0
  89. package/js/lib/dalliance/js/utils.js +370 -0
  90. package/js/lib/dalliance-lib.js +3594 -0
  91. package/js/lib/dalliance-lib.min.js +68 -0
  92. package/js/lib/jDataView.js +2 -0
  93. package/js/lib/jParser.js +192 -0
  94. package/js/lib/jquery-ui.js +8 -0
  95. package/js/lib/jquery.js +2 -0
  96. package/js/lib/jquery.mousehold.js +53 -0
  97. package/js/lib/jquery.mousewheel.js +84 -0
  98. package/js/lib/jquery.tipsy.js +258 -0
  99. package/js/lib/rtree.js +1 -0
  100. package/js/plugins/controlPanel.js +395 -0
  101. package/js/plugins/fileDrop.js +62 -0
  102. package/js/plugins/focusRegion.js +12 -0
  103. package/js/plugins/fullscreen.js +77 -0
  104. package/js/plugins/karyotype.js +210 -0
  105. package/js/plugins/resizer.js +45 -0
  106. package/js/plugins/tooltips.js +94 -0
  107. package/js/plugins/trackControls.js +143 -0
  108. package/package.json +43 -0
  109. package/test/View/__snapshots__/render-bar-graph.test.js.snap +111 -0
  110. package/test/View/__snapshots__/render-blocks.test.js.snap +105 -0
  111. package/test/View/__snapshots__/render-chromosome.test.js.snap +5 -0
  112. package/test/View/__snapshots__/render-highlights.test.js.snap +73 -0
  113. package/test/View/__snapshots__/render-insert-variants.test.js.snap +9 -0
  114. package/test/View/__snapshots__/render-labels.test.js.snap +241 -0
  115. package/test/View/__snapshots__/render-legends.test.js.snap +13 -0
  116. package/test/View/__snapshots__/render-line-graph.test.js.snap +349 -0
  117. package/test/View/__snapshots__/render-scalebar.test.js.snap +49 -0
  118. package/test/View/__snapshots__/render-scaleline.test.js.snap +31 -0
  119. package/test/View/__snapshots__/render-sequence.test.js.snap +23 -0
  120. package/test/View/__snapshots__/render-stranded.test.js.snap +5 -0
  121. package/test/View/__snapshots__/render-transcripts.test.js.snap +193 -0
  122. package/test/View/render-bar-graph.test.js +87 -0
  123. package/test/View/render-blocks.test.js +171 -0
  124. package/test/View/render-chromosome.test.js +40 -0
  125. package/test/View/render-highlights.test.js +67 -0
  126. package/test/View/render-insert-variants.test.js +11 -0
  127. package/test/View/render-labels.test.js +266 -0
  128. package/test/View/render-legends.test.js +31 -0
  129. package/test/View/render-line-graph.test.js +169 -0
  130. package/test/View/render-scalebar.test.js +36 -0
  131. package/test/View/render-scaleline.test.js +28 -0
  132. package/test/View/render-sequence.test.js +49 -0
  133. package/test/View/render-stranded.test.js +10 -0
  134. package/test/View/render-transcripts.test.js +165 -0
  135. package/test/create-and-destroy.test.js +63 -0
  136. package/test/track-ordering.test.js +514 -0
  137. package/test/track_config/__snapshots__/config-settings.test.js.snap +23 -0
  138. package/test/track_config/config-settings.test.js +321 -0
  139. package/test/track_config/zoom-level-settings.test.js +98 -0
  140. package/test/utils.js +80 -0
  141. package/utils/createGenome.js +52 -0
  142. package/utils/devServer.js +36 -0
  143. package/utils/expandedTemplate.html +46 -0
  144. package/utils/git-hooks/post-commit +9 -0
  145. package/utils/git-hooks/pre-commit +7 -0
  146. package/utils/git-hooks/setup +6 -0
  147. package/utils/makeExpanded.js +19 -0
  148. package/webpack.config.js +39 -0
@@ -0,0 +1,749 @@
1
+ /* -*- mode: javascript; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2
+
3
+ //
4
+ // Dalliance Genome Explorer
5
+ // (c) Thomas Down 2006-2010
6
+ //
7
+ // das.js: queries and low-level data model.
8
+ //
9
+
10
+ var dasLibErrorHandler = function(errMsg) {
11
+ alert(errMsg);
12
+ }
13
+ var dasLibRequestQueue = new Array();
14
+
15
+
16
+
17
+ function DASSegment(name, start, end, description) {
18
+ this.name = name;
19
+ this.start = start;
20
+ this.end = end;
21
+ this.description = description;
22
+ }
23
+ DASSegment.prototype.toString = function() {
24
+ return this.name + ':' + this.start + '..' + this.end;
25
+ };
26
+ DASSegment.prototype.isBounded = function() {
27
+ return this.start && this.end;
28
+ }
29
+ DASSegment.prototype.toDASQuery = function() {
30
+ var q = 'segment=' + this.name;
31
+ if (this.start && this.end) {
32
+ q += (':' + this.start + ',' + this.end);
33
+ }
34
+ return q;
35
+ }
36
+
37
+
38
+ function DASSource(a1, a2) {
39
+ var options;
40
+ if (typeof a1 == 'string') {
41
+ this.uri = a1;
42
+ options = a2 || {};
43
+ } else {
44
+ options = a1 || {};
45
+ }
46
+ for (var k in options) {
47
+ if (typeof(options[k]) != 'function') {
48
+ this[k] = options[k];
49
+ }
50
+ }
51
+
52
+
53
+ if (!this.coords) {
54
+ this.coords = [];
55
+ }
56
+ if (!this.props) {
57
+ this.props = {};
58
+ }
59
+
60
+ this.dasBaseURI = this.uri;
61
+ if (this.dasBaseURI && this.dasBaseURI.substr(this.uri.length - 1) != '/') {
62
+ this.dasBaseURI = this.dasBaseURI + '/';
63
+ }
64
+ }
65
+
66
+ function DASCoords() {
67
+ }
68
+
69
+ function coordsMatch(c1, c2) {
70
+ return c1.taxon == c2.taxon && c1.auth == c2.auth && c1.version == c2.version;
71
+ }
72
+
73
+ //
74
+ // DAS 1.6 entry_points command
75
+ //
76
+
77
+ DASSource.prototype.entryPoints = function(callback) {
78
+ var dasURI = this.dasBaseURI + 'entry_points';
79
+ this.doCrossDomainRequest(dasURI, function(responseXML) {
80
+ if (!responseXML) {
81
+ return callback([]);
82
+ }
83
+
84
+ var entryPoints = new Array();
85
+
86
+ var segs = responseXML.getElementsByTagName('SEGMENT');
87
+ for (var i = 0; i < segs.length; ++i) {
88
+ var seg = segs[i];
89
+ var segId = seg.getAttribute('id');
90
+
91
+ var segSize = seg.getAttribute('size');
92
+ var segMin, segMax;
93
+ if (segSize) {
94
+ segMin = 1; segMax = segSize|0;
95
+ } else {
96
+ segMin = seg.getAttribute('start');
97
+ if (segMin) {
98
+ segMin |= 0;
99
+ }
100
+ segMax = seg.getAttribute('stop');
101
+ if (segMax) {
102
+ segMax |= 0;
103
+ }
104
+ }
105
+ var segDesc = null;
106
+ if (seg.firstChild) {
107
+ segDesc = seg.firstChild.nodeValue;
108
+ }
109
+ entryPoints.push(new DASSegment(segId, segMin, segMax, segDesc));
110
+ }
111
+ callback(entryPoints);
112
+ });
113
+ }
114
+
115
+ //
116
+ // DAS 1.6 sequence command
117
+ // Do we need an option to fall back to the dna command?
118
+ //
119
+
120
+ function DASSequence(name, start, end, alpha, seq) {
121
+ this.name = name;
122
+ this.start = start;
123
+ this.end = end;
124
+ this.alphabet = alpha;
125
+ this.seq = seq;
126
+ }
127
+
128
+ DASSource.prototype.sequence = function(segment, callback) {
129
+ var dasURI = this.dasBaseURI + 'sequence?' + segment.toDASQuery();
130
+ this.doCrossDomainRequest(dasURI, function(responseXML) {
131
+ if (!responseXML) {
132
+ callback([]);
133
+ return;
134
+ } else {
135
+ var seqs = new Array();
136
+
137
+ var segs = responseXML.getElementsByTagName('SEQUENCE');
138
+ for (var i = 0; i < segs.length; ++i) {
139
+ var seg = segs[i];
140
+ var segId = seg.getAttribute('id');
141
+ var segMin = seg.getAttribute('start');
142
+ var segMax = seg.getAttribute('stop');
143
+ var segAlpha = 'DNA';
144
+ var segSeq = null;
145
+ if (seg.firstChild) {
146
+ var rawSeq = seg.firstChild.nodeValue;
147
+ segSeq = '';
148
+ var idx = 0;
149
+ while (true) {
150
+ var space = rawSeq.indexOf('\n', idx);
151
+ if (space >= 0) {
152
+ segSeq += rawSeq.substring(idx, space);
153
+ idx = space + 1;
154
+ } else {
155
+ segSeq += rawSeq.substring(idx);
156
+ break;
157
+ }
158
+ }
159
+ }
160
+ seqs.push(new DASSequence(segId, segMin, segMax, segAlpha, segSeq));
161
+ }
162
+
163
+ callback(seqs);
164
+ }
165
+ });
166
+ }
167
+
168
+ //
169
+ // DAS 1.6 features command
170
+ //
171
+
172
+ function DASFeature() {
173
+ // We initialize these in the parser...
174
+ }
175
+
176
+ function DASGroup() {
177
+ // We initialize these in the parser, too...
178
+ }
179
+
180
+ function DASLink(desc, uri) {
181
+ this.desc = desc;
182
+ this.uri = uri;
183
+ }
184
+
185
+ DASSource.prototype.features = function(segment, options, callback) {
186
+ options = options || {};
187
+ var thisB = this;
188
+
189
+ var dasURI;
190
+ if (this.features_uri) {
191
+ dasURI = this.features_uri;
192
+ } else {
193
+ var filters = [];
194
+
195
+ if (segment) {
196
+ filters.push(segment.toDASQuery());
197
+ } else if (options.group) {
198
+ var g = options.group;
199
+ if (typeof g == 'string') {
200
+ filters.push('group_id=' + g);
201
+ } else {
202
+ for (var gi = 0; gi < g.length; ++gi) {
203
+ filters.push('group_id=' + g[gi]);
204
+ }
205
+ }
206
+ }
207
+
208
+ if (options.adjacent) {
209
+ var adj = options.adjacent;
210
+ if (typeof adj == 'string') {
211
+ adj = [adj];
212
+ }
213
+ for (var ai = 0; ai < adj.length; ++ai) {
214
+ filters.push('adjacent=' + adj[ai]);
215
+ }
216
+ }
217
+
218
+ if (options.type) {
219
+ if (typeof options.type == 'string') {
220
+ filters.push('type=' + options.type);
221
+ } else {
222
+ for (var ti = 0; ti < options.type.length; ++ti) {
223
+ filters.push('type=' + options.type[ti]);
224
+ }
225
+ }
226
+ }
227
+
228
+ if (options.maxbins) {
229
+ filters.push('maxbins=' + options.maxbins);
230
+ }
231
+
232
+ if (filters.length > 0) {
233
+ dasURI = this.dasBaseURI + 'features?' + filters.join(';');
234
+ } else {
235
+ callback([], 'No filters specified');
236
+ }
237
+ }
238
+
239
+
240
+ this.doCrossDomainRequest(dasURI, function(responseXML, req) {
241
+ if (!responseXML) {
242
+ var msg;
243
+ if (req.status == 0) {
244
+ msg = 'server may not support CORS';
245
+ } else {
246
+ msg = 'status=' + req.status;
247
+ }
248
+ callback([], 'Failed request: ' + msg);
249
+ return;
250
+ }
251
+ /* if (req) {
252
+ var caps = req.getResponseHeader('X-DAS-Capabilties');
253
+ if (caps) {
254
+ alert(caps);
255
+ }
256
+ } */
257
+
258
+ var features = new Array();
259
+ var segmentMap = {};
260
+
261
+ var segs = responseXML.getElementsByTagName('SEGMENT');
262
+ for (var si = 0; si < segs.length; ++si) {
263
+ var segmentXML = segs[si];
264
+ var segmentID = segmentXML.getAttribute('id');
265
+ segmentMap[segmentID] = {
266
+ min: segmentXML.getAttribute('start'),
267
+ max: segmentXML.getAttribute('stop')
268
+ };
269
+
270
+ var featureXMLs = segmentXML.getElementsByTagName('FEATURE');
271
+ for (var i = 0; i < featureXMLs.length; ++i) {
272
+ var feature = featureXMLs[i];
273
+ var dasFeature = new DASFeature();
274
+
275
+ dasFeature.segment = segmentID;
276
+ dasFeature.id = feature.getAttribute('id');
277
+ dasFeature.label = feature.getAttribute('label');
278
+
279
+
280
+ /*
281
+ var childNodes = feature.childNodes;
282
+ for (var c = 0; c < childNodes.length; ++c) {
283
+ var cn = childNodes[c];
284
+ if (cn.nodeType == Node.ELEMENT_NODE) {
285
+ var key = cn.tagName;
286
+ //var val = null;
287
+ //if (cn.firstChild) {
288
+ // val = cn.firstChild.nodeValue;
289
+ //}
290
+ dasFeature[key] = 'x';
291
+ }
292
+ } */
293
+
294
+
295
+ var spos = elementValue(feature, "START");
296
+ var epos = elementValue(feature, "END");
297
+ if ((spos|0) > (epos|0)) {
298
+ dasFeature.min = epos|0;
299
+ dasFeature.max = spos|0;
300
+ } else {
301
+ dasFeature.min = spos|0;
302
+ dasFeature.max = epos|0;
303
+ }
304
+ {
305
+ var tec = feature.getElementsByTagName('TYPE');
306
+ if (tec.length > 0) {
307
+ var te = tec[0];
308
+ if (te.firstChild) {
309
+ dasFeature.type = te.firstChild.nodeValue;
310
+ }
311
+ dasFeature.typeId = te.getAttribute('id');
312
+ dasFeature.typeCv = te.getAttribute('cvId');
313
+ }
314
+ }
315
+ dasFeature.type = elementValue(feature, "TYPE");
316
+ if (!dasFeature.type && dasFeature.typeId) {
317
+ dasFeature.type = dasFeature.typeId; // FIXME?
318
+ }
319
+
320
+ dasFeature.method = elementValue(feature, "METHOD");
321
+ {
322
+ var ori = elementValue(feature, "ORIENTATION");
323
+ if (!ori) {
324
+ ori = '0';
325
+ }
326
+ dasFeature.orientation = ori;
327
+ }
328
+ dasFeature.score = elementValue(feature, "SCORE");
329
+ dasFeature.links = dasLinksOf(feature);
330
+ dasFeature.notes = dasNotesOf(feature);
331
+
332
+ var groups = feature.getElementsByTagName("GROUP");
333
+ for (var gi = 0; gi < groups.length; ++gi) {
334
+ var groupXML = groups[gi];
335
+ var dasGroup = new DASGroup();
336
+ dasGroup.type = groupXML.getAttribute('type');
337
+ dasGroup.id = groupXML.getAttribute('id');
338
+ dasGroup.links = dasLinksOf(groupXML);
339
+ dasGroup.notes = dasNotesOf(groupXML);
340
+ if (!dasFeature.groups) {
341
+ dasFeature.groups = new Array(dasGroup);
342
+ } else {
343
+ dasFeature.groups.push(dasGroup);
344
+ }
345
+ }
346
+
347
+ // Magic notes. Check with TAD before changing this.
348
+ if (dasFeature.notes) {
349
+ for (var ni = 0; ni < dasFeature.notes.length; ++ni) {
350
+ var n = dasFeature.notes[ni];
351
+ if (n.indexOf('Genename=') == 0) {
352
+ var gg = new DASGroup();
353
+ gg.type='gene';
354
+ gg.id = n.substring(9);
355
+ if (!dasFeature.groups) {
356
+ dasFeature.groups = new Array(gg);
357
+ } else {
358
+ dasFeature.groups.push(gg);
359
+ }
360
+ }
361
+ }
362
+ }
363
+
364
+ {
365
+ var pec = feature.getElementsByTagName('PART');
366
+ if (pec.length > 0) {
367
+ var parts = [];
368
+ for (var pi = 0; pi < pec.length; ++pi) {
369
+ parts.push(pec[pi].getAttribute('id'));
370
+ }
371
+ dasFeature.parts = parts;
372
+ }
373
+ }
374
+ {
375
+ var pec = feature.getElementsByTagName('PARENT');
376
+ if (pec.length > 0) {
377
+ var parents = [];
378
+ for (var pi = 0; pi < pec.length; ++pi) {
379
+ parents.push(pec[pi].getAttribute('id'));
380
+ }
381
+ dasFeature.parents = parents;
382
+ }
383
+ }
384
+
385
+ features.push(dasFeature);
386
+ }
387
+ }
388
+
389
+ callback(features, undefined, segmentMap);
390
+ },
391
+ function (err) {
392
+ callback([], err);
393
+ });
394
+ }
395
+
396
+ function DASAlignment(type) {
397
+ this.type = type;
398
+ this.objects = {};
399
+ this.blocks = [];
400
+ }
401
+
402
+ DASSource.prototype.alignments = function(segment, options, callback) {
403
+ var dasURI = this.dasBaseURI + 'alignment?query=' + segment;
404
+ this.doCrossDomainRequest(dasURI, function(responseXML) {
405
+ if (!responseXML) {
406
+ callback([], 'Failed request ' + dasURI);
407
+ return;
408
+ }
409
+
410
+ var alignments = [];
411
+ var aliXMLs = responseXML.getElementsByTagName('alignment');
412
+ for (var ai = 0; ai < aliXMLs.length; ++ai) {
413
+ var aliXML = aliXMLs[ai];
414
+ var ali = new DASAlignment(aliXML.getAttribute('alignType'));
415
+ var objXMLs = aliXML.getElementsByTagName('alignObject');
416
+ for (var oi = 0; oi < objXMLs.length; ++oi) {
417
+ var objXML = objXMLs[oi];
418
+ var obj = {
419
+ id: objXML.getAttribute('intObjectId'),
420
+ accession: objXML.getAttribute('dbAccessionId'),
421
+ version: objXML.getAttribute('objectVersion'),
422
+ dbSource: objXML.getAttribute('dbSource'),
423
+ dbVersion: objXML.getAttribute('dbVersion')
424
+ };
425
+ ali.objects[obj.id] = obj;
426
+ }
427
+
428
+ var blockXMLs = aliXML.getElementsByTagName('block');
429
+ for (var bi = 0; bi < blockXMLs.length; ++bi) {
430
+ var blockXML = blockXMLs[bi];
431
+ var block = {
432
+ order: blockXML.getAttribute('blockOrder'),
433
+ segments: []
434
+ };
435
+ var segXMLs = blockXML.getElementsByTagName('segment');
436
+ for (var si = 0; si < segXMLs.length; ++si) {
437
+ var segXML = segXMLs[si];
438
+ var seg = {
439
+ object: segXML.getAttribute('intObjectId'),
440
+ min: segXML.getAttribute('start'),
441
+ max: segXML.getAttribute('end'),
442
+ strand: segXML.getAttribute('strand'),
443
+ cigar: elementValue(segXML, 'cigar')
444
+ };
445
+ block.segments.push(seg);
446
+ }
447
+ ali.blocks.push(block);
448
+ }
449
+
450
+ alignments.push(ali);
451
+ }
452
+ callback(alignments);
453
+ });
454
+ }
455
+
456
+
457
+ function DASStylesheet() {
458
+ /*
459
+ this.highZoomStyles = new Object();
460
+ this.mediumZoomStyles = new Object();
461
+ this.lowZoomStyles = new Object();
462
+ */
463
+
464
+ this.styles = [];
465
+ }
466
+
467
+ DASStylesheet.prototype.pushStyle = function(filters, zoom, style) {
468
+ /*
469
+
470
+ if (!zoom) {
471
+ this.highZoomStyles[type] = style;
472
+ this.mediumZoomStyles[type] = style;
473
+ this.lowZoomStyles[type] = style;
474
+ } else if (zoom == 'high') {
475
+ this.highZoomStyles[type] = style;
476
+ } else if (zoom == 'medium') {
477
+ this.mediumZoomStyles[type] = style;
478
+ } else if (zoom == 'low') {
479
+ this.lowZoomStyles[type] = style;
480
+ }
481
+
482
+ */
483
+
484
+ if (!filters) {
485
+ filters = {type: 'default'};
486
+ }
487
+ var styleHolder = shallowCopy(filters);
488
+ if (zoom) {
489
+ styleHolder.zoom = zoom;
490
+ }
491
+ styleHolder.style = style;
492
+ this.styles.push(styleHolder);
493
+ }
494
+
495
+ function DASStyle() {
496
+ }
497
+
498
+ DASSource.prototype.stylesheet = function(successCB, failureCB) {
499
+ var dasURI, creds = this.credentials;
500
+ if (this.stylesheet_uri) {
501
+ dasURI = this.stylesheet_uri;
502
+ creds = false;
503
+ } else {
504
+ dasURI = this.dasBaseURI + 'stylesheet';
505
+ }
506
+
507
+ doCrossDomainRequest(dasURI, function(responseXML) {
508
+ if (!responseXML) {
509
+ if (failureCB) {
510
+ failureCB();
511
+ }
512
+ return;
513
+ }
514
+ var stylesheet = new DASStylesheet();
515
+ var typeXMLs = responseXML.getElementsByTagName('TYPE');
516
+ for (var i = 0; i < typeXMLs.length; ++i) {
517
+ var typeStyle = typeXMLs[i];
518
+
519
+ var filter = {};
520
+ filter.type = typeStyle.getAttribute('id'); // Am I right in thinking that this makes DASSTYLE XML invalid? Ugh.
521
+ filter.label = typeStyle.getAttribute('label');
522
+ filter.method = typeStyle.getAttribute('method');
523
+ var glyphXMLs = typeStyle.getElementsByTagName('GLYPH');
524
+ for (var gi = 0; gi < glyphXMLs.length; ++gi) {
525
+ var glyphXML = glyphXMLs[gi];
526
+ var zoom = glyphXML.getAttribute('zoom');
527
+ var glyph = childElementOf(glyphXML);
528
+ var style = new DASStyle();
529
+ style.glyph = glyph.localName;
530
+ var child = glyph.firstChild;
531
+
532
+ while (child) {
533
+ if (child.nodeType == Node.ELEMENT_NODE) {
534
+ // alert(child.localName);
535
+ style[child.localName] = child.firstChild.nodeValue;
536
+ }
537
+ child = child.nextSibling;
538
+ }
539
+ stylesheet.pushStyle(filter, zoom, style);
540
+ }
541
+ }
542
+ successCB(stylesheet);
543
+ }, creds);
544
+ }
545
+
546
+ //
547
+ // sources command
548
+ //
549
+
550
+ function DASRegistry(uri, opts)
551
+ {
552
+ opts = opts || {};
553
+ this.uri = uri;
554
+ this.opts = opts;
555
+ }
556
+
557
+ DASRegistry.prototype.sources = function(callback, failure, opts)
558
+ {
559
+ if (!opts) {
560
+ opts = {};
561
+ }
562
+
563
+ var filters = [];
564
+ if (opts.taxon) {
565
+ filters.push('organism=' + opts.taxon);
566
+ }
567
+ if (opts.auth) {
568
+ filters.push('authority=' + opts.auth);
569
+ }
570
+ if (opts.version) {
571
+ filters.push('version=' + opts.version);
572
+ }
573
+ var quri = this.uri;
574
+ if (filters.length > 0) {
575
+ quri = quri + '?' + filters.join('&'); // '&' as a separator to hack around dasregistry.org bug.
576
+ }
577
+
578
+ doCrossDomainRequest(quri, function(responseXML) {
579
+ if (!responseXML && failure) {
580
+ failure();
581
+ return;
582
+ }
583
+
584
+ var sources = [];
585
+ var sourceXMLs = responseXML.getElementsByTagName('SOURCE');
586
+ for (var si = 0; si < sourceXMLs.length; ++si) {
587
+ var sourceXML = sourceXMLs[si];
588
+ var versionXMLs = sourceXML.getElementsByTagName('VERSION');
589
+ if (versionXMLs.length < 1) {
590
+ continue;
591
+ }
592
+ var versionXML = versionXMLs[0];
593
+
594
+ var coordXMLs = versionXML.getElementsByTagName('COORDINATES');
595
+ var coords = [];
596
+ for (var ci = 0; ci < coordXMLs.length; ++ci) {
597
+ var coordXML = coordXMLs[ci];
598
+ var coord = new DASCoords();
599
+ coord.auth = coordXML.getAttribute('authority');
600
+ coord.taxon = coordXML.getAttribute('taxid');
601
+ coord.version = coordXML.getAttribute('version');
602
+ coords.push(coord);
603
+ }
604
+
605
+ var caps = [];
606
+ var capXMLs = versionXML.getElementsByTagName('CAPABILITY');
607
+ var uri;
608
+ for (var ci = 0; ci < capXMLs.length; ++ci) {
609
+ var capXML = capXMLs[ci];
610
+
611
+ caps.push(capXML.getAttribute('type'));
612
+
613
+ if (capXML.getAttribute('type') == 'das1:features') {
614
+ var fep = capXML.getAttribute('query_uri');
615
+ uri = fep.substring(0, fep.length - ('features'.length));
616
+ }
617
+ }
618
+
619
+ var props = {};
620
+ var propXMLs = versionXML.getElementsByTagName('PROP');
621
+ for (var pi = 0; pi < propXMLs.length; ++pi) {
622
+ pusho(props, propXMLs[pi].getAttribute('name'), propXMLs[pi].getAttribute('value'));
623
+ }
624
+
625
+ if (uri) {
626
+ var source = new DASSource(uri, {
627
+ source_uri: sourceXML.getAttribute('uri'),
628
+ name: sourceXML.getAttribute('title'),
629
+ desc: sourceXML.getAttribute('description'),
630
+ coords: coords,
631
+ props: props,
632
+ capabilities: caps
633
+ });
634
+ sources.push(source);
635
+ }
636
+ }
637
+
638
+ callback(sources);
639
+ });
640
+ }
641
+
642
+
643
+ //
644
+ // Utility functions
645
+ //
646
+
647
+ function elementValue(element, tag)
648
+ {
649
+ var children = element.getElementsByTagName(tag);
650
+ if (children.length > 0 && children[0].firstChild) {
651
+ return children[0].firstChild.nodeValue;
652
+ } else {
653
+ return null;
654
+ }
655
+ }
656
+
657
+ function childElementOf(element)
658
+ {
659
+ if (element.hasChildNodes()) {
660
+ var child = element.firstChild;
661
+ do {
662
+ if (child.nodeType == Node.ELEMENT_NODE) {
663
+ return child;
664
+ }
665
+ child = child.nextSibling;
666
+ } while (child != null);
667
+ }
668
+ return null;
669
+ }
670
+
671
+
672
+ function dasLinksOf(element)
673
+ {
674
+ var links = new Array();
675
+ var maybeLinkChilden = element.getElementsByTagName('LINK');
676
+ for (var ci = 0; ci < maybeLinkChilden.length; ++ci) {
677
+ var linkXML = maybeLinkChilden[ci];
678
+ if (linkXML.parentNode == element) {
679
+ links.push(new DASLink(linkXML.firstChild ? linkXML.firstChild.nodeValue : 'Unknown', linkXML.getAttribute('href')));
680
+ }
681
+ }
682
+
683
+ return links;
684
+ }
685
+
686
+ function dasNotesOf(element)
687
+ {
688
+ var notes = [];
689
+ var maybeNotes = element.getElementsByTagName('NOTE');
690
+ for (var ni = 0; ni < maybeNotes.length; ++ni) {
691
+ if (maybeNotes[ni].firstChild) {
692
+ notes.push(maybeNotes[ni].firstChild.nodeValue);
693
+ }
694
+ }
695
+ return notes;
696
+ }
697
+
698
+ function doCrossDomainRequest(url, handler, credentials, custAuth) {
699
+ // TODO: explicit error handlers?
700
+
701
+ if (window.XDomainRequest) {
702
+ var req = new XDomainRequest();
703
+ req.onload = function() {
704
+ var dom = new ActiveXObject("Microsoft.XMLDOM");
705
+ dom.async = false;
706
+ dom.loadXML(req.responseText);
707
+ handler(dom);
708
+ }
709
+ req.open("get", url);
710
+ req.send('');
711
+ } else {
712
+ var reqStart = Date.now();
713
+ var req = new XMLHttpRequest();
714
+
715
+ req.onreadystatechange = function() {
716
+ if (req.readyState == 4) {
717
+ if (req.status >= 200 || req.status == 0) {
718
+ handler(req.responseXML, req);
719
+ }
720
+ }
721
+ };
722
+ req.open("get", url, true);
723
+ if (credentials) {
724
+ req.withCredentials = true;
725
+ }
726
+ if (custAuth) {
727
+ req.setRequestHeader('X-DAS-Authorisation', custAuth);
728
+ }
729
+ req.setRequestHeader('Accept', 'application/xml,*/*');
730
+ req.send('');
731
+ }
732
+ }
733
+
734
+ DASSource.prototype.doCrossDomainRequest = function(url, handler, errHandler) {
735
+ var custAuth;
736
+ if (this.xUser) {
737
+ custAuth = 'Basic ' + btoa(this.xUser + ':' + this.xPass);
738
+ }
739
+
740
+ try {
741
+ return doCrossDomainRequest(url, handler, this.credentials, custAuth);
742
+ } catch (err) {
743
+ if (errHandler) {
744
+ errHandler(err);
745
+ } else {
746
+ throw err;
747
+ }
748
+ }
749
+ }