jvectormap-rails 1.0.1 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (202) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +3 -1
  3. data/README.md +9 -4
  4. data/Rakefile +8 -8
  5. data/jvectormap-rails.gemspec +7 -7
  6. data/lib/jvectormap-rails.rb +2 -10
  7. data/lib/jvectormap/rails/engine.rb +11 -2
  8. data/lib/jvectormap/rails/version.rb +3 -5
  9. data/tasks/jvectormap.rake +6 -3
  10. data/vendor/assets/javascripts/jvectormap.js +32 -25
  11. data/vendor/assets/javascripts/jvectormap/jquery-jvectormap.js +5 -6
  12. data/vendor/assets/javascripts/jvectormap/lib/jquery-mousewheel.js +201 -0
  13. data/vendor/assets/javascripts/jvectormap/maps/africa_merc.js +1 -0
  14. data/vendor/assets/javascripts/jvectormap/maps/africa_mill.js +1 -0
  15. data/vendor/assets/javascripts/jvectormap/maps/ar_merc.js +1 -0
  16. data/vendor/assets/javascripts/jvectormap/maps/ar_mill.js +1 -0
  17. data/vendor/assets/javascripts/jvectormap/maps/asia_merc.js +1 -0
  18. data/vendor/assets/javascripts/jvectormap/maps/asia_mill.js +1 -0
  19. data/vendor/assets/javascripts/jvectormap/maps/at_merc.js +1 -0
  20. data/vendor/assets/javascripts/jvectormap/maps/at_mill.js +1 -0
  21. data/vendor/assets/javascripts/jvectormap/maps/au_merc.js +1 -0
  22. data/vendor/assets/javascripts/jvectormap/maps/au_mill.js +1 -0
  23. data/vendor/assets/javascripts/jvectormap/maps/be_merc.js +1 -0
  24. data/vendor/assets/javascripts/jvectormap/maps/be_mill.js +1 -0
  25. data/vendor/assets/javascripts/jvectormap/maps/ca_lcc.js +1 -0
  26. data/vendor/assets/javascripts/jvectormap/maps/ca_merc.js +1 -0
  27. data/vendor/assets/javascripts/jvectormap/maps/ca_mill.js +1 -0
  28. data/vendor/assets/javascripts/jvectormap/maps/ch_merc.js +1 -0
  29. data/vendor/assets/javascripts/jvectormap/maps/ch_mill.js +1 -0
  30. data/vendor/assets/javascripts/jvectormap/maps/cn_merc.js +1 -0
  31. data/vendor/assets/javascripts/jvectormap/maps/cn_mill.js +1 -0
  32. data/vendor/assets/javascripts/jvectormap/maps/co_merc.js +1 -0
  33. data/vendor/assets/javascripts/jvectormap/maps/co_mill.js +1 -0
  34. data/vendor/assets/javascripts/jvectormap/maps/continents_merc.js +1 -0
  35. data/vendor/assets/javascripts/jvectormap/maps/continents_mill.js +1 -0
  36. data/vendor/assets/javascripts/jvectormap/maps/de_merc.js +1 -0
  37. data/vendor/assets/javascripts/jvectormap/maps/de_mill.js +1 -0
  38. data/vendor/assets/javascripts/jvectormap/maps/dk_merc.js +1 -0
  39. data/vendor/assets/javascripts/jvectormap/maps/dk_mill.js +1 -0
  40. data/vendor/assets/javascripts/jvectormap/maps/es_merc.js +1 -0
  41. data/vendor/assets/javascripts/jvectormap/maps/es_mill.js +1 -0
  42. data/vendor/assets/javascripts/jvectormap/maps/europe_merc.js +1 -0
  43. data/vendor/assets/javascripts/jvectormap/maps/europe_mill.js +1 -0
  44. data/vendor/assets/javascripts/jvectormap/maps/fr_merc.js +1 -0
  45. data/vendor/assets/javascripts/jvectormap/maps/fr_mill.js +1 -0
  46. data/vendor/assets/javascripts/jvectormap/maps/fr_regions_2016_merc.js +1 -0
  47. data/vendor/assets/javascripts/jvectormap/maps/fr_regions_2016_mill.js +1 -0
  48. data/vendor/assets/javascripts/jvectormap/maps/fr_regions_merc.js +1 -0
  49. data/vendor/assets/javascripts/jvectormap/maps/fr_regions_mill.js +1 -0
  50. data/vendor/assets/javascripts/jvectormap/maps/in_merc.js +1 -0
  51. data/vendor/assets/javascripts/jvectormap/maps/in_mill.js +1 -0
  52. data/vendor/assets/javascripts/jvectormap/maps/it_merc.js +1 -0
  53. data/vendor/assets/javascripts/jvectormap/maps/it_mill.js +1 -0
  54. data/vendor/assets/javascripts/jvectormap/maps/it_regions_merc.js +1 -0
  55. data/vendor/assets/javascripts/jvectormap/maps/it_regions_mill.js +1 -0
  56. data/vendor/assets/javascripts/jvectormap/maps/kr_merc.js +1 -0
  57. data/vendor/assets/javascripts/jvectormap/maps/kr_mill.js +1 -0
  58. data/vendor/assets/javascripts/jvectormap/maps/nl_merc.js +1 -0
  59. data/vendor/assets/javascripts/jvectormap/maps/nl_mill.js +1 -0
  60. data/vendor/assets/javascripts/jvectormap/maps/no_merc.js +1 -0
  61. data/vendor/assets/javascripts/jvectormap/maps/no_mill.js +1 -0
  62. data/vendor/assets/javascripts/jvectormap/maps/north_america_merc.js +1 -0
  63. data/vendor/assets/javascripts/jvectormap/maps/north_america_mill.js +1 -0
  64. data/vendor/assets/javascripts/jvectormap/maps/nz_merc.js +1 -0
  65. data/vendor/assets/javascripts/jvectormap/maps/nz_mill.js +1 -0
  66. data/vendor/assets/javascripts/jvectormap/maps/oceania_merc.js +1 -0
  67. data/vendor/assets/javascripts/jvectormap/maps/oceania_mill.js +1 -0
  68. data/vendor/assets/javascripts/jvectormap/maps/pl_merc.js +1 -0
  69. data/vendor/assets/javascripts/jvectormap/maps/pl_mill.js +1 -0
  70. data/vendor/assets/javascripts/jvectormap/maps/pt_merc.js +1 -0
  71. data/vendor/assets/javascripts/jvectormap/maps/pt_mill.js +1 -0
  72. data/vendor/assets/javascripts/jvectormap/maps/ru_fd_merc.js +1 -0
  73. data/vendor/assets/javascripts/jvectormap/maps/ru_fd_mill.js +1 -0
  74. data/vendor/assets/javascripts/jvectormap/maps/ru_merc.js +1 -0
  75. data/vendor/assets/javascripts/jvectormap/maps/ru_mill.js +1 -0
  76. data/vendor/assets/javascripts/jvectormap/maps/se_merc.js +1 -0
  77. data/vendor/assets/javascripts/jvectormap/maps/se_mill.js +1 -0
  78. data/vendor/assets/javascripts/jvectormap/maps/south_america_merc.js +1 -0
  79. data/vendor/assets/javascripts/jvectormap/maps/south_america_mill.js +1 -0
  80. data/vendor/assets/javascripts/jvectormap/maps/th_merc.js +1 -0
  81. data/vendor/assets/javascripts/jvectormap/maps/th_mill.js +1 -0
  82. data/vendor/assets/javascripts/jvectormap/maps/uk_countries_merc.js +1 -0
  83. data/vendor/assets/javascripts/jvectormap/maps/uk_countries_mill.js +1 -0
  84. data/vendor/assets/javascripts/jvectormap/maps/uk_regions_merc.js +1 -0
  85. data/vendor/assets/javascripts/jvectormap/maps/uk_regions_mill.js +1 -0
  86. data/vendor/assets/javascripts/jvectormap/maps/us-il-chicago_merc.js +1 -0
  87. data/vendor/assets/javascripts/jvectormap/maps/us-il-chicago_mill.js +1 -0
  88. data/vendor/assets/javascripts/jvectormap/maps/us-ny-newyork_merc.js +1 -0
  89. data/vendor/assets/javascripts/jvectormap/maps/us-ny-newyork_mill.js +1 -0
  90. data/vendor/assets/javascripts/jvectormap/maps/us_aea.js +1 -0
  91. data/vendor/assets/javascripts/jvectormap/maps/us_lcc.js +1 -0
  92. data/vendor/assets/javascripts/jvectormap/maps/us_merc.js +1 -0
  93. data/vendor/assets/javascripts/jvectormap/maps/us_mill.js +1 -0
  94. data/vendor/assets/javascripts/jvectormap/maps/ve_merc.js +1 -0
  95. data/vendor/assets/javascripts/jvectormap/maps/ve_mill.js +1 -0
  96. data/vendor/assets/javascripts/jvectormap/maps/world_merc.js +1 -0
  97. data/vendor/assets/javascripts/jvectormap/maps/world_mill.js +1 -0
  98. data/vendor/assets/javascripts/jvectormap/maps/za_merc.js +1 -0
  99. data/vendor/assets/javascripts/jvectormap/maps/za_mill.js +1 -0
  100. data/vendor/assets/javascripts/jvectormap/{lib → src}/abstract-canvas-element.js +26 -0
  101. data/vendor/assets/javascripts/jvectormap/{lib → src}/abstract-element.js +0 -0
  102. data/vendor/assets/javascripts/jvectormap/{lib → src}/abstract-shape-element.js +1 -24
  103. data/vendor/assets/javascripts/jvectormap/{lib → src}/color-scale.js +0 -0
  104. data/vendor/assets/javascripts/jvectormap/{lib → src}/data-series.js +36 -17
  105. data/vendor/assets/javascripts/jvectormap/src/jvectormap.js +185 -0
  106. data/vendor/assets/javascripts/jvectormap/src/legend.js +83 -0
  107. data/vendor/assets/javascripts/jvectormap/src/map-object.js +73 -0
  108. data/vendor/assets/javascripts/jvectormap/{lib/world-map.js → src/map.js} +357 -148
  109. data/vendor/assets/javascripts/jvectormap/src/marker.js +76 -0
  110. data/vendor/assets/javascripts/jvectormap/src/multimap.js +139 -0
  111. data/vendor/assets/javascripts/jvectormap/{lib → src}/numeric-scale.js +41 -3
  112. data/vendor/assets/javascripts/jvectormap/src/ordinal-scale.js +21 -0
  113. data/vendor/assets/javascripts/jvectormap/{lib → src}/proj.js +0 -0
  114. data/vendor/assets/javascripts/jvectormap/src/region.js +45 -0
  115. data/vendor/assets/javascripts/jvectormap/{lib → src}/simple-scale.js +0 -0
  116. data/vendor/assets/javascripts/jvectormap/{lib → src}/svg-canvas-element.js +4 -0
  117. data/vendor/assets/javascripts/jvectormap/{lib → src}/svg-circle-element.js +0 -0
  118. data/vendor/assets/javascripts/jvectormap/{lib → src}/svg-element.js +0 -0
  119. data/vendor/assets/javascripts/jvectormap/{lib → src}/svg-group-element.js +0 -0
  120. data/vendor/assets/javascripts/jvectormap/src/svg-image-element.js +36 -0
  121. data/vendor/assets/javascripts/jvectormap/{lib → src}/svg-path-element.js +0 -0
  122. data/vendor/assets/javascripts/jvectormap/src/svg-shape-element.js +49 -0
  123. data/vendor/assets/javascripts/jvectormap/src/svg-text-element.js +13 -0
  124. data/vendor/assets/javascripts/jvectormap/{lib → src}/vector-canvas.js +2 -0
  125. data/vendor/assets/javascripts/jvectormap/{lib → src}/vml-canvas-element.js +0 -0
  126. data/vendor/assets/javascripts/jvectormap/{lib → src}/vml-circle-element.js +0 -0
  127. data/vendor/assets/javascripts/jvectormap/{lib → src}/vml-element.js +1 -0
  128. data/vendor/assets/javascripts/jvectormap/{lib → src}/vml-group-element.js +0 -0
  129. data/vendor/assets/javascripts/jvectormap/src/vml-image-element.js +47 -0
  130. data/vendor/assets/javascripts/jvectormap/{lib → src}/vml-path-element.js +1 -14
  131. data/vendor/assets/javascripts/jvectormap/{lib → src}/vml-shape-element.js +0 -0
  132. data/vendor/assets/stylesheets/jvectormap.css +107 -9
  133. metadata +127 -103
  134. data/History.txt +0 -7
  135. data/lib/jvectormap/rails/railtie.rb +0 -17
  136. data/vendor/assets/javascripts/jvectormap/jquery-mousewheel.js +0 -84
  137. data/vendor/assets/javascripts/jvectormap/lib/jvectormap.js +0 -99
  138. data/vendor/assets/javascripts/jvectormap/lib/ordinal-scale.js +0 -7
  139. data/vendor/assets/javascripts/jvectormap/lib/svg-shape-element.js +0 -7
  140. data/vendor/assets/javascripts/jvectormap/maps/ar_merc_en.js +0 -1
  141. data/vendor/assets/javascripts/jvectormap/maps/ar_mill_en.js +0 -1
  142. data/vendor/assets/javascripts/jvectormap/maps/at_merc_en.js +0 -1
  143. data/vendor/assets/javascripts/jvectormap/maps/at_mill_en.js +0 -1
  144. data/vendor/assets/javascripts/jvectormap/maps/au_merc_en.js +0 -1
  145. data/vendor/assets/javascripts/jvectormap/maps/au_mill_en.js +0 -1
  146. data/vendor/assets/javascripts/jvectormap/maps/be_merc_en.js +0 -1
  147. data/vendor/assets/javascripts/jvectormap/maps/be_mill_en.js +0 -1
  148. data/vendor/assets/javascripts/jvectormap/maps/ca_lcc_en.js +0 -1
  149. data/vendor/assets/javascripts/jvectormap/maps/ca_merc_en.js +0 -1
  150. data/vendor/assets/javascripts/jvectormap/maps/ca_mill_en.js +0 -1
  151. data/vendor/assets/javascripts/jvectormap/maps/ch_merc_en.js +0 -1
  152. data/vendor/assets/javascripts/jvectormap/maps/ch_mill_en.js +0 -1
  153. data/vendor/assets/javascripts/jvectormap/maps/cn_merc_en.js +0 -1
  154. data/vendor/assets/javascripts/jvectormap/maps/cn_mill_en.js +0 -1
  155. data/vendor/assets/javascripts/jvectormap/maps/co_merc_en.js +0 -1
  156. data/vendor/assets/javascripts/jvectormap/maps/co_mill_en.js +0 -1
  157. data/vendor/assets/javascripts/jvectormap/maps/de_merc_en.js +0 -1
  158. data/vendor/assets/javascripts/jvectormap/maps/de_mill_en.js +0 -1
  159. data/vendor/assets/javascripts/jvectormap/maps/dk_merc_en.js +0 -1
  160. data/vendor/assets/javascripts/jvectormap/maps/dk_mill_en.js +0 -1
  161. data/vendor/assets/javascripts/jvectormap/maps/es_merc_en.js +0 -1
  162. data/vendor/assets/javascripts/jvectormap/maps/es_mill_en.js +0 -1
  163. data/vendor/assets/javascripts/jvectormap/maps/europe_merc_en.js +0 -1
  164. data/vendor/assets/javascripts/jvectormap/maps/europe_mill_en.js +0 -1
  165. data/vendor/assets/javascripts/jvectormap/maps/fr_merc_en.js +0 -1
  166. data/vendor/assets/javascripts/jvectormap/maps/fr_mill_en.js +0 -1
  167. data/vendor/assets/javascripts/jvectormap/maps/in_merc_en.js +0 -1
  168. data/vendor/assets/javascripts/jvectormap/maps/in_mill_en.js +0 -1
  169. data/vendor/assets/javascripts/jvectormap/maps/it_merc_en.js +0 -1
  170. data/vendor/assets/javascripts/jvectormap/maps/it_mill_en.js +0 -1
  171. data/vendor/assets/javascripts/jvectormap/maps/nl_merc_en.js +0 -1
  172. data/vendor/assets/javascripts/jvectormap/maps/nl_mill_en.js +0 -1
  173. data/vendor/assets/javascripts/jvectormap/maps/no_merc_en.js +0 -1
  174. data/vendor/assets/javascripts/jvectormap/maps/no_mill_en.js +0 -1
  175. data/vendor/assets/javascripts/jvectormap/maps/nz_merc_en.js +0 -1
  176. data/vendor/assets/javascripts/jvectormap/maps/nz_mill_en.js +0 -1
  177. data/vendor/assets/javascripts/jvectormap/maps/ph_regions_merc_en.js +0 -1
  178. data/vendor/assets/javascripts/jvectormap/maps/ph_regions_mill_en.js +0 -1
  179. data/vendor/assets/javascripts/jvectormap/maps/pl_merc_en.js +0 -1
  180. data/vendor/assets/javascripts/jvectormap/maps/pl_mill_en.js +0 -1
  181. data/vendor/assets/javascripts/jvectormap/maps/pt_merc_en.js +0 -1
  182. data/vendor/assets/javascripts/jvectormap/maps/pt_mill_en.js +0 -1
  183. data/vendor/assets/javascripts/jvectormap/maps/se_merc_en.js +0 -1
  184. data/vendor/assets/javascripts/jvectormap/maps/se_mill_en.js +0 -1
  185. data/vendor/assets/javascripts/jvectormap/maps/th_merc_en.js +0 -1
  186. data/vendor/assets/javascripts/jvectormap/maps/th_mill_en.js +0 -1
  187. data/vendor/assets/javascripts/jvectormap/maps/th_regions_merc_en.js +0 -1
  188. data/vendor/assets/javascripts/jvectormap/maps/th_regions_mill_en.js +0 -1
  189. data/vendor/assets/javascripts/jvectormap/maps/uk_merc_en.js +0 -1
  190. data/vendor/assets/javascripts/jvectormap/maps/uk_mill_en.js +0 -1
  191. data/vendor/assets/javascripts/jvectormap/maps/us-il-chicago_mill_en.js +0 -1
  192. data/vendor/assets/javascripts/jvectormap/maps/us-ny-newyork_mill_en.js +0 -1
  193. data/vendor/assets/javascripts/jvectormap/maps/us_aea_en.js +0 -1
  194. data/vendor/assets/javascripts/jvectormap/maps/us_lcc_en.js +0 -1
  195. data/vendor/assets/javascripts/jvectormap/maps/us_merc_en.js +0 -1
  196. data/vendor/assets/javascripts/jvectormap/maps/us_mill_en.js +0 -1
  197. data/vendor/assets/javascripts/jvectormap/maps/ve_merc_en.js +0 -1
  198. data/vendor/assets/javascripts/jvectormap/maps/ve_mill_en.js +0 -1
  199. data/vendor/assets/javascripts/jvectormap/maps/world_merc_en.js +0 -1
  200. data/vendor/assets/javascripts/jvectormap/maps/world_mill_en.js +0 -1
  201. data/vendor/assets/javascripts/jvectormap/maps/za_merc_en.js +0 -1
  202. data/vendor/assets/javascripts/jvectormap/maps/za_mill_en.js +0 -1
