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,633 @@
1
+ <% url_helper = QuickSearch::Engine.routes.url_helpers %>
2
+
3
+ (function() {
4
+ var Globals = {};
5
+
6
+ $(document).on("turbolinks:load", function() {
7
+ if ($("#graph_top_searches").length) {
8
+ d3.select("#tsIconContainer").append("i")
9
+ .attr("class", "fa fa-spinner fa-spin fa-5x fa-fw big-icon")
10
+ .attr("id", "tsIcon");
11
+ // Redraw graph if the date range is changed
12
+ document.getElementById("dateButton").addEventListener("click", function() {
13
+ var from = $("#from").datepicker("getDate");
14
+ var to = new Date($("#to").datepicker("getDate").getTime() + 1000*60*60*24);
15
+ document.getElementById("numDays").innerHTML = "" + parseInt((to-from)/(1000*60*60*24));
16
+ $.ajax({
17
+ type: "GET",
18
+ contentType: "application/json; charset=utf-8",
19
+ url: '<%= url_helper.data_top_searches_path %>',
20
+ dataType: "json",
21
+ data: {
22
+ "start_date": from,
23
+ "end_date": to,
24
+ "num_results": document.getElementById("num").value
25
+ },
26
+ success: function(searchDataSet) {
27
+ var searchData = _.cloneDeep(searchDataSet);
28
+ Globals.OriginalData = searchData;
29
+ Globals.Data = searchData;
30
+ sort_search_data(Globals.Sort);
31
+ },
32
+ error: function(result) {
33
+ error();
34
+ }
35
+ });
36
+ });
37
+ $.ajax({
38
+ type: "GET",
39
+ contentType: "application/json; charset=utf-8",
40
+ url: '<%= url_helper.data_top_searches_path %>',
41
+ dataType: "json",
42
+ success: function(searchDataSet) {
43
+ d3.select("#tsIcon").transition().duration(250)
44
+ .style("opacity", .000001)
45
+ .remove();
46
+ var searchData = _.cloneDeep(searchDataSet);
47
+ Globals.OriginalData = searchData;
48
+ Globals.Data = searchData;
49
+ Globals.Sort = 0;
50
+ Globals.Height = 450;
51
+ draw_graph_top_searches();
52
+ },
53
+ error: function(result) {
54
+ error();
55
+ }
56
+ });
57
+ }
58
+ });
59
+
60
+ function error() {
61
+ console.log("Error retrieving data");
62
+ }
63
+
64
+ function draw_graph_top_searches() {
65
+ if ($("#graph_top_searches").length) {
66
+ // General Variables
67
+ var svg; // SVG to contain graph
68
+ var dataInt; // Internal reference to graph dataset
69
+ var sortStates; // Array indicating the currently selected sort state
70
+ var key; // Key function to maintain object constancy
71
+ var triangle; // Triangle object for sort buttons
72
+ // Dimension Variables
73
+ var margin; // Blank space around edge of SVG left as margin
74
+ var rowHeight; // Height of each row of data
75
+ var width; // Drawable width of SVG (not including margins)
76
+ var height; // Drawable height of SVG (not including margins)
77
+ var oldHeight; // Previous height of SVG
78
+ var textPadding; // Padding around text elements
79
+ var barHeight; // Height of data bars
80
+ var rankWidth; // Width of rank column
81
+ var categoryWidth; // Width of category column
82
+ var countWidth; // Width of count column
83
+ var percentWidth; // Width of percent column
84
+ var cumPercentWidth;// Width of cumulative percent column
85
+ var percBarCenter; // Center x for count/percent data bar
86
+ var cumPercBarStart;// Beginning x for cumulative percent data bar
87
+ var triangleSpacing;// Space around triangular sort buttons
88
+ // Scale Variables
89
+ var percScale; // Scale for count/percent data bar
90
+ var cumPercScale; // Scale for cumulative percent data bar
91
+ // Selection Variables
92
+ var groupEnter; // Entry selection for gAll
93
+ var gAll; // Group containing all elements
94
+ var headGroupEnter; // Entry selection for headRow
95
+ var headRow; // Group containing all head elements
96
+ var headEnter; // Entry selection for all head elements
97
+ var triangles; // Sort triangles
98
+ var dataGroupEnter; // Entry selection for dataRows
99
+ var dataRows; // Group containing all data elements
100
+ var dataRects; // Background rectangles
101
+ var dataRanks; // Rank text
102
+ var dataLabels; // Label text
103
+ var dataClicks; // Click text
104
+ var dataPercents; // Percent text
105
+ var dataCumPercents;// Cumulative percent text
106
+ var percBar; // Count/percent data bar
107
+ var cumPercBar; // Cumulative percent data bar
108
+ var lightBorder; // Light border (surrounds all elements)
109
+ var darkBorder; // Dark border (surrounds data elements)
110
+
111
+ // Initialize General Variables ///////////////////////////////////////////////////////////
112
+ svg = d3.select("#graph_top_searches");
113
+
114
+ dataInt = Globals.Data;
115
+
116
+ sortStates = [0, 0, 0, 0];
117
+ sortStates[Globals.Sort] = 1;
118
+
119
+ key = function(d) {
120
+ return d.key;
121
+ };
122
+
123
+ triangle = d3.symbol().type(d3.symbolTriangle).size(20);
124
+
125
+ // Initialize Dimension Variables /////////////////////////////////////////////////////////
126
+ margin = {
127
+ top: 20,
128
+ right: 20,
129
+ bottom: 20,
130
+ left: 20
131
+ };
132
+ rowHeight = 35;
133
+ width = +svg.attr("width") - margin.left - margin.right;
134
+ height = (dataInt.length + 1) * rowHeight;
135
+ oldHeight = Globals.Height;
136
+ textPadding = 5;
137
+ barHeight = 25;
138
+ rankWidth = 2 * width / 16;
139
+ categoryWidth = 4 * width / 16;
140
+ countWidth = 2 * width / 16;
141
+ percentWidth = 3 * width / 16;
142
+ cumPercentWidth = 5 * width / 16;
143
+ percBarCenter = rankWidth + categoryWidth + countWidth + 13 * d3.max(dataInt, function(d) {
144
+ return d.count.toString().length;
145
+ });
146
+ cumPercBarStart = rankWidth + categoryWidth + countWidth + percentWidth + 3 * textPadding + 13 * d3.max(dataInt, function(d) {
147
+ return d.cum_percentage.toString().length;
148
+ });
149
+ triangleSpacing = 15;
150
+
151
+ // Initialize Scale Variables /////////////////////////////////////////////////////////////
152
+ percScale = d3.scaleLinear().rangeRound([0, countWidth + percentWidth - 100]);
153
+ percScale.domain([0, d3.max(dataInt, function(d) {
154
+ return d.cum_percentage
155
+ })]);
156
+
157
+ cumPercScale = d3.scaleLinear().rangeRound([0, countWidth + percentWidth - 100]);
158
+ cumPercScale.domain([0, d3.max(dataInt, function(d) {
159
+ return d.cum_percentage
160
+ })]);
161
+
162
+ // Misc ///////////////////////////////////////////////////////////////////////////////////
163
+ // Transition the svg height depending on previous height
164
+ svg.transition().delay(function(d) {
165
+ if (oldHeight > height) {
166
+ return 500;
167
+ } else {
168
+ return 0;
169
+ }
170
+ })
171
+ .duration(750)
172
+ .attr("height", height + margin.top + margin.bottom)
173
+ .on("end", function(d) {
174
+ Globals.Height = height;
175
+ });
176
+
177
+ // Make overarching group /////////////////////////////////////////////////////////////////
178
+ groupEnter = svg.selectAll("g").data([dataInt]).enter();
179
+
180
+ groupEnter.append("g")
181
+ .attr("class", "gAll");
182
+
183
+ gAll = svg.select(".gAll")
184
+ .attr("transform", "translate(" + margin.left + "," + margin.top + ")");
185
+
186
+ // Make header row ////////////////////////////////////////////////////////////////////////
187
+ headGroupEnter = gAll.selectAll(".headRow").data([dataInt]).enter();
188
+
189
+ headGroupEnter.append("g")
190
+ .attr("class", "headRow");
191
+
192
+ headRow = gAll.select(".headRow")
193
+ .attr("transform", "translate(0,0)");
194
+
195
+ headEnter = headRow.selectAll("rect").data([dataInt]).enter();
196
+
197
+ // Make background rect
198
+ headEnter.append("rect")
199
+ .attr("class", "darkBar")
200
+ .attr("x", 0)
201
+ .attr("y", 0)
202
+ .attr("width", width)
203
+ .attr("height", rowHeight);
204
+
205
+ // Make rank text & sort rect
206
+ headEnter.append("text")
207
+ .text("Rank")
208
+ .attr("class", "headText")
209
+ .attr("transform", "translate(" + textPadding + "," + (rowHeight / 2 + textPadding) + ")");
210
+
211
+ headEnter.append("rect")
212
+ .attr("class", "sortRect")
213
+ .attr("x", (rankWidth - 2 * triangleSpacing))
214
+ .attr("y", 0)
215
+ .attr("width", 2 * triangleSpacing)
216
+ .attr("height", rowHeight)
217
+ .on("click", function(d) {
218
+ if (Globals.Sort == 0) {
219
+ sort_search_data(1);
220
+ } else {
221
+ sort_search_data(0);
222
+ }
223
+ });
224
+
225
+ // Make category text & sort rect
226
+ headEnter.append("text")
227
+ .text("Query")
228
+ .attr("class", "headText")
229
+ .attr("transform", "translate(" + (rankWidth + textPadding) + "," + (rowHeight / 2 + textPadding) + ")");
230
+
231
+ headEnter.append("rect")
232
+ .attr("class", "sortRect")
233
+ .attr("x", (rankWidth + categoryWidth - 2 * triangleSpacing))
234
+ .attr("y", 0)
235
+ .attr("width", 2 * triangleSpacing)
236
+ .attr("height", rowHeight)
237
+ .on("click", function(d) {
238
+ if (Globals.Sort == 2) {
239
+ sort_search_data(3);
240
+ } else {
241
+ sort_search_data(2);
242
+ }
243
+ });
244
+
245
+ // Make count, percent, & cumulative percent text
246
+ headEnter.append("text")
247
+ .text("Count")
248
+ .attr("class", "headText")
249
+ .attr("transform", "translate(" + (rankWidth + categoryWidth + textPadding) + "," + (rowHeight / 2 + textPadding) + ")");
250
+
251
+ headEnter.append("text")
252
+ .text("Percent")
253
+ .attr("class", "percentText")
254
+ .attr("transform", "translate(" + (rankWidth + categoryWidth + countWidth + percentWidth - textPadding) + "," + (rowHeight / 2 + textPadding) + ")");
255
+
256
+ headEnter.append("text")
257
+ .text("Cumulative Percent")
258
+ .attr("class", "headText")
259
+ .attr("transform", "translate(" + (rankWidth + categoryWidth + countWidth + percentWidth + 3 * textPadding) + "," + (rowHeight / 2 + textPadding) + ")");
260
+
261
+ // Make sort triangles
262
+ triangles = headRow.selectAll("path").data(sortStates);
263
+
264
+ triangles.enter().append("path")
265
+ .attr("d", triangle)
266
+ .attr("pointer-events", "none")
267
+ .attr("transform", function(d, i) {
268
+ if (i == 0) {
269
+ return "translate(" + (rankWidth - triangleSpacing) + "," + (rowHeight / 2 - textPadding) + ")";
270
+ } else if (i == 1) {
271
+ return "translate(" + (rankWidth - triangleSpacing) + "," + (rowHeight / 2 + textPadding) + ") rotate(180)";
272
+ } else if (i == 2) {
273
+ return "translate(" + (rankWidth + categoryWidth - triangleSpacing) + "," + (rowHeight / 2 - textPadding) + ")";
274
+ } else if (i == 3) {
275
+ return "translate(" + (rankWidth + categoryWidth - triangleSpacing) + "," + (rowHeight / 2 + textPadding) + ") rotate(180)";
276
+ }
277
+ })
278
+ .merge(triangles)
279
+ .transition().duration(500)
280
+ .attr("fill", function(d, i) {
281
+ if (d) {
282
+ return "steelblue";
283
+ } else {
284
+ return "lightsteelblue";
285
+ }
286
+ });
287
+
288
+ // Make data rows /////////////////////////////////////////////////////////////////////////
289
+ dataGroupEnter = gAll.selectAll(".dataRows").data([dataInt]).enter();
290
+
291
+ dataGroupEnter.append("g")
292
+ .attr("class", "dataRows");
293
+
294
+ dataRows = gAll.select(".dataRows")
295
+ .attr("transform", "translate(0,0)");
296
+
297
+ // Make background rects
298
+ dataRects = dataRows.selectAll(".darkBar, .lightBar").data(dataInt, key);
299
+
300
+ dataRects.transition().delay(function(d) {
301
+ if (oldHeight > height) {
302
+ return 500;
303
+ } else {
304
+ return 0;
305
+ }
306
+ })
307
+ .duration(750)
308
+ .attr("y", function(d, i) {
309
+ return (i + 1) * rowHeight;
310
+ });
311
+ dataRects.exit().remove();
312
+ dataRects.enter().append("rect")
313
+ .style("opacity", .000001)
314
+ .attr("class", function(d, i) { return "darkBar"; })
315
+ .attr("x", 0)
316
+ .attr("y", function(d, i) {
317
+ return (i + 1) * rowHeight;
318
+ })
319
+ .attr("width", width)
320
+ .attr("height", rowHeight)
321
+ .transition().delay(750).duration(500)
322
+ .style("opacity", 1);
323
+
324
+ // Make rank text
325
+ dataRanks = dataRows.selectAll(".dataRank").data(dataInt, key);
326
+
327
+ dataRanks.transition().delay(function(d) {
328
+ if (oldHeight > height) {
329
+ return 500;
330
+ } else {
331
+ return 0;
332
+ }
333
+ })
334
+ .duration(750)
335
+ .attr("transform", function(d, i) {
336
+ return "translate(" + textPadding + "," + Math.floor((i + 1) * rowHeight + rowHeight / 2 + textPadding) + ")";
337
+ })
338
+ .text(function(d) {
339
+ return d.rank;
340
+ });
341
+ dataRanks.exit().transition().duration(500)
342
+ .style("opacity", .000001)
343
+ .remove();
344
+ dataRanks.enter().append("text")
345
+ .style("opacity", .000001)
346
+ .text(function(d) {
347
+ return d.rank;
348
+ })
349
+ .attr("class", "dataRank")
350
+ .attr("transform", function(d, i) {
351
+ return "translate(" + textPadding + "," + Math.floor((i + 1) * rowHeight + rowHeight / 2 + textPadding) + ")";
352
+ })
353
+ .transition().delay(750).duration(500)
354
+ .style("opacity", 1);
355
+
356
+ // Make label text
357
+ dataLabels = dataRows.selectAll(".dataLabel").data(dataInt, key);
358
+
359
+ dataLabels.transition().delay(function(d) {
360
+ if (oldHeight > height) {
361
+ return 500;
362
+ } else {
363
+ return 0;
364
+ }
365
+ })
366
+ .duration(750)
367
+ .attr("transform", function(d, i) {
368
+ return "translate(" + (rankWidth + textPadding) + "," + Math.floor((i + 1) * rowHeight + rowHeight / 2 + textPadding) + ")";
369
+ })
370
+ .text(function(d) {
371
+ if (d.label.length > 25) {
372
+ return d.label.slice(0, 20) + "...";
373
+ } else {
374
+ return d.label;
375
+ }
376
+ });
377
+ dataLabels.exit().transition().duration(500)
378
+ .style("opacity", .000001)
379
+ .remove();
380
+ dataLabels.enter().append("text")
381
+ .style("opacity", .000001)
382
+ .text(function(d) {
383
+ if (d.label.length > 25) {
384
+ return d.label.slice(0, 20) + "...";
385
+ } else {
386
+ return d.label;
387
+ }
388
+ })
389
+ .attr("class", "dataLabel")
390
+ .attr("transform", function(d, i) {
391
+ return "translate(" + (rankWidth + textPadding) + "," + Math.floor((i + 1) * rowHeight + rowHeight / 2 + textPadding) + ")";
392
+ })
393
+ .transition().delay(750).duration(500)
394
+ .style("opacity", 1);
395
+
396
+ // Make click text
397
+ var dataClicks = dataRows.selectAll(".dataClick").data(dataInt, key);
398
+
399
+ dataClicks.transition().delay(function(d) {
400
+ if (oldHeight > height) {
401
+ return 500;
402
+ } else {
403
+ return 0;
404
+ }
405
+ })
406
+ .duration(750)
407
+ .attr("transform", function(d, i) {
408
+ return "translate(" + (rankWidth + categoryWidth + textPadding) + "," + Math.floor((i + 1) * rowHeight + rowHeight / 2 + textPadding) + ")";
409
+ })
410
+ .text(function(d) {
411
+ return d.count;
412
+ });
413
+ dataClicks.exit().transition().duration(500)
414
+ .style("opacity", .000001)
415
+ .remove();
416
+ dataClicks.enter().append("text")
417
+ .style("opacity", .000001)
418
+ .text(function(d) {
419
+ return d.count;
420
+ })
421
+ .attr("class", "dataClick")
422
+ .attr("transform", function(d, i) {
423
+ return "translate(" + (rankWidth + categoryWidth + textPadding) + "," + Math.floor((i + 1) * rowHeight + rowHeight / 2 + textPadding) + ")";
424
+ })
425
+ .transition().delay(750).duration(500)
426
+ .style("opacity", 1);
427
+
428
+ // Make percent text
429
+ dataPercents = dataRows.selectAll(".dataPercent").data(dataInt, key);
430
+
431
+ dataPercents.transition().delay(function(d) {
432
+ if (oldHeight > height) {
433
+ return 500;
434
+ } else {
435
+ return 0;
436
+ }
437
+ })
438
+ .duration(750)
439
+ .attr("transform", function(d, i) {
440
+ return "translate(" + (rankWidth + categoryWidth + countWidth + percentWidth - textPadding) + "," + Math.floor((i + 1) * rowHeight + rowHeight / 2 + textPadding) + ")";
441
+ })
442
+ .text(function(d) {
443
+ return d.percentage + "%";
444
+ });
445
+ dataPercents.exit().transition().duration(500)
446
+ .style("opacity", .000001)
447
+ .remove();
448
+ dataPercents.enter().append("text")
449
+ .style("opacity", .000001)
450
+ .text(function(d) {
451
+ return d.percentage + "%";
452
+ })
453
+ .attr("class", "dataPercent")
454
+ .attr("transform", function(d, i) {
455
+ return "translate(" + (rankWidth + categoryWidth + countWidth + percentWidth - textPadding) + "," + Math.floor((i + 1) * rowHeight + rowHeight / 2 + textPadding) + ")";
456
+ })
457
+ .transition().delay(750).duration(500)
458
+ .style("opacity", 1);
459
+
460
+ // Make click text
461
+ dataCumPercents = dataRows.selectAll(".dataCumPercent").data(dataInt, key);
462
+
463
+ dataCumPercents.transition().delay(function(d) {
464
+ if (oldHeight > height) {
465
+ return 500;
466
+ } else {
467
+ return 0;
468
+ }
469
+ })
470
+ .duration(750)
471
+ .attr("transform", function(d, i) {
472
+ return "translate(" + (rankWidth + categoryWidth + countWidth + percentWidth + 3 * textPadding) + "," + Math.floor((i + 1) * rowHeight + rowHeight / 2 + textPadding) + ")";
473
+ })
474
+ .text(function(d) {
475
+ return d.cum_percentage + "%";
476
+ });
477
+ dataCumPercents.exit().transition().duration(500)
478
+ .style("opacity", .000001)
479
+ .remove();
480
+ dataCumPercents.enter().append("text")
481
+ .style("opacity", .000001)
482
+ .text(function(d) {
483
+ return d.cum_percentage + "%";
484
+ })
485
+ .attr("class", "dataCumPercent")
486
+ .attr("transform", function(d, i) {
487
+ return "translate(" + (rankWidth + categoryWidth + countWidth + percentWidth + 3 * textPadding) + "," + Math.floor((i + 1) * rowHeight + rowHeight / 2 + textPadding) + ")";
488
+ })
489
+ .transition().delay(750).duration(500)
490
+ .style("opacity", 1);
491
+
492
+ // Make perc bars
493
+ percBar = dataRows.selectAll(".percBar").data(dataInt, key);
494
+
495
+ percBar.transition().delay(function(d) {
496
+ if (oldHeight > height) {
497
+ return 500;
498
+ } else {
499
+ return 0;
500
+ }
501
+ })
502
+ .duration(750)
503
+ .attr("y", function(d, i) {
504
+ return (i + 1) * rowHeight + (rowHeight - barHeight) / 2;
505
+ })
506
+ .attr("width", function(d) {
507
+ return percScale(d.percentage);
508
+ })
509
+ .attr("x", function(d) {
510
+ return percBarCenter - percScale(d.percentage) / 2;
511
+ });
512
+ percBar.exit().transition().duration(500)
513
+ .attr("x", percBarCenter)
514
+ .attr("width", 0)
515
+ .remove();
516
+ percBar.enter().append("rect")
517
+ .attr("class", "percBar")
518
+ .attr("x", function(d) {
519
+ return percBarCenter;
520
+ })
521
+ .attr("y", function(d, i) {
522
+ return (i + 1) * rowHeight + (rowHeight - barHeight) / 2;
523
+ })
524
+ .attr("width", function(d) {
525
+ return 0;
526
+ })
527
+ .attr("height", barHeight)
528
+ .transition().delay(750).duration(500)
529
+ .attr("x", function(d) {
530
+ return percBarCenter - percScale(d.percentage) / 2;
531
+ })
532
+ .attr("width", function(d) {
533
+ return percScale(d.percentage);
534
+ });
535
+
536
+ // Make cumulative perc bars
537
+ cumPercBar = dataRows.selectAll(".cumPercBar").data(dataInt, key);
538
+
539
+ cumPercBar.transition().delay(function(d) {
540
+ if (oldHeight > height) {
541
+ return 500;
542
+ } else {
543
+ return 0;
544
+ }
545
+ })
546
+ .duration(750)
547
+ .attr("y", function(d, i) {
548
+ return (i + 1) * rowHeight + (rowHeight - barHeight) / 2;
549
+ })
550
+ .attr("width", function(d) {
551
+ return cumPercScale(d.cum_percentage);
552
+ })
553
+ .attr("x", function(d) {
554
+ return cumPercBarStart;
555
+ });
556
+ cumPercBar.exit().transition().duration(500)
557
+ .attr("width", 0)
558
+ .remove();
559
+ cumPercBar.enter().append("rect")
560
+ .attr("class", "cumPercBar")
561
+ .attr("x", function(d) {
562
+ return cumPercBarStart;
563
+ })
564
+ .attr("y", function(d, i) {
565
+ return (i + 1) * rowHeight + (rowHeight - barHeight) / 2;
566
+ })
567
+ .attr("width", function(d) {
568
+ return 0;
569
+ })
570
+ .attr("height", barHeight)
571
+ .transition().delay(750).duration(500)
572
+ .attr("width", function(d) {
573
+ return cumPercScale(d.cum_percentage);
574
+ });
575
+
576
+ // Add borders ////////////////////////////////////////////////////////////////////////////
577
+ lightBorder = gAll.selectAll(".lightBorder").data([dataInt]);
578
+
579
+ lightBorder.transition().delay(function(d) {
580
+ if (oldHeight > height) {
581
+ return 500;
582
+ } else {
583
+ return 0;
584
+ }
585
+ })
586
+ .duration(750)
587
+ .attr("height", height);
588
+ lightBorder.exit().remove();
589
+ lightBorder.enter().append("rect")
590
+ .attr("class", "lightBorder")
591
+ .attr("x", 0)
592
+ .attr("y", 0)
593
+ .attr("width", width)
594
+ .attr("height", height);;
595
+
596
+ darkBorder = gAll.selectAll(".darkBorder").data([dataInt]);
597
+
598
+ darkBorder.transition().delay(function(d) {
599
+ if (oldHeight > height) {
600
+ return 500;
601
+ } else {
602
+ return 0;
603
+ }
604
+ })
605
+ .duration(750)
606
+ .attr("height", height - rowHeight);
607
+ darkBorder.exit().remove();
608
+ darkBorder.enter().append("rect")
609
+ .attr("class", "darkBorder")
610
+ .attr("x", 0)
611
+ .attr("y", rowHeight)
612
+ .attr("width", width)
613
+ .attr("height", height - rowHeight);
614
+ }
615
+ }
616
+
617
+ function sort_search_data(sort) {
618
+ Globals.Data = Globals.OriginalData.sort(function(a, b) {
619
+ switch(sort) {
620
+ case 0: return d3.ascending(a.rank,b.rank);
621
+ case 1: return d3.ascending(b.rank,a.rank);
622
+
623
+ case 2: return d3.ascending(a.label,b.label);
624
+ case 3: return d3.ascending(b.label,a.label);
625
+ }
626
+ });
627
+
628
+ // Update global sort
629
+ Globals.Sort = sort;
630
+ draw_graph_top_searches();
631
+ }
632
+
633
+ })();