imerss-bioinfo 1.0.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 (182) hide show
  1. package/README.md +156 -0
  2. package/build.js +196 -0
  3. package/docs/css/imerss-viz-all.css +1227 -0
  4. package/docs/css/imerss-viz-wp-overrides.css +70 -0
  5. package/docs/css/pepiowelh.css +76 -0
  6. package/docs/css/xetthecum-external.css +47 -0
  7. package/docs/css/xetthecum-shared.css +80 -0
  8. package/docs/css/xetthecum.css +526 -0
  9. package/docs/js/imerss-viz-all.js +58 -0
  10. package/docs/js/imerss-viz-all.js.map +1 -0
  11. package/docs/js/jquery.js +10881 -0
  12. package/index.html +81 -0
  13. package/index.js +7 -0
  14. package/indexWithJustMap.html +92 -0
  15. package/indexWithMap.html +79 -0
  16. package/indexWithMapHoweSound.html +91 -0
  17. package/indexWithMapPepiowelh.html +119 -0
  18. package/indexWithMapValdes.html +90 -0
  19. package/indexWithMapXetthecum.html +90 -0
  20. package/package.json +50 -0
  21. package/src/WoRMS/taxonAPI.js +13 -0
  22. package/src/arphify.js +662 -0
  23. package/src/assignNames.js +103 -0
  24. package/src/auxBuild/restoreJQuery.js +1 -0
  25. package/src/buildSource/Comprehensive Lists.html +42 -0
  26. package/src/buildSource/Data Paper Part I Visualisation.html +50 -0
  27. package/src/buildSource/Galiano Life List.html +43 -0
  28. package/src/buildSource/Metchosin/index.html +22 -0
  29. package/src/buildSource/Pe'pi'ow'elh.html +72 -0
  30. package/src/buildSource/Squamish Life List.html +48 -0
  31. package/src/buildSource/Valdes Island Biodiversity.html +64 -0
  32. package/src/buildSource/Xetthecum.html +40 -0
  33. package/src/buildSource/dataPaperSunburstAndMap.html +30 -0
  34. package/src/buildSource/index.html +224 -0
  35. package/src/client/css/imerss-viz-wp-overrides.css +70 -0
  36. package/src/client/css/imerss-viz.css +531 -0
  37. package/src/client/css/pepiowelh.css +76 -0
  38. package/src/client/css/xetthecum-external.css +47 -0
  39. package/src/client/css/xetthecum-shared.css +80 -0
  40. package/src/client/css/xetthecum.css +526 -0
  41. package/src/client/html/imerss-viz-map-only.html +75 -0
  42. package/src/client/html/imerss-viz-map-pepi.html +77 -0
  43. package/src/client/html/imerss-viz-map-xetthecum.html +90 -0
  44. package/src/client/html/imerss-viz-map.html +75 -0
  45. package/src/client/html/imerss-viz.html +58 -0
  46. package/src/client/html/importing Xetthecum patterns.txt +10 -0
  47. package/src/client/html/xetthecum-patterns.html +27 -0
  48. package/src/client/img/Animalia_2.svg +1 -0
  49. package/src/client/img/Animalia_Annelida.svg +655 -0
  50. package/src/client/img/Animalia_Chaetognatha.svg +72 -0
  51. package/src/client/img/Animalia_Cnidaria.svg +173 -0
  52. package/src/client/img/Animalia_Ctenophora.svg +298 -0
  53. package/src/client/img/Animalia_Nemertea.svg +54 -0
  54. package/src/client/img/Animalia_Phoronida.svg +271 -0
  55. package/src/client/img/Animalia_Platyhelminthes.svg +58 -0
  56. package/src/client/img/Animalia_Porifera.svg +220 -0
  57. package/src/client/img/Animalia_Sipuncula.svg +155 -0
  58. package/src/client/img/Arachnoidiscus_schmidtii_web_1-2-scaled.webp +0 -0
  59. package/src/client/img/Arrow-down.svg +11 -0
  60. package/src/client/img/Arrow-up.svg +6 -0
  61. package/src/client/img/Chromista.svg +1 -0
  62. package/src/client/img/Pepiowelh/BlackNoWe2-wb-bb.png +0 -0
  63. package/src/client/img/Pepiowelh/BlackNoWe2-wb.png +0 -0
  64. package/src/client/img/Pepiowelh/BlackNoWe2.png +0 -0
  65. package/src/client/img/Pepiowelh/Ecocultural Mapping Banner.svg +1 -0
  66. package/src/client/img/Plankton.jpg +0 -0
  67. package/src/client/img/Plantae.svg +1 -0
  68. package/src/client/img/Plantae_2.svg +1 -0
  69. package/src/client/img/Protista.svg +1 -0
  70. package/src/client/img/Valdes/Valdes Island Conservancy.jpg +0 -0
  71. package/src/client/img/Xetthecum/Agricultural.jpg +0 -0
  72. package/src/client/img/Xetthecum/Anthropogenic_banner.jpg +0 -0
  73. package/src/client/img/Xetthecum/Broad_Leaf.jpg +0 -0
  74. package/src/client/img/Xetthecum/Caves.jpg +0 -0
  75. package/src/client/img/Xetthecum/Coastal_Bluffs.jpg +0 -0
  76. package/src/client/img/Xetthecum/Conifer_Pole_Sapling.jpg +0 -0
  77. package/src/client/img/Xetthecum/Developed.jpg +0 -0
  78. package/src/client/img/Xetthecum/Dock.jpg +0 -0
  79. package/src/client/img/Xetthecum/Eelgrass.jpg +0 -0
  80. package/src/client/img/Xetthecum/Forests_banner.jpg +0 -0
  81. package/src/client/img/Xetthecum/Freshwater_banner.jpg +0 -0
  82. package/src/client/img/Xetthecum/Greig_Creek.jpg +0 -0
  83. package/src/client/img/Xetthecum/Intertidal.jpg +0 -0
  84. package/src/client/img/Xetthecum/Laughlin_Lake.jpg +0 -0
  85. package/src/client/img/Xetthecum/Marine_banner.jpg +0 -0
  86. package/src/client/img/Xetthecum/Mature_Conifer_Forest.jpg +0 -0
  87. package/src/client/img/Xetthecum/Porlier_Pass_Road.jpg +0 -0
  88. package/src/client/img/Xetthecum/Riparian.jpg +0 -0
  89. package/src/client/img/Xetthecum/Rural.jpg +0 -0
  90. package/src/client/img/Xetthecum/Subtidal.jpg +0 -0
  91. package/src/client/img/Xetthecum/Wetland.jpg +0 -0
  92. package/src/client/img/Xetthecum/Woodland.jpg +0 -0
  93. package/src/client/img/Xetthecum/Woodland_banner.jpg +0 -0
  94. package/src/client/img/Xetthecum/Xetthecum.jpg +0 -0
  95. package/src/client/img/Xetthecum/Young_Conifer_Forest.jpg +0 -0
  96. package/src/client/img/Xetthecum/Young_Mixed_Forest.jpg +0 -0
  97. package/src/client/img/Xetthecum/food.svg +38 -0
  98. package/src/client/img/Xetthecum/indicator.svg +52 -0
  99. package/src/client/img/Xetthecum/material.svg +186 -0
  100. package/src/client/img/Xetthecum/medicinal.svg +62 -0
  101. package/src/client/img/Xetthecum/missing-value.svg +3 -0
  102. package/src/client/img/Xetthecum/spiritual.svg +13 -0
  103. package/src/client/img/Xetthecum/trade.svg +74 -0
  104. package/src/client/img/audio.svg +5 -0
  105. package/src/client/img/external-link.svg +3 -0
  106. package/src/client/img/selected-eye.svg +4 -0
  107. package/src/client/img/selected-tick.svg +3 -0
  108. package/src/client/img/thumbs/BCLeps.jpg +0 -0
  109. package/src/client/img/thumbs/Checklist.jpg +0 -0
  110. package/src/client/img/thumbs/Data-Paper-Figma.jpg +0 -0
  111. package/src/client/img/thumbs/Galiano-Data-Paper.jpg +0 -0
  112. package/src/client/img/thumbs/Galiano.jpg +0 -0
  113. package/src/client/img/thumbs/Maxwell.jpg +0 -0
  114. package/src/client/img/thumbs/Squamish.jpg +0 -0
  115. package/src/client/img/thumbs/Valdes.jpg +0 -0
  116. package/src/client/img/thumbs/Xetthecum.jpg +0 -0
  117. package/src/client/img/up-arrow.svg +4 -0
  118. package/src/client/js/autocomplete.js +53 -0
  119. package/src/client/js/checklist.js +179 -0
  120. package/src/client/js/colour.js +139 -0
  121. package/src/client/js/datasetControls.js +212 -0
  122. package/src/client/js/imerss-viz.js +1397 -0
  123. package/src/client/js/leafletMap.js +357 -0
  124. package/src/client/js/leafletMapWithGrid.js +337 -0
  125. package/src/client/js/leafletMapWithRegions.js +381 -0
  126. package/src/client/js/renderSVG.js +108 -0
  127. package/src/client/js/tabs.js +53 -0
  128. package/src/client/js/xetthecum.js +106 -0
  129. package/src/client/json/emptyPhyloMap.json +1 -0
  130. package/src/client/json/kingdomPhyloMap.json +17 -0
  131. package/src/client/json/phyloMap.json +58 -0
  132. package/src/compare.js +97 -0
  133. package/src/compilecsv.js +47 -0
  134. package/src/dataProcessing/LZ4.js +27 -0
  135. package/src/dataProcessing/coordinatePatch.js +151 -0
  136. package/src/dataProcessing/readCSV.js +107 -0
  137. package/src/dataProcessing/readCSVwithMap.js +90 -0
  138. package/src/dataProcessing/readCSVwithoutMap.js +25 -0
  139. package/src/dataProcessing/readJSON.js +23 -0
  140. package/src/dataProcessing/sqlite.js +174 -0
  141. package/src/dataProcessing/summarise.js +122 -0
  142. package/src/dataProcessing/taxonScrape.js +14 -0
  143. package/src/dataProcessing/worker.js +31 -0
  144. package/src/dataProcessing/writeCSV.js +34 -0
  145. package/src/dataProcessing/writeJSON.js +15 -0
  146. package/src/dbtaxa.js +96 -0
  147. package/src/deAuthorise.js +48 -0
  148. package/src/deqgis.js +148 -0
  149. package/src/expressions/expr.js +65 -0
  150. package/src/expressions/jsep.js +925 -0
  151. package/src/filterFirst.js +51 -0
  152. package/src/geom/geoJSON.js +121 -0
  153. package/src/iNaturalist/examples/api.inaturalist.org-v1-taxa!q=Acmispon americanus americanus.json +200 -0
  154. package/src/iNaturalist/examples/api.inaturalist.org-v1-taxa!q=Flabellina japonica.json +61 -0
  155. package/src/iNaturalist/examples/www.inaturalist.org-taxa-877359.json +132 -0
  156. package/src/iNaturalist/iNatUrls.js +17 -0
  157. package/src/iNaturalist/obsAPI.js +150 -0
  158. package/src/iNaturalist/taxonAPI.js +460 -0
  159. package/src/inatObs.js +120 -0
  160. package/src/inattify.js +123 -0
  161. package/src/intersect.js +80 -0
  162. package/src/intersectFilter.js +48 -0
  163. package/src/landlocked.js +137 -0
  164. package/src/lib/jquery.binarytransport.js +51 -0
  165. package/src/lib/lz4-commentary.txt +9 -0
  166. package/src/lib/lz4.js +73 -0
  167. package/src/lib/point-in-polygon.js +36 -0
  168. package/src/lz4.js +40 -0
  169. package/src/marmalise.js +333 -0
  170. package/src/materialise.js +68 -0
  171. package/src/reintegrate.js +71 -0
  172. package/src/taxonomise.js +615 -0
  173. package/src/unscrewGBIF.js +44 -0
  174. package/src/utils/dataSource.js +173 -0
  175. package/src/utils/settleStructure.js +62 -0
  176. package/src/utils/utils.js +92 -0
  177. package/src/viz/plethify.js +39 -0
  178. package/src/wormify.js +154 -0
  179. package/src/xetthecum/xetthecumFilters.js +126 -0
  180. package/test/testDataSource.js +182 -0
  181. package/test/testiNatObsSource.js +38 -0
  182. package/test/testiNatSource.js +50 -0