@@ -0,0 +1,83 @@
1
+ /**
2
+ * Represents map legend.
3
+ * @constructor
4
+ * @param {Object} params Configuration parameters.
5
+ * @param {String} params.cssClass Additional CSS class to apply to legend element.
6
+ * @param {Boolean} params.vertical If <code>true</code> legend will be rendered as vertical.
7
+ * @param {String} params.title Legend title.
8
+ * @param {Function} params.labelRender Method to convert series values to legend labels.
9
+ */
10
+ jvm.Legend = function(params) {
11
+ this.params = params || {};
12
+ this.map = this.params.map;
13
+ this.series = this.params.series;
14
+ this.body = jvm.$('<div/>');
15
+ this.body.addClass('jvectormap-legend');
16
+ if (this.params.cssClass) {
17
+ this.body.addClass(this.params.cssClass);
18
+ }
19
+
20
+ if (params.vertical) {
21
+ this.map.legendCntVertical.append( this.body );
22
+ } else {
23
+ this.map.legendCntHorizontal.append( this.body );
24
+ }
25
+
26
+ this.render();
27
+ }
28
+
29
+ jvm.Legend.prototype.render = function(){
30
+ var ticks = this.series.scale.getTicks(),
31
+ i,
32
+ inner = jvm.$('<div/>').addClass('jvectormap-legend-inner'),
33
+ tick,
34
+ sample,
35
+ label;
36
+
37
+ this.body.html('');
38
+ if (this.params.title) {
39
+ this.body.append(
40
+ jvm.$('<div/>').addClass('jvectormap-legend-title').html(this.params.title)
41
+ );
42
+ }
43
+ this.body.append(inner);
44
+
45
+ for (i = 0; i < ticks.length; i++) {
46
+ tick = jvm.$('<div/>').addClass('jvectormap-legend-tick');
47
+ sample = jvm.$('<div/>').addClass('jvectormap-legend-tick-sample');
48
+
49
+ switch (this.series.params.attribute) {
50
+ case 'fill':
51
+ if (jvm.isImageUrl(ticks[i].value)) {
52
+ sample.css('background', 'url('+ticks[i].value+')');
53
+ } else {
54
+ sample.css('background', ticks[i].value);
55
+ }
56
+ break;
57
+ case 'stroke':
58
+ sample.css('background', ticks[i].value);
59
+ break;
60
+ case 'image':
61
+ sample.css('background', 'url('+ticks[i].value+') no-repeat center center');
62
+ break;
63
+ case 'r':
64
+ jvm.$('<div/>').css({
65
+ 'border-radius': ticks[i].value,
66
+ border: this.map.params.markerStyle.initial['stroke-width']+'px '+
67
+ this.map.params.markerStyle.initial['stroke']+' solid',
68
+ width: ticks[i].value * 2 + 'px',
69
+ height: ticks[i].value * 2 + 'px',
70
+ background: this.map.params.markerStyle.initial['fill']
71
+ }).appendTo(sample);
72
+ break;
73
+ }
74
+ tick.append( sample );
75
+ label = ticks[i].label;
76
+ if (this.params.labelRender) {
77
+ label = this.params.labelRender(label);
78
+ }
79
+ tick.append( jvm.$('<div>'+label+' </div>').addClass('jvectormap-legend-tick-text') );
80
+ inner.append(tick);
81
+ }
82
+ inner.append( jvm.$('<div/>').css('clear', 'both') );
83
+ }
@@ -0,0 +1,73 @@
1
+ jvm.MapObject = function(config){};
2
+
3
+ jvm.MapObject.prototype.getLabelText = function(key){
4
+ var text;
5
+
6
+ if (this.config.label) {
7
+ if (typeof this.config.label.render === 'function') {
8
+ text = this.config.label.render(key);
9
+ } else {
10
+ text = key;
11
+ }
12
+ } else {
13
+ text = null;
14
+ }
15
+ return text;
16
+ }
17
+
18
+ jvm.MapObject.prototype.getLabelOffsets = function(key){
19
+ var offsets;
20
+
21
+ if (this.config.label) {
22
+ if (typeof this.config.label.offsets === 'function') {
23
+ offsets = this.config.label.offsets(key);
24
+ } else if (typeof this.config.label.offsets === 'object') {
25
+ offsets = this.config.label.offsets[key];
26
+ }
27
+ }
28
+ return offsets || [0, 0];
29
+ }
30
+
31
+ /**
32
+ * Set hovered state to the element. Hovered state means mouse cursor is over element. Styles will be updates respectively.
33
+ * @param {Boolean} isHovered <code>true</code> to make element hovered, <code>false</code> otherwise.
34
+ */
35
+ jvm.MapObject.prototype.setHovered = function(isHovered){
36
+ if (this.isHovered !== isHovered) {
37
+ this.isHovered = isHovered;
38
+ this.shape.isHovered = isHovered;
39
+ this.shape.updateStyle();
40
+ if (this.label) {
41
+ this.label.isHovered = isHovered;
42
+ this.label.updateStyle();
43
+ }
44
+ }
45
+ };
46
+
47
+ /**
48
+ * Set selected state to the element. Styles will be updates respectively.
49
+ * @param {Boolean} isSelected <code>true</code> to make element selected, <code>false</code> otherwise.
50
+ */
51
+ jvm.MapObject.prototype.setSelected = function(isSelected){
52
+ if (this.isSelected !== isSelected) {
53
+ this.isSelected = isSelected;
54
+ this.shape.isSelected = isSelected;
55
+ this.shape.updateStyle();
56
+ if (this.label) {
57
+ this.label.isSelected = isSelected;
58
+ this.label.updateStyle();
59
+ }
60
+ jvm.$(this.shape).trigger('selected', [isSelected]);
61
+ }
62
+ };
63
+
64
+ jvm.MapObject.prototype.setStyle = function(){
65
+ this.shape.setStyle.apply(this.shape, arguments);
66
+ };
67
+
68
+ jvm.MapObject.prototype.remove = function(){
69
+ this.shape.remove();
70
+ if (this.label) {
71
+ this.label.remove();
72
+ }
73
+ };
@@ -2,12 +2,15 @@
2
2
  * Creates map, draws paths, binds events.
