activeadmin_ueditor 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (289) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +56 -0
  3. data/Gemfile +3 -0
  4. data/LICENSE +21 -0
  5. data/LICENSE.txt +20 -0
  6. data/README.md +61 -0
  7. data/Rakefile +3 -0
  8. data/activeadmin_ueditor.gemspec +20 -0
  9. data/app/assets/javascripts/.DS_Store +0 -0
  10. data/app/assets/javascripts/activeadmin/.DS_Store +0 -0
  11. data/app/assets/javascripts/activeadmin/ueditor/.DS_Store +0 -0
  12. data/app/assets/javascripts/activeadmin/ueditor/ueditor.all.js +29568 -0
  13. data/app/assets/javascripts/activeadmin/ueditor/ueditor.all.min.js +18 -0
  14. data/app/assets/javascripts/activeadmin/ueditor/ueditor.config.js +414 -0
  15. data/app/assets/javascripts/activeadmin/ueditor_input.js +14 -0
  16. data/lib/activeadmin/ueditor/engine.rb +11 -0
  17. data/lib/activeadmin/ueditor/version.rb +7 -0
  18. data/lib/activeadmin/ueditor.rb +3 -0
  19. data/lib/activeadmin_ueditor.rb +5 -0
  20. data/lib/formtastic/inputs/ueditor_input.rb +16 -0
  21. data/public/assets/ueditor/dialogs/anchor/anchor.html +40 -0
  22. data/public/assets/ueditor/dialogs/attachment/attachment.css +681 -0
  23. data/public/assets/ueditor/dialogs/attachment/attachment.html +60 -0
  24. data/public/assets/ueditor/dialogs/attachment/attachment.js +754 -0
  25. data/public/assets/ueditor/dialogs/attachment/fileTypeImages/icon_chm.gif +0 -0
  26. data/public/assets/ueditor/dialogs/attachment/fileTypeImages/icon_default.png +0 -0
  27. data/public/assets/ueditor/dialogs/attachment/fileTypeImages/icon_doc.gif +0 -0
  28. data/public/assets/ueditor/dialogs/attachment/fileTypeImages/icon_exe.gif +0 -0
  29. data/public/assets/ueditor/dialogs/attachment/fileTypeImages/icon_jpg.gif +0 -0
  30. data/public/assets/ueditor/dialogs/attachment/fileTypeImages/icon_mp3.gif +0 -0
  31. data/public/assets/ueditor/dialogs/attachment/fileTypeImages/icon_mv.gif +0 -0
  32. data/public/assets/ueditor/dialogs/attachment/fileTypeImages/icon_pdf.gif +0 -0
  33. data/public/assets/ueditor/dialogs/attachment/fileTypeImages/icon_ppt.gif +0 -0
  34. data/public/assets/ueditor/dialogs/attachment/fileTypeImages/icon_psd.gif +0 -0
  35. data/public/assets/ueditor/dialogs/attachment/fileTypeImages/icon_rar.gif +0 -0
  36. data/public/assets/ueditor/dialogs/attachment/fileTypeImages/icon_txt.gif +0 -0
  37. data/public/assets/ueditor/dialogs/attachment/fileTypeImages/icon_xls.gif +0 -0
  38. data/public/assets/ueditor/dialogs/attachment/images/alignicon.gif +0 -0
  39. data/public/assets/ueditor/dialogs/attachment/images/alignicon.png +0 -0
  40. data/public/assets/ueditor/dialogs/attachment/images/bg.png +0 -0
  41. data/public/assets/ueditor/dialogs/attachment/images/file-icons.gif +0 -0
  42. data/public/assets/ueditor/dialogs/attachment/images/file-icons.png +0 -0
  43. data/public/assets/ueditor/dialogs/attachment/images/icons.gif +0 -0
  44. data/public/assets/ueditor/dialogs/attachment/images/icons.png +0 -0
  45. data/public/assets/ueditor/dialogs/attachment/images/image.png +0 -0
  46. data/public/assets/ueditor/dialogs/attachment/images/progress.png +0 -0
  47. data/public/assets/ueditor/dialogs/attachment/images/success.gif +0 -0
  48. data/public/assets/ueditor/dialogs/attachment/images/success.png +0 -0
  49. data/public/assets/ueditor/dialogs/background/background.css +94 -0
  50. data/public/assets/ueditor/dialogs/background/background.html +56 -0
  51. data/public/assets/ueditor/dialogs/background/background.js +376 -0
  52. data/public/assets/ueditor/dialogs/background/images/bg.png +0 -0
  53. data/public/assets/ueditor/dialogs/background/images/success.png +0 -0
  54. data/public/assets/ueditor/dialogs/charts/chart.config.js +65 -0
  55. data/public/assets/ueditor/dialogs/charts/charts.css +165 -0
  56. data/public/assets/ueditor/dialogs/charts/charts.html +89 -0
  57. data/public/assets/ueditor/dialogs/charts/charts.js +519 -0
  58. data/public/assets/ueditor/dialogs/charts/images/charts0.png +0 -0
  59. data/public/assets/ueditor/dialogs/charts/images/charts1.png +0 -0
  60. data/public/assets/ueditor/dialogs/charts/images/charts2.png +0 -0
  61. data/public/assets/ueditor/dialogs/charts/images/charts3.png +0 -0
  62. data/public/assets/ueditor/dialogs/charts/images/charts4.png +0 -0
  63. data/public/assets/ueditor/dialogs/charts/images/charts5.png +0 -0
  64. data/public/assets/ueditor/dialogs/emotion/emotion.css +43 -0
  65. data/public/assets/ueditor/dialogs/emotion/emotion.html +54 -0
  66. data/public/assets/ueditor/dialogs/emotion/emotion.js +186 -0
  67. data/public/assets/ueditor/dialogs/emotion/images/0.gif +0 -0
  68. data/public/assets/ueditor/dialogs/emotion/images/bface.gif +0 -0
  69. data/public/assets/ueditor/dialogs/emotion/images/cface.gif +0 -0
  70. data/public/assets/ueditor/dialogs/emotion/images/fface.gif +0 -0
  71. data/public/assets/ueditor/dialogs/emotion/images/jxface2.gif +0 -0
  72. data/public/assets/ueditor/dialogs/emotion/images/neweditor-tab-bg.png +0 -0
  73. data/public/assets/ueditor/dialogs/emotion/images/tface.gif +0 -0
  74. data/public/assets/ueditor/dialogs/emotion/images/wface.gif +0 -0
  75. data/public/assets/ueditor/dialogs/emotion/images/yface.gif +0 -0
  76. data/public/assets/ueditor/dialogs/gmap/gmap.html +89 -0
  77. data/public/assets/ueditor/dialogs/help/help.css +7 -0
  78. data/public/assets/ueditor/dialogs/help/help.html +82 -0
  79. data/public/assets/ueditor/dialogs/help/help.js +56 -0
  80. data/public/assets/ueditor/dialogs/image/image.css +894 -0
  81. data/public/assets/ueditor/dialogs/image/image.html +120 -0
  82. data/public/assets/ueditor/dialogs/image/image.js +1142 -0
  83. data/public/assets/ueditor/dialogs/image/images/alignicon.jpg +0 -0
  84. data/public/assets/ueditor/dialogs/image/images/bg.png +0 -0
  85. data/public/assets/ueditor/dialogs/image/images/icons.gif +0 -0
  86. data/public/assets/ueditor/dialogs/image/images/icons.png +0 -0
  87. data/public/assets/ueditor/dialogs/image/images/image.png +0 -0
  88. data/public/assets/ueditor/dialogs/image/images/progress.png +0 -0
  89. data/public/assets/ueditor/dialogs/image/images/success.gif +0 -0
  90. data/public/assets/ueditor/dialogs/image/images/success.png +0 -0
  91. data/public/assets/ueditor/dialogs/insertframe/insertframe.html +98 -0
  92. data/public/assets/ueditor/dialogs/internal.js +81 -0
  93. data/public/assets/ueditor/dialogs/link/link.html +126 -0
  94. data/public/assets/ueditor/dialogs/map/map.html +135 -0
  95. data/public/assets/ueditor/dialogs/map/show.html +118 -0
  96. data/public/assets/ueditor/dialogs/music/music.css +30 -0
  97. data/public/assets/ueditor/dialogs/music/music.html +32 -0
  98. data/public/assets/ueditor/dialogs/music/music.js +192 -0
  99. data/public/assets/ueditor/dialogs/preview/preview.html +40 -0
  100. data/public/assets/ueditor/dialogs/scrawl/images/addimg.png +0 -0
  101. data/public/assets/ueditor/dialogs/scrawl/images/brush.png +0 -0
  102. data/public/assets/ueditor/dialogs/scrawl/images/delimg.png +0 -0
  103. data/public/assets/ueditor/dialogs/scrawl/images/delimgH.png +0 -0
  104. data/public/assets/ueditor/dialogs/scrawl/images/empty.png +0 -0
  105. data/public/assets/ueditor/dialogs/scrawl/images/emptyH.png +0 -0
  106. data/public/assets/ueditor/dialogs/scrawl/images/eraser.png +0 -0
  107. data/public/assets/ueditor/dialogs/scrawl/images/redo.png +0 -0
  108. data/public/assets/ueditor/dialogs/scrawl/images/redoH.png +0 -0
  109. data/public/assets/ueditor/dialogs/scrawl/images/scale.png +0 -0
  110. data/public/assets/ueditor/dialogs/scrawl/images/scaleH.png +0 -0
  111. data/public/assets/ueditor/dialogs/scrawl/images/size.png +0 -0
  112. data/public/assets/ueditor/dialogs/scrawl/images/undo.png +0 -0
  113. data/public/assets/ueditor/dialogs/scrawl/images/undoH.png +0 -0
  114. data/public/assets/ueditor/dialogs/scrawl/scrawl.css +72 -0
  115. data/public/assets/ueditor/dialogs/scrawl/scrawl.html +95 -0
  116. data/public/assets/ueditor/dialogs/scrawl/scrawl.js +671 -0
  117. data/public/assets/ueditor/dialogs/searchreplace/searchreplace.html +102 -0
  118. data/public/assets/ueditor/dialogs/searchreplace/searchreplace.js +164 -0
  119. data/public/assets/ueditor/dialogs/snapscreen/snapscreen.html +58 -0
  120. data/public/assets/ueditor/dialogs/spechars/spechars.html +21 -0
  121. data/public/assets/ueditor/dialogs/spechars/spechars.js +57 -0
  122. data/public/assets/ueditor/dialogs/table/dragicon.png +0 -0
  123. data/public/assets/ueditor/dialogs/table/edittable.css +84 -0
  124. data/public/assets/ueditor/dialogs/table/edittable.html +64 -0
  125. data/public/assets/ueditor/dialogs/table/edittable.js +237 -0
  126. data/public/assets/ueditor/dialogs/table/edittd.html +61 -0
  127. data/public/assets/ueditor/dialogs/table/edittip.html +33 -0
  128. data/public/assets/ueditor/dialogs/template/config.js +42 -0
  129. data/public/assets/ueditor/dialogs/template/images/bg.gif +0 -0
  130. data/public/assets/ueditor/dialogs/template/images/pre0.png +0 -0
  131. data/public/assets/ueditor/dialogs/template/images/pre1.png +0 -0
  132. data/public/assets/ueditor/dialogs/template/images/pre2.png +0 -0
  133. data/public/assets/ueditor/dialogs/template/images/pre3.png +0 -0
  134. data/public/assets/ueditor/dialogs/template/images/pre4.png +0 -0
  135. data/public/assets/ueditor/dialogs/template/template.css +18 -0
  136. data/public/assets/ueditor/dialogs/template/template.html +26 -0
  137. data/public/assets/ueditor/dialogs/template/template.js +53 -0
  138. data/public/assets/ueditor/dialogs/video/images/bg.png +0 -0
  139. data/public/assets/ueditor/dialogs/video/images/center_focus.jpg +0 -0
  140. data/public/assets/ueditor/dialogs/video/images/file-icons.gif +0 -0
  141. data/public/assets/ueditor/dialogs/video/images/file-icons.png +0 -0
  142. data/public/assets/ueditor/dialogs/video/images/icons.gif +0 -0
  143. data/public/assets/ueditor/dialogs/video/images/icons.png +0 -0
  144. data/public/assets/ueditor/dialogs/video/images/image.png +0 -0
  145. data/public/assets/ueditor/dialogs/video/images/left_focus.jpg +0 -0
  146. data/public/assets/ueditor/dialogs/video/images/none_focus.jpg +0 -0
  147. data/public/assets/ueditor/dialogs/video/images/progress.png +0 -0
  148. data/public/assets/ueditor/dialogs/video/images/right_focus.jpg +0 -0
  149. data/public/assets/ueditor/dialogs/video/images/success.gif +0 -0
  150. data/public/assets/ueditor/dialogs/video/images/success.png +0 -0
  151. data/public/assets/ueditor/dialogs/video/video.css +635 -0
  152. data/public/assets/ueditor/dialogs/video/video.html +86 -0
  153. data/public/assets/ueditor/dialogs/video/video.js +791 -0
  154. data/public/assets/ueditor/dialogs/webapp/webapp.html +53 -0
  155. data/public/assets/ueditor/dialogs/wordimage/fClipboard_ueditor.swf +0 -0
  156. data/public/assets/ueditor/dialogs/wordimage/imageUploader.swf +0 -0
  157. data/public/assets/ueditor/dialogs/wordimage/tangram.js +1495 -0
  158. data/public/assets/ueditor/dialogs/wordimage/wordimage.html +111 -0
  159. data/public/assets/ueditor/dialogs/wordimage/wordimage.js +157 -0
  160. data/public/assets/ueditor/lang/en/en.js +684 -0
  161. data/public/assets/ueditor/lang/en/images/addimage.png +0 -0
  162. data/public/assets/ueditor/lang/en/images/alldeletebtnhoverskin.png +0 -0
  163. data/public/assets/ueditor/lang/en/images/alldeletebtnupskin.png +0 -0
  164. data/public/assets/ueditor/lang/en/images/background.png +0 -0
  165. data/public/assets/ueditor/lang/en/images/button.png +0 -0
  166. data/public/assets/ueditor/lang/en/images/copy.png +0 -0
  167. data/public/assets/ueditor/lang/en/images/deletedisable.png +0 -0
  168. data/public/assets/ueditor/lang/en/images/deleteenable.png +0 -0
  169. data/public/assets/ueditor/lang/en/images/listbackground.png +0 -0
  170. data/public/assets/ueditor/lang/en/images/localimage.png +0 -0
  171. data/public/assets/ueditor/lang/en/images/music.png +0 -0
  172. data/public/assets/ueditor/lang/en/images/rotateleftdisable.png +0 -0
  173. data/public/assets/ueditor/lang/en/images/rotateleftenable.png +0 -0
  174. data/public/assets/ueditor/lang/en/images/rotaterightdisable.png +0 -0
  175. data/public/assets/ueditor/lang/en/images/rotaterightenable.png +0 -0
  176. data/public/assets/ueditor/lang/en/images/upload.png +0 -0
  177. data/public/assets/ueditor/lang/zh-cn/images/copy.png +0 -0
  178. data/public/assets/ueditor/lang/zh-cn/images/localimage.png +0 -0
  179. data/public/assets/ueditor/lang/zh-cn/images/music.png +0 -0
  180. data/public/assets/ueditor/lang/zh-cn/images/upload.png +0 -0
  181. data/public/assets/ueditor/lang/zh-cn/zh-cn.js +669 -0
  182. data/public/assets/ueditor/themes/default/css/ueditor.css +1903 -0
  183. data/public/assets/ueditor/themes/default/css/ueditor.min.css +8 -0
  184. data/public/assets/ueditor/themes/default/dialogbase.css +100 -0
  185. data/public/assets/ueditor/themes/default/images/anchor.gif +0 -0
  186. data/public/assets/ueditor/themes/default/images/arrow.png +0 -0
  187. data/public/assets/ueditor/themes/default/images/arrow_down.png +0 -0
  188. data/public/assets/ueditor/themes/default/images/arrow_up.png +0 -0
  189. data/public/assets/ueditor/themes/default/images/button-bg.gif +0 -0
  190. data/public/assets/ueditor/themes/default/images/cancelbutton.gif +0 -0
  191. data/public/assets/ueditor/themes/default/images/charts.png +0 -0
  192. data/public/assets/ueditor/themes/default/images/cursor_h.gif +0 -0
  193. data/public/assets/ueditor/themes/default/images/cursor_h.png +0 -0
  194. data/public/assets/ueditor/themes/default/images/cursor_v.gif +0 -0
  195. data/public/assets/ueditor/themes/default/images/cursor_v.png +0 -0
  196. data/public/assets/ueditor/themes/default/images/dialog-title-bg.png +0 -0
  197. data/public/assets/ueditor/themes/default/images/filescan.png +0 -0
  198. data/public/assets/ueditor/themes/default/images/highlighted.gif +0 -0
  199. data/public/assets/ueditor/themes/default/images/icons-all.gif +0 -0
  200. data/public/assets/ueditor/themes/default/images/icons.gif +0 -0
  201. data/public/assets/ueditor/themes/default/images/icons.png +0 -0
  202. data/public/assets/ueditor/themes/default/images/loaderror.png +0 -0
  203. data/public/assets/ueditor/themes/default/images/loading.gif +0 -0
  204. data/public/assets/ueditor/themes/default/images/lock.gif +0 -0
  205. data/public/assets/ueditor/themes/default/images/neweditor-tab-bg.png +0 -0
  206. data/public/assets/ueditor/themes/default/images/pagebreak.gif +0 -0
  207. data/public/assets/ueditor/themes/default/images/scale.png +0 -0
  208. data/public/assets/ueditor/themes/default/images/sortable.png +0 -0
  209. data/public/assets/ueditor/themes/default/images/spacer.gif +0 -0
  210. data/public/assets/ueditor/themes/default/images/sparator_v.png +0 -0
  211. data/public/assets/ueditor/themes/default/images/table-cell-align.png +0 -0
  212. data/public/assets/ueditor/themes/default/images/tangram-colorpicker.png +0 -0
  213. data/public/assets/ueditor/themes/default/images/toolbar_bg.png +0 -0
  214. data/public/assets/ueditor/themes/default/images/unhighlighted.gif +0 -0
  215. data/public/assets/ueditor/themes/default/images/upload.png +0 -0
  216. data/public/assets/ueditor/themes/default/images/videologo.gif +0 -0
  217. data/public/assets/ueditor/themes/default/images/word.gif +0 -0
  218. data/public/assets/ueditor/themes/default/images/wordpaste.png +0 -0
  219. data/public/assets/ueditor/themes/iframe.css +1 -0
  220. data/public/assets/ueditor/third-party/SyntaxHighlighter/shCore.js +3655 -0
  221. data/public/assets/ueditor/third-party/SyntaxHighlighter/shCoreDefault.css +1 -0
  222. data/public/assets/ueditor/third-party/codemirror/codemirror.css +104 -0
  223. data/public/assets/ueditor/third-party/codemirror/codemirror.js +3581 -0
  224. data/public/assets/ueditor/third-party/highcharts/adapters/mootools-adapter.js +13 -0
  225. data/public/assets/ueditor/third-party/highcharts/adapters/mootools-adapter.src.js +313 -0
  226. data/public/assets/ueditor/third-party/highcharts/adapters/prototype-adapter.js +15 -0
  227. data/public/assets/ueditor/third-party/highcharts/adapters/prototype-adapter.src.js +316 -0
  228. data/public/assets/ueditor/third-party/highcharts/adapters/standalone-framework.js +17 -0
  229. data/public/assets/ueditor/third-party/highcharts/adapters/standalone-framework.src.js +583 -0
  230. data/public/assets/ueditor/third-party/highcharts/highcharts-more.js +50 -0
  231. data/public/assets/ueditor/third-party/highcharts/highcharts-more.src.js +2430 -0
  232. data/public/assets/ueditor/third-party/highcharts/highcharts.js +283 -0
  233. data/public/assets/ueditor/third-party/highcharts/highcharts.src.js +16974 -0
  234. data/public/assets/ueditor/third-party/highcharts/modules/annotations.js +7 -0
  235. data/public/assets/ueditor/third-party/highcharts/modules/annotations.src.js +401 -0
  236. data/public/assets/ueditor/third-party/highcharts/modules/canvas-tools.js +133 -0
  237. data/public/assets/ueditor/third-party/highcharts/modules/canvas-tools.src.js +3113 -0
  238. data/public/assets/ueditor/third-party/highcharts/modules/data.js +17 -0
  239. data/public/assets/ueditor/third-party/highcharts/modules/data.src.js +582 -0
  240. data/public/assets/ueditor/third-party/highcharts/modules/drilldown.js +11 -0
  241. data/public/assets/ueditor/third-party/highcharts/modules/drilldown.src.js +447 -0
  242. data/public/assets/ueditor/third-party/highcharts/modules/exporting.js +22 -0
  243. data/public/assets/ueditor/third-party/highcharts/modules/exporting.src.js +709 -0
  244. data/public/assets/ueditor/third-party/highcharts/modules/funnel.js +12 -0
  245. data/public/assets/ueditor/third-party/highcharts/modules/funnel.src.js +289 -0
  246. data/public/assets/ueditor/third-party/highcharts/modules/heatmap.js +1 -0
  247. data/public/assets/ueditor/third-party/highcharts/modules/heatmap.src.js +53 -0
  248. data/public/assets/ueditor/third-party/highcharts/modules/map.js +27 -0
  249. data/public/assets/ueditor/third-party/highcharts/modules/map.src.js +1002 -0
  250. data/public/assets/ueditor/third-party/highcharts/modules/no-data-to-display.js +12 -0
  251. data/public/assets/ueditor/third-party/highcharts/modules/no-data-to-display.src.js +128 -0
  252. data/public/assets/ueditor/third-party/highcharts/themes/dark-blue.js +254 -0
  253. data/public/assets/ueditor/third-party/highcharts/themes/dark-green.js +255 -0
  254. data/public/assets/ueditor/third-party/highcharts/themes/gray.js +257 -0
  255. data/public/assets/ueditor/third-party/highcharts/themes/grid.js +103 -0
  256. data/public/assets/ueditor/third-party/highcharts/themes/skies.js +89 -0
  257. data/public/assets/ueditor/third-party/jquery-1.10.2.js +9789 -0
  258. data/public/assets/ueditor/third-party/jquery-1.10.2.min.js +6 -0
  259. data/public/assets/ueditor/third-party/jquery-1.10.2.min.map +1 -0
  260. data/public/assets/ueditor/third-party/snapscreen/UEditorSnapscreen.exe +0 -0
  261. data/public/assets/ueditor/third-party/video-js/font/vjs.eot +0 -0
  262. data/public/assets/ueditor/third-party/video-js/font/vjs.svg +65 -0
  263. data/public/assets/ueditor/third-party/video-js/font/vjs.ttf +0 -0
  264. data/public/assets/ueditor/third-party/video-js/font/vjs.woff +0 -0
  265. data/public/assets/ueditor/third-party/video-js/video-js.css +766 -0
  266. data/public/assets/ueditor/third-party/video-js/video-js.min.css +5 -0
  267. data/public/assets/ueditor/third-party/video-js/video-js.swf +0 -0
  268. data/public/assets/ueditor/third-party/video-js/video.dev.js +7108 -0
  269. data/public/assets/ueditor/third-party/video-js/video.js +129 -0
  270. data/public/assets/ueditor/third-party/webuploader/Uploader.swf +0 -0
  271. data/public/assets/ueditor/third-party/webuploader/webuploader.css +28 -0
  272. data/public/assets/ueditor/third-party/webuploader/webuploader.custom.js +5670 -0
  273. data/public/assets/ueditor/third-party/webuploader/webuploader.custom.min.js +2 -0
  274. data/public/assets/ueditor/third-party/webuploader/webuploader.flashonly.js +4176 -0
  275. data/public/assets/ueditor/third-party/webuploader/webuploader.flashonly.min.js +2 -0
  276. data/public/assets/ueditor/third-party/webuploader/webuploader.html5only.js +5559 -0
  277. data/public/assets/ueditor/third-party/webuploader/webuploader.html5only.min.js +2 -0
  278. data/public/assets/ueditor/third-party/webuploader/webuploader.js +6733 -0
  279. data/public/assets/ueditor/third-party/webuploader/webuploader.min.js +2 -0
  280. data/public/assets/ueditor/third-party/webuploader/webuploader.withoutimage.js +4593 -0
  281. data/public/assets/ueditor/third-party/webuploader/webuploader.withoutimage.min.js +2 -0
  282. data/public/assets/ueditor/third-party/xss.min.js +1 -0
  283. data/public/assets/ueditor/third-party/zeroclipboard/ZeroClipboard.js +1256 -0
  284. data/public/assets/ueditor/third-party/zeroclipboard/ZeroClipboard.min.js +9 -0
  285. data/public/assets/ueditor/third-party/zeroclipboard/ZeroClipboard.swf +0 -0
  286. data/public/assets/ueditor/ueditor.parse.js +1022 -0
  287. data/public/assets/ueditor/ueditor.parse.min.js +7 -0
  288. data/screenshot.png +0 -0
  289. metadata +343 -0
