Mercurial > repos > adam-novak > hexagram
comparison hexagram-6ae12361157c/hexagram/tools.js @ 0:1407e3634bcf draft default tip
Uploaded r11 from test tool shed.
author | adam-novak |
---|---|
date | Tue, 22 Oct 2013 14:17:59 -0400 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:1407e3634bcf |
---|---|
1 // tools.js: Code to run all the tools in the menu bar. | |
2 // References globals in hexagram.js to actually do the tools' work. | |
3 | |
4 // To add a tool: | |
5 // * Make a $(function() {...}); block to hold your code. | |
6 // * Add a tool with add_tool with your tool code as the callback. | |
7 // * Add at least one tool listener with add_tool_listener. Give it cleanup code | |
8 // if necessary to remove temporary UI elements. | |
9 // * Make sure to set selected_tool to undefined when your tool's normal | |
10 // workflow completes, so that the infowindow can use click events again. | |
11 // (it got set to your tool's name by the code prepended to your callback). | |
12 | |
13 $(function() { | |
14 // Set up the add text control | |
15 add_tool("add-text", "Add Text...", function() { | |
16 | |
17 // We'll prompt the user for some text, and then put a label where they | |
18 // next click. | |
19 | |
20 var text = prompt("Enter some text, and click anywhere on the " + | |
21 "visualization to place it there", "Label Text"); | |
22 | |
23 if(!text) { | |
24 // They don't want to put a label | |
25 selected_tool = undefined; | |
26 return; | |
27 } | |
28 | |
29 // Add a tool listenerr that places the label. It fires on a click | |
30 // anywhere on anything on the map, including the background. We keep a | |
31 // handle to it so we can remove it when it fires, ensuring we get just | |
32 // one label. See http://stackoverflow.com/a/1544185 | |
33 var handle = add_tool_listener("click", function(event) { | |
34 | |
35 // Make a new MapLabel at the click position | |
36 // See http://bit.ly/18MbLhR (the MapLabel library example page) | |
37 var map_label = new MapLabel({ | |
38 text: text, | |
39 position: event.latLng, | |
40 map: googlemap, | |
41 fontSize: 10, | |
42 align: "left" | |
43 }); | |
44 | |
45 // Subscribe tool listeners to the label | |
46 subscribe_tool_listeners(map_label); | |
47 | |
48 // Don't trigger again | |
49 remove_tool_listener(handle); | |
50 }, function() { | |
51 // Cleanup: de-select ourselves. | |
52 selected_tool = undefined; | |
53 }); | |
54 }); | |
55 }); | |
56 | |
57 $(function() { | |
58 // Set up the selection tool | |
59 add_tool("select", "Select", function() { | |
60 | |
61 // Turn on a crosshair cursor | |
62 googlemap.setOptions({ | |
63 draggableCursor:"crosshair" | |
64 }); | |
65 | |
66 // Add a listener to start the selection where the user clicks | |
67 var start_handle = add_tool_listener("click", | |
68 function(event) { | |
69 | |
70 // Don't trigger again | |
71 remove_tool_listener(start_handle); | |
72 | |
73 // Turn on a crosshair cursor again | |
74 googlemap.setOptions({ | |
75 draggableCursor:"crosshair" | |
76 }); | |
77 | |
78 // Store the start of the selection | |
79 var selection_start = event.latLng; | |
80 | |
81 print("Selection started at " + selection_start); | |
82 | |
83 // Make a rectangle for the selection | |
84 var rectangle = new google.maps.Rectangle({ | |
85 fillColor: "#FFFFFF", | |
86 strokeColor: "#FFFFFF", | |
87 strokeWeight: 2, | |
88 strokeOpacity: 1.0, | |
89 fillOpacity: 0.5, | |
90 // Don't give us a clickable cursor, or take mouse events. | |
91 clickable: false, | |
92 map: googlemap, | |
93 bounds: new google.maps.LatLngBounds(selection_start, | |
94 selection_start) | |
95 }); | |
96 | |
97 // This holds a selection preview event handler that should happen | |
98 // when we mouse over the map or the rectangle. | |
99 var preview = function(event) { | |
100 | |
101 // Store the end of the selection (provisionally) | |
102 var selection_end = event.latLng; | |
103 | |
104 | |
105 if(selection_end.lng() < selection_start.lng()) { | |
106 // The user has selected a backwards rectangle, which wraps | |
107 // across the place where the globe is cut. None of our | |
108 // selections ever need to do this. | |
109 | |
110 // Make the rectangle backwards | |
111 rectangle.setBounds(new google.maps.LatLngBounds( | |
112 selection_end, selection_start)); | |
113 | |
114 } else { | |
115 // Make the rectangle forwards | |
116 rectangle.setBounds(new google.maps.LatLngBounds( | |
117 selection_start, selection_end)); | |
118 } | |
119 } | |
120 | |
121 // This holds a cleanup function to get rid of the rectangle when | |
122 // the resizing listener goes away. | |
123 var preview_cleanup = function() { | |
124 // Remove the rectangle | |
125 rectangle.setMap(undefined); | |
126 | |
127 // Remove the crosshair cursor | |
128 googlemap.setOptions({ | |
129 draggableCursor: undefined | |
130 }); | |
131 }; | |
132 | |
133 // Add a mouse move listener for interactivity | |
134 // Works over the map, hexes, or the rectangle. | |
135 var move_handle = add_tool_listener("mousemove", preview, | |
136 preview_cleanup); | |
137 | |
138 // We need a listener to finish the selection | |
139 var finish = function(event) { | |
140 // Don't trigger again | |
141 remove_tool_listener(stop_handle); | |
142 | |
143 // Also stop the dynamic updates. This removes the rectangle. | |
144 remove_tool_listener(move_handle); | |
145 | |
146 // Store the end of the selection | |
147 var selection_end = event.latLng; | |
148 | |
149 print("Selection ended at " + selection_end); | |
150 | |
151 // Select the rectangle by arbitrary corners. | |
152 select_rectangle(selection_start, selection_end); | |
153 }; | |
154 | |
155 // Attach the listener. | |
156 // The listener can still use its own handle because variable | |
157 // references are resolved at runtime. | |
158 var stop_handle = add_tool_listener("click", finish, function() { | |
159 // Cleanup: say this tool is no longer selected | |
160 selected_tool = undefined; | |
161 }); | |
162 | |
163 }, function() { | |
164 // Remove the crosshair cursor | |
165 googlemap.setOptions({ | |
166 draggableCursor: undefined | |
167 }); | |
168 }); | |
169 }); | |
170 }); | |
171 | |
172 // A tool for importing a list of hexes as a selection | |
173 $(function() { | |
174 add_tool("import", "Import...", function() { | |
175 // Make the import form | |
176 var import_form = $("<form/>").attr("title", | |
177 "Import List As Selection"); | |
178 | |
179 import_form.append($("<div/>").text("Input names, one per line:")); | |
180 | |
181 // A big text box | |
182 var text_area = $("<textarea/>").addClass("import"); | |
183 import_form.append(text_area); | |
184 | |
185 import_form.append($("<div/>").text( | |
186 "Open a file:")); | |
187 | |
188 // This holds a file form element | |
189 var file_picker = $("<input/>").attr("type", "file").addClass("import"); | |
190 | |
191 import_form.append(file_picker); | |
192 | |
193 file_picker.change(function(event) { | |
194 // When a file is selected, read it in and populate the text box. | |
195 | |
196 // What file do we really want to read? | |
197 var file = event.target.files[0]; | |
198 | |
199 // Make a FileReader to read the file | |
200 var reader = new FileReader(); | |
201 | |
202 reader.onload = function(read_event) { | |
203 // When we read with readAsText, we get a string. Just stuff it | |
204 // in the text box for the user to see. | |
205 text_area.text(reader.result); | |
206 }; | |
207 | |
208 // Read the file, and, when it comes in, stick it in the textbox. | |
209 reader.readAsText(file); | |
210 }); | |
211 | |
212 import_form.dialog({ | |
213 modal: true, | |
214 buttons: { | |
215 "Import": function() { | |
216 // Do the import of the data. The data in question is always | |
217 // in the textbox. | |
218 | |
219 // Select all the entered hexes | |
220 select_string(text_area.val()); | |
221 | |
222 // Finally, close the dialog | |
223 $(this).dialog("close"); | |
224 | |
225 // Done with the tool | |
226 selected_tool = undefined; | |
227 } | |
228 }, | |
229 close: function() { | |
230 // They didn't want to use this tool. | |
231 selected_tool = undefined; | |
232 } | |
233 }); | |
234 }); | |
235 }); | |
236 | |
237 // The actual text to selection import function used by that tool | |
238 function select_string(string) { | |
239 // Given a string of hex names, one per line, make a selection of all those | |
240 // hexes. | |
241 | |
242 // This is an array of signature names entered. | |
243 var to_select = []; | |
244 | |
245 // This holds the array of lines. Split on newlines (as seen in | |
246 // jQuery.tsv.js) | |
247 var lines = string.split(/\r?\n/); | |
248 | |
249 for(var i = 0; i < lines.length; i++) { | |
250 // Trim and add to our requested selection | |
251 to_select.push(lines[i].trim()); | |
252 } | |
253 | |
254 // Add a selection with as many of the requested hexes as actually exist and | |
255 // pass the current filters. | |
256 select_list(to_select); | |
257 } | |
258 | |
259 // And a tool for exporting selections as lists of hexes | |
260 $(function() { | |
261 add_tool("export", "Export...", function() { | |
262 // Make the export form | |
263 var export_form = $("<form/>").attr("title", | |
264 "Export Selection As List"); | |
265 | |
266 export_form.append($("<div/>").text("Select a selection to export:")); | |
267 | |
268 // Make a select box for picking from all selections. | |
269 var select_box = $("<select/>"); | |
270 | |
271 // Populate it with all existing selections | |
272 for(var layer_name in layers) { | |
273 if(layers[layer_name].selection) { | |
274 // This is a selection, so add it to the dropdown. | |
275 select_box.append($("<option/>").text(layer_name).attr("value", | |
276 layer_name)); | |
277 } | |
278 } | |
279 | |
280 export_form.append(select_box); | |
281 | |
282 export_form.append($("<div/>").text("Exported data:")); | |
283 | |
284 // A big text box | |
285 var text_area = $("<textarea/>").addClass("export"); | |
286 text_area.prop("readonly", true); | |
287 export_form.append(text_area); | |
288 | |
289 // Add a download as file link. The "download" attribute makes the | |
290 // browser save it, and the href data URI holds the data. | |
291 var download_link = $("<a/>").attr("download", "selection.txt"); | |
292 download_link.attr("href", "data:text/plain;base64,"); | |
293 download_link.text("Download As Text"); | |
294 | |
295 export_form.append(download_link); | |
296 | |
297 text_area.focus(function() { | |
298 // Select all on focus. | |
299 | |
300 $(this).select(); | |
301 }); | |
302 | |
303 text_area.mouseup(function(event) { | |
304 // Don't change selection on mouseup. See | |
305 // http://stackoverflow.com/a/5797700/402891 and | |
306 // http://stackoverflow.com/q/3380458/402891 | |
307 event.preventDefault(); | |
308 }); | |
309 | |
310 select_box.change(function() { | |
311 // Update the text area with the list of hexes in the selected | |
312 // layer. | |
313 | |
314 // Get the layer name. | |
315 var layer_name = select_box.val(); | |
316 if(!have_layer(layer_name)) { | |
317 // Not a real layer. | |
318 // Probably just an empty select or something | |
319 return; | |
320 } | |
321 | |
322 // This holds our list. We build it in a string so we can escape it | |
323 // with one .text() call when adding it to the page. | |
324 var exported = ""; | |
325 | |
326 // Get the layer data to export | |
327 var layer_data = layers[layer_name].data; | |
328 for(var signature in layer_data) { | |
329 if(layer_data[signature]) { | |
330 // It's selected, put it in | |
331 | |
332 if(exported != "") { | |
333 // If there's already text, put a newline first. | |
334 exported += "\n"; | |
335 } | |
336 | |
337 exported += signature; | |
338 } | |
339 } | |
340 | |
341 // Now we know all the signatures from the selection, so tell the | |
342 // page. | |
343 text_area.text(exported); | |
344 | |
345 // Also fill in the data URI for saving. We use the handy | |
346 // window.bota encoding function. | |
347 download_link.attr("href", "data:text/plain;base64," + | |
348 window.btoa(exported)); | |
349 }); | |
350 | |
351 // Trigger the change event on the select box for the first selected | |
352 // thing, if any. | |
353 select_box.change(); | |
354 | |
355 export_form.dialog({ | |
356 modal: true, | |
357 buttons: { | |
358 "Done": function() { | |
359 // First, close the dialog | |
360 $(this).dialog("close"); | |
361 | |
362 // Done with the tool | |
363 selected_tool = undefined; | |
364 } | |
365 }, | |
366 close: function() { | |
367 // They didn't want to use this tool. | |
368 selected_tool = undefined; | |
369 } | |
370 }); | |
371 }); | |
372 }); | |
373 | |
374 $(function() { | |
375 // Set up the link to this page control | |
376 add_tool("link-to-page", "Link to this Page...", function() { | |
377 | |
378 // We will provide the user with an alert box with the link to the | |
379 // hexagrap visualization map. | |
380 | |
381 var link = (window.location.protocol + "//" + window.location.host | |
382 + "/" + window.location.pathname); | |
383 | |
384 alert(link); | |
385 selected_tool = undefined; | |
386 | |
387 }); | |
388 }); | |
389 |