1/// <reference path="/js/vendor/lodash.js" /> 2 3jQuery.fn.extend({ 4 legendRanges: function (options) { 5 return new jQuery.LegendRanges(options) 6 } 7}); 8 9jQuery.LegendRanges = function (options) { 10 this._legendScale = options.legendScale; 11 this._timeSeries = options.timeSeries; 12 this._colors = options.colors; 13 this._colorSelection = options.colorSelection; 14 this._legendIntervals = options.legendIntervals; 15 this._colorsPalette = options.colorsPalette; 16}; 17 18jQuery.LegendRanges.prototype.setOption = function (option, value) { 19 switch (option) { 20 case 'intervalCount': 21 this._colorSelection.intervalCount = value; 22 break; 23 case 'startColor': 24 this._colorSelection.startColor = value; 25 this._legendIntervals = this._updateLegendColors(); 26 break; 27 case 'endColor': 28 this._colorSelection.endColor = value; 29 this._legendIntervals = this._updateLegendColors(); 30 break; 31 case 'legendIntervals': 32 this._legendIntervals = value; 33 break; 34 case 'legendScale': 35 this._legendScale = value; 36 this._legendIntervals = this.serializeIntervals(this.refreshLegendRanges()); 37 break; 38 case 'timeSeries': 39 this._timeSeries = value; 40 break; 41 case 'colorSelection': 42 this._colorSelection = value; 43 break; 44 case 'colors': 45 this._colors = value; 46 break; 47 case 'colorsPalette': 48 this._colorsPalette = value; 49 break; 50 }; 51}; 52 53jQuery.LegendRanges.prototype.serializeIntervals = function (intervals) { 54 if (!intervals) 55 return null; 56 57 var result = []; 58 59 for (var i = 0; i < intervals.length; i++) { 60 result.push(intervals[i].low); 61 result.push(intervals[i].color); 62 63 if (i == intervals.length - 1) 64 result.push(intervals[i].high); 65 }; 66 67 return result; 68}; 69 70jQuery.LegendRanges.prototype.deserializeIntervals = function (intervals) { 71 var result = []; 72 73 var i = 1; 74 while (i < intervals.length - 1) { 75 result.push({ 76 color: intervals[i], 77 low: intervals[i - 1], 78 high: intervals[i + 1] 79 }); 80 81 i += 2; 82 }; 83 84 return result; 85}; 86 87jQuery.LegendRanges.prototype._smoothenLegendRange = function (range) { 88 var p_low = Math.floor(Math.log(Math.abs(range.low)) / Math.LN10); 89 var p_diff = Math.floor(Math.log(Math.abs(range.high - range.low)) / Math.LN10); 90 var p_high = Math.floor(Math.log(Math.abs(range.high)) / Math.LN10); 91 92 if (p_low == -Infinity) p_low = 0; 93 if (p_diff == -Infinity) p_diff = Infinity; 94 if (p_high == -Infinity) p_high = 0; 95 96 var precision = Math.min(p_diff, p_low) - 1; 97 var factor = Math.pow(10, precision); 98 99 if (factor) { 100 var smoothed = Math.round(range.low / factor) * factor; 101 102 if (smoothed > range.low) { 103 range.low -= factor; 104 range.low = Math.round(range.low / factor) * factor; 105 } 106 else 107 range.low = smoothed; 108 109 range.low = Math.round(range.low / factor) * factor; 110 range.low = Math.round(range.low * 100) / 100; 111 } 112 113 p_diff = Math.floor(Math.log(Math.abs(range.high - range.low)) / Math.LN10); 114 precision = Math.min(p_diff, p_high) - 1; 115 factor = Math.pow(10, precision); 116 117 if (factor) { 118 var smoothed = Math.round(range.high / factor) * factor; 119 120 if (smoothed < range.high) { 121 range.high += factor; 122 range.high = Math.round(range.high / factor) * factor; 123 } 124 else 125 range.high = smoothed; 126 127 range.high = Math.round(range.high * 100) / 100; 128 } 129}; 130 131jQuery.LegendRanges.prototype._getGradient = function (start, end, count) { 132 var invert = false; 133 var lowColor, highColor; 134 var result = []; 135 136 if (start < end) { 137 lowColor = start; 138 highColor = end; 139 invert = true; 140 } else { 141 lowColor = end; 142 highColor = start; 143 }; 144 145 for (var i = 0; i < count; i++) { 146 var r = highColor >> 16; 147 var g = highColor >> 8 & 0xFF; 148 var b = highColor & 0xFF; 149 150 var fraction = count == 1 ? 0 : i / (count - 1); 151 152 r += ((lowColor >> 16) - r) * fraction; 153 g += ((lowColor >> 8 & 0xFF) - g) * fraction; 154 b += ((lowColor & 0xFF) - b) * fraction; 155 156 result[i] = (r << 16 | g << 8 | b).toString(16); 157 158 var zeroes = ""; 159 for (var j = result[i].length; j < 6; j++) 160 zeroes += "0"; 161 162 result[i] = zeroes + result[i]; 163 } 164 165 if (invert) 166 result = result.reverse(); 167 168 return result; 169}; 170 171jQuery.LegendRanges.prototype._sortRegionByValue = function (mapCodetoValue) { 172 var getKeys = Object.keys || function (obj) { 173 if (obj !== Object(obj)) throw new TypeError('Invalid object'); 174 var keys = []; 175 for (var key in obj) if (Object.hasOwnProperty.call(obj, key)) keys[keys.length] = key; 176 return keys; 177 }; 178 179 var regionCodes = getKeys(mapCodetoValue); 180 181 var values = [], i, j = 0; 182 183 for (i in mapCodetoValue) 184 values[j++] = mapCodetoValue[i].value * 1; 185 186 for (i = 0; i < values.length; i++) 187 for (j = i + 1; j < values.length; j++) { 188 if (values[i] > values[j]) { 189 var temp = values[i]; 190 values[i] = values[j];
191 values[j] = temp; 192 193 temp = regionCodes[i]; 194 regionCodes[i] = regionCodes[j]; 195 regionCodes[j] = temp; 196 } 197 } 198 199 return regionCodes; 200}; 201 202jQuery.LegendRanges.prototype.getLegendRanges = function (count) { 203 if (!this._timeSeries || this._timeSeries.length == 0) 204 return []; 205 206 // sort regions: this code works 5 times faster than previous. 207 208 var keys = _.keys(this._timeSeries[0].data); 209 var ts = this._timeSeries[0].data; 210 211 var temp = _.chain(keys).map(function (key) { 212 return { 213 key: key, 214 value: parseFloat(ts[key].value) 215 } 216 }).uniqBy('value').value(); 217 218 if (temp.length === 0) { 219 return []; 220 } 221 222 var data = {}; 223 224 for (var i = 0; i < temp.length; i++) 225 data[temp[i].key] = temp[i]; 226 227 var regions = this._sortRegionByValue(data); 228 229 var legendRanges = []; 230 var min = data[regions[0]].value; 231 var range = { low: min, high: 0 }; 232 var lowVal = null; 233 234 function addLegendRangeEntry(highVal) { 235 range.high = highVal; 236 this._smoothenLegendRange(range); 237 legendRanges.push({ low: lowVal ? lowVal : range.low, high: range.high }); 238 range.low = range.high; 239 lowVal = range.low; 240 }; 241 242 if (Knoema.Utils.keys(data).length > 0) { 243 if (this._legendScale == 'equalQuantiles') { 244 var max = data[regions[regions.length - 1]].value; 245 var valueGap = (max - min) / count; 246 247 for (var i = 1; i <= count; i++) 248 addLegendRangeEntry.call(this, min + i * valueGap); 249 } 250 else { 251 var factor = Math.floor(regions.length / count); 252 var indexForExtraRegions = count - (regions.length - factor * count); 253 var j = -1; 254 255 for (var i = 0; i < count; i++) { 256 if (i >= indexForExtraRegions) 257 j += 1; 258 259 j += factor; 260 261 if (j > -1 && j < regions.length) 262 addLegendRangeEntry.call(this, data[regions[j]].value); 263 } 264 } 265 } 266 267 // KN-81477 Dataset works with errors 268 if (legendRanges.length === 1 && regions.length === 1 && regions[0] === 'WLD') { 269 legendRanges[0].color = 'white'; 270 } 271 272 return legendRanges; 273}; 274 275jQuery.LegendRanges.prototype._getColors = function () { 276 277 if ((!this._colors || !this._colors.length) && Boolean(this._colorsPalette)) 278 this._colors = this._colorsPalette.slice(0, 6); 279 280 if (this._colors && this._colors.length > 0 && this._colors.length == this._colorSelection.intervalCount) { 281 return this._colors.map(function (item) { return item.replace('#', '') }); 282 } 283 284 if (this._colors && this._colors.length > 0 && this._colorSelection.intervalCount) { 285 var colors = this._colors.slice(0, 6); 286 switch (parseInt(this._colorSelection.intervalCount)) { 287 case 2: 288 colorCodes = [colors[0], colors[5]]; 289 break; 290 case 4: 291 colorCodes = [colors[0], colors[2], colors[3], colors[5]]; 292 break; 293 case 5: 294 colorCodes = [colors[0], colors[1], colors[2], colors[3], colors[4]]; 295 break; 296 case 6: 297 colorCodes = colors; 298 break; 299 default: 300 case 3: 301 colorCodes = [colors[0], colors[3], colors[5]]; 302 break; 303 } 304 return colorCodes.map(function (item) { return item.replace('#', '') }); 305 } 306 else if (this._colorSelection != null && (this._colorSelection.intervalCount)) { 307 var colorSelection = this._colorSelection; 308 var intervals = colorSelection.intervalCount; 309 var color1 = '0x' + colorSelection.startColor; 310 var color2 = '0x' + (colorSelection.endColor || colorSelection.startColor); 311 } 312 else { 313 314 //TODO Move this to Knoema.ThemePicker 315 function getAppColor(colorName) { 316 var appColors = { 317 green: '#76933c', 318 blue: '#366092', 319 orange: '#e26b0a', 320 gray: '#262626', 321 violet: '#60497a', 322 pink: '#993366', 323 red: '#cc0000', 324 maroon: '#800000' 325 }; 326 if (colorName) 327 return appColors[colorName.toLowerCase()]; 328 else 329 return colorName; 330 }; 331 332 color1 = getAppColor('gray').replace('#', '0x'); 333 color2 = getAppColor('blue').replace('#', '0x'); 334 intervals = 3; 335 } 336 337 var colors = this._getGradient(color1, color2, intervals); 338 var regions = []; 339 340 if (this._timeSeries) 341 regions = this._sortRegionByValue(this._timeSeries[0].data); 342 else 343 return []; 344 345 if (regions.length < colors.length) 346 colors.splice(regions.length, colors.length - regions.length); 347 348 return colors; 349}; 350 351jQuery.LegendRanges.prototype.refreshLegendRanges = function () { 352 if (this._legendIntervals) { 353 var intervals = this.deserializeIntervals(this._legendIntervals); 354 355 for (var i = 0; i < intervals.length; i++) { 356 intervals[i].low = null; 357 intervals[i].high = null; 358 } 359 360 return intervals; 361 } 362 363 return null; 364}; 365 366jQuery.LegendRanges.prototype.getParsedIntervals = function () { 367 if (this._legendIntervals) { 368 var intervals = this.deserializeIntervals(this._legendIntervals); 369 var ranges = this.getLegendRanges(intervals.length); 370 371 var emptyRange = false; 372 373 for (var i = 0; i < intervals.length; i++) 374 if (!intervals[i].low && !intervals[i].high) 375 emptyRange = true; 376 377 if (emptyRange) { 378 if (ranges.length > 0) { 379 380 intervals.splice(ranges.length, intervals.length - ranges.length); 381 382 for (var i = 0; i < intervals.length; i++) 383 if (ranges[i]) { 384 intervals[i].low = ranges[i].low; 385 intervals[i].high = ranges[i].high; 386 } 387 } 388 else 389 intervals = []; 390 } 391 392 return intervals; 393 } 394 else { 395 var colors = this._getColors(); 396 var ranges = this.getLegendRanges(colors.length); 397 var result = []; 398 399 colors.splice(ranges.length, colors.length - ranges.length); 400 401 for (var i = 0; i < colors.length; i++) 402 result.push({ 403 color: colors[i], 404 low: ranges[i].low, 405 high: ranges[i].high 406 }); 407 408 if (result.length === 1 && this._timeSeries[0].data["WLD"]) { 409 result[0].color = 'white'; 410 result[0].low = result[0].high = this._timeSeries[0].data["WLD"].value; 411 } 412 413 return result; 414 } 415}; 416 417jQuery.LegendRanges.prototype._updateLegendColors = function () { 418 if (this._legendIntervals) { 419 var intervals = this.deserializeIntervals(this._legendIntervals); 420 var colors = this._getColors(); 421 422 for (var i = 0; i < colors.length; i++) 423 intervals[i].color = colors[i]; 424 425 return this.serializeIntervals(intervals); 426 }; 427 428 return null; 429}; 430 431jQuery.LegendRanges.prototype.getLegendIntervals = function () { 432 return this._legendIntervals; 433}; 434 435jQuery.LegendRanges.prototype.setIntervalColor = function (index, color) { 436 var intervals = []; 437 438 if (this._legendIntervals) { 439 intervals = this.deserializeIntervals(this._legendIntervals); 440 441 if (index < intervals.length) 442 intervals[index].color = color; 443 } 444 else { 445 var colors = this._getColors(); 446 447 for (var i = 0; i < colors.length; i++) 448 intervals.push({ 449 color: i == index ? color : colors[i], 450 low: null, 451 high: null 452 }); 453 } 454 455 this._legendIntervals = this.serializeIntervals(intervals); 456};
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.