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,908 @@
1
+ <% url_helper = QuickSearch::Engine.routes.url_helpers %>
2
+
3
+ (function() {
4
+ var Globals = {};
5
+
6
+ $(document).on("turbolinks:load", function() {
7
+ if ($("#graph_general_statistics").length) {
8
+ var from = $("#from").datepicker("getDate");
9
+ var to = new Date($("#to").datepicker("getDate").getTime() + 1000*60*60*24);
10
+ Globals.Days_In_Sample = parseInt((to-from)/(1000*60*60*24));
11
+ d3.select("#graphIconContainer").append("i")
12
+ .attr("class", "fa fa-spinner fa-spin fa-5x fa-fw big-icon")
13
+ .attr("id", "graphIcon");
14
+ d3.select("#tableIconContainer").append("i")
15
+ .attr("class", "fa fa-spinner fa-spin fa-5x fa-fw big-icon")
16
+ .attr("id", "tableIcon");
17
+ // Redraw graph if the date range is changed
18
+ document.getElementById("dateButton").addEventListener("click", function() {
19
+ var from = $("#from").datepicker("getDate");
20
+ var to = new Date($("#to").datepicker("getDate").getTime() + 1000*60*60*24);
21
+ Globals.Days_In_Sample = parseInt((to-from)/(1000*60*60*24));
22
+ document.getElementById("numDays").innerHTML = "" + Globals.Days_In_Sample;
23
+ $.ajax({
24
+ type: "GET",
25
+ contentType: "application/json; charset=utf-8",
26
+ url: '<%= url_helper.data_general_statistics_path %>',
27
+ dataType: "json",
28
+ data: {
29
+ "start_date": from,
30
+ "end_date": to
31
+ },
32
+ success: function(generalStatisticsDataSet) {
33
+ Globals.Data = _.cloneDeep(generalStatisticsDataSet)
34
+ var dataMain = _.cloneDeep(Globals.Data);
35
+ var dataMini = _.cloneDeep(Globals.Data);
36
+
37
+ draw_graph_general_statistics(dataMain, false, Globals.Index, true);
38
+
39
+ draw_graph_mini(dataMini[0], "#mini0");
40
+ draw_graph_mini(dataMini[1], "#mini1");
41
+ draw_graph_mini(dataMini[2], "#mini2");
42
+ },
43
+ error: function(result) {
44
+ error();
45
+ }
46
+ });
47
+ $.ajax({
48
+ type: "GET",
49
+ contentType: "application/json; charset=utf-8",
50
+ url: '<%= url_helper.data_general_table_path %>',
51
+ dataType: "json",
52
+ data: {
53
+ "start_date": from,
54
+ "end_date": to
55
+ },
56
+ success: function(tableDataSet) {
57
+ var dataTable = _.cloneDeep(tableDataSet);
58
+ draw_table(dataTable);
59
+ },
60
+ error: function(result) {
61
+ error();
62
+ }
63
+ });
64
+ });
65
+ $.ajax({
66
+ type: "GET",
67
+ contentType: "application/json; charset=utf-8",
68
+ url: '<%= url_helper.data_general_statistics_path %>',
69
+ dataType: "json",
70
+ success: function(generalStatisticsDataSet) {
71
+ d3.select("#graphIcon").transition().duration(250)
72
+ .style("opacity", .000001)
73
+ .remove();
74
+ Globals.Data = _.cloneDeep(generalStatisticsDataSet)
75
+ var dataMain = _.cloneDeep(Globals.Data);
76
+ var dataMini = _.cloneDeep(Globals.Data);
77
+
78
+ draw_graph_general_statistics(dataMain, false, 0, false);
79
+
80
+ draw_graph_mini(dataMini[0], "#mini0");
81
+ draw_graph_mini(dataMini[1], "#mini1");
82
+ draw_graph_mini(dataMini[2], "#mini2");
83
+
84
+ if ($("#graph_general_statistics").length) {
85
+ document.getElementById("mini0").addEventListener("click", function() {
86
+ load_new_data(0);
87
+ })
88
+ document.getElementById("mini1").addEventListener("click", function() {
89
+ load_new_data(1);
90
+ })
91
+ document.getElementById("mini2").addEventListener("click", function() {
92
+ load_new_data(2);
93
+ })
94
+ }
95
+ },
96
+ error: function(result) {
97
+ error();
98
+ }
99
+ });
100
+ $.ajax({
101
+ type: "GET",
102
+ contentType: "application/json; charset=utf-8",
103
+ url: '<%= url_helper.data_general_table_path %>',
104
+ dataType: "json",
105
+ success: function(tableDataSet) {
106
+ d3.select("#tableIcon").remove();
107
+ var dataTable = _.cloneDeep(tableDataSet);
108
+ draw_table(dataTable);
109
+ },
110
+ error: function(result) {
111
+ error();
112
+ }
113
+ });
114
+ }
115
+ });
116
+
117
+ function error() {
118
+ console.log("Error retrieving data");
119
+ }
120
+
121
+ function draw_graph_general_statistics(dataShared, transitioning, index, dateUpdated) {
122
+ if ($("#graph_general_statistics").length) {
123
+ // General Variables
124
+ var svg; // SVG to contain graph
125
+ var dataInt; // Internal reference to graph dataset
126
+ var titles; // Array of possible titles for graph
127
+ var title; // Title as determined by index passed in
128
+ // Dimension Variables
129
+ var margin; // Blank space around top graph (focus)
130
+ var margin2; // Blank space around bottom graph (context)
131
+ var width; // Drawable width of focus/context (not including margins)
132
+ var height; // Drawable height of focus (not including margins)
133
+ var height2; // Drawable height of context (not including margins)
134
+ // Date Variables
135
+ var parseDate; // Function to parse dates into proper format
136
+ var dateRange; // Range of dates in data set
137
+ var numDays; // Number of days in range
138
+ // Scale Variables
139
+ var x; // X-scale for focus graph
140
+ var x2; // X-scale for context graph
141
+ var y; // Y-scale for focus graph
142
+ var y2; // Y-scale for context graph
143
+ // Brush and Zoom Variables
144
+ var brush; // Object that allows domain selection by brush movement
145
+ var zoom; // Object that allows domain selection by zooming
146
+ // Axis Variables
147
+ var xAxis; // X-axis for focus graph
148
+ var xAxis2; // X-axis for context graph
149
+ var yAxis; // Y-axis for focus graph
150
+ // Area Variables
151
+ var area; // Area for focus graph
152
+ var area2; // Area for context graph
153
+ // Selection Variables
154
+ var gAllSelection; // Selection for overarching group
155
+ var gAll; // Group containing all elements
156
+ var focusSelection; // Selection for focus group
157
+ var focus; // Group containing all focus elements
158
+ var contextSelection; // Selection for context group
159
+ var context; // Group containing all context elements
160
+ var clipSelection; // Selection for clip path
161
+ var xAxisSelection; // Selection for xAxis
162
+ var yAxisSelection; // Selection for yAxis
163
+ var titleSelection; // Selection for title
164
+ var focusPathSelection; // Selection for focus path (area)
165
+ var xAxis2Selection; // Selection for xAxis2
166
+ var contextPathSelection; // Selection for context path (area)
167
+ var brushSelection; // Selection for brush
168
+ var zoomSelection; // Selection for zoom
169
+ // Update global index
170
+ Globals.Index = index;
171
+
172
+ // Initialize General Variables ///////////////////////////////////////////////////////////
173
+ svg = d3.select("#graph_general_statistics");
174
+
175
+ dataInt = dataShared[index];
176
+
177
+ titles = ["Clicks", "Sessions", "Searches"];
178
+
179
+ title = titles[index];
180
+
181
+ // Initialize Dimension Variables /////////////////////////////////////////////////////////
182
+ margin = {
183
+ top: 40,
184
+ right: 20,
185
+ bottom: 110,
186
+ left: 40
187
+ };
188
+ margin2 = {
189
+ top: 430,
190
+ right: 20,
191
+ bottom: 30,
192
+ left: 40
193
+ };
194
+ width = +svg.attr("width") - margin.left - margin.right;
195
+ height = +svg.attr("height") - margin.top - margin.bottom;
196
+ height2 = +svg.attr("height") - margin2.top - margin2.bottom;
197
+
198
+ // Initialize Date Variables and Parse Dates //////////////////////////////////////////////
199
+ parseDate = d3.timeParse("%Y-%m-%d");
200
+
201
+ dataInt.forEach(function(d) {
202
+ d.date = parseDate(d.date);
203
+ });
204
+
205
+ dateRange = d3.extent(dataInt, function(d) {
206
+ return d.date;
207
+ });
208
+
209
+ numDays = parseInt((dateRange[1]-dateRange[0])/(1000*60*60*24));
210
+
211
+ // Initialize Scale Variables /////////////////////////////////////////////////////////////
212
+ x = d3.scaleTime().range([0, width]);
213
+ x2 = d3.scaleTime().range([0, width]);
214
+ y = d3.scaleLinear().range([height, 0]);
215
+ y2 = d3.scaleLinear().range([height2, 0]);
216
+
217
+ // Set domains
218
+ x2.domain(d3.extent(dataInt, function(d) {
219
+ return d.date;
220
+ }));
221
+ if (_.isEqual(undefined, Globals.Domain)) {
222
+ x.domain(d3.extent(dataInt, function(d) {
223
+ return d.date;
224
+ }));
225
+ } else {
226
+ var lb, ub;
227
+ if (Globals.Domain[0] < x2.domain()[0]) {
228
+ lb = x2.domain()[0];
229
+ } else {
230
+ lb = Globals.Domain[0];
231
+ }
232
+ if (Globals.Domain[1] > x2.domain()[1]) {
233
+ ub = x2.domain()[1];
234
+ } else {
235
+ ub = Globals.Domain[1];
236
+ }
237
+ if(Globals.Domain[0]>x2.domain()[1] || Globals.Domain[1]<x2.domain()[0]) {
238
+ lb = x2.domain()[0];
239
+ ub = x2.domain()[1];
240
+ }
241
+ x.domain([lb, ub]);
242
+ }
243
+ y.domain([0, d3.max(dataInt, function(d) {
244
+ return d.count;
245
+ })]);
246
+ y2.domain(y.domain());
247
+
248
+ // Initialize Brush and Zoom Variables ////////////////////////////////////////////////////
249
+ brush = d3.brushX()
250
+ .extent([
251
+ [0, 0],
252
+ [width, height2]
253
+ ])
254
+ .on("brush end", brushed);
255
+
256
+ zoom = d3.zoom()
257
+ .scaleExtent([1, 1000])
258
+ .translateExtent([
259
+ [0, 0],
260
+ [width, height]
261
+ ])
262
+ .extent([
263
+ [0, 0],
264
+ [width, height]
265
+ ])
266
+ .on("zoom", zoomed);
267
+
268
+ // Initialize Axis Variables //////////////////////////////////////////////////////////////
269
+ xAxis = d3.axisBottom(x);
270
+ xAxis2 = d3.axisBottom(x2);
271
+ yAxis = d3.axisLeft(y);
272
+
273
+ // Initialize Area Variables //////////////////////////////////////////////////////////////
274
+ area = d3.area()
275
+ .curve(d3.curveMonotoneX)
276
+ .x(function(d) {
277
+ return x(d.date);
278
+ })
279
+ .y0(height)
280
+ .y1(function(d) {
281
+ return y(d.count);
282
+ });
283
+
284
+ area2 = d3.area()
285
+ .curve(d3.curveMonotoneX)
286
+ .x(function(d) {
287
+ return x2(d.date);
288
+ })
289
+ .y0(height2)
290
+ .y1(function(d) {
291
+ return y2(d.count);
292
+ });
293
+
294
+ // Make overarching group /////////////////////////////////////////////////////////////////
295
+ gAllSelection = svg.selectAll(".gAll").data([dataInt]);
296
+
297
+ gAllSelection.exit().transition().duration(500)
298
+ .style("opacity", .000001)
299
+ .remove();
300
+ gAllSelection.enter().append("g")
301
+ .attr("class", "gAll")
302
+ .attr("transform", "translate(0,0)");
303
+
304
+ gAll = svg.select(".gAll");
305
+
306
+ // Make focus
307
+ focusSelection = gAll.selectAll(".focus").data([dataInt]);
308
+
309
+ focusSelection.exit().transition().duration(500)
310
+ .style("opacity", .000001)
311
+ .remove();
312
+ focusSelection.enter().append("g")
313
+ .attr("class", "focus")
314
+ .attr("transform", "translate(" + margin.left + "," + margin.top + ")");
315
+
316
+ focus = gAll.select(".focus");
317
+
318
+ // Make context
319
+ contextSelection = gAll.selectAll(".context").data([dataInt]);
320
+
321
+ contextSelection.exit().transition().duration(500)
322
+ .style("opacity", .000001)
323
+ .remove();
324
+ contextSelection.enter().append("g")
325
+ .attr("class", "context")
326
+ .attr("transform", "translate(" + margin2.left + "," + margin2.top + ")");
327
+
328
+ context = gAll.select(".context");
329
+
330
+ // Make clip path
331
+ clipSelection = gAll.selectAll("defs").data([dataInt]);
332
+
333
+ clipSelection.exit().transition().duration(500)
334
+ .style("opacity", .000001)
335
+ .remove();
336
+ clipSelection.enter().append("defs").append("clipPath")
337
+ .attr("id", "clip")
338
+ .append("rect")
339
+ .attr("width", width)
340
+ .attr("height", height);
341
+
342
+ // Make focus x axis
343
+ xAxisSelection = focus.selectAll(".xAxis").data([dataInt]);
344
+
345
+ xAxisSelection.transition().duration(750)
346
+ .call(xAxis);
347
+ xAxisSelection.exit().transition().duration(500)
348
+ .style("opacity", .000001)
349
+ .remove();
350
+ xAxisSelection.enter().append("g")
351
+ .style("opacity", .000001)
352
+ .attr("class", "xAxis")
353
+ .attr("transform", "translate(0," + height + ")")
354
+ .call(xAxis)
355
+ .transition().duration(500)
356
+ .style("opacity", 1);
357
+
358
+ // Make focus y axis
359
+ yAxisSelection = focus.selectAll(".yAxis").data([dataInt]);
360
+
361
+ yAxisSelection.transition().duration(750)
362
+ .call(yAxis);
363
+ yAxisSelection.exit().transition().duration(500)
364
+ .style("opacity", .000001)
365
+ .remove();
366
+ yAxisSelection.enter().append("g")
367
+ .style("opacity", .000001)
368
+ .attr("class", "yAxis")
369
+ .attr("transform", "translate(0,0)")
370
+ .call(yAxis)
371
+ .transition().duration(500)
372
+ .style("opacity", 1);
373
+
374
+ // Make chart title
375
+ titleSelection = svg.selectAll(".chartTitle").data([dataInt]);
376
+
377
+ titleSelection.transition().duration(325)
378
+ .style("opacity", .00001)
379
+ .transition()
380
+ .text(title)
381
+ .transition().duration(325)
382
+ .style("opacity", 1);
383
+ titleSelection.exit().transition().duration(500)
384
+ .style("opacity", .000001)
385
+ .remove();
386
+ titleSelection.enter().append("text")
387
+ .style("opacity", .000001)
388
+ .text(title)
389
+ .attr("class", "chartTitle")
390
+ .attr("transform", "translate(" + (width / 2) + "," + 30 + ")")
391
+ .transition().duration(500)
392
+ .style("opacity", 1);
393
+
394
+ // Make focus path
395
+ focusPathSelection = focus.selectAll(".area").data([dataInt]);
396
+
397
+ focusPathSelection.datum(dataInt).transition().duration(750)
398
+ .attr("d", area);
399
+ focusPathSelection.exit().transition().duration(500)
400
+ .style("opacity", .000001)
401
+ .remove();
402
+ focusPathSelection.enter().append("path")
403
+ .style("opacity", .000001)
404
+ .datum(dataInt)
405
+ .attr("class", "area")
406
+ .transition().duration(500)
407
+ .style("opacity", 1);;
408
+
409
+ // Make context x axis
410
+ xAxis2Selection = context.selectAll(".xAxis").data([dataInt]);
411
+
412
+ xAxis2Selection.transition().duration(500)
413
+ .call(xAxis2);
414
+ xAxis2Selection.exit().transition().duration(500)
415
+ .style("opacity", .000001)
416
+ .remove();
417
+ xAxis2Selection.enter().append("g")
418
+ .style("opacity", .000001)
419
+ .attr("class", "xAxis")
420
+ .attr("transform", "translate(0," + height2 + ")")
421
+ .call(xAxis2)
422
+ .transition().duration(500)
423
+ .style("opacity", 1);
424
+
425
+ // Make context path
426
+ contextPathSelection = context.selectAll(".area").data([dataInt]);
427
+
428
+ contextPathSelection.datum(dataInt).transition().duration(750)
429
+ .attr("d", area2);
430
+ contextPathSelection.exit().transition().duration(500)
431
+ .style("opacity", .000001)
432
+ .remove();
433
+ contextPathSelection.enter().append("path")
434
+ .style("opacity", .000001)
435
+ .datum(dataInt)
436
+ .attr("class", "area")
437
+ .attr("d", area2)
438
+ .transition().duration(500)
439
+ .style("opacity", 1);
440
+
441
+ // Make brush container
442
+ brushSelection = context.selectAll(".brush").data([dataInt]);
443
+
444
+ brushSelection.exit().transition().duration(500)
445
+ .style("opacity", .000001)
446
+ .remove();
447
+ brushSelection.enter().append("g")
448
+ .attr("class", "brush")
449
+ .call(brush)
450
+ .call(brush.move, x.range())
451
+ .merge(brushSelection)
452
+ .style("opacity", 1)
453
+ .call(brush);
454
+
455
+ // Misc ///////////////////////////////////////////////////////////////////////////////////
456
+ // Have to prevent zoom or brush temporarily for transitions to execute
457
+ if (transitioning) {
458
+ setTimeout(function() {
459
+ transitioning = false;
460
+ }, 50);
461
+ } // If not on transition, fade in brush
462
+ else {
463
+ svg.selectAll(".brush")
464
+ .style("opacity", .000001)
465
+ .transition().duration(500)
466
+ .style("opacity", 1);
467
+ }
468
+
469
+ // Before updating domains, move brush to domain it was previously set to
470
+ if (dateUpdated) {
471
+ var lb, ub;
472
+ if (x2(Globals.Domain[0]) < 0) {
473
+ lb = 0;
474
+ } else {
475
+ lb = x2(Globals.Domain[0]);
476
+ }
477
+ if (x2(Globals.Domain[1]) > width) {
478
+ ub = width;
479
+ } else {
480
+ ub = x2(Globals.Domain[1]);
481
+ }
482
+ if(Globals.Domain[0]>x2.domain()[1] || Globals.Domain[1]<x2.domain()[0]) {
483
+ lb = 0;
484
+ ub = width;
485
+ }
486
+ context.select(".brush").call(brush.move, [lb, ub]);
487
+ context.select(".brush").transition().duration(500)
488
+ .style("opacity", 1);
489
+ }
490
+
491
+ // Make zoom container
492
+ zoomSelection = gAll.selectAll(".zoom").data([dataInt]);
493
+
494
+ zoomSelection.exit().transition().duration(500)
495
+ .style("opacity", .000001)
496
+ .remove();
497
+ zoomSelection.enter().append("rect")
498
+ .attr("class", "zoom")
499
+ .attr("width", width)
500
+ .attr("height", height)
501
+ .attr("transform", "translate(" + margin.left + "," + margin.top + ")")
502
+ .merge(zoomSelection)
503
+ .call(zoom);
504
+
505
+
506
+ function brushed() {
507
+ if (!transitioning) {
508
+ if (d3.event.sourceEvent && d3.event.sourceEvent.type === "zoom") return;
509
+ var s = d3.event.selection || x2.range();
510
+ x.domain(s.map(x2.invert, x2));
511
+ Globals.Domain = x.domain();
512
+ focus.select(".area").attr("d", area);
513
+ focus.select(".xAxis").call(xAxis);
514
+ svg.select(".zoom").call(zoom.transform, d3.zoomIdentity
515
+ .scale(width / (s[1] - s[0]))
516
+ .translate(-s[0], 0));
517
+ }
518
+ }
519
+
520
+ function zoomed() {
521
+ if (!transitioning) {
522
+ if (d3.event.sourceEvent && d3.event.sourceEvent.type === "brush") return;
523
+ var t = d3.event.transform;
524
+ x.domain(t.rescaleX(x2).domain());
525
+ Globals.Domain = x.domain();
526
+ focus.select(".area").attr("d", area);
527
+ focus.select(".xAxis").call(xAxis);
528
+ context.select(".brush").call(brush.move, x.range().map(t.invertX, t));
529
+ }
530
+ }
531
+ }
532
+ }
533
+
534
+ function load_new_data(index) {
535
+ var updateData = _.cloneDeep(Globals.Data);
536
+ draw_graph_general_statistics(updateData, true, index, false);
537
+ }
538
+
539
+ function draw_graph_mini(dataShared, id) {
540
+ if ($("#graph_general_statistics").length) {
541
+ // General Variables
542
+ var svg; // SVG to contain graph
543
+ var dataInt; // Internal reference to graph dataset
544
+ var title; // Title as determined by id passed in
545
+ // Dimension Variables
546
+ var margin; // Blank space around graph
547
+ var width; // Drawable width of graph (not including margins)
548
+ var height; // Drawable height of graph (not including margins)
549
+ // Date Variables
550
+ var parseDate; // Function to parse dates into proper format
551
+ // Scale Variables
552
+ var x; // X-scale for graph
553
+ var y; // Y-scale for graph
554
+ // Axis Variables
555
+ var xAxis; // X-axis for graph
556
+ var yAxis; // Y-axis for graph
557
+ // Area Variables
558
+ var area; // Area for graph
559
+ // Selection Variables
560
+ var gAllSelection; // Selection for overarching group
561
+ var gAll; // Group containing all elements
562
+ var xAxisSelection; // Selection for xAxis
563
+ var yAxisSelection; // Selection for yAxis
564
+ var pathSelection; // Selection for path
565
+ var textSelection; // Selection for title
566
+
567
+ // Initialize General Variables ///////////////////////////////////////////////////////////
568
+ svg = d3.select(id);
569
+
570
+ dataInt = dataShared;
571
+
572
+ title = "";
573
+ if (id == "#mini0") {
574
+ title = "Clicks";
575
+ } else if (id == "#mini1") {
576
+ title = "Sessions";
577
+ } else {
578
+ title = "Searches";
579
+ }
580
+
581
+ // Initialize Dimension Variables /////////////////////////////////////////////////////////
582
+ margin = {
583
+ top: 5,
584
+ right: 5,
585
+ bottom: 5,
586
+ left: 5
587
+ };
588
+ width = +svg.attr("width") - margin.left - margin.right;
589
+ height = +svg.attr("height") - margin.top - margin.bottom;
590
+
591
+ // Initialize Date Variables and Parse Dates //////////////////////////////////////////////
592
+ parseDate = d3.timeParse("%Y-%m-%d");
593
+
594
+ dataInt.forEach(function(d) {
595
+ d.date = parseDate(d.date);
596
+ });
597
+
598
+ // Initialize Scale Variables /////////////////////////////////////////////////////////////
599
+ x = d3.scaleTime().range([0, width]);
600
+ y = d3.scaleLinear().range([height, 0]);
601
+
602
+ // Set domains
603
+ x.domain(d3.extent(dataInt, function(d) {
604
+ return d.date;
605
+ }));
606
+ y.domain([0, d3.max(dataInt, function(d) {
607
+ return d.count;
608
+ })]);
609
+
610
+ // Initialize Axis Variables //////////////////////////////////////////////////////////////
611
+ xAxis = d3.axisBottom(x);
612
+ yAxis = d3.axisLeft(y);
613
+
614
+ // Remove ticks from axes
615
+ xAxis.tickSizeOuter(0);
616
+ yAxis.tickSizeOuter(0);
617
+
618
+ // Initialize Area Variables //////////////////////////////////////////////////////////////
619
+ area = d3.area()
620
+ .curve(d3.curveMonotoneX)
621
+ .x(function(d) {
622
+ return x(d.date);
623
+ })
624
+ .y0(height)
625
+ .y1(function(d) {
626
+ return y(d.count);
627
+ });
628
+
629
+ // Make overarching group /////////////////////////////////////////////////////////////////
630
+ gAllSelection = svg.selectAll(".gAll").data([dataInt]);
631
+
632
+ gAllSelection.exit().transition().duration(500)
633
+ .style("opacity", .000001)
634
+ .remove();
635
+ gAllSelection.enter().append("g")
636
+ .attr("class", "gAll")
637
+ .attr("transform", "translate(" + margin.left + "," + margin.top + ")");
638
+
639
+ gAll = svg.select(".gAll");
640
+
641
+ // Append clip path
642
+ svg.append("defs").append("clipPath")
643
+ .attr("id", "clipMini")
644
+ .append("rect")
645
+ .attr("width", width)
646
+ .attr("height", height);
647
+
648
+ // Make xAxis
649
+ xAxisSelection = gAll.selectAll(".xAxis").data([dataInt]);
650
+
651
+ xAxisSelection.exit().transition().duration(500)
652
+ .style("opacity", .000001)
653
+ .remove();
654
+ xAxisSelection.enter().append("g")
655
+ .style("opacity", .000001)
656
+ .attr("class", "xAxis")
657
+ .attr("transform", "translate(0," + height + ")")
658
+ .call(xAxis.ticks(0))
659
+ .transition().duration(500)
660
+ .style("opacity", 1);
661
+
662
+ // Make yAxis
663
+ yAxisSelection = gAll.selectAll(".yAxis").data([dataInt]);
664
+
665
+ yAxisSelection.exit().transition().duration(500)
666
+ .style("opacity", .000001)
667
+ .remove();
668
+ yAxisSelection.enter().append("g")
669
+ .style("opacity", .000001)
670
+ .attr("class", "yAxis")
671
+ .call(yAxis.ticks(0))
672
+ .transition().duration(500)
673
+ .style("opacity", 1);
674
+
675
+ // Make path
676
+ pathSelection = gAll.selectAll(".areaMini").data([dataInt]);
677
+
678
+ pathSelection.datum(dataInt).transition().duration(750)
679
+ .attr("d", area);
680
+ pathSelection.exit().transition().duration(500)
681
+ .style("opacity", .000001)
682
+ .remove();
683
+ pathSelection.enter().append("path")
684
+ .style("opacity", .000001)
685
+ .datum(dataInt)
686
+ .attr("class", "areaMini")
687
+ .attr("d", area)
688
+ .transition().duration(500)
689
+ .style("opacity", 1);
690
+
691
+ // Make title
692
+ textSelection = gAll.selectAll(".chartTitle").data([dataInt]);
693
+
694
+ textSelection.exit().transition().duration(500)
695
+ .style("opacity", .000001)
696
+ .remove();
697
+ textSelection.enter().append("text")
698
+ .style("opacity", .000001)
699
+ .text(title)
700
+ .attr("class", "chartTitle")
701
+ .attr("transform", "translate(" + (width / 2) + "," + (height - margin.bottom) + ")")
702
+ .transition().duration(500)
703
+ .style("opacity", 1);
704
+ }
705
+ }
706
+
707
+ function draw_table(dataShared) {
708
+ if ($("#graph_general_statistics").length) {
709
+ // General Variables
710
+ var svg; // SVG to contain graph
711
+ var dataInt; // Internal reference to graph dataset
712
+ // Dimension Variables
713
+ var margin; // Blank space around graph
714
+ var width; // Drawable width of graph (not including margins)
715
+ var height; // Drawable height of graph (not including margins)
716
+ var horizontalTextOffset; // Horizontal text padding
717
+ var verticalTextOffset; // Vertical text padding
718
+ // Scale Variables
719
+ var x; // X-scale for graph
720
+ var y; // Y-scale for graph
721
+ // Additional Data Variables
722
+ var lineData; // Data for line construction (two x,y pairs)
723
+ var headingData; // Data for heading construction (text, x, and y values)
724
+ var keys; // Keys used to traverse dataset
725
+ // Selection Variables
726
+ var groupEnter; // Entry selection for overarching group
727
+ var gAll; // Group containing all elements
728
+ var lineGroup; // Group containing all lines
729
+ var headingGroup; // Group containing all headings
730
+ var dataGroup; // Group containing all data elements
731
+
732
+ // Initialize General Variables ///////////////////////////////////////////////////////////
733
+ svg = d3.select("#graph_general_table");
734
+
735
+ dataInt = dataShared;
736
+
737
+ // Initialize Dimension Variables /////////////////////////////////////////////////////////
738
+ margin = {
739
+ top: 20,
740
+ right: 20,
741
+ bottom: 20,
742
+ left: 20
743
+ };
744
+ width = +svg.attr("width") - margin.left - margin.right;
745
+ height = +svg.attr("height") - margin.top - margin.bottom;
746
+ horizontalTextOffset = 10;
747
+ verticalTextOffset = 30;
748
+
749
+ // Initialize Scale Variables /////////////////////////////////////////////////////////////
750
+ x = d3.scaleLinear().rangeRound([0, width]);
751
+ y = d3.scaleLinear().rangeRound([0, height]);
752
+
753
+ // Set domains
754
+ x.domain([0, 100]);
755
+ y.domain([0, 100]);
756
+
757
+ // Initialize Additional Data Variables ///////////////////////////////////////////////////
758
+ lineData = [ {x1: x(0 ), y1: y(25 ), x2: x(100), y2: y(25 )}
759
+ ,{x1: x(20 ), y1: y(0 ), x2: x(20 ), y2: y(100)}
760
+ ,{x1: x(36 ), y1: y(0 ), x2: x(36 ), y2: y(100)}
761
+ ,{x1: x(52 ), y1: y(0 ), x2: x(52 ), y2: y(100)}
762
+ ,{x1: x(68 ), y1: y(0 ), x2: x(68 ), y2: y(100)}
763
+ ,{x1: x(84 ), y1: y(0 ), x2: x(84 ), y2: y(100)}];
764
+
765
+ headingData = [ {txt: "Clicks", x1: x(2 ), y1: y(37.5)}
766
+ ,{txt: "Searches", x1: x(2 ), y1: y(62.5)}
767
+ ,{txt: "Sessions", x1: x(2 ), y1: y(87.5)}
768
+ ,{txt: "Total", x1: x(22), y1: y(12.5)}
769
+ ,{txt: "Per Day", x1: x(38), y1: y(12.5)}
770
+ ,{txt: "Per Click", x1: x(54), y1: y(12.5)}
771
+ ,{txt: "Per Search", x1: x(70), y1: y(12.5)}
772
+ ,{txt: "Per Session", x1: x(86), y1: y(12.5)}];
773
+
774
+ keys = ["clicks", "searches", "sessions"];
775
+
776
+ // Make overarching group /////////////////////////////////////////////////////////////////
777
+ groupEnter = svg.selectAll("g").data([dataInt]).enter();
778
+
779
+ groupEnter.append("g")
780
+ .attr("class", "gAll");
781
+
782
+ gAll = svg.select(".gAll")
783
+ .attr("transform", "translate(" + margin.left + "," + margin.top + ")");
784
+
785
+
786
+
787
+ // Add Lines For Grid
788
+ gAll.selectAll(".lineGroup").data([dataInt]).enter().append("g")
789
+ .attr("class", "lineGroup");
790
+
791
+ lineGroup = gAll.select(".lineGroup")
792
+ .attr("transform", "translate(0,0)");
793
+
794
+ lineGroup.selectAll(".gridLine").data(lineData).enter().append("line")
795
+ .style("opacity", .000001)
796
+ .attr("class", "gridLine")
797
+ .attr("x1", function(d) { return d.x1; })
798
+ .attr("x2", function(d) { return d.x2; })
799
+ .attr("y1", function(d) { return d.y1; })
800
+ .attr("y2", function(d) { return d.y2; })
801
+ .transition().duration(500)
802
+ .style("opacity", 1);;
803
+
804
+ // Add row/column headings headings
805
+ gAll.selectAll(".headingGroup").data([dataInt]).enter().append("g")
806
+ .attr("class", "headingGroup");
807
+
808
+ headingGroup = gAll.select(".headingGroup")
809
+ .attr("transform", "translate(0,0)");
810
+
811
+ headingGroup.selectAll(".headText").data(headingData).enter().append("text")
812
+ .style("opacity", .000001)
813
+ .attr("class", "headText")
814
+ .text(function (d) { return d.txt; })
815
+ .attr("transform", function(d) { return "translate(" + d.x1 + "," + d.y1 + ")"; })
816
+ .transition().duration(500)
817
+ .style("opacity", 1);;
818
+
819
+ // Add data text
820
+ gAll.selectAll(".dataGroup").data([dataInt]).enter().append("g")
821
+ .attr("class", "dataGroup");
822
+
823
+ dataGroup = gAll.select(".dataGroup")
824
+ .attr("transform", "translate(0,0)");
825
+
826
+ // Totals column
827
+ dataGroup.selectAll(".totalText").data(dataInt)
828
+ .transition().duration(325)
829
+ .style("opacity", .000001)
830
+ .transition()
831
+ .text(function (d,i) { return d[keys[i]]; })
832
+ .transition().duration(325)
833
+ .style("opacity", 1);
834
+ dataGroup.selectAll(".totalText").data(dataInt).enter().append("text")
835
+ .style("opacity", .000001)
836
+ .attr("class", "totalText")
837
+ .text(function (d,i) { return d[keys[i]]; })
838
+ .attr("transform", function(d, i) { return "translate(" + x(22) + "," + y(37.5+25*i) + ")"; })
839
+ .transition().duration(500)
840
+ .style("opacity", 1);
841
+
842
+ // Per Day column
843
+ dataGroup.selectAll(".perDayText").data(dataInt)
844
+ .transition().duration(325)
845
+ .style("opacity", .000001)
846
+ .transition()
847
+ .text(function (d,i) { return Math.round(parseInt(d[keys[i]])/Globals.Days_In_Sample * 10000)/10000; })
848
+ .transition().duration(325)
849
+ .style("opacity", 1);
850
+ dataGroup.selectAll(".perDayText").data(dataInt).enter().append("text")
851
+ .style("opacity", .000001)
852
+ .attr("class", "perDayText")
853
+ .text(function (d,i) { return Math.round(parseInt(d[keys[i]])/Globals.Days_In_Sample * 10000)/10000; })
854
+ .attr("transform", function(d, i) { return "translate(" + x(38) + "," + y(37.5+25*i) + ")"; })
855
+ .transition().duration(500)
856
+ .style("opacity", 1);
857
+
858
+ // Per Click column
859
+ dataGroup.selectAll(".perClickText").data(dataInt)
860
+ .transition().duration(325)
861
+ .style("opacity", .000001)
862
+ .transition()
863
+ .text(function (d,i) { return Math.round(parseInt(d[keys[i]])/parseInt(dataInt[0]["clicks"]) * 10000)/10000; })
864
+ .transition().duration(325)
865
+ .style("opacity", 1);
866
+ dataGroup.selectAll(".perClickText").data(dataInt).enter().append("text")
867
+ .style("opacity", .000001)
868
+ .attr("class", "perClickText")
869
+ .text(function (d,i) { return Math.round(parseInt(d[keys[i]])/parseInt(dataInt[0]["clicks"]) * 10000)/10000; })
870
+ .attr("transform", function(d, i) { return "translate(" + x(54) + "," + y(37.5+25*i) + ")"; })
871
+ .transition().duration(500)
872
+ .style("opacity", 1);
873
+
874
+ // Per Search column
875
+ dataGroup.selectAll(".perSearchText").data(dataInt)
876
+ .transition().duration(325)
877
+ .style("opacity", .000001)
878
+ .transition()
879
+ .text(function (d,i) { return Math.round(parseInt(d[keys[i]])/parseInt(dataInt[1]["searches"]) * 10000)/10000; })
880
+ .transition().duration(325)
881
+ .style("opacity", 1);
882
+ dataGroup.selectAll(".perSearchText").data(dataInt).enter().append("text")
883
+ .style("opacity", .000001)
884
+ .attr("class", "perSearchText")
885
+ .text(function (d,i) { return Math.round(parseInt(d[keys[i]])/parseInt(dataInt[1]["searches"]) * 10000)/10000; })
886
+ .attr("transform", function(d, i) { return "translate(" + x(70) + "," + y(37.5+25*i) + ")"; })
887
+ .transition().duration(500)
888
+ .style("opacity", 1);
889
+
890
+ // Per Session column
891
+ dataGroup.selectAll(".perSessionText").data(dataInt)
892
+ .transition().duration(325)
893
+ .style("opacity", .000001)
894
+ .transition()
895
+ .text(function (d,i) { return Math.round(parseInt(d[keys[i]])/parseInt(dataInt[2]["sessions"]) * 10000)/10000; })
896
+ .transition().duration(325)
897
+ .style("opacity", 1);
898
+ dataGroup.selectAll(".perSessionText").data(dataInt).enter().append("text")
899
+ .style("opacity", .000001)
900
+ .attr("class", "perSessionText")
901
+ .text(function (d,i) { return Math.round(parseInt(d[keys[i]])/parseInt(dataInt[2]["sessions"]) * 10000)/10000; })
902
+ .attr("transform", function(d, i) { return "translate(" + x(86) + "," + y(37.5+25*i) + ")"; })
903
+ .transition().duration(500)
904
+ .style("opacity", 1);
905
+ }
906
+ }
907
+
908
+ })();