summaryrefslogtreecommitdiff
path: root/public/javascripts/admin_search.js
diff options
context:
space:
mode:
Diffstat (limited to 'public/javascripts/admin_search.js')
-rw-r--r--public/javascripts/admin_search.js393
1 files changed, 208 insertions, 185 deletions
diff --git a/public/javascripts/admin_search.js b/public/javascripts/admin_search.js
index 9bf878b..7604bb7 100644
--- a/public/javascripts/admin_search.js
+++ b/public/javascripts/admin_search.js
@@ -1,5 +1,4 @@
1admin_search = { 1admin_search = {
2
3 initialize : function() { 2 initialize : function() {
4 $(document).bind("keydown", 'Alt+f', function(){ 3 $(document).bind("keydown", 'Alt+f', function(){
5 admin_search.display_toggle(); 4 admin_search.display_toggle();
@@ -20,25 +19,12 @@ admin_search = {
20 } 19 }
21 }); 20 });
22 21
23 $("#search_term").bind("input", function() { 22 initSearchPicker({
24 if (!$('#search_widget').is(':visible')) return; 23 inputSelector: "#search_term",
25 if ($(this).val()) { 24 resultsSelector: "#menu_search_results",
26 $.ajax({ 25 url: ADMIN_SEARCH_URL,
27 type: "GET", 26 isActive: function() { return $('#search_widget').is(':visible'); },
28 url: ADMIN_SEARCH_URL, 27 resultsHeaderHtml: "<p class='search_more'>Press Enter to see all results ⏎</p>"
29 data: "search_term=" + $(this).val(),
30 dataType: "json",
31 success: function(results) {
32 admin_search.show_results(results);
33 },
34 error: function(xhr, status, error) {
35 console.log("Ajax error:", status, error, xhr.status, xhr.responseText);
36 }
37 });
38 } else {
39 $('#search_results').slideUp();
40 $('#search_results').empty();
41 }
42 }); 28 });
43 }, 29 },
44 30
@@ -49,75 +35,155 @@ admin_search = {
49 $('#search_widget').fadeIn(); 35 $('#search_widget').fadeIn();
50 $('#search_term').focus(); 36 $('#search_term').focus();
51 } 37 }
52 },
53
54 show_results : function(results) {
55 $('#search_results').empty();
56 if (results.length) {
57 $('#search_results').append(
58 "<p class='search_more'>Press Enter to see all results ⏎</p>"
59 );
60 }
61 for (result in results) {
62 $('#search_results').append(
63 "<p><a href='" + results[result].node_path + "'>" +
64 results[result].title +
65 "<span class='result_path'>" + results[result].unique_name + "</span>" +
66 "</a></p>"
67 );
68 }
69 $('#search_results').slideDown();
70 } 38 }
71}; 39};
72 40
73menu_items = { 41function initSearchPicker(options) {
42 var inputSelector = options.inputSelector;
43 var resultsSelector = options.resultsSelector;
44 var url = options.url || ADMIN_MENU_SEARCH_URL;
45 var onSelect = options.onSelect;
46 var isActive = options.isActive;
47 var resultsHeaderHtml = options.resultsHeaderHtml;
48 var renderResults = options.renderResults;
49 var loadOnFocus = options.loadOnFocus; // optional, fires an initial search on focus with no term typed yet
50 var requestId = 0;
51 var timeout;
52 var results = $(resultsSelector);
74 53
75 initialize_search : function() { 54 function runSearch(term) {
76 $("#menu_search_term").bind("keyup", function() { 55 var thisRequest = ++requestId;
77 if ($(this).attr("value")) { 56 $.ajax({
78 $.ajax({ 57 type: "GET",
79 type: "GET", 58 url: url,
80 url: ADMIN_MENU_SEARCH_URL, 59 data: "search_term=" + term,
81 data: "search_term=" + $(this).attr("value"), 60 dataType: "json",
82 dataType: "json", 61 success: function(data) {
83 success : function(results) { 62 if (thisRequest !== requestId) return;
84 menu_items.show_results(results); 63 results.empty();
64
65 var found;
66 if (renderResults) {
67 found = renderResults(data, results, resultsHeaderHtml);
68 } else {
69 if (data.length && resultsHeaderHtml) {
70 results.append(resultsHeaderHtml);
85 } 71 }
86 }); 72 found = false;
87 } 73 for (var i = 0; i < data.length; i++) {
88 else { 74 (function(node) {
89 $('#search_results').slideUp(); 75 var link;
90 $('#search_results').empty(); 76 if (onSelect) {
77 link = $(
78 "<p><a href='#'>" + node.title +
79 "<span class='result_path'>" + node.unique_name + "</span></a></p>"
80 );
81 link.find("a").bind("click", function() {
82 onSelect(node);
83 results.slideUp();
84 results.empty();
85 return false;
86 });
87 } else {
88 link = $(
89 "<p><a href='" + node.node_path + "'>" + node.title +
90 "<span class='result_path'>" + node.unique_name + "</span></a></p>"
91 );
92 }
93 results.append(link);
94 found = true;
95 })(data[i]);
96 }
97 }
98
99 if (found) {
100 results.slideDown();
101 } else {
102 results.slideUp();
103 }
104 },
105 error: function(xhr, status, error) {
106 console.log("Ajax error:", status, error, xhr.status, xhr.responseText);
91 } 107 }
92 }); 108 });
93 }, 109 }
94 110
95 show_results : function(results) { 111 $(inputSelector).bind("input", function() {
96 $("#search_results").empty(); 112 if (isActive && !isActive()) return;
97 for (result in results) {
98 var link = $(("<a href='#'>"+ results[result].title + "</a>"));
99 $(link).bind("click", menu_items.link_closure(results[result]));
100 113
114 var term = $(this).val();
115 clearTimeout(timeout);
101 116
102 // Sometimes I don't get jquery; wrap() didn't work *sigh* 117 if (!term) {
103 // Guess I'll need a book someday or another framework 118 results.slideUp();
104 var wrapper = $("<div></div>"); 119 results.empty();
105 $(wrapper).append(link) 120 return;
121 }
106 122
107 $("#search_results").append(wrapper); 123 timeout = setTimeout(function() { runSearch(term); }, 250);
124 });
108 125
109 } 126 if (loadOnFocus) {
110 }, 127 $(inputSelector).bind("focus", function() {
128 if (isActive && !isActive()) return;
129 if ($(this).val()) return; // the input handler above already covers a real term
130 runSearch("");
131 });
132 }
133}
111 134
112 link_closure : function(node) { 135dashboard_search = {
113 var barf = function(){ 136 initialize : function() {
114 $("#menu_item_node_id").val(node.node_id); 137 initSearchPicker({
115 $("#menu_item_path").val("/" + node.unique_name); 138 inputSelector: "#dashboard_search_term",
116 $("#menu_item_title").val(node.title); 139 resultsSelector: "#dashboard_search_results",
117 return false; 140 url: DASHBOARD_SEARCH_URL,
118 } 141 resultsHeaderHtml: "<p class='search_more'>Press Enter to see all results ⏎</p>",
142 renderResults: function(data, results, resultsHeaderHtml) {
143 var found = false;
144
145 if ((data.tags.length || data.nodes.length) && resultsHeaderHtml) {
146 results.append(resultsHeaderHtml);
147 }
148
149 if (data.tags.length) {
150 results.append("<p class='search_group_label'>Tags</p>");
151 var tag_row = $("<div class='search_tag_row'></div>");
152 data.tags.forEach(function(tag) {
153 tag_row.append("<a class='search_tag_pill' href='" + tag.tag_path + "'>" + tag.name + "</a>");
154 found = true;
155 });
156 results.append(tag_row);
157 }
158
159 if (data.nodes.length) {
160 results.append("<p class='search_group_label'>Pages</p>");
161 data.nodes.forEach(function(node) {
162 results.append(
163 "<p><a href='" + node.node_path + "'>" + node.title +
164 "<span class='result_path'>" + node.unique_name + "</span></a></p>"
165 );
166 found = true;
167 });
168 }
169
170 return found;
171 }
172 });
173 }
174};
119 175
120 return barf; 176menu_items = {
177 initialize_search : function() {
178 initSearchPicker({
179 inputSelector: "#menu_search_term",
180 resultsSelector: "#menu_item_search_results",
181 onSelect: function(node) {
182 $("#menu_item_node_id").val(node.node_id);
183 $("#menu_item_path").val("/" + node.unique_name);
184 $("#menu_item_title").val(node.title);
185 }
186 });
121 } 187 }
122}; 188};
123 189
@@ -125,136 +191,93 @@ parent_search = {
125 initialize_search : function() { 191 initialize_search : function() {
126 parent_search.initialize_radio_buttons(); 192 parent_search.initialize_radio_buttons();
127 193
128 $("#parent_search_term").bind("keyup", function() { 194 initSearchPicker({
129 if ($(this).attr("value")) { 195 inputSelector: "#parent_search_term",
130 $.ajax({ 196 resultsSelector: "#parent_search_results",
131 type: "GET", 197 onSelect: function(node) {
132 url: ADMIN_MENU_SEARCH_URL, 198 $("#parent_search_term").val(node.title);
133 data: "search_term=" + $(this).attr("value"), 199 $("#parent_id").val(node.node_id).attr("data-unique-name", node.unique_name);
134 dataType: "json", 200 parent_search.update_resulting_path();
135 success : function(results) {
136 parent_search.show_results(results);
137 }
138 });
139 }
140 else {
141 $('#search_results').slideUp();
142 $('#search_results').empty();
143 } 201 }
144 }); 202 });
145 },
146 203
147 show_results : function(results) { 204 $("#title").bind("input", function() {
148 $("#search_results").empty(); 205 parent_search.update_resulting_path();
149 var found = false; 206 });
150 for (result in results) {
151 var link = $(("<a href='#'>"+ results[result].title + "</a>"));
152 $(link).bind("click", parent_search.link_closure(results[result]));
153 207
208 $("#copy_resulting_path").bind("click", function() {
209 var path = $("#resulting_path").text();
210 if (path === "—" || !navigator.clipboard) return;
211 navigator.clipboard.writeText(path);
212 });
213 },
154 214
155 // Sometimes I don't get jquery; wrap() didn't work *sigh* 215 update_resulting_path : function() {
156 // Guess I'll need a book someday or another framework 216 var kind = $("input[name='kind']:checked");
157 var wrapper = $("<div></div>"); 217 var title = $("#title").val();
158 $(wrapper).append(link);
159 218
160 $("#search_results").append(wrapper); 219 if (title === "") {
161 found = true; 220 $("#resulting_path").text("—");
221 return;
162 } 222 }
163 if (found)
164 $('#search_results').slideDown();
165 },
166 223
167 link_closure : function(node) { 224 var prefix = kind.val() === "generic"
168 var barf = function(){ 225 ? ($("#parent_id").attr("data-unique-name") || "")
169 $("#parent_search_term").attr("value", node.title); 226 : (kind.attr("data-path-prefix") || "");
170 $("#parent_id").attr("value", node.node_id);
171 $('#search_results').slideUp();
172 $('#search_results').empty();
173 return false;
174 }
175 227
176 return barf; 228 clearTimeout(parent_search.path_timeout);
229 parent_search.path_timeout = setTimeout(function() {
230 $.get(PARAMETERIZE_PREVIEW_URL, { title: title }, function(slug) {
231 $("#resulting_path").text(window.location.origin + "/" + (prefix ? prefix + "/" : "") + slug);
232 });
233 }, 300);
177 }, 234 },
178 235
179 initialize_radio_buttons : function() { 236 initialize_radio_buttons : function() {
180 $("#kind_top_level").bind("change", function(){ 237 parent_search.sync_parent_field();
181 $("#parent_search_field").hide(); 238 $("input[name='kind']").bind("change", function() {
182 }); 239 parent_search.sync_parent_field();
183 240 parent_search.update_resulting_path();
184 $("#kind_update").bind("change", function(){
185 $("#parent_search_field").hide();
186 }); 241 });
242 },
187 243
188 $("#kind_press_release").bind("change", function(){ 244 sync_parent_field : function() {
245 var kind = $("input[name='kind']:checked").val();
246 if (kind === "generic") {
247 $("#parent_search_field").show();
248 } else {
189 $("#parent_search_field").hide(); 249 $("#parent_search_field").hide();
190 }); 250 }
251 }
252};
191 253
192 $("#kind_generic").bind("change", function(){ 254move_to_search = {
193 $("#parent_search_field").show(); 255 initialize_search : function() {
256 initSearchPicker({
257 inputSelector: "#move_to_search_term",
258 resultsSelector: "#move_to_search_results",
259 onSelect: function(node) {
260 $("#move_to_search_term").val(node.title);
261 $("#node_staged_parent_id").val(node.node_id);
262 }
194 }); 263 });
195
196 } 264 }
197} 265};
198 266
199move_to_search = { 267event_search = {
200 initialize_search : function() { 268 initialize_search : function() {
201 $("#move_to_search_term").bind("keyup", function() { move_to_search.do_search($(this))}); 269 initSearchPicker({
202 $("#move_to_search_term").bind("keydown", function() { move_to_search.do_search($(this))}); 270 inputSelector: "#event_node_search_term",
203 $("#move_to_search_term").bind("keypress", function() { move_to_search.do_search($(this))}); 271 resultsSelector: "#event_search_results",
204 $("#move_to_search_term").bind("paste", function() { move_to_search.do_search($(this))}); 272 onSelect: function(node) {
205 $("#move_to_search_term").bind("cut", function() { move_to_search.do_search($(this))}); 273 $("#event_node_search_term").val(node.title);
206 }, 274 $("#event_node_id").val(node.node_id);
207 275
208 do_search : function(_this) { 276 var title_field = $("#event_title");
209 if (_this.attr("value")) { 277 if (title_field.val() === "") {
210 $.ajax({ 278 $("#event_title_hint").text("Using \"" + node.title + "\" from the associated node.");
211 type: "GET",
212 url: ADMIN_MENU_SEARCH_URL,
213 data: "search_term=" + _this.attr("value"),
214 dataType: "json",
215 success : function(results) {
216 move_to_search.show_results(results);
217 } 279 }
218 }); 280 }
219 } 281 });
220 else {
221 $('#search_results').slideUp();
222 $('#search_results').empty();
223 }
224 },
225
226 show_results : function(results) {
227 $("#search_results").empty();
228 var found = false;
229 for (result in results) {
230 var link = $(("<a href='#'>"+ results[result].title + "</a>"));
231 $(link).bind("click", move_to_search.link_closure(results[result]));
232
233
234 // Sometimes I don't get jquery; wrap() didn't work *sigh*
235 // Guess I'll need a book someday or another framework
236 var wrapper = $("<div></div>");
237 $(wrapper).append(link)
238
239 $("#search_results").append(wrapper);
240 found = true;
241 }
242 if (found)
243 $('#search_results').slideDown();
244 else
245 $('#search_results').slideUp();
246
247 },
248
249 link_closure : function(node) {
250 var barf = function(){
251 $("#move_to_search_term").attr("value", node.title);
252 $("#node_staged_parent_id").attr("value", node.node_id);
253 $('#search_results').slideUp();
254 $('#search_results').empty();
255 return false;
256 }
257
258 return barf;
259 } 282 }
260} 283};