quick_search-core 0.1.1 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (136) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +7 -6
  3. data/app/assets/javascripts/quick_search.js.erb +9 -0
  4. data/app/assets/javascripts/quick_search/appstats.js.erb +73 -0
  5. data/app/assets/javascripts/quick_search/appstats_best_bets.js.erb +905 -0
  6. data/app/assets/javascripts/quick_search/appstats_clicks_overview.js.erb +719 -0
  7. data/app/assets/javascripts/quick_search/appstats_general_statistics.js.erb +908 -0
  8. data/app/assets/javascripts/quick_search/appstats_sessions_details.js.erb +660 -0
  9. data/app/assets/javascripts/quick_search/appstats_sessions_overview.js.erb +481 -0
  10. data/app/assets/javascripts/quick_search/appstats_spelling_suggestions.js.erb +902 -0
  11. data/app/assets/javascripts/quick_search/appstats_top_searches.js.erb +633 -0
  12. data/app/assets/javascripts/quick_search/event_tracking.js.erb +22 -33
  13. data/app/assets/javascripts/quick_search/xhr_search.js +7 -3
  14. data/app/assets/stylesheets/quick_search/appstats.scss +148 -0
  15. data/app/assets/stylesheets/quick_search/quick_search.scss +0 -16
  16. data/app/controllers/concerns/quick_search/doi_trap.rb +1 -1
  17. data/app/controllers/quick_search/appstats_controller.rb +267 -144
  18. data/app/controllers/quick_search/logging_controller.rb +165 -0
  19. data/app/controllers/quick_search/search_controller.rb +1 -23
  20. data/app/controllers/quick_search/typeahead_controller.rb +48 -0
  21. data/app/models/event.rb +6 -0
  22. data/app/models/search.rb +7 -0
  23. data/app/models/session.rb +9 -0
  24. data/app/searchers/quick_search/best_bets_searcher.rb +1 -1
  25. data/app/views/layouts/quick_search/_google_analytics.html.erb +4 -9
  26. data/app/views/layouts/quick_search/_search_form.html.erb +2 -2
  27. data/app/views/layouts/quick_search/application.html.erb +4 -0
  28. data/app/views/quick_search/appstats/_date_range.html.erb +14 -13
  29. data/app/views/quick_search/appstats/_graph_best_bets.html.erb +6 -0
  30. data/app/views/quick_search/appstats/_graph_clicks_overview.html.erb +12 -0
  31. data/app/views/quick_search/appstats/_graph_general_statistics.html.erb +19 -0
  32. data/app/views/quick_search/appstats/_graph_sessions_details.html.erb +19 -0
  33. data/app/views/quick_search/appstats/_graph_sessions_overview.html.erb +9 -0
  34. data/app/views/quick_search/appstats/_graph_spelling_suggestions.html.erb +6 -0
  35. data/app/views/quick_search/appstats/_graph_top_searches.html.erb +6 -0
  36. data/app/views/quick_search/appstats/_menu.html.erb +16 -3
  37. data/app/views/quick_search/appstats/_sessions_details_device_filters.html.erb +9 -0
  38. data/app/views/quick_search/appstats/_sessions_details_location_filters.html.erb +9 -0
  39. data/app/views/quick_search/appstats/_sessions_overview_graph_filters.html.erb +9 -0
  40. data/app/views/quick_search/appstats/clicks_overview.html.erb +3 -14
  41. data/app/views/quick_search/appstats/index.html.erb +3 -23
  42. data/app/views/quick_search/appstats/sessions_details.html.erb +9 -0
  43. data/app/views/quick_search/appstats/sessions_overview.html.erb +9 -0
  44. data/app/views/quick_search/appstats/top_searches.html.erb +3 -32
  45. data/app/views/quick_search/appstats/top_spot.html.erb +7 -7
  46. data/app/views/quick_search/search/_module_with_paging.html.erb +1 -1
  47. data/app/views/quick_search/search/_result_title.html.erb +1 -1
  48. data/config/quicksearch_config.yml.example +3 -0
  49. data/config/routes.rb +31 -3
  50. data/db/migrate/20161201141003_create_sessions.rb +12 -0
  51. data/db/migrate/20161201142811_change_event_columns.rb +11 -0
  52. data/db/migrate/20161201143901_add_session_id_to_searches.rb +5 -0
  53. data/db/migrate/20161212192454_add_date_string_columns.rb +11 -0
  54. data/db/seeds.rb +83 -7
  55. data/lib/generators/quick_search/templates/quick_search_typeahead.js +253 -0
  56. data/lib/generators/quick_search/typeahead_generator.rb +162 -0
  57. data/lib/quick_search/engine.rb +1 -0
  58. data/lib/quick_search/version.rb +1 -1
  59. data/test/dummy/db/schema.rb +25 -6
  60. data/test/dummy/log/benchmark.log +121 -241
  61. data/test/dummy/log/development.log +236 -0
  62. data/test/dummy/tmp/cache/assets/sprockets/v3.0/0b/0bXp2nnjPLNuYQRAMo1RkhNr8RSC8vqZo_7soo0XZTE.cache +1 -0
  63. data/test/dummy/tmp/cache/assets/sprockets/v3.0/3p/3pAfj3gt9c9rLmOrDkMvW2r6Swm5YhuGQ1EN3va9LDE.cache +6 -0
  64. data/test/dummy/tmp/cache/assets/sprockets/v3.0/3r/3r7qg-LCIcD5882b6GKgRTZycpAlhoSNJccVH06yRCQ.cache +3 -0
  65. data/test/dummy/tmp/cache/assets/sprockets/v3.0/{UA/UAOIipK_ejTAUFI6XxASoweyUiC3t64VfVzV-MfsFD8.cache → 4h/4hLiHzJdffGLMZCeIkbisOdFQSyqs54YkoZpBpGotVk.cache} +0 -0
  66. data/test/dummy/tmp/cache/assets/sprockets/v3.0/{Hr/Hr-kCuPY72nIKAdnsDTz9JqXd_z1WL6FSGMAq4HppZg.cache → 5Y/5Yh8GnSzywqhuMWMloKnL9FnuIxa9rBw6hN2Ecv0urw.cache} +0 -0
  67. data/test/dummy/tmp/cache/assets/sprockets/v3.0/8h/8hHsBZ0Il3GVKNj0HgTh-s-XpPVkHrcSY0EJ4v548sk.cache +4 -0
  68. data/test/dummy/tmp/cache/assets/sprockets/v3.0/{fI/fInu_Gja7ik39t207tqj4CtlL0akQRbjD2T7qEtd0zE.cache → 8n/8nKAboU_CeVIX30-Q9BtSV5TXdE07WU8hO0OQ0N3KOs.cache} +0 -0
  69. data/test/dummy/tmp/cache/assets/sprockets/v3.0/{dz/dzCaa80YgyvJINTgsyrVhKv9UQ1OC82GfAsA-IP96iQ.cache → Af/Afug8duevWkZFPkOMnZ5z_IbRT6JMZo4jw1QFmLiXXA.cache} +0 -0
  70. data/test/dummy/tmp/cache/assets/sprockets/v3.0/C2/C24SLDoUbdiHRmPZx5lIZ3XPXmn9FDq7j7gZmbpDtcE.cache +1 -0
  71. data/test/dummy/tmp/cache/assets/sprockets/v3.0/CH/CHuDjj47dHGqRD3uN1JNwnlFyjjEKB09KR6WVsLj2Do.cache +3 -0
  72. data/test/dummy/tmp/cache/assets/sprockets/v3.0/Ci/Cif3NOwhu5i6Qm3iRv2gNJLi_cu8yDVz0Nrq8TZu1tc.cache +3 -0
  73. data/test/dummy/tmp/cache/assets/sprockets/v3.0/FQ/FQWd8V-Pek1LBAfW9vzcG-FpWySsPRhMVzH9DlPxLWU.cache +1 -0
  74. data/test/dummy/tmp/cache/assets/sprockets/v3.0/Fa/FaYEz8CfLTkxVZvnbgKGvJMhhBwNvEgsZgUwaHNRlaQ.cache +0 -0
  75. data/test/dummy/tmp/cache/assets/sprockets/v3.0/IA/IALQq6ICbs3VBSRsaUmGuN73Qv5wDfWTP86VmMh_sVs.cache +0 -0
  76. data/test/dummy/tmp/cache/assets/sprockets/v3.0/K1/K1jnTrW-_s64kqCA6fnoQ-ID-rDaGX34J-TNPyzDbLs.cache +1 -0
  77. data/test/dummy/tmp/cache/assets/sprockets/v3.0/Mz/MzXE1Go_GKyu6AvJPhw394BtPM_jVTf0hMwobBi15tk.cache +1 -0
  78. data/test/dummy/tmp/cache/assets/sprockets/v3.0/Os/OsIhoBDw5N2AWGQ-EMK79tgwPS1AC6Dy_gMSJdOv2Ss.cache +0 -0
  79. data/test/dummy/tmp/cache/assets/sprockets/v3.0/{B5/B5ptGSZGmgHvoK2UDCAtpMhWxJEKxKFhyL9ACeBfzQk.cache → PC/PCth9nzoRrp5GI3Ut8FxlGpXjH63V7k2p4PRwfyu2sQ.cache} +0 -0
  80. data/test/dummy/tmp/cache/assets/sprockets/v3.0/Pw/Pw3Jv2p7MsQz6pttCZig6VMVQ30sRyIDRS-2nM32yqY.cache +3 -0
  81. data/test/dummy/tmp/cache/assets/sprockets/v3.0/RI/RIOgtcuvLAJZl62RvAzqine3jCO3i2qyhswiW2G1bw8.cache +3 -0
  82. data/test/dummy/tmp/cache/assets/sprockets/v3.0/R_/R_6WhfFaPUAOAFfFd4bgUonI5aB4Fa6iOMY2J6G3U98.cache +4 -0
  83. data/test/dummy/tmp/cache/assets/sprockets/v3.0/{pj/pjJDYrBipDo6Tr9_-W4UDzfZZ4UPTy9YpXrBQFRXnlo.cache → S3/S3gPdA-Zqya5r6wNhnlwqGV3B3-GDaA8i1fL_jo66AI.cache} +0 -0
  84. data/test/dummy/tmp/cache/assets/sprockets/v3.0/SS/SS3eYrFE6ghi5G_3POW760Y4BWo5OAaK5QjDrRGXOcs.cache +1 -0
  85. data/test/dummy/tmp/cache/assets/sprockets/v3.0/{jj/jjdQCKZsewws2eRP7b2AVxRMvseOp8djjlDkB8UOtac.cache → Sq/SqjdxmYsdurpx9xk1ks32WEtf3D9_2BysE7RMxnOlmU.cache} +1 -1
  86. data/test/dummy/tmp/cache/assets/sprockets/v3.0/{os/os0qWv3yDfep0e7vVSGTgfn_n3xc4C4QZgmMzLQn0Ks.cache → Ta/TaJnQ_l0sfSsDOyVoi-S-KZQ6vIwzBhmS6hmNA_n8ug.cache} +0 -0
  87. data/test/dummy/tmp/cache/assets/sprockets/v3.0/{o6/o6ZQbq1aBFuVrE2xLbSbyZH2736sWM3Yj4ky9chT1bI.cache → X_/X_CxFXEdZo2C_in7FopAuAbplHn6W_V0SXyVQAMnTzI.cache} +0 -0
  88. data/test/dummy/tmp/cache/assets/sprockets/v3.0/{sR/sRU-UT8qK_38kkiFDXKBPogO1oOZuSvJFH-pgqPL_Ms.cache → Yh/YhRWll6bzgYE6Dmc5fVKbHyv5om4y3-27UrWeUbQcGk.cache} +0 -0
  89. data/test/dummy/tmp/cache/assets/sprockets/v3.0/{OD/ODHapE0li3WI1laVJoksoI5nmQd-8dDJXq_VxS4XefE.cache → _u/_uiA10I5HyJR94Tbc4a06CzdrQCAXX7Iz86WS5PKDQo.cache} +0 -0
  90. data/test/dummy/tmp/cache/assets/sprockets/v3.0/ai/ainCVF4dxXf85KoOLUSHvMMGg0qBNc7Vg-s-9v2ENJI.cache +4 -0
  91. data/test/dummy/tmp/cache/assets/sprockets/v3.0/cQ/cQqt0ri9GFvVnIs1pJUugIJs5tDuGQMMntW5CwpK6YY.cache +1 -0
  92. data/test/dummy/tmp/cache/assets/sprockets/v3.0/{1n/1nStVaWIQEwAlksUpB1fInwq6v3TikPvuRaSwwCnCLQ.cache → e0/e0Y2Gz8ftaW2O0RjoN2iWguitI-JQZckScAZqlQYkng.cache} +0 -0
  93. data/test/dummy/tmp/cache/assets/sprockets/v3.0/iH/iHnlNNY3rfdbVqt8LZBfcDQYONR8dA8LmxA9fv5paro.cache +2 -0
  94. data/test/dummy/tmp/cache/assets/sprockets/v3.0/{F0/F0oWBwLHpGFYNNtnGav-dJFH8rMDpNA5L8_aWm5Wq34.cache → ir/irxgIDPIY6Wz6fHWYp1dIrqAT1_8oa6-oiwqbFE_e-w.cache} +0 -0
  95. data/test/dummy/tmp/cache/assets/sprockets/v3.0/kn/knUtyVrg7nMIPldZa4MHhe7cC9eMchLZS4mc5HDWgDY.cache +1 -0
  96. data/test/dummy/tmp/cache/assets/sprockets/v3.0/ks/ks4DoIuUV6oUzoiXoPh7sW1k5ExNoUkR7ICjwuRnAT0.cache +1 -0
  97. data/test/dummy/tmp/cache/assets/sprockets/v3.0/m3/m375QQakjXd_2Trpvdot-i90nmeCCh0HWtzS66ZvxUU.cache +1 -0
  98. data/test/dummy/tmp/cache/assets/sprockets/v3.0/rQ/rQ_FgYkT2hdw9A6XmJKGgVb2dMtCrWWHwtS0X1_kdl0.cache +1 -0
  99. data/test/dummy/tmp/cache/assets/sprockets/v3.0/{pw/pwiIhcWPwTuy5Miz5zqOQGYFx-K3TbaCVQ6ls7EBkk0.cache → rU/rUqFWwHqrT5jeIFCEezOPsMMZiAU7ri6RKBGS2ezAfg.cache} +0 -0
  100. data/test/dummy/tmp/cache/assets/sprockets/v3.0/{pO/pO8hHVwybv1ZJBdPa2YC6bjqmk020OYFl85TYxtmrWQ.cache → rq/rqf5-J6k_zLc9ZlUgMj28nviKtRsko3-iEp_m_uNeY0.cache} +0 -0
  101. data/test/dummy/tmp/cache/assets/test/sprockets/13fe41fee1fe35b49d145bcc06610705 +0 -0
  102. data/test/dummy/tmp/cache/assets/test/sprockets/2f5173deea6c795b8fdde723bb4b63af +0 -0
  103. data/test/dummy/tmp/cache/assets/test/sprockets/357970feca3ac29060c1e3861e2c0953 +0 -0
  104. data/test/dummy/tmp/cache/assets/test/sprockets/cffd775d018f68ce5dba1ee0d951a994 +0 -0
  105. data/test/dummy/tmp/cache/assets/test/sprockets/d771ace226fc8215a3572e0aa35bb0d6 +0 -0
  106. data/test/dummy/tmp/cache/assets/test/sprockets/f7cbd26ba1d28d48de824f0e94586655 +0 -0
  107. metadata +143 -119
  108. data/app/assets/javascripts/quick_search/appstats.js +0 -8
  109. data/app/views/quick_search/appstats/_click_count_table.html.erb +0 -23
  110. data/app/views/quick_search/appstats/_top_spot_report_table.html.erb +0 -33
  111. data/app/views/quick_search/appstats/module_click_detail.html.erb +0 -32
  112. data/app/views/quick_search/appstats/top_spot_detail.html.erb +0 -35
  113. data/test/dummy/tmp/cache/assets/sprockets/v3.0/0_/0_w_ydOOEFQOoETxJa-IxKppQocaiDwM5V08djCPYso.cache +0 -3
  114. data/test/dummy/tmp/cache/assets/sprockets/v3.0/3m/3mWfBeEpm_bJvaPQZYvnnAVtE_2helOWh_Tv-cEflrk.cache +0 -5
  115. data/test/dummy/tmp/cache/assets/sprockets/v3.0/4s/4sg52OgD5l4qx4GnojCVxg2itqwqb-KRanEdmdMus3Y.cache +0 -0
  116. data/test/dummy/tmp/cache/assets/sprockets/v3.0/5U/5UPnsccuZFLk9OqbmFMvB55mbvGptApx9Z55HWjEN90.cache +0 -3
  117. data/test/dummy/tmp/cache/assets/sprockets/v3.0/9a/9acKNgyVD8_WK401tMy6Ce98g-LS4VpwFvGQdzCV9mI.cache +0 -0
  118. data/test/dummy/tmp/cache/assets/sprockets/v3.0/Ba/BaymviI8cwAJQMOIzWCf6Lt-PM2sNFTvY9hQKsfDNNw.cache +0 -3
  119. data/test/dummy/tmp/cache/assets/sprockets/v3.0/Dd/DdFHg3C_voetfvKGKX7t8PGzZlkO45-huHNtaou5rxg.cache +0 -1
  120. data/test/dummy/tmp/cache/assets/sprockets/v3.0/Fp/FprCQeeZguht46WNSpA3Y3JHKehovFXrj63nDrvvwFE.cache +0 -1
  121. data/test/dummy/tmp/cache/assets/sprockets/v3.0/GJ/GJrfWiarIi0Dt6sdKVMfUF1cdZ6NbqZxXHhzNbFtpBw.cache +0 -1
  122. data/test/dummy/tmp/cache/assets/sprockets/v3.0/Gp/GpoziOxxB-hisco0rl7Nnsnw0UWud7R9Yge2Q3o1eN4.cache +0 -2
  123. data/test/dummy/tmp/cache/assets/sprockets/v3.0/It/It5VkJv-53-LICLKZWWyp2WcbD86DGotAL0MY3hhfpg.cache +0 -6
  124. data/test/dummy/tmp/cache/assets/sprockets/v3.0/O6/O6dw148Xya7NYlsRFMEzJyvRcySM6iOL1jRUpdQo9B8.cache +0 -1
  125. data/test/dummy/tmp/cache/assets/sprockets/v3.0/Oj/OjMkKTW7OkthjJAQHDID8GV30IZC9F0dJ1zGiFame9U.cache +0 -4
  126. data/test/dummy/tmp/cache/assets/sprockets/v3.0/SU/SUtZ_ltPqy9A9A-_zqNPhNPvjxCOnrdqXHSZv5S9mOk.cache +0 -1
  127. data/test/dummy/tmp/cache/assets/sprockets/v3.0/Tv/TvZgmm69VEMHUJQIBoij61oXMkgzp6whVo7l8mJ9qpw.cache +0 -3
  128. data/test/dummy/tmp/cache/assets/sprockets/v3.0/YJ/YJZdK01T1KTS84Mb6p_2TasmJNZeGZc4FMtBPCKGr_M.cache +0 -3
  129. data/test/dummy/tmp/cache/assets/sprockets/v3.0/ah/ahhhd3ysbQmVDNzq2L_rb4t6rqqdnqeY6ujztBoZDA8.cache +0 -1
  130. data/test/dummy/tmp/cache/assets/sprockets/v3.0/gv/gvZKkbgiExbcQrT4eo0HB-j4JoDRAxdmDjKRxeEdK0Y.cache +0 -1
  131. data/test/dummy/tmp/cache/assets/sprockets/v3.0/hj/hj_r-O1QjHJIPcZVnlB_FGPdIRAi9NkxpT2oXDRIsGE.cache +0 -1
  132. data/test/dummy/tmp/cache/assets/sprockets/v3.0/o2/o2V1ahk8vFR6sXWNh5BB7w6MBj04zCyX-o1xFZONydE.cache +0 -1
  133. data/test/dummy/tmp/cache/assets/sprockets/v3.0/tE/tEO71oPPFXN_2c4p39nU0OiF9ARg13fjdQlnPqAx1KY.cache +0 -4
  134. data/test/dummy/tmp/cache/assets/sprockets/v3.0/tW/tWFRsAv4WWu2ch-x3AJZd3KOvBXG3MwH6Q6Xn-tFBtw.cache +0 -1
  135. data/test/dummy/tmp/cache/assets/sprockets/v3.0/x6/x6W754ylumshr3wBUHHmcgyWs8UR3Od7FaI6tqvjKmk.cache +0 -1
  136. data/test/dummy/tmp/cache/assets/sprockets/v3.0/yy/yyJ1P7RQciOiW8TgQiu1RMDdbWd4rqxd2BGU9HkY3L8.cache +0 -0