3
3
  * @constructor
4
4
  * @param {Object} params Parameters to initialize map with.
5
- * @param {String} params.map Name of the map in the format <code>territory_proj_lang</code> where <code>territory</code> is a unique code or name of the territory which the map represents (ISO 3166 alpha 2 standard is used where possible), <code>proj</code> is a name of projection used to generate representation of the map on the plane (projections are named according to the conventions of proj4 utility) and <code>lang</code> is a code of the language, used for the names of regions.
5
+ * @param {String} params.map Name of the map in the format <code>territory_proj_lang</code> where <code>territory</code> is a unique code or name of the territory which the map represents (ISO 3166 standard is used where possible), <code>proj</code> is a name of projection used to generate representation of the map on the plane (projections are named according to the conventions of proj4 utility) and <code>lang</code> is a code of the language, used for the names of regions.
6
6
  * @param {String} params.backgroundColor Background color of the map in CSS format.
7
7
  * @param {Boolean} params.zoomOnScroll When set to true map could be zoomed using mouse scroll. Default value is <code>true</code>.
8
+ * @param {Boolean} params.zoomOnScrollSpeed Mouse scroll speed. Number from 1 to 10. Default value is <code>3</code>.
9
+ * @param {Boolean} params.panOnDrag When set to true, the map pans when being dragged. Default value is <code>true</code>.
8
10
  * @param {Number} params.zoomMax Indicates the maximum zoom ratio which could be reached zooming the map. Default value is <code>8</code>.
