1/*! 2 * JQVMap: jQuery Vector Map Library 3 * @author JQVMap <[email protected]> 4 * @version 1.5.1 5 * @link http://jqvmap.com 6 * @license https://github.com/manifestinteractive/jqvmap/blob/master/LICENSE 7 * @builddate 2016/06/02 8 */ 9 10var bretagne = '#5B7485'; 11var provence_alpe_cote_d_azur = '#506A7D'; 12var nouvelle_aquitaine = '#456174'; 13var bourgogne_franche_comte = '#3A586C'; 14var occitanie = '#2F4E64'; 15var ile_de_france = '#224257'; 16var pays_de_la_loire = '#203E53'; 17var auvergne_rhone_alpes = '#1F3B4E'; 18var corse = '#1D374A'; 19var hauts_de_france = '#1B3445'; 20var centre_val_de_loire = '#193040'; 21var grand_est = '#172D3C'; 22var normandie = '#162937'; 23var outre_mer = '#142633'; 24 25var region_colors = { 26 80: hauts_de_france, 27 '02': hauts_de_france, 28 77: ile_de_france, 29 12: occitanie, 30 47: nouvelle_aquitaine, 31 81: occitanie, 32 '07': auvergne_rhone_alpes, 33 90: bourgogne_franche_comte, 34 48: occitanie, 35 84: provence_alpe_cote_d_azur, 36 '01': auvergne_rhone_alpes, 37 73: auvergne_rhone_alpes, 38 74: auvergne_rhone_alpes, 39 39: bourgogne_franche_comte, 40 25: bourgogne_franche_comte, 41 '04': provence_alpe_cote_d_azur, 42 '05': provence_alpe_cote_d_azur, 43 32: occitanie, 44 24: nouvelle_aquitaine, 45 51: grand_est, 46 60: hauts_de_france, 47 52: grand_est, 48 88: grand_est, 49 27: normandie, 50 61: normandie, 51 79: nouvelle_aquitaine, 52 16: nouvelle_aquitaine, 53 49: pays_de_la_loire, 54 53: pays_de_la_loire, 55 59: hauts_de_france, 56 62: hauts_de_france, 57 '08': grand_est, 58 54: grand_est, 59 57: grand_est, 60 67: grand_est, 61 68: grand_est, 62 55: grand_est, 63 87: nouvelle_aquitaine, 64 18: centre_val_de_loire, 65 '03': auvergne_rhone_alpes, 66 41: centre_val_de_loire, 67 70: bourgogne_franche_comte, 68 23: nouvelle_aquitaine, 69 36: centre_val_de_loire, 70 971: outre_mer, 71 972: outre_mer, 72 974: outre_mer, 73 973: outre_mer, 74 976: outre_mer, 75 63: auvergne_rhone_alpes, 76 43: auvergne_rhone_alpes, 77 42: auvergne_rhone_alpes, 78 15: auvergne_rhone_alpes, 79 19: nouvelle_aquitaine, 80 46: occitanie, 81 71: bourgogne_franche_comte, 82 26: auvergne_rhone_alpes, 83 21: bourgogne_franche_comte, 84 76: normandie, 85 38: auvergne_rhone_alpes, 86 58: bourgogne_franche_comte, 87 69: auvergne_rhone_alpes, 88 91: ile_de_france, 89 45: centre_val_de_loire, 90 86: nouvelle_aquitaine, 91 10: grand_est, 92 89: bourgogne_franche_comte, 93 95: ile_de_france, 94 37: centre_val_de_loire, 95 72: pays_de_la_loire, 96 78: ile_de_france, 97 28: centre_val_de_loire, 98 82: occitanie, 99 66: occitanie, 100 11: occitanie, 101 64: nouvelle_aquitaine, 102 65: occitanie, 103 '09': occitanie, 104 34: occitanie, 105 31: occitanie, 106 '06': provence_alpe_cote_d_azur, 107 '2b': corse, 108 '2a': corse, 109 83: provence_alpe_cote_d_azur, 110 30: occitanie, 111 13: provence_alpe_cote_d_azur, 112 40: nouvelle_aquitaine, 113 50: normandie, 114 14: normandie, 115 85: pays_de_la_loire, 116 17: nouvelle_aquitaine, 117 33: nouvelle_aquitaine, 118 44: pays_de_la_loire, 119 22: bretagne, 120 35: bretagne, 121 29: bretagne, 122 56: bretagne, 123 93: ile_de_france, 124 75: ile_de_france, 125 94: ile_de_france, 126 92: ile_de_france, 127}; 128 129var VectorCanvas = function (width, height, params) { 130 this.mode = window.SVGAngle ? 'svg' : 'vml'; 131 this.params = params; 132 133 if (this.mode === 'svg') { 134 this.createSvgNode = function (nodeName) { 135 return document.createElementNS(this.svgns, nodeName); 136 }; 137 } else { 138 try { 139 if (!document.namespaces.rvml) { 140 document.namespaces.add('rvml', 'urn:schemas-microsoft-com:vml'); 141 } 142 this.createVmlNode = function (tagName) { 143 return document.createElement('<rvml:' + tagName + ' class="rvml">'); 144 }; 145 } catch (e) { 146 this.createVmlNode = function (tagName) { 147 return document.createElement( 148 '<' + 149 tagName + 150 ' xmlns="urn:schemas-microsoft.com:vml" class="rvml">', 151 ); 152 }; 153 } 154 155 document.createStyleSheet().addRule('.rvml', 'behavior:url(#default#VML)'); 156 } 157 158 if (this.mode === 'svg') { 159 this.canvas = this.createSvgNode('svg'); 160 } else { 161 this.canvas = this.createVmlNode('group'); 162 this.canvas.style.position = 'absolute'; 163 } 164 165 this.setSize(width, height); 166}; 167 168VectorCanvas.prototype = { 169 svgns: 'http://www.w3.org/2000/svg',
170 mode: 'svg', 171 width: 0, 172 height: 0, 173 canvas: null, 174}; 175 176var ColorScale = function (colors, normalizeFunction, minValue, maxValue) { 177 if (colors) { 178 this.setColors(colors); 179 } 180 if (normalizeFunction) { 181 this.setNormalizeFunction(normalizeFunction); 182 } 183 if (minValue) { 184 this.setMin(minValue); 185 } 186 if (minValue) { 187 this.setMax(maxValue); 188 } 189}; 190 191ColorScale.prototype = { 192 colors: [], 193}; 194 195var JQVMap = function (params) { 196 params = params || {}; 197 var map = this; 198 var mapData = JQVMap.maps[params.map]; 199 var mapPins; 200 201 if (!mapData) { 202 throw new Error( 203 'Invalid "' + 204 params.map + 205 '" map parameter. Please make sure you have loaded this map file in your HTML.', 206 ); 207 } 208 209 this.selectedRegions = []; 210 this.multiSelectRegion = params.multiSelectRegion; 211 212 this.container = params.container; 213 214 this.defaultWidth = mapData.width; 215 this.defaultHeight = mapData.height; 216 217 this.color = params.color; 218 this.selectedColor = params.selectedColor; 219 this.hoverColor = params.hoverColor; 220 this.hoverColors = params.hoverColors; 221 this.hoverOpacity = params.hoverOpacity; 222 this.setBackgroundColor(params.backgroundColor); 223 224 this.width = params.container.width(); 225 this.height = params.container.height(); 226 227 this.resize(); 228 229 jQuery(window).resize(function () { 230 var newWidth = params.container.width(); 231 var newHeight = params.container.height(); 232 233 if (newWidth && newHeight) { 234 map.width = newWidth; 235 map.height = newHeight; 236 map.resize(); 237 map.canvas.setSize(map.width, map.height); 238 map.applyTransform(); 239 240 var resizeEvent = jQuery.Event('resize.jqvmap'); 241 jQuery(params.container).trigger(resizeEvent, [newWidth, newHeight]); 242 243 if (mapPins) { 244 jQuery('.jqvmap-pin').remove(); 245 map.pinHandlers = false; 246 map.placePins(mapPins.pins, mapPins.mode); 247 } 248 } 249 }); 250 251 this.canvas = new VectorCanvas(this.width, this.height, params); 252 params.container.append(this.canvas.canvas); 253 254 this.makeDraggable(); 255 256 this.rootGroup = this.canvas.createGroup(true); 257 258 this.index = JQVMap.mapIndex; 259 this.label = jQuery('<div/>') 260 .addClass('jqvmap-label') 261 .appendTo(jQuery('body')) 262 .hide(); 263 264 if (params.enableZoom) { 265 jQuery('<div/>') 266 .addClass('jqvmap-zoomin') 267 .text('+') 268 .appendTo(params.container); 269 jQuery('<div/>') 270 .addClass('jqvmap-zoomout') 271 .html('−') 272 .appendTo(params.container); 273 } 274 275 map.countries = []; 276 277 for (var key in mapData.paths) { 278 var path = this.canvas.createPath({ 279 path: mapData.paths[key].path, 280 }); 281 282 path.setFill(this.color); 283 path.id = map.getCountryId(key); 284 map.countries[key] = path; 285 286 if (this.canvas.mode === 'svg') { 287 path.setAttribute('class', 'jqvmap-region'); 288 } else { 289 jQuery(path).addClass('jqvmap-region'); 290 } 291 292 jQuery(this.rootGroup).append(path); 293 } 294 295 jQuery(params.container).delegate( 296 this.canvas.mode === 'svg' ? 'path' : 'shape', 297 'mouseover mouseout', 298 function (e) { 299 var containerPath = e.target, 300 code = e.target.id.split('_').pop(), 301 labelShowEvent = jQuery.Event('labelShow.jqvmap'), 302 regionMouseOverEvent = jQuery.Event('regionMouseOver.jqvmap'); 303 304 code = code.toLowerCase(); 305 306 if (e.type === 'mouseover') { 307 jQuery(params.container).trigger(regionMouseOverEvent, [ 308 code, 309 mapData.paths[code].name, 310 ]); 311 if (!regionMouseOverEvent.isDefaultPrevented()) { 312 map.highlight(code, containerPath); 313 } 314 if (params.showTooltip) {
315 map.label.text(code.toUpperCase() + ' - ' + mapData.paths[code].name); 316 jQuery(params.container).trigger(labelShowEvent, [map.label, code]); 317 318 if (!labelShowEvent.isDefaultPrevented()) { 319 map.label.show(); 320 map.labelWidth = map.label.width(); 321 map.labelHeight = map.label.height(); 322 } 323 } 324 } else { 325 map.unhighlight(code, containerPath); 326 327 map.label.hide(); 328 jQuery(params.container).trigger('regionMouseOut.jqvmap', [ 329 code, 330 mapData.paths[code].name, 331 ]); 332 } 333 }, 334 ); 335 336 jQuery(params.container).delegate( 337 this.canvas.mode === 'svg' ? 'path' : 'shape', 338 'click', 339 function (regionClickEvent) { 340 var targetPath = regionClickEvent.target; 341 var code = regionClickEvent.target.id.split('_').pop(); 342 var mapClickEvent = jQuery.Event('regionClick.jqvmap'); 343 344 code = code.toLowerCase(); 345 346 jQuery(params.container).trigger(mapClickEvent, [ 347 code, 348 mapData.paths[code].name, 349 ]); 350 351 if (!params.multiSelectRegion && !mapClickEvent.isDefaultPrevented()) { 352 for (var keyPath in mapData.paths) { 353 map.countries[keyPath].currentFillColor = 354 map.countries[keyPath].getOriginalFill(); 355 map.countries[keyPath].setFill( 356 map.countries[keyPath].getOriginalFill(), 357 ); 358 } 359 } 360 361 if (!mapClickEvent.isDefaultPrevented()) { 362 if (map.isSelected(code)) { 363 map.deselect(code, targetPath); 364 } else { 365 map.select(code, targetPath); 366 } 367 } 368 }, 369 ); 370 371 if (params.showTooltip) { 372 params.container.mousemove(function (e) { 373 if (map.label.is(':visible')) { 374 var left = e.pageX - 15 - map.labelWidth; 375 var top = e.pageY - 15 - map.labelHeight; 376 377 if (left < 0) { 378 left = e.pageX + 15; 379 } 380 if (top < 0) { 381 top = e.pageY + 15; 382 } 383 384 map.label.css({ 385 left: left, 386 top: top, 387 }); 388 } 389 }); 390 } 391 392 this.setColors(params.colors); 393 394 this.canvas.canvas.appendChild(this.rootGroup); 395 396 this.applyTransform(); 397 398 this.colorScale = new ColorScale( 399 params.scaleColors, 400 params.normalizeFunction, 401 params.valueMin, 402 params.valueMax, 403 ); 404 405 if (params.values) { 406 this.values = params.values; 407 this.setValues(params.values); 408 } 409 410 if (params.selectedRegions) { 411 if (params.selectedRegions instanceof Array) { 412 for (var k in params.selectedRegions) { 413 this.select(params.selectedRegions[k].toLowerCase()); 414 } 415 } else { 416 this.select(params.selectedRegions.toLowerCase()); 417 } 418 } 419 420 this.bindZoomButtons(); 421 422 if (params.pins) { 423 mapPins = { 424 pins: params.pins, 425 mode: params.pinMode, 426 }; 427 428 this.pinHandlers = false; 429 this.placePins(params.pins, params.pinMode); 430 } 431 432 if (params.showLabels) { 433 this.pinHandlers = false; 434 435 var pins = {}; 436 for (key in map.countries) { 437 if (typeof map.countries[key] !== 'function') { 438 if (!params.pins || !params.pins[key]) { 439 pins[key] = key.toUpperCase(); 440 } 441 } 442 } 443 444 mapPins = { 445 pins: pins, 446 mode: 'content', 447 }; 448 449 this.placePins(pins, 'content'); 450 } 451 452 JQVMap.mapIndex++; 453}; 454 455JQVMap.prototype = { 456 transX: 0, 457 transY: 0, 458 scale: 1, 459 baseTransX: 0, 460 baseTransY: 0, 461 baseScale: 1, 462 width: 0, 463 height: 0, 464 countries: {}, 465 countriesColors: {}, 466 countriesData: {}, 467 zoomStep: 1.4, 468 zoomMaxStep: 4, 469 zoomCurStep: 1, 470}; 471 472JQVMap.xlink = 'http://www.w3.org/1999/xlink'; 473JQVMap.mapIndex = 1; 474JQVMap.maps = {}; 475 476(function () { 477 var apiParams = { 478 colors: 1, 479 values: 1, 480 backgroundColor: 1, 481 scaleColors: 1, 482 normalizeFunction: 1, 483 enableZoom: 1, 484 showTooltip: 1, 485 borderColor: 1, 486 borderWidth: 1, 487 borderOpacity: 1, 488 selectedRegions: 1, 489 multiSelectRegion: 1, 490 }; 491 492 var apiEvents = { 493 onLabelShow: 'labelShow', 494 onLoad: 'load', 495 onRegionOver: 'regionMouseOver', 496 onRegionOut: 'regionMouseOut',
497 onRegionClick: 'regionClick', 498 onRegionSelect: 'regionSelect', 499 onRegionDeselect: 'regionDeselect', 500 onResize: 'resize', 501 }; 502 503 jQuery.fn.vectorMap = function (options) { 504 var defaultParams = { 505 map: 'world_en', 506 backgroundColor: '#a5bfdd', 507 color: '#f4f3f0', 508 hoverColor: '#c9dfaf', 509 hoverColors: {}, 510 selectedColor: '#c9dfaf', 511 scaleColors: ['#b6d6ff', '#005ace'], 512 normalizeFunction: 'linear', 513 enableZoom: true, 514 showTooltip: true, 515 borderColor: '#818181', 516 borderWidth: 1, 517 borderOpacity: 0.25, 518 selectedRegions: null, 519 multiSelectRegion: false, 520 }, 521 map = this.data('mapObject'); 522 523 if (options === 'addMap') { 524 JQVMap.maps[arguments[1]] = arguments[2]; 525 } else if (options === 'set' && apiParams[arguments[1]]) { 526 map[ 527 'set' + arguments[1].charAt(0).toUpperCase() + arguments[1].substr(1) 528 ].apply(map, Array.prototype.slice.call(arguments, 2)); 529 } else if ( 530 typeof options === 'string' && 531 typeof map[options] === 'function' 532 ) { 533 return map[options].apply(map, Array.prototype.slice.call(arguments, 1)); 534 } else { 535 jQuery.extend(defaultParams, options); 536 defaultParams.container = this; 537 this.css({ position: 'relative', overflow: 'hidden' }); 538 539 map = new JQVMap(defaultParams); 540 541 this.data('mapObject', map); 542 543 this.unbind('.jqvmap'); 544 545 for (var e in apiEvents) { 546 if (defaultParams[e]) { 547 this.bind(apiEvents[e] + '.jqvmap', defaultParams[e]); 548 } 549 } 550 551 var loadEvent = jQuery.Event('load.jqvmap'); 552 jQuery(defaultParams.container).trigger(loadEvent, map); 553 554 return map; 555 } 556 }; 557})(jQuery); 558 559ColorScale.arrayToRgb = function (ar) { 560 var rgb = '#'; 561 var d; 562 for (var i = 0; i < ar.length; i++) { 563 d = ar[i].toString(16); 564 rgb += d.length === 1 ? '0' + d : d; 565 } 566 return rgb; 567}; 568 569ColorScale.prototype.getColor = function (value) { 570 if (typeof this.normalize === 'function') { 571 value = this.normalize(value); 572 } 573 574 var lengthes = []; 575 var fullLength = 0; 576 var l; 577 578 for (var i = 0; i < this.colors.length - 1; i++) { 579 l = this.vectorLength( 580 this.vectorSubtract(this.colors[i + 1], this.colors[i]), 581 ); 582 lengthes.push(l); 583 fullLength += l; 584 } 585 586 var c = (this.maxValue - this.minValue) / fullLength; 587 588 for (i = 0; i < lengthes.length; i++) { 589 lengthes[i] *= c; 590 } 591 592 i = 0; 593 value -= this.minValue; 594 595 while (value - lengthes[i] >= 0) { 596 value -= lengthes[i]; 597 i++; 598 } 599 600 var color; 601 if (i === this.colors.length - 1) { 602 color = this.vectorToNum(this.colors[i]).toString(16); 603 } else { 604 color = this.vectorToNum( 605 this.vectorAdd( 606 this.colors[i], 607 this.vectorMult( 608 this.vectorSubtract(this.colors[i + 1], this.colors[i]), 609 value / lengthes[i], 610 ), 611 ), 612 ).toString(16); 613 } 614 615 while (color.length < 6) { 616 color = '0' + color; 617 } 618 return '#' + color; 619}; 620 621ColorScale.rgbToArray = function (rgb) { 622 rgb = rgb.substr(1); 623 return [ 624 parseInt(rgb.substr(0, 2), 16), 625 parseInt(rgb.substr(2, 2), 16), 626 parseInt(rgb.substr(4, 2), 16), 627 ]; 628}; 629 630ColorScale.prototype.setColors = function (colors) { 631 for (var i = 0; i < colors.length; i++) { 632 colors[i] = ColorScale.rgbToArray(colors[i]); 633 } 634 this.colors = colors; 635}; 636 637ColorScale.prototype.setMax = function (max) { 638 this.clearMaxValue = max; 639 if (typeof this.normalize === 'function') { 640 this.maxValue = this.normalize(max); 641 } else { 642 this.maxValue = max; 643 } 644}; 645 646ColorScale.prototype.setMin = function (min) { 647 this.clearMinValue = min; 648 649 if (typeof this.normalize === 'function') { 650 this.minValue = this.normalize(min); 651 } else { 652 this.minValue = min; 653 } 654}; 655 656ColorScale.prototype.setNormalizeFunction = function (f) { 657 if (f === 'polynomial') { 658 this.normalize = function (value) { 659 return Math.pow(value, 0.2); 660 }; 661 } else if (f === 'linear') { 662 delete this.normalize; 663 } else { 664 this.normalize = f; 665 } 666 this.setMin(this.clearMinValue); 667 this.setMax(this.clearMaxValue); 668}; 669 670ColorScale.prototype.vectorAdd = function (vector1, vector2) { 671 var vector = []; 672 for (var i = 0; i < vector1.length; i++) { 673 vector[i] = vector1[i] + vector2[i]; 674 } 675 return vector; 676}; 677 678ColorScale.prototype.vectorLength = function (vector) { 679 var result = 0; 680 for (var i = 0; i < vector.length; i++) { 681 result += vector[i] * vector[i]; 682 } 683 return Math.sqrt(result); 684}; 685 686ColorScale.prototype.vectorMult = function (vector, num) { 687 var result = []; 688 for (var i = 0; i < vector.length; i++) { 689 result[i] = vector[i] * num; 690 } 691 return result; 692}; 693 694ColorScale.prototype.vectorSubtract = function (vector1, vector2) { 695 var vector = []; 696 for (var i = 0; i < vector1.length; i++) { 697 vector[i] = vector1[i] - vector2[i]; 698 } 699 return vector; 700}; 701 702ColorScale.prototype.vectorToNum = function (vector) { 703 var num = 0; 704 for (var i = 0; i < vector.length; i++) { 705 num += Math.round(vector[i]) * Math.pow(256, vector.length - i - 1); 706 } 707 return num; 708}; 709 710JQVMap.prototype.applyTransform = function () { 711 var maxTransX, maxTransY, minTransX, minTransY; 712 if (this.defaultWidth * this.scale <= this.width) { 713 maxTransX = 714 (this.width - this.defaultWidth * this.scale) / (2 * this.scale); 715 minTransX = 716 (this.width - this.defaultWidth * this.scale) / (2 * this.scale); 717 } else { 718 maxTransX = 0; 719 minTransX = (this.width - this.defaultWidth * this.scale) / this.scale; 720 } 721 722 if (this.defaultHeight * this.scale <= this.height) { 723 maxTransY = 724 (this.height - this.defaultHeight * this.scale) / (2 * this.scale); 725 minTransY = 726 (this.height - this.defaultHeight * this.scale) / (2 * this.scale); 727 } else { 728 maxTransY = 0; 729 minTransY = (this.height - this.defaultHeight * this.scale) / this.scale; 730 } 731 732 if (this.transY > maxTransY) { 733 this.transY = maxTransY; 734 } else if (this.transY < minTransY) { 735 this.transY = minTransY; 736 } 737 if (this.transX > maxTransX) { 738 this.transX = maxTransX; 739 } else if (this.transX < minTransX) { 740 this.transX = minTransX; 741 } 742 743 this.canvas.applyTransformParams(this.scale, this.transX, this.transY); 744}; 745 746JQVMap.prototype.bindZoomButtons = function () { 747 var map = this; 748 this.container.find('.jqvmap-zoomin').click(function () { 749 map.zoomIn(); 750 }); 751 this.container.find('.jqvmap-zoomout').click(function () { 752 map.zoomOut(); 753 }); 754}; 755 756JQVMap.prototype.deselect = function (cc, path) {
757 cc = cc.toLowerCase(); 758 path = path || jQuery('#' + this.getCountryId(cc))[0]; 759 760 if (this.isSelected(cc)) { 761 this.selectedRegions.splice(this.selectIndex(cc), 1); 762 763 jQuery(this.container).trigger('regionDeselect.jqvmap', [cc]); 764 path.currentFillColor = path.getOriginalFill(); 765 path.setFill(path.getOriginalFill()); 766 } else { 767 for (var key in this.countries) { 768 this.selectedRegions.splice(this.selectedRegions.indexOf(key), 1); 769 this.countries[key].currentFillColor = this.color; 770 this.countries[key].setFill(this.color); 771 } 772 } 773}; 774 775JQVMap.prototype.getCountryId = function (cc) { 776 return 'jqvmap' + this.index + '_' + cc; 777}; 778 779JQVMap.prototype.getPin = function (cc) { 780 var pinObj = jQuery('#' + this.getPinId(cc)); 781 return pinObj.html(); 782}; 783 784JQVMap.prototype.getPinId = function (cc) { 785 return this.getCountryId(cc) + '_pin'; 786}; 787 788JQVMap.prototype.getPins = function () { 789 var pins = this.container.find('.jqvmap-pin'); 790 var ret = {}; 791 jQuery.each(pins, function (index, pinObj) { 792 pinObj = jQuery(pinObj); 793 var cc = pinObj.attr('for').toLowerCase(); 794 var pinContent = pinObj.html(); 795 ret[cc] = pinContent; 796 }); 797 return JSON.stringify(ret); 798}; 799 800JQVMap.prototype.highlight = function (cc, path) { 801 path = path || jQuery('#' + this.getCountryId(cc))[0]; 802 if (this.hoverOpacity) { 803 path.setOpacity(this.hoverOpacity); 804 } else if (this.hoverColors && cc in this.hoverColors) { 805 path.currentFillColor = path.getFill() + ''; 806 path.setFill(this.hoverColors[cc]); 807 } else if (this.hoverColor) { 808 path.currentFillColor = path.getFill() + ''; 809 path.setFill(this.hoverColor); 810 } 811}; 812 813JQVMap.prototype.isSelected = function (cc) { 814 return this.selectIndex(cc) >= 0; 815}; 816 817JQVMap.prototype.makeDraggable = function () { 818 var mouseDown = false; 819 var oldPageX, oldPageY; 820 var self = this; 821 822 self.isMoving = false; 823 self.isMovingTimeout = false; 824 825 var lastTouchCount; 826 var touchCenterX; 827 var touchCenterY; 828 var touchStartDistance; 829 var touchStartScale; 830 var touchX; 831 var touchY; 832 833 this.container 834 .mousemove(function (e) { 835 if (mouseDown) { 836 self.transX -= (oldPageX - e.pageX) / self.scale; 837 self.transY -= (oldPageY - e.pageY) / self.scale; 838 839 self.applyTransform(); 840 841 oldPageX = e.pageX; 842 oldPageY = e.pageY; 843 844 self.isMoving = true; 845 if (self.isMovingTimeout) { 846 clearTimeout(self.isMovingTimeout); 847 } 848 849 self.container.trigger('drag'); 850 } 851 852 return false; 853 }) 854 .mousedown(function (e) { 855 mouseDown = true; 856 oldPageX = e.pageX; 857 oldPageY = e.pageY; 858 859 return false; 860 }) 861 .mouseup(function () { 862 mouseDown = false; 863 864 clearTimeout(self.isMovingTimeout); 865 self.isMovingTimeout = setTimeout(function () { 866 self.isMoving = false; 867 }, 100); 868 869 return false; 870 }) 871 .mouseout(function () { 872 if (mouseDown && self.isMoving) { 873 clearTimeout(self.isMovingTimeout); 874 self.isMovingTimeout = setTimeout(function () { 875 mouseDown = false; 876 self.isMoving = false; 877 }, 100); 878 879 return false; 880 } 881 }); 882 883 jQuery(this.container).bind('touchmove', function (e) { 884 var offset; 885 var scale; 886 var touches = e.originalEvent.touches; 887 var transformXOld; 888 var transformYOld; 889 890 if (touches.length === 1) { 891 if (lastTouchCount === 1) { 892 if (touchX === touches[0].pageX && touchY === touches[0].pageY) { 893 return; 894 } 895 896 transformXOld = self.transX; 897 transformYOld = self.transY; 898 899 self.transX -= (touchX - touches[0].pageX) / self.scale; 900 self.transY -= (touchY - touches[0].pageY) / self.scale; 901 902 self.applyTransform(); 903 904 if (transformXOld !== self.transX || transformYOld !== self.transY) { 905 e.preventDefault(); 906 } 907 908 self.isMoving = true; 909 if (self.isMovingTimeout) { 910 clearTimeout(self.isMovingTimeout); 911 } 912 } 913 914 touchX = touches[0].pageX; 915 touchY = touches[0].pageY; 916 } else if (touches.length === 2) { 917 if (lastTouchCount === 2) { 918 scale = 919 Math.sqrt( 920 Math.pow(touches[0].pageX - touches[1].pageX, 2) + 921 Math.pow(touches[0].pageY - touches[1].pageY, 2), 922 ) / touchStartDistance; 923 924 self.setScale(touchStartScale * scale, touchCenterX, touchCenterY); 925 926 e.preventDefault(); 927 } else { 928 offset = jQuery(self.container).offset(); 929 if (touches[0].pageX > touches[1].pageX) { 930 touchCenterX = 931 touches[1].pageX + (touches[0].pageX - touches[1].pageX) / 2; 932 } else { 933 touchCenterX = 934 touches[0].pageX + (touches[1].pageX - touches[0].pageX) / 2; 935 } 936 937 if (touches[0].pageY > touches[1].pageY) { 938 touchCenterY = 939 touches[1].pageY + (touches[0].pageY - touches[1].pageY) / 2; 940 } else { 941 touchCenterY = 942 touches[0].pageY + (touches[1].pageY - touches[0].pageY) / 2; 943 } 944 945 touchCenterX -= offset.left; 946 touchCenterY -= offset.top; 947 touchStartScale = self.scale; 948 949 touchStartDistance = Math.sqrt( 950 Math.pow(touches[0].pageX - touches[1].pageX, 2) + 951 Math.pow(touches[0].pageY - touches[1].pageY, 2), 952 ); 953 } 954 } 955 956 lastTouchCount = touches.length; 957 }); 958 959 jQuery(this.container).bind('touchstart', function () { 960 lastTouchCount = 0; 961 }); 962 963 jQuery(this.container).bind('touchend', function () { 964 lastTouchCount = 0; 965 }); 966}; 967 968JQVMap.prototype.placePins = function (pins, pinMode) { 969 var map = this; 970
971 if (!pinMode || (pinMode !== 'content' && pinMode !== 'id')) { 972 pinMode = 'content'; 973 } 974 975 if (pinMode === 'content') { 976 //treat pin as content 977 jQuery.each(pins, function (index, pin) { 978 if (jQuery('#' + map.getCountryId(index)).length === 0) { 979 return; 980 } 981 982 var pinIndex = map.getPinId(index); 983 var $pin = jQuery('#' + pinIndex); 984 if ($pin.length > 0) { 985 $pin.remove(); 986 } 987 map.container.append( 988 '<div id="' + 989 pinIndex + 990 '" for="' + 991 index + 992 '" class="jqvmap-pin" style="position:absolute">' + 993 pin + 994 '</div>', 995 ); 996 }); 997 } else { 998 //treat pin as id of an html content 999 jQuery.each(pins, function (index, pin) { 1000 if (jQuery('#' + map.getCountryId(index)).length === 0) { 1001 return; 1002 } 1003 var pinIndex = map.getPinId(index); 1004 var $pin = jQuery('#' + pinIndex); 1005 if ($pin.length > 0) { 1006 $pin.remove(); 1007 } 1008 map.container.append( 1009 '<div id="' + 1010 pinIndex + 1011 '" for="' + 1012 index + 1013 '" class="jqvmap-pin" style="position:absolute"></div>', 1014 ); 1015 $pin.append(jQuery('#' + pin)); 1016 }); 1017 } 1018 1019 this.positionPins(); 1020 if (!this.pinHandlers) { 1021 this.pinHandlers = true; 1022 var positionFix = function () { 1023 map.positionPins(); 1024 }; 1025 this.container 1026 .bind('zoomIn', positionFix) 1027 .bind('zoomOut', positionFix) 1028 .bind('drag', positionFix); 1029 } 1030}; 1031 1032JQVMap.prototype.positionPins = function () { 1033 var map = this; 1034 var pins = this.container.find('.jqvmap-pin'); 1035 jQuery.each(pins, function (index, pinObj) { 1036 pinObj = jQuery(pinObj); 1037 var countryId = map.getCountryId(pinObj.attr('for').toLowerCase()); 1038 var countryObj = jQuery('#' + countryId); 1039 var bbox = countryObj[0].getBBox(); 1040 1041 var scale = map.scale; 1042 var rootCoords = map.canvas.rootGroup.getBoundingClientRect(); 1043 var mapCoords = map.container[0].getBoundingClientRect(); 1044 var coords = { 1045 left: rootCoords.left - mapCoords.left, 1046 top: rootCoords.top - mapCoords.top, 1047 }; 1048 1049 var middleX = bbox.x * scale + (bbox.width * scale) / 2;
1050 var middleY = bbox.y * scale + (bbox.height * scale) / 2; 1051 1052 pinObj.css({ 1053 left: coords.left + middleX - pinObj.width() / 2, 1054 top: coords.top + middleY - pinObj.height() / 2, 1055 }); 1056 }); 1057}; 1058 1059JQVMap.prototype.removePin = function (cc) { 1060 cc = cc.toLowerCase(); 1061 jQuery('#' + this.getPinId(cc)).remove(); 1062}; 1063 1064JQVMap.prototype.removePins = function () { 1065 this.container.find('.jqvmap-pin').remove(); 1066}; 1067 1068JQVMap.prototype.reset = function () { 1069 for (var key in this.countries) { 1070 this.countries[key].setFill(this.color); 1071 } 1072 this.scale = this.baseScale; 1073 this.transX = this.baseTransX; 1074 this.transY = this.baseTransY; 1075 this.applyTransform(); 1076 this.zoomCurStep = 1; 1077}; 1078 1079JQVMap.prototype.resize = function () { 1080 var curBaseScale = this.baseScale; 1081 if (this.width / this.height > this.defaultWidth / this.defaultHeight) { 1082 this.baseScale = this.height / this.defaultHeight; 1083 this.baseTransX = 1084 Math.abs(this.width - this.defaultWidth * this.baseScale) / 1085 (2 * this.baseScale); 1086 } else { 1087 this.baseScale = this.width / this.defaultWidth; 1088 this.baseTransY = 1089 Math.abs(this.height - this.defaultHeight * this.baseScale) / 1090 (2 * this.baseScale); 1091 } 1092 this.scale *= this.baseScale / curBaseScale; 1093 this.transX *= this.baseScale / curBaseScale; 1094 this.transY *= this.baseScale / curBaseScale; 1095}; 1096 1097JQVMap.prototype.select = function (cc, path) { 1098 cc = cc.toLowerCase(); 1099 path = path || jQuery('#' + this.getCountryId(cc))[0]; 1100 1101 if (!this.isSelected(cc)) { 1102 if (this.multiSelectRegion) { 1103 this.selectedRegions.push(cc); 1104 } else { 1105 this.selectedRegions = [cc]; 1106 } 1107 1108 jQuery(this.container).trigger('regionSelect.jqvmap', [cc]); 1109 if (this.selectedColor && path) { 1110 path.currentFillColor = this.selectedColor; 1111 path.setFill(this.selectedColor); 1112 } 1113 } 1114}; 1115 1116JQVMap.prototype.selectIndex = function (cc) { 1117 cc = cc.toLowerCase(); 1118 for (var i = 0; i < this.selectedRegions.length; i++) { 1119 if (cc === this.selectedRegions[i]) { 1120 return i; 1121 } 1122 } 1123 return -1; 1124}; 1125 1126JQVMap.prototype.setBackgroundColor = function (backgroundColor) { 1127 this.container.css('background-color', backgroundColor); 1128}; 1129 1130JQVMap.prototype.setColors = function (key, color) { 1131 if (typeof key === 'string') { 1132 this.countries[key].setFill(color); 1133 this.countries[key].setAttribute('original', color); 1134 } else { 1135 var colors = key; 1136 1137 for (var code in colors) { 1138 if (this.countries[code]) { 1139 this.countries[code].setFill(colors[code]); 1140 this.countries[code].setAttribute('original', colors[code]); 1141 } 1142 } 1143 } 1144}; 1145 1146JQVMap.prototype.setNormalizeFunction = function (f) { 1147 this.colorScale.setNormalizeFunction(f); 1148 1149 if (this.values) { 1150 this.setValues(this.values); 1151 } 1152}; 1153 1154JQVMap.prototype.setScale = function (scale) { 1155 this.scale = scale; 1156 this.applyTransform(); 1157}; 1158 1159JQVMap.prototype.setScaleColors = function (colors) { 1160 this.colorScale.setColors(colors); 1161 1162 if (this.values) { 1163 this.setValues(this.values); 1164 } 1165}; 1166 1167JQVMap.prototype.setValues = function (values) { 1168 var max = 0, 1169 min = Number.MAX_VALUE, 1170 val; 1171 1172 for (var cc in values) { 1173 cc = cc.toLowerCase(); 1174 val = parseFloat(values[cc]); 1175 1176 if (isNaN(val)) { 1177 continue; 1178 } 1179 if (val > max) { 1180 max = values[cc]; 1181 } 1182 if (val < min) { 1183 min = val; 1184 } 1185 } 1186 1187 if (min === max) { 1188 max++; 1189 } 1190 1191 this.colorScale.setMin(min); 1192 this.colorScale.setMax(max); 1193 1194 var colors = {}; 1195 for (cc in values) { 1196 cc = cc.toLowerCase(); 1197 val = parseFloat(values[cc]); 1198 colors[cc] = isNaN(val) ? this.color : this.colorScale.getColor(val); 1199 } 1200 this.setColors(colors); 1201 this.values = values; 1202}; 1203 1204JQVMap.prototype.unhighlight = function (cc, path) { 1205 cc = cc.toLowerCase(); 1206 path = path || jQuery('#' + this.getCountryId(cc))[0]; 1207 path.setOpacity(1); 1208 if (path.currentFillColor) { 1209 path.setFill(path.currentFillColor); 1210 } 1211}; 1212 1213JQVMap.prototype.zoomIn = function () { 1214 var map = this; 1215 var sliderDelta = 1216 (jQuery('#zoom').innerHeight() - 6 * 2 - 15 * 2 - 3 * 2 - 7 - 6) / 1217 (this.zoomMaxStep - this.zoomCurStep); 1218 1219 if (map.zoomCurStep < map.zoomMaxStep) { 1220 map.transX -= 1221 (map.width / map.scale - map.width / (map.scale * map.zoomStep)) / 2; 1222 map.transY -= 1223 (map.height / map.scale - map.height / (map.scale * map.zoomStep)) / 2; 1224 map.setScale(map.scale * map.zoomStep); 1225 map.zoomCurStep++; 1226 1227 var $slider = jQuery('#zoomSlider'); 1228 1229 $slider.css('top', parseInt($slider.css('top'), 10) - sliderDelta); 1230 1231 map.container.trigger('zoomIn'); 1232 } 1233}; 1234 1235JQVMap.prototype.zoomOut = function () { 1236 var map = this; 1237 var sliderDelta = 1238 (jQuery('#zoom').innerHeight() - 6 * 2 - 15 * 2 - 3 * 2 - 7 - 6) / 1239 (this.zoomMaxStep - this.zoomCurStep); 1240 1241 if (map.zoomCurStep > 1) { 1242 map.transX += 1243 (map.width / (map.scale / map.zoomStep) - map.width / map.scale) / 2; 1244 map.transY += 1245 (map.height / (map.scale / map.zoomStep) - map.height / map.scale) / 2; 1246 map.setScale(map.scale / map.zoomStep); 1247 map.zoomCurStep--; 1248 1249 var $slider = jQuery('#zoomSlider'); 1250 1251 $slider.css('top', parseInt($slider.css('top'), 10) + sliderDelta); 1252 1253 map.container.trigger('zoomOut'); 1254 } 1255}; 1256 1257VectorCanvas.prototype.applyTransformParams = function (scale, transX, transY) { 1258 if (this.mode === 'svg') { 1259 this.rootGroup.setAttribute( 1260 'transform', 1261 'scale(' + scale + ') translate(' + transX + ', ' + transY + ')', 1262 ); 1263 } else { 1264 this.rootGroup.coordorigin = 1265 this.width - transX + ',' + (this.height - transY); 1266 this.rootGroup.coordsize = this.width / scale + ',' + this.height / scale; 1267 } 1268}; 1269 1270VectorCanvas.prototype.createGroup = function (isRoot) { 1271 var node; 1272 if (this.mode === 'svg') { 1273 node = this.createSvgNode('g'); 1274 } else { 1275 node = this.createVmlNode('group'); 1276 node.style.width = this.width + 'px'; 1277 node.style.height = this.height + 'px'; 1278 node.style.left = '0px'; 1279 node.style.top = '0px'; 1280 node.coordorigin = '0 0'; 1281 node.coordsize = this.width + ' ' + this.height; 1282 } 1283 1284 if (isRoot) { 1285 this.rootGroup = node; 1286 } 1287 return node; 1288}; 1289 1290VectorCanvas.prototype.createPath = function (config) { 1291 var node; 1292 if (this.mode === 'svg') { 1293 node = this.createSvgNode('path'); 1294 node.setAttribute('d', config.path); 1295 1296 if (this.params.borderColor !== null) { 1297 node.setAttribute('stroke', this.params.borderColor); 1298 } 1299 if (this.params.borderWidth > 0) { 1300 node.setAttribute('stroke-width', this.params.borderWidth); 1301 node.setAttribute('stroke-linecap', 'round'); 1302 node.setAttribute('stroke-linejoin', 'round'); 1303 } 1304 if (this.params.borderOpacity > 0) { 1305 node.setAttribute('stroke-opacity', this.params.borderOpacity); 1306 } 1307 1308 node.setFill = function (color) { 1309 this.setAttribute('fill', color); 1310 if (this.getAttribute('original') === null) { 1311 this.setAttribute('original', color); 1312 } 1313 }; 1314 1315 node.getFill = function () { 1316 return this.getAttribute('fill'); 1317 }; 1318 1319 node.getOriginalFill = function () { 1320 return this.getAttribute('original'); 1321 }; 1322 1323 node.setOpacity = function (opacity) { 1324 this.setAttribute('fill-opacity', opacity); 1325 }; 1326 } else { 1327 node = this.createVmlNode('shape'); 1328 node.coordorigin = '0 0'; 1329 node.coordsize = this.width + ' ' + this.height; 1330 node.style.width = this.width + 'px'; 1331 node.style.height = this.height + 'px'; 1332 node.fillcolor = JQVMap.defaultFillColor; 1333 node.stroked = false;
1334 node.path = VectorCanvas.pathSvgToVml(config.path); 1335 1336 var scale = this.createVmlNode('skew'); 1337 scale.on = true; 1338 scale.matrix = '0.01,0,0,0.01,0,0'; 1339 scale.offset = '0,0'; 1340 1341 node.appendChild(scale); 1342 1343 var fill = this.createVmlNode('fill'); 1344 node.appendChild(fill); 1345 1346 node.setFill = function (color) { 1347 this.getElementsByTagName('fill')[0].color = color; 1348 if (this.getAttribute('original') === null) { 1349 this.setAttribute('original', color); 1350 } 1351 }; 1352 1353 node.getFill = function () { 1354 return this.getElementsByTagName('fill')[0].color; 1355 }; 1356 node.getOriginalFill = function () { 1357 return this.getAttribute('original'); 1358 }; 1359 node.setOpacity = function (opacity) { 1360 this.getElementsByTagName('fill')[0].opacity = 1361 parseInt(opacity * 100, 10) + '%'; 1362 }; 1363 } 1364 return node; 1365}; 1366 1367VectorCanvas.prototype.pathSvgToVml = function (path) { 1368 var result = ''; 1369 var cx = 0, 1370 cy = 0, 1371 ctrlx, 1372 ctrly; 1373 1374 return path 1375 .replace( 1376 /([MmLlHhVvCcSs])((?:-?(?:\d+)?(?:\.\d+)?,?\s?)+)/g, 1377 function (segment, letter, coords) { 1378 coords = coords 1379 .replace(/(\d)-/g, '$1,-') 1380 .replace(/\s+/g, ',') 1381 .split(','); 1382 if (!coords[0]) { 1383 coords.shift(); 1384 } 1385 1386 for (var i = 0, l = coords.length; i < l; i++) { 1387 coords[i] = Math.round(100 * coords[i]); 1388 } 1389 1390 switch (letter) { 1391 case 'm': 1392 cx += coords[0]; 1393 cy += coords[1]; 1394 result = 't' + coords.join(','); 1395 break; 1396 1397 case 'M': 1398 cx = coords[0]; 1399 cy = coords[1]; 1400 result = 'm' + coords.join(','); 1401 break; 1402 1403 case 'l': 1404 cx += coords[0]; 1405 cy += coords[1]; 1406 result = 'r' + coords.join(','); 1407 break; 1408 1409 case 'L': 1410 cx = coords[0]; 1411 cy = coords[1]; 1412 result = 'l' + coords.join(','); 1413 break; 1414 1415 case 'h': 1416 cx += coords[0]; 1417 result = 'r' + coords[0] + ',0'; 1418 break; 1419 1420 case 'H': 1421 cx = coords[0]; 1422 result = 'l' + cx + ',' + cy; 1423 break; 1424 1425 case 'v': 1426 cy += coords[0]; 1427 result = 'r0,' + coords[0]; 1428 break; 1429 1430 case 'V': 1431 cy = coords[0]; 1432 result = 'l' + cx + ',' + cy; 1433 break; 1434 1435 case 'c': 1436 ctrlx = cx + coords[coords.length - 4]; 1437 ctrly = cy + coords[coords.length - 3]; 1438 cx += coords[coords.length - 2]; 1439 cy += coords[coords.length - 1]; 1440 result = 'v' + coords.join(','); 1441 break; 1442 1443 case 'C': 1444 ctrlx = coords[coords.length - 4]; 1445 ctrly = coords[coords.length - 3]; 1446 cx = coords[coords.length - 2]; 1447 cy = coords[coords.length - 1]; 1448 result = 'c' + coords.join(','); 1449 break; 1450 1451 case 's': 1452 coords.unshift(cy - ctrly); 1453 coords.unshift(cx - ctrlx); 1454 ctrlx = cx + coords[coords.length - 4]; 1455 ctrly = cy + coords[coords.length - 3]; 1456 cx += coords[coords.length - 2]; 1457 cy += coords[coords.length - 1]; 1458 result = 'v' + coords.join(','); 1459 break; 1460 1461 case 'S': 1462 coords.unshift(cy + cy - ctrly); 1463 coords.unshift(cx + cx - ctrlx); 1464 ctrlx = coords[coords.length - 4]; 1465 ctrly = coords[coords.length - 3]; 1466 cx = coords[coords.length - 2]; 1467 cy = coords[coords.length - 1]; 1468 result = 'c' + coords.join(','); 1469 break; 1470 1471 default: 1472 break; 1473 } 1474 1475 return result; 1476 }, 1477 ) 1478 .replace(/z/g, ''); 1479}; 1480 1481VectorCanvas.prototype.setSize = function (width, height) { 1482 if (this.mode === 'svg') { 1483 this.canvas.setAttribute('width', width); 1484 this.canvas.setAttribute('height', height); 1485 } else { 1486 this.canvas.style.width = width + 'px'; 1487 this.canvas.style.height = height + 'px'; 1488 this.canvas.coordsize = width + ' ' + height; 1489 this.canvas.coordorigin = '0 0'; 1490 if (this.rootGroup) { 1491 var paths = this.rootGroup.getElementsByTagName('shape'); 1492 for (var i = 0, l = paths.length; i < l; i++) { 1493 paths[i].coordsize = width + ' ' + height; 1494 paths[i].style.width = width + 'px'; 1495 paths[i].style.height = height + 'px'; 1496 } 1497 this.rootGroup.coordsize = width + ' ' + height; 1498 this.rootGroup.style.width = width + 'px'; 1499 this.rootGroup.style.height = height + 'px'; 1500 } 1501 } 1502 this.width = width; 1503 this.height = height; 1504};
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.