@@ -0,0 +1,381 @@
1
+ /* global L */
2
+
3
+ "use strict";
4
+
5
+ // noinspection ES6ConvertVarToLetConst // otherwise this is a duplicate on minifying
6
+ var hortis = fluid.registerNamespace("hortis");
7
+
8
+ fluid.defaults("hortis.leafletMap.withRegions", {
9
+ selectors: {
10
+ legendKeys: ".fld-imerss-map-legend-keys"
11
+ },
12
+ modelListeners: {
13
+ selectedRegions: [{
14
+ namespace: "map",
15
+ path: "selectedRegions",
16
+ func: "hortis.leafletMap.withRegions.showSelectedRegions",
17
+ args: ["{that}", "{change}.value"]
18
+ }, {
19
+ namespace: "legend",
20
+ path: "selectedRegions.*",
21
+ func: "hortis.legendKey.selectRegion",
22
+ args: ["{that}", "{change}.value", "{change}.path"]
23
+ }]
24
+ },
25
+ // See notes about this field in leafletMap
26
+ selectionTransactionSource: "map",
27
+ // legendKey: "@expand:hortis.leafletMap.renderLegendKey({that}.classes)",
28
+ model: {
29
+ // From leafletMap parent grade mapBlockTooltipId: string
30
+ // selectedRegions: classKey -> boolean
31
+ // selectedCommunities: communityKey -> boolean
32
+ // TODO: apparently this field is now disused
33
+ selectionRoute: "map" // either "map" or "taxa"
34
+ },
35
+ members: {
36
+ features: "{sunburst}.viz.features",
37
+ classes: "{sunburst}.viz.classes",
38
+ communities: "{sunburst}.viz.communities",
39
+ toPlot: "{sunburst}.viz.communities", // For general contract of hortis.mapBlockToFocusedTaxa - rename this field, e.g. selectableRegions
40
+ regions: "{sunburst}.viz.classes",
41
+ outerPanel: "{sunburst}.dom.mapOuterPanel"
42
+ },
43
+ listeners: {
44
+ "buildMap.addRegions": "hortis.leafletMap.withRegions.addRegions({that})",
45
+ "buildMap.drawRegions": "hortis.leafletMap.withRegions.drawRegions({that})",
46
+ "buildMap.drawLegend": "hortis.legendKey.drawLegend({that})",
47
+ "clearMapSelection.regions": "hortis.clearSelectedRegions({that})",
48
+ // class, community
49
+ "selectRegion.regionSelection": "hortis.leafletMap.regionSelection({that}, {arguments}.0, {arguments}.1)",
50
+ "onCreate.listenTaxonLinks": "hortis.listenTaxonLinks({sunburst})",
51
+ "onCreate.validateTaxonLinks": "hortis.validateTaxonLinks({sunburst}, {that})"
52
+ },
53
+ events: {
54
+ selectRegion: null
55
+ },
56
+ components: {
57
+ bannerManager: {
58
+ type: "hortis.bannerManager",
59
+ container: "body",
60
+ options: {
61
+ model: {
62
+ selectedCommunities: "{hortis.leafletMap}.model.selectedCommunities"
63
+ }
64
+ }
65
+ }
66
+ }
67
+ });
68
+
69
+ fluid.registerNamespace("hortis.legendKey");
70
+
71
+ hortis.legendKey.rowTemplate = "<div class=\"fld-imerss-legend-row\ %rowClass\">" +
72
+ "<span class=\"fld-imerss-legend-icon\"></span>" +
73
+ "<span class=\"fld-imerss-legend-preview %previewClass\" style=\"%previewStyle\"></span>" +
74
+ "<span class=\"fld-imerss-legend-label\">%keyLabel</span>" +
75
+ "</div>";
76
+
77
+ hortis.legendKey.blockTemplate = "<div class=\"fld-imerss-legend-block\"><span class=\"fld-imerss-legend-block-name\">%community</span>%rows</div>";
78
+
79
+ hortis.legendKey.renderMarkup = function (markup, clazz, className) {
80
+ const style = hortis.fillColorToStyle(clazz.fillColor || clazz.color);
81
+ const normal = hortis.normaliseToClass(className);
82
+ return fluid.stringTemplate(markup, {
83
+ rowClass: "fld-imerss-legend-row-" + normal,
84
+ previewClass: "fld-imerss-class-" + normal,
85
+ previewStyle: "background-color: " + style.fillColor,
86
+ keyLabel: className
87
+ });
88
+ };
89
+
90
+ hortis.legendKey.drawLegend = function (map) {
91
+ const blocks = fluid.transform(map.communities, function (community, key) {
92
+ const clazzRows = fluid.transform(community.classes, function (troo, className) {
93
+ return hortis.legendKey.renderMarkup(hortis.legendKey.rowTemplate, map.classes[className], className);
94
+ });
95
+ return fluid.stringTemplate(hortis.legendKey.blockTemplate, {
96
+ community: key,
97
+ rows: Object.values(clazzRows).join("\n")
98
+ });
99
+ });
100
+ const markup = Object.values(blocks).join("\n");
101
+ const legendKeys = map.locate("legendKeys");
102
+ legendKeys.html(markup);
103
+ map.clazzToLegendNodes = fluid.transform(map.classes, function (troo, className) {
104
+ const rowSel = ".fld-imerss-legend-row-" + hortis.normaliseToClass(className);
105
+ const row = legendKeys.find(rowSel);
106
+ row.click(function () {
107
+ map.events.selectRegion.fire(className, map.classes[className].community);
108
+ });
109
+ });
110
+ };
111
+
112
+ hortis.toggleClass = function (element, clazz, value) {
113
+ element.toggleClass(clazz, value);
114
+ };
115
+
116
+ hortis.legendKey.selectRegion = function (map, value, path) {
117
+ const className = fluid.peek(path);
118
+ const row = map.locate("legendKeys").find(".fld-imerss-legend-row-" + hortis.normaliseToClass(className));
119
+ row.toggleClass("fld-imerss-selected", value);
120
+ };
121
+
122
+ hortis.fillColorToStyle = function (fillColor) {
123
+ return {
124
+ fillColor: fluid.colour.arrayToString(fillColor),
125
+ fillOpacity: 1
126
+ };
127
+ };
128
+
129
+
130
+ fluid.defaults("hortis.bannerManager", {
131
+ gradeNames: "fluid.viewComponent",
132
+ selectors: {
133
+ banner: ".fl-xetthecum-banner"
134
+ },
135
+ modelListeners: {
136
+ "selectedCommunities.*": {
137
+ func: "hortis.bannerManager.toggleClass",
138
+ args: ["{that}.dom.banner", "{change}.value", "{change}.path"]
139
+ }
140
+ }
141
+ });
142
+
143
+ hortis.normaliseToClass = function (str) {
144
+ return str.toLowerCase().replace(/ /g, "-");
145
+ };
146
+
147
+ hortis.bannerManager.toggleClass = function (banner, state, path) {
148
+ const community = fluid.peek(path);
149
+ banner.toggleClass("fld-imerss-banner-" + hortis.normaliseToClass(community), state);
150
+ };
151
+
152
+ hortis.leafletMap.seColumns = ["What", "Where", "Importance", "Protection", "Source"];
153
+
154
+ hortis.leafletMap.hulqNameTemplate = " / <span aria-label=\"%label\" title=\"%label\" class=\"fl-imerss-hulq-name\">%hulqName</span>";
155
+
156
+ hortis.leafletMap.outerPanelPhoto = "<div class=\"fl-imerss-photo %photoClass\"></div>";
157
+
158
+ hortis.leafletMap.outerPanelCommunity = "<div class=\"fld-imerss-map-community\">Community:<br/>%community%hulqBlock</div>";
159
+ hortis.leafletMap.outerPanelClass = "<div class=\"fld-imerss-map-class\">%clazz%hulqBlock</div>";
160
+
161
+ hortis.leafletMap.outerPanelBlock =
162
+ "<div class=\"fld-imerss-map-panel-block fld-taxonDisplay-expandable-header fl-taxonDisplay-runon-header\">%blockName" + hortis.expandButtonMarkup + "</div>" +
163
+ "<div class=\"fld-taxonDisplay-expandable-remainder fl-taxonDisplay-runon-remainder\">%block</div>";
164
+
165
+
166
+ hortis.leafletMap.renderHulqName = function (row) {
167
+ return fluid.stringTemplate(hortis.leafletMap.hulqNameTemplate, {
168
+ hulqName: row.hulqName,
169
+ label: "Meaning: " + hortis.encodeHTML(row.hulqMeaning) + " Source: " + hortis.encodeHTML(row.hulqSource)
170
+ });
171
+ };
172
+
173
+ hortis.textToMarkup = function (text) {
174
+ return hortis.encodeHTML(text).replace(/\n/g, "<br/>");
175
+ };
176
+
177
+ hortis.taxonLinkRegex = /\[([^\[]+)\]\(([^\)]*)\)/gm;
178
+
179
+ hortis.convertTaxonLinks = function (text) {
180
+ return text.replace(hortis.taxonLinkRegex, function (match, p1, p2) {
181
+ return "<a class=\"fld-imerss-taxon-link\" href=\"" + p2 + "\">" + p1 + "</a>";
182
+ });
183
+ };
184
+
185
+ hortis.linkToTaxon = function (sunburst, taxonLink) {
186
+ const targetTaxon = taxonLink.substring("#taxon:".length);
187
+ return sunburst.lookupTaxon(targetTaxon);
188
+ };
189
+
190
+ hortis.validateTaxonLinks = function (sunburst, map) {
191
+ fluid.each(map.communities, function (community, key) {
192
+ const text = community.culturalValues;
193
+ let match;
194
+ do { // Ridiculous syntax from https://stackoverflow.com/a/6323598
195
+ match = hortis.taxonLinkRegex.exec(text);
196
+ if (match) {
197
+ const taxonLink = match[2];
198
+ const taxon = hortis.linkToTaxon(sunburst, taxonLink);
199
+ if (!taxon) {
200
+ console.log("Failed to look up taxon " + taxonLink + " for community key " + key);
201
+ }
202
+ }
203
+ } while (match);
204
+ });
205
+ };
206
+
207
+ // Accepts mouse event and function accepting row
208
+ hortis.withTaxonLink = function (sunburst, e, func) {
209
+ const target = e.target.getAttribute("href");
210
+ e.preventDefault();
211
+ console.log("Got event target ", target);
212
+ if (target.startsWith("#taxon:")) {
213
+ const row = hortis.linkToTaxon(sunburst, target);
214
+ if (row) {
215
+ func(row);
216
+ }
217
+ }
218
+ };
219
+
220
+ hortis.listenTaxonLinks = function (sunburst) {
221
+ $(document).on("click", ".fld-imerss-taxon-link", function (e) {
222
+ hortis.withTaxonLink(sunburst, e, function (row) {
223
+ sunburst.events.changeLayoutId.fire(row.id);
224
+ });
225
+ });
226
+
227
+ $(document).on("mouseenter", ".fld-imerss-taxon-link", function (e) {
228
+ hortis.withTaxonLink(sunburst, e, function (row) {
229
+ sunburst.mouseEvent = e;
230
+ sunburst.applier.change("hoverId", row.id);
231
+ });
232
+ });
233
+ $(document).on("mouseleave", ".fld-imerss-taxon-link", function () {
234
+ sunburst.applier.change("hoverId", null);
235
+ });
236
+ };
237
+
238
+ hortis.leafletMap.renderMapOuterPanel = function (map) {
239
+ const selectedClazz = fluid.keyForValue(map.model.selectedRegions, true);
240
+ const clazz = map.classes[selectedClazz];
241
+ let topPanel = "";
242
+ if (clazz.hasImage) {
243
+ topPanel += fluid.stringTemplate(hortis.leafletMap.outerPanelPhoto, {
244
+ photoClass: "fld-imerss-class-image-" + hortis.normaliseToClass(selectedClazz)
245
+ });
246
+ }
247
+ const communityName = map.model.mapBlockTooltipId;
248
+ const community = map.communities[communityName];
249
+ topPanel += fluid.stringTemplate(hortis.leafletMap.outerPanelCommunity, {
250
+ community: map.model.mapBlockTooltipId,
251
+ hulqBlock: community.hulqName ? hortis.leafletMap.renderHulqName(community) : ""
252
+ });
253
+ topPanel += fluid.stringTemplate(hortis.leafletMap.outerPanelClass, {
254
+ clazz: selectedClazz,
255
+ hulqBlock: clazz.hulqName ? hortis.leafletMap.renderHulqName(clazz) : ""
256
+ });
257
+ let bottomPanel = "";
258
+ if (community.culturalValues) {
259
+ const cultureBlock =
260
+ hortis.convertTaxonLinks(hortis.textToMarkup(community.culturalValues)) +
261
+ "<br/><br/><div class=\"fld-imerss-map-class-se-col\">Sources:</div>" +
262
+ hortis.textToMarkup(community.culturalValuesSources);
263
+ const allCultureBlock = fluid.stringTemplate(hortis.leafletMap.outerPanelBlock, {
264
+ blockName: "Cultural Values",
265
+ block: cultureBlock
266
+ });
267
+ bottomPanel += allCultureBlock;
268
+ }
269
+ if (clazz["sE-Tagline"]) {
270
+ let ecoBlock = "<div class=\"fld-imerss-map-class-tagline\">" + clazz["sE-Tagline"] + "</div>";
271
+ hortis.leafletMap.seColumns.forEach(function (col) {
272
+ ecoBlock += "<div class=\"fld-imerss-map-class-se-col\">" + col + ": </div>";
273
+ ecoBlock += "<div class=\"fld-imerss-map-class-se-val\">" + clazz["sE-" + col] + "</div>";
274
+ });
275
+ const allEcoBlock = fluid.stringTemplate(hortis.leafletMap.outerPanelBlock, {
276
+ blockName: "Ecological Values",
277
+ block: ecoBlock
278
+ });
279
+ bottomPanel += allEcoBlock;
280
+ }
281
+ return topPanel + bottomPanel;
282
+ };
283
+
284
+ // Most code from here on gets preserved in Howe Sound
285
+
286
+ hortis.leafletMap.withRegions.selectedRegions = function (selectedRegion, regions) {
287
+ return fluid.transform(regions, function (junk, key) {
288
+ // Note simplest way to avoid highlighting all when there is no map selection is to say none are selected
289
+ return selectedRegion ? key === selectedRegion : false;
290
+ });
291
+ };
292
+
293
+ // TODO: This gets preserved but we need to split off the outerPanel update
294
+ hortis.leafletMap.regionSelection = function (map, className, community) {
295
+ map.applier.change("mapBlockTooltipId", community);
296
+ map.applier.change("selectedRegions", hortis.leafletMap.withRegions.selectedRegions(className, map.classes));
297
+ map.applier.change("selectedCommunities", hortis.leafletMap.withRegions.selectedRegions(community, map.communities));
298
+ map.outerPanel.html(hortis.leafletMap.renderMapOuterPanel(map));
299
+ };
300
+
301
+ // TODO: This gets preserved
302
+ hortis.clearSelectedRegions = function (map) {
303
+ map.applier.change("selectedRegions", hortis.leafletMap.withRegions.selectedRegions(null, map.classes));
304
+ map.applier.change("selectedCommunities", hortis.leafletMap.withRegions.selectedRegions(null, map.communities));
305
+ };
306
+
307
+
308
+ hortis.regionOpacity = function (region) {
309
+ return "--imerss-" + hortis.normaliseToClass(region) + "-opacity";
310
+ };
311
+
312
+ hortis.regionBorder = function (region) {
313
+ return "--imerss-" + hortis.normaliseToClass(region) + "-stroke";
314
+ };
315
+
316
+ hortis.leafletMap.withRegions.showSelectedRegions = function (map, selectedRegions) {
317
+ const style = map.container[0].style;
318
+ const noSelection = map.model.mapBlockTooltipId === null;
319
+ Object.keys(map.regions).forEach(function (key) {
320
+ const lineFeature = map.classes[key].color;
321
+ style.setProperty(hortis.regionOpacity(key), selectedRegions[key] || noSelection ? "1.0" : "0.4");
322
+ style.setProperty(hortis.regionBorder(key), selectedRegions[key] ? "#FEF410" : (lineFeature ? fluid.colour.arrayToString(lineFeature) : "none"));
323
+ });
324
+ };
325
+
326
+ hortis.leafletMap.withRegions.addRegions = function (that) {
327
+ that.map.createPane("hortis-regions");
328
+ that.regionGroup = L.layerGroup({pane: "hortis-regions"}).addTo(that.map);
329
+ };
330
+
331
+ hortis.addStyle = function (text) {
332
+ const style = document.createElement("style");
333
+ style.type = "text/css";
334
+ style.innerText = text;
335
+ document.getElementsByTagName("head")[0].appendChild(style);
336
+ };
337
+
338
+ hortis.leafletMap.withRegions.drawRegions = function (map) {
339
+ const regionClass = function (className) {
340
+ return "fld-imerss-region-" + hortis.normaliseToClass(className);
341
+ };
342
+ map.applier.change("selectedRegions", hortis.leafletMap.withRegions.selectedRegions(null, map.classes));
343
+
344
+ map.regionGroup.clearLayers();
345
+
346
+ // Note nothing currently reads this property
347
+ map.liveFeatures = map.features.map(function (feature) {
348
+ const className = feature.properties.clazz;
349
+ const community = feature.properties.COMMUNITY;
350
+ const clazz = map.classes[className];
351
+ const options = clazz.fillColor ? {
352
+ style: hortis.fillColorToStyle(clazz.fillColor),
353
+ weight: 3,
354
+ stroke: "yellow" // Leaflet doesn't listen to weight if there is no initial stroke
355
+ } : {
356
+ style: {
357
+ color: fluid.colour.arrayToString(clazz.color),
358
+ weight: 3
359
+ }
360
+ };
361
+ options.className = regionClass(className) + " fld-imerss-region";
362
+ const Lpolygon = L.geoJSON(feature, options);
363
+ map.regionGroup.addLayer(Lpolygon);
364
+
365
+ Lpolygon.on("click", function () {
366
+ console.log("Map clicked on community ", community, " region ", className);
367
+ map.events.selectRegion.fire(className, community);
368
+ });
369
+ return {
370
+ Lpolygon: Lpolygon,
371
+ properties: feature.properties
372
+ };
373
+ });
374
+ const highlightStyle = Object.keys(map.regions).map(function (key) {
375
+ return "." + regionClass(key) + " {\n" +
376
+ " fill-opacity: var(" + hortis.regionOpacity(key) + ");\n" +
377
+ " stroke: var(" + hortis.regionBorder(key) + ");\n" +
378
+ "}\n";
379
+ });
380
+ hortis.addStyle(highlightStyle.join("\n"));
381
+ };
@@ -0,0 +1,108 @@
1
+ /*
2
+ Copyright 2017 Antranig Basman
3
+ Licensed under the Educational Community License (ECL), Version 2.0 or the New
4
+ BSD license. You may not use this file except in compliance with one these
5
+ Licenses.
6
+ You may obtain a copy of the ECL 2.0 License and BSD License at
7
+ https://github.com/fluid-project/infusion/raw/master/Infusion-LICENSE.txt
8
+ */
9
+ "use strict";
10
+
11
+ var hortis = fluid.registerNamespace("hortis");
12
+
13
+ hortis.encodeHTML = function (str) {
14
+ return str.replace(/[&<>'"]/g, function (tag) {
15
+ return {
16
+ "&": "&amp;",
17
+ "<": "&lt;",
18
+ ">": "&gt;",
19
+ "'": "&#39;",
20
+ "\"": "&quot;"
21
+ }[tag];
22
+ });
23
+ };
24
+
25
+ hortis.renderSVGElement = function (markup, parentContainer) {
26
+ // Approach taken from http://stackoverflow.com/a/36507333
27
+ var container = $.parseXML(markup);
28
+ var element = container.documentElement;
29
+ parentContainer.append(element);
30
+ return element;
31
+ };
32
+
33
+ hortis.renderNumber = function (number) {
34
+ if (Math.abs(number) < 1e-5) {
35
+ return "0";
36
+ } else {
37
+ return number.toFixed(3);
38
+ }
39
+ };
40
+
41
+ hortis.emitPath = function (elements) {
42
+ var togo = "";
43
+ elements.forEach(function (elem) {
44
+ if (typeof(elem) === "string") {
45
+ togo += elem;
46
+ } else {
47
+ togo += hortis.renderNumber(elem);
48
+ }
49
+ });
50
+ return togo;
51
+ };
52
+
53
+ hortis.circularPath = function (radius) {
54
+ var r = radius;
55
+ return hortis.emitPath(["M", -r, " ", 0,
56
+ "A", r, " ", r, " 0 1 0 ", r, " ", 0,
57
+ "A", r, " ", r, " 0 1 0 ", -r, " ", 0
58
+ ]);
59
+ };
60
+
61
+ hortis.annularPath = function (innerRadius, outerRadius) {
62
+ var ir = innerRadius, or = outerRadius;
63
+ return hortis.emitPath(["M", -or, " ", 0,
64
+ "A", or, " ", or, " 0 1 0 ", or, " ", 0,
65
+ "A", or, " ", or, " 0 1 0 ", -or, " ", 0,
66
+ "Z",
67
+ "M", -ir, " ", 0,
68
+ "A", ir, " ", ir, " 0 1 1 ", ir, " ", 0,
69
+ "A", ir, " ", ir, " 0 1 1 ", -ir, " ", 0,
70
+ "Z"
71
+ ]);
72
+ };
73
+
74
+ hortis.segmentPath = function (startAngle, endAngle, innerRadius, outerRadius) {
75
+ var cs = Math.cos(startAngle), ss = -Math.sin(startAngle),
76
+ ce = Math.cos(endAngle), se = -Math.sin(endAngle),
77
+ i = innerRadius, o = outerRadius,
78
+ lfa = (+((endAngle - startAngle) >= Math.PI)).toString();
79
+ // https://developer.mozilla.org/en-US/docs/Web/SVG/Tutorial/Paths#Arcs
80
+ return hortis.emitPath(["M", cs * i, " ", ss * i,
81
+ "A", i, " ", i, " 0 ", lfa, " 0 ", ce * i, " ", se * i,
82
+ "L", ce * o, " ", se * o,
83
+ "A", o, " ", o, " 0 ", lfa, " 1 ", cs * o, " ", ss * o,
84
+ "Z"]);
85
+ };
86
+
87
+ hortis.linearTextPath = function (leftAngle, rightAngle, innerRadius, outerRadius) {
88
+ var midAngle = (leftAngle + rightAngle) / 2,
89
+ c = Math.cos(midAngle), s = -Math.sin(midAngle),
90
+ sr = c > 0 ? innerRadius : outerRadius,
91
+ fr = c > 0 ? outerRadius : innerRadius;
92
+ return hortis.emitPath(["M", c * sr, " ", s * sr, "L", c * fr, " ", s * fr]);
93
+ };
94
+
95
+ hortis.segmentTextPath = function (startAngle, endAngle, outerRadius) {
96
+ var cs = Math.cos(startAngle), ss = -Math.sin(startAngle),
97
+ ce = Math.cos(endAngle), se = -Math.sin(endAngle),
98
+ ar = outerRadius - 20,
99
+ lfa = (+((endAngle - startAngle) >= Math.PI)).toString();
100
+ return hortis.emitPath(["M", cs * ar, " ", ss * ar,
101
+ "A", ar, " ", ar, " 0 ", lfa, " 0 ", ce * ar, " ", se * ar]);
102
+ };
103
+
104
+ hortis.circularTextPath = function (outerRadius) {
105
+ var ar = outerRadius - 20;
106
+ return hortis.emitPath(["M", "-0.1 ", -ar,
107
+ "A", ar, " ", ar, " 0 1 0 ", "0.1 ", -ar]);
108
+ };
@@ -0,0 +1,53 @@
1
+ /*
2
+ Copyright 2021 Antranig Basman
3
+ Licensed under the Educational Community License (ECL), Version 2.0 or the New
4
+ BSD license. You may not use this file except in compliance with one these
5
+ Licenses.
6
+ You may obtain a copy of the ECL 2.0 License and BSD License at
7
+ https://github.com/fluid-project/infusion/raw/master/Infusion-LICENSE.txt
8
+ */
9
+
10
+
11
+ "use strict";
12
+
13
+ var hortis = fluid.registerNamespace("hortis");
14
+
15
+ /**********************
16
+ * Tabs *
17
+ *********************/
18
+
19
+ fluid.defaults("hortis.tabs", {
20
+ gradeNames: ["fluid.viewComponent"],
21
+ tabOptions: {},
22
+ model: {
23
+ selectedTab: null
24
+ },
25
+ listeners: {
26
+ "onCreate.initTabs": {
27
+ "this": "{that}.container",
28
+ "method": "tabs",
29
+ "args": "{that}.options.tabOptions"
30
+ },
31
+ "onCreate.bindEvents": {
32
+ funcName: "hortis.tabs.bindEvents"
33
+ }
34
+ }
35
+ });
36
+
37
+ hortis.tabs.findTab = function (that, tabId) {
38
+ return fluid.find(that.options.tabIds, function (id, key) {
39
+ return id === tabId ? key : undefined;
40
+ });
41
+ };
42
+
43
+ hortis.tabs.bindEvents = function (that) {
44
+ that.container.on("tabsactivate", function (event, ui) {
45
+ const tabId = ui.newTab.find("a").attr("href").substring(1);
46
+ const tab = hortis.tabs.findTab(that, tabId);
47
+ that.applier.change("selectedTab", tab);
48
+ });
49
+ const initialIndex = Object.keys(that.options.tabIds).indexOf(that.model.selectedTab);
50
+ if (initialIndex !== -1) {
51
+ that.container.tabs("option", "active", initialIndex);
52
+ }
53
+ };
@@ -0,0 +1,106 @@
1
+ /*
2
+ Copyright 2022 Antranig Basman
3
+ Licensed under the Educational Community License (ECL), Version 2.0 or the New
4
+ BSD license. You may not use this file except in compliance with one these
5
+ Licenses.
6
+ You may obtain a copy of the ECL 2.0 License and BSD License at
7
+ https://github.com/fluid-project/infusion/raw/master/Infusion-LICENSE.txt
8
+ */
9
+
10
+ "use strict";
11
+
12
+ var hortis = fluid.registerNamespace("hortis");
13
+
14
+ fluid.defaults("hortis.xetthecumSunburstLoader", {
15
+ gradeNames: "fluid.viewComponent",
16
+ bioPanelLabel: "Biodiversity",
17
+ mapPanelLabel: "Ecological Communities",
18
+ distributeOptions: {
19
+ sunburstLabel: {
20
+ target: "{that hortis.sunburst}.options.model.panelLabel",
21
+ source: "{that}.options.bioPanelLabel"
22
+ },
23
+ checklistLabel: {
24
+ target: "{that hortis.checklist}.options.model.panelLabel",
25
+ source: "{that}.options.bioPanelLabel"
26
+ },
27
+ mapWithLabel: {
28
+ record: "hortis.withPanelLabel",
29
+ target: "{that hortis.leafletMap}.options.gradeNames"
30
+ },
31
+ mapLabel: {
32
+ target: "{that hortis.leafletMap}.options.model.panelLabel",
33
+ source: "{that}.options.mapPanelLabel"
34
+ },
35
+ outerPanelSelector: {
36
+ target: "{that hortis.sunburst}.options.selectors.mapOuterPanel",
37
+ record: ".fld-imerss-map-outer-panel"
38
+ }
39
+ },
40
+ components: {
41
+ infoPanelManager: {
42
+ type: "hortis.infoPanelManager",
43
+ container: "{sunburstLoader}.container",
44
+ createOnEvent: "sunburstLoaded",
45
+ options: {
46
+ listeners: { // Another one for the reuse failure up to 5.x - we have to put these here because of createOnEvent
47
+ "{hortis.leafletMap}.events.selectRegion": {
48
+ namespace: "updateInfoPanel",
49
+ changePath: "{infoPanelManager}.model.visiblePanel",
50
+ value: "map"
51
+ },
52
+ // TODO: Horrid notational problem here - can't duplicate key in JSON and can't put namespace in it
53
+ "{sunburst}.events.changeLayoutId": [{
54
+ namespace: "clearMapSelection",
55
+ listener: "hortis.clearMapSelectionConditionally",
56
+ args: ["{hortis.leafletMap}", "{arguments}.0", "{arguments}.1"]
57
+ }, {
58
+ namespace: "changeLayoutId",
59
+ changePath: "{infoPanelManager}.model.visiblePanel",
60
+ value: "taxa"
61
+ }]
62
+ }
63
+ }
64
+ }
65
+ }
66
+ });
67
+
68
+ hortis.clearMapSelectionConditionally = function (map, layoutId, source) {
69
+ console.log("ClearMapSelectionConditionally with layoutId ", layoutId, " source " + source);
70
+ if (source !== "rowFocus") {
71
+ map.events.clearMapSelection.fire();
72
+ }
73
+ };
74
+
75
+ fluid.defaults("hortis.infoPanelManager", {
76
+ gradeNames: "fluid.viewComponent",
77
+ selectors: {
78
+ map: ".fld-imerss-map-outer-panel-wrapper",
79
+ taxa: ".fld-imerss-taxonDisplay-wrapper"
80
+ },
81
+ panels: {
82
+ map: true,
83
+ taxa: true
84
+ },
85
+ model: {
86
+ visiblePanel: "taxa",
87
+ visiblePanels: {}
88
+ },
89
+ modelRelay: {
90
+ visiblePanels: {
91
+ target: "visiblePanels",
92
+ func: (panel, panels) => {
93
+ return fluid.transform(panels, (troo, thisPanel) => panel === thisPanel);
94
+ },
95
+ args: ["{that}.model.visiblePanel", "{that}.options.panels"]
96
+ },
97
+ visibleMap: {
98
+ target: "dom.map.visible",
99
+ source: "visiblePanels.map"
100
+ },
101
+ visibleTaxa: {
102
+ target: "dom.taxa.visible",
103
+ source: "visiblePanels.taxa"
104
+ }
105
+ }
106
+ });
@@ -0,0 +1 @@
1
+ {}
@@ -0,0 +1,17 @@
1
+ {
2
+ "kingdom:Animalia": {
3
+ "colour": "#f26522"
4
+ },
5
+ "kingdom:Chromista": {
6
+ "colour": "#009fd3"
7
+ },
8
+ "kingdom:Plantae": {
9
+ "colour": "#8cc63f"
10
+ },
11
+ "kingdom:Protozoa": {
12
+ "colour": "#1eb28f"
13
+ },
14
+ "kingdom:Fungi": {
15
+ "colour": "#f06"
16
+ }
17
+ }