@@ -0,0 +1,2430 @@
1
+ // ==ClosureCompiler==
2
+ // @compilation_level SIMPLE_OPTIMIZATIONS
3
+
4
+ /**
5
+ * @license Highcharts JS v3.0.6 (2013-10-04)
6
+ *
7
+ * (c) 2009-2013 Torstein Hønsi
8
+ *
9
+ * License: www.highcharts.com/license
10
+ */
11
+
12
+ // JSLint options:
13
+ /*global Highcharts, HighchartsAdapter, document, window, navigator, setInterval, clearInterval, clearTimeout, setTimeout, location, jQuery, $, console */
14
+
15
+ (function (Highcharts, UNDEFINED) {
16
+ var arrayMin = Highcharts.arrayMin,
17
+ arrayMax = Highcharts.arrayMax,
18
+ each = Highcharts.each,
19
+ extend = Highcharts.extend,
20
+ merge = Highcharts.merge,
21
+ map = Highcharts.map,
22
+ pick = Highcharts.pick,
23
+ pInt = Highcharts.pInt,
24
+ defaultPlotOptions = Highcharts.getOptions().plotOptions,
25
+ seriesTypes = Highcharts.seriesTypes,
26
+ extendClass = Highcharts.extendClass,
27
+ splat = Highcharts.splat,
28
+ wrap = Highcharts.wrap,
29
+ Axis = Highcharts.Axis,
30
+ Tick = Highcharts.Tick,
31
+ Series = Highcharts.Series,
32
+ colProto = seriesTypes.column.prototype,
33
+ math = Math,
34
+ mathRound = math.round,
35
+ mathFloor = math.floor,
36
+ mathMax = math.max,
37
+ noop = function () {};/**
38
+ * The Pane object allows options that are common to a set of X and Y axes.
39
+ *
40
+ * In the future, this can be extended to basic Highcharts and Highstock.
41
+ */
42
+ function Pane(options, chart, firstAxis) {
43
+ this.init.call(this, options, chart, firstAxis);
44
+ }
45
+
46
+ // Extend the Pane prototype
47
+ extend(Pane.prototype, {
48
+
49
+ /**
50
+ * Initiate the Pane object
51
+ */
52
+ init: function (options, chart, firstAxis) {
53
+ var pane = this,
54
+ backgroundOption,
55
+ defaultOptions = pane.defaultOptions;
56
+
57
+ pane.chart = chart;
58
+
59
+ // Set options
60
+ if (chart.angular) { // gauges
61
+ defaultOptions.background = {}; // gets extended by this.defaultBackgroundOptions
62
+ }
63
+ pane.options = options = merge(defaultOptions, options);
64
+
65
+ backgroundOption = options.background;
66
+
67
+ // To avoid having weighty logic to place, update and remove the backgrounds,
68
+ // push them to the first axis' plot bands and borrow the existing logic there.
69
+ if (backgroundOption) {
70
+ each([].concat(splat(backgroundOption)).reverse(), function (config) {
71
+ var backgroundColor = config.backgroundColor; // if defined, replace the old one (specific for gradients)
72
+ config = merge(pane.defaultBackgroundOptions, config);
73
+ if (backgroundColor) {
74
+ config.backgroundColor = backgroundColor;
75
+ }
76
+ config.color = config.backgroundColor; // due to naming in plotBands
77
+ firstAxis.options.plotBands.unshift(config);
78
+ });
79
+ }
80
+ },
81
+
82
+ /**
83
+ * The default options object
84
+ */
85
+ defaultOptions: {
86
+ // background: {conditional},
87
+ center: ['50%', '50%'],
88
+ size: '85%',
89
+ startAngle: 0
90
+ //endAngle: startAngle + 360
91
+ },
92
+
93
+ /**
94
+ * The default background options
95
+ */
96
+ defaultBackgroundOptions: {
97
+ shape: 'circle',
98
+ borderWidth: 1,
99
+ borderColor: 'silver',
100
+ backgroundColor: {
101
+ linearGradient: { x1: 0, y1: 0, x2: 0, y2: 1 },
102
+ stops: [
103
+ [0, '#FFF'],
104
+ [1, '#DDD']
105
+ ]
106
+ },
107
+ from: Number.MIN_VALUE, // corrected to axis min
108
+ innerRadius: 0,
109
+ to: Number.MAX_VALUE, // corrected to axis max
110
+ outerRadius: '105%'
111
+ }
112
+
113
+ });
114
+ var axisProto = Axis.prototype,
115
+ tickProto = Tick.prototype;
116
+
117
+ /**
118
+ * Augmented methods for the x axis in order to hide it completely, used for the X axis in gauges
119
+ */
120
+ var hiddenAxisMixin = {
121
+ getOffset: noop,
122
+ redraw: function () {
123
+ this.isDirty = false; // prevent setting Y axis dirty
124
+ },
125
+ render: function () {
126
+ this.isDirty = false; // prevent setting Y axis dirty
127
+ },
128
+ setScale: noop,
129
+ setCategories: noop,
130
+ setTitle: noop
131
+ };
132
+
133
+ /**
134
+ * Augmented methods for the value axis
135
+ */
136
+ /*jslint unparam: true*/
137
+ var radialAxisMixin = {
138
+ isRadial: true,
139
+
140
+ /**
141
+ * The default options extend defaultYAxisOptions
142
+ */
143
+ defaultRadialGaugeOptions: {
144
+ labels: {
145
+ align: 'center',
146
+ x: 0,
147
+ y: null // auto
148
+ },
149
+ minorGridLineWidth: 0,
150
+ minorTickInterval: 'auto',
151
+ minorTickLength: 10,
152
+ minorTickPosition: 'inside',
153
+ minorTickWidth: 1,
154
+ plotBands: [],
155
+ tickLength: 10,
156
+ tickPosition: 'inside',
157
+ tickWidth: 2,
158
+ title: {
159
+ rotation: 0
160
+ },
161
+ zIndex: 2 // behind dials, points in the series group
162
+ },
163
+
164
+ // Circular axis around the perimeter of a polar chart
165
+ defaultRadialXOptions: {
166
+ gridLineWidth: 1, // spokes
167
+ labels: {
168
+ align: null, // auto
169
+ distance: 15,
170
+ x: 0,
171
+ y: null // auto
172
+ },
173
+ maxPadding: 0,
174
+ minPadding: 0,
175
+ plotBands: [],
176
+ showLastLabel: false,
177
+ tickLength: 0
178
+ },
179
+
180
+ // Radial axis, like a spoke in a polar chart
181
+ defaultRadialYOptions: {
182
+ gridLineInterpolation: 'circle',
183
+ labels: {
184
+ align: 'right',
185
+ x: -3,
186
+ y: -2
187
+ },
188
+ plotBands: [],
189
+ showLastLabel: false,
190
+ title: {
191
+ x: 4,
192
+ text: null,
193
+ rotation: 90
194
+ }
195
+ },
196
+
197
+ /**
198
+ * Merge and set options
199
+ */
200
+ setOptions: function (userOptions) {
201
+
202
+ this.options = merge(
203
+ this.defaultOptions,
204
+ this.defaultRadialOptions,
205
+ userOptions
206
+ );
207
+
208
+ },
209
+
210
+ /**
211
+ * Wrap the getOffset method to return zero offset for title or labels in a radial
212
+ * axis
213
+ */
214
+ getOffset: function () {
215
+ // Call the Axis prototype method (the method we're in now is on the instance)
216
+ axisProto.getOffset.call(this);
217
+
218
+ // Title or label offsets are not counted
219
+ this.chart.axisOffset[this.side] = 0;
220
+ },
221
+
222
+
223
+ /**
224
+ * Get the path for the axis line. This method is also referenced in the getPlotLinePath
225
+ * method.
226
+ */
227
+ getLinePath: function (lineWidth, radius) {
228
+ var center = this.center;
229
+ radius = pick(radius, center[2] / 2 - this.offset);
230
+
231
+ return this.chart.renderer.symbols.arc(
232
+ this.left + center[0],
233
+ this.top + center[1],
234
+ radius,
235
+ radius,
236
+ {
237
+ start: this.startAngleRad,
238
+ end: this.endAngleRad,
239
+ open: true,
240
+ innerR: 0
241
+ }
242
+ );
243
+ },
244
+
245
+ /**
246
+ * Override setAxisTranslation by setting the translation to the difference
247
+ * in rotation. This allows the translate method to return angle for
248
+ * any given value.
249
+ */
250
+ setAxisTranslation: function () {
251
+
252
+ // Call uber method
253
+ axisProto.setAxisTranslation.call(this);
254
+
255
+ // Set transA and minPixelPadding
256
+ if (this.center) { // it's not defined the first time
257
+ if (this.isCircular) {
258
+
259
+ this.transA = (this.endAngleRad - this.startAngleRad) /
260
+ ((this.max - this.min) || 1);
261
+
262
+
263
+ } else {
264
+ this.transA = (this.center[2] / 2) / ((this.max - this.min) || 1);
265
+ }
266
+
267
+ if (this.isXAxis) {
268
+ this.minPixelPadding = this.transA * this.minPointOffset +
269
+ (this.reversed ? (this.endAngleRad - this.startAngleRad) / 4 : 0); // ???
270
+ }
271
+ }
272
+ },
273
+
274
+ /**
275
+ * In case of auto connect, add one closestPointRange to the max value right before
276
+ * tickPositions are computed, so that ticks will extend passed the real max.
277
+ */
278
+ beforeSetTickPositions: function () {
279
+ if (this.autoConnect) {
280
+ this.max += (this.categories && 1) || this.pointRange || this.closestPointRange || 0; // #1197, #2260
281
+ }
282
+ },
283
+
284
+ /**
285
+ * Override the setAxisSize method to use the arc's circumference as length. This
286
+ * allows tickPixelInterval to apply to pixel lengths along the perimeter
287
+ */
288
+ setAxisSize: function () {
289
+
290
+ axisProto.setAxisSize.call(this);
291
+
292
+ if (this.isRadial) {
293
+
294
+ // Set the center array
295
+ this.center = this.pane.center = seriesTypes.pie.prototype.getCenter.call(this.pane);
296
+
297
+ this.len = this.width = this.height = this.isCircular ?
298
+ this.center[2] * (this.endAngleRad - this.startAngleRad) / 2 :
299
+ this.center[2] / 2;
300
+ }
301
+ },
302
+
303
+ /**
304
+ * Returns the x, y coordinate of a point given by a value and a pixel distance
305
+ * from center
306
+ */
307
+ getPosition: function (value, length) {
308
+ if (!this.isCircular) {
309
+ length = this.translate(value);
310
+ value = this.min;
311
+ }
312
+
313
+ return this.postTranslate(
314
+ this.translate(value),
315
+ pick(length, this.center[2] / 2) - this.offset
316
+ );
317
+ },
318
+
319
+ /**
320
+ * Translate from intermediate plotX (angle), plotY (axis.len - radius) to final chart coordinates.
321
+ */
322
+ postTranslate: function (angle, radius) {
323
+
324
+ var chart = this.chart,
325
+ center = this.center;
326
+
327
+ angle = this.startAngleRad + angle;
328
+
329
+ return {
330
+ x: chart.plotLeft + center[0] + Math.cos(angle) * radius,
331
+ y: chart.plotTop + center[1] + Math.sin(angle) * radius
332
+ };
333
+
334
+ },
335
+
336
+ /**
337
+ * Find the path for plot bands along the radial axis
338
+ */
339
+ getPlotBandPath: function (from, to, options) {
340
+ var center = this.center,
341
+ startAngleRad = this.startAngleRad,
342
+ fullRadius = center[2] / 2,
343
+ radii = [
344
+ pick(options.outerRadius, '100%'),
345
+ options.innerRadius,
346
+ pick(options.thickness, 10)
347
+ ],
348
+ percentRegex = /%$/,
349
+ start,
350
+ end,
351
+ open,
352
+ isCircular = this.isCircular, // X axis in a polar chart
353
+ ret;
354
+
355
+ // Polygonal plot bands
356
+ if (this.options.gridLineInterpolation === 'polygon') {
357
+ ret = this.getPlotLinePath(from).concat(this.getPlotLinePath(to, true));
358
+
359
+ // Circular grid bands
360
+ } else {
361
+
362
+ // Plot bands on Y axis (radial axis) - inner and outer radius depend on to and from
363
+ if (!isCircular) {
364
+ radii[0] = this.translate(from);
365
+ radii[1] = this.translate(to);
366
+ }
367
+
368
+ // Convert percentages to pixel values
369
+ radii = map(radii, function (radius) {
370
+ if (percentRegex.test(radius)) {
371
+ radius = (pInt(radius, 10) * fullRadius) / 100;
372
+ }
373
+ return radius;
374
+ });
375
+
376
+ // Handle full circle
377
+ if (options.shape === 'circle' || !isCircular) {
378
+ start = -Math.PI / 2;
379
+ end = Math.PI * 1.5;
380
+ open = true;
381
+ } else {
382
+ start = startAngleRad + this.translate(from);
383
+ end = startAngleRad + this.translate(to);
384
+ }
385
+
386
+
387
+ ret = this.chart.renderer.symbols.arc(
388
+ this.left + center[0],
389
+ this.top + center[1],
390
+ radii[0],
391
+ radii[0],
392
+ {
393
+ start: start,
394
+ end: end,
395
+ innerR: pick(radii[1], radii[0] - radii[2]),
396
+ open: open
397
+ }
398
+ );
399
+ }
400
+
401
+ return ret;
402
+ },
403
+
404
+ /**
405
+ * Find the path for plot lines perpendicular to the radial axis.
406
+ */
407
+ getPlotLinePath: function (value, reverse) {
408
+ var axis = this,
409
+ center = axis.center,
410
+ chart = axis.chart,
411
+ end = axis.getPosition(value),
412
+ xAxis,
413
+ xy,
414
+ tickPositions,
415
+ ret;
416
+
417
+ // Spokes
418
+ if (axis.isCircular) {
419
+ ret = ['M', center[0] + chart.plotLeft, center[1] + chart.plotTop, 'L', end.x, end.y];
420
+
421
+ // Concentric circles
422
+ } else if (axis.options.gridLineInterpolation === 'circle') {
423
+ value = axis.translate(value);
424
+ if (value) { // a value of 0 is in the center
425
+ ret = axis.getLinePath(0, value);
426
+ }
427
+ // Concentric polygons
428
+ } else {
429
+ xAxis = chart.xAxis[0];
430
+ ret = [];
431
+ value = axis.translate(value);
432
+ tickPositions = xAxis.tickPositions;
433
+ if (xAxis.autoConnect) {
434
+ tickPositions = tickPositions.concat([tickPositions[0]]);
435
+ }
436
+ // Reverse the positions for concatenation of polygonal plot bands
437
+ if (reverse) {
438
+ tickPositions = [].concat(tickPositions).reverse();
439
+ }
440
+
441
+ each(tickPositions, function (pos, i) {
442
+ xy = xAxis.getPosition(pos, value);
443
+ ret.push(i ? 'L' : 'M', xy.x, xy.y);
444
+ });
445
+
446
+ }
447
+ return ret;
448
+ },
449
+
450
+ /**
451
+ * Find the position for the axis title, by default inside the gauge
452
+ */
453
+ getTitlePosition: function () {
454
+ var center = this.center,
455
+ chart = this.chart,
456
+ titleOptions = this.options.title;
457
+
458
+ return {
459
+ x: chart.plotLeft + center[0] + (titleOptions.x || 0),
460
+ y: chart.plotTop + center[1] - ({ high: 0.5, middle: 0.25, low: 0 }[titleOptions.align] *
461
+ center[2]) + (titleOptions.y || 0)
462
+ };
463
+ }
464
+
465
+ };
466
+ /*jslint unparam: false*/
467
+
468
+ /**
469
+ * Override axisProto.init to mix in special axis instance functions and function overrides
470
+ */
471
+ wrap(axisProto, 'init', function (proceed, chart, userOptions) {
472
+ var axis = this,
473
+ angular = chart.angular,
474
+ polar = chart.polar,
475
+ isX = userOptions.isX,
476
+ isHidden = angular && isX,
477
+ isCircular,
478
+ startAngleRad,
479
+ endAngleRad,
480
+ options,
481
+ chartOptions = chart.options,
482
+ paneIndex = userOptions.pane || 0,
483
+ pane,
484
+ paneOptions;
485
+
486
+ // Before prototype.init
487
+ if (angular) {
488
+ extend(this, isHidden ? hiddenAxisMixin : radialAxisMixin);
489
+ isCircular = !isX;
490
+ if (isCircular) {
491
+ this.defaultRadialOptions = this.defaultRadialGaugeOptions;
492
+ }
493
+
494
+ } else if (polar) {
495
+ //extend(this, userOptions.isX ? radialAxisMixin : radialAxisMixin);
496
+ extend(this, radialAxisMixin);
497
+ isCircular = isX;
498
+ this.defaultRadialOptions = isX ? this.defaultRadialXOptions : merge(this.defaultYAxisOptions, this.defaultRadialYOptions);
499
+
500
+ }
501
+
502
+ // Run prototype.init
503
+ proceed.call(this, chart, userOptions);
504
+
505
+ if (!isHidden && (angular || polar)) {
506
+ options = this.options;
507
+
508
+ // Create the pane and set the pane options.
509
+ if (!chart.panes) {
510
+ chart.panes = [];
511
+ }
512
+ this.pane = pane = chart.panes[paneIndex] = chart.panes[paneIndex] || new Pane(
513
+ splat(chartOptions.pane)[paneIndex],
514
+ chart,
515
+ axis
516
+ );
517
+ paneOptions = pane.options;
518
+
519
+
520
+ // Disable certain features on angular and polar axes
521
+ chart.inverted = false;
522
+ chartOptions.chart.zoomType = null;
523
+
524
+ // Start and end angle options are
525
+ // given in degrees relative to top, while internal computations are
526
+ // in radians relative to right (like SVG).
527
+ this.startAngleRad = startAngleRad = (paneOptions.startAngle - 90) * Math.PI / 180;
528
+ this.endAngleRad = endAngleRad = (pick(paneOptions.endAngle, paneOptions.startAngle + 360) - 90) * Math.PI / 180;
529
+ this.offset = options.offset || 0;
530
+
531
+ this.isCircular = isCircular;
532
+
533
+ // Automatically connect grid lines?
534
+ if (isCircular && userOptions.max === UNDEFINED && endAngleRad - startAngleRad === 2 * Math.PI) {
535
+ this.autoConnect = true;
536
+ }
537
+ }
538
+
539
+ });
540
+
541
+ /**
542
+ * Add special cases within the Tick class' methods for radial axes.
543
+ */
544
+ wrap(tickProto, 'getPosition', function (proceed, horiz, pos, tickmarkOffset, old) {
545
+ var axis = this.axis;
546
+
547
+ return axis.getPosition ?
548
+ axis.getPosition(pos) :
549
+ proceed.call(this, horiz, pos, tickmarkOffset, old);
550
+ });
551
+
552
+ /**
553
+ * Wrap the getLabelPosition function to find the center position of the label
554
+ * based on the distance option
555
+ */
556
+ wrap(tickProto, 'getLabelPosition', function (proceed, x, y, label, horiz, labelOptions, tickmarkOffset, index, step) {
557
+ var axis = this.axis,
558
+ optionsY = labelOptions.y,
559
+ ret,
560
+ align = labelOptions.align,
561
+ angle = ((axis.translate(this.pos) + axis.startAngleRad + Math.PI / 2) / Math.PI * 180) % 360;
562
+
563
+ if (axis.isRadial) {
564
+ ret = axis.getPosition(this.pos, (axis.center[2] / 2) + pick(labelOptions.distance, -25));
565
+
566
+ // Automatically rotated
567
+ if (labelOptions.rotation === 'auto') {
568
+ label.attr({
569
+ rotation: angle
570
+ });
571
+
572
+ // Vertically centered
573
+ } else if (optionsY === null) {
574
+ optionsY = pInt(label.styles.lineHeight) * 0.9 - label.getBBox().height / 2;
575
+
576
+ }
577
+
578
+ // Automatic alignment
579
+ if (align === null) {
580
+ if (axis.isCircular) {
581
+ if (angle > 20 && angle < 160) {
582
+ align = 'left'; // right hemisphere
583
+ } else if (angle > 200 && angle < 340) {
584
+ align = 'right'; // left hemisphere
585
+ } else {
586
+ align = 'center'; // top or bottom
587
+ }
588
+ } else {
589
+ align = 'center';
590
+ }
591
+ label.attr({
592
+ align: align
593
+ });
594
+ }
595
+
596
+ ret.x += labelOptions.x;
597
+ ret.y += optionsY;
598
+
599
+ } else {
600
+ ret = proceed.call(this, x, y, label, horiz, labelOptions, tickmarkOffset, index, step);
601
+ }
602
+ return ret;
603
+ });
604
+
605
+ /**
606
+ * Wrap the getMarkPath function to return the path of the radial marker
607
+ */
608
+ wrap(tickProto, 'getMarkPath', function (proceed, x, y, tickLength, tickWidth, horiz, renderer) {
609
+ var axis = this.axis,
610
+ endPoint,
611
+ ret;
612
+
613
+ if (axis.isRadial) {
614
+ endPoint = axis.getPosition(this.pos, axis.center[2] / 2 + tickLength);
615
+ ret = [
616
+ 'M',
617
+ x,
618
+ y,
619
+ 'L',
620
+ endPoint.x,
621
+ endPoint.y
622
+ ];
623
+ } else {
624
+ ret = proceed.call(this, x, y, tickLength, tickWidth, horiz, renderer);
625
+ }
626
+ return ret;
627
+ });/*
628
+ * The AreaRangeSeries class
629
+ *
630
+ */
631
+
632
+ /**
633
+ * Extend the default options with map options
634
+ */
635
+ defaultPlotOptions.arearange = merge(defaultPlotOptions.area, {
636
+ lineWidth: 1,
637
+ marker: null,
638
+ threshold: null,
639
+ tooltip: {
640
+ pointFormat: '<span style="color:{series.color}">{series.name}</span>: <b>{point.low}</b> - <b>{point.high}</b><br/>'
641
+ },
642
+ trackByArea: true,
643
+ dataLabels: {
644
+ verticalAlign: null,
645
+ xLow: 0,
646
+ xHigh: 0,
647
+ yLow: 0,
648
+ yHigh: 0
649
+ }
650
+ });
651
+
652
+ /**
653
+ * Add the series type
654
+ */
655
+ seriesTypes.arearange = Highcharts.extendClass(seriesTypes.area, {
656
+ type: 'arearange',
657
+ pointArrayMap: ['low', 'high'],
658
+ toYData: function (point) {
659
+ return [point.low, point.high];
660
+ },
661
+ pointValKey: 'low',
662
+
663
+ /**
664
+ * Extend getSegments to force null points if the higher value is null. #1703.
665
+ */
666
+ getSegments: function () {
667
+ var series = this;
668
+
669
+ each(series.points, function (point) {
670
+ if (!series.options.connectNulls && (point.low === null || point.high === null)) {
671
+ point.y = null;
672
+ } else if (point.low === null && point.high !== null) {
673
+ point.y = point.high;
674
+ }
675
+ });
676
+ Series.prototype.getSegments.call(this);
677
+ },
678
+
679
+ /**
680
+ * Translate data points from raw values x and y to plotX and plotY
681
+ */
682
+ translate: function () {
683
+ var series = this,
684
+ yAxis = series.yAxis;
685
+
686
+ seriesTypes.area.prototype.translate.apply(series);
687
+
688
+ // Set plotLow and plotHigh
689
+ each(series.points, function (point) {
690
+
691
+ var low = point.low,
692
+ high = point.high,
693
+ plotY = point.plotY;
694
+
695
+ if (high === null && low === null) {
696
+ point.y = null;
697
+ } else if (low === null) {
698
+ point.plotLow = point.plotY = null;
699
+ point.plotHigh = yAxis.translate(high, 0, 1, 0, 1);
700
+ } else if (high === null) {
701
+ point.plotLow = plotY;
702
+ point.plotHigh = null;
703
+ } else {
704
+ point.plotLow = plotY;
705
+ point.plotHigh = yAxis.translate(high, 0, 1, 0, 1);
706
+ }
707
+ });
708
+ },
709
+
710
+ /**
711
+ * Extend the line series' getSegmentPath method by applying the segment
712
+ * path to both lower and higher values of the range
713
+ */
714
+ getSegmentPath: function (segment) {
715
+
716
+ var lowSegment,
717
+ highSegment = [],
718
+ i = segment.length,
719
+ baseGetSegmentPath = Series.prototype.getSegmentPath,
720
+ point,
721
+ linePath,
722
+ lowerPath,
723
+ options = this.options,
724
+ step = options.step,
725
+ higherPath;
726
+
727
+ // Remove nulls from low segment
728
+ lowSegment = HighchartsAdapter.grep(segment, function (point) {
729
+ return point.plotLow !== null;
730
+ });
731
+
732
+ // Make a segment with plotX and plotY for the top values
733
+ while (i--) {
734
+ point = segment[i];
735
+ if (point.plotHigh !== null) {
736
+ highSegment.push({
737
+ plotX: point.plotX,
738
+ plotY: point.plotHigh
739
+ });
740
+ }
741
+ }
742
+
743
+ // Get the paths
744
+ lowerPath = baseGetSegmentPath.call(this, lowSegment);
745
+ if (step) {
746
+ if (step === true) {
747
+ step = 'left';
748
+ }
749
+ options.step = { left: 'right', center: 'center', right: 'left' }[step]; // swap for reading in getSegmentPath
750
+ }
751
+ higherPath = baseGetSegmentPath.call(this, highSegment);
752
+ options.step = step;
753
+
754
+ // Create a line on both top and bottom of the range
755
+ linePath = [].concat(lowerPath, higherPath);
756
+
757
+ // For the area path, we need to change the 'move' statement into 'lineTo' or 'curveTo'
758
+ higherPath[0] = 'L'; // this probably doesn't work for spline
759
+ this.areaPath = this.areaPath.concat(lowerPath, higherPath);
760
+
761
+ return linePath;
762
+ },
763
+
764
+ /**
765
+ * Extend the basic drawDataLabels method by running it for both lower and higher
766
+ * values.
767
+ */
768
+ drawDataLabels: function () {
769
+
770
+ var data = this.data,
771
+ length = data.length,
772
+ i,
773
+ originalDataLabels = [],
774
+ seriesProto = Series.prototype,
775
+ dataLabelOptions = this.options.dataLabels,
776
+ point,
777
+ inverted = this.chart.inverted;
778
+
779
+ if (dataLabelOptions.enabled || this._hasPointLabels) {
780
+
781
+ // Step 1: set preliminary values for plotY and dataLabel and draw the upper labels
782
+ i = length;
783
+ while (i--) {
784
+ point = data[i];
785
+
786
+ // Set preliminary values
787
+ point.y = point.high;
788
+ point.plotY = point.plotHigh;
789
+
790
+ // Store original data labels and set preliminary label objects to be picked up
791
+ // in the uber method
792
+ originalDataLabels[i] = point.dataLabel;
793
+ point.dataLabel = point.dataLabelUpper;
794
+
795
+ // Set the default offset
796
+ point.below = false;
797
+ if (inverted) {
798
+ dataLabelOptions.align = 'left';
799
+ dataLabelOptions.x = dataLabelOptions.xHigh;
800
+ } else {
801
+ dataLabelOptions.y = dataLabelOptions.yHigh;
802
+ }
803
+ }
804
+ seriesProto.drawDataLabels.apply(this, arguments); // #1209
805
+
806
+ // Step 2: reorganize and handle data labels for the lower values
807
+ i = length;
808
+ while (i--) {
809
+ point = data[i];
810
+
811
+ // Move the generated labels from step 1, and reassign the original data labels
812
+ point.dataLabelUpper = point.dataLabel;
813
+ point.dataLabel = originalDataLabels[i];
814
+
815
+ // Reset values
816
+ point.y = point.low;
817
+ point.plotY = point.plotLow;
818
+
819
+ // Set the default offset
820
+ point.below = true;
821
+ if (inverted) {
822
+ dataLabelOptions.align = 'right';
823
+ dataLabelOptions.x = dataLabelOptions.xLow;
824
+ } else {
825
+ dataLabelOptions.y = dataLabelOptions.yLow;
826
+ }
827
+ }
828
+ seriesProto.drawDataLabels.apply(this, arguments);
829
+ }
830
+
831
+ },
832
+
833
+ alignDataLabel: seriesTypes.column.prototype.alignDataLabel,
834
+
835
+ getSymbol: seriesTypes.column.prototype.getSymbol,
836
+
837
+ drawPoints: noop
838
+ });/**
839
+ * The AreaSplineRangeSeries class
840
+ */
841
+
842
+ defaultPlotOptions.areasplinerange = merge(defaultPlotOptions.arearange);
843
+
844
+ /**
845
+ * AreaSplineRangeSeries object
846
+ */
847
+ seriesTypes.areasplinerange = extendClass(seriesTypes.arearange, {
848
+ type: 'areasplinerange',
849
+ getPointSpline: seriesTypes.spline.prototype.getPointSpline
850
+ });/**
851
+ * The ColumnRangeSeries class
852
+ */
853
+ defaultPlotOptions.columnrange = merge(defaultPlotOptions.column, defaultPlotOptions.arearange, {
854
+ lineWidth: 1,
855
+ pointRange: null
856
+ });
857
+
858
+ /**
859
+ * ColumnRangeSeries object
860
+ */
861
+ seriesTypes.columnrange = extendClass(seriesTypes.arearange, {
862
+ type: 'columnrange',
863
+ /**
864
+ * Translate data points from raw values x and y to plotX and plotY
865
+ */
866
+ translate: function () {
867
+ var series = this,
868
+ yAxis = series.yAxis,
869
+ plotHigh;
870
+
871
+ colProto.translate.apply(series);
872
+
873
+ // Set plotLow and plotHigh
874
+ each(series.points, function (point) {
875
+ var shapeArgs = point.shapeArgs,
876
+ minPointLength = series.options.minPointLength,
877
+ heightDifference,
878
+ height,
879
+ y;
880
+
881
+ point.plotHigh = plotHigh = yAxis.translate(point.high, 0, 1, 0, 1);
882
+ point.plotLow = point.plotY;
883
+
884
+ // adjust shape
885
+ y = plotHigh;
886
+ height = point.plotY - plotHigh;
887
+
888
+ if (height < minPointLength) {
889
+ heightDifference = (minPointLength - height);
890
+ height += heightDifference;
891
+ y -= heightDifference / 2;
892
+ }
893
+ shapeArgs.height = height;
894
+ shapeArgs.y = y;
895
+ });
896
+ },
897
+ trackerGroups: ['group', 'dataLabels'],
898
+ drawGraph: noop,
899
+ pointAttrToOptions: colProto.pointAttrToOptions,
900
+ drawPoints: colProto.drawPoints,
901
+ drawTracker: colProto.drawTracker,
902
+ animate: colProto.animate,
903
+ getColumnMetrics: colProto.getColumnMetrics
904
+ });
905
+ /*
906
+ * The GaugeSeries class
907
+ */
908
+
909
+
910
+
911
+ /**
912
+ * Extend the default options
913
+ */
914
+ defaultPlotOptions.gauge = merge(defaultPlotOptions.line, {
915
+ dataLabels: {
916
+ enabled: true,
917
+ y: 15,
918
+ borderWidth: 1,
919
+ borderColor: 'silver',
920
+ borderRadius: 3,
921
+ style: {
922
+ fontWeight: 'bold'
923
+ },
924
+ verticalAlign: 'top',
925
+ zIndex: 2
926
+ },
927
+ dial: {
928
+ // radius: '80%',
929
+ // backgroundColor: 'black',
930
+ // borderColor: 'silver',
931
+ // borderWidth: 0,
932
+ // baseWidth: 3,
933
+ // topWidth: 1,
934
+ // baseLength: '70%' // of radius
935
+ // rearLength: '10%'
936
+ },
937
+ pivot: {
938
+ //radius: 5,
939
+ //borderWidth: 0
940
+ //borderColor: 'silver',
941
+ //backgroundColor: 'black'
942
+ },
943
+ tooltip: {
944
+ headerFormat: ''
945
+ },
946
+ showInLegend: false
947
+ });
948
+
949
+ /**
950
+ * Extend the point object
951
+ */
952
+ var GaugePoint = Highcharts.extendClass(Highcharts.Point, {
953
+ /**
954
+ * Don't do any hover colors or anything
955
+ */
956
+ setState: function (state) {
957
+ this.state = state;
958
+ }
959
+ });
960
+
961
+
962
+ /**
963
+ * Add the series type
964
+ */
965
+ var GaugeSeries = {
966
+ type: 'gauge',
967
+ pointClass: GaugePoint,
968
+
969
+ // chart.angular will be set to true when a gauge series is present, and this will
970
+ // be used on the axes
971
+ angular: true,
972
+ drawGraph: noop,
973
+ fixedBox: true,
974
+ trackerGroups: ['group', 'dataLabels'],
975
+
976
+ /**
977
+ * Calculate paths etc
978
+ */
979
+ translate: function () {
980
+
981
+ var series = this,
982
+ yAxis = series.yAxis,
983
+ options = series.options,
984
+ center = yAxis.center;
985
+
986
+ series.generatePoints();
987
+
988
+ each(series.points, function (point) {
989
+
990
+ var dialOptions = merge(options.dial, point.dial),
991
+ radius = (pInt(pick(dialOptions.radius, 80)) * center[2]) / 200,
992
+ baseLength = (pInt(pick(dialOptions.baseLength, 70)) * radius) / 100,
993
+ rearLength = (pInt(pick(dialOptions.rearLength, 10)) * radius) / 100,
994
+ baseWidth = dialOptions.baseWidth || 3,
995
+ topWidth = dialOptions.topWidth || 1,
996
+ rotation = yAxis.startAngleRad + yAxis.translate(point.y, null, null, null, true);
997
+
998
+ // Handle the wrap option
999
+ if (options.wrap === false) {
1000
+ rotation = Math.max(yAxis.startAngleRad, Math.min(yAxis.endAngleRad, rotation));
1001
+ }
1002
+ rotation = rotation * 180 / Math.PI;
1003
+
1004
+ point.shapeType = 'path';
1005
+ point.shapeArgs = {
1006
+ d: dialOptions.path || [
1007
+ 'M',
1008
+ -rearLength, -baseWidth / 2,
1009
+ 'L',
1010
+ baseLength, -baseWidth / 2,
1011
+ radius, -topWidth / 2,
1012
+ radius, topWidth / 2,
1013
+ baseLength, baseWidth / 2,
1014
+ -rearLength, baseWidth / 2,
1015
+ 'z'
1016
+ ],
1017
+ translateX: center[0],
1018
+ translateY: center[1],
1019
+ rotation: rotation
1020
+ };
1021
+
1022
+ // Positions for data label
1023
+ point.plotX = center[0];
1024
+ point.plotY = center[1];
1025
+ });
1026
+ },
1027
+
1028
+ /**
1029
+ * Draw the points where each point is one needle
1030
+ */
1031
+ drawPoints: function () {
1032
+
1033
+ var series = this,
1034
+ center = series.yAxis.center,
1035
+ pivot = series.pivot,
1036
+ options = series.options,
1037
+ pivotOptions = options.pivot,
1038
+ renderer = series.chart.renderer;
1039
+
1040
+ each(series.points, function (point) {
1041
+
1042
+ var graphic = point.graphic,
1043
+ shapeArgs = point.shapeArgs,
1044
+ d = shapeArgs.d,
1045
+ dialOptions = merge(options.dial, point.dial); // #1233
1046
+
1047
+ if (graphic) {
1048
+ graphic.animate(shapeArgs);
1049
+ shapeArgs.d = d; // animate alters it
1050
+ } else {
1051
+ point.graphic = renderer[point.shapeType](shapeArgs)
1052
+ .attr({
1053
+ stroke: dialOptions.borderColor || 'none',
1054
+ 'stroke-width': dialOptions.borderWidth || 0,
1055
+ fill: dialOptions.backgroundColor || 'black',
1056
+ rotation: shapeArgs.rotation // required by VML when animation is false
1057
+ })
1058
+ .add(series.group);
1059
+ }
1060
+ });
1061
+
1062
+ // Add or move the pivot
1063
+ if (pivot) {
1064
+ pivot.animate({ // #1235
1065
+ translateX: center[0],
1066
+ translateY: center[1]
1067
+ });
1068
+ } else {
1069
+ series.pivot = renderer.circle(0, 0, pick(pivotOptions.radius, 5))
1070
+ .attr({
1071
+ 'stroke-width': pivotOptions.borderWidth || 0,
1072
+ stroke: pivotOptions.borderColor || 'silver',
1073
+ fill: pivotOptions.backgroundColor || 'black'
1074
+ })
1075
+ .translate(center[0], center[1])
1076
+ .add(series.group);
1077
+ }
1078
+ },
1079
+
1080
+ /**
1081
+ * Animate the arrow up from startAngle
1082
+ */
1083
+ animate: function (init) {
1084
+ var series = this;
1085
+
1086
+ if (!init) {
1087
+ each(series.points, function (point) {
1088
+ var graphic = point.graphic;
1089
+
1090
+ if (graphic) {
1091
+ // start value
1092
+ graphic.attr({
1093
+ rotation: series.yAxis.startAngleRad * 180 / Math.PI
1094
+ });
1095
+
1096
+ // animate
1097
+ graphic.animate({
1098
+ rotation: point.shapeArgs.rotation
1099
+ }, series.options.animation);
1100
+ }
1101
+ });
1102
+
1103
+ // delete this function to allow it only once
1104
+ series.animate = null;
1105
+ }
1106
+ },
1107
+
1108
+ render: function () {
1109
+ this.group = this.plotGroup(
1110
+ 'group',
1111
+ 'series',
1112
+ this.visible ? 'visible' : 'hidden',
1113
+ this.options.zIndex,
1114
+ this.chart.seriesGroup
1115
+ );
1116
+ seriesTypes.pie.prototype.render.call(this);
1117
+ this.group.clip(this.chart.clipRect);
1118
+ },
1119
+
1120
+ setData: seriesTypes.pie.prototype.setData,
1121
+ drawTracker: seriesTypes.column.prototype.drawTracker
1122
+ };
1123
+ seriesTypes.gauge = Highcharts.extendClass(seriesTypes.line, GaugeSeries);/* ****************************************************************************
1124
+ * Start Box plot series code *
1125
+ *****************************************************************************/
1126
+
1127
+ // Set default options
1128
+ defaultPlotOptions.boxplot = merge(defaultPlotOptions.column, {
1129
+ fillColor: '#FFFFFF',
1130
+ lineWidth: 1,
1131
+ //medianColor: null,
1132
+ medianWidth: 2,
1133
+ states: {
1134
+ hover: {
1135
+ brightness: -0.3
1136
+ }
1137
+ },
1138
+ //stemColor: null,
1139
+ //stemDashStyle: 'solid'
1140
+ //stemWidth: null,
1141
+ threshold: null,
1142
+ tooltip: {
1143
+ pointFormat: '<span style="color:{series.color};font-weight:bold">{series.name}</span><br/>' +
1144
+ 'Maximum: {point.high}<br/>' +
1145
+ 'Upper quartile: {point.q3}<br/>' +
1146
+ 'Median: {point.median}<br/>' +
1147
+ 'Lower quartile: {point.q1}<br/>' +
1148
+ 'Minimum: {point.low}<br/>'
1149
+
1150
+ },
1151
+ //whiskerColor: null,
1152
+ whiskerLength: '50%',
1153
+ whiskerWidth: 2
1154
+ });
1155
+
1156
+ // Create the series object
1157
+ seriesTypes.boxplot = extendClass(seriesTypes.column, {
1158
+ type: 'boxplot',
1159
+ pointArrayMap: ['low', 'q1', 'median', 'q3', 'high'], // array point configs are mapped to this
1160
+ toYData: function (point) { // return a plain array for speedy calculation
1161
+ return [point.low, point.q1, point.median, point.q3, point.high];
1162
+ },
1163
+ pointValKey: 'high', // defines the top of the tracker
1164
+
1165
+ /**
1166
+ * One-to-one mapping from options to SVG attributes
1167
+ */
1168
+ pointAttrToOptions: { // mapping between SVG attributes and the corresponding options
1169
+ fill: 'fillColor',
1170
+ stroke: 'color',
1171
+ 'stroke-width': 'lineWidth'
1172
+ },
1173
+
1174
+ /**
1175
+ * Disable data labels for box plot
1176
+ */
1177
+ drawDataLabels: noop,
1178
+
1179
+ /**
1180
+ * Translate data points from raw values x and y to plotX and plotY
1181
+ */
1182
+ translate: function () {
1183
+ var series = this,
1184
+ yAxis = series.yAxis,
1185
+ pointArrayMap = series.pointArrayMap;
1186
+
1187
+ seriesTypes.column.prototype.translate.apply(series);
1188
+
1189
+ // do the translation on each point dimension
1190
+ each(series.points, function (point) {
1191
+ each(pointArrayMap, function (key) {
1192
+ if (point[key] !== null) {
1193
+ point[key + 'Plot'] = yAxis.translate(point[key], 0, 1, 0, 1);
1194
+ }
1195
+ });
1196
+ });
1197
+ },
1198
+
1199
+ /**
1200
+ * Draw the data points
1201
+ */
1202
+ drawPoints: function () {
1203
+ var series = this, //state = series.state,
1204
+ points = series.points,
1205
+ options = series.options,
1206
+ chart = series.chart,
1207
+ renderer = chart.renderer,
1208
+ pointAttr,
1209
+ q1Plot,
1210
+ q3Plot,
1211
+ highPlot,
1212
+ lowPlot,
1213
+ medianPlot,
1214
+ crispCorr,
1215
+ crispX,
1216
+ graphic,
1217
+ stemPath,
1218
+ stemAttr,
1219
+ boxPath,
1220
+ whiskersPath,
1221
+ whiskersAttr,
1222
+ medianPath,
1223
+ medianAttr,
1224
+ width,
1225
+ left,
1226
+ right,
1227
+ halfWidth,
1228
+ shapeArgs,
1229
+ color,
1230
+ doQuartiles = series.doQuartiles !== false, // error bar inherits this series type but doesn't do quartiles
1231
+ whiskerLength = parseInt(series.options.whiskerLength, 10) / 100;
1232
+
1233
+
1234
+ each(points, function (point) {
1235
+
1236
+ graphic = point.graphic;
1237
+ shapeArgs = point.shapeArgs; // the box
1238
+ stemAttr = {};
1239
+ whiskersAttr = {};
1240
+ medianAttr = {};
1241
+ color = point.color || series.color;
1242
+
1243
+ if (point.plotY !== UNDEFINED) {
1244
+
1245
+ pointAttr = point.pointAttr[point.selected ? 'selected' : ''];
1246
+
1247
+ // crisp vector coordinates
1248
+ width = shapeArgs.width;
1249
+ left = mathFloor(shapeArgs.x);
1250
+ right = left + width;
1251
+ halfWidth = mathRound(width / 2);
1252
+ //crispX = mathRound(left + halfWidth) + crispCorr;
1253
+ q1Plot = mathFloor(doQuartiles ? point.q1Plot : point.lowPlot);// + crispCorr;
1254
+ q3Plot = mathFloor(doQuartiles ? point.q3Plot : point.lowPlot);// + crispCorr;
1255
+ highPlot = mathFloor(point.highPlot);// + crispCorr;
1256
+ lowPlot = mathFloor(point.lowPlot);// + crispCorr;
1257
+
1258
+ // Stem attributes
1259
+ stemAttr.stroke = point.stemColor || options.stemColor || color;
1260
+ stemAttr['stroke-width'] = pick(point.stemWidth, options.stemWidth, options.lineWidth);
1261
+ stemAttr.dashstyle = point.stemDashStyle || options.stemDashStyle;
1262
+
1263
+ // Whiskers attributes
1264
+ whiskersAttr.stroke = point.whiskerColor || options.whiskerColor || color;
1265
+ whiskersAttr['stroke-width'] = pick(point.whiskerWidth, options.whiskerWidth, options.lineWidth);
1266
+
1267
+ // Median attributes
1268
+ medianAttr.stroke = point.medianColor || options.medianColor || color;
1269
+ medianAttr['stroke-width'] = pick(point.medianWidth, options.medianWidth, options.lineWidth);
1270
+
1271
+
1272
+ // The stem
1273
+ crispCorr = (stemAttr['stroke-width'] % 2) / 2;
1274
+ crispX = left + halfWidth + crispCorr;
1275
+ stemPath = [
1276
+ // stem up
1277
+ 'M',
1278
+ crispX, q3Plot,
1279
+ 'L',
1280
+ crispX, highPlot,
1281
+
1282
+ // stem down
1283
+ 'M',
1284
+ crispX, q1Plot,
1285
+ 'L',
1286
+ crispX, lowPlot,
1287
+ 'z'
1288
+ ];
1289
+
1290
+ // The box
1291
+ if (doQuartiles) {
1292
+ crispCorr = (pointAttr['stroke-width'] % 2) / 2;
1293
+ crispX = mathFloor(crispX) + crispCorr;
1294
+ q1Plot = mathFloor(q1Plot) + crispCorr;
1295
+ q3Plot = mathFloor(q3Plot) + crispCorr;
1296
+ left += crispCorr;
1297
+ right += crispCorr;
1298
+ boxPath = [
1299
+ 'M',
1300
+ left, q3Plot,
1301
+ 'L',
1302
+ left, q1Plot,
1303
+ 'L',
1304
+ right, q1Plot,
1305
+ 'L',
1306
+ right, q3Plot,
1307
+ 'L',
1308
+ left, q3Plot,
1309
+ 'z'
1310
+ ];
1311
+ }
1312
+
1313
+ // The whiskers
1314
+ if (whiskerLength) {
1315
+ crispCorr = (whiskersAttr['stroke-width'] % 2) / 2;
1316
+ highPlot = highPlot + crispCorr;
1317
+ lowPlot = lowPlot + crispCorr;
1318
+ whiskersPath = [
1319
+ // High whisker
1320
+ 'M',
1321
+ crispX - halfWidth * whiskerLength,
1322
+ highPlot,
1323
+ 'L',
1324
+ crispX + halfWidth * whiskerLength,
1325
+ highPlot,
1326
+
1327
+ // Low whisker
1328
+ 'M',
1329
+ crispX - halfWidth * whiskerLength,
1330
+ lowPlot,
1331
+ 'L',
1332
+ crispX + halfWidth * whiskerLength,
1333
+ lowPlot
1334
+ ];
1335
+ }
1336
+
1337
+ // The median
1338
+ crispCorr = (medianAttr['stroke-width'] % 2) / 2;
1339
+ medianPlot = mathRound(point.medianPlot) + crispCorr;
1340
+ medianPath = [
1341
+ 'M',
1342
+ left,
1343
+ medianPlot,
1344
+ 'L',
1345
+ right,
1346
+ medianPlot,
1347
+ 'z'
1348
+ ];
1349
+
1350
+ // Create or update the graphics
1351
+ if (graphic) { // update
1352
+
1353
+ point.stem.animate({ d: stemPath });
1354
+ if (whiskerLength) {
1355
+ point.whiskers.animate({ d: whiskersPath });
1356
+ }
1357
+ if (doQuartiles) {
1358
+ point.box.animate({ d: boxPath });
1359
+ }
1360
+ point.medianShape.animate({ d: medianPath });
1361
+
1362
+ } else { // create new
1363
+ point.graphic = graphic = renderer.g()
1364
+ .add(series.group);
1365
+
1366
+ point.stem = renderer.path(stemPath)
1367
+ .attr(stemAttr)
1368
+ .add(graphic);
1369
+
1370
+ if (whiskerLength) {
1371
+ point.whiskers = renderer.path(whiskersPath)
1372
+ .attr(whiskersAttr)
1373
+ .add(graphic);
1374
+ }
1375
+ if (doQuartiles) {
1376
+ point.box = renderer.path(boxPath)
1377
+ .attr(pointAttr)
1378
+ .add(graphic);
1379
+ }
1380
+ point.medianShape = renderer.path(medianPath)
1381
+ .attr(medianAttr)
1382
+ .add(graphic);
1383
+ }
1384
+ }
1385
+ });
1386
+
1387
+ }
1388
+
1389
+
1390
+ });
1391
+
1392
+ /* ****************************************************************************
1393
+ * End Box plot series code *
1394
+ *****************************************************************************/
1395
+ /* ****************************************************************************
1396
+ * Start error bar series code *
1397
+ *****************************************************************************/
1398
+
1399
+ // 1 - set default options
1400
+ defaultPlotOptions.errorbar = merge(defaultPlotOptions.boxplot, {
1401
+ color: '#000000',
1402
+ grouping: false,
1403
+ linkedTo: ':previous',
1404
+ tooltip: {
1405
+ pointFormat: defaultPlotOptions.arearange.tooltip.pointFormat
1406
+ },
1407
+ whiskerWidth: null
1408
+ });
1409
+
1410
+ // 2 - Create the series object
1411
+ seriesTypes.errorbar = extendClass(seriesTypes.boxplot, {
1412
+ type: 'errorbar',
1413
+ pointArrayMap: ['low', 'high'], // array point configs are mapped to this
1414
+ toYData: function (point) { // return a plain array for speedy calculation
1415
+ return [point.low, point.high];
1416
+ },
1417
+ pointValKey: 'high', // defines the top of the tracker
1418
+ doQuartiles: false,
1419
+
1420
+ /**
1421
+ * Get the width and X offset, either on top of the linked series column
1422
+ * or standalone
1423
+ */
1424
+ getColumnMetrics: function () {
1425
+ return (this.linkedParent && this.linkedParent.columnMetrics) ||
1426
+ seriesTypes.column.prototype.getColumnMetrics.call(this);
1427
+ }
1428
+ });
1429
+
1430
+ /* ****************************************************************************
1431
+ * End error bar series code *
1432
+ *****************************************************************************/
1433
+ /* ****************************************************************************
1434
+ * Start Waterfall series code *
1435
+ *****************************************************************************/
1436
+
1437
+ // 1 - set default options
1438
+ defaultPlotOptions.waterfall = merge(defaultPlotOptions.column, {
1439
+ lineWidth: 1,
1440
+ lineColor: '#333',
1441
+ dashStyle: 'dot',
1442
+ borderColor: '#333'
1443
+ });
1444
+
1445
+
1446
+ // 2 - Create the series object
1447
+ seriesTypes.waterfall = extendClass(seriesTypes.column, {
1448
+ type: 'waterfall',
1449
+
1450
+ upColorProp: 'fill',
1451
+
1452
+ pointArrayMap: ['low', 'y'],
1453
+
1454
+ pointValKey: 'y',
1455
+
1456
+ /**
1457
+ * Init waterfall series, force stacking
1458
+ */
1459
+ init: function (chart, options) {
1460
+ // force stacking
1461
+ options.stacking = true;
1462
+
1463
+ seriesTypes.column.prototype.init.call(this, chart, options);
1464
+ },
1465
+
1466
+
1467
+ /**
1468
+ * Translate data points from raw values
1469
+ */
1470
+ translate: function () {
1471
+ var series = this,
1472
+ options = series.options,
1473
+ axis = series.yAxis,
1474
+ len,
1475
+ i,
1476
+ points,
1477
+ point,
1478
+ shapeArgs,
1479
+ stack,
1480
+ y,
1481
+ previousY,
1482
+ stackPoint,
1483
+ threshold = options.threshold,
1484
+ crispCorr = (options.borderWidth % 2) / 2;
1485
+
1486
+ // run column series translate
1487
+ seriesTypes.column.prototype.translate.apply(this);
1488
+
1489
+ previousY = threshold;
1490
+ points = series.points;
1491
+
1492
+ for (i = 0, len = points.length; i < len; i++) {
1493
+ // cache current point object
1494
+ point = points[i];
1495
+ shapeArgs = point.shapeArgs;
1496
+
1497
+ // get current stack
1498
+ stack = series.getStack(i);
1499
+ stackPoint = stack.points[series.index];
1500
+
1501
+ // override point value for sums
1502
+ if (isNaN(point.y)) {
1503
+ point.y = series.yData[i];
1504
+ }
1505
+
1506
+ // up points
1507
+ y = mathMax(previousY, previousY + point.y) + stackPoint[0];
1508
+ shapeArgs.y = axis.translate(y, 0, 1);
1509
+
1510
+
1511
+ // sum points
1512
+ if (point.isSum || point.isIntermediateSum) {
1513
+ shapeArgs.y = axis.translate(stackPoint[1], 0, 1);
1514
+ shapeArgs.height = axis.translate(stackPoint[0], 0, 1) - shapeArgs.y;
1515
+
1516
+ // if it's not the sum point, update previous stack end position
1517
+ } else {
1518
+ previousY += stack.total;
1519
+ }
1520
+
1521
+ // negative points
1522
+ if (shapeArgs.height < 0) {
1523
+ shapeArgs.y += shapeArgs.height;
1524
+ shapeArgs.height *= -1;
1525
+ }
1526
+
1527
+ point.plotY = shapeArgs.y = mathRound(shapeArgs.y) - crispCorr;
1528
+ shapeArgs.height = mathRound(shapeArgs.height);
1529
+ point.yBottom = shapeArgs.y + shapeArgs.height;
1530
+ }
1531
+ },
1532
+
1533
+ /**
1534
+ * Call default processData then override yData to reflect waterfall's extremes on yAxis
1535
+ */
1536
+ processData: function (force) {
1537
+ var series = this,
1538
+ options = series.options,
1539
+ yData = series.yData,
1540
+ points = series.points,
1541
+ point,
1542
+ dataLength = yData.length,
1543
+ threshold = options.threshold || 0,
1544
+ subSum,
1545
+ sum,
1546
+ dataMin,
1547
+ dataMax,
1548
+ y,
1549
+ i;
1550
+
1551
+ sum = subSum = dataMin = dataMax = threshold;
1552
+
1553
+ for (i = 0; i < dataLength; i++) {
1554
+ y = yData[i];
1555
+ point = points && points[i] ? points[i] : {};
1556
+
1557
+ if (y === "sum" || point.isSum) {
1558
+ yData[i] = sum;
1559
+ } else if (y === "intermediateSum" || point.isIntermediateSum) {
1560
+ yData[i] = subSum;
1561
+ subSum = threshold;
1562
+ } else {
1563
+ sum += y;
1564
+ subSum += y;
1565
+ }
1566
+ dataMin = Math.min(sum, dataMin);
1567
+ dataMax = Math.max(sum, dataMax);
1568
+ }
1569
+
1570
+ Series.prototype.processData.call(this, force);
1571
+
1572
+ // Record extremes
1573
+ series.dataMin = dataMin;
1574
+ series.dataMax = dataMax;
1575
+ },
1576
+
1577
+ /**
1578
+ * Return y value or string if point is sum
1579
+ */
1580
+ toYData: function (pt) {
1581
+ if (pt.isSum) {
1582
+ return "sum";
1583
+ } else if (pt.isIntermediateSum) {
1584
+ return "intermediateSum";
1585
+ }
1586
+
1587
+ return pt.y;
1588
+ },
1589
+
1590
+ /**
1591
+ * Postprocess mapping between options and SVG attributes
1592
+ */
1593
+ getAttribs: function () {
1594
+ seriesTypes.column.prototype.getAttribs.apply(this, arguments);
1595
+
1596
+ var series = this,
1597
+ options = series.options,
1598
+ stateOptions = options.states,
1599
+ upColor = options.upColor || series.color,
1600
+ hoverColor = Highcharts.Color(upColor).brighten(0.1).get(),
1601
+ seriesDownPointAttr = merge(series.pointAttr),
1602
+ upColorProp = series.upColorProp;
1603
+
1604
+ seriesDownPointAttr[''][upColorProp] = upColor;
1605
+ seriesDownPointAttr.hover[upColorProp] = stateOptions.hover.upColor || hoverColor;
1606
+ seriesDownPointAttr.select[upColorProp] = stateOptions.select.upColor || upColor;
1607
+
1608
+ each(series.points, function (point) {
1609
+ if (point.y > 0 && !point.color) {
1610
+ point.pointAttr = seriesDownPointAttr;
1611
+ point.color = upColor;
1612
+ }
1613
+ });
1614
+ },
1615
+
1616
+ /**
1617
+ * Draw columns' connector lines
1618
+ */
1619
+ getGraphPath: function () {
1620
+
1621
+ var data = this.data,
1622
+ length = data.length,
1623
+ lineWidth = this.options.lineWidth + this.options.borderWidth,
1624
+ normalizer = mathRound(lineWidth) % 2 / 2,
1625
+ path = [],
1626
+ M = 'M',
1627
+ L = 'L',
1628
+ prevArgs,
1629
+ pointArgs,
1630
+ i,
1631
+ d;
1632
+
1633
+ for (i = 1; i < length; i++) {
1634
+ pointArgs = data[i].shapeArgs;
1635
+ prevArgs = data[i - 1].shapeArgs;
1636
+
1637
+ d = [
1638
+ M,
1639
+ prevArgs.x + prevArgs.width, prevArgs.y + normalizer,
1640
+ L,
1641
+ pointArgs.x, prevArgs.y + normalizer
1642
+ ];
1643
+
1644
+ if (data[i - 1].y < 0) {
1645
+ d[2] += prevArgs.height;
1646
+ d[5] += prevArgs.height;
1647
+ }
1648
+
1649
+ path = path.concat(d);
1650
+ }
1651
+
1652
+ return path;
1653
+ },
1654
+
1655
+ /**
1656
+ * Extremes are recorded in processData
1657
+ */
1658
+ getExtremes: noop,
1659
+
1660
+ /**
1661
+ * Return stack for given index
1662
+ */
1663
+ getStack: function (i) {
1664
+ var axis = this.yAxis,
1665
+ stacks = axis.stacks,
1666
+ key = this.stackKey;
1667
+
1668
+ if (this.processedYData[i] < this.options.threshold) {
1669
+ key = '-' + key;
1670
+ }
1671
+
1672
+ return stacks[key][i];
1673
+ },
1674
+
1675
+ drawGraph: Series.prototype.drawGraph
1676
+ });
1677
+
1678
+ /* ****************************************************************************
1679
+ * End Waterfall series code *
1680
+ *****************************************************************************/
1681
+ /* ****************************************************************************
1682
+ * Start Bubble series code *
1683
+ *****************************************************************************/
1684
+
1685
+ // 1 - set default options
1686
+ defaultPlotOptions.bubble = merge(defaultPlotOptions.scatter, {
1687
+ dataLabels: {
1688
+ inside: true,
1689
+ style: {
1690
+ color: 'white',
1691
+ textShadow: '0px 0px 3px black'
1692
+ },
1693
+ verticalAlign: 'middle'
1694
+ },
1695
+ // displayNegative: true,
1696
+ marker: {
1697
+ // fillOpacity: 0.5,
1698
+ lineColor: null, // inherit from series.color
1699
+ lineWidth: 1
1700
+ },
1701
+ minSize: 8,
1702
+ maxSize: '20%',
1703
+ // negativeColor: null,
1704
+ tooltip: {
1705
+ pointFormat: '({point.x}, {point.y}), Size: {point.z}'
1706
+ },
1707
+ turboThreshold: 0,
1708
+ zThreshold: 0
1709
+ });
1710
+
1711
+ // 2 - Create the series object
1712
+ seriesTypes.bubble = extendClass(seriesTypes.scatter, {
1713
+ type: 'bubble',
1714
+ pointArrayMap: ['y', 'z'],
1715
+ trackerGroups: ['group', 'dataLabelsGroup'],
1716
+
1717
+ /**
1718
+ * Mapping between SVG attributes and the corresponding options
1719
+ */
1720
+ pointAttrToOptions: {
1721
+ stroke: 'lineColor',
1722
+ 'stroke-width': 'lineWidth',
1723
+ fill: 'fillColor'
1724
+ },
1725
+
1726
+ /**
1727
+ * Apply the fillOpacity to all fill positions
1728
+ */
1729
+ applyOpacity: function (fill) {
1730
+ var markerOptions = this.options.marker,
1731
+ fillOpacity = pick(markerOptions.fillOpacity, 0.5);
1732
+
1733
+ // When called from Legend.colorizeItem, the fill isn't predefined
1734
+ fill = fill || markerOptions.fillColor || this.color;
1735
+
1736
+ if (fillOpacity !== 1) {
1737
+ fill = Highcharts.Color(fill).setOpacity(fillOpacity).get('rgba');
1738
+ }
1739
+ return fill;
1740
+ },
1741
+
1742
+ /**
1743
+ * Extend the convertAttribs method by applying opacity to the fill
1744
+ */
1745
+ convertAttribs: function () {
1746
+ var obj = Series.prototype.convertAttribs.apply(this, arguments);
1747
+
1748
+ obj.fill = this.applyOpacity(obj.fill);
1749
+
1750
+ return obj;
1751
+ },
1752
+
1753
+ /**
1754
+ * Get the radius for each point based on the minSize, maxSize and each point's Z value. This
1755
+ * must be done prior to Series.translate because the axis needs to add padding in
1756
+ * accordance with the point sizes.
1757
+ */
1758
+ getRadii: function (zMin, zMax, minSize, maxSize) {
1759
+ var len,
1760
+ i,
1761
+ pos,
1762
+ zData = this.zData,
1763
+ radii = [],
1764
+ zRange;
1765
+
1766
+ // Set the shape type and arguments to be picked up in drawPoints
1767
+ for (i = 0, len = zData.length; i < len; i++) {
1768
+ zRange = zMax - zMin;
1769
+ pos = zRange > 0 ? // relative size, a number between 0 and 1
1770
+ (zData[i] - zMin) / (zMax - zMin) :
1771
+ 0.5;
1772
+ radii.push(math.ceil(minSize + pos * (maxSize - minSize)) / 2);
1773
+ }
1774
+ this.radii = radii;
1775
+ },
1776
+
1777
+ /**
1778
+ * Perform animation on the bubbles
1779
+ */
1780
+ animate: function (init) {
1781
+ var animation = this.options.animation;
1782
+
1783
+ if (!init) { // run the animation
1784
+ each(this.points, function (point) {
1785
+ var graphic = point.graphic,
1786
+ shapeArgs = point.shapeArgs;
1787
+
1788
+ if (graphic && shapeArgs) {
1789
+ // start values
1790
+ graphic.attr('r', 1);
1791
+
1792
+ // animate
1793
+ graphic.animate({
1794
+ r: shapeArgs.r
1795
+ }, animation);
1796
+ }
1797
+ });
1798
+
1799
+ // delete this function to allow it only once
1800
+ this.animate = null;
1801
+ }
1802
+ },
1803
+
1804
+ /**
1805
+ * Extend the base translate method to handle bubble size
1806
+ */
1807
+ translate: function () {
1808
+
1809
+ var i,
1810
+ data = this.data,
1811
+ point,
1812
+ radius,
1813
+ radii = this.radii;
1814
+
1815
+ // Run the parent method
1816
+ seriesTypes.scatter.prototype.translate.call(this);
1817
+
1818
+ // Set the shape type and arguments to be picked up in drawPoints
1819
+ i = data.length;
1820
+
1821
+ while (i--) {
1822
+ point = data[i];
1823
+ radius = radii ? radii[i] : 0; // #1737
1824
+
1825
+ // Flag for negativeColor to be applied in Series.js
1826
+ point.negative = point.z < (this.options.zThreshold || 0);
1827
+
1828
+ if (radius >= this.minPxSize / 2) {
1829
+ // Shape arguments
1830
+ point.shapeType = 'circle';
1831
+ point.shapeArgs = {
1832
+ x: point.plotX,
1833
+ y: point.plotY,
1834
+ r: radius
1835
+ };
1836
+
1837
+ // Alignment box for the data label
1838
+ point.dlBox = {
1839
+ x: point.plotX - radius,
1840
+ y: point.plotY - radius,
1841
+ width: 2 * radius,
1842
+ height: 2 * radius
1843
+ };
1844
+ } else { // below zThreshold
1845
+ point.shapeArgs = point.plotY = point.dlBox = UNDEFINED; // #1691
1846
+ }
1847
+ }
1848
+ },
1849
+
1850
+ /**
1851
+ * Get the series' symbol in the legend
1852
+ *
1853
+ * @param {Object} legend The legend object
1854
+ * @param {Object} item The series (this) or point
1855
+ */
1856
+ drawLegendSymbol: function (legend, item) {
1857
+ var radius = pInt(legend.itemStyle.fontSize) / 2;
1858
+
1859
+ item.legendSymbol = this.chart.renderer.circle(
1860
+ radius,
1861
+ legend.baseline - radius,
1862
+ radius
1863
+ ).attr({
1864
+ zIndex: 3
1865
+ }).add(item.legendGroup);
1866
+ item.legendSymbol.isMarker = true;
1867
+
1868
+ },
1869
+
1870
+ drawPoints: seriesTypes.column.prototype.drawPoints,
1871
+ alignDataLabel: seriesTypes.column.prototype.alignDataLabel
1872
+ });
1873
+
1874
+ /**
1875
+ * Add logic to pad each axis with the amount of pixels
1876
+ * necessary to avoid the bubbles to overflow.
1877
+ */
1878
+ Axis.prototype.beforePadding = function () {
1879
+ var axis = this,
1880
+ axisLength = this.len,
1881
+ chart = this.chart,
1882
+ pxMin = 0,
1883
+ pxMax = axisLength,
1884
+ isXAxis = this.isXAxis,
1885
+ dataKey = isXAxis ? 'xData' : 'yData',
1886
+ min = this.min,
1887
+ extremes = {},
1888
+ smallestSize = math.min(chart.plotWidth, chart.plotHeight),
1889
+ zMin = Number.MAX_VALUE,
1890
+ zMax = -Number.MAX_VALUE,
1891
+ range = this.max - min,
1892
+ transA = axisLength / range,
1893
+ activeSeries = [];
1894
+
1895
+ // Handle padding on the second pass, or on redraw
1896
+ if (this.tickPositions) {
1897
+ each(this.series, function (series) {
1898
+
1899
+ var seriesOptions = series.options,
1900
+ zData;
1901
+
1902
+ if (series.type === 'bubble' && series.visible) {
1903
+
1904
+ // Correction for #1673
1905
+ axis.allowZoomOutside = true;
1906
+
1907
+ // Cache it
1908
+ activeSeries.push(series);
1909
+
1910
+ if (isXAxis) { // because X axis is evaluated first
1911
+
1912
+ // For each series, translate the size extremes to pixel values
1913
+ each(['minSize', 'maxSize'], function (prop) {
1914
+ var length = seriesOptions[prop],
1915
+ isPercent = /%$/.test(length);
1916
+
1917
+ length = pInt(length);
1918
+ extremes[prop] = isPercent ?
1919
+ smallestSize * length / 100 :
1920
+ length;
1921
+
1922
+ });
1923
+ series.minPxSize = extremes.minSize;
1924
+
1925
+ // Find the min and max Z
1926
+ zData = series.zData;
1927
+ if (zData.length) { // #1735
1928
+ zMin = math.min(
1929
+ zMin,
1930
+ math.max(
1931
+ arrayMin(zData),
1932
+ seriesOptions.displayNegative === false ? seriesOptions.zThreshold : -Number.MAX_VALUE
1933
+ )
1934
+ );
1935
+ zMax = math.max(zMax, arrayMax(zData));
1936
+ }
1937
+ }
1938
+ }
1939
+ });
1940
+
1941
+ each(activeSeries, function (series) {
1942
+
1943
+ var data = series[dataKey],
1944
+ i = data.length,
1945
+ radius;
1946
+
1947
+ if (isXAxis) {
1948
+ series.getRadii(zMin, zMax, extremes.minSize, extremes.maxSize);
1949
+ }
1950
+
1951
+ if (range > 0) {
1952
+ while (i--) {
1953
+ radius = series.radii[i];
1954
+ pxMin = Math.min(((data[i] - min) * transA) - radius, pxMin);
1955
+ pxMax = Math.max(((data[i] - min) * transA) + radius, pxMax);
1956
+ }
1957
+ }
1958
+ });
1959
+
1960
+ if (activeSeries.length && range > 0 && pick(this.options.min, this.userMin) === UNDEFINED && pick(this.options.max, this.userMax) === UNDEFINED) {
1961
+ pxMax -= axisLength;
1962
+ transA *= (axisLength + pxMin - pxMax) / axisLength;
1963
+ this.min += pxMin / transA;
1964
+ this.max += pxMax / transA;
1965
+ }
1966
+ }
1967
+ };
1968
+
1969
+ /* ****************************************************************************
1970
+ * End Bubble series code *
1971
+ *****************************************************************************/
1972
+ /**
1973
+ * Extensions for polar charts. Additionally, much of the geometry required for polar charts is
1974
+ * gathered in RadialAxes.js.
1975
+ *
1976
+ */
1977
+
1978
+ var seriesProto = Series.prototype,
1979
+ pointerProto = Highcharts.Pointer.prototype;
1980
+
1981
+
1982
+
1983
+ /**
1984
+ * Translate a point's plotX and plotY from the internal angle and radius measures to
1985
+ * true plotX, plotY coordinates
1986
+ */
1987
+ seriesProto.toXY = function (point) {
1988
+ var xy,
1989
+ chart = this.chart,
1990
+ plotX = point.plotX,
1991
+ plotY = point.plotY;
1992
+
1993
+ // Save rectangular plotX, plotY for later computation
1994
+ point.rectPlotX = plotX;
1995
+ point.rectPlotY = plotY;
1996
+
1997
+ // Record the angle in degrees for use in tooltip
1998
+ point.clientX = ((plotX / Math.PI * 180) + this.xAxis.pane.options.startAngle) % 360;
1999
+
2000
+ // Find the polar plotX and plotY
2001
+ xy = this.xAxis.postTranslate(point.plotX, this.yAxis.len - plotY);
2002
+ point.plotX = point.polarPlotX = xy.x - chart.plotLeft;
2003
+ point.plotY = point.polarPlotY = xy.y - chart.plotTop;
2004
+ };
2005
+
2006
+ /**
2007
+ * Order the tooltip points to get the mouse capture ranges correct. #1915.
2008
+ */
2009
+ seriesProto.orderTooltipPoints = function (points) {
2010
+ if (this.chart.polar) {
2011
+ points.sort(function (a, b) {
2012
+ return a.clientX - b.clientX;
2013
+ });
2014
+
2015
+ // Wrap mouse tracking around to capture movement on the segment to the left
2016
+ // of the north point (#1469, #2093).
2017
+ if (points[0]) {
2018
+ points[0].wrappedClientX = points[0].clientX + 360;
2019
+ points.push(points[0]);
2020
+ }
2021
+ }
2022
+ };
2023
+
2024
+
2025
+ /**
2026
+ * Add some special init logic to areas and areasplines
2027
+ */
2028
+ function initArea(proceed, chart, options) {
2029
+ proceed.call(this, chart, options);
2030
+ if (this.chart.polar) {
2031
+
2032
+ /**
2033
+ * Overridden method to close a segment path. While in a cartesian plane the area
2034
+ * goes down to the threshold, in the polar chart it goes to the center.
2035
+ */
2036
+ this.closeSegment = function (path) {
2037
+ var center = this.xAxis.center;
2038
+ path.push(
2039
+ 'L',
2040
+ center[0],
2041
+ center[1]
2042
+ );
2043
+ };
2044
+
2045
+ // Instead of complicated logic to draw an area around the inner area in a stack,
2046
+ // just draw it behind
2047
+ this.closedStacks = true;
2048
+ }
2049
+ }
2050
+ wrap(seriesTypes.area.prototype, 'init', initArea);
2051
+ wrap(seriesTypes.areaspline.prototype, 'init', initArea);
2052
+
2053
+
2054
+ /**
2055
+ * Overridden method for calculating a spline from one point to the next
2056
+ */
2057
+ wrap(seriesTypes.spline.prototype, 'getPointSpline', function (proceed, segment, point, i) {
2058
+
2059
+ var ret,
2060
+ smoothing = 1.5, // 1 means control points midway between points, 2 means 1/3 from the point, 3 is 1/4 etc;
2061
+ denom = smoothing + 1,
2062
+ plotX,
2063
+ plotY,
2064
+ lastPoint,
2065
+ nextPoint,
2066
+ lastX,
2067
+ lastY,
2068
+ nextX,
2069
+ nextY,
2070
+ leftContX,
2071
+ leftContY,
2072
+ rightContX,
2073
+ rightContY,
2074
+ distanceLeftControlPoint,
2075
+ distanceRightControlPoint,
2076
+ leftContAngle,
2077
+ rightContAngle,
2078
+ jointAngle;
2079
+
2080
+
2081
+ if (this.chart.polar) {
2082
+
2083
+ plotX = point.plotX;
2084
+ plotY = point.plotY;
2085
+ lastPoint = segment[i - 1];
2086
+ nextPoint = segment[i + 1];
2087
+
2088
+ // Connect ends
2089
+ if (this.connectEnds) {
2090
+ if (!lastPoint) {
2091
+ lastPoint = segment[segment.length - 2]; // not the last but the second last, because the segment is already connected
2092
+ }
2093
+ if (!nextPoint) {
2094
+ nextPoint = segment[1];
2095
+ }
2096
+ }
2097
+
2098
+ // find control points
2099
+ if (lastPoint && nextPoint) {
2100
+
2101
+ lastX = lastPoint.plotX;
2102
+ lastY = lastPoint.plotY;
2103
+ nextX = nextPoint.plotX;
2104
+ nextY = nextPoint.plotY;
2105
+ leftContX = (smoothing * plotX + lastX) / denom;
2106
+ leftContY = (smoothing * plotY + lastY) / denom;
2107
+ rightContX = (smoothing * plotX + nextX) / denom;
2108
+ rightContY = (smoothing * plotY + nextY) / denom;
2109
+ distanceLeftControlPoint = Math.sqrt(Math.pow(leftContX - plotX, 2) + Math.pow(leftContY - plotY, 2));
2110
+ distanceRightControlPoint = Math.sqrt(Math.pow(rightContX - plotX, 2) + Math.pow(rightContY - plotY, 2));
2111
+ leftContAngle = Math.atan2(leftContY - plotY, leftContX - plotX);
2112
+ rightContAngle = Math.atan2(rightContY - plotY, rightContX - plotX);
2113
+ jointAngle = (Math.PI / 2) + ((leftContAngle + rightContAngle) / 2);
2114
+
2115
+
2116
+ // Ensure the right direction, jointAngle should be in the same quadrant as leftContAngle
2117
+ if (Math.abs(leftContAngle - jointAngle) > Math.PI / 2) {
2118
+ jointAngle -= Math.PI;
2119
+ }
2120
+
2121
+ // Find the corrected control points for a spline straight through the point
2122
+ leftContX = plotX + Math.cos(jointAngle) * distanceLeftControlPoint;
2123
+ leftContY = plotY + Math.sin(jointAngle) * distanceLeftControlPoint;
2124
+ rightContX = plotX + Math.cos(Math.PI + jointAngle) * distanceRightControlPoint;
2125
+ rightContY = plotY + Math.sin(Math.PI + jointAngle) * distanceRightControlPoint;
2126
+
2127
+ // Record for drawing in next point
2128
+ point.rightContX = rightContX;
2129
+ point.rightContY = rightContY;
2130
+
2131
+ }
2132
+
2133
+
2134
+ // moveTo or lineTo
2135
+ if (!i) {
2136
+ ret = ['M', plotX, plotY];
2137
+ } else { // curve from last point to this
2138
+ ret = [
2139
+ 'C',
2140
+ lastPoint.rightContX || lastPoint.plotX,
2141
+ lastPoint.rightContY || lastPoint.plotY,
2142
+ leftContX || plotX,
2143
+ leftContY || plotY,
2144
+ plotX,
2145
+ plotY
2146
+ ];
2147
+ lastPoint.rightContX = lastPoint.rightContY = null; // reset for updating series later
2148
+ }
2149
+
2150
+
2151
+ } else {
2152
+ ret = proceed.call(this, segment, point, i);
2153
+ }
2154
+ return ret;
2155
+ });
2156
+
2157
+ /**
2158
+ * Extend translate. The plotX and plotY values are computed as if the polar chart were a
2159
+ * cartesian plane, where plotX denotes the angle in radians and (yAxis.len - plotY) is the pixel distance from
2160
+ * center.
2161
+ */
2162
+ wrap(seriesProto, 'translate', function (proceed) {
2163
+
2164
+ // Run uber method
2165
+ proceed.call(this);
2166
+
2167
+ // Postprocess plot coordinates
2168
+ if (this.chart.polar && !this.preventPostTranslate) {
2169
+ var points = this.points,
2170
+ i = points.length;
2171
+ while (i--) {
2172
+ // Translate plotX, plotY from angle and radius to true plot coordinates
2173
+ this.toXY(points[i]);
2174
+ }
2175
+ }
2176
+ });
2177
+
2178
+ /**
2179
+ * Extend getSegmentPath to allow connecting ends across 0 to provide a closed circle in
2180
+ * line-like series.
2181
+ */
2182
+ wrap(seriesProto, 'getSegmentPath', function (proceed, segment) {
2183
+
2184
+ var points = this.points;
2185
+
2186
+ // Connect the path
2187
+ if (this.chart.polar && this.options.connectEnds !== false &&
2188
+ segment[segment.length - 1] === points[points.length - 1] && points[0].y !== null) {
2189
+ this.connectEnds = true; // re-used in splines
2190
+ segment = [].concat(segment, [points[0]]);
2191
+ }
2192
+
2193
+ // Run uber method
2194
+ return proceed.call(this, segment);
2195
+
2196
+ });
2197
+
2198
+
2199
+ function polarAnimate(proceed, init) {
2200
+ var chart = this.chart,
2201
+ animation = this.options.animation,
2202
+ group = this.group,
2203
+ markerGroup = this.markerGroup,
2204
+ center = this.xAxis.center,
2205
+ plotLeft = chart.plotLeft,
2206
+ plotTop = chart.plotTop,
2207
+ attribs;
2208
+
2209
+ // Specific animation for polar charts
2210
+ if (chart.polar) {
2211
+
2212
+ // Enable animation on polar charts only in SVG. In VML, the scaling is different, plus animation
2213
+ // would be so slow it would't matter.
2214
+ if (chart.renderer.isSVG) {
2215
+
2216
+ if (animation === true) {
2217
+ animation = {};
2218
+ }
2219
+
2220
+ // Initialize the animation
2221
+ if (init) {
2222
+
2223
+ // Scale down the group and place it in the center
2224
+ attribs = {
2225
+ translateX: center[0] + plotLeft,
2226
+ translateY: center[1] + plotTop,
2227
+ scaleX: 0.001, // #1499
2228
+ scaleY: 0.001
2229
+ };
2230
+
2231
+ group.attr(attribs);
2232
+ if (markerGroup) {
2233
+ markerGroup.attrSetters = group.attrSetters;
2234
+ markerGroup.attr(attribs);
2235
+ }
2236
+
2237
+ // Run the animation
2238
+ } else {
2239
+ attribs = {
2240
+ translateX: plotLeft,
2241
+ translateY: plotTop,
2242
+ scaleX: 1,
2243
+ scaleY: 1
2244
+ };
2245
+ group.animate(attribs, animation);
2246
+ if (markerGroup) {
2247
+ markerGroup.animate(attribs, animation);
2248
+ }
2249
+
2250
+ // Delete this function to allow it only once
2251
+ this.animate = null;
2252
+ }
2253
+ }
2254
+
2255
+ // For non-polar charts, revert to the basic animation
2256
+ } else {
2257
+ proceed.call(this, init);
2258
+ }
2259
+ }
2260
+
2261
+ // Define the animate method for both regular series and column series and their derivatives
2262
+ wrap(seriesProto, 'animate', polarAnimate);
2263
+ wrap(colProto, 'animate', polarAnimate);
2264
+
2265
+
2266
+ /**
2267
+ * Throw in a couple of properties to let setTooltipPoints know we're indexing the points
2268
+ * in degrees (0-360), not plot pixel width.
2269
+ */
2270
+ wrap(seriesProto, 'setTooltipPoints', function (proceed, renew) {
2271
+
2272
+ if (this.chart.polar) {
2273
+ extend(this.xAxis, {
2274
+ tooltipLen: 360 // degrees are the resolution unit of the tooltipPoints array
2275
+ });
2276
+ }
2277
+
2278
+ // Run uber method
2279
+ return proceed.call(this, renew);
2280
+ });
2281
+
2282
+
2283
+ /**
2284
+ * Extend the column prototype's translate method
2285
+ */
2286
+ wrap(colProto, 'translate', function (proceed) {
2287
+
2288
+ var xAxis = this.xAxis,
2289
+ len = this.yAxis.len,
2290
+ center = xAxis.center,
2291
+ startAngleRad = xAxis.startAngleRad,
2292
+ renderer = this.chart.renderer,
2293
+ start,
2294
+ points,
2295
+ point,
2296
+ i;
2297
+
2298
+ this.preventPostTranslate = true;
2299
+
2300
+ // Run uber method
2301
+ proceed.call(this);
2302
+
2303
+ // Postprocess plot coordinates
2304
+ if (xAxis.isRadial) {
2305
+ points = this.points;
2306
+ i = points.length;
2307
+ while (i--) {
2308
+ point = points[i];
2309
+ start = point.barX + startAngleRad;
2310
+ point.shapeType = 'path';
2311
+ point.shapeArgs = {
2312
+ d: renderer.symbols.arc(
2313
+ center[0],
2314
+ center[1],
2315
+ len - point.plotY,
2316
+ null,
2317
+ {
2318
+ start: start,
2319
+ end: start + point.pointWidth,
2320
+ innerR: len - pick(point.yBottom, len)
2321
+ }
2322
+ )
2323
+ };
2324
+ this.toXY(point); // provide correct plotX, plotY for tooltip
2325
+ }
2326
+ }
2327
+ });
2328
+
2329
+
2330
+ /**
2331
+ * Align column data labels outside the columns. #1199.
2332
+ */
2333
+ wrap(colProto, 'alignDataLabel', function (proceed, point, dataLabel, options, alignTo, isNew) {
2334
+
2335
+ if (this.chart.polar) {
2336
+ var angle = point.rectPlotX / Math.PI * 180,
2337
+ align,
2338
+ verticalAlign;
2339
+
2340
+ // Align nicely outside the perimeter of the columns
2341
+ if (options.align === null) {
2342
+ if (angle > 20 && angle < 160) {
2343
+ align = 'left'; // right hemisphere
2344
+ } else if (angle > 200 && angle < 340) {
2345
+ align = 'right'; // left hemisphere
2346
+ } else {
2347
+ align = 'center'; // top or bottom
2348
+ }
2349
+ options.align = align;
2350
+ }
2351
+ if (options.verticalAlign === null) {
2352
+ if (angle < 45 || angle > 315) {
2353
+ verticalAlign = 'bottom'; // top part
2354
+ } else if (angle > 135 && angle < 225) {
2355
+ verticalAlign = 'top'; // bottom part
2356
+ } else {
2357
+ verticalAlign = 'middle'; // left or right
2358
+ }
2359
+ options.verticalAlign = verticalAlign;
2360
+ }
2361
+
2362
+ seriesProto.alignDataLabel.call(this, point, dataLabel, options, alignTo, isNew);
2363
+ } else {
2364
+ proceed.call(this, point, dataLabel, options, alignTo, isNew);
2365
+ }
2366
+
2367
+ });
2368
+
2369
+ /**
2370
+ * Extend the mouse tracker to return the tooltip position index in terms of
2371
+ * degrees rather than pixels
2372
+ */
2373
+ wrap(pointerProto, 'getIndex', function (proceed, e) {
2374
+ var ret,
2375
+ chart = this.chart,
2376
+ center,
2377
+ x,
2378
+ y;
2379
+
2380
+ if (chart.polar) {
2381
+ center = chart.xAxis[0].center;
2382
+ x = e.chartX - center[0] - chart.plotLeft;
2383
+ y = e.chartY - center[1] - chart.plotTop;
2384
+
2385
+ ret = 180 - Math.round(Math.atan2(x, y) / Math.PI * 180);
2386
+
2387
+ } else {
2388
+
2389
+ // Run uber method
2390
+ ret = proceed.call(this, e);
2391
+ }
2392
+ return ret;
2393
+ });
2394
+
2395
+ /**
2396
+ * Extend getCoordinates to prepare for polar axis values
2397
+ */
2398
+ wrap(pointerProto, 'getCoordinates', function (proceed, e) {
2399
+ var chart = this.chart,
2400
+ ret = {
2401
+ xAxis: [],
2402
+ yAxis: []
2403
+ };
2404
+
2405
+ if (chart.polar) {
2406
+
2407
+ each(chart.axes, function (axis) {
2408
+ var isXAxis = axis.isXAxis,
2409
+ center = axis.center,
2410
+ x = e.chartX - center[0] - chart.plotLeft,
2411
+ y = e.chartY - center[1] - chart.plotTop;
2412
+
2413
+ ret[isXAxis ? 'xAxis' : 'yAxis'].push({
2414
+ axis: axis,
2415
+ value: axis.translate(
2416
+ isXAxis ?
2417
+ Math.PI - Math.atan2(x, y) : // angle
2418
+ Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2)), // distance from center
2419
+ true
2420
+ )
2421
+ });
2422
+ });
2423
+
2424
+ } else {
2425
+ ret = proceed.call(this, e);
2426
+ }
2427
+
2428
+ return ret;
2429
+ });
2430
+ }(Highcharts));