repsheet_visualizer 0.2.2 → 0.2.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (298) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile.lock +1 -1
  3. data/lib/repsheet_visualizer/application/app.rb +2 -2
  4. data/lib/repsheet_visualizer/application/public/javascripts/application.js +0 -4
  5. data/lib/repsheet_visualizer/application/views/activity.erb +5 -0
  6. data/lib/repsheet_visualizer/application/views/actors.erb +5 -0
  7. data/lib/repsheet_visualizer/application/views/breakdown.erb +5 -0
  8. data/lib/repsheet_visualizer/application/views/whitelist.erb +5 -0
  9. data/lib/repsheet_visualizer/application/views/worldview.erb +5 -0
  10. data/lib/repsheet_visualizer/version.rb +1 -1
  11. metadata +2 -289
  12. data/redesign/actor.html +0 -228
  13. data/redesign/chart-flot.html +0 -698
  14. data/redesign/chart-morris.html +0 -528
  15. data/redesign/chart-sparkline.html +0 -702
  16. data/redesign/css/App.css +0 -3436
  17. data/redesign/css/Login.css +0 -88
  18. data/redesign/css/bootstrap.min.css +0 -9
  19. data/redesign/css/custom.css +0 -0
  20. data/redesign/css/font-awesome.min.css +0 -395
  21. data/redesign/fonts/FontAwesome.otf +0 -0
  22. data/redesign/fonts/fontawesome-webfont.eot +0 -0
  23. data/redesign/fonts/fontawesome-webfont.svg +0 -414
  24. data/redesign/fonts/fontawesome-webfont.ttf +0 -0
  25. data/redesign/fonts/fontawesome-webfont.woff +0 -0
  26. data/redesign/fonts/glyphicons-halflings-regular.eot +0 -0
  27. data/redesign/fonts/glyphicons-halflings-regular.svg +0 -228
  28. data/redesign/fonts/glyphicons-halflings-regular.ttf +0 -0
  29. data/redesign/fonts/glyphicons-halflings-regular.woff +0 -0
  30. data/redesign/form-extended.html +0 -1052
  31. data/redesign/form-regular.html +0 -863
  32. data/redesign/form-validation.html +0 -678
  33. data/redesign/img/avatars/avatar-1.jpg +0 -0
  34. data/redesign/img/avatars/avatar-2.jpg +0 -0
  35. data/redesign/img/avatars/avatar-large-1.jpg +0 -0
  36. data/redesign/img/avatars/avatar-large-2.jpg +0 -0
  37. data/redesign/img/gallery/zoom.png +0 -0
  38. data/redesign/img/jquery/handle-vertical.png +0 -0
  39. data/redesign/img/jquery/handle.png +0 -0
  40. data/redesign/img/layout/sidebar-bg.png +0 -0
  41. data/redesign/img/loaders/ajax-loader.gif +0 -0
  42. data/redesign/img/logos/logo-login.png +0 -0
  43. data/redesign/img/logos/logo.png +0 -0
  44. data/redesign/img/mockup.png +0 -0
  45. data/redesign/img/photos/blur-lg.jpg +0 -0
  46. data/redesign/img/photos/blur-sm.jpg +0 -0
  47. data/redesign/img/photos/clock-lg.jpg +0 -0
  48. data/redesign/img/photos/clock-sm.jpg +0 -0
  49. data/redesign/img/photos/lens-lg.jpg +0 -0
  50. data/redesign/img/photos/lens-sm.jpg +0 -0
  51. data/redesign/img/photos/map.png +0 -0
  52. data/redesign/img/photos/rust-lg.jpg +0 -0
  53. data/redesign/img/photos/rust-sm.jpg +0 -0
  54. data/redesign/img/pricing/label-editable.png +0 -0
  55. data/redesign/img/pricing/label-red.png +0 -0
  56. data/redesign/img/pricing/label-yellow.png +0 -0
  57. data/redesign/index.html +0 -328
  58. data/redesign/js/App.js +0 -372
  59. data/redesign/js/Login.js +0 -17
  60. data/redesign/js/demos/buttons.js +0 -7
  61. data/redesign/js/demos/calendar.js +0 -142
  62. data/redesign/js/demos/charts/flot/area.js +0 -73
  63. data/redesign/js/demos/charts/flot/chart1.js +0 -77
  64. data/redesign/js/demos/charts/flot/chart2.js +0 -70
  65. data/redesign/js/demos/charts/flot/chart3.js +0 -71
  66. data/redesign/js/demos/charts/flot/chart4.js +0 -69
  67. data/redesign/js/demos/charts/flot/donut.js +0 -49
  68. data/redesign/js/demos/charts/flot/horizontal.js +0 -56
  69. data/redesign/js/demos/charts/flot/line.js +0 -76
  70. data/redesign/js/demos/charts/flot/pie.js +0 -50
  71. data/redesign/js/demos/charts/flot/scatter.js +0 -62
  72. data/redesign/js/demos/charts/flot/stacked-area.js +0 -86
  73. data/redesign/js/demos/charts/flot/stacked-horizontal.js +0 -60
  74. data/redesign/js/demos/charts/flot/stacked-vertical.js +0 -75
  75. data/redesign/js/demos/charts/flot/vertical.js +0 -70
  76. data/redesign/js/demos/charts/morris/area.js +0 -28
  77. data/redesign/js/demos/charts/morris/bar.js +0 -29
  78. data/redesign/js/demos/charts/morris/donut.js +0 -26
  79. data/redesign/js/demos/charts/morris/line.js +0 -30
  80. data/redesign/js/demos/dashboard.js +0 -26
  81. data/redesign/js/demos/form-extended.js +0 -61
  82. data/redesign/js/demos/popups.js +0 -16
  83. data/redesign/js/demos/pricing.js +0 -10
  84. data/redesign/js/demos/sliders.js +0 -77
  85. data/redesign/js/libs/bootstrap.js +0 -1999
  86. data/redesign/js/libs/bootstrap.min.js +0 -6
  87. data/redesign/js/libs/css/ui-lightness/images/ui-bg_diagonals-thick_18_b81900_40x40.png +0 -0
  88. data/redesign/js/libs/css/ui-lightness/images/ui-bg_diagonals-thick_20_666666_40x40.png +0 -0
  89. data/redesign/js/libs/css/ui-lightness/images/ui-bg_flat_10_000000_40x100.png +0 -0
  90. data/redesign/js/libs/css/ui-lightness/images/ui-bg_glass_100_f6f6f6_1x400.png +0 -0
  91. data/redesign/js/libs/css/ui-lightness/images/ui-bg_glass_100_fdf5ce_1x400.png +0 -0
  92. data/redesign/js/libs/css/ui-lightness/images/ui-bg_glass_65_ffffff_1x400.png +0 -0
  93. data/redesign/js/libs/css/ui-lightness/images/ui-bg_gloss-wave_35_f6a828_500x100.png +0 -0
  94. data/redesign/js/libs/css/ui-lightness/images/ui-bg_highlight-soft_100_eeeeee_1x100.png +0 -0
  95. data/redesign/js/libs/css/ui-lightness/images/ui-bg_highlight-soft_75_ffe45c_1x100.png +0 -0
  96. data/redesign/js/libs/css/ui-lightness/images/ui-icons_222222_256x240.png +0 -0
  97. data/redesign/js/libs/css/ui-lightness/images/ui-icons_228ef1_256x240.png +0 -0
  98. data/redesign/js/libs/css/ui-lightness/images/ui-icons_ef8c08_256x240.png +0 -0
  99. data/redesign/js/libs/css/ui-lightness/images/ui-icons_ffd27a_256x240.png +0 -0
  100. data/redesign/js/libs/css/ui-lightness/images/ui-icons_ffffff_256x240.png +0 -0
  101. data/redesign/js/libs/css/ui-lightness/jquery-ui-1.9.2.custom.css +0 -294
  102. data/redesign/js/libs/css/ui-lightness/jquery-ui-1.9.2.custom.min.css +0 -7
  103. data/redesign/js/libs/jquery-1.9.1.min.js +0 -5
  104. data/redesign/js/libs/jquery-ui-1.9.2.custom.min.js +0 -6
  105. data/redesign/js/libs/jquery.min.map +0 -1
  106. data/redesign/js/libs/raphael-2.1.2.min.js +0 -11
  107. data/redesign/js/plugins/autosize/jquery.autosize.min.js +0 -7
  108. data/redesign/js/plugins/datatables/DT_bootstrap.js +0 -148
  109. data/redesign/js/plugins/datatables/img/Sorting icons.psd +0 -0
  110. data/redesign/js/plugins/datatables/img/back_disabled.png +0 -0
  111. data/redesign/js/plugins/datatables/img/back_enabled.png +0 -0
  112. data/redesign/js/plugins/datatables/img/back_enabled_hover.png +0 -0
  113. data/redesign/js/plugins/datatables/img/datatable-row-openclose.png +0 -0
  114. data/redesign/js/plugins/datatables/img/favicon.ico +0 -0
  115. data/redesign/js/plugins/datatables/img/forward_disabled.png +0 -0
  116. data/redesign/js/plugins/datatables/img/forward_enabled.png +0 -0
  117. data/redesign/js/plugins/datatables/img/forward_enabled_hover.png +0 -0
  118. data/redesign/js/plugins/datatables/img/sort_asc.png +0 -0
  119. data/redesign/js/plugins/datatables/img/sort_asc_disabled.png +0 -0
  120. data/redesign/js/plugins/datatables/img/sort_both.png +0 -0
  121. data/redesign/js/plugins/datatables/img/sort_desc.png +0 -0
  122. data/redesign/js/plugins/datatables/img/sort_desc_disabled.png +0 -0
  123. data/redesign/js/plugins/datatables/jquery.dataTables.min.js +0 -155
  124. data/redesign/js/plugins/datepicker/bootstrap-datepicker.js +0 -1258
  125. data/redesign/js/plugins/datepicker/datepicker.css +0 -481
  126. data/redesign/js/plugins/datepicker/less/datepicker.less +0 -122
  127. data/redesign/js/plugins/fileupload/bootstrap-fileupload.css +0 -132
  128. data/redesign/js/plugins/fileupload/bootstrap-fileupload.js +0 -169
  129. data/redesign/js/plugins/fileupload/bootstrap-fileupload.min.css +0 -31
  130. data/redesign/js/plugins/fileupload/bootstrap-fileupload.min.js +0 -7
  131. data/redesign/js/plugins/flot/jquery.flot.js +0 -2599
  132. data/redesign/js/plugins/flot/jquery.flot.orderBars.js +0 -186
  133. data/redesign/js/plugins/flot/jquery.flot.pie.js +0 -750
  134. data/redesign/js/plugins/flot/jquery.flot.resize.js +0 -57
  135. data/redesign/js/plugins/flot/jquery.flot.stack.js +0 -184
  136. data/redesign/js/plugins/flot/jquery.flot.tooltip.min.js +0 -14
  137. data/redesign/js/plugins/fullcalendar/fullcalendar.css +0 -589
  138. data/redesign/js/plugins/fullcalendar/fullcalendar.js +0 -6110
  139. data/redesign/js/plugins/fullcalendar/fullcalendar.min.js +0 -7
  140. data/redesign/js/plugins/fullcalendar/fullcalendar.print.css +0 -32
  141. data/redesign/js/plugins/fullcalendar/gcal.js +0 -107
  142. data/redesign/js/plugins/howl/howl.js +0 -70
  143. data/redesign/js/plugins/howl/howl.min.js +0 -2
  144. data/redesign/js/plugins/icheck/jquery.icheck.js +0 -462
  145. data/redesign/js/plugins/icheck/jquery.icheck.min.js +0 -11
  146. data/redesign/js/plugins/icheck/skins/all.css +0 -61
  147. data/redesign/js/plugins/icheck/skins/flat/_all.css +0 -540
  148. data/redesign/js/plugins/icheck/skins/flat/aero.css +0 -54
  149. data/redesign/js/plugins/icheck/skins/flat/aero.png +0 -0
  150. data/redesign/js/plugins/icheck/skins/flat/aero@2x.png +0 -0
  151. data/redesign/js/plugins/icheck/skins/flat/blue.css +0 -54
  152. data/redesign/js/plugins/icheck/skins/flat/blue.png +0 -0
  153. data/redesign/js/plugins/icheck/skins/flat/blue@2x.png +0 -0
  154. data/redesign/js/plugins/icheck/skins/flat/flat.css +0 -54
  155. data/redesign/js/plugins/icheck/skins/flat/flat.png +0 -0
  156. data/redesign/js/plugins/icheck/skins/flat/flat@2x.png +0 -0
  157. data/redesign/js/plugins/icheck/skins/flat/green.css +0 -54
  158. data/redesign/js/plugins/icheck/skins/flat/green.png +0 -0
  159. data/redesign/js/plugins/icheck/skins/flat/green@2x.png +0 -0
  160. data/redesign/js/plugins/icheck/skins/flat/grey.css +0 -54
  161. data/redesign/js/plugins/icheck/skins/flat/grey.png +0 -0
  162. data/redesign/js/plugins/icheck/skins/flat/grey@2x.png +0 -0
  163. data/redesign/js/plugins/icheck/skins/flat/orange.css +0 -54
  164. data/redesign/js/plugins/icheck/skins/flat/orange.png +0 -0
  165. data/redesign/js/plugins/icheck/skins/flat/orange@2x.png +0 -0
  166. data/redesign/js/plugins/icheck/skins/flat/pink.css +0 -54
  167. data/redesign/js/plugins/icheck/skins/flat/pink.png +0 -0
  168. data/redesign/js/plugins/icheck/skins/flat/pink@2x.png +0 -0
  169. data/redesign/js/plugins/icheck/skins/flat/purple.css +0 -54
  170. data/redesign/js/plugins/icheck/skins/flat/purple.png +0 -0
  171. data/redesign/js/plugins/icheck/skins/flat/purple@2x.png +0 -0
  172. data/redesign/js/plugins/icheck/skins/flat/red.css +0 -54
  173. data/redesign/js/plugins/icheck/skins/flat/red.png +0 -0
  174. data/redesign/js/plugins/icheck/skins/flat/red@2x.png +0 -0
  175. data/redesign/js/plugins/icheck/skins/flat/yellow.css +0 -54
  176. data/redesign/js/plugins/icheck/skins/flat/yellow.png +0 -0
  177. data/redesign/js/plugins/icheck/skins/flat/yellow@2x.png +0 -0
  178. data/redesign/js/plugins/icheck/skins/futurico/futurico.css +0 -54
  179. data/redesign/js/plugins/icheck/skins/futurico/futurico.png +0 -0
  180. data/redesign/js/plugins/icheck/skins/futurico/futurico@2x.png +0 -0
  181. data/redesign/js/plugins/icheck/skins/line/_all.css +0 -740
  182. data/redesign/js/plugins/icheck/skins/line/aero.css +0 -74
  183. data/redesign/js/plugins/icheck/skins/line/blue.css +0 -74
  184. data/redesign/js/plugins/icheck/skins/line/green.css +0 -74
  185. data/redesign/js/plugins/icheck/skins/line/grey.css +0 -74
  186. data/redesign/js/plugins/icheck/skins/line/line.css +0 -74
  187. data/redesign/js/plugins/icheck/skins/line/line.png +0 -0
  188. data/redesign/js/plugins/icheck/skins/line/line@2x.png +0 -0
  189. data/redesign/js/plugins/icheck/skins/line/orange.css +0 -74
  190. data/redesign/js/plugins/icheck/skins/line/pink.css +0 -74
  191. data/redesign/js/plugins/icheck/skins/line/purple.css +0 -74
  192. data/redesign/js/plugins/icheck/skins/line/red.css +0 -74
  193. data/redesign/js/plugins/icheck/skins/line/yellow.css +0 -74
  194. data/redesign/js/plugins/icheck/skins/minimal/_all.css +0 -600
  195. data/redesign/js/plugins/icheck/skins/minimal/aero.css +0 -60
  196. data/redesign/js/plugins/icheck/skins/minimal/aero.png +0 -0
  197. data/redesign/js/plugins/icheck/skins/minimal/aero@2x.png +0 -0
  198. data/redesign/js/plugins/icheck/skins/minimal/blue.css +0 -60
  199. data/redesign/js/plugins/icheck/skins/minimal/blue.png +0 -0
  200. data/redesign/js/plugins/icheck/skins/minimal/blue@2x.png +0 -0
  201. data/redesign/js/plugins/icheck/skins/minimal/green.css +0 -60
  202. data/redesign/js/plugins/icheck/skins/minimal/green.png +0 -0
  203. data/redesign/js/plugins/icheck/skins/minimal/green@2x.png +0 -0
  204. data/redesign/js/plugins/icheck/skins/minimal/grey.css +0 -60
  205. data/redesign/js/plugins/icheck/skins/minimal/grey.png +0 -0
  206. data/redesign/js/plugins/icheck/skins/minimal/grey@2x.png +0 -0
  207. data/redesign/js/plugins/icheck/skins/minimal/minimal.css +0 -60
  208. data/redesign/js/plugins/icheck/skins/minimal/minimal.png +0 -0
  209. data/redesign/js/plugins/icheck/skins/minimal/minimal@2x.png +0 -0
  210. data/redesign/js/plugins/icheck/skins/minimal/orange.css +0 -60
  211. data/redesign/js/plugins/icheck/skins/minimal/orange.png +0 -0
  212. data/redesign/js/plugins/icheck/skins/minimal/orange@2x.png +0 -0
  213. data/redesign/js/plugins/icheck/skins/minimal/pink.css +0 -60
  214. data/redesign/js/plugins/icheck/skins/minimal/pink.png +0 -0
  215. data/redesign/js/plugins/icheck/skins/minimal/pink@2x.png +0 -0
  216. data/redesign/js/plugins/icheck/skins/minimal/purple.css +0 -60
  217. data/redesign/js/plugins/icheck/skins/minimal/purple.png +0 -0
  218. data/redesign/js/plugins/icheck/skins/minimal/purple@2x.png +0 -0
  219. data/redesign/js/plugins/icheck/skins/minimal/red.css +0 -60
  220. data/redesign/js/plugins/icheck/skins/minimal/red.png +0 -0
  221. data/redesign/js/plugins/icheck/skins/minimal/red@2x.png +0 -0
  222. data/redesign/js/plugins/icheck/skins/minimal/yellow.css +0 -60
  223. data/redesign/js/plugins/icheck/skins/minimal/yellow.png +0 -0
  224. data/redesign/js/plugins/icheck/skins/minimal/yellow@2x.png +0 -0
  225. data/redesign/js/plugins/icheck/skins/polaris/polaris.css +0 -60
  226. data/redesign/js/plugins/icheck/skins/polaris/polaris.png +0 -0
  227. data/redesign/js/plugins/icheck/skins/polaris/polaris@2x.png +0 -0
  228. data/redesign/js/plugins/icheck/skins/square/_all.css +0 -600
  229. data/redesign/js/plugins/icheck/skins/square/aero.css +0 -60
  230. data/redesign/js/plugins/icheck/skins/square/aero.png +0 -0
  231. data/redesign/js/plugins/icheck/skins/square/aero@2x.png +0 -0
  232. data/redesign/js/plugins/icheck/skins/square/blue.css +0 -60
  233. data/redesign/js/plugins/icheck/skins/square/blue.png +0 -0
  234. data/redesign/js/plugins/icheck/skins/square/blue@2x.png +0 -0
  235. data/redesign/js/plugins/icheck/skins/square/green.css +0 -60
  236. data/redesign/js/plugins/icheck/skins/square/green.png +0 -0
  237. data/redesign/js/plugins/icheck/skins/square/green@2x.png +0 -0
  238. data/redesign/js/plugins/icheck/skins/square/grey.css +0 -60
  239. data/redesign/js/plugins/icheck/skins/square/grey.png +0 -0
  240. data/redesign/js/plugins/icheck/skins/square/grey@2x.png +0 -0
  241. data/redesign/js/plugins/icheck/skins/square/orange.css +0 -60
  242. data/redesign/js/plugins/icheck/skins/square/orange.png +0 -0
  243. data/redesign/js/plugins/icheck/skins/square/orange@2x.png +0 -0
  244. data/redesign/js/plugins/icheck/skins/square/pink.css +0 -60
  245. data/redesign/js/plugins/icheck/skins/square/pink.png +0 -0
  246. data/redesign/js/plugins/icheck/skins/square/pink@2x.png +0 -0
  247. data/redesign/js/plugins/icheck/skins/square/purple.css +0 -60
  248. data/redesign/js/plugins/icheck/skins/square/purple.png +0 -0
  249. data/redesign/js/plugins/icheck/skins/square/purple@2x.png +0 -0
  250. data/redesign/js/plugins/icheck/skins/square/red.css +0 -60
  251. data/redesign/js/plugins/icheck/skins/square/red.png +0 -0
  252. data/redesign/js/plugins/icheck/skins/square/red@2x.png +0 -0
  253. data/redesign/js/plugins/icheck/skins/square/square.css +0 -60
  254. data/redesign/js/plugins/icheck/skins/square/square.png +0 -0
  255. data/redesign/js/plugins/icheck/skins/square/square@2x.png +0 -0
  256. data/redesign/js/plugins/icheck/skins/square/yellow.css +0 -60
  257. data/redesign/js/plugins/icheck/skins/square/yellow.png +0 -0
  258. data/redesign/js/plugins/icheck/skins/square/yellow@2x.png +0 -0
  259. data/redesign/js/plugins/magnific/jquery.magnific-popup.js +0 -2026
  260. data/redesign/js/plugins/magnific/jquery.magnific-popup.min.js +0 -4
  261. data/redesign/js/plugins/magnific/magnific-popup.css +0 -396
  262. data/redesign/js/plugins/morris/morris.css +0 -1
  263. data/redesign/js/plugins/morris/morris.min.js +0 -1
  264. data/redesign/js/plugins/parsley/parsley.js +0 -1363
  265. data/redesign/js/plugins/select2/select2-spinner.gif +0 -0
  266. data/redesign/js/plugins/select2/select2.css +0 -615
  267. data/redesign/js/plugins/select2/select2.js +0 -3217
  268. data/redesign/js/plugins/select2/select2.min.js +0 -22
  269. data/redesign/js/plugins/select2/select2.png +0 -0
  270. data/redesign/js/plugins/select2/select2x2.png +0 -0
  271. data/redesign/js/plugins/simplecolorpicker/jquery.simplecolorpicker.css +0 -98
  272. data/redesign/js/plugins/simplecolorpicker/jquery.simplecolorpicker.js +0 -211
  273. data/redesign/js/plugins/sparkline/jquery.sparkline.min.js +0 -5
  274. data/redesign/js/plugins/tableCheckable/jquery.tableCheckable.js +0 -122
  275. data/redesign/js/plugins/textarea-counter/jquery.textarea-counter.js +0 -163
  276. data/redesign/js/plugins/timepicker/bootstrap-timepicker.css +0 -121
  277. data/redesign/js/plugins/timepicker/bootstrap-timepicker.js +0 -893
  278. data/redesign/page-404.html +0 -446
  279. data/redesign/page-500.html +0 -453
  280. data/redesign/page-blank.html +0 -417
  281. data/redesign/page-calendar.html +0 -491
  282. data/redesign/page-gallery.html +0 -736
  283. data/redesign/page-invoice.html +0 -705
  284. data/redesign/page-login-social.html +0 -111
  285. data/redesign/page-login.html +0 -82
  286. data/redesign/page-pricing.html +0 -707
  287. data/redesign/page-settings.html +0 -665
  288. data/redesign/page-support.html +0 -825
  289. data/redesign/table-advanced.html +0 -1297
  290. data/redesign/table-basic.html +0 -777
  291. data/redesign/table-responsive.html +0 -720
  292. data/redesign/ui-buttons.html +0 -901
  293. data/redesign/ui-icons.html +0 -1392
  294. data/redesign/ui-popups.html +0 -781
  295. data/redesign/ui-portlets.html +0 -887
  296. data/redesign/ui-sliders.html +0 -520
  297. data/redesign/ui-tabs.html +0 -663
  298. data/redesign/ui-typography.html +0 -687