9
11
  * @param {Number} params.zoomMin Indicates the minimum zoom ratio which could be reached zooming the map. Default value is <code>1</code>.
10
12
  * @param {Number} params.zoomStep Indicates the multiplier used to zoom map with +/- buttons. Default value is <code>1.6</code>.
13
+ * @param {Boolean} params.zoomAnimate Indicates whether or not to animate changing of map zoom with zoom buttons.
11
14
  * @param {Boolean} params.regionsSelectable When set to true regions of the map could be selected. Default value is <code>false</code>.
12
15
  * @param {Boolean} params.regionsSelectableOne Allow only one region to be selected at the moment. Default value is <code>false</code>.
13
16
  * @param {Boolean} params.markersSelectable When set to true markers on the map could be selected. Default value is <code>false</code>.
@@ -22,13 +25,27 @@
22
25
  "stroke-opacity": 1
23
26
  },
24
27
  hover: {
25
- "fill-opacity": 0.8
28
+ "fill-opacity": 0.8,
29
+ cursor: 'pointer'
26
30
  },
27
31
  selected: {
28
32
  fill: 'yellow'
29
33
  },
30
34
  selectedHover: {
31
35
  }
36
+ }</pre>
37
+ * @param {Object} params.regionLabelStyle Set the styles for the regions' labels. Each region or marker has four states: <code>initial</code> (default state), <code>hover</code> (when the mouse cursor is over the region or marker), <code>selected</code> (when region or marker is selected), <code>selectedHover</code> (when the mouse cursor is over the region or marker and it's selected simultaneously). Styles could be set for each of this states. Default value for that parameter is:
38
+ <pre>{
39
+ initial: {
40
+ 'font-family': 'Verdana',
41
+ 'font-size': '12',
42
+ 'font-weight': 'bold',
43
+ cursor: 'default',
44
+ fill: 'black'
45
+ },
46
+ hover: {
47
+ cursor: 'pointer'
48
+ }
32
49
  }</pre>
33
50
  * @param {Object} params.markerStyle Set the styles for the map's markers. Any parameter suitable for <code>regionStyle</code> could be used as well as numeric parameter <code>r</code> to set the marker's radius. Default value for that parameter is:
34
51
  <pre>{
@@ -42,7 +59,8 @@
42
59
  },
43
60
  hover: {
44
61
  stroke: 'black',
45
- "stroke-width": 2
62
+ "stroke-width": 2,
63
+ cursor: 'pointer'
46
64
  },
47
65
  selected: {
48
66
  fill: 'blue'
@@ -50,51 +68,63 @@
50
68
  selectedHover: {
51
69
  }
52
70
  }</pre>
