summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--app/controllers/admin_controller.rb4
-rw-r--r--app/views/events/edit.html.erb4
-rw-r--r--app/views/events/new.html.erb2
-rw-r--r--app/views/layouts/admin.html.erb4
-rw-r--r--app/views/menu_items/edit.html.erb2
-rw-r--r--app/views/menu_items/new.html.erb4
-rw-r--r--app/views/nodes/edit.html.erb14
-rw-r--r--app/views/nodes/new.html.erb2
-rw-r--r--public/javascripts/admin_search.js351
-rw-r--r--public/stylesheets/admin.css13
10 files changed, 135 insertions, 265 deletions
diff --git a/app/controllers/admin_controller.rb b/app/controllers/admin_controller.rb
index 435df57..3c45c49 100644
--- a/app/controllers/admin_controller.rb
+++ b/app/controllers/admin_controller.rb
@@ -31,7 +31,7 @@ class AdminController < ApplicationController
31 end 31 end
32 32
33 def search 33 def search
34 @results = Node.search params[:search_term], :per_page => 1000 34 @results = Node.editor_search(params[:search_term])
35 35
36 respond_to do |format| 36 respond_to do |format|
37 format.html do 37 format.html do
@@ -53,7 +53,7 @@ class AdminController < ApplicationController
53 if params[:search_term] == "Root" 53 if params[:search_term] == "Root"
54 @results = [Node.root] 54 @results = [Node.root]
55 else 55 else
56 @results = Node.search params[:search_term] 56 @results = Node.editor_search(params[:search_term])
57 end 57 end
58 58
59 respond_to do |format| 59 respond_to do |format|
diff --git a/app/views/events/edit.html.erb b/app/views/events/edit.html.erb
index 6cb04bd..45b084f 100644
--- a/app/views/events/edit.html.erb
+++ b/app/views/events/edit.html.erb
@@ -19,12 +19,12 @@
19 <details> 19 <details>
20 <summary>Change node</summary> 20 <summary>Change node</summary>
21 <%= text_field_tag :event_node_search_term %> 21 <%= text_field_tag :event_node_search_term %>
22 <div id="search_results"></div> 22 <div id="event_search_results" class="search_results"></div>
23 <span class="field_hint">This will re-link the event to a different node — rarely needed.</span> 23 <span class="field_hint">This will re-link the event to a different node — rarely needed.</span>
24 </details> 24 </details>
25 <% else %> 25 <% else %>
26 <%= text_field_tag :event_node_search_term %> 26 <%= text_field_tag :event_node_search_term %>
27 <div id="search_results"></div> 27 <div id="event_search_results" class="search_results"></div>
28 <span class="field_hint">Optional — search and pick a node to associate this event with a page.</span> 28 <span class="field_hint">Optional — search and pick a node to associate this event with a page.</span>
29 <% end %> 29 <% end %>
30 <%= f.hidden_field :node_id %> 30 <%= f.hidden_field :node_id %>
diff --git a/app/views/events/new.html.erb b/app/views/events/new.html.erb
index b20fe48..7a1ee7a 100644
--- a/app/views/events/new.html.erb
+++ b/app/views/events/new.html.erb
@@ -10,7 +10,7 @@
10 <div class="node_description">Node</div> 10 <div class="node_description">Node</div>
11 <div class="node_content"> 11 <div class="node_content">
12 <%= text_field_tag :event_node_search_term %> 12 <%= text_field_tag :event_node_search_term %>
13 <div id="search_results"></div> 13 <div id="event_search_results" class="search_results"></div>
14 <%= f.hidden_field :node_id %> 14 <%= f.hidden_field :node_id %>
15 <span class="field_hint">Optional — search and pick a node to associate this event with a page.</span> 15 <span class="field_hint">Optional — search and pick a node to associate this event with a page.</span>
16 </div> 16 </div>
diff --git a/app/views/layouts/admin.html.erb b/app/views/layouts/admin.html.erb
index e714c28..079346b 100644
--- a/app/views/layouts/admin.html.erb
+++ b/app/views/layouts/admin.html.erb
@@ -56,9 +56,7 @@
56 <span>Search: </span><%= text_field_tag :search_term, nil, autocomplete: "off" %> 56 <span>Search: </span><%= text_field_tag :search_term, nil, autocomplete: "off" %>
57 <% end %> 57 <% end %>
58 </div> 58 </div>
59 <div id="menu_search_results" style="display: none"> 59 <div id="menu_search_results" class="search_results" style="display: none"></div>
60
61 </div>
62 </div> 60 </div>
63 </body> 61 </body>
64</html> 62</html>
diff --git a/app/views/menu_items/edit.html.erb b/app/views/menu_items/edit.html.erb
index dc5e8f9..44e5a79 100644
--- a/app/views/menu_items/edit.html.erb
+++ b/app/views/menu_items/edit.html.erb
@@ -6,7 +6,7 @@
6 <div class="node_description">Search</div> 6 <div class="node_description">Search</div>
7 <div class="node_content"> 7 <div class="node_content">
8 <%= text_field_tag :menu_search_term %> 8 <%= text_field_tag :menu_search_term %>
9 <div id="search_results"></div> 9 <div id="menu_item_search_results" class="search_results"></div>
10 </div> 10 </div>
11 11
12 <div class="node_description">Node Id</div> 12 <div class="node_description">Node Id</div>
diff --git a/app/views/menu_items/new.html.erb b/app/views/menu_items/new.html.erb
index 68081d0..223cb8e 100644
--- a/app/views/menu_items/new.html.erb
+++ b/app/views/menu_items/new.html.erb
@@ -7,9 +7,7 @@
7 <td class="description">Search</td> 7 <td class="description">Search</td>
8 <td> 8 <td>
9 <%= text_field_tag :menu_search_term %> 9 <%= text_field_tag :menu_search_term %>
10 <div id="search_results"> 10 <div id="menu_item_search_results" class="search_results"></div>
11
12 </div>
13 </td> 11 </td>
14 </tr> 12 </tr>
15 <tr> 13 <tr>
diff --git a/app/views/nodes/edit.html.erb b/app/views/nodes/edit.html.erb
index 1c19410..13b78fc 100644
--- a/app/views/nodes/edit.html.erb
+++ b/app/views/nodes/edit.html.erb
@@ -45,14 +45,12 @@
45 <div class="node_description">parent</div> 45 <div class="node_description">parent</div>
46 <div class="node_content"> 46 <div class="node_content">
47 <%= text_field_tag :move_to_search_term, @node.parent.title rescue "" %> 47 <%= text_field_tag :move_to_search_term, @node.parent.title rescue "" %>
48 <div id="search_results"> 48 <div id="move_to_search_results" class="search_results"></div>
49 49 <%= f.hidden_field(
50 </div> 50 :staged_parent_id,
51 <%= f.hidden_field( 51 :value => @node.staged_parent_id || @node.parent_id
52 :staged_parent_id, 52 )
53 :value => @node.staged_parent_id || @node.parent_id 53 %>
54 )
55 %>
56 </div> 54 </div>
57 55
58 <%= fields_for @page do |d| %> 56 <%= fields_for @page do |d| %>
diff --git a/app/views/nodes/new.html.erb b/app/views/nodes/new.html.erb
index afc632f..bb7e078 100644
--- a/app/views/nodes/new.html.erb
+++ b/app/views/nodes/new.html.erb
@@ -34,7 +34,7 @@
34 <div class="node_content"> 34 <div class="node_content">
35 <%= text_field_tag :parent_search_term, @parent_name %> 35 <%= text_field_tag :parent_search_term, @parent_name %>
36 <%= hidden_field_tag :parent_id, @parent_id %> 36 <%= hidden_field_tag :parent_id, @parent_id %>
37 <div id="search_results"></div> 37 <div id="parent_search_results" class="search_results"></div>
38 </div> 38 </div>
39 </div> 39 </div>
40 40
diff --git a/public/javascripts/admin_search.js b/public/javascripts/admin_search.js
index 0e70845..f553334 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 $('#menu_search_results').slideUp();
40 $('#menu_search_results').empty();
41 }
42 }); 28 });
43 }, 29 },
44 30
@@ -49,75 +35,97 @@ 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 $('#menu_search_results').empty();
56 if (results.length) {
57 $('#menu_search_results').append(
58 "<p class='search_more'>Press Enter to see all results ⏎</p>"
59 );
60 }
61 for (result in results) {
62 $('#menu_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 $('#menu_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; // omit for a real-navigation search like admin_search
46 var isActive = options.isActive; // optional guard, checked before every search
47 var resultsHeaderHtml = options.resultsHeaderHtml; // optional, prepended only when results exist
48 var requestId = 0;
49 var timeout;
74 50
75 initialize_search : function() { 51 $(inputSelector).bind("input", function() {
76 $("#menu_search_term").bind("input", function() { 52 if (isActive && !isActive()) return;
77 if ($(this).val()) {
78 $.ajax({
79 type: "GET",
80 url: ADMIN_MENU_SEARCH_URL,
81 data: "search_term=" + $(this).val(),
82 dataType: "json",
83 success : function(results) {
84 menu_items.show_results(results);
85 }
86 });
87 }
88 else {
89 $('#search_results').slideUp();
90 $('#search_results').empty();
91 }
92 });
93 },
94
95 show_results : function(results) {
96 $("#search_results").empty();
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 53
54 var term = $(this).val();
55 var results = $(resultsSelector);
56 clearTimeout(timeout);
101 57
102 // Sometimes I don't get jquery; wrap() didn't work *sigh* 58 if (!term) {
103 // Guess I'll need a book someday or another framework 59 results.slideUp();
104 var wrapper = $("<div></div>"); 60 results.empty();
105 $(wrapper).append(link) 61 return;
106
107 $("#search_results").append(wrapper);
108
109 } 62 }
110 },
111 63
112 link_closure : function(node) { 64 timeout = setTimeout(function() {
113 var barf = function(){ 65 var thisRequest = ++requestId;
114 $("#menu_item_node_id").val(node.node_id); 66 $.ajax({
115 $("#menu_item_path").val("/" + node.unique_name); 67 type: "GET",
116 $("#menu_item_title").val(node.title); 68 url: url,
117 return false; 69 data: "search_term=" + term,
118 } 70 dataType: "json",
71 success: function(nodes) {
72 if (thisRequest !== requestId) return;
73 results.empty();
74 if (nodes.length && resultsHeaderHtml) {
75 results.append(resultsHeaderHtml);
76 }
77 var found = false;
78 for (var i = 0; i < nodes.length; i++) {
79 (function(node) {
80 var link;
81 if (onSelect) {
82 link = $(
83 "<p><a href='#'>" + node.title +
84 "<span class='result_path'>" + node.unique_name + "</span>" +
85 "</a></p>"
86 );
87 link.find("a").bind("click", function() {
88 onSelect(node);
89 results.slideUp();
90 results.empty();
91 return false;
92 });
93 } else {
94 link = $(
95 "<p><a href='" + node.node_path + "'>" + node.title +
96 "<span class='result_path'>" + node.unique_name + "</span>" +
97 "</a></p>"
98 );
99 }
100 results.append(link);
101 found = true;
102 })(nodes[i]);
103 }
104 if (found) {
105 results.slideDown();
106 } else {
107 results.slideUp();
108 }
109 },
110 error: function(xhr, status, error) {
111 console.log("Ajax error:", status, error, xhr.status, xhr.responseText);
112 }
113 });
114 }, 250);
115 });
116}
119 117
120 return barf; 118menu_items = {
119 initialize_search : function() {
120 initSearchPicker({
121 inputSelector: "#menu_search_term",
122 resultsSelector: "#menu_item_search_results",
123 onSelect: function(node) {
124 $("#menu_item_node_id").val(node.node_id);
125 $("#menu_item_path").val("/" + node.unique_name);
126 $("#menu_item_title").val(node.title);
127 }
128 });
121 } 129 }
122}; 130};
123 131
@@ -125,21 +133,13 @@ parent_search = {
125 initialize_search : function() { 133 initialize_search : function() {
126 parent_search.initialize_radio_buttons(); 134 parent_search.initialize_radio_buttons();
127 135
128 $("#parent_search_term").bind("input", function() { 136 initSearchPicker({
129 if ($(this).val()) { 137 inputSelector: "#parent_search_term",
130 $.ajax({ 138 resultsSelector: "#parent_search_results",
131 type: "GET", 139 onSelect: function(node) {
132 url: ADMIN_MENU_SEARCH_URL, 140 $("#parent_search_term").val(node.title);
133 data: "search_term=" + $(this).val(), 141 $("#parent_id").val(node.node_id).attr("data-unique-name", node.unique_name);
134 dataType: "json", 142 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 } 143 }
144 }); 144 });
145 145
@@ -154,38 +154,6 @@ parent_search = {
154 }); 154 });
155 }, 155 },
156 156
157 show_results : function(results) {
158 $("#search_results").empty();
159 var found = false;
160 for (result in results) {
161
162 var link = $((
163 "<p><a href='#'>" + results[result].title +
164 "<span class='result_path'>" + results[result].unique_name + "</span>" +
165 "</a></p>"));
166
167 $(link).bind("click", parent_search.link_closure(results[result]));
168
169 $("#search_results").append(link);
170 found = true;
171 }
172 if (found)
173 $('#search_results').slideDown();
174 },
175
176 link_closure : function(node) {
177 var barf = function(){
178 $("#parent_search_term").val(node.title);
179 $("#parent_id").val(node.node_id).attr("data-unique-name", node.unique_name);
180 $('#search_results').slideUp();
181 $('#search_results').empty();
182 parent_search.update_resulting_path();
183 return false;
184 }
185
186 return barf;
187 },
188
189 update_resulting_path : function() { 157 update_resulting_path : function() {
190 var kind = $("input[name='kind']:checked"); 158 var kind = $("input[name='kind']:checked");
191 var title = $("#title").val(); 159 var title = $("#title").val();
@@ -223,122 +191,35 @@ parent_search = {
223 $("#parent_search_field").hide(); 191 $("#parent_search_field").hide();
224 } 192 }
225 } 193 }
226} 194};
227 195
228move_to_search = { 196move_to_search = {
229 initialize_search : function() { 197 initialize_search : function() {
230 $("#move_to_search_term").bind("input", function() {move_to_search.do_search($(this))}); 198 initSearchPicker({
231 }, 199 inputSelector: "#move_to_search_term",
232 200 resultsSelector: "#move_to_search_results",
233 do_search : function(_this) { 201 onSelect: function(node) {
234 if (_this.val()) { 202 $("#move_to_search_term").val(node.title);
235 $.ajax({ 203 $("#node_staged_parent_id").val(node.node_id);
236 type: "GET", 204 }
237 url: ADMIN_MENU_SEARCH_URL, 205 });
238 data: "search_term=" + _this.val(),
239 dataType: "json",
240 success : function(results) {
241 move_to_search.show_results(results);
242 }
243 });
244 }
245 else {
246 $('#search_results').slideUp();
247 $('#search_results').empty();
248 }
249 },
250
251 show_results : function(results) {
252 $("#search_results").empty();
253 var found = false;
254 for (result in results) {
255 var link = $(("<a href='#'>"+ results[result].title + "</a>"));
256 $(link).bind("click", move_to_search.link_closure(results[result]));
257
258
259 // Sometimes I don't get jquery; wrap() didn't work *sigh*
260 // Guess I'll need a book someday or another framework
261 var wrapper = $("<div></div>");
262 $(wrapper).append(link)
263
264 $("#search_results").append(wrapper);
265 found = true;
266 }
267 if (found)
268 $('#search_results').slideDown();
269 else
270 $('#search_results').slideUp();
271
272 },
273
274 link_closure : function(node) {
275 var barf = function(){
276 $("#move_to_search_term").val(node.title);
277 $("#node_staged_parent_id").val(node.node_id);
278 $('#search_results').slideUp();
279 $('#search_results').empty();
280 return false;
281 }
282
283 return barf;
284 } 206 }
285} 207};
286 208
287event_search = { 209event_search = {
288 initialize_search : function() { 210 initialize_search : function() {
289 $("#event_node_search_term").bind("input", function() { 211 initSearchPicker({
290 if ($(this).val()) { 212 inputSelector: "#event_node_search_term",
291 $.ajax({ 213 resultsSelector: "#event_search_results",
292 type: "GET", 214 onSelect: function(node) {
293 url: ADMIN_MENU_SEARCH_URL, 215 $("#event_node_search_term").val(node.title);
294 data: "search_term=" + $(this).val(), 216 $("#event_node_id").val(node.node_id);
295 dataType: "json",
296 success : function(results) {
297 event_search.show_results(results);
298 }
299 });
300 }
301 else {
302 $('#search_results').slideUp();
303 $('#search_results').empty();
304 }
305 });
306 },
307 217
308 show_results : function(results) { 218 var title_field = $("#event_title");
309 $("#search_results").empty(); 219 if (title_field.val() === "") {
310 var found = false; 220 $("#event_title_hint").text("Using \"" + node.title + "\" from the associated node.");
311 for (result in results) { 221 }
312 var link = $((
313 "<p><a href='#'>" + results[result].title +
314 "<span class='result_path'>" + results[result].unique_name + "</span>" +
315 "</a></p>"));
316
317 $(link).bind("click", event_search.link_closure(results[result]));
318
319 $("#search_results").append(link);
320 found = true;
321 }
322 if (found)
323 $('#search_results').slideDown();
324 else
325 $('#search_results').slideUp();
326 },
327
328 link_closure : function(node) {
329 var barf = function(){
330 $("#event_node_search_term").val(node.title);
331 $("#event_node_id").val(node.node_id);
332 $('#search_results').slideUp();
333 $('#search_results').empty();
334
335 var title_field = $("#event_title");
336 if (title_field.val() === "") {
337 $("#event_title_hint").text("Using \"" + node.title + "\" from the associated node.");
338 } 222 }
339 223 });
340 return false;
341 }
342 return barf;
343 } 224 }
344}; 225};
diff --git a/public/stylesheets/admin.css b/public/stylesheets/admin.css
index 5c1e489..da31535 100644
--- a/public/stylesheets/admin.css
+++ b/public/stylesheets/admin.css
@@ -155,7 +155,6 @@ input[type=radio] {
155 padding-right: 5px; 155 padding-right: 5px;
156 padding-top: 1px; 156 padding-top: 1px;
157 padding-bottom: 1px; 157 padding-bottom: 1px;
158 text-transform: lowercase;
159} 158}
160 159
161#metadata a:hover { 160#metadata a:hover {
@@ -1023,22 +1022,19 @@ div#draft_list table td.actions a {
1023 font-size: 18px; 1022 font-size: 18px;
1024} 1023}
1025 1024
1026#menu_search_results p, 1025.search_results p {
1027#search_results p {
1028 margin: 0; 1026 margin: 0;
1029 padding: 4px 4px 0 4px; 1027 padding: 4px 4px 0 4px;
1030 border-bottom: 1px solid #e8e8e8; 1028 border-bottom: 1px solid #e8e8e8;
1031} 1029}
1032 1030
1033#menu_search_results p a, 1031.search_results p a {
1034#search_results p a {
1035 display: block; 1032 display: block;
1036 font-weight: bold; 1033 font-weight: bold;
1037 font-size: 0.95rem; 1034 font-size: 0.95rem;
1038} 1035}
1039 1036
1040#menu_search_results p span.result_path, 1037.search_results p span.result_path {
1041#search_results p span.result_path {
1042 display: block; 1038 display: block;
1043 margin-top: 2px; 1039 margin-top: 2px;
1044 font-size: 0.75rem; 1040 font-size: 0.75rem;
@@ -1047,8 +1043,7 @@ div#draft_list table td.actions a {
1047 padding-bottom: 4px; 1043 padding-bottom: 4px;
1048} 1044}
1049 1045
1050#menu_search_results p.search_more, 1046.search_results p.search_more {
1051#search_results p.search_more {
1052 margin: 0; 1047 margin: 0;
1053 padding: 6px 4px; 1048 padding: 6px 4px;
1054 font-size: 0.8rem; 1049 font-size: 0.8rem;