@@ -1,7 +0,0 @@
1
- /**
2
- * Bootstrap.js by @mdo and @fat, extended by @ArnoldDaniels.
3
- * plugins: bootstrap-fileupload.js
4
- * Copyright 2012 Twitter, Inc.
5
- * http://www.apache.org/licenses/LICENSE-2.0.txt
6
- */
7
- !function(e){var t=function(t,n){this.$element=e(t),this.type=this.$element.data("uploadtype")||(this.$element.find(".thumbnail").length>0?"image":"file"),this.$input=this.$element.find(":file");if(this.$input.length===0)return;this.name=this.$input.attr("name")||n.name,this.$hidden=this.$element.find('input[type=hidden][name="'+this.name+'"]'),this.$hidden.length===0&&(this.$hidden=e('<input type="hidden" />'),this.$element.prepend(this.$hidden)),this.$preview=this.$element.find(".fileupload-preview");var r=this.$preview.css("height");this.$preview.css("display")!="inline"&&r!="0px"&&r!="none"&&this.$preview.css("line-height",r),this.original={exists:this.$element.hasClass("fileupload-exists"),preview:this.$preview.html(),hiddenVal:this.$hidden.val()},this.$remove=this.$element.find('[data-dismiss="fileupload"]'),this.$element.find('[data-trigger="fileupload"]').on("click.fileupload",e.proxy(this.trigger,this)),this.listen()};t.prototype={listen:function(){this.$input.on("change.fileupload",e.proxy(this.change,this)),e(this.$input[0].form).on("reset.fileupload",e.proxy(this.reset,this)),this.$remove&&this.$remove.on("click.fileupload",e.proxy(this.clear,this))},change:function(e,t){if(t==="clear")return;var n=e.target.files!==undefined?e.target.files[0]:e.target.value?{name:e.target.value.replace(/^.+\\/,"")}:null;if(!n){this.clear();return}this.$hidden.val(""),this.$hidden.attr("name",""),this.$input.attr("name",this.name);if(this.type==="image"&&this.$preview.length>0&&(typeof n.type!="undefined"?n.type.match("image.*"):n.name.match(/\.(gif|png|jpe?g)$/i))&&typeof FileReader!="undefined"){var r=new FileReader,i=this.$preview,s=this.$element;r.onload=function(e){i.html('<img src="'+e.target.result+'" '+(i.css("max-height")!="none"?'style="max-height: '+i.css("max-height")+';"':"")+" />"),s.addClass("fileupload-exists").removeClass("fileupload-new")},r.readAsDataURL(n)}else this.$preview.text(n.name),this.$element.addClass("fileupload-exists").removeClass("fileupload-new")},clear:function(e){this.$hidden.val(""),this.$hidden.attr("name",this.name),this.$input.attr("name","");if(navigator.userAgent.match(/msie/i)){var t=this.$input.clone(!0);this.$input.after(t),this.$input.remove(),this.$input=t}else this.$input.val("");this.$preview.html(""),this.$element.addClass("fileupload-new").removeClass("fileupload-exists"),e&&(this.$input.trigger("change",["clear"]),e.preventDefault())},reset:function(e){this.clear(),this.$hidden.val(this.original.hiddenVal),this.$preview.html(this.original.preview),this.original.exists?this.$element.addClass("fileupload-exists").removeClass("fileupload-new"):this.$element.addClass("fileupload-new").removeClass("fileupload-exists")},trigger:function(e){this.$input.trigger("click"),e.preventDefault()}},e.fn.fileupload=function(n){return this.each(function(){var r=e(this),i=r.data("fileupload");i||r.data("fileupload",i=new t(this,n)),typeof n=="string"&&i[n]()})},e.fn.fileupload.Constructor=t,e(document).on("click.fileupload.data-api",'[data-provides="fileupload"]',function(t){var n=e(this);if(n.data("fileupload"))return;n.fileupload(n.data());var r=e(t.target).closest('[data-dismiss="fileupload"],[data-trigger="fileupload"]');r.length>0&&(r.trigger("click.fileupload"),t.preventDefault())})}(window.jQuery)
@@ -1,2599 +0,0 @@
1
- /*! Javascript plotting library for jQuery, v. 0.7.
2
- *
3
- * Released under the MIT license by IOLA, December 2007.
4
- *
5
- */
6
-
7
- // first an inline dependency, jquery.colorhelpers.js, we inline it here
8
- // for convenience
9
-
10
- /* Plugin for jQuery for working with colors.
11
- *
12
- * Version 1.1.
13
- *
14
- * Inspiration from jQuery color animation plugin by John Resig.
15
- *
16
- * Released under the MIT license by Ole Laursen, October 2009.
17
- *
18
- * Examples:
19
- *
20
- * $.color.parse("#fff").scale('rgb', 0.25).add('a', -0.5).toString()
21
- * var c = $.color.extract($("#mydiv"), 'background-color');
22
- * console.log(c.r, c.g, c.b, c.a);
23
- * $.color.make(100, 50, 25, 0.4).toString() // returns "rgba(100,50,25,0.4)"
24
- *
25
- * Note that .scale() and .add() return the same modified object
26
- * instead of making a new one.
27
- *
28
- * V. 1.1: Fix error handling so e.g. parsing an empty string does
29
- * produce a color rather than just crashing.
30
- */
31
- (function(B){B.color={};B.color.make=function(F,E,C,D){var G={};G.r=F||0;G.g=E||0;G.b=C||0;G.a=D!=null?D:1;G.add=function(J,I){for(var H=0;H<J.length;++H){G[J.charAt(H)]+=I}return G.normalize()};G.scale=function(J,I){for(var H=0;H<J.length;++H){G[J.charAt(H)]*=I}return G.normalize()};G.toString=function(){if(G.a>=1){return"rgb("+[G.r,G.g,G.b].join(",")+")"}else{return"rgba("+[G.r,G.g,G.b,G.a].join(",")+")"}};G.normalize=function(){function H(J,K,I){return K<J?J:(K>I?I:K)}G.r=H(0,parseInt(G.r),255);G.g=H(0,parseInt(G.g),255);G.b=H(0,parseInt(G.b),255);G.a=H(0,G.a,1);return G};G.clone=function(){return B.color.make(G.r,G.b,G.g,G.a)};return G.normalize()};B.color.extract=function(D,C){var E;do{E=D.css(C).toLowerCase();if(E!=""&&E!="transparent"){break}D=D.parent()}while(!B.nodeName(D.get(0),"body"));if(E=="rgba(0, 0, 0, 0)"){E="transparent"}return B.color.parse(E)};B.color.parse=function(F){var E,C=B.color.make;if(E=/rgb\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*\)/.exec(F)){return C(parseInt(E[1],10),parseInt(E[2],10),parseInt(E[3],10))}if(E=/rgba\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]+(?:\.[0-9]+)?)\s*\)/.exec(F)){return C(parseInt(E[1],10),parseInt(E[2],10),parseInt(E[3],10),parseFloat(E[4]))}if(E=/rgb\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*\)/.exec(F)){return C(parseFloat(E[1])*2.55,parseFloat(E[2])*2.55,parseFloat(E[3])*2.55)}if(E=/rgba\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\s*\)/.exec(F)){return C(parseFloat(E[1])*2.55,parseFloat(E[2])*2.55,parseFloat(E[3])*2.55,parseFloat(E[4]))}if(E=/#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/.exec(F)){return C(parseInt(E[1],16),parseInt(E[2],16),parseInt(E[3],16))}if(E=/#([a-fA-F0-9])([a-fA-F0-9])([a-fA-F0-9])/.exec(F)){return C(parseInt(E[1]+E[1],16),parseInt(E[2]+E[2],16),parseInt(E[3]+E[3],16))}var D=B.trim(F).toLowerCase();if(D=="transparent"){return C(255,255,255,0)}else{E=A[D]||[0,0,0];return C(E[0],E[1],E[2])}};var A={aqua:[0,255,255],azure:[240,255,255],beige:[245,245,220],black:[0,0,0],blue:[0,0,255],brown:[165,42,42],cyan:[0,255,255],darkblue:[0,0,139],darkcyan:[0,139,139],darkgrey:[169,169,169],darkgreen:[0,100,0],darkkhaki:[189,183,107],darkmagenta:[139,0,139],darkolivegreen:[85,107,47],darkorange:[255,140,0],darkorchid:[153,50,204],darkred:[139,0,0],darksalmon:[233,150,122],darkviolet:[148,0,211],fuchsia:[255,0,255],gold:[255,215,0],green:[0,128,0],indigo:[75,0,130],khaki:[240,230,140],lightblue:[173,216,230],lightcyan:[224,255,255],lightgreen:[144,238,144],lightgrey:[211,211,211],lightpink:[255,182,193],lightyellow:[255,255,224],lime:[0,255,0],magenta:[255,0,255],maroon:[128,0,0],navy:[0,0,128],olive:[128,128,0],orange:[255,165,0],pink:[255,192,203],purple:[128,0,128],violet:[128,0,128],red:[255,0,0],silver:[192,192,192],white:[255,255,255],yellow:[255,255,0]}})(jQuery);
32
-
33
- // the actual Flot code
34
- (function($) {
35
- function Plot(placeholder, data_, options_, plugins) {
36
- // data is on the form:
37
- // [ series1, series2 ... ]
38
- // where series is either just the data as [ [x1, y1], [x2, y2], ... ]
39
- // or { data: [ [x1, y1], [x2, y2], ... ], label: "some label", ... }
40
-
41
- var series = [],
42
- options = {
43
- // the color theme used for graphs
44
- colors: ["#edc240", "#afd8f8", "#cb4b4b", "#4da74d", "#9440ed"],
45
- legend: {
46
- show: true,
47
- noColumns: 1, // number of colums in legend table
48
- labelFormatter: null, // fn: string -> string
49
- labelBoxBorderColor: "#ccc", // border color for the little label boxes
50
- container: null, // container (as jQuery object) to put legend in, null means default on top of graph
51
- position: "ne", // position of default legend container within plot
52
- margin: 5, // distance from grid edge to default legend container within plot
53
- backgroundColor: null, // null means auto-detect
54
- backgroundOpacity: 0.85 // set to 0 to avoid background
55
- },
56
- xaxis: {
57
- show: null, // null = auto-detect, true = always, false = never
58
- position: "bottom", // or "top"
59
- mode: null, // null or "time"
60
- color: null, // base color, labels, ticks
61
- tickColor: null, // possibly different color of ticks, e.g. "rgba(0,0,0,0.15)"
62
- transform: null, // null or f: number -> number to transform axis
63
- inverseTransform: null, // if transform is set, this should be the inverse function
64
- min: null, // min. value to show, null means set automatically
65
- max: null, // max. value to show, null means set automatically
66
- autoscaleMargin: null, // margin in % to add if auto-setting min/max
67
- ticks: null, // either [1, 3] or [[1, "a"], 3] or (fn: axis info -> ticks) or app. number of ticks for auto-ticks
68
- tickFormatter: null, // fn: number -> string
69
- labelWidth: null, // size of tick labels in pixels
70
- labelHeight: null,
71
- reserveSpace: null, // whether to reserve space even if axis isn't shown
72
- tickLength: null, // size in pixels of ticks, or "full" for whole line
73
- alignTicksWithAxis: null, // axis number or null for no sync
74
-
75
- // mode specific options
76
- tickDecimals: null, // no. of decimals, null means auto
77
- tickSize: null, // number or [number, "unit"]
78
- minTickSize: null, // number or [number, "unit"]
79
- monthNames: null, // list of names of months
80
- timeformat: null, // format string to use
81
- twelveHourClock: false // 12 or 24 time in time mode
82
- },
83
- yaxis: {
84
- autoscaleMargin: 0.02,
85
- position: "left" // or "right"
86
- },
87
- xaxes: [],
88
- yaxes: [],
89
- series: {
90
- points: {
91
- show: false,
92
- radius: 3,
93
- lineWidth: 2, // in pixels
94
- fill: true,
95
- fillColor: "#ffffff",
96
- symbol: "circle" // or callback
97
- },
98
- lines: {
99
- // we don't put in show: false so we can see
100
- // whether lines were actively disabled
101
- lineWidth: 2, // in pixels
102
- fill: false,
103
- fillColor: null,
104
- steps: false
105
- },
106
- bars: {
107
- show: false,
108
- lineWidth: 2, // in pixels
109
- barWidth: 1, // in units of the x axis
110
- fill: true,
111
- fillColor: null,
112
- align: "left", // or "center"
113
- horizontal: false
114
- },
115
- shadowSize: 3
116
- },
117
- grid: {
118
- show: true,
119
- aboveData: false,
120
- color: "#545454", // primary color used for outline and labels
121
- backgroundColor: null, // null for transparent, else color
122
- borderColor: null, // set if different from the grid color
123
- tickColor: null, // color for the ticks, e.g. "rgba(0,0,0,0.15)"
124
- labelMargin: 5, // in pixels
125
- axisMargin: 8, // in pixels
126
- borderWidth: 2, // in pixels
127
- minBorderMargin: null, // in pixels, null means taken from points radius
128
- markings: null, // array of ranges or fn: axes -> array of ranges
129
- markingsColor: "#f4f4f4",
130
- markingsLineWidth: 2,
131
- // interactive stuff
132
- clickable: false,
133
- hoverable: false,
134
- autoHighlight: true, // highlight in case mouse is near
135
- mouseActiveRadius: 10 // how far the mouse can be away to activate an item
136
- },
137
- hooks: {}
138
- },
139
- canvas = null, // the canvas for the plot itself
140
- overlay = null, // canvas for interactive stuff on top of plot
141
- eventHolder = null, // jQuery object that events should be bound to
142
- ctx = null, octx = null,
143
- xaxes = [], yaxes = [],
144
- plotOffset = { left: 0, right: 0, top: 0, bottom: 0},
145
- canvasWidth = 0, canvasHeight = 0,
146
- plotWidth = 0, plotHeight = 0,
147
- hooks = {
148
- processOptions: [],
149
- processRawData: [],
150
- processDatapoints: [],
151
- drawSeries: [],
152
- draw: [],
153
- bindEvents: [],
154
- drawOverlay: [],
155
- shutdown: []
156
- },
157
- plot = this;
158
-
159
- // public functions
160
- plot.setData = setData;
161
- plot.setupGrid = setupGrid;
162
- plot.draw = draw;
163
- plot.getPlaceholder = function() { return placeholder; };
164
- plot.getCanvas = function() { return canvas; };
165
- plot.getPlotOffset = function() { return plotOffset; };
166
- plot.width = function () { return plotWidth; };
167
- plot.height = function () { return plotHeight; };
168
- plot.offset = function () {
169
- var o = eventHolder.offset();
170
- o.left += plotOffset.left;
171
- o.top += plotOffset.top;
172
- return o;
173
- };
174
- plot.getData = function () { return series; };
175
- plot.getAxes = function () {
176
- var res = {}, i;
177
- $.each(xaxes.concat(yaxes), function (_, axis) {
178
- if (axis)
179
- res[axis.direction + (axis.n != 1 ? axis.n : "") + "axis"] = axis;
180
- });
181
- return res;
182
- };
183
- plot.getXAxes = function () { return xaxes; };
184
- plot.getYAxes = function () { return yaxes; };
185
- plot.c2p = canvasToAxisCoords;
186
- plot.p2c = axisToCanvasCoords;
187
- plot.getOptions = function () { return options; };
188
- plot.highlight = highlight;
189
- plot.unhighlight = unhighlight;
190
- plot.triggerRedrawOverlay = triggerRedrawOverlay;
191
- plot.pointOffset = function(point) {
192
- return {
193
- left: parseInt(xaxes[axisNumber(point, "x") - 1].p2c(+point.x) + plotOffset.left),
194
- top: parseInt(yaxes[axisNumber(point, "y") - 1].p2c(+point.y) + plotOffset.top)
195
- };
196
- };
197
- plot.shutdown = shutdown;
198
- plot.resize = function () {
199
- getCanvasDimensions();
200
- resizeCanvas(canvas);
201
- resizeCanvas(overlay);
202
- };
203
-
204
- // public attributes
205
- plot.hooks = hooks;
206
-
207
- // initialize
208
- initPlugins(plot);
209
- parseOptions(options_);
210
- setupCanvases();
211
- setData(data_);
212
- setupGrid();
213
- draw();
214
- bindEvents();
215
-
216
-
217
- function executeHooks(hook, args) {
218
- args = [plot].concat(args);
219
- for (var i = 0; i < hook.length; ++i)
220
- hook[i].apply(this, args);
221
- }
222
-
223
- function initPlugins() {
224
- for (var i = 0; i < plugins.length; ++i) {
225
- var p = plugins[i];
226
- p.init(plot);
227
- if (p.options)
228
- $.extend(true, options, p.options);
229
- }
230
- }
231
-
232
- function parseOptions(opts) {
233
- var i;
234
-
235
- $.extend(true, options, opts);
236
-
237
- if (options.xaxis.color == null)
238
- options.xaxis.color = options.grid.color;
239
- if (options.yaxis.color == null)
240
- options.yaxis.color = options.grid.color;
241
-
242
- if (options.xaxis.tickColor == null) // backwards-compatibility
243
- options.xaxis.tickColor = options.grid.tickColor;
244
- if (options.yaxis.tickColor == null) // backwards-compatibility
245
- options.yaxis.tickColor = options.grid.tickColor;
246
-
247
- if (options.grid.borderColor == null)
248
- options.grid.borderColor = options.grid.color;
249
- if (options.grid.tickColor == null)
250
- options.grid.tickColor = $.color.parse(options.grid.color).scale('a', 0.22).toString();
251
-
252
- // fill in defaults in axes, copy at least always the
253
- // first as the rest of the code assumes it'll be there
254
- for (i = 0; i < Math.max(1, options.xaxes.length); ++i)
255
- options.xaxes[i] = $.extend(true, {}, options.xaxis, options.xaxes[i]);
256
- for (i = 0; i < Math.max(1, options.yaxes.length); ++i)
257
- options.yaxes[i] = $.extend(true, {}, options.yaxis, options.yaxes[i]);
258
-
259
- // backwards compatibility, to be removed in future
260
- if (options.xaxis.noTicks && options.xaxis.ticks == null)
261
- options.xaxis.ticks = options.xaxis.noTicks;
262
- if (options.yaxis.noTicks && options.yaxis.ticks == null)
263
- options.yaxis.ticks = options.yaxis.noTicks;
264
- if (options.x2axis) {
265
- options.xaxes[1] = $.extend(true, {}, options.xaxis, options.x2axis);
266
- options.xaxes[1].position = "top";
267
- }
268
- if (options.y2axis) {
269
- options.yaxes[1] = $.extend(true, {}, options.yaxis, options.y2axis);
270
- options.yaxes[1].position = "right";
271
- }
272
- if (options.grid.coloredAreas)
273
- options.grid.markings = options.grid.coloredAreas;
274
- if (options.grid.coloredAreasColor)
275
- options.grid.markingsColor = options.grid.coloredAreasColor;
276
- if (options.lines)
277
- $.extend(true, options.series.lines, options.lines);
278
- if (options.points)
279
- $.extend(true, options.series.points, options.points);
280
- if (options.bars)
281
- $.extend(true, options.series.bars, options.bars);
282
- if (options.shadowSize != null)
283
- options.series.shadowSize = options.shadowSize;
284
-
285
- // save options on axes for future reference
286
- for (i = 0; i < options.xaxes.length; ++i)
287
- getOrCreateAxis(xaxes, i + 1).options = options.xaxes[i];
288
- for (i = 0; i < options.yaxes.length; ++i)
289
- getOrCreateAxis(yaxes, i + 1).options = options.yaxes[i];
290
-
291
- // add hooks from options
292
- for (var n in hooks)
293
- if (options.hooks[n] && options.hooks[n].length)
294
- hooks[n] = hooks[n].concat(options.hooks[n]);
295
-
296
- executeHooks(hooks.processOptions, [options]);
297
- }
298
-
299
- function setData(d) {
300
- series = parseData(d);
301
- fillInSeriesOptions();
302
- processData();
303
- }
304
-
305
- function parseData(d) {
306
- var res = [];
307
- for (var i = 0; i < d.length; ++i) {
308
- var s = $.extend(true, {}, options.series);
309
-
310
- if (d[i].data != null) {
311
- s.data = d[i].data; // move the data instead of deep-copy
312
- delete d[i].data;
313
-
314
- $.extend(true, s, d[i]);
315
-
316
- d[i].data = s.data;
317
- }
318
- else
319
- s.data = d[i];
320
- res.push(s);
321
- }
322
-
323
- return res;
324
- }
325
-
326
- function axisNumber(obj, coord) {
327
- var a = obj[coord + "axis"];
328
- if (typeof a == "object") // if we got a real axis, extract number
329
- a = a.n;
330
- if (typeof a != "number")
331
- a = 1; // default to first axis
332
- return a;
333
- }
334
-
335
- function allAxes() {
336
- // return flat array without annoying null entries
337
- return $.grep(xaxes.concat(yaxes), function (a) { return a; });
338
- }
339
-
340
- function canvasToAxisCoords(pos) {
341
- // return an object with x/y corresponding to all used axes
342
- var res = {}, i, axis;
343
- for (i = 0; i < xaxes.length; ++i) {
344
- axis = xaxes[i];
345
- if (axis && axis.used)
346
- res["x" + axis.n] = axis.c2p(pos.left);
347
- }
348
-
349
- for (i = 0; i < yaxes.length; ++i) {
350
- axis = yaxes[i];
351
- if (axis && axis.used)
352
- res["y" + axis.n] = axis.c2p(pos.top);
353
- }
354
-
355
- if (res.x1 !== undefined)
356
- res.x = res.x1;
357
- if (res.y1 !== undefined)
358
- res.y = res.y1;
359
-
360
- return res;
361
- }
362
-
363
- function axisToCanvasCoords(pos) {
364
- // get canvas coords from the first pair of x/y found in pos
365
- var res = {}, i, axis, key;
366
-
367
- for (i = 0; i < xaxes.length; ++i) {
368
- axis = xaxes[i];
369
- if (axis && axis.used) {
370
- key = "x" + axis.n;
371
- if (pos[key] == null && axis.n == 1)
372
- key = "x";
373
-
374
- if (pos[key] != null) {
375
- res.left = axis.p2c(pos[key]);
376
- break;
377
- }
378
- }
379
- }
380
-
381
- for (i = 0; i < yaxes.length; ++i) {
382
- axis = yaxes[i];
383
- if (axis && axis.used) {
384
- key = "y" + axis.n;
385
- if (pos[key] == null && axis.n == 1)
386
- key = "y";
387
-
388
- if (pos[key] != null) {
389
- res.top = axis.p2c(pos[key]);
390
- break;
391
- }
392
- }
393
- }
394
-
395
- return res;
396
- }
397
-
398
- function getOrCreateAxis(axes, number) {
399
- if (!axes[number - 1])
400
- axes[number - 1] = {
401
- n: number, // save the number for future reference
402
- direction: axes == xaxes ? "x" : "y",
403
- options: $.extend(true, {}, axes == xaxes ? options.xaxis : options.yaxis)
404
- };
405
-
406
- return axes[number - 1];
407
- }
408
-
409
- function fillInSeriesOptions() {
410
- var i;
411
-
412
- // collect what we already got of colors
413
- var neededColors = series.length,
414
- usedColors = [],
415
- assignedColors = [];
416
- for (i = 0; i < series.length; ++i) {
417
- var sc = series[i].color;
418
- if (sc != null) {
419
- --neededColors;
420
- if (typeof sc == "number")
421
- assignedColors.push(sc);
422
- else
423
- usedColors.push($.color.parse(series[i].color));
424
- }
425
- }
426
-
427
- // we might need to generate more colors if higher indices
428
- // are assigned
429
- for (i = 0; i < assignedColors.length; ++i) {
430
- neededColors = Math.max(neededColors, assignedColors[i] + 1);
431
- }
432
-
433
- // produce colors as needed
434
- var colors = [], variation = 0;
435
- i = 0;
436
- while (colors.length < neededColors) {
437
- var c;
438
- if (options.colors.length == i) // check degenerate case
439
- c = $.color.make(100, 100, 100);
440
- else
441
- c = $.color.parse(options.colors[i]);
442
-
443
- // vary color if needed
444
- var sign = variation % 2 == 1 ? -1 : 1;
445
- c.scale('rgb', 1 + sign * Math.ceil(variation / 2) * 0.2)
446
-
447
- // FIXME: if we're getting to close to something else,
448
- // we should probably skip this one
449
- colors.push(c);
450
-
451
- ++i;
452
- if (i >= options.colors.length) {
453
- i = 0;
454
- ++variation;
455
- }
456
- }
457
-
458
- // fill in the options
459
- var colori = 0, s;
460
- for (i = 0; i < series.length; ++i) {
461
- s = series[i];
462
-
463
- // assign colors
464
- if (s.color == null) {
465
- s.color = colors[colori].toString();
466
- ++colori;
467
- }
468
- else if (typeof s.color == "number")
469
- s.color = colors[s.color].toString();
470
-
471
- // turn on lines automatically in case nothing is set
472
- if (s.lines.show == null) {
473
- var v, show = true;
474
- for (v in s)
475
- if (s[v] && s[v].show) {
476
- show = false;
477
- break;
478
- }
479
- if (show)
480
- s.lines.show = true;
481
- }
482
-
483
- // setup axes
484
- s.xaxis = getOrCreateAxis(xaxes, axisNumber(s, "x"));
485
- s.yaxis = getOrCreateAxis(yaxes, axisNumber(s, "y"));
486
- }
487
- }
488
-
489
- function processData() {
490
- var topSentry = Number.POSITIVE_INFINITY,
491
- bottomSentry = Number.NEGATIVE_INFINITY,
492
- fakeInfinity = Number.MAX_VALUE,
493
- i, j, k, m, length,
494
- s, points, ps, x, y, axis, val, f, p;
495
-
496
- function updateAxis(axis, min, max) {
497
- if (min < axis.datamin && min != -fakeInfinity)
498
- axis.datamin = min;
499
- if (max > axis.datamax && max != fakeInfinity)
500
- axis.datamax = max;
501
- }
502
-
503
- $.each(allAxes(), function (_, axis) {
504
- // init axis
505
- axis.datamin = topSentry;
506
- axis.datamax = bottomSentry;
507
- axis.used = false;
508
- });
509
-
510
- for (i = 0; i < series.length; ++i) {
511
- s = series[i];
512
- s.datapoints = { points: [] };
513
-
514
- executeHooks(hooks.processRawData, [ s, s.data, s.datapoints ]);
515
- }
516
-
517
- // first pass: clean and copy data
518
- for (i = 0; i < series.length; ++i) {
519
- s = series[i];
520
-
521
- var data = s.data, format = s.datapoints.format;
522
-
523
- if (!format) {
524
- format = [];
525
- // find out how to copy
526
- format.push({ x: true, number: true, required: true });
527
- format.push({ y: true, number: true, required: true });
528
-
529
- if (s.bars.show || (s.lines.show && s.lines.fill)) {
530
- format.push({ y: true, number: true, required: false, defaultValue: 0 });
531
- if (s.bars.horizontal) {
532
- delete format[format.length - 1].y;
533
- format[format.length - 1].x = true;
534
- }
535
- }
536
-
537
- s.datapoints.format = format;
538
- }
539
-
540
- if (s.datapoints.pointsize != null)
541
- continue; // already filled in
542
-
543
- s.datapoints.pointsize = format.length;
544
-
545
- ps = s.datapoints.pointsize;
546
- points = s.datapoints.points;
547
-
548
- insertSteps = s.lines.show && s.lines.steps;
549
- s.xaxis.used = s.yaxis.used = true;
550
-
551
- for (j = k = 0; j < data.length; ++j, k += ps) {
552
- p = data[j];
553
-
554
- var nullify = p == null;
555
- if (!nullify) {
556
- for (m = 0; m < ps; ++m) {
557
- val = p[m];
558
- f = format[m];
559
-
560
- if (f) {
561
- if (f.number && val != null) {
562
- val = +val; // convert to number
563
- if (isNaN(val))
564
- val = null;
565
- else if (val == Infinity)
566
- val = fakeInfinity;
567
- else if (val == -Infinity)
568
- val = -fakeInfinity;
569
- }
570
-
571
- if (val == null) {
572
- if (f.required)
573
- nullify = true;
574
-
575
- if (f.defaultValue != null)
576
- val = f.defaultValue;
577
- }
578
- }
579
-
580
- points[k + m] = val;
581
- }
582
- }
583
-
584
- if (nullify) {
585
- for (m = 0; m < ps; ++m) {
586
- val = points[k + m];
587
- if (val != null) {
588
- f = format[m];
589
- // extract min/max info
590
- if (f.x)
591
- updateAxis(s.xaxis, val, val);
592
- if (f.y)
593
- updateAxis(s.yaxis, val, val);
594
- }
595
- points[k + m] = null;
596
- }
597
- }
598
- else {
599
- // a little bit of line specific stuff that
600
- // perhaps shouldn't be here, but lacking
601
- // better means...
602
- if (insertSteps && k > 0
603
- && points[k - ps] != null
604
- && points[k - ps] != points[k]
605
- && points[k - ps + 1] != points[k + 1]) {
606
- // copy the point to make room for a middle point
607
- for (m = 0; m < ps; ++m)
608
- points[k + ps + m] = points[k + m];
609
-
610
- // middle point has same y
611
- points[k + 1] = points[k - ps + 1];
612
-
613
- // we've added a point, better reflect that
614
- k += ps;
615
- }
616
- }
617
- }
618
- }
619
-
620
- // give the hooks a chance to run
621
- for (i = 0; i < series.length; ++i) {
622
- s = series[i];
623
-
624
- executeHooks(hooks.processDatapoints, [ s, s.datapoints]);
625
- }
626
-
627
- // second pass: find datamax/datamin for auto-scaling
628
- for (i = 0; i < series.length; ++i) {
629
- s = series[i];
630
- points = s.datapoints.points,
631
- ps = s.datapoints.pointsize;
632
-
633
- var xmin = topSentry, ymin = topSentry,
634
- xmax = bottomSentry, ymax = bottomSentry;
635
-
636
- for (j = 0; j < points.length; j += ps) {
637
- if (points[j] == null)
638
- continue;
639
-
640
- for (m = 0; m < ps; ++m) {
641
- val = points[j + m];
642
- f = format[m];
643
- if (!f || val == fakeInfinity || val == -fakeInfinity)
644
- continue;
645
-
646
- if (f.x) {
647
- if (val < xmin)
648
- xmin = val;
649
- if (val > xmax)
650
- xmax = val;
651
- }
652
- if (f.y) {
653
- if (val < ymin)
654
- ymin = val;
655
- if (val > ymax)
656
- ymax = val;
657
- }
658
- }
659
- }
660
-
661
- if (s.bars.show) {
662
- // make sure we got room for the bar on the dancing floor
663
- var delta = s.bars.align == "left" ? 0 : -s.bars.barWidth/2;
664
- if (s.bars.horizontal) {
665
- ymin += delta;
666
- ymax += delta + s.bars.barWidth;
667
- }
668
- else {
669
- xmin += delta;
670
- xmax += delta + s.bars.barWidth;
671
- }
672
- }
673
-
674
- updateAxis(s.xaxis, xmin, xmax);
675
- updateAxis(s.yaxis, ymin, ymax);
676
- }
677
-
678
- $.each(allAxes(), function (_, axis) {
679
- if (axis.datamin == topSentry)
680
- axis.datamin = null;
681
- if (axis.datamax == bottomSentry)
682
- axis.datamax = null;
683
- });
684
- }
685
-
686
- function makeCanvas(skipPositioning, cls) {
687
- var c = document.createElement('canvas');
688
- c.className = cls;
689
- c.width = canvasWidth;
690
- c.height = canvasHeight;
691
-
692
- if (!skipPositioning)
693
- $(c).css({ position: 'absolute', left: 0, top: 0 });
694
-
695
- $(c).appendTo(placeholder);
696
-
697
- if (!c.getContext) // excanvas hack
698
- c = window.G_vmlCanvasManager.initElement(c);
699
-
700
- // used for resetting in case we get replotted
701
- c.getContext("2d").save();
702
-
703
- return c;
704
- }
705
-
706
- function getCanvasDimensions() {
707
- canvasWidth = placeholder.width();
708
- canvasHeight = placeholder.height();
709
-
710
- if (canvasWidth <= 0 || canvasHeight <= 0)
711
- throw "Invalid dimensions for plot, width = " + canvasWidth + ", height = " + canvasHeight;
712
- }
713
-
714
- function resizeCanvas(c) {
715
- // resizing should reset the state (excanvas seems to be
716
- // buggy though)
717
- if (c.width != canvasWidth)
718
- c.width = canvasWidth;
719
-
720
- if (c.height != canvasHeight)
721
- c.height = canvasHeight;
722
-
723
- // so try to get back to the initial state (even if it's
724
- // gone now, this should be safe according to the spec)
725
- var cctx = c.getContext("2d");
726
- cctx.restore();
727
-
728
- // and save again
729
- cctx.save();
730
- }
731
-
732
- function setupCanvases() {
733
- var reused,
734
- existingCanvas = placeholder.children("canvas.base"),
735
- existingOverlay = placeholder.children("canvas.overlay");
736
-
737
- if (existingCanvas.length == 0 || existingOverlay == 0) {
738
- // init everything
739
-
740
- placeholder.html(""); // make sure placeholder is clear
741
-
742
- placeholder.css({ padding: 0 }); // padding messes up the positioning
743
-
744
- if (placeholder.css("position") == 'static')
745
- placeholder.css("position", "relative"); // for positioning labels and overlay
746
-
747
- getCanvasDimensions();
748
-
749
- canvas = makeCanvas(true, "base");
750
- overlay = makeCanvas(false, "overlay"); // overlay canvas for interactive features
751
-
752
- reused = false;
753
- }
754
- else {
755
- // reuse existing elements
756
-
757
- canvas = existingCanvas.get(0);
758
- overlay = existingOverlay.get(0);
759
-
760
- reused = true;
761
- }
762
-
763
- ctx = canvas.getContext("2d");
764
- octx = overlay.getContext("2d");
765
-
766
- // we include the canvas in the event holder too, because IE 7
767
- // sometimes has trouble with the stacking order
768
- eventHolder = $([overlay, canvas]);
769
-
770
- if (reused) {
771
- // run shutdown in the old plot object
772
- placeholder.data("plot").shutdown();
773
-
774
- // reset reused canvases
775
- plot.resize();
776
-
777
- // make sure overlay pixels are cleared (canvas is cleared when we redraw)
778
- octx.clearRect(0, 0, canvasWidth, canvasHeight);
779
-
780
- // then whack any remaining obvious garbage left
781
- eventHolder.unbind();
782
- placeholder.children().not([canvas, overlay]).remove();
783
- }
784
-
785
- // save in case we get replotted
786
- placeholder.data("plot", plot);
787
- }
788
-
789
- function bindEvents() {
790
- // bind events
791
- if (options.grid.hoverable) {
792
- eventHolder.mousemove(onMouseMove);
793
- eventHolder.mouseleave(onMouseLeave);
794
- }
795
-
796
- if (options.grid.clickable)
797
- eventHolder.click(onClick);
798
-
799
- executeHooks(hooks.bindEvents, [eventHolder]);
800
- }
801
-
802
- function shutdown() {
803
- if (redrawTimeout)
804
- clearTimeout(redrawTimeout);
805
-
806
- eventHolder.unbind("mousemove", onMouseMove);
807
- eventHolder.unbind("mouseleave", onMouseLeave);
808
- eventHolder.unbind("click", onClick);
809
-
810
- executeHooks(hooks.shutdown, [eventHolder]);
811
- }
812
-
813
- function setTransformationHelpers(axis) {
814
- // set helper functions on the axis, assumes plot area
815
- // has been computed already
816
-
817
- function identity(x) { return x; }
818
-
819
- var s, m, t = axis.options.transform || identity,
820
- it = axis.options.inverseTransform;
821
-
822
- // precompute how much the axis is scaling a point
823
- // in canvas space
824
- if (axis.direction == "x") {
825
- s = axis.scale = plotWidth / Math.abs(t(axis.max) - t(axis.min));
826
- m = Math.min(t(axis.max), t(axis.min));
827
- }
828
- else {
829
- s = axis.scale = plotHeight / Math.abs(t(axis.max) - t(axis.min));
830
- s = -s;
831
- m = Math.max(t(axis.max), t(axis.min));
832
- }
833
-
834
- // data point to canvas coordinate
835
- if (t == identity) // slight optimization
836
- axis.p2c = function (p) { return (p - m) * s; };
837
- else
838
- axis.p2c = function (p) { return (t(p) - m) * s; };
839
- // canvas coordinate to data point
840
- if (!it)
841
- axis.c2p = function (c) { return m + c / s; };
842
- else
843
- axis.c2p = function (c) { return it(m + c / s); };
844
- }
845
-
846
- function measureTickLabels(axis) {
847
- var opts = axis.options, i, ticks = axis.ticks || [], labels = [],
848
- l, w = opts.labelWidth, h = opts.labelHeight, dummyDiv;
849
-
850
- function makeDummyDiv(labels, width) {
851
- return $('<div style="position:absolute;top:-10000px;' + width + 'font-size:smaller">' +
852
- '<div class="' + axis.direction + 'Axis ' + axis.direction + axis.n + 'Axis">'
853
- + labels.join("") + '</div></div>')
854
- .appendTo(placeholder);
855
- }
856
-
857
- if (axis.direction == "x") {
858
- // to avoid measuring the widths of the labels (it's slow), we
859
- // construct fixed-size boxes and put the labels inside
860
- // them, we don't need the exact figures and the
861
- // fixed-size box content is easy to center
862
- if (w == null)
863
- w = Math.floor(canvasWidth / (ticks.length > 0 ? ticks.length : 1));
864
-
865
- // measure x label heights
866
- if (h == null) {
867
- labels = [];
868
- for (i = 0; i < ticks.length; ++i) {
869
- l = ticks[i].label;
870
- if (l)
871
- labels.push('<div class="tickLabel" style="float:left;width:' + w + 'px">' + l + '</div>');
872
- }
873
-
874
- if (labels.length > 0) {
875
- // stick them all in the same div and measure
876
- // collective height
877
- labels.push('<div style="clear:left"></div>');
878
- dummyDiv = makeDummyDiv(labels, "width:10000px;");
879
- h = dummyDiv.height();
880
- dummyDiv.remove();
881
- }
882
- }
883
- }
884
- else if (w == null || h == null) {
885
- // calculate y label dimensions
886
- for (i = 0; i < ticks.length; ++i) {
887
- l = ticks[i].label;
888
- if (l)
889
- labels.push('<div class="tickLabel">' + l + '</div>');
890
- }
891
-
892
- if (labels.length > 0) {
893
- dummyDiv = makeDummyDiv(labels, "");
894
- if (w == null)
895
- w = dummyDiv.children().width();
896
- if (h == null)
897
- h = dummyDiv.find("div.tickLabel").height();
898
- dummyDiv.remove();
899
- }
900
- }
901
-
902
- if (w == null)
903
- w = 0;
904
- if (h == null)
905
- h = 0;
906
-
907
- axis.labelWidth = w;
908
- axis.labelHeight = h;
909
- }
910
-
911
- function allocateAxisBoxFirstPhase(axis) {
912
- // find the bounding box of the axis by looking at label
913
- // widths/heights and ticks, make room by diminishing the
914
- // plotOffset
915
-
916
- var lw = axis.labelWidth,
917
- lh = axis.labelHeight,
918
- pos = axis.options.position,
919
- tickLength = axis.options.tickLength,
920
- axismargin = options.grid.axisMargin,
921
- padding = options.grid.labelMargin,
922
- all = axis.direction == "x" ? xaxes : yaxes,
923
- index;
924
-
925
- // determine axis margin
926
- var samePosition = $.grep(all, function (a) {
927
- return a && a.options.position == pos && a.reserveSpace;
928
- });
929
- if ($.inArray(axis, samePosition) == samePosition.length - 1)
930
- axismargin = 0; // outermost
931
-
932
- // determine tick length - if we're innermost, we can use "full"
933
- if (tickLength == null)
934
- tickLength = "full";
935
-
936
- var sameDirection = $.grep(all, function (a) {
937
- return a && a.reserveSpace;
938
- });
939
-
940
- var innermost = $.inArray(axis, sameDirection) == 0;
941
- if (!innermost && tickLength == "full")
942
- tickLength = 5;
943
-
944
- if (!isNaN(+tickLength))
945
- padding += +tickLength;
946
-
947
- // compute box
948
- if (axis.direction == "x") {
949
- lh += padding;
950
-
951
- if (pos == "bottom") {
952
- plotOffset.bottom += lh + axismargin;
953
- axis.box = { top: canvasHeight - plotOffset.bottom, height: lh };
954
- }
955
- else {
956
- axis.box = { top: plotOffset.top + axismargin, height: lh };
957
- plotOffset.top += lh + axismargin;
958
- }
959
- }
960
- else {
961
- lw += padding;
962
-
963
- if (pos == "left") {
964
- axis.box = { left: plotOffset.left + axismargin, width: lw };
965
- plotOffset.left += lw + axismargin;
966
- }
967
- else {
968
- plotOffset.right += lw + axismargin;
969
- axis.box = { left: canvasWidth - plotOffset.right, width: lw };
970
- }
971
- }
972
-
973
- // save for future reference
974
- axis.position = pos;
975
- axis.tickLength = tickLength;
976
- axis.box.padding = padding;
977
- axis.innermost = innermost;
978
- }
979
-
980
- function allocateAxisBoxSecondPhase(axis) {
981
- // set remaining bounding box coordinates
982
- if (axis.direction == "x") {
983
- axis.box.left = plotOffset.left;
984
- axis.box.width = plotWidth;
985
- }
986
- else {
987
- axis.box.top = plotOffset.top;
988
- axis.box.height = plotHeight;
989
- }
990
- }
991
-
992
- function setupGrid() {
993
- var i, axes = allAxes();
994
-
995
- // first calculate the plot and axis box dimensions
996
-
997
- $.each(axes, function (_, axis) {
998
- axis.show = axis.options.show;
999
- if (axis.show == null)
1000
- axis.show = axis.used; // by default an axis is visible if it's got data
1001
-
1002
- axis.reserveSpace = axis.show || axis.options.reserveSpace;
1003
-
1004
- setRange(axis);
1005
- });
1006
-
1007
- allocatedAxes = $.grep(axes, function (axis) { return axis.reserveSpace; });
1008
-
1009
- plotOffset.left = plotOffset.right = plotOffset.top = plotOffset.bottom = 0;
1010
- if (options.grid.show) {
1011
- $.each(allocatedAxes, function (_, axis) {
1012
- // make the ticks
1013
- setupTickGeneration(axis);
1014
- setTicks(axis);
1015
- snapRangeToTicks(axis, axis.ticks);
1016
-
1017
- // find labelWidth/Height for axis
1018
- measureTickLabels(axis);
1019
- });
1020
-
1021
- // with all dimensions in house, we can compute the
1022
- // axis boxes, start from the outside (reverse order)
1023
- for (i = allocatedAxes.length - 1; i >= 0; --i)
1024
- allocateAxisBoxFirstPhase(allocatedAxes[i]);
1025
-
1026
- // make sure we've got enough space for things that
1027
- // might stick out
1028
- var minMargin = options.grid.minBorderMargin;
1029
- if (minMargin == null) {
1030
- minMargin = 0;
1031
- for (i = 0; i < series.length; ++i)
1032
- minMargin = Math.max(minMargin, series[i].points.radius + series[i].points.lineWidth/2);
1033
- }
1034
-
1035
- for (var a in plotOffset) {
1036
- plotOffset[a] += options.grid.borderWidth;
1037
- plotOffset[a] = Math.max(minMargin, plotOffset[a]);
1038
- }
1039
- }
1040
-
1041
- plotWidth = canvasWidth - plotOffset.left - plotOffset.right;
1042
- plotHeight = canvasHeight - plotOffset.bottom - plotOffset.top;
1043
-
1044
- // now we got the proper plotWidth/Height, we can compute the scaling
1045
- $.each(axes, function (_, axis) {
1046
- setTransformationHelpers(axis);
1047
- });
1048
-
1049
- if (options.grid.show) {
1050
- $.each(allocatedAxes, function (_, axis) {
1051
- allocateAxisBoxSecondPhase(axis);
1052
- });
1053
-
1054
- insertAxisLabels();
1055
- }
1056
-
1057
- insertLegend();
1058
- }
1059
-
1060
- function setRange(axis) {
1061
- var opts = axis.options,
1062
- min = +(opts.min != null ? opts.min : axis.datamin),
1063
- max = +(opts.max != null ? opts.max : axis.datamax),
1064
- delta = max - min;
1065
-
1066
- if (delta == 0.0) {
1067
- // degenerate case
1068
- var widen = max == 0 ? 1 : 0.01;
1069
-
1070
- if (opts.min == null)
1071
- min -= widen;
1072
- // always widen max if we couldn't widen min to ensure we
1073
- // don't fall into min == max which doesn't work
1074
- if (opts.max == null || opts.min != null)
1075
- max += widen;
1076
- }
1077
- else {
1078
- // consider autoscaling
1079
- var margin = opts.autoscaleMargin;
1080
- if (margin != null) {
1081
- if (opts.min == null) {
1082
- min -= delta * margin;
1083
- // make sure we don't go below zero if all values
1084
- // are positive
1085
- if (min < 0 && axis.datamin != null && axis.datamin >= 0)
1086
- min = 0;
1087
- }
1088
- if (opts.max == null) {
1089
- max += delta * margin;
1090
- if (max > 0 && axis.datamax != null && axis.datamax <= 0)
1091
- max = 0;
1092
- }
1093
- }
1094
- }
1095
- axis.min = min;
1096
- axis.max = max;
1097
- }
1098
-
1099
- function setupTickGeneration(axis) {
1100
- var opts = axis.options;
1101
-
1102
- // estimate number of ticks
1103
- var noTicks;
1104
- if (typeof opts.ticks == "number" && opts.ticks > 0)
1105
- noTicks = opts.ticks;
1106
- else
1107
- // heuristic based on the model a*sqrt(x) fitted to
1108
- // some data points that seemed reasonable
1109
- noTicks = 0.3 * Math.sqrt(axis.direction == "x" ? canvasWidth : canvasHeight);
1110
-
1111
- var delta = (axis.max - axis.min) / noTicks,
1112
- size, generator, unit, formatter, i, magn, norm;
1113
-
1114
- if (opts.mode == "time") {
1115
- // pretty handling of time
1116
-
1117
- // map of app. size of time units in milliseconds
1118
- var timeUnitSize = {
1119
- "second": 1000,
1120
- "minute": 60 * 1000,
1121
- "hour": 60 * 60 * 1000,
1122
- "day": 24 * 60 * 60 * 1000,
1123
- "month": 30 * 24 * 60 * 60 * 1000,
1124
- "year": 365.2425 * 24 * 60 * 60 * 1000
1125
- };
1126
-
1127
-
1128
- // the allowed tick sizes, after 1 year we use
1129
- // an integer algorithm
1130
- var spec = [
1131
- [1, "second"], [2, "second"], [5, "second"], [10, "second"],
1132
- [30, "second"],
1133
- [1, "minute"], [2, "minute"], [5, "minute"], [10, "minute"],
1134
- [30, "minute"],
1135
- [1, "hour"], [2, "hour"], [4, "hour"],
1136
- [8, "hour"], [12, "hour"],
1137
- [1, "day"], [2, "day"], [3, "day"],
1138
- [0.25, "month"], [0.5, "month"], [1, "month"],
1139
- [2, "month"], [3, "month"], [6, "month"],
1140
- [1, "year"]
1141
- ];
1142
-
1143
- var minSize = 0;
1144
- if (opts.minTickSize != null) {
1145
- if (typeof opts.tickSize == "number")
1146
- minSize = opts.tickSize;
1147
- else
1148
- minSize = opts.minTickSize[0] * timeUnitSize[opts.minTickSize[1]];
1149
- }
1150
-
1151
- for (var i = 0; i < spec.length - 1; ++i)
1152
- if (delta < (spec[i][0] * timeUnitSize[spec[i][1]]
1153
- + spec[i + 1][0] * timeUnitSize[spec[i + 1][1]]) / 2
1154
- && spec[i][0] * timeUnitSize[spec[i][1]] >= minSize)
1155
- break;
1156
- size = spec[i][0];
1157
- unit = spec[i][1];
1158
-
1159
- // special-case the possibility of several years
1160
- if (unit == "year") {
1161
- magn = Math.pow(10, Math.floor(Math.log(delta / timeUnitSize.year) / Math.LN10));
1162
- norm = (delta / timeUnitSize.year) / magn;
1163
- if (norm < 1.5)
1164
- size = 1;
1165
- else if (norm < 3)
1166
- size = 2;
1167
- else if (norm < 7.5)
1168
- size = 5;
1169
- else
1170
- size = 10;
1171
-
1172
- size *= magn;
1173
- }
1174
-
1175
- axis.tickSize = opts.tickSize || [size, unit];
1176
-
1177
- generator = function(axis) {
1178
- var ticks = [],
1179
- tickSize = axis.tickSize[0], unit = axis.tickSize[1],
1180
- d = new Date(axis.min);
1181
-
1182
- var step = tickSize * timeUnitSize[unit];
1183
-
1184
- if (unit == "second")
1185
- d.setUTCSeconds(floorInBase(d.getUTCSeconds(), tickSize));
1186
- if (unit == "minute")
1187
- d.setUTCMinutes(floorInBase(d.getUTCMinutes(), tickSize));
1188
- if (unit == "hour")
1189
- d.setUTCHours(floorInBase(d.getUTCHours(), tickSize));
1190
- if (unit == "month")
1191
- d.setUTCMonth(floorInBase(d.getUTCMonth(), tickSize));
1192
- if (unit == "year")
1193
- d.setUTCFullYear(floorInBase(d.getUTCFullYear(), tickSize));
1194
-
1195
- // reset smaller components
1196
- d.setUTCMilliseconds(0);
1197
- if (step >= timeUnitSize.minute)
1198
- d.setUTCSeconds(0);
1199
- if (step >= timeUnitSize.hour)
1200
- d.setUTCMinutes(0);
1201
- if (step >= timeUnitSize.day)
1202
- d.setUTCHours(0);
1203
- if (step >= timeUnitSize.day * 4)
1204
- d.setUTCDate(1);
1205
- if (step >= timeUnitSize.year)
1206
- d.setUTCMonth(0);
1207
-
1208
-
1209
- var carry = 0, v = Number.NaN, prev;
1210
- do {
1211
- prev = v;
1212
- v = d.getTime();
1213
- ticks.push(v);
1214
- if (unit == "month") {
1215
- if (tickSize < 1) {
1216
- // a bit complicated - we'll divide the month
1217
- // up but we need to take care of fractions
1218
- // so we don't end up in the middle of a day
1219
- d.setUTCDate(1);
1220
- var start = d.getTime();
1221
- d.setUTCMonth(d.getUTCMonth() + 1);
1222
- var end = d.getTime();
1223
- d.setTime(v + carry * timeUnitSize.hour + (end - start) * tickSize);
1224
- carry = d.getUTCHours();
1225
- d.setUTCHours(0);
1226
- }
1227
- else
1228
- d.setUTCMonth(d.getUTCMonth() + tickSize);
1229
- }
1230
- else if (unit == "year") {
1231
- d.setUTCFullYear(d.getUTCFullYear() + tickSize);
1232
- }
1233
- else
1234
- d.setTime(v + step);
1235
- } while (v < axis.max && v != prev);
1236
-
1237
- return ticks;
1238
- };
1239
-
1240
- formatter = function (v, axis) {
1241
- var d = new Date(v);
1242
-
1243
- // first check global format
1244
- if (opts.timeformat != null)
1245
- return $.plot.formatDate(d, opts.timeformat, opts.monthNames);
1246
-
1247
- var t = axis.tickSize[0] * timeUnitSize[axis.tickSize[1]];
1248
- var span = axis.max - axis.min;
1249
- var suffix = (opts.twelveHourClock) ? " %p" : "";
1250
-
1251
- if (t < timeUnitSize.minute)
1252
- fmt = "%h:%M:%S" + suffix;
1253
- else if (t < timeUnitSize.day) {
1254
- if (span < 2 * timeUnitSize.day)
1255
- fmt = "%h:%M" + suffix;
1256
- else
1257
- fmt = "%b %d %h:%M" + suffix;
1258
- }
1259
- else if (t < timeUnitSize.month)
1260
- fmt = "%b %d";
1261
- else if (t < timeUnitSize.year) {
1262
- if (span < timeUnitSize.year)
1263
- fmt = "%b";
1264
- else
1265
- fmt = "%b %y";
1266
- }
1267
- else
1268
- fmt = "%y";
1269
-
1270
- return $.plot.formatDate(d, fmt, opts.monthNames);
1271
- };
1272
- }
1273
- else {
1274
- // pretty rounding of base-10 numbers
1275
- var maxDec = opts.tickDecimals;
1276
- var dec = -Math.floor(Math.log(delta) / Math.LN10);
1277
- if (maxDec != null && dec > maxDec)
1278
- dec = maxDec;
1279
-
1280
- magn = Math.pow(10, -dec);
1281
- norm = delta / magn; // norm is between 1.0 and 10.0
1282
-
1283
- if (norm < 1.5)
1284
- size = 1;
1285
- else if (norm < 3) {
1286
- size = 2;
1287
- // special case for 2.5, requires an extra decimal
1288
- if (norm > 2.25 && (maxDec == null || dec + 1 <= maxDec)) {
1289
- size = 2.5;
1290
- ++dec;
1291
- }
1292
- }
1293
- else if (norm < 7.5)
1294
- size = 5;
1295
- else
1296
- size = 10;
1297
-
1298
- size *= magn;
1299
-
1300
- if (opts.minTickSize != null && size < opts.minTickSize)
1301
- size = opts.minTickSize;
1302
-
1303
- axis.tickDecimals = Math.max(0, maxDec != null ? maxDec : dec);
1304
- axis.tickSize = opts.tickSize || size;
1305
-
1306
- generator = function (axis) {
1307
- var ticks = [];
1308
-
1309
- // spew out all possible ticks
1310
- var start = floorInBase(axis.min, axis.tickSize),
1311
- i = 0, v = Number.NaN, prev;
1312
- do {
1313
- prev = v;
1314
- v = start + i * axis.tickSize;
1315
- ticks.push(v);
1316
- ++i;
1317
- } while (v < axis.max && v != prev);
1318
- return ticks;
1319
- };
1320
-
1321
- formatter = function (v, axis) {
1322
- return v.toFixed(axis.tickDecimals);
1323
- };
1324
- }
1325
-
1326
- if (opts.alignTicksWithAxis != null) {
1327
- var otherAxis = (axis.direction == "x" ? xaxes : yaxes)[opts.alignTicksWithAxis - 1];
1328
- if (otherAxis && otherAxis.used && otherAxis != axis) {
1329
- // consider snapping min/max to outermost nice ticks
1330
- var niceTicks = generator(axis);
1331
- if (niceTicks.length > 0) {
1332
- if (opts.min == null)
1333
- axis.min = Math.min(axis.min, niceTicks[0]);
1334
- if (opts.max == null && niceTicks.length > 1)
1335
- axis.max = Math.max(axis.max, niceTicks[niceTicks.length - 1]);
1336
- }
1337
-
1338
- generator = function (axis) {
1339
- // copy ticks, scaled to this axis
1340
- var ticks = [], v, i;
1341
- for (i = 0; i < otherAxis.ticks.length; ++i) {
1342
- v = (otherAxis.ticks[i].v - otherAxis.min) / (otherAxis.max - otherAxis.min);
1343
- v = axis.min + v * (axis.max - axis.min);
1344
- ticks.push(v);
1345
- }
1346
- return ticks;
1347
- };
1348
-
1349
- // we might need an extra decimal since forced
1350
- // ticks don't necessarily fit naturally
1351
- if (axis.mode != "time" && opts.tickDecimals == null) {
1352
- var extraDec = Math.max(0, -Math.floor(Math.log(delta) / Math.LN10) + 1),
1353
- ts = generator(axis);
1354
-
1355
- // only proceed if the tick interval rounded
1356
- // with an extra decimal doesn't give us a
1357
- // zero at end
1358
- if (!(ts.length > 1 && /\..*0$/.test((ts[1] - ts[0]).toFixed(extraDec))))
1359
- axis.tickDecimals = extraDec;
1360
- }
1361
- }
1362
- }
1363
-
1364
- axis.tickGenerator = generator;
1365
- if ($.isFunction(opts.tickFormatter))
1366
- axis.tickFormatter = function (v, axis) { return "" + opts.tickFormatter(v, axis); };
1367
- else
1368
- axis.tickFormatter = formatter;
1369
- }
1370
-
1371
- function setTicks(axis) {
1372
- var oticks = axis.options.ticks, ticks = [];
1373
- if (oticks == null || (typeof oticks == "number" && oticks > 0))
1374
- ticks = axis.tickGenerator(axis);
1375
- else if (oticks) {
1376
- if ($.isFunction(oticks))
1377
- // generate the ticks
1378
- ticks = oticks({ min: axis.min, max: axis.max });
1379
- else
1380
- ticks = oticks;
1381
- }
1382
-
1383
- // clean up/labelify the supplied ticks, copy them over
1384
- var i, v;
1385
- axis.ticks = [];
1386
- for (i = 0; i < ticks.length; ++i) {
1387
- var label = null;
1388
- var t = ticks[i];
1389
- if (typeof t == "object") {
1390
- v = +t[0];
1391
- if (t.length > 1)
1392
- label = t[1];
1393
- }
1394
- else
1395
- v = +t;
1396
- if (label == null)
1397
- label = axis.tickFormatter(v, axis);
1398
- if (!isNaN(v))
1399
- axis.ticks.push({ v: v, label: label });
1400
- }
1401
- }
1402
-
1403
- function snapRangeToTicks(axis, ticks) {
1404
- if (axis.options.autoscaleMargin && ticks.length > 0) {
1405
- // snap to ticks
1406
- if (axis.options.min == null)
1407
- axis.min = Math.min(axis.min, ticks[0].v);
1408
- if (axis.options.max == null && ticks.length > 1)
1409
- axis.max = Math.max(axis.max, ticks[ticks.length - 1].v);
1410
- }
1411
- }
1412
-
1413
- function draw() {
1414
- ctx.clearRect(0, 0, canvasWidth, canvasHeight);
1415
-
1416
- var grid = options.grid;
1417
-
1418
- // draw background, if any
1419
- if (grid.show && grid.backgroundColor)
1420
- drawBackground();
1421
-
1422
- if (grid.show && !grid.aboveData)
1423
- drawGrid();
1424
-
1425
- for (var i = 0; i < series.length; ++i) {
1426
- executeHooks(hooks.drawSeries, [ctx, series[i]]);
1427
- drawSeries(series[i]);
1428
- }
1429
-
1430
- executeHooks(hooks.draw, [ctx]);
1431
-
1432
- if (grid.show && grid.aboveData)
1433
- drawGrid();
1434
- }
1435
-
1436
- function extractRange(ranges, coord) {
1437
- var axis, from, to, key, axes = allAxes();
1438
-
1439
- for (i = 0; i < axes.length; ++i) {
1440
- axis = axes[i];
1441
- if (axis.direction == coord) {
1442
- key = coord + axis.n + "axis";
1443
- if (!ranges[key] && axis.n == 1)
1444
- key = coord + "axis"; // support x1axis as xaxis
1445
- if (ranges[key]) {
1446
- from = ranges[key].from;
1447
- to = ranges[key].to;
1448
- break;
1449
- }
1450
- }
1451
- }
1452
-
1453
- // backwards-compat stuff - to be removed in future
1454
- if (!ranges[key]) {
1455
- axis = coord == "x" ? xaxes[0] : yaxes[0];
1456
- from = ranges[coord + "1"];
1457
- to = ranges[coord + "2"];
1458
- }
1459
-
1460
- // auto-reverse as an added bonus
1461
- if (from != null && to != null && from > to) {
1462
- var tmp = from;
1463
- from = to;
1464
- to = tmp;
1465
- }
1466
-
1467
- return { from: from, to: to, axis: axis };
1468
- }
1469
-
1470
- function drawBackground() {
1471
- ctx.save();
1472
- ctx.translate(plotOffset.left, plotOffset.top);
1473
-
1474
- ctx.fillStyle = getColorOrGradient(options.grid.backgroundColor, plotHeight, 0, "rgba(255, 255, 255, 0)");
1475
- ctx.fillRect(0, 0, plotWidth, plotHeight);
1476
- ctx.restore();
1477
- }
1478
-
1479
- function drawGrid() {
1480
- var i;
1481
-
1482
- ctx.save();
1483
- ctx.translate(plotOffset.left, plotOffset.top);
1484
-
1485
- // draw markings
1486
- var markings = options.grid.markings;
1487
- if (markings) {
1488
- if ($.isFunction(markings)) {
1489
- var axes = plot.getAxes();
1490
- // xmin etc. is backwards compatibility, to be
1491
- // removed in the future
1492
- axes.xmin = axes.xaxis.min;
1493
- axes.xmax = axes.xaxis.max;
1494
- axes.ymin = axes.yaxis.min;
1495
- axes.ymax = axes.yaxis.max;
1496
-
1497
- markings = markings(axes);
1498
- }
1499
-
1500
- for (i = 0; i < markings.length; ++i) {
1501
- var m = markings[i],
1502
- xrange = extractRange(m, "x"),
1503
- yrange = extractRange(m, "y");
1504
-
1505
- // fill in missing
1506
- if (xrange.from == null)
1507
- xrange.from = xrange.axis.min;
1508
- if (xrange.to == null)
1509
- xrange.to = xrange.axis.max;
1510
- if (yrange.from == null)
1511
- yrange.from = yrange.axis.min;
1512
- if (yrange.to == null)
1513
- yrange.to = yrange.axis.max;
1514
-
1515
- // clip
1516
- if (xrange.to < xrange.axis.min || xrange.from > xrange.axis.max ||
1517
- yrange.to < yrange.axis.min || yrange.from > yrange.axis.max)
1518
- continue;
1519
-
1520
- xrange.from = Math.max(xrange.from, xrange.axis.min);
1521
- xrange.to = Math.min(xrange.to, xrange.axis.max);
1522
- yrange.from = Math.max(yrange.from, yrange.axis.min);
1523
- yrange.to = Math.min(yrange.to, yrange.axis.max);
1524
-
1525
- if (xrange.from == xrange.to && yrange.from == yrange.to)
1526
- continue;
1527
-
1528
- // then draw
1529
- xrange.from = xrange.axis.p2c(xrange.from);
1530
- xrange.to = xrange.axis.p2c(xrange.to);
1531
- yrange.from = yrange.axis.p2c(yrange.from);
1532
- yrange.to = yrange.axis.p2c(yrange.to);
1533
-
1534
- if (xrange.from == xrange.to || yrange.from == yrange.to) {
1535
- // draw line
1536
- ctx.beginPath();
1537
- ctx.strokeStyle = m.color || options.grid.markingsColor;
1538
- ctx.lineWidth = m.lineWidth || options.grid.markingsLineWidth;
1539
- ctx.moveTo(xrange.from, yrange.from);
1540
- ctx.lineTo(xrange.to, yrange.to);
1541
- ctx.stroke();
1542
- }
1543
- else {
1544
- // fill area
1545
- ctx.fillStyle = m.color || options.grid.markingsColor;
1546
- ctx.fillRect(xrange.from, yrange.to,
1547
- xrange.to - xrange.from,
1548
- yrange.from - yrange.to);
1549
- }
1550
- }
1551
- }
1552
-
1553
- // draw the ticks
1554
- var axes = allAxes(), bw = options.grid.borderWidth;
1555
-
1556
- for (var j = 0; j < axes.length; ++j) {
1557
- var axis = axes[j], box = axis.box,
1558
- t = axis.tickLength, x, y, xoff, yoff;
1559
- if (!axis.show || axis.ticks.length == 0)
1560
- continue
1561
-
1562
- ctx.strokeStyle = axis.options.tickColor || $.color.parse(axis.options.color).scale('a', 0.22).toString();
1563
- ctx.lineWidth = 1;
1564
-
1565
- // find the edges
1566
- if (axis.direction == "x") {
1567
- x = 0;
1568
- if (t == "full")
1569
- y = (axis.position == "top" ? 0 : plotHeight);
1570
- else
1571
- y = box.top - plotOffset.top + (axis.position == "top" ? box.height : 0);
1572
- }
1573
- else {
1574
- y = 0;
1575
- if (t == "full")
1576
- x = (axis.position == "left" ? 0 : plotWidth);
1577
- else
1578
- x = box.left - plotOffset.left + (axis.position == "left" ? box.width : 0);
1579
- }
1580
-
1581
- // draw tick bar
1582
- if (!axis.innermost) {
1583
- ctx.beginPath();
1584
- xoff = yoff = 0;
1585
- if (axis.direction == "x")
1586
- xoff = plotWidth;
1587
- else
1588
- yoff = plotHeight;
1589
-
1590
- if (ctx.lineWidth == 1) {
1591
- x = Math.floor(x) + 0.5;
1592
- y = Math.floor(y) + 0.5;
1593
- }
1594
-
1595
- ctx.moveTo(x, y);
1596
- ctx.lineTo(x + xoff, y + yoff);
1597
- ctx.stroke();
1598
- }
1599
-
1600
- // draw ticks
1601
- ctx.beginPath();
1602
- for (i = 0; i < axis.ticks.length; ++i) {
1603
- var v = axis.ticks[i].v;
1604
-
1605
- xoff = yoff = 0;
1606
-
1607
- if (v < axis.min || v > axis.max
1608
- // skip those lying on the axes if we got a border
1609
- || (t == "full" && bw > 0
1610
- && (v == axis.min || v == axis.max)))
1611
- continue;
1612
-
1613
- if (axis.direction == "x") {
1614
- x = axis.p2c(v);
1615
- yoff = t == "full" ? -plotHeight : t;
1616
-
1617
- if (axis.position == "top")
1618
- yoff = -yoff;
1619
- }
1620
- else {
1621
- y = axis.p2c(v);
1622
- xoff = t == "full" ? -plotWidth : t;
1623
-
1624
- if (axis.position == "left")
1625
- xoff = -xoff;
1626
- }
1627
-
1628
- if (ctx.lineWidth == 1) {
1629
- if (axis.direction == "x")
1630
- x = Math.floor(x) + 0.5;
1631
- else
1632
- y = Math.floor(y) + 0.5;
1633
- }
1634
-
1635
- ctx.moveTo(x, y);
1636
- ctx.lineTo(x + xoff, y + yoff);
1637
- }
1638
-
1639
- ctx.stroke();
1640
- }
1641
-
1642
-
1643
- // draw border
1644
- if (bw) {
1645
- ctx.lineWidth = bw;
1646
- ctx.strokeStyle = options.grid.borderColor;
1647
- ctx.strokeRect(-bw/2, -bw/2, plotWidth + bw, plotHeight + bw);
1648
- }
1649
-
1650
- ctx.restore();
1651
- }
1652
-
1653
- function insertAxisLabels() {
1654
- placeholder.find(".tickLabels").remove();
1655
-
1656
- var html = ['<div class="tickLabels" style="font-size:smaller">'];
1657
-
1658
- var axes = allAxes();
1659
- for (var j = 0; j < axes.length; ++j) {
1660
- var axis = axes[j], box = axis.box;
1661
- if (!axis.show)
1662
- continue;
1663
- //debug: html.push('<div style="position:absolute;opacity:0.10;background-color:red;left:' + box.left + 'px;top:' + box.top + 'px;width:' + box.width + 'px;height:' + box.height + 'px"></div>')
1664
- html.push('<div class="' + axis.direction + 'Axis ' + axis.direction + axis.n + 'Axis" style="color:' + axis.options.color + '">');
1665
- for (var i = 0; i < axis.ticks.length; ++i) {
1666
- var tick = axis.ticks[i];
1667
- if (!tick.label || tick.v < axis.min || tick.v > axis.max)
1668
- continue;
1669
-
1670
- var pos = {}, align;
1671
-
1672
- if (axis.direction == "x") {
1673
- align = "center";
1674
- pos.left = Math.round(plotOffset.left + axis.p2c(tick.v) - axis.labelWidth/2);
1675
- if (axis.position == "bottom")
1676
- pos.top = box.top + box.padding;
1677
- else
1678
- pos.bottom = canvasHeight - (box.top + box.height - box.padding);
1679
- }
1680
- else {
1681
- pos.top = Math.round(plotOffset.top + axis.p2c(tick.v) - axis.labelHeight/2);
1682
- if (axis.position == "left") {
1683
- pos.right = canvasWidth - (box.left + box.width - box.padding)
1684
- align = "right";
1685
- }
1686
- else {
1687
- pos.left = box.left + box.padding;
1688
- align = "left";
1689
- }
1690
- }
1691
-
1692
- pos.width = axis.labelWidth;
1693
-
1694
- var style = ["position:absolute", "text-align:" + align ];
1695
- for (var a in pos)
1696
- style.push(a + ":" + pos[a] + "px")
1697
-
1698
- html.push('<div class="tickLabel" style="' + style.join(';') + '">' + tick.label + '</div>');
1699
- }
1700
- html.push('</div>');
1701
- }
1702
-
1703
- html.push('</div>');
1704
-
1705
- placeholder.append(html.join(""));
1706
- }
1707
-
1708
- function drawSeries(series) {
1709
- if (series.lines.show)
1710
- drawSeriesLines(series);
1711
- if (series.bars.show)
1712
- drawSeriesBars(series);
1713
- if (series.points.show)
1714
- drawSeriesPoints(series);
1715
- }
1716
-
1717
- function drawSeriesLines(series) {
1718
- function plotLine(datapoints, xoffset, yoffset, axisx, axisy) {
1719
- var points = datapoints.points,
1720
- ps = datapoints.pointsize,
1721
- prevx = null, prevy = null;
1722
-
1723
- ctx.beginPath();
1724
- for (var i = ps; i < points.length; i += ps) {
1725
- var x1 = points[i - ps], y1 = points[i - ps + 1],
1726
- x2 = points[i], y2 = points[i + 1];
1727
-
1728
- if (x1 == null || x2 == null)
1729
- continue;
1730
-
1731
- // clip with ymin
1732
- if (y1 <= y2 && y1 < axisy.min) {
1733
- if (y2 < axisy.min)
1734
- continue; // line segment is outside
1735
- // compute new intersection point
1736
- x1 = (axisy.min - y1) / (y2 - y1) * (x2 - x1) + x1;
1737
- y1 = axisy.min;
1738
- }
1739
- else if (y2 <= y1 && y2 < axisy.min) {
1740
- if (y1 < axisy.min)
1741
- continue;
1742
- x2 = (axisy.min - y1) / (y2 - y1) * (x2 - x1) + x1;
1743
- y2 = axisy.min;
1744
- }
1745
-
1746
- // clip with ymax
1747
- if (y1 >= y2 && y1 > axisy.max) {
1748
- if (y2 > axisy.max)
1749
- continue;
1750
- x1 = (axisy.max - y1) / (y2 - y1) * (x2 - x1) + x1;
1751
- y1 = axisy.max;
1752
- }
1753
- else if (y2 >= y1 && y2 > axisy.max) {
1754
- if (y1 > axisy.max)
1755
- continue;
1756
- x2 = (axisy.max - y1) / (y2 - y1) * (x2 - x1) + x1;
1757
- y2 = axisy.max;
1758
- }
1759
-
1760
- // clip with xmin
1761
- if (x1 <= x2 && x1 < axisx.min) {
1762
- if (x2 < axisx.min)
1763
- continue;
1764
- y1 = (axisx.min - x1) / (x2 - x1) * (y2 - y1) + y1;
1765
- x1 = axisx.min;
1766
- }
1767
- else if (x2 <= x1 && x2 < axisx.min) {
1768
- if (x1 < axisx.min)
1769
- continue;
1770
- y2 = (axisx.min - x1) / (x2 - x1) * (y2 - y1) + y1;
1771
- x2 = axisx.min;
1772
- }
1773
-
1774
- // clip with xmax
1775
- if (x1 >= x2 && x1 > axisx.max) {
1776
- if (x2 > axisx.max)
1777
- continue;
1778
- y1 = (axisx.max - x1) / (x2 - x1) * (y2 - y1) + y1;
1779
- x1 = axisx.max;
1780
- }
1781
- else if (x2 >= x1 && x2 > axisx.max) {
1782
- if (x1 > axisx.max)
1783
- continue;
1784
- y2 = (axisx.max - x1) / (x2 - x1) * (y2 - y1) + y1;
1785
- x2 = axisx.max;
1786
- }
1787
-
1788
- if (x1 != prevx || y1 != prevy)
1789
- ctx.moveTo(axisx.p2c(x1) + xoffset, axisy.p2c(y1) + yoffset);
1790
-
1791
- prevx = x2;
1792
- prevy = y2;
1793
- ctx.lineTo(axisx.p2c(x2) + xoffset, axisy.p2c(y2) + yoffset);
1794
- }
1795
- ctx.stroke();
1796
- }
1797
-
1798
- function plotLineArea(datapoints, axisx, axisy) {
1799
- var points = datapoints.points,
1800
- ps = datapoints.pointsize,
1801
- bottom = Math.min(Math.max(0, axisy.min), axisy.max),
1802
- i = 0, top, areaOpen = false,
1803
- ypos = 1, segmentStart = 0, segmentEnd = 0;
1804
-
1805
- // we process each segment in two turns, first forward
1806
- // direction to sketch out top, then once we hit the
1807
- // end we go backwards to sketch the bottom
1808
- while (true) {
1809
- if (ps > 0 && i > points.length + ps)
1810
- break;
1811
-
1812
- i += ps; // ps is negative if going backwards
1813
-
1814
- var x1 = points[i - ps],
1815
- y1 = points[i - ps + ypos],
1816
- x2 = points[i], y2 = points[i + ypos];
1817
-
1818
- if (areaOpen) {
1819
- if (ps > 0 && x1 != null && x2 == null) {
1820
- // at turning point
1821
- segmentEnd = i;
1822
- ps = -ps;
1823
- ypos = 2;
1824
- continue;
1825
- }
1826
-
1827
- if (ps < 0 && i == segmentStart + ps) {
1828
- // done with the reverse sweep
1829
- ctx.fill();
1830
- areaOpen = false;
1831
- ps = -ps;
1832
- ypos = 1;
1833
- i = segmentStart = segmentEnd + ps;
1834
- continue;
1835
- }
1836
- }
1837
-
1838
- if (x1 == null || x2 == null)
1839
- continue;
1840
-
1841
- // clip x values
1842
-
1843
- // clip with xmin
1844
- if (x1 <= x2 && x1 < axisx.min) {
1845
- if (x2 < axisx.min)
1846
- continue;
1847
- y1 = (axisx.min - x1) / (x2 - x1) * (y2 - y1) + y1;
1848
- x1 = axisx.min;
1849
- }
1850
- else if (x2 <= x1 && x2 < axisx.min) {
1851
- if (x1 < axisx.min)
1852
- continue;
1853
- y2 = (axisx.min - x1) / (x2 - x1) * (y2 - y1) + y1;
1854
- x2 = axisx.min;
1855
- }
1856
-
1857
- // clip with xmax
1858
- if (x1 >= x2 && x1 > axisx.max) {
1859
- if (x2 > axisx.max)
1860
- continue;
1861
- y1 = (axisx.max - x1) / (x2 - x1) * (y2 - y1) + y1;
1862
- x1 = axisx.max;
1863
- }
1864
- else if (x2 >= x1 && x2 > axisx.max) {
1865
- if (x1 > axisx.max)
1866
- continue;
1867
- y2 = (axisx.max - x1) / (x2 - x1) * (y2 - y1) + y1;
1868
- x2 = axisx.max;
1869
- }
1870
-
1871
- if (!areaOpen) {
1872
- // open area
1873
- ctx.beginPath();
1874
- ctx.moveTo(axisx.p2c(x1), axisy.p2c(bottom));
1875
- areaOpen = true;
1876
- }
1877
-
1878
- // now first check the case where both is outside
1879
- if (y1 >= axisy.max && y2 >= axisy.max) {
1880
- ctx.lineTo(axisx.p2c(x1), axisy.p2c(axisy.max));
1881
- ctx.lineTo(axisx.p2c(x2), axisy.p2c(axisy.max));
1882
- continue;
1883
- }
1884
- else if (y1 <= axisy.min && y2 <= axisy.min) {
1885
- ctx.lineTo(axisx.p2c(x1), axisy.p2c(axisy.min));
1886
- ctx.lineTo(axisx.p2c(x2), axisy.p2c(axisy.min));
1887
- continue;
1888
- }
1889
-
1890
- // else it's a bit more complicated, there might
1891
- // be a flat maxed out rectangle first, then a
1892
- // triangular cutout or reverse; to find these
1893
- // keep track of the current x values
1894
- var x1old = x1, x2old = x2;
1895
-
1896
- // clip the y values, without shortcutting, we
1897
- // go through all cases in turn
1898
-
1899
- // clip with ymin
1900
- if (y1 <= y2 && y1 < axisy.min && y2 >= axisy.min) {
1901
- x1 = (axisy.min - y1) / (y2 - y1) * (x2 - x1) + x1;
1902
- y1 = axisy.min;
1903
- }
1904
- else if (y2 <= y1 && y2 < axisy.min && y1 >= axisy.min) {
1905
- x2 = (axisy.min - y1) / (y2 - y1) * (x2 - x1) + x1;
1906
- y2 = axisy.min;
1907
- }
1908
-
1909
- // clip with ymax
1910
- if (y1 >= y2 && y1 > axisy.max && y2 <= axisy.max) {
1911
- x1 = (axisy.max - y1) / (y2 - y1) * (x2 - x1) + x1;
1912
- y1 = axisy.max;
1913
- }
1914
- else if (y2 >= y1 && y2 > axisy.max && y1 <= axisy.max) {
1915
- x2 = (axisy.max - y1) / (y2 - y1) * (x2 - x1) + x1;
1916
- y2 = axisy.max;
1917
- }
1918
-
1919
- // if the x value was changed we got a rectangle
1920
- // to fill
1921
- if (x1 != x1old) {
1922
- ctx.lineTo(axisx.p2c(x1old), axisy.p2c(y1));
1923
- // it goes to (x1, y1), but we fill that below
1924
- }
1925
-
1926
- // fill triangular section, this sometimes result
1927
- // in redundant points if (x1, y1) hasn't changed
1928
- // from previous line to, but we just ignore that
1929
- ctx.lineTo(axisx.p2c(x1), axisy.p2c(y1));
1930
- ctx.lineTo(axisx.p2c(x2), axisy.p2c(y2));
1931
-
1932
- // fill the other rectangle if it's there
1933
- if (x2 != x2old) {
1934
- ctx.lineTo(axisx.p2c(x2), axisy.p2c(y2));
1935
- ctx.lineTo(axisx.p2c(x2old), axisy.p2c(y2));
1936
- }
1937
- }
1938
- }
1939
-
1940
- ctx.save();
1941
- ctx.translate(plotOffset.left, plotOffset.top);
1942
- ctx.lineJoin = "round";
1943
-
1944
- var lw = series.lines.lineWidth,
1945
- sw = series.shadowSize;
1946
- // FIXME: consider another form of shadow when filling is turned on
1947
- if (lw > 0 && sw > 0) {
1948
- // draw shadow as a thick and thin line with transparency
1949
- ctx.lineWidth = sw;
1950
- ctx.strokeStyle = "rgba(0,0,0,0.1)";
1951
- // position shadow at angle from the mid of line
1952
- var angle = Math.PI/18;
1953
- plotLine(series.datapoints, Math.sin(angle) * (lw/2 + sw/2), Math.cos(angle) * (lw/2 + sw/2), series.xaxis, series.yaxis);
1954
- ctx.lineWidth = sw/2;
1955
- plotLine(series.datapoints, Math.sin(angle) * (lw/2 + sw/4), Math.cos(angle) * (lw/2 + sw/4), series.xaxis, series.yaxis);
1956
- }
1957
-
1958
- ctx.lineWidth = lw;
1959
- ctx.strokeStyle = series.color;
1960
- var fillStyle = getFillStyle(series.lines, series.color, 0, plotHeight);
1961
- if (fillStyle) {
1962
- ctx.fillStyle = fillStyle;
1963
- plotLineArea(series.datapoints, series.xaxis, series.yaxis);
1964
- }
1965
-
1966
- if (lw > 0)
1967
- plotLine(series.datapoints, 0, 0, series.xaxis, series.yaxis);
1968
- ctx.restore();
1969
- }
1970
-
1971
- function drawSeriesPoints(series) {
1972
- function plotPoints(datapoints, radius, fillStyle, offset, shadow, axisx, axisy, symbol) {
1973
- var points = datapoints.points, ps = datapoints.pointsize;
1974
-
1975
- for (var i = 0; i < points.length; i += ps) {
1976
- var x = points[i], y = points[i + 1];
1977
- if (x == null || x < axisx.min || x > axisx.max || y < axisy.min || y > axisy.max)
1978
- continue;
1979
-
1980
- ctx.beginPath();
1981
- x = axisx.p2c(x);
1982
- y = axisy.p2c(y) + offset;
1983
- if (symbol == "circle")
1984
- ctx.arc(x, y, radius, 0, shadow ? Math.PI : Math.PI * 2, false);
1985
- else
1986
- symbol(ctx, x, y, radius, shadow);
1987
- ctx.closePath();
1988
-
1989
- if (fillStyle) {
1990
- ctx.fillStyle = fillStyle;
1991
- ctx.fill();
1992
- }
1993
- ctx.stroke();
1994
- }
1995
- }
1996
-
1997
- ctx.save();
1998
- ctx.translate(plotOffset.left, plotOffset.top);
1999
-
2000
- var lw = series.points.lineWidth,
2001
- sw = series.shadowSize,
2002
- radius = series.points.radius,
2003
- symbol = series.points.symbol;
2004
- if (lw > 0 && sw > 0) {
2005
- // draw shadow in two steps
2006
- var w = sw / 2;
2007
- ctx.lineWidth = w;
2008
- ctx.strokeStyle = "rgba(0,0,0,0.1)";
2009
- plotPoints(series.datapoints, radius, null, w + w/2, true,
2010
- series.xaxis, series.yaxis, symbol);
2011
-
2012
- ctx.strokeStyle = "rgba(0,0,0,0.2)";
2013
- plotPoints(series.datapoints, radius, null, w/2, true,
2014
- series.xaxis, series.yaxis, symbol);
2015
- }
2016
-
2017
- ctx.lineWidth = lw;
2018
- ctx.strokeStyle = series.color;
2019
- plotPoints(series.datapoints, radius,
2020
- getFillStyle(series.points, series.color), 0, false,
2021
- series.xaxis, series.yaxis, symbol);
2022
- ctx.restore();
2023
- }
2024
-
2025
- function drawBar(x, y, b, barLeft, barRight, offset, fillStyleCallback, axisx, axisy, c, horizontal, lineWidth) {
2026
- var left, right, bottom, top,
2027
- drawLeft, drawRight, drawTop, drawBottom,
2028
- tmp;
2029
-
2030
- // in horizontal mode, we start the bar from the left
2031
- // instead of from the bottom so it appears to be
2032
- // horizontal rather than vertical
2033
- if (horizontal) {
2034
- drawBottom = drawRight = drawTop = true;
2035
- drawLeft = false;
2036
- left = b;
2037
- right = x;
2038
- top = y + barLeft;
2039
- bottom = y + barRight;
2040
-
2041
- // account for negative bars
2042
- if (right < left) {
2043
- tmp = right;
2044
- right = left;
2045
- left = tmp;
2046
- drawLeft = true;
2047
- drawRight = false;
2048
- }
2049
- }
2050
- else {
2051
- drawLeft = drawRight = drawTop = true;
2052
- drawBottom = false;
2053
- left = x + barLeft;
2054
- right = x + barRight;
2055
- bottom = b;
2056
- top = y;
2057
-
2058
- // account for negative bars
2059
- if (top < bottom) {
2060
- tmp = top;
2061
- top = bottom;
2062
- bottom = tmp;
2063
- drawBottom = true;
2064
- drawTop = false;
2065
- }
2066
- }
2067
-
2068
- // clip
2069
- if (right < axisx.min || left > axisx.max ||
2070
- top < axisy.min || bottom > axisy.max)
2071
- return;
2072
-
2073
- if (left < axisx.min) {
2074
- left = axisx.min;
2075
- drawLeft = false;
2076
- }
2077
-
2078
- if (right > axisx.max) {
2079
- right = axisx.max;
2080
- drawRight = false;
2081
- }
2082
-
2083
- if (bottom < axisy.min) {
2084
- bottom = axisy.min;
2085
- drawBottom = false;
2086
- }
2087
-
2088
- if (top > axisy.max) {
2089
- top = axisy.max;
2090
- drawTop = false;
2091
- }
2092
-
2093
- left = axisx.p2c(left);
2094
- bottom = axisy.p2c(bottom);
2095
- right = axisx.p2c(right);
2096
- top = axisy.p2c(top);
2097
-
2098
- // fill the bar
2099
- if (fillStyleCallback) {
2100
- c.beginPath();
2101
- c.moveTo(left, bottom);
2102
- c.lineTo(left, top);
2103
- c.lineTo(right, top);
2104
- c.lineTo(right, bottom);
2105
- c.fillStyle = fillStyleCallback(bottom, top);
2106
- c.fill();
2107
- }
2108
-
2109
- // draw outline
2110
- if (lineWidth > 0 && (drawLeft || drawRight || drawTop || drawBottom)) {
2111
- c.beginPath();
2112
-
2113
- // FIXME: inline moveTo is buggy with excanvas
2114
- c.moveTo(left, bottom + offset);
2115
- if (drawLeft)
2116
- c.lineTo(left, top + offset);
2117
- else
2118
- c.moveTo(left, top + offset);
2119
- if (drawTop)
2120
- c.lineTo(right, top + offset);
2121
- else
2122
- c.moveTo(right, top + offset);
2123
- if (drawRight)
2124
- c.lineTo(right, bottom + offset);
2125
- else
2126
- c.moveTo(right, bottom + offset);
2127
- if (drawBottom)
2128
- c.lineTo(left, bottom + offset);
2129
- else
2130
- c.moveTo(left, bottom + offset);
2131
- c.stroke();
2132
- }
2133
- }
2134
-
2135
- function drawSeriesBars(series) {
2136
- function plotBars(datapoints, barLeft, barRight, offset, fillStyleCallback, axisx, axisy) {
2137
- var points = datapoints.points, ps = datapoints.pointsize;
2138
-
2139
- for (var i = 0; i < points.length; i += ps) {
2140
- if (points[i] == null)
2141
- continue;
2142
- drawBar(points[i], points[i + 1], points[i + 2], barLeft, barRight, offset, fillStyleCallback, axisx, axisy, ctx, series.bars.horizontal, series.bars.lineWidth);
2143
- }
2144
- }
2145
-
2146
- ctx.save();
2147
- ctx.translate(plotOffset.left, plotOffset.top);
2148
-
2149
- // FIXME: figure out a way to add shadows (for instance along the right edge)
2150
- ctx.lineWidth = series.bars.lineWidth;
2151
- ctx.strokeStyle = series.color;
2152
- var barLeft = series.bars.align == "left" ? 0 : -series.bars.barWidth/2;
2153
- var fillStyleCallback = series.bars.fill ? function (bottom, top) { return getFillStyle(series.bars, series.color, bottom, top); } : null;
2154
- plotBars(series.datapoints, barLeft, barLeft + series.bars.barWidth, 0, fillStyleCallback, series.xaxis, series.yaxis);
2155
- ctx.restore();
2156
- }
2157
-
2158
- function getFillStyle(filloptions, seriesColor, bottom, top) {
2159
- var fill = filloptions.fill;
2160
- if (!fill)
2161
- return null;
2162
-
2163
- if (filloptions.fillColor)
2164
- return getColorOrGradient(filloptions.fillColor, bottom, top, seriesColor);
2165
-
2166
- var c = $.color.parse(seriesColor);
2167
- c.a = typeof fill == "number" ? fill : 0.4;
2168
- c.normalize();
2169
- return c.toString();
2170
- }
2171
-
2172
- function insertLegend() {
2173
- placeholder.find(".legend").remove();
2174
-
2175
- if (!options.legend.show)
2176
- return;
2177
-
2178
- var fragments = [], rowStarted = false,
2179
- lf = options.legend.labelFormatter, s, label;
2180
- for (var i = 0; i < series.length; ++i) {
2181
- s = series[i];
2182
- label = s.label;
2183
- if (!label)
2184
- continue;
2185
-
2186
- if (i % options.legend.noColumns == 0) {
2187
- if (rowStarted)
2188
- fragments.push('</tr>');
2189
- fragments.push('<tr>');
2190
- rowStarted = true;
2191
- }
2192
-
2193
- if (lf)
2194
- label = lf(label, s);
2195
-
2196
- fragments.push(
2197
- '<td class="legendColorBox"><div style="border:1px solid ' + options.legend.labelBoxBorderColor + ';padding:1px"><div style="width:4px;height:0;border:5px solid ' + s.color + ';overflow:hidden"></div></div></td>' +
2198
- '<td class="legendLabel">' + label + '</td>');
2199
- }
2200
- if (rowStarted)
2201
- fragments.push('</tr>');
2202
-
2203
- if (fragments.length == 0)
2204
- return;
2205
-
2206
- var table = '<table style="font-size:smaller;color:' + options.grid.color + '">' + fragments.join("") + '</table>';
2207
- if (options.legend.container != null)
2208
- $(options.legend.container).html(table);
2209
- else {
2210
- var pos = "",
2211
- p = options.legend.position,
2212
- m = options.legend.margin;
2213
- if (m[0] == null)
2214
- m = [m, m];
2215
- if (p.charAt(0) == "n")
2216
- pos += 'top:' + (m[1] + plotOffset.top) + 'px;';
2217
- else if (p.charAt(0) == "s")
2218
- pos += 'bottom:' + (m[1] + plotOffset.bottom) + 'px;';
2219
- if (p.charAt(1) == "e")
2220
- pos += 'right:' + (m[0] + plotOffset.right) + 'px;';
2221
- else if (p.charAt(1) == "w")
2222
- pos += 'left:' + (m[0] + plotOffset.left) + 'px;';
2223
- var legend = $('<div class="legend">' + table.replace('style="', 'style="position:absolute;' + pos +';') + '</div>').appendTo(placeholder);
2224
- if (options.legend.backgroundOpacity != 0.0) {
2225
- // put in the transparent background
2226
- // separately to avoid blended labels and
2227
- // label boxes
2228
- var c = options.legend.backgroundColor;
2229
- if (c == null) {
2230
- c = options.grid.backgroundColor;
2231
- if (c && typeof c == "string")
2232
- c = $.color.parse(c);
2233
- else
2234
- c = $.color.extract(legend, 'background-color');
2235
- c.a = 1;
2236
- c = c.toString();
2237
- }
2238
- var div = legend.children();
2239
- $('<div style="position:absolute;width:' + div.width() + 'px;height:' + div.height() + 'px;' + pos +'background-color:' + c + ';"> </div>').prependTo(legend).css('opacity', options.legend.backgroundOpacity);
2240
- }
2241
- }
2242
- }
2243
-
2244
-
2245
- // interactive features
2246
-
2247
- var highlights = [],
2248
- redrawTimeout = null;
2249
-
2250
- // returns the data item the mouse is over, or null if none is found
2251
- function findNearbyItem(mouseX, mouseY, seriesFilter) {
2252
- var maxDistance = options.grid.mouseActiveRadius,
2253
- smallestDistance = maxDistance * maxDistance + 1,
2254
- item = null, foundPoint = false, i, j;
2255
-
2256
- for (i = series.length - 1; i >= 0; --i) {
2257
- if (!seriesFilter(series[i]))
2258
- continue;
2259
-
2260
- var s = series[i],
2261
- axisx = s.xaxis,
2262
- axisy = s.yaxis,
2263
- points = s.datapoints.points,
2264
- ps = s.datapoints.pointsize,
2265
- mx = axisx.c2p(mouseX), // precompute some stuff to make the loop faster
2266
- my = axisy.c2p(mouseY),
2267
- maxx = maxDistance / axisx.scale,
2268
- maxy = maxDistance / axisy.scale;
2269
-
2270
- // with inverse transforms, we can't use the maxx/maxy
2271
- // optimization, sadly
2272
- if (axisx.options.inverseTransform)
2273
- maxx = Number.MAX_VALUE;
2274
- if (axisy.options.inverseTransform)
2275
- maxy = Number.MAX_VALUE;
2276
-
2277
- if (s.lines.show || s.points.show) {
2278
- for (j = 0; j < points.length; j += ps) {
2279
- var x = points[j], y = points[j + 1];
2280
- if (x == null)
2281
- continue;
2282
-
2283
- // For points and lines, the cursor must be within a
2284
- // certain distance to the data point
2285
- if (x - mx > maxx || x - mx < -maxx ||
2286
- y - my > maxy || y - my < -maxy)
2287
- continue;
2288
-
2289
- // We have to calculate distances in pixels, not in
2290
- // data units, because the scales of the axes may be different
2291
- var dx = Math.abs(axisx.p2c(x) - mouseX),
2292
- dy = Math.abs(axisy.p2c(y) - mouseY),
2293
- dist = dx * dx + dy * dy; // we save the sqrt
2294
-
2295
- // use <= to ensure last point takes precedence
2296
- // (last generally means on top of)
2297
- if (dist < smallestDistance) {
2298
- smallestDistance = dist;
2299
- item = [i, j / ps];
2300
- }
2301
- }
2302
- }
2303
-
2304
- if (s.bars.show && !item) { // no other point can be nearby
2305
- var barLeft = s.bars.align == "left" ? 0 : -s.bars.barWidth/2,
2306
- barRight = barLeft + s.bars.barWidth;
2307
-
2308
- for (j = 0; j < points.length; j += ps) {
2309
- var x = points[j], y = points[j + 1], b = points[j + 2];
2310
- if (x == null)
2311
- continue;
2312
-
2313
- // for a bar graph, the cursor must be inside the bar
2314
- if (series[i].bars.horizontal ?
2315
- (mx <= Math.max(b, x) && mx >= Math.min(b, x) &&
2316
- my >= y + barLeft && my <= y + barRight) :
2317
- (mx >= x + barLeft && mx <= x + barRight &&
2318
- my >= Math.min(b, y) && my <= Math.max(b, y)))
2319
- item = [i, j / ps];
2320
- }
2321
- }
2322
- }
2323
-
2324
- if (item) {
2325
- i = item[0];
2326
- j = item[1];
2327
- ps = series[i].datapoints.pointsize;
2328
-
2329
- return { datapoint: series[i].datapoints.points.slice(j * ps, (j + 1) * ps),
2330
- dataIndex: j,
2331
- series: series[i],
2332
- seriesIndex: i };
2333
- }
2334
-
2335
- return null;
2336
- }
2337
-
2338
- function onMouseMove(e) {
2339
- if (options.grid.hoverable)
2340
- triggerClickHoverEvent("plothover", e,
2341
- function (s) { return s["hoverable"] != false; });
2342
- }
2343
-
2344
- function onMouseLeave(e) {
2345
- if (options.grid.hoverable)
2346
- triggerClickHoverEvent("plothover", e,
2347
- function (s) { return false; });
2348
- }
2349
-
2350
- function onClick(e) {
2351
- triggerClickHoverEvent("plotclick", e,
2352
- function (s) { return s["clickable"] != false; });
2353
- }
2354
-
2355
- // trigger click or hover event (they send the same parameters
2356
- // so we share their code)
2357
- function triggerClickHoverEvent(eventname, event, seriesFilter) {
2358
- var offset = eventHolder.offset(),
2359
- canvasX = event.pageX - offset.left - plotOffset.left,
2360
- canvasY = event.pageY - offset.top - plotOffset.top,
2361
- pos = canvasToAxisCoords({ left: canvasX, top: canvasY });
2362
-
2363
- pos.pageX = event.pageX;
2364
- pos.pageY = event.pageY;
2365
-
2366
- var item = findNearbyItem(canvasX, canvasY, seriesFilter);
2367
-
2368
- if (item) {
2369
- // fill in mouse pos for any listeners out there
2370
- item.pageX = parseInt(item.series.xaxis.p2c(item.datapoint[0]) + offset.left + plotOffset.left);
2371
- item.pageY = parseInt(item.series.yaxis.p2c(item.datapoint[1]) + offset.top + plotOffset.top);
2372
- }
2373
-
2374
- if (options.grid.autoHighlight) {
2375
- // clear auto-highlights
2376
- for (var i = 0; i < highlights.length; ++i) {
2377
- var h = highlights[i];
2378
- if (h.auto == eventname &&
2379
- !(item && h.series == item.series &&
2380
- h.point[0] == item.datapoint[0] &&
2381
- h.point[1] == item.datapoint[1]))
2382
- unhighlight(h.series, h.point);
2383
- }
2384
-
2385
- if (item)
2386
- highlight(item.series, item.datapoint, eventname);
2387
- }
2388
-
2389
- placeholder.trigger(eventname, [ pos, item ]);
2390
- }
2391
-
2392
- function triggerRedrawOverlay() {
2393
- if (!redrawTimeout)
2394
- redrawTimeout = setTimeout(drawOverlay, 30);
2395
- }
2396
-
2397
- function drawOverlay() {
2398
- redrawTimeout = null;
2399
-
2400
- // draw highlights
2401
- octx.save();
2402
- octx.clearRect(0, 0, canvasWidth, canvasHeight);
2403
- octx.translate(plotOffset.left, plotOffset.top);
2404
-
2405
- var i, hi;
2406
- for (i = 0; i < highlights.length; ++i) {
2407
- hi = highlights[i];
2408
-
2409
- if (hi.series.bars.show)
2410
- drawBarHighlight(hi.series, hi.point);
2411
- else
2412
- drawPointHighlight(hi.series, hi.point);
2413
- }
2414
- octx.restore();
2415
-
2416
- executeHooks(hooks.drawOverlay, [octx]);
2417
- }
2418
-
2419
- function highlight(s, point, auto) {
2420
- if (typeof s == "number")
2421
- s = series[s];
2422
-
2423
- if (typeof point == "number") {
2424
- var ps = s.datapoints.pointsize;
2425
- point = s.datapoints.points.slice(ps * point, ps * (point + 1));
2426
- }
2427
-
2428
- var i = indexOfHighlight(s, point);
2429
- if (i == -1) {
2430
- highlights.push({ series: s, point: point, auto: auto });
2431
-
2432
- triggerRedrawOverlay();
2433
- }
2434
- else if (!auto)
2435
- highlights[i].auto = false;
2436
- }
2437
-
2438
- function unhighlight(s, point) {
2439
- if (s == null && point == null) {
2440
- highlights = [];
2441
- triggerRedrawOverlay();
2442
- }
2443
-
2444
- if (typeof s == "number")
2445
- s = series[s];
2446
-
2447
- if (typeof point == "number")
2448
- point = s.data[point];
2449
-
2450
- var i = indexOfHighlight(s, point);
2451
- if (i != -1) {
2452
- highlights.splice(i, 1);
2453
-
2454
- triggerRedrawOverlay();
2455
- }
2456
- }
2457
-
2458
- function indexOfHighlight(s, p) {
2459
- for (var i = 0; i < highlights.length; ++i) {
2460
- var h = highlights[i];
2461
- if (h.series == s && h.point[0] == p[0]
2462
- && h.point[1] == p[1])
2463
- return i;
2464
- }
2465
- return -1;
2466
- }
2467
-
2468
- function drawPointHighlight(series, point) {
2469
- var x = point[0], y = point[1],
2470
- axisx = series.xaxis, axisy = series.yaxis;
2471
-
2472
- if (x < axisx.min || x > axisx.max || y < axisy.min || y > axisy.max)
2473
- return;
2474
-
2475
- var pointRadius = series.points.radius + series.points.lineWidth / 2;
2476
- octx.lineWidth = pointRadius;
2477
- octx.strokeStyle = $.color.parse(series.color).scale('a', 0.5).toString();
2478
- var radius = 1.5 * pointRadius,
2479
- x = axisx.p2c(x),
2480
- y = axisy.p2c(y);
2481
-
2482
- octx.beginPath();
2483
- if (series.points.symbol == "circle")
2484
- octx.arc(x, y, radius, 0, 2 * Math.PI, false);
2485
- else
2486
- series.points.symbol(octx, x, y, radius, false);
2487
- octx.closePath();
2488
- octx.stroke();
2489
- }
2490
-
2491
- function drawBarHighlight(series, point) {
2492
- octx.lineWidth = series.bars.lineWidth;
2493
- octx.strokeStyle = $.color.parse(series.color).scale('a', 0.5).toString();
2494
- var fillStyle = $.color.parse(series.color).scale('a', 0.5).toString();
2495
- var barLeft = series.bars.align == "left" ? 0 : -series.bars.barWidth/2;
2496
- drawBar(point[0], point[1], point[2] || 0, barLeft, barLeft + series.bars.barWidth,
2497
- 0, function () { return fillStyle; }, series.xaxis, series.yaxis, octx, series.bars.horizontal, series.bars.lineWidth);
2498
- }
2499
-
2500
- function getColorOrGradient(spec, bottom, top, defaultColor) {
2501
- if (typeof spec == "string")
2502
- return spec;
2503
- else {
2504
- // assume this is a gradient spec; IE currently only
2505
- // supports a simple vertical gradient properly, so that's
2506
- // what we support too
2507
- var gradient = ctx.createLinearGradient(0, top, 0, bottom);
2508
-
2509
- for (var i = 0, l = spec.colors.length; i < l; ++i) {
2510
- var c = spec.colors[i];
2511
- if (typeof c != "string") {
2512
- var co = $.color.parse(defaultColor);
2513
- if (c.brightness != null)
2514
- co = co.scale('rgb', c.brightness)
2515
- if (c.opacity != null)
2516
- co.a *= c.opacity;
2517
- c = co.toString();
2518
- }
2519
- gradient.addColorStop(i / (l - 1), c);
2520
- }
2521
-
2522
- return gradient;
2523
- }
2524
- }
2525
- }
2526
-
2527
- $.plot = function(placeholder, data, options) {
2528
- //var t0 = new Date();
2529
- var plot = new Plot($(placeholder), data, options, $.plot.plugins);
2530
- //(window.console ? console.log : alert)("time used (msecs): " + ((new Date()).getTime() - t0.getTime()));
2531
- return plot;
2532
- };
2533
-
2534
- $.plot.version = "0.7";
2535
-
2536
- $.plot.plugins = [];
2537
-
2538
- // returns a string with the date d formatted according to fmt
2539
- $.plot.formatDate = function(d, fmt, monthNames) {
2540
- var leftPad = function(n) {
2541
- n = "" + n;
2542
- return n.length == 1 ? "0" + n : n;
2543
- };
2544
-
2545
- var r = [];
2546
- var escape = false, padNext = false;
2547
- var hours = d.getUTCHours();
2548
- var isAM = hours < 12;
2549
- if (monthNames == null)
2550
- monthNames = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
2551
-
2552
- if (fmt.search(/%p|%P/) != -1) {
2553
- if (hours > 12) {
2554
- hours = hours - 12;
2555
- } else if (hours == 0) {
2556
- hours = 12;
2557
- }
2558
- }
2559
- for (var i = 0; i < fmt.length; ++i) {
2560
- var c = fmt.charAt(i);
2561
-
2562
- if (escape) {
2563
- switch (c) {
2564
- case 'h': c = "" + hours; break;
2565
- case 'H': c = leftPad(hours); break;
2566
- case 'M': c = leftPad(d.getUTCMinutes()); break;
2567
- case 'S': c = leftPad(d.getUTCSeconds()); break;
2568
- case 'd': c = "" + d.getUTCDate(); break;
2569
- case 'm': c = "" + (d.getUTCMonth() + 1); break;
2570
- case 'y': c = "" + d.getUTCFullYear(); break;
2571
- case 'b': c = "" + monthNames[d.getUTCMonth()]; break;
2572
- case 'p': c = (isAM) ? ("" + "am") : ("" + "pm"); break;
2573
- case 'P': c = (isAM) ? ("" + "AM") : ("" + "PM"); break;
2574
- case '0': c = ""; padNext = true; break;
2575
- }
2576
- if (c && padNext) {
2577
- c = leftPad(c);
2578
- padNext = false;
2579
- }
2580
- r.push(c);
2581
- if (!padNext)
2582
- escape = false;
2583
- }
2584
- else {
2585
- if (c == "%")
2586
- escape = true;
2587
- else
2588
- r.push(c);
2589
- }
2590
- }
2591
- return r.join("");
2592
- };
2593
-
2594
- // round to nearby lower multiple of base
2595
- function floorInBase(n, base) {
2596
- return base * Math.floor(n / base);
2597
- }
2598
-
2599
- })(jQuery);