@@ -0,0 +1,660 @@
1
+ <% url_helper = QuickSearch::Engine.routes.url_helpers %>
2
+
3
+ (function() {
4
+ var Globals = {};
5
+ Globals["#graph_sessions_location"] = {};
6
+ Globals["#graph_sessions_device"] = {};
7
+
8
+ $(document).on("turbolinks:load", function() {
9
+ if ($("#graph_sessions_location").length) {
10
+ d3.select("#locationIconContainer").append("i")
11
+ .attr("class", "fa fa-spinner fa-spin fa-5x fa-fw big-icon")
12
+ .attr("id", "locationIcon");
13
+ d3.select("#deviceIconContainer").append("i")
14
+ .attr("class", "fa fa-spinner fa-spin fa-5x fa-fw big-icon")
15
+ .attr("id", "deviceIcon");
16
+ // Redraw graph if the date range is changed
17
+ document.getElementById("dateButton").addEventListener("click", function() {
18
+ var from = $("#from").datepicker("getDate");
19
+ var to = new Date($("#to").datepicker("getDate").getTime() + 1000*60*60*24);
20
+ document.getElementById("numDays").innerHTML = "" + parseInt((to-from)/(1000*60*60*24));
21
+ var usePercLoc = Globals["#graph_sessions_location"].UsePerc
22
+ $.ajax({
23
+ type: "GET",
24
+ contentType: "application/json; charset=utf-8",
25
+ url: '<%= url_helper.data_sessions_location_path %>',
26
+ dataType: "json",
27
+ data: {
28
+ "start_date": from,
29
+ "end_date": to,
30
+ "use_perc": usePercLoc
31
+ },
32
+ success: function(sessionsDataSet) {
33
+ var dataMain = _.cloneDeep(sessionsDataSet);
34
+ draw_graph_sessions_details("#graph_sessions_location", dataMain, false, true, usePercLoc);
35
+ },
36
+ error: function(result) {
37
+ error();
38
+ }
39
+ });
40
+ var usePercDev = Globals["#graph_sessions_device"].UsePerc;
41
+ $.ajax({
42
+ type: "GET",
43
+ contentType: "application/json; charset=utf-8",
44
+ url: '<%= url_helper.data_sessions_device_path %>',
45
+ dataType: "json",
46
+ data: {
47
+ "start_date": from,
48
+ "end_date": to,
49
+ "use_perc": usePercDev
50
+ },
51
+ success: function(sessionsDataSet) {
52
+ var dataMain = _.cloneDeep(sessionsDataSet);
53
+ draw_graph_sessions_details("#graph_sessions_device", dataMain, false, true, usePercDev);
54
+ },
55
+ error: function(result) {
56
+ error();
57
+ }
58
+ });
59
+ });
60
+ $.ajax({
61
+ type: "GET",
62
+ contentType: "application/json; charset=utf-8",
63
+ url: '<%= url_helper.data_sessions_location_path %>',
64
+ dataType: "json",
65
+ success: function(sessionsDataSet) {
66
+ d3.select("#locationIcon").transition().duration(250)
67
+ .style("opacity", .000001)
68
+ .remove();
69
+ var dataMain = _.cloneDeep(sessionsDataSet);
70
+ draw_graph_sessions_details("#graph_sessions_location", dataMain, false, false, false);
71
+
72
+ if ($("#graph_sessions_location").length) {
73
+ document.getElementsByClassName("session_location_filter")[0].addEventListener("click", process_filters);
74
+ document.getElementsByClassName("session_location_filter")[1].addEventListener("click", process_filters);
75
+ }
76
+ },
77
+ error: function(result) {
78
+ error();
79
+ }
80
+ });
81
+ $.ajax({
82
+ type: "GET",
83
+ contentType: "application/json; charset=utf-8",
84
+ url: '<%= url_helper.data_sessions_device_path %>',
85
+ dataType: "json",
86
+ success: function(sessionsDataSet) {
87
+ d3.select("#deviceIcon").transition().duration(250)
88
+ .style("opacity", .000001)
89
+ .remove();
90
+ var dataMain = _.cloneDeep(sessionsDataSet);
91
+ draw_graph_sessions_details("#graph_sessions_device", dataMain, false, false, false);
92
+
93
+ if ($("#graph_sessions_location").length) {
94
+ document.getElementsByClassName("session_device_filter")[0].addEventListener("click", process_filters);
95
+ document.getElementsByClassName("session_device_filter")[1].addEventListener("click", process_filters);
96
+ }
97
+ },
98
+ error: function(result) {
99
+ error();
100
+ }
101
+ });
102
+ }
103
+ });
104
+
105
+ function error() {
106
+ console.log("Error retrieving data");
107
+ }
108
+
109
+ function draw_graph_sessions_details(id, dataShared, transitioning, dateUpdated, usePerc) {
110
+ if ($("#graph_sessions_location").length) {
111
+ // General Variables
112
+ var svg; // SVG to contain graph
113
+ var dataInt; // Internal reference to graph dataset
114
+ // Dimension Variables
115
+ var margin; // Blank space around top graph (focus)
116
+ var margin2; // Blank space around bottom graph (context)
117
+ var width; // Drawable width of focus/context (not including margins)
118
+ var height; // Drawable height of focus (not including margins)
119
+ var height2; // Drawable height of context (not including margins)
120
+ // Date Variables
121
+ var parseDate; // Function to parse dates into proper format
122
+ // Scale Variables
123
+ var x; // X-scale for focus graph
124
+ var x2; // X-scale for context graph
125
+ var y; // Y-scale for focus graph
126
+ var y2; // Y-scale for context graph
127
+ // Brush and Zoom Variables
128
+ var brush; // Object that allows domain selection by brush movement
129
+ var zoom; // Object that allows domain selection by zooming
130
+ // Axis Variables
131
+ var xAxis; // X-axis for focus graph
132
+ var xAxis2; // X-axis for context graph
133
+ var yAxis; // Y-axis for focus graph
134
+ var yAxisFormat; // Conditional format for yAxis, depending on if displaying percentages or raw values
135
+ // Area Variables
136
+ var area; // Bottom area for focus graph
137
+ var areaTop; // Top area for focus graph
138
+ var area2; // Bottom area for context graph
139
+ var area2Top; // Top area for context graph
140
+ // Additional Data Variables
141
+ var legendData; // Data for legend construction (class and text fields)
142
+ // Selection Variables
143
+ var gAllSelection; // Selection for overarching group
144
+ var gAll; // Group containing all elements
145
+ var focusSelection; // Selection for focus group
146
+ var focus; // Group containing all focus elements
147
+ var contextSelection; // Selection for context group
148
+ var context; // Group containing all context elements
149
+ var clipSelection; // Selection for clip path
150
+ var legendGroupSelection; // Selection for legend group
151
+ var legendGroup; // Group containing all legnend information
152
+ var legendRectSelection; // Selection for legend rectangles
153
+ var legendTextSelection; // Selection for legend text
154
+ var xAxisSelection; // Selection for xAxis
155
+ var yAxisSelection; // Selection for yAxis
156
+ var titleSelection; // Selection for title
157
+ var focusPathSelection; // Selection for bottom focus path (area)
158
+ var focusPathTopSelection; // Selection for top focus path (area)
159
+ var xAxis2Selection; // Selection for xAxis2
160
+ var contextPathSelection; // Selection for bottom context path (area)
161
+ var contextPathTopSelection;// Selection for top context path (area)
162
+ var brushSelection; // Selection for brush
163
+ var zoomSelection; // Selection for zoom
164
+ // Update global percent flag
165
+ Globals[id].UsePerc = usePerc;
166
+
167
+ // Initialize General Variables ///////////////////////////////////////////////////////////
168
+ svg = d3.select(id);
169
+
170
+ dataInt = dataShared;
171
+
172
+ // Initialize Dimension Variables /////////////////////////////////////////////////////////
173
+ margin = {
174
+ top: 50,
175
+ right: 20,
176
+ bottom: 110,
177
+ left: 40
178
+ };
179
+ margin2 = {
180
+ top: 430,
181
+ right: 20,
182
+ bottom: 30,
183
+ left: 40
184
+ };
185
+ width = +svg.attr("width") - margin.left - margin.right;
186
+ height = +svg.attr("height") - margin.top - margin.bottom;
187
+ height2 = +svg.attr("height") - margin2.top - margin2.bottom;
188
+
189
+ // Initialize Date Variables and Parse Dates //////////////////////////////////////////////
190
+ parseDate = d3.timeParse("%Y-%m-%d");
191
+
192
+ dataInt.forEach(function(d) {
193
+ d.date = parseDate(d.date);
194
+ });
195
+
196
+ // Initialize Scale Variables /////////////////////////////////////////////////////////////
197
+ x = d3.scaleTime().range([0, width]);
198
+ x2 = d3.scaleTime().range([0, width]);
199
+ y = d3.scaleLinear().range([height, 0]);
200
+ y2 = d3.scaleLinear().range([height2, 0]);
201
+
202
+ // Set domains
203
+ x2.domain(d3.extent(dataInt, function(d) {
204
+ return d.date;
205
+ }));
206
+ if (_.isEqual(undefined, Globals[id].Domain)) {
207
+ x.domain(d3.extent(dataInt, function(d) {
208
+ return d.date;
209
+ }));
210
+ } else {
211
+ var lb, ub;
212
+ if (Globals[id].Domain[0] < x2.domain()[0]) {
213
+ lb = x2.domain()[0];
214
+ } else {
215
+ lb = Globals[id].Domain[0];
216
+ }
217
+ if (Globals[id].Domain[1] > x2.domain()[1]) {
218
+ ub = x2.domain()[1];
219
+ } else {
220
+ ub = Globals[id].Domain[1];
221
+ }
222
+ if(Globals[id].Domain[0]>x2.domain()[1] || Globals[id].Domain[1]<x2.domain()[0]) {
223
+ lb = x2.domain()[0];
224
+ ub = x2.domain()[1];
225
+ }
226
+ x.domain([lb, ub]);
227
+ }
228
+ y.domain([0, d3.max(dataInt, function(d) {
229
+ return d.on + d.off;
230
+ })]);
231
+ y2.domain(y.domain());
232
+
233
+
234
+ // Initialize Brush and Zoom Variables ////////////////////////////////////////////////////
235
+ brush = d3.brushX()
236
+ .extent([
237
+ [0, 0],
238
+ [width, height2]
239
+ ])
240
+ .on("brush end", brushed);
241
+
242
+ zoom = d3.zoom()
243
+ .scaleExtent([1, 1000])
244
+ .translateExtent([
245
+ [0, 0],
246
+ [width, height]
247
+ ])
248
+ .extent([
249
+ [0, 0],
250
+ [width, height]
251
+ ])
252
+ .on("zoom", zoomed);
253
+
254
+ // Initialize Axis Variables //////////////////////////////////////////////////////////////
255
+ xAxis = d3.axisBottom(x);
256
+ xAxis2 = d3.axisBottom(x2);
257
+ yAxis = d3.axisLeft(y);
258
+ yAxisFormat = usePerc ? d3.format(".0%") : null;
259
+
260
+ yAxis.tickFormat(yAxisFormat);
261
+
262
+ // Initialize Area Variables //////////////////////////////////////////////////////////////
263
+ area = d3.area()
264
+ .curve(d3.curveMonotoneX)
265
+ .x(function(d) {
266
+ return x(d.date);
267
+ })
268
+ .y0(height)
269
+ .y1(function(d) {
270
+ return y(d.on);
271
+ });
272
+
273
+ areaTop = d3.area()
274
+ .curve(d3.curveMonotoneX)
275
+ .x(function(d) {
276
+ return x(d.date);
277
+ })
278
+ .y0(function(d) {
279
+ return y(d.on)+5;
280
+ })
281
+ .y1(function(d) {
282
+ return y(d.on + d.off);
283
+ });
284
+
285
+ area2 = d3.area()
286
+ .curve(d3.curveMonotoneX)
287
+ .x(function(d) {
288
+ return x2(d.date);
289
+ })
290
+ .y0(height2)
291
+ .y1(function(d) {
292
+ return y2(d.on);
293
+ });
294
+
295
+ area2Top = d3.area()
296
+ .curve(d3.curveMonotoneX)
297
+ .x(function(d) {
298
+ return x2(d.date);
299
+ })
300
+ .y0(function(d) {
301
+ return y2(d.on)+1;
302
+ })
303
+ .y1(function(d) {
304
+ return y2(d.on + d.off);
305
+ });
306
+
307
+ // Initialize Additional Data Variables ///////////////////////////////////////////////////
308
+ legendData = [{areaClass: "legendRect", locationText: "On Campus", deviceText: "On Mobile Device"},
309
+ {areaClass: "lightLegendRect", locationText: "Off Campus", deviceText: "On Non-Mobile Device"}];
310
+
311
+ // Make overarching group /////////////////////////////////////////////////////////////////
312
+ gAllSelection = svg.selectAll(".gAll").data([dataInt]);
313
+
314
+ gAllSelection.exit().transition().duration(500)
315
+ .style("opacity", .000001)
316
+ .remove();
317
+ gAllSelection.enter().append("g")
318
+ .attr("class", "gAll")
319
+ .attr("transform", "translate(0,0)");
320
+
321
+ gAll = svg.select(".gAll");
322
+
323
+ // Make focus
324
+ focusSelection = gAll.selectAll(".focus").data([dataInt]);
325
+
326
+ focusSelection.exit().transition().duration(500)
327
+ .style("opacity", .000001)
328
+ .remove();
329
+ focusSelection.enter().append("g")
330
+ .attr("class", "focus")
331
+ .attr("transform", "translate(" + margin.left + "," + margin.top + ")");
332
+
333
+ focus = gAll.select(".focus");
334
+
335
+ // Make context
336
+ contextSelection = gAll.selectAll(".context").data([dataInt]);
337
+
338
+ contextSelection.exit().transition().duration(500)
339
+ .style("opacity", .000001)
340
+ .remove();
341
+ contextSelection.enter().append("g")
342
+ .attr("class", "context")
343
+ .attr("transform", "translate(" + margin2.left + "," + margin2.top + ")");
344
+
345
+ context = gAll.select(".context");
346
+
347
+ // Make clip path
348
+ clipSelection = gAll.selectAll("defs").data([dataInt]);
349
+
350
+ clipSelection.exit().transition().duration(500)
351
+ .style("opacity", .000001)
352
+ .remove();
353
+ clipSelection.enter().append("defs").append("clipPath")
354
+ .attr("id", "clip")
355
+ .append("rect")
356
+ .attr("width", width)
357
+ .attr("height", height);
358
+
359
+ // Make legendGroup
360
+ legendGroupSelection = gAll.selectAll(".legend").data([dataInt]);
361
+
362
+ legendGroupSelection.exit().transition().duration(500)
363
+ .style("opacity", .000001)
364
+ .remove();
365
+ legendGroupSelection.enter().append("g")
366
+ .attr("class", "legend")
367
+ .attr("transform", "translate(" + margin.left + "," + 0 + ")");
368
+
369
+ legendGroup = svg.select(".legend");
370
+
371
+ // Make legendRects and legendText
372
+ legendRectSelection = legendGroup.selectAll(".legendRect, .lightLegendRect").data(legendData);
373
+
374
+ legendRectSelection.exit().transition().duration(500)
375
+ .style("opacity", .000001)
376
+ .remove();
377
+ legendRectSelection.enter().append("rect")
378
+ .style("opacity", .000001)
379
+ .attr("class", function(d, i) {
380
+ return d.areaClass;
381
+ })
382
+ .attr("width", width/32)
383
+ .attr("height", width/32)
384
+ .attr("transform", function (d,i) {
385
+ return "translate(" + (width/5 + i*2*width/5) + "," + 5 + ")";
386
+ })
387
+ .transition().duration(500)
388
+ .style("opacity", 1);
389
+
390
+ var legendTextSelection = legendGroup.selectAll(".legendText").data(legendData);
391
+
392
+ legendTextSelection.exit().transition().duration(500)
393
+ .style("opacity", .000001)
394
+ .remove();
395
+ legendTextSelection.enter().append("text")
396
+ .style("opacity", .000001)
397
+ .attr("class", "legendText")
398
+ .text(function(d) {
399
+ if (id=="#graph_sessions_location") {
400
+ return d.locationText;
401
+ } else {
402
+ return d.deviceText;
403
+ }
404
+ })
405
+ .attr("transform", function(d, i) {
406
+ return "translate(" + (width/5 + i*2*width/5 + width/32 + 5) + "," + (5 + 3*width/128) + ")";
407
+ })
408
+ .transition().duration(500)
409
+ .style("opacity", 1);
410
+
411
+ // Make focus x axis
412
+ xAxisSelection = focus.selectAll(".xAxis").data([dataInt]);
413
+
414
+ xAxisSelection.transition().duration(750)
415
+ .call(xAxis);
416
+ xAxisSelection.exit().transition().duration(500)
417
+ .style("opacity", .000001)
418
+ .remove();
419
+ xAxisSelection.enter().append("g")
420
+ .style("opacity", .000001)
421
+ .attr("class", "xAxis")
422
+ .attr("transform", "translate(0," + height + ")")
423
+ .call(xAxis)
424
+ .transition().duration(500)
425
+ .style("opacity", 1);
426
+
427
+ // Make focus y axis
428
+ yAxisSelection = focus.selectAll(".yAxis").data([dataInt]);
429
+
430
+ yAxisSelection.transition().duration(750)
431
+ .call(yAxis);
432
+ yAxisSelection.exit().transition().duration(500)
433
+ .style("opacity", .000001)
434
+ .remove();
435
+ yAxisSelection.enter().append("g")
436
+ .style("opacity", .000001)
437
+ .attr("class", "yAxis")
438
+ .attr("transform", "translate(0,0)")
439
+ .call(yAxis)
440
+ .transition().duration(500)
441
+ .style("opacity", 1);
442
+
443
+ // Make focus path
444
+ focusPathSelection = focus.selectAll(".area").data([dataInt]);
445
+
446
+ focusPathSelection.datum(dataInt).transition().duration(750)
447
+ .attr("d", area);
448
+ focusPathSelection.exit().transition().duration(500)
449
+ .style("opacity", .000001)
450
+ .remove();
451
+ focusPathSelection.enter().append("path")
452
+ .style("opacity", .000001)
453
+ .datum(dataInt)
454
+ .attr("class", "area")
455
+ .transition().duration(500)
456
+ .style("opacity", 1);
457
+
458
+ focusPathTopSelection = focus.selectAll(".areaLight").data([dataInt]);
459
+
460
+ focusPathTopSelection.datum(dataInt).transition().duration(750)
461
+ .attr("d", areaTop);
462
+ focusPathTopSelection.exit().transition().duration(500)
463
+ .style("opacity", .000001)
464
+ .remove();
465
+ focusPathTopSelection.enter().append("path")
466
+ .style("opacity", .000001)
467
+ .datum(dataInt)
468
+ .attr("class", "areaLight")
469
+ .transition().duration(500)
470
+ .style("opacity", 1);
471
+
472
+ // Make context x axis
473
+ xAxis2Selection = context.selectAll(".xAxis").data([dataInt]);
474
+
475
+ xAxis2Selection.transition().duration(500)
476
+ .call(xAxis2);
477
+ xAxis2Selection.exit().transition().duration(500)
478
+ .style("opacity", .000001)
479
+ .remove();
480
+ xAxis2Selection.enter().append("g")
481
+ .style("opacity", .000001)
482
+ .attr("class", "xAxis")
483
+ .attr("transform", "translate(0," + height2 + ")")
484
+ .call(xAxis2)
485
+ .transition().duration(500)
486
+ .style("opacity", 1);
487
+
488
+ // Make context path
489
+ contextPathSelection = context.selectAll(".area").data([dataInt]);
490
+
491
+ contextPathSelection.datum(dataInt).transition().duration(750)
492
+ .attr("d", area2);
493
+ contextPathSelection.exit().transition().duration(500)
494
+ .style("opacity", .000001)
495
+ .remove();
496
+ contextPathSelection.enter().append("path")
497
+ .style("opacity", .000001)
498
+ .datum(dataInt)
499
+ .attr("class", "area")
500
+ .attr("d", area2)
501
+ .transition().duration(500)
502
+ .style("opacity", 1);
503
+
504
+ contextPathTopSelection = context.selectAll(".areaLight").data([dataInt]);
505
+
506
+ contextPathTopSelection.datum(dataInt).transition().duration(750)
507
+ .attr("d", area2Top);
508
+ contextPathTopSelection.exit().transition().duration(500)
509
+ .style("opacity", .000001)
510
+ .remove();
511
+ contextPathTopSelection.enter().append("path")
512
+ .style("opacity", .000001)
513
+ .datum(dataInt)
514
+ .attr("class", "areaLight")
515
+ .attr("d", area2Top)
516
+ .transition().duration(500)
517
+ .style("opacity", 1);
518
+
519
+ // Make brush container
520
+ brushSelection = context.selectAll(".brush").data([dataInt]);
521
+
522
+ brushSelection.exit().transition().duration(500)
523
+ .style("opacity", .000001)
524
+ .remove();
525
+ brushSelection.enter().append("g")
526
+ .attr("class", "brush")
527
+ .call(brush)
528
+ .call(brush.move, x.range())
529
+ .merge(brushSelection)
530
+ .style("opacity", 1)
531
+ .call(brush);
532
+
533
+ // Misc ///////////////////////////////////////////////////////////////////////////////////
534
+ // Have to prevent zoom or brush temporarily for transitions to execute
535
+ if (transitioning) {
536
+ setTimeout(function() {
537
+ transitioning = false;
538
+ }, 50);
539
+ } // If not on transition, fade in brush
540
+ else {
541
+ svg.selectAll(".brush")
542
+ .style("opacity", .000001)
543
+ .transition().duration(500)
544
+ .style("opacity", 1);
545
+ }
546
+
547
+ // Before updating domains, move brush to domain it was previously set to
548
+ if (dateUpdated) {
549
+ var lb, ub;
550
+ if (x2(Globals[id].Domain[0]) < 0) {
551
+ lb = 0;
552
+ } else {
553
+ lb = x2(Globals[id].Domain[0]);
554
+ }
555
+ if (x2(Globals[id].Domain[1]) > width) {
556
+ ub = width;
557
+ } else {
558
+ ub = x2(Globals[id].Domain[1]);
559
+ }
560
+ if(Globals[id].Domain[0]>x2.domain()[1] || Globals[id].Domain[1]<x2.domain()[0]) {
561
+ lb = 0;
562
+ ub = width;
563
+ }
564
+ context.select(".brush").call(brush.move, [lb, ub]);
565
+ context.select(".brush").transition().duration(500)
566
+ .style("opacity", 1);
567
+ }
568
+
569
+ // Make zoom container
570
+ zoomSelection = gAll.selectAll(".zoom").data([dataInt]);
571
+
572
+ zoomSelection.exit().transition().duration(500)
573
+ .style("opacity", .000001)
574
+ .remove();
575
+ zoomSelection.enter().append("rect")
576
+ .attr("class", "zoom")
577
+ .attr("width", width)
578
+ .attr("height", height)
579
+ .attr("transform", "translate(" + margin.left + "," + margin.top + ")")
580
+ .merge(zoomSelection)
581
+ .call(zoom);
582
+
583
+
584
+ function brushed() {
585
+ if (!transitioning) {
586
+ if (d3.event.sourceEvent && d3.event.sourceEvent.type === "zoom") return;
587
+ var s = d3.event.selection || x2.range();
588
+ x.domain(s.map(x2.invert, x2));
589
+ Globals[id].Domain = x.domain();
590
+ focus.select(".area").attr("d", area);
591
+ focus.select(".areaLight").attr("d", areaTop);
592
+ focus.select(".xAxis").call(xAxis);
593
+ svg.select(".zoom").call(zoom.transform, d3.zoomIdentity
594
+ .scale(width / (s[1] - s[0]))
595
+ .translate(-s[0], 0));
596
+ }
597
+ }
598
+
599
+ function zoomed() {
600
+ if (!transitioning) {
601
+ if (d3.event.sourceEvent && d3.event.sourceEvent.type === "brush") return;
602
+ var t = d3.event.transform;
603
+ x.domain(t.rescaleX(x2).domain());
604
+ Globals[id].Domain = x.domain();
605
+ focus.select(".area").attr("d", area);
606
+ focus.select(".areaLight").attr("d", areaTop);
607
+ focus.select(".xAxis").call(xAxis);
608
+ context.select(".brush").call(brush.move, x.range().map(t.invertX, t));
609
+ }
610
+ }
611
+ }
612
+ }
613
+
614
+ function process_filters() {
615
+ var loc = document.querySelector('input[name = "loc"]:checked').value;
616
+ var dev = document.querySelector('input[name = "dev"]:checked').value;
617
+ var from = $("#from").datepicker("getDate");
618
+ var to = new Date($("#to").datepicker("getDate").getTime() + 1000*60*60*24);
619
+
620
+ var usePercLoc = _.isEqual(loc,"perc") ? true : false;
621
+ $.ajax({
622
+ type: "GET",
623
+ contentType: "application/json; charset=utf-8",
624
+ url: '<%= url_helper.data_sessions_location_path %>',
625
+ dataType: "json",
626
+ data: {
627
+ "start_date": from,
628
+ "end_date": to,
629
+ "use_perc": usePercLoc
630
+ },
631
+ success: function(sessionsDataSet) {
632
+ var dataMain = _.cloneDeep(sessionsDataSet);
633
+ draw_graph_sessions_details("#graph_sessions_location", dataMain, true, false, usePercLoc);
634
+ },
635
+ error: function(result) {
636
+ error();
637
+ }
638
+ });
639
+
640
+ var usePercDev = _.isEqual(dev,"perc") ? true : false;
641
+ $.ajax({
642
+ type: "GET",
643
+ contentType: "application/json; charset=utf-8",
644
+ url: '<%= url_helper.data_sessions_device_path %>',
645
+ dataType: "json",
646
+ data: {
647
+ "start_date": from,
648
+ "end_date": to,
649
+ "use_perc": usePercDev
650
+ },
651
+ success: function(sessionsDataSet) {
652
+ var dataMain = _.cloneDeep(sessionsDataSet);
653
+ draw_graph_sessions_details("#graph_sessions_device", dataMain, true, false, usePercDev);
654
+ },
655
+ error: function(result) {
656
+ error();
657
+ }
658
+ });
659
+ }
660
+ })();