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