omf_web 0.9.1 → 0.9.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (243) hide show
  1. data/.gitignore +0 -1
  2. data/README.md +8 -2
  3. data/doc/screenshot.png +0 -0
  4. data/example/{basic → NOT_WORKING/basic}/hello-world-wired.rb +0 -0
  5. data/example/{basic → NOT_WORKING/basic}/visualisation.yml +0 -0
  6. data/example/{brooklyn → NOT_WORKING/brooklyn}/brooklynDemo.sq3 +0 -0
  7. data/example/{brooklyn → NOT_WORKING/brooklyn}/brooklyn_gps.dat +0 -0
  8. data/example/{brooklyn → NOT_WORKING/brooklyn}/brooklyn_server.rb +0 -0
  9. data/example/{brooklyn → NOT_WORKING/brooklyn}/brooklyn_wimax.dat +0 -0
  10. data/example/{brooklyn → NOT_WORKING/brooklyn}/sql_source.rb +0 -0
  11. data/example/{code → NOT_WORKING/code}/code_server.rb +0 -0
  12. data/example/{frisbee → NOT_WORKING/frisbee}/data_sources/parse_log.rb +0 -0
  13. data/example/{frisbee → NOT_WORKING/frisbee}/data_sources/pxe_slice-2012-06-02t02.25.00-04.00.log +0 -0
  14. data/example/{frisbee → NOT_WORKING/frisbee}/progress_chart.yaml +0 -0
  15. data/example/{frisbee → NOT_WORKING/frisbee}/progress_tab.yaml +0 -0
  16. data/example/{frisbee → NOT_WORKING/frisbee}/progress_table.yaml +0 -0
  17. data/example/{frisbee → NOT_WORKING/frisbee}/viz_server.rb +0 -0
  18. data/example/{gec12 → NOT_WORKING/gec12}/gec12-53.rb +0 -0
  19. data/example/{gec12 → NOT_WORKING/gec12}/gec12_demo.sq3 +0 -0
  20. data/example/{gec12 → NOT_WORKING/gec12}/gec12_demo_server.rb +0 -0
  21. data/example/{gec12 → NOT_WORKING/gec12}/visualization.rb +0 -0
  22. data/example/{incoming → NOT_WORKING/incoming}/ofpu_barchart_widget.yaml +0 -0
  23. data/example/{log → NOT_WORKING/log}/log_config.xml +0 -0
  24. data/example/{log → NOT_WORKING/log}/log_server.rb +0 -0
  25. data/example/{network → NOT_WORKING/network}/flow_tab.yaml +0 -0
  26. data/example/{network → NOT_WORKING/network}/network_server.rb +0 -0
  27. data/example/{text → NOT_WORKING/text}/test.md +0 -0
  28. data/example/{text → NOT_WORKING/text}/test.rb +0 -0
  29. data/example/{wimax → NOT_WORKING/wimax}/downlink.yaml +0 -0
  30. data/example/{wimax → NOT_WORKING/wimax}/power.yaml +0 -0
  31. data/example/{wimax → NOT_WORKING/wimax}/snapshot.db +0 -0
  32. data/example/{wimax → NOT_WORKING/wimax}/snapshot.sql +0 -0
  33. data/example/{wimax → NOT_WORKING/wimax}/test.rb +0 -0
  34. data/example/{wimax → NOT_WORKING/wimax}/uplink.yaml +0 -0
  35. data/example/{wimax → NOT_WORKING/wimax}/viz_server.rb +0 -0
  36. data/example/demo/data_sources/mobile_network.rb +3 -0
  37. data/example/demo/data_sources/static_network.rb +54 -0
  38. data/example/demo/widgets/charts_tab.yaml +21 -16
  39. data/example/demo/widgets/linked_graphs_tab.yaml +95 -0
  40. data/example/demo/widgets/mobile_network_widget.yaml +1 -1
  41. data/example/demo/widgets/pie_chart_widget.yaml +1 -1
  42. data/lib/omf-web/config.ru +2 -2
  43. data/lib/omf-web/data_source_proxy.rb +81 -19
  44. data/lib/omf-web/rack/websocket_handler.rb +77 -23
  45. data/lib/omf-web/theme/abstract_page.rb +43 -26
  46. data/lib/omf-web/theme/bright/code_renderer.rb +1 -1
  47. data/lib/omf-web/theme/bright/page.rb +1 -0
  48. data/lib/omf-web/theme/bright/tabbed_renderer.rb +7 -0
  49. data/lib/omf-web/version.rb +7 -0
  50. data/lib/omf-web/widget/data_widget.rb +38 -46
  51. data/lib/omf-web/widget/layout/stacked_layout.rb +2 -1
  52. data/lib/omf-web/widget/layout/tabbed_layout.rb +1 -2
  53. data/{MARUKU-LICENSE → lib/omf-web/widget/text/maruku/MARUKU-LICENSE} +0 -0
  54. data/lib/{maruku → omf-web/widget/text/maruku}/helpers.rb +0 -0
  55. data/lib/{maruku → omf-web/widget/text/maruku}/input/parse_block.rb +0 -0
  56. data/lib/{maruku → omf-web/widget/text/maruku}/output/to_html.rb +26 -21
  57. data/lib/omf-web/widget/text/maruku.rb +5 -0
  58. data/omf_web.gemspec +2 -1
  59. data/share/htdocs/{js → UNUSED}/log/table.js +0 -0
  60. data/share/htdocs/{css → graph/css}/graph.css +0 -0
  61. data/share/htdocs/{image/graph → graph/img}/bar_chart.png +0 -0
  62. data/share/htdocs/{image/graph → graph/img}/donut_chart.png +0 -0
  63. data/share/htdocs/{image/graph → graph/img}/funnel.png +0 -0
  64. data/share/htdocs/{image/graph → graph/img}/info.png +0 -0
  65. data/share/htdocs/{image/graph → graph/img}/line_chart.png +0 -0
  66. data/share/htdocs/{image/graph → graph/img}/line_chart_fill.png +0 -0
  67. data/share/htdocs/{image/graph → graph/img}/misc.png +0 -0
  68. data/share/htdocs/{image/graph → graph/img}/overview.png +0 -0
  69. data/share/htdocs/{image/graph → graph/img}/pie_chart.png +0 -0
  70. data/share/htdocs/{image/graph → graph/img}/scatter_plot.png +0 -0
  71. data/share/htdocs/{image/graph → graph/img}/stacked_bar_chart.png +0 -0
  72. data/share/htdocs/{image/graph → graph/img}/stacked_line_chart.png +0 -0
  73. data/share/htdocs/{image/graph → graph/img}/table.png +0 -0
  74. data/share/htdocs/{js/graph → graph/js}/abstract_chart.js +1 -1
  75. data/share/htdocs/{js/graph → graph/js}/abstract_nv_chart.js +8 -13
  76. data/share/htdocs/{js/graph → graph/js}/abstract_widget.js +9 -16
  77. data/share/htdocs/{js/graph → graph/js}/axis.js +1 -1
  78. data/share/htdocs/{js/graph → graph/js}/barchart.js +2 -2
  79. data/share/htdocs/{js/graph → graph/js}/code_mirror.js +1 -5
  80. data/share/htdocs/{js/graph → graph/js}/discrete_bar_chart.js +1 -1
  81. data/share/htdocs/{js/graph → graph/js}/histogram2.js +1 -1
  82. data/share/htdocs/{js/graph → graph/js}/holt_winters_chart.js +1 -1
  83. data/share/htdocs/{js/graph → graph/js}/line_chart3.js +1 -1
  84. data/share/htdocs/{js/graph → graph/js}/line_chart_with_focus.js +1 -1
  85. data/share/htdocs/{js/graph → graph/js}/map2.js +1 -1
  86. data/share/htdocs/{js/graph → graph/js}/multi_barchart.js +1 -1
  87. data/share/htdocs/graph/js/network2.js +412 -0
  88. data/share/htdocs/{js/graph → graph/js}/pie_chart2.js +1 -1
  89. data/share/htdocs/{js/graph → graph/js}/scatter_plot.js +1 -1
  90. data/share/htdocs/{js/graph → graph/js}/table2.js +17 -20
  91. data/share/htdocs/js/data_source2.js +187 -60
  92. data/share/htdocs/js/require3.js +38 -57
  93. data/share/htdocs/theme/bright/css/bright.css +4 -4
  94. data/share/htdocs/vendor/jquery/jquery.js +9404 -0
  95. data/share/htdocs/vendor/osa/LICENSE.txt +11 -0
  96. data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_arrow_green_left.svg +0 -0
  97. data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_arrow_yellow_right.svg +0 -0
  98. data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_awareness.svg +0 -0
  99. data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_camera-web.svg +0 -0
  100. data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_cloud.svg +0 -0
  101. data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_contract.svg +0 -0
  102. data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_database.svg +0 -0
  103. data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_desktop.svg +0 -0
  104. data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_desktop_imac.svg +0 -0
  105. data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_device-music.svg +0 -0
  106. data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_device-scanner.svg +0 -0
  107. data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_device-usb-wifi.svg +0 -0
  108. data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_device-usb.svg +0 -0
  109. data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_device-wireless-router.svg +0 -0
  110. data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_disposal.svg +0 -0
  111. data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_drive-harddisk.svg +0 -0
  112. data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_drive-optical.svg +0 -0
  113. data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_firewall.svg +0 -0
  114. data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_home.svg +0 -0
  115. data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_hub.svg +0 -0
  116. data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_iPhone.svg +0 -0
  117. data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_ics_drive.svg +0 -0
  118. data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_ics_plc.svg +0 -0
  119. data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_ics_thermometer.svg +0 -0
  120. data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_id_card.svg +0 -0
  121. data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_image-generic.svg +0 -0
  122. data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_laptop.svg +0 -0
  123. data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_lifecycle.svg +0 -0
  124. data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_lightning.svg +0 -0
  125. data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_media-flash.svg +0 -0
  126. data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_media-optical.svg +0 -0
  127. data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_media-tape.svg +0 -0
  128. data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_mobile_pda.svg +0 -0
  129. data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_padlock.svg +0 -0
  130. data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_printer.svg +0 -0
  131. data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_server.svg +0 -0
  132. data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_server_application.svg +0 -0
  133. data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_server_database.svg +0 -0
  134. data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_server_directory.svg +0 -0
  135. data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_server_distribution.svg +0 -0
  136. data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_server_file.svg +0 -0
  137. data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_server_gateway.svg +0 -0
  138. data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_server_identity.svg +0 -0
  139. data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_server_mail.svg +0 -0
  140. data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_server_media.svg +0 -0
  141. data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_server_monitor.svg +0 -0
  142. data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_server_proxy.svg +0 -0
  143. data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_server_terminal.svg +0 -0
  144. data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_server_web.svg +0 -0
  145. data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_site-branch.svg +0 -0
  146. data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_site-factory.svg +0 -0
  147. data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_site-head-office.svg +0 -0
  148. data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_site-neighbourhood.svg +0 -0
  149. data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_user_audit.svg +0 -0
  150. data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_user_black_hat.svg +0 -0
  151. data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_user_blue.svg +0 -0
  152. data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_user_blue_security_specialist.svg +0 -0
  153. data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_user_blue_sysadmin.svg +0 -0
  154. data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_user_blue_tester.svg +0 -0
  155. data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_user_blue_tie.svg +0 -0
  156. data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_user_green.svg +0 -0
  157. data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_user_green_architect.svg +0 -0
  158. data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_user_green_business_manager.svg +0 -0
  159. data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_user_green_developer.svg +0 -0
  160. data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_user_green_operations.svg +0 -0
  161. data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_user_green_project_manager.svg +0 -0
  162. data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_user_green_service_manager.svg +0 -0
  163. data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_user_green_warning.svg +0 -0
  164. data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_user_large_group.svg +0 -0
  165. data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_users_blue_green.svg +0 -0
  166. data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_vpn.svg +0 -0
  167. data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_warning.svg +0 -0
  168. data/share/htdocs/{svg/osa → vendor/osa/svg}/osa_wireless_network.svg +0 -0
  169. data/share/htdocs/{image → vendor/unknown/image}/.DS_Store +0 -0
  170. data/share/htdocs/{image → vendor/unknown/image}/add_icon.gif +0 -0
  171. data/share/htdocs/{image → vendor/unknown/image}/alertbad_icon.gif +0 -0
  172. data/share/htdocs/{image → vendor/unknown/image}/alertgood_icon.gif +0 -0
  173. data/share/htdocs/{image → vendor/unknown/image}/back_disabled.jpg +0 -0
  174. data/share/htdocs/{image → vendor/unknown/image}/back_disabled.png +0 -0
  175. data/share/htdocs/{image → vendor/unknown/image}/back_enabled.jpg +0 -0
  176. data/share/htdocs/{image → vendor/unknown/image}/back_enabled.png +0 -0
  177. data/share/htdocs/{image → vendor/unknown/image}/back_enabled_hover.jpg +0 -0
  178. data/share/htdocs/{image → vendor/unknown/image}/back_enabled_hover.png +0 -0
  179. data/share/htdocs/{image → vendor/unknown/image}/bottom-bg.gif +0 -0
  180. data/share/htdocs/{image → vendor/unknown/image}/forward_disabled.jpg +0 -0
  181. data/share/htdocs/{image → vendor/unknown/image}/forward_disabled.png +0 -0
  182. data/share/htdocs/{image → vendor/unknown/image}/forward_enabled.jpg +0 -0
  183. data/share/htdocs/{image → vendor/unknown/image}/forward_enabled.png +0 -0
  184. data/share/htdocs/{image → vendor/unknown/image}/forward_enabled_hover.jpg +0 -0
  185. data/share/htdocs/{image → vendor/unknown/image}/forward_enabled_hover.png +0 -0
  186. data/share/htdocs/{image → vendor/unknown/image}/icon-remove.gif +0 -0
  187. data/share/htdocs/{image → vendor/unknown/image}/indicator.gif +0 -0
  188. data/share/htdocs/{image → vendor/unknown/image}/laptop.png +0 -0
  189. data/share/htdocs/{image → vendor/unknown/image}/logo-bottom.gif +0 -0
  190. data/share/htdocs/{image → vendor/unknown/image}/nav-tab-arrow.gif +0 -0
  191. data/share/htdocs/{image → vendor/unknown/image}/norbit_big.gif +0 -0
  192. data/share/htdocs/{image → vendor/unknown/image}/norbit_clipart.png +0 -0
  193. data/share/htdocs/{image → vendor/unknown/image}/progress_bar.gif +0 -0
  194. data/share/htdocs/{image → vendor/unknown/image}/right-bg.gif +0 -0
  195. data/share/htdocs/{image → vendor/unknown/image}/sort_asc.png +0 -0
  196. data/share/htdocs/{image → vendor/unknown/image}/sort_asc_disabled.png +0 -0
  197. data/share/htdocs/{image → vendor/unknown/image}/sort_both.png +0 -0
  198. data/share/htdocs/{image → vendor/unknown/image}/sort_desc.png +0 -0
  199. data/share/htdocs/{image → vendor/unknown/image}/sort_desc_disabled.png +0 -0
  200. data/share/htdocs/{image → vendor/unknown/image}/spinner.gif +0 -0
  201. data/share/htdocs/{svg → vendor/unknown/svg}/ap.svg +0 -0
  202. data/share/htdocs/{svg → vendor/unknown/svg}/router.svg +0 -0
  203. metadata +198 -216
  204. data/example/demo/widgets/dashboard_tab.yaml +0 -28
  205. data/example/demo/widgets/download_tab.yaml +0 -42
  206. data/example/demo/widgets/edit_tab.yaml +0 -20
  207. data/example/demo/widgets/generator_tab.yaml +0 -12
  208. data/lib/omf-oml/endpoint.rb +0 -175
  209. data/lib/omf-oml/indexed_table.rb +0 -57
  210. data/lib/omf-oml/network.rb +0 -413
  211. data/lib/omf-oml/oml_tuple.rb +0 -62
  212. data/lib/omf-oml/schema.rb +0 -191
  213. data/lib/omf-oml/sequel/sequel_server.rb +0 -412
  214. data/lib/omf-oml/sql_row.rb +0 -302
  215. data/lib/omf-oml/sql_source.rb +0 -131
  216. data/lib/omf-oml/table.rb +0 -131
  217. data/lib/omf-oml/tuple.rb +0 -97
  218. data/lib/omf_oml.rb +0 -4
  219. data/share/htdocs/css/coderay.css +0 -127
  220. data/share/htdocs/css/ie.css +0 -40
  221. data/share/htdocs/css/lightbox.css +0 -62
  222. data/share/htdocs/css/scaffold.css +0 -74
  223. data/share/htdocs/css/screen.css +0 -1313
  224. data/share/htdocs/css/search.css +0 -102
  225. data/share/htdocs/css/table.css +0 -538
  226. data/share/htdocs/css/table2.css +0 -191
  227. data/share/htdocs/css/welcome.css +0 -103
  228. data/share/htdocs/css/wfob.css +0 -171
  229. data/share/htdocs/css/wshow.css +0 -69
  230. data/share/htdocs/gec9_demo.html +0 -39
  231. data/share/htdocs/images +0 -1
  232. data/share/htdocs/js/graph/histogram.js +0 -229
  233. data/share/htdocs/js/graph/line_chart.js +0 -342
  234. data/share/htdocs/js/graph/line_chart2.js +0 -232
  235. data/share/htdocs/js/graph/line_chart_fc.js +0 -94
  236. data/share/htdocs/js/graph/map.js +0 -85
  237. data/share/htdocs/js/graph/network.js +0 -591
  238. data/share/htdocs/js/graph/network2.js +0 -318
  239. data/share/htdocs/js/graph/pie_chart.js +0 -130
  240. data/share/htdocs/js/graph/table.js +0 -94
  241. data/share/htdocs/js/require2.js +0 -1998
  242. data/share/htdocs/js/timelines.js +0 -101
  243. data/share/htdocs/stylesheet/grid.css +0 -31