53
- * @param {Object|Array} params.markers Set of markers to add to the map during initialization. In case of array is provided, codes of markers will be set as string representations of array indexes. Each marker is represented by <code>latLng</code> (array of two numeric values), <code>name</code> (string which will be show on marker's label) and any marker styles.
54
- * @param {Object} params.series Object with two keys: <code>markers</code> and <code>regions</code>. Each of which is an array of series configs to be applied to the respective map elements. See <a href="jvm.DataSeries.html">DataSeries</a> description for a list of parameters available.
55
- * @param {Object|String} params.focusOn This parameter sets the initial position and scale of the map viewport. It could be expressed as a string representing region which should be in focus or an object representing coordinates and scale to set. For example to focus on the center of the map at the double scale you can provide the following value:
71
+ * @param {Object} params.markerLabelStyle Set the styles for the markers' labels. Default value for that parameter is:
56
72
  <pre>{
57
- x: 0.5,
58
- y: 0.5,
59
- scale: 2
73
+ initial: {
74
+ 'font-family': 'Verdana',
75
+ 'font-size': '12',
76
+ 'font-weight': 'bold',
77
+ cursor: 'default',
78
+ fill: 'black'
79
+ },
80
+ hover: {
81
+ cursor: 'pointer'
82
+ }
60
83
  }</pre>
84
+ * @param {Object|Array} params.markers Set of markers to add to the map during initialization. In case of array is provided, codes of markers will be set as string representations of array indexes. Each marker is represented by <code>latLng</code> (array of two numeric values), <code>name</code> (string which will be show on marker's tip) and any marker styles.
85
+ * @param {Object} params.series Object with two keys: <code>markers</code> and <code>regions</code>. Each of which is an array of series configs to be applied to the respective map elements. See <a href="jvm.DataSeries.html">DataSeries</a> description for a list of parameters available.
86
+ * @param {Object|String} params.focusOn This parameter sets the initial position and scale of the map viewport. See <code>setFocus</code> docuemntation for possible parameters.
87
+ * @param {Object} params.labels Defines parameters for rendering static labels. Object could contain two keys: <code>regions</code> and <code>markers</code>. Each key value defines configuration object with the following possible options:
88
+ <ul>
89
+ <li><code>render {Function}</code> - defines method for converting region code or marker index to actual label value.</li>
90
+ <li><code>offsets {Object|Function}</code> - provides method or object which could be used to define label offset by region code or marker index.</li>
91
+ </ul>
92
+ <b>Plase note: static labels feature is not supported in Internet Explorer 8 and below.</b>
61
93
  * @param {Array|Object|String} params.selectedRegions Set initially selected regions.
62
94
  * @param {Array|Object|String} params.selectedMarkers Set initially selected markers.
63
- * @param {Function} params.onRegionLabelShow <code>(Event e, Object label, String code)</code> Will be called right before the region label is going to be shown.
95
+ * @param {Function} params.onRegionTipShow <code>(Event e, Object tip, String code)</code> Will be called right before the region tip is going to be shown.
64
96
  * @param {Function} params.onRegionOver <code>(Event e, String code)</code> Will be called on region mouse over event.
65
97
  * @param {Function} params.onRegionOut <code>(Event e, String code)</code> Will be called on region mouse out event.
66
98
  * @param {Function} params.onRegionClick <code>(Event e, String code)</code> Will be called on region click event.
67
99
  * @param {Function} params.onRegionSelected <code>(Event e, String code, Boolean isSelected, Array selectedRegions)</code> Will be called when region is (de)selected. <code>isSelected</code> parameter of the callback indicates whether region is selected or not. <code>selectedRegions</code> contains codes of all currently selected regions.
68
- * @param {Function} params.onMarkerLabelShow <code>(Event e, Object label, String code)</code> Will be called right before the marker label is going to be shown.
100
+ * @param {Function} params.onMarkerTipShow <code>(Event e, Object tip, String code)</code> Will be called right before the marker tip is going to be shown.
69
101
  * @param {Function} params.onMarkerOver <code>(Event e, String code)</code> Will be called on marker mouse over event.
70
102
  * @param {Function} params.onMarkerOut <code>(Event e, String code)</code> Will be called on marker mouse out event.
71
103
  * @param {Function} params.onMarkerClick <code>(Event e, String code)</code> Will be called on marker click event.
72
104
  * @param {Function} params.onMarkerSelected <code>(Event e, String code, Boolean isSelected, Array selectedMarkers)</code> Will be called when marker is (de)selected. <code>isSelected</code> parameter of the callback indicates whether marker is selected or not. <code>selectedMarkers</code> contains codes of all currently selected markers.
73
105
  * @param {Function} params.onViewportChange <code>(Event e, Number scale)</code> Triggered when the map's viewport is changed (map was panned or zoomed).
74
106
  */
75
- jvm.WorldMap = function(params) {
107
+ jvm.Map = function(params) {
76
108
  var map = this,
77
109
  e;
78
110
 
79
- this.params = jvm.$.extend(true, {}, jvm.WorldMap.defaultParams, params);
111
+ this.params = jvm.$.extend(true, {}, jvm.Map.defaultParams, params);
80
112
 
81
- if (!jvm.WorldMap.maps[this.params.map]) {
113
+ if (!jvm.Map.maps[this.params.map]) {
82
114
  throw new Error('Attempt to use map which was not loaded: '+this.params.map);
83
115
  }
84
116
 
85
- this.mapData = jvm.WorldMap.maps[this.params.map];
117
+ this.mapData = jvm.Map.maps[this.params.map];
86
118
  this.markers = {};
87
119
  this.regions = {};
88
120
  this.regionsColors = {};
89
121
  this.regionsData = {};
90
122
 
91
- this.container = jvm.$('<div>').css({width: '100%', height: '100%'}).addClass('jvectormap-container');
92
- this.params.container.append( this.container );
123
+ this.container = jvm.$('<div>').addClass('jvectormap-container');
124
+ if (this.params.container) {
125
+ this.params.container.append( this.container );
126
+ }
93
127
  this.container.data('mapObject', this);
94
- this.container.css({
95
- position: 'relative',
96
- overflow: 'hidden'
97
- });
98
128
 
99
129
  this.defaultWidth = this.mapData.width;
100
130
  this.defaultHeight = this.mapData.height;
@@ -102,41 +132,44 @@ jvm.WorldMap = function(params) {
102
132
  this.setBackgroundColor(this.params.backgroundColor);
103
133
 
104
134
  this.onResize = function(){
105
- map.setSize();
135
+ map.updateSize();
106
136
  }
107
137
  jvm.$(window).resize(this.onResize);
108
138
 
109
- for (e in jvm.WorldMap.apiEvents) {
139
+ for (e in jvm.Map.apiEvents) {
110
140
  if (this.params[e]) {
111
- this.container.bind(jvm.WorldMap.apiEvents[e]+'.jvectormap', this.params[e]);
141
+ this.container.bind(jvm.Map.apiEvents[e]+'.jvectormap', this.params[e]);
112
142
  }
113
143
  }
114
144
 
115
145
  this.canvas = new jvm.VectorCanvas(this.container[0], this.width, this.height);
116
146
 
117
- if ( ('ontouchstart' in window) || (window.DocumentTouch && document instanceof DocumentTouch) ) {
118
- if (this.params.bindTouchEvents) {
147
+ if (this.params.bindTouchEvents) {
148
+ if (('ontouchstart' in window) || (window.DocumentTouch && document instanceof DocumentTouch)) {
119
149
  this.bindContainerTouchEvents();
150
+ } else if (window.MSGesture) {
151
+ this.bindContainerPointerEvents();
120
152
  }
121
- } else {
122
- this.bindContainerEvents();
123
153
  }
154
+ this.bindContainerEvents();
124
155
  this.bindElementEvents();
125
- this.createLabel();
156
+ this.createTip();
126
157
  if (this.params.zoomButtons) {
127
158
  this.bindZoomButtons();
128
159
  }
160
+
129
161
  this.createRegions();
130
162
  this.createMarkers(this.params.markers || {});
131
163
 
132
- this.setSize();
164
+ this.updateSize();
133
165
 
134
166
  if (this.params.focusOn) {
135
- if (typeof this.params.focusOn === 'object') {
136
- this.setFocus.call(this, this.params.focusOn.scale, this.params.focusOn.x, this.params.focusOn.y);
137
- } else {
138
- this.setFocus.call(this, this.params.focusOn);
167
+ if (typeof this.params.focusOn === 'string') {
168
+ this.params.focusOn = {region: this.params.focusOn};
169
+ } else if (jvm.$.isArray(this.params.focusOn)) {
170
+ this.params.focusOn = {regions: this.params.focusOn};
139
171
  }
172
+ this.setFocus(this.params.focusOn);
140
173
  }
141
174
 
142
175
  if (this.params.selectedRegions) {
@@ -146,12 +179,17 @@ jvm.WorldMap = function(params) {
146
179
  this.setSelectedMarkers(this.params.selectedMarkers);
147
180
  }
148
181
 
182
+ this.legendCntHorizontal = jvm.$('<div/>').addClass('jvectormap-legend-cnt jvectormap-legend-cnt-h');
183
+ this.legendCntVertical = jvm.$('<div/>').addClass('jvectormap-legend-cnt jvectormap-legend-cnt-v');
184
+ this.container.append(this.legendCntHorizontal);
185
+ this.container.append(this.legendCntVertical);
186
+
149
187
  if (this.params.series) {
150
188
  this.createSeries();
151
189
  }
152
190
  };
153
191
 
154
- jvm.WorldMap.prototype = {
192
+ jvm.Map.prototype = {
155
193
  transX: 0,
156
194
  transY: 0,
157
195
  scale: 1,
@@ -187,7 +225,7 @@ jvm.WorldMap.prototype = {
187
225
  /**
188
226
  * Synchronize the size of the map with the size of the container. Suitable in situations where the size of the container is changed programmatically or container is shown after it became visible.
189
227
  */
190
- setSize: function(){
228
+ updateSize: function(){
191
229
  this.width = this.container.width();
192
230
  this.height = this.container.height();
193
231
  this.resize();
@@ -252,6 +290,8 @@ jvm.WorldMap.prototype = {
252
290
  this.repositionMarkers();
253
291
  }
254
292
 
293
+ this.repositionLabels();
294
+
255
295
  this.container.trigger('viewportChange', [this.scale/this.baseScale, this.transX, this.transY]);
256
296
  },
257
297
 
@@ -261,36 +301,39 @@ jvm.WorldMap.prototype = {
261
301
  oldPageY,
262
302
  map = this;
263
303
 
264
- this.container.mousemove(function(e){
265
- if (mouseDown) {
266
- map.transX -= (oldPageX - e.pageX) / map.scale;
267
- map.transY -= (oldPageY - e.pageY) / map.scale;
304
+ if (this.params.panOnDrag) {
305
+ this.container.mousemove(function(e){
306
+ if (mouseDown) {
307
+ map.transX -= (oldPageX - e.pageX) / map.scale;
308
+ map.transY -= (oldPageY - e.pageY) / map.scale;
268
309
 
269
- map.applyTransform();
310
+ map.applyTransform();
270
311
 
312
+ oldPageX = e.pageX;
313
+ oldPageY = e.pageY;
314
+ }
315
+ return false;
316
+ }).mousedown(function(e){
317
+ mouseDown = true;
271
318
  oldPageX = e.pageX;
272
319
  oldPageY = e.pageY;
273
- }
274
- return false;
275
- }).mousedown(function(e){
276
- mouseDown = true;
277
- oldPageX = e.pageX;
278
- oldPageY = e.pageY;
279
- return false;
280
- });
320
+ return false;
321
+ });
281
322
 
282
- jvm.$('body').mouseup(function(){
283
- mouseDown = false;
284
- });
323
+ this.onContainerMouseUp = function(){
324
+ mouseDown = false;
325
+ };
326
+ jvm.$('body').mouseup(this.onContainerMouseUp);
327
+ }
285
328
 
286
329
  if (this.params.zoomOnScroll) {
287
330
  this.container.mousewheel(function(event, delta, deltaX, deltaY) {
288
331
  var offset = jvm.$(map.container).offset(),
289
332
  centerX = event.pageX - offset.left,
290
333
  centerY = event.pageY - offset.top,
291
- zoomStep = Math.pow(1.3, deltaY);
334
+ zoomStep = Math.pow(1 + map.params.zoomOnScrollSpeed / 1000, event.deltaFactor * event.deltaY);
292
335
 
293
- map.label.hide();
336
+ map.tip.hide();
294
337
 
295
338
  map.setScale(map.scale * zoomStep, centerX, centerY);
296
339
  event.preventDefault();
@@ -309,7 +352,10 @@ jvm.WorldMap.prototype = {
309
352
  lastTouchesLength,
310
353
  handleTouchEvent = function(e){
311
354
  var touches = e.originalEvent.touches,
312
- scale;
355
+ offset,
356
+ scale,
357
+ transXOld,
358
+ transYOld;
313
359
 
314
360
  if (e.type == 'touchstart') {
315
361
  lastTouchesLength = 0;
@@ -317,11 +363,15 @@ jvm.WorldMap.prototype = {
317
363
 
318
364
  if (touches.length == 1) {
319
365
  if (lastTouchesLength == 1) {
366
+ transXOld = map.transX;
367
+ transYOld = map.transY;
320
368
  map.transX -= (touchX - touches[0].pageX) / map.scale;
321
369
  map.transY -= (touchY - touches[0].pageY) / map.scale;
322
370
  map.applyTransform();
323
- map.label.hide();
324
- e.preventDefault();
371
+ map.tip.hide();
372
+ if (transXOld != map.transX || transYOld != map.transY) {
373
+ e.preventDefault();
374
+ }
325
375
  }
326
376
  touchX = touches[0].pageX;
327
377
  touchY = touches[0].pageY;
@@ -336,9 +386,10 @@ jvm.WorldMap.prototype = {
336
386
  centerTouchX,
337
387
  centerTouchY
338
388
  )
339
- map.label.hide();
389
+ map.tip.hide();
340
390
  e.preventDefault();
341
391
  } else {
392
+ offset = jvm.$(map.container).offset();
342
393
  if (touches[0].pageX > touches[1].pageX) {
343
394
  centerTouchX = touches[1].pageX + (touches[0].pageX - touches[1].pageX) / 2;
344
395
  } else {
@@ -349,6 +400,8 @@ jvm.WorldMap.prototype = {
349
400
  } else {
350
401
  centerTouchY = touches[0].pageY + (touches[1].pageY - touches[0].pageY) / 2;
351
402
  }
403
+ centerTouchX -= offset.left;
404
+ centerTouchY -= offset.top;
352
405
  touchStartScale = map.scale;
353
406
  touchStartDistance = Math.sqrt(
354
407
  Math.pow(touches[0].pageX - touches[1].pageX, 2) +
@@ -364,24 +417,67 @@ jvm.WorldMap.prototype = {
364
417
  jvm.$(this.container).bind('touchmove', handleTouchEvent);
365
418
  },
366
419
 
420
+ bindContainerPointerEvents: function(){
421
+ var map = this,
422
+ gesture = new MSGesture(),
423
+ element = this.container[0],
424
+ handlePointerDownEvent = function(e){
425
+ gesture.addPointer(e.pointerId);
426
+ },
427
+ handleGestureEvent = function(e){
428
+ var offset,
429
+ scale,
430
+ transXOld,
431
+ transYOld;
432
+
433
+ if (e.translationX != 0 || e.translationY != 0) {
434
+ transXOld = map.transX;
435
+ transYOld = map.transY;
436
+ map.transX += e.translationX / map.scale;
437
+ map.transY += e.translationY / map.scale;
438
+ map.applyTransform();
439
+ map.tip.hide();
440
+ if (transXOld != map.transX || transYOld != map.transY) {
441
+ e.preventDefault();
442
+ }
443
+ }
444
+ if (e.scale != 1) {
445
+ map.setScale(
446
+ map.scale * e.scale,
447
+ e.offsetX,
448
+ e.offsetY
449
+ )
450
+ map.tip.hide();
451
+ e.preventDefault();
452
+ }
453
+ };
454
+
455
+ gesture.target = element;
456
+ element.addEventListener("MSGestureChange", handleGestureEvent, false);
457
+ element.addEventListener("pointerdown", handlePointerDownEvent, false);
458
+ },
459
+
367
460
  bindElementEvents: function(){
368
461
  var map = this,
462
+ pageX,
463
+ pageY,
369
464
  mouseMoved;
370
465
 
371
- this.container.mousemove(function(){
372
- mouseMoved = true;
466
+ this.container.mousemove(function(e){
467
+ if (Math.abs(pageX - e.pageX) + Math.abs(pageY - e.pageY) > 2) {
468
+ mouseMoved = true;
469
+ }
373
470
  });
374
471
 
375
472
  /* Can not use common class selectors here because of the bug in jQuery
376
473
  SVG handling, use with caution. */
377
474
  this.container.delegate("[class~='jvectormap-element']", 'mouseover mouseout', function(e){
378
- var path = this,
379
- baseVal = jvm.$(this).attr('class').baseVal ? jvm.$(this).attr('class').baseVal : jvm.$(this).attr('class'),
475
+ var baseVal = jvm.$(this).attr('class').baseVal || jvm.$(this).attr('class'),
380
476
  type = baseVal.indexOf('jvectormap-region') === -1 ? 'marker' : 'region',
381
477
  code = type == 'region' ? jvm.$(this).attr('data-code') : jvm.$(this).attr('data-index'),
382
478
  element = type == 'region' ? map.regions[code].element : map.markers[code].element,
383
- labelText = type == 'region' ? map.mapData.paths[code].name : (map.markers[code].config.name || ''),
384
- labelShowEvent = jvm.$.Event(type+'LabelShow.jvectormap'),
479
+ tipText = type == 'region' ? map.mapData.paths[code].name : (map.markers[code].config.name || ''),
480
+ tipShowEvent = jvm.$.Event(type+'TipShow.jvectormap'),
385
481
  overEvent = jvm.$.Event(type+'Over.jvectormap');
386
482
 
387
483
  if (e.type == 'mouseover') {
@@ -390,16 +486,16 @@ jvm.WorldMap.prototype = {
390
486
  element.setHovered(true);
391
487
  }
392
488
 
393
- map.label.text(labelText);
394
- map.container.trigger(labelShowEvent, [map.label, code]);
395
- if (!labelShowEvent.isDefaultPrevented()) {
396
- map.label.show();
397
- map.labelWidth = map.label.width();
398
- map.labelHeight = map.label.height();
489
+ map.tip.text(tipText);
490
+ map.container.trigger(tipShowEvent, [map.tip, code]);
491
+ if (!tipShowEvent.isDefaultPrevented()) {
492
+ map.tip.show();
493
+ map.tipWidth = map.tip.width();
494
+ map.tipHeight = map.tip.height();
399
495
  }
400
496
  } else {
401
497
  element.setHovered(false);
402
- map.label.hide();
498
+ map.tip.hide();
403
499
  map.container.trigger(type+'Out.jvectormap', [code]);
404
500
  }
405
501
  });
@@ -407,14 +503,15 @@ jvm.WorldMap.prototype = {
407
503
  /* Can not use common class selectors here because of the bug in jQuery
408
504
  SVG handling, use with caution. */
409
505
  this.container.delegate("[class~='jvectormap-element']", 'mousedown', function(e){
506
+ pageX = e.pageX;
507
+ pageY = e.pageY;
410
508
  mouseMoved = false;
411
509
  });
412
510
 
413
511
  /* Can not use common class selectors here because of the bug in jQuery
414
512
  SVG handling, use with caution. */
415
- this.container.delegate("[class~='jvectormap-element']", 'mouseup', function(e){
416
- var path = this,
417
- baseVal = jvm.$(this).attr('class').baseVal ? jvm.$(this).attr('class').baseVal : jvm.$(this).attr('class'),
513
+ this.container.delegate("[class~='jvectormap-element']", 'mouseup', function(){
514
+ var baseVal = jvm.$(this).attr('class').baseVal ? jvm.$(this).attr('class').baseVal : jvm.$(this).attr('class'),
418
515
  type = baseVal.indexOf('jvectormap-region') === -1 ? 'marker' : 'region',
419
516
  code = type == 'region' ? jvm.$(this).attr('data-code') : jvm.$(this).attr('data-index'),
420
517
  clickEvent = jvm.$.Event(type+'Click.jvectormap'),
@@ -441,21 +538,21 @@ jvm.WorldMap.prototype = {
441
538
  jvm.$('<div/>').addClass('jvectormap-zoomout').html('&#x2212;').appendTo(this.container);
442
539
 
443
540
  this.container.find('.jvectormap-zoomin').click(function(){
444
- map.setScale(map.scale * map.params.zoomStep, map.width / 2, map.height / 2);
541
+ map.setScale(map.scale * map.params.zoomStep, map.width / 2, map.height / 2, false, map.params.zoomAnimate);
445
542
  });
446
543
  this.container.find('.jvectormap-zoomout').click(function(){
447
- map.setScale(map.scale / map.params.zoomStep, map.width / 2, map.height / 2);
544
+ map.setScale(map.scale / map.params.zoomStep, map.width / 2, map.height / 2, false, map.params.zoomAnimate);
448
545
  });
449
546
  },
450
547
 
451
- createLabel: function(){
548
+ createTip: function(){
452
549
  var map = this;
453
550
 
454
- this.label = jvm.$('<div/>').addClass('jvectormap-label').appendTo(jvm.$('body'));
551
+ this.tip = jvm.$('<div/>').addClass('jvectormap-tip').appendTo(jvm.$('body'));
455
552
 
456
553
  this.container.mousemove(function(e){
457
- var left = e.pageX-15-map.labelWidth,
458
- top = e.pageY-15-map.labelHeight;
554
+ var left = e.pageX-15-map.tipWidth,
555
+ top = e.pageY-15-map.tipHeight;
459
556
 
460
557
  if (left < 5) {
461
558
  left = e.pageX + 15;
@@ -464,18 +561,28 @@ jvm.WorldMap.prototype = {
464
561
  top = e.pageY + 15;
465
562
  }
466
563
 
467
- if (map.label.is(':visible')) {
468
- map.label.css({
469
- left: left,
470
- top: top
471
- })
472
- }
564
+ map.tip.css({
565
+ left: left,
566
+ top: top
567
+ });
473
568
  });
474
569
  },
475
570
 
476
- setScale: function(scale, anchorX, anchorY, isCentered) {
477
- var zoomStep,
478
- viewportChangeEvent = jvm.$.Event('zoom.jvectormap');
571
+ setScale: function(scale, anchorX, anchorY, isCentered, animate) {
572
+ var viewportChangeEvent = jvm.$.Event('zoom.jvectormap'),
573
+ interval,
574
+ that = this,
575
+ i = 0,
576
+ count = Math.abs(Math.round((scale - this.scale) * 60 / Math.max(scale, this.scale))),
577
+ scaleStart,
578
+ scaleDiff,
579
+ transXStart,
580
+ transXDiff,
581
+ transYStart,
582
+ transYDiff,
583
+ transX,
584
+ transY,
585
+ deferred = new jvm.$.Deferred();
479
586
 
480
587
  if (scale > this.params.zoomMax * this.baseScale) {
481
588
  scale = this.params.zoomMax * this.baseScale;
@@ -486,41 +593,77 @@ jvm.WorldMap.prototype = {
486
593
  if (typeof anchorX != 'undefined' && typeof anchorY != 'undefined') {
487
594
  zoomStep = scale / this.scale;
488
595
  if (isCentered) {
489
- this.transX = anchorX + this.defaultWidth * (this.width / (this.defaultWidth * scale)) / 2;
490
- this.transY = anchorY + this.defaultHeight * (this.height / (this.defaultHeight * scale)) / 2;
596
+ transX = anchorX + this.defaultWidth * (this.width / (this.defaultWidth * scale)) / 2;
597
+ transY = anchorY + this.defaultHeight * (this.height / (this.defaultHeight * scale)) / 2;
491
598
  } else {
492
- this.transX -= (zoomStep - 1) / scale * anchorX;
493
- this.transY -= (zoomStep - 1) / scale * anchorY;
599
+ transX = this.transX - (zoomStep - 1) / scale * anchorX;
600
+ transY = this.transY - (zoomStep - 1) / scale * anchorY;
494
601
  }
495
602
  }
496
603
 
497
- this.scale = scale;
498
- this.applyTransform();
499
- this.container.trigger(viewportChangeEvent, [scale/this.baseScale]);
604
+ if (animate && count > 0) {
605
+ scaleStart = this.scale;
606
+ scaleDiff = (scale - scaleStart) / count;
607
+ transXStart = this.transX * this.scale;
608
+ transYStart = this.transY * this.scale;
609
+ transXDiff = (transX * scale - transXStart) / count;
610
+ transYDiff = (transY * scale - transYStart) / count;
611
+ interval = setInterval(function(){
612
+ i += 1;
613
+ that.scale = scaleStart + scaleDiff * i;
614
+ that.transX = (transXStart + transXDiff * i) / that.scale;
615
+ that.transY = (transYStart + transYDiff * i) / that.scale;
616
+ that.applyTransform();
617
+ if (i == count) {
618
+ clearInterval(interval);
619
+ that.container.trigger(viewportChangeEvent, [scale/that.baseScale]);
620
+ deferred.resolve();
621
+ }
622
+ }, 10);
623
+ } else {
624
+ this.transX = transX;
625
+ this.transY = transY;
626
+ this.scale = scale;
627
+ this.applyTransform();
628
+ this.container.trigger(viewportChangeEvent, [scale/this.baseScale]);
629
+ deferred.resolve();
630
+ }
631
+
632
+ return deferred;
500
633
  },
501
634
 
502
635
  /**
503
636
  * Set the map's viewport to the specific point and set zoom of the map to the specific level. Point and zoom level could be defined in two ways: using the code of some region to focus on or a central point and zoom level as numbers.
504
- * @param {Number|String|Array} scale|regionCode|regionCodes If the first parameter of this method is a string or array of strings and there are regions with the these codes, the viewport will be set to show all these regions. Otherwise if the first parameter is a number, the viewport will be set to show the map with provided scale.
505
- * @param {Number} centerX Number from 0 to 1 specifying the horizontal coordinate of the central point of the viewport.
506
- * @param {Number} centerY Number from 0 to 1 specifying the vertical coordinate of the central point of the viewport.
637
+ * @param This method takes a configuration object as the single argument. The options passed to it are the following:
638
+ * @param {Array} params.regions Array of region codes to zoom to.
639
+ * @param {String} params.region Region code to zoom to.
640
+ * @param {Number} params.scale Map scale to set.
641
+ * @param {Number} params.lat Latitude to set viewport to.
642
+ * @param {Number} params.lng Longitude to set viewport to.
643
+ * @param {Number} params.x Number from 0 to 1 specifying the horizontal coordinate of the central point of the viewport.
644
+ * @param {Number} params.y Number from 0 to 1 specifying the vertical coordinate of the central point of the viewport.
645
+ * @param {Boolean} params.animate Indicates whether or not to animate the scale change and transition.
507
646
  */
508
- setFocus: function(scale, centerX, centerY){
647
+ setFocus: function(config){
509
648
  var bbox,
510
649
  itemBbox,
511
650
  newBbox,
512
651
  codes,
513
- i;
652
+ i,
653
+ point;
514
654
 
515
- if (jvm.$.isArray(scale) || this.regions[scale]) {
516
- if (jvm.$.isArray(scale)) {
517
- codes = scale;
518
- } else {
519
- codes = [scale]
520
- }
655
+ config = config || {};
656
+
657
+ if (config.region) {
658
+ codes = [config.region];
659
+ } else if (config.regions) {
660
+ codes = config.regions;
661
+ }
662
+
663
+ if (codes) {
521
664
  for (i = 0; i < codes.length; i++) {
522
665
  if (this.regions[codes[i]]) {
523
- itemBbox = this.regions[codes[i]].element.getBBox();
666
+ itemBbox = this.regions[codes[i]].element.shape.getBBox();
524
667
  if (itemBbox) {
525
668
  if (typeof bbox == 'undefined') {
526
669
  bbox = itemBbox;
@@ -536,15 +679,23 @@ jvm.WorldMap.prototype = {
536
679
  }
537
680
  }
538
681
  }
539
- this.setScale(
682
+ return this.setScale(
540
683
  Math.min(this.width / bbox.width, this.height / bbox.height),
541
684
  - (bbox.x + bbox.width / 2),
542
685
  - (bbox.y + bbox.height / 2),
543
- true
686
+ true,
687
+ config.animate
544
688
  );
545
689
  } else {
546
- scale = scale * this.baseScale;
547
- this.setScale(scale, - centerX * this.defaultWidth, - centerY * this.defaultHeight, true);
690
+ if (config.lat && config.lng) {
691
+ point = this.latLngToPoint(config.lat, config.lng);
692
+ config.x = this.transX - point.x / this.scale;
693
+ config.y = this.transY - point.y / this.scale;
694
+ } else if (config.x && config.y) {
695
+ config.x *= -this.defaultWidth;
696
+ config.y *= -this.defaultHeight;
697
+ }
698
+ return this.setScale(config.scale * this.baseScale, config.x, config.y, true, config.animate);
548
699
  }
549
700
  },
550
701
 
@@ -637,8 +788,8 @@ jvm.WorldMap.prototype = {
637
788
  },
638
789
 
639
790
  /**
640
- * Return the instance of WorldMap. Useful when instantiated as a jQuery plug-in.
641
- * @returns {WorldMap}
791
+ * Return the instance of Map. Useful when instantiated as a jQuery plug-in.
792
+ * @returns {Map}
642
793
  */
643
794
  getMapObject: function(){
644
795
  return this;
@@ -657,15 +808,23 @@ jvm.WorldMap.prototype = {
657
808
  region,
658
809
  map = this;
659
810
 
811
+ this.regionLabelsGroup = this.regionLabelsGroup || this.canvas.addGroup();
812
+
660
813
  for (key in this.mapData.paths) {
661
- region = this.canvas.addPath({
662
- d: this.mapData.paths[key].path,
663
- "data-code": key
664
- }, jvm.$.extend(true, {}, this.params.regionStyle));
665
- jvm.$(region.node).bind('selected', function(e, isSelected){
666
- map.container.trigger('regionSelected.jvectormap', [jvm.$(this).attr('data-code'), isSelected, map.getSelectedRegions()]);
814
+ region = new jvm.Region({
815
+ map: this,
816
+ path: this.mapData.paths[key].path,
817
+ code: key,
818
+ style: jvm.$.extend(true, {}, this.params.regionStyle),
819
+ labelStyle: jvm.$.extend(true, {}, this.params.regionLabelStyle),
820
+ canvas: this.canvas,
821
+ labelsGroup: this.regionLabelsGroup,
822
+ label: this.canvas.mode != 'vml' ? (this.params.labels && this.params.labels.regions) : null
823
+ });
824
+
825
+ jvm.$(region.shape).bind('selected', function(e, isSelected){
826
+ map.container.trigger('regionSelected.jvectormap', [jvm.$(this.node).attr('data-code'), isSelected, map.getSelectedRegions()]);
667
827
  });
668
- region.addClass('jvectormap-region jvectormap-element');
669
828
  this.regions[key] = {
670
829
  element: region,
671
830
  config: this.mapData.paths[key]
@@ -682,6 +841,7 @@ jvm.WorldMap.prototype = {
682
841
  map = this;
683
842
 
684
843
  this.markersGroup = this.markersGroup || this.canvas.addGroup();
844
+ this.markerLabelsGroup = this.markerLabelsGroup || this.canvas.addGroup();
685
845
 
686
846
  if (jvm.$.isArray(markers)) {
687
847
  markersArray = markers.slice();
@@ -696,14 +856,21 @@ jvm.WorldMap.prototype = {
696
856
  point = this.getMarkerPosition( markerConfig );
697
857
 
698
858
  if (point !== false) {
699
- marker = this.canvas.addCircle({
700
- "data-index": i,
859
+ marker = new jvm.Marker({
860
+ map: this,
861
+ style: jvm.$.extend(true, {}, this.params.markerStyle, {initial: markerConfig.style || {}}),
862
+ labelStyle: jvm.$.extend(true, {}, this.params.markerLabelStyle),
863
+ index: i,
701
864
  cx: point.x,
702
- cy: point.y
703
- }, jvm.$.extend(true, {}, this.params.markerStyle, {initial: markerConfig.style || {}}), this.markersGroup);
704
- marker.addClass('jvectormap-marker jvectormap-element');
705
- jvm.$(marker.node).bind('selected', function(e, isSelected){
706
- map.container.trigger('markerSelected.jvectormap', [jvm.$(this).attr('data-index'), isSelected, map.getSelectedMarkers()]);
865
+ cy: point.y,
866
+ group: this.markersGroup,
867
+ canvas: this.canvas,
868
+ labelsGroup: this.markerLabelsGroup,
869
+ label: this.canvas.mode != 'vml' ? (this.params.labels && this.params.labels.markers) : null
870
+ });
871
+
872
+ jvm.$(marker.shape).bind('selected', function(e, isSelected){
873
+ map.container.trigger('markerSelected.jvectormap', [jvm.$(this.node).attr('data-index'), isSelected, map.getSelectedMarkers()]);
707
874
  });
708
875
  if (this.markers[i]) {
709
876
  this.removeMarkers([i]);
@@ -725,8 +892,20 @@ jvm.WorldMap.prototype = {
725
892
  }
726
893
  },
727
894
 
895
+ repositionLabels: function() {
896
+ var key;
897
+
898
+ for (key in this.regions) {
899
+ this.regions[key].element.updateLabelPosition();
900
+ }
901
+
902
+ for (key in this.markers) {
903
+ this.markers[key].element.updateLabelPosition();
904
+ }
905
+ },
906
+
728
907
  getMarkerPosition: function(markerConfig) {
729
- if (jvm.WorldMap.maps[this.params.map].projection) {
908
+ if (jvm.Map.maps[this.params.map].projection) {
730
909
  return this.latLngToPoint.apply(this, markerConfig.latLng || [0, 0]);
731
910
  } else {
732
911
  return {
@@ -753,7 +932,9 @@ jvm.WorldMap.prototype = {
753
932
 
754
933
  for (i = 0; i < seriesData.length; i++) {
755
934
  values = {};
756
- values[key] = seriesData[i];
935
+ if (typeof seriesData[i] !== 'undefined') {
936
+ values[key] = seriesData[i];
937
+ }
757
938
  data.push(values);
758
939
  }
759
940
  this.addMarkers(markers, data);
@@ -808,13 +989,10 @@ jvm.WorldMap.prototype = {
808
989
  */
809
990
  latLngToPoint: function(lat, lng) {
810
991
  var point,
811
- proj = jvm.WorldMap.maps[this.params.map].projection,
992
+ proj = jvm.Map.maps[this.params.map].projection,
812
993
  centralMeridian = proj.centralMeridian,
813
- width = this.width - this.baseTransX * 2 * this.baseScale,
814
- height = this.height - this.baseTransY * 2 * this.baseScale,
815
994
  inset,
816
- bbox,
817
- scaleFactor = this.scale / this.baseScale;
995
+ bbox;
818
996
 
819
997
  if (lng < (-180 + centralMeridian)) {
820
998
  lng += 360;
@@ -844,9 +1022,9 @@ jvm.WorldMap.prototype = {
844
1022
  * @param {Number} y Y-axis of point on map in pixels.
845
1023
  */
846
1024
  pointToLatLng: function(x, y) {
847
- var proj = jvm.WorldMap.maps[this.params.map].projection,
1025
+ var proj = jvm.Map.maps[this.params.map].projection,
848
1026
  centralMeridian = proj.centralMeridian,
849
- insets = jvm.WorldMap.maps[this.params.map].insets,
1027
+ insets = jvm.Map.maps[this.params.map].insets,
850
1028
  i,
851
1029
  inset,
852
1030
  bbox,
@@ -872,7 +1050,7 @@ jvm.WorldMap.prototype = {
872
1050
  },
873
1051
 
874
1052
  getInsetForPoint: function(x, y){
875
- var insets = jvm.WorldMap.maps[this.params.map].insets,
1053
+ var insets = jvm.Map.maps[this.params.map].insets,
876
1054
  i,
877
1055
  bbox;
878
1056
 
@@ -897,7 +1075,8 @@ jvm.WorldMap.prototype = {
897
1075
  for (i = 0; i < this.params.series[key].length; i++) {
898
1076
  this.series[key][i] = new jvm.DataSeries(
899
1077
  this.params.series[key][i],
900
- this[key]
1078
+ this[key],
1079
+ this
901
1080
  );
902
1081
  }
903
1082
  }
@@ -907,21 +1086,25 @@ jvm.WorldMap.prototype = {
907
1086
  * Gracefully remove the map and and all its accessories, unbind event handlers.
908
1087
  */
909
1088
  remove: function(){
910
- this.label.remove();
1089
+ this.tip.remove();
911
1090
  this.container.remove();
912
1091
  jvm.$(window).unbind('resize', this.onResize);
1092
+ jvm.$('body').unbind('mouseup', this.onContainerMouseUp);
913
1093
  }
914
1094
  };
915
1095
 
916
- jvm.WorldMap.maps = {};
917
- jvm.WorldMap.defaultParams = {
1096
+ jvm.Map.maps = {};
1097
+ jvm.Map.defaultParams = {
918
1098
  map: 'world_mill_en',
919
1099
  backgroundColor: '#505050',
920
1100
  zoomButtons: true,
921
1101
  zoomOnScroll: true,
1102
+ zoomOnScrollSpeed: 3,
1103
+ panOnDrag: true,
922
1104
  zoomMax: 8,
923
1105
  zoomMin: 1,
924
1106
  zoomStep: 1.6,
1107
+ zoomAnimate: true,
925
1108
  regionsSelectable: false,
926
1109
  markersSelectable: false,
927
1110
  bindTouchEvents: true,
@@ -934,7 +1117,8 @@ jvm.WorldMap.defaultParams = {
934
1117
  "stroke-opacity": 1
935
1118
  },
936
1119
  hover: {
937
- "fill-opacity": 0.8
1120
+ "fill-opacity": 0.8,
1121
+ cursor: 'pointer'
938
1122
  },
939
1123
  selected: {
940
1124
  fill: 'yellow'
@@ -942,6 +1126,18 @@ jvm.WorldMap.defaultParams = {
942
1126
  selectedHover: {
943
1127
  }
944
1128
  },
1129
+ regionLabelStyle: {
1130
+ initial: {
1131
+ 'font-family': 'Verdana',
1132
+ 'font-size': '12',
1133
+ 'font-weight': 'bold',
1134
+ cursor: 'default',
1135
+ fill: 'black'
1136
+ },
1137
+ hover: {
1138
+ cursor: 'pointer'
1139
+ }
1140
+ },
945
1141
  markerStyle: {
946
1142
  initial: {
947
1143
  fill: 'grey',
@@ -953,25 +1149,38 @@ jvm.WorldMap.defaultParams = {
953
1149
  },
954
1150
  hover: {
955
1151
  stroke: 'black',
956
- "stroke-width": 2
1152
+ "stroke-width": 2,
1153
+ cursor: 'pointer'
957
1154
  },
958
1155
  selected: {
959
1156
  fill: 'blue'
960
1157
  },
961
1158
  selectedHover: {
962
1159
  }
1160
+ },
1161
+ markerLabelStyle: {
1162
+ initial: {
1163
+ 'font-family': 'Verdana',
1164
+ 'font-size': '12',
1165
+ 'font-weight': 'bold',
1166
+ cursor: 'default',
1167
+ fill: 'black'
1168
+ },
1169
+ hover: {
1170
+ cursor: 'pointer'
1171
+ }
963
1172
  }
964
1173
  };
965
- jvm.WorldMap.apiEvents = {
966
- onRegionLabelShow: 'regionLabelShow',
1174
+ jvm.Map.apiEvents = {
1175
+ onRegionTipShow: 'regionTipShow',
967
1176
  onRegionOver: 'regionOver',
968
1177
  onRegionOut: 'regionOut',
969
1178
  onRegionClick: 'regionClick',
970
1179
  onRegionSelected: 'regionSelected',
971
- onMarkerLabelShow: 'markerLabelShow',
1180
+ onMarkerTipShow: 'markerTipShow',
972
1181
  onMarkerOver: 'markerOver',
973
1182
  onMarkerOut: 'markerOut',
974
1183
  onMarkerClick: 'markerClick',
975
1184
  onMarkerSelected: 'markerSelected',
976
1185
  onViewportChange: 'viewportChange'
977
- };
1186
+ };