@@ -5,8 +5,8 @@ OML.data_sources = function() {
5
5
 
6
6
  function context() {};
7
7
 
8
- context.register = function(name, updateURL, schema, events) {
9
- sources[name] = new OML.data_source(name, updateURL, schema, events);
8
+ context.register = function(opts) {
9
+ sources[opts.id || opts.name] = new OML.data_source(opts);
10
10
  return context;
11
11
  };
12
12
 
@@ -15,14 +15,14 @@ OML.data_sources = function() {
15
15
  var dynamic = false;
16
16
 
17
17
  if (typeof(ds_descr) == 'object') {
18
- name = ds_descr.name;
18
+ name = ds_descr.id || ds_descr.name;
19
19
  dynamic = ds_descr.dynamic;
20
20
  } else {
21
21
  name = ds_descr;
22
22
  }
23
23
  var source = sources[name];
24
24
  if (! source) {
25
- raise("Unknown data source '" + name + "'.");
25
+ throw("Unknown data source '" + name + "'.");
26
26
  }
27
27
  if (dynamic) {
28
28
  source.is_dynamic(dynamic);
@@ -33,48 +33,51 @@ OML.data_sources = function() {
33
33
  return context;
34
34
  }();
35
35
 
36
- OML.data_source = function(name, updateURL, schema, events) {
37
- var event_name = "data_source." + this.name + ".changed";
38
- var indexes = [];
39
- var update_interval = -1;
40
- var ws = null; // points to web socket instance
36
+ OML.data_source = function(opts) {
41
37
 
42
- function ds() {};
43
- ds.version = "0.1";
38
+ var name = opts.id || opts.name;
39
+ var event_name = "data_source." + name + ".changed";
40
+ var rows = opts.rows || [];
41
+ var offset = opts.offset || -1; // Number of (initial) rows skipped (count towards 'max_rows')
42
+ var schema = opts.schema;
44
43
 
45
- this.create_index = function(index) {
46
- var idx = this.indexes[index];
47
- if (idx) return;
48
-
49
- this._create_index(index);
50
- };
51
-
52
- ds.create_index = function(index) {
53
- var idx = indexes[index] = {};
54
- // index ignores rows with identical index
55
- _.map(events, function(r) {
56
- idx[r[index]] = r;
57
- });
58
- };
44
+ var data_source = {
45
+ version: "0.1",
46
+ name: name,
47
+ schema: schema,
48
+ rows: function() {return rows},
49
+ index_for_column: index_for_column,
50
+ is_dynamic: is_dynamic,
51
+ event_name: event_name,
52
+ }
53
+
54
+ var indexes = {};
55
+ var unique_index_check = null;
59
56
 
60
- ds.get_indexed_row = function(index, key) {
61
- var idx = indexes[index];
62
- if (idx == undefined) {
63
- throw "Need to create index first";
57
+ var update_interval = -1;
58
+ var ws = null; // points to web socket instance
59
+
60
+ function index_for_column(col_descr) {
61
+ var i = col_descr.index;
62
+ var index = indexes[i];
63
+ if (!index) {
64
+ index = indexes[i] = {};
65
+ _.each(rows, function(r) { index[r[i]] = r; })
66
+ }
67
+ return function(key) {
68
+ return indexes[i][key]; // need fresh lookup as we may redo index
64
69
  }
65
- return idx[key];
66
70
  }
67
71
 
68
- ds.update_indexes = function() {
69
- var self = this;
70
- _.each(indexes, function(value, key) {
71
- var i = 0;
72
- self._create_index(key);
72
+ function update_indexes() {
73
+ // This can most likley be done more efficiently if we consider what has changed
74
+ _.each(indexes, function(ignore, i) {
75
+ var index = indexes[i] = {};
76
+ _.each(rows, function(r) { index[r[i]] = r; })
73
77
  });
74
-
75
78
  }
76
-
77
- ds.is_dynamic = function(_) {
79
+
80
+ function is_dynamic(_) {
78
81
  if (!arguments.length) {
79
82
  return update_interval > 0 || ws;
80
83
  }
@@ -88,29 +91,22 @@ OML.data_source = function(name, updateURL, schema, events) {
88
91
  }
89
92
  if (interval < 0) return false;
90
93
 
91
- //if (window.WebSocket) {
92
- if (false) { // web sockets don't work right now
93
- _start_web_socket();
94
+ if (window.WebSocket) {
95
+ //if (false) { // web sockets don't work right now
96
+ //start_web_socket();
94
97
  } else {
95
- _start_polling_backend();
98
+ start_polling_backend();
96
99
  }
97
100
  }
98
101
 
99
- ds._start_web_socket = function() {
102
+ var ws = null; // Websocket identifier
103
+ function start_web_socket() {
100
104
  if (ws) return; // already running
101
105
 
102
- var url = 'ws://' + window.location.host + '/_ws';
103
- var ws = new WebSocket(url);
104
- var self = this;
105
- ws.onopen = function() {
106
- ws.send('id:' + name);
107
- };
108
- ws.onmessage = function(evt) {
109
- // evt.data contains received string.
110
- var msg = jQuery.parseJSON(evt.data);
111
- var data = msg;
112
- self.events.append(data);
113
- };
106
+ var url = 'ws://' + window.location.host + '/_ws?sid=' + opts.sid;
107
+ ws = new WebSocket(url);
108
+ ws.onopen = on_open;
109
+ ws.onmessage = on_message;
114
110
  ws.onclose = function() {
115
111
  var status = "onclose";
116
112
  };
@@ -118,8 +114,81 @@ OML.data_source = function(name, updateURL, schema, events) {
118
114
  var status = "onerror";
119
115
  };
120
116
  }
117
+
118
+ // Send a message to the server
119
+ //
120
+ // @params type - Type of message
121
+ // @params args - Hash of additional args ('ds_name' of this data source will be added)
122
+ //
123
+ // TODO: Would need to cache messages if connection isn't established yet
124
+ //
125
+ function send_server_msg(type, args) {
126
+ args.ds_name = name;
127
+ msg = {type: type, args: args}
128
+ ws.send(JSON.stringify(msg));
129
+ }
130
+
131
+
132
+ function on_open() {
133
+ if (!active_slice_col_name) {
134
+ send_server_msg('register_data_source', {offset: offset + rows.length})
135
+ }
136
+ };
137
+
138
+ function on_message(evt) {
139
+ // evt.data contains received string.
140
+ var msg = jQuery.parseJSON(evt.data);
141
+ switch(msg.type) {
142
+ case 'datasource_update':
143
+ on_update(msg);
144
+ break;
145
+ case 'reply':
146
+ // great
147
+ break;
148
+ default:
149
+ throw "Unknown message type '" + msg.type + "'.";
150
+ }
151
+ };
152
+
153
+ function on_update(msg) {
154
+ if (unique_index_check) {
155
+ // Let's first see if we simply replace a row
156
+ _.each(msg.rows, function(r) {
157
+ if (!unique_index_check(r)) {
158
+ rows.push(r); // new index
159
+ }
160
+ });
161
+ } else {
162
+ // need to append to 'rows' as it's referenced in other closures
163
+ _.each(msg.rows, function(r) { rows.push(r) });
164
+ var chop = msg.offset - offset;
165
+ if (offset >= 0 && chop > 0) {
166
+ rows = _.rest(rows, chop);
167
+ }
168
+ }
169
+ offset = msg.offset;
170
+
171
+ update_indexes();
172
+ var evt = {data_source: data_source};
173
+ OHUB.trigger(event_name, evt);
174
+ OHUB.trigger("data_source.changed", evt);
175
+ }
176
+
177
+ // Request a new slice from the server. Clear existing state
178
+ function set_slice_column(col_value) {
179
+ if (active_slice_value == col_value) return;
180
+
181
+ active_slice_column_id = col_value;
182
+ // Reset state
183
+ rows = [];
184
+ update_indexes();
185
+ sm = {col_name: active_slice_col_name, col_value: col_value}
186
+ send_server_msg('request_slice', {slice: sm})
187
+ }
188
+ var active_slice_col_name = null;
189
+ var active_slice_value = null;
121
190
 
122
- ds._start_polling_backend = function() {
191
+ function start_polling_backend() {
123
192
  var first_time = this.update_interval < 0;
124
193
 
125
194
  if (this.update_interval < 0 || this.update_interval > interval) {
@@ -128,7 +197,7 @@ OML.data_source = function(name, updateURL, schema, events) {
128
197
 
129
198
  if (first_time) {
130
199
  var self = this;
131
- L.require(['/resource/vendor/jquery/jquery.js', '/resource/vendor/jquery/jquery.periodicalupdater.js'], function() {
200
+ L.require(['vendor/jquery/jquery.js', 'vendor/jquery/jquery.periodicalupdater.js'], function() {
132
201
  var update_interval = self.update_interval * 1000;
133
202
  if (update_interval < 1000) update_interval = 3000;
134
203
  var opts = {
@@ -152,10 +221,68 @@ OML.data_source = function(name, updateURL, schema, events) {
152
221
  return true;
153
222
  }
154
223
 
155
- this.on_changed = function(update_f) {
156
- OHUB.bind(this.event_name, update_f);
224
+ // Let's check if this data_source maintains uniqueness along one axis (column)
225
+ if (opts.unique_column) {
226
+ var col_name = opts.unique_column;
227
+ var index = -1;
228
+ _.find(schema, function(cd) {
229
+ index += 1;
230
+ return cd.name == col_name;
231
+ });
232
+ if (index >= 0) {
233
+ var key2row = {};
234
+ unique_index_check = function (row) {
235
+ var key = row[index];
236
+ var existing_row = key2row[key];
237
+ if (existing_row) {
238
+ // replace content of existing row with 'row'
239
+ // Need to replace in place, there may be a better way
240
+ existing_row.length = 0;
241
+ _.each(row, function(e) { existing_row.push(e); })
242
+ return true;
243
+ }
244
+ key2row[key] = row;
245
+ return false;
246
+ }
247
+ // pre-seed
248
+ rows = _.uniq(rows, false, function(r) { return r[index]; });
249
+ _.each(rows, function(r) { key2row[r[index]] = r; });
250
+ } else {
251
+ throw "Error in processing option 'unique_column'. Unknown column '" + col_name + "'."
252
+ }
157
253
  }
158
254
 
159
- return ds;
255
+ // In slice mode, only fetch a 'slice' of the underlying data source. A slice
256
+ // is defined by specific value in the 'slice_column' of all rows.
257
+ //
258
+ // opts.slice:
259
+ // slice_column: id
260
+ // event:
261
+ // name: graph.static_network.links.changed
262
+ // key: id
263
+ if (opts.slice) {
264
+ var so = opts.slice;
265
+ active_slice_col_name = so.slice_column;
266
+
267
+ if (so.event) {
268
+ var evt_name = so.event.name;
269
+ if (! evt_name)
270
+ throw "Missing event name in slice definition for data source '" + name + "'.";
271
+ OHUB.bind(evt_name, function(evt) {
272
+ set_slice_column(evt.id);
273
+ })
274
+ }
275
+ }
276
+
277
+ if (window.WebSocket) {
278
+ start_web_socket();
279
+ }
280
+
281
+ // Bind to event directly
282
+ // this.on_changed = function(update_f) {
283
+ // OHUB.bind(this.event_name, update_f);
284
+ // }
285
+
286
+ return data_source;
160
287
  }
161
288
 
@@ -113,17 +113,36 @@ L = new function() {
113
113
  };
114
114
 
115
115
  } else { // css
116
- sel = document.createElement("link");
116
+ var sel = document.createElement("link");
117
117
  sel.href = url;
118
118
  sel.rel = "stylesheet";
119
119
  sel.type ="text/css";
120
- // there is no consistent support for detecting the successful loading of
121
- // a css file. Not sure what happens if we simply don't care.
122
- this._onLoad(url);
123
- //this._css_el = sel;
120
+ this._monitor_css_loaded(sel, url)
124
121
  }
125
122
  return sel;
126
123
  }
124
+
125
+ this._monitor_css_loaded = function(sel, url) {
126
+ var href = sel.href;
127
+ var self = this;
128
+ window.setTimeout(function() {
129
+ var sheets = document.styleSheets;
130
+ for (var i = 0; i < sheets.length; i++) {
131
+ var sheet = sheets[i];
132
+ if (sheet.href == href) {
133
+ // TODO: HACK ALLERT
134
+ // OK, stylesheet is loaded but we are having issues with SLickgrid and Chrome
135
+ // recoginisng it immediately, maybe a delay helps
136
+ window.setTimeout(function() {
137
+ self._onLoad(url);
138
+ }, 200);
139
+ return;
140
+ }
141
+ }
142
+ // still not loaded, try again
143
+ self._monitor_css_loaded(sel, url);
144
+ }, 100) ;
145
+ }
127
146
 
128
147
  this._getAbsoluteUrl = function(url) {
129
148
  if (url.indexOf(':') < 0) { // don't change when it contains protocol
@@ -134,7 +153,8 @@ L = new function() {
134
153
  s.push('js');
135
154
  }
136
155
  var ext = s.pop();
137
- url = this.baseURL + '/' + ext + "/" + url;
156
+ //url = this.baseURL + '/' + ext + "/" + url;
157
+ url = this.baseURL + '/' + url;
138
158
  }
139
159
  }
140
160
  return url;
@@ -247,56 +267,7 @@ L = new function() {
247
267
  }
248
268
  return true;
249
269
  };
250
-
251
- // Report that an URL has been loaded through some other means
252
- var self = this;
253
- $(document).ready(function() {
254
- self._loaded['#DOM_LOADED'] = true;
255
- self._checkAllPending();
256
- });
257
-
258
-
259
- // this._checkOnePending = function(p) {
260
- // var deps = p.deps;
261
- // var loaded = this._loaded;
262
- // var l = deps.length;
263
- // for (; l;) {
264
- // var name = deps[--l];
265
- // if (loaded[name] != true) {
266
- // return p;
267
- // }
268
- // }
269
- // // OK, all dependencies fulfilled.
270
- // var op = p.op;
271
- // switch (op) {
272
- // case "load":
273
- // var next = p.next;
274
- // var url = next.shift();
275
- // var new_pending = null;
276
- // if (next.length > 0) {
277
- // // load next one
278
- // new_pending = {op: 'load', deps: [url], next: next};
279
- // }
280
- // this._loadOne(url);
281
- // return new_pending;
282
- // case "provide":
283
- // if (p.onReady) {
284
- // p.onReady();
285
- // }
286
- // this._provided[p.obj_name] = true;
287
- // return null;
288
- // case "require":
289
- // if (this._provided[p.obj_name] == true) {
290
- // if (p.onReady) {
291
- // p.onReady();
292
- // }
293
- // return null; // done
294
- // }
295
- // return p;
296
- // }
297
- // return null; // not sure what op that is, let's remove it
298
- // }
299
-
270
+
300
271
  this._arr_flatten = function(array) {
301
272
  // http://tech.karbassi.com/2009/12/17/pure-javascript-flatten-array/
302
273
  var flat = [];
@@ -306,6 +277,16 @@ L = new function() {
306
277
  }
307
278
  return flat;
308
279
  }
280
+
281
+ // Report that an URL has been loaded through some other means
282
+ var self = this;
283
+ //this.require(['vendor/jquery/jquery.js'], function() {
284
+ $(document).ready(function() {
285
+ self._loaded['#DOM_LOADED'] = true;
286
+ self._checkAllPending();
287
+ });
288
+ //});
289
+
309
290
  };
310
- //L.deps = {};
291
+
311
292
 
@@ -233,19 +233,19 @@ ol.widget_tools_menu li.current a {
233
233
  }
234
234
 
235
235
  ol.widget_tools_menu li.data_line_chart2 a {
236
- background: url(/resource/image/graph/line_chart.png) 0px -50px no-repeat;
236
+ background: url(/resource/graph/img/line_chart.png) 0px -50px no-repeat;
237
237
  }
238
238
 
239
239
  ol.widget_tools_menu li.data_scatter_plot a {
240
- background: url(/resource/image/graph/scatter_plot.png) 0px 0px no-repeat;
240
+ background: url(/resource/graph/img/scatter_plot.png) 0px 0px no-repeat;
241
241
  }
242
242
 
243
243
  ol.widget_tools_menu li.data_table2 a {
244
- background: url(/resource/image/graph/table.png) 0px -50px no-repeat;
244
+ background: url(/resource/graph/img/table.png) 0px -50px no-repeat;
245
245
  }
246
246
 
247
247
  ol.widget_tools_menu li.info a {
248
- background: url(/resource/image/graph/info.png) 3px 3px no-repeat;
248
+ background: url(/resource/graph/img/info.png) 3px 3px no-repeat;
249
249
  margin-left: 10px
250
250
  }
251
251