Mercurial > repos > adam-novak > hexagram
view 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 |
line wrap: on
line source
// tools.js: Code to run all the tools in the menu bar. // References globals in hexagram.js to actually do the tools' work. // To add a tool: // * Make a $(function() {...}); block to hold your code. // * Add a tool with add_tool with your tool code as the callback. // * Add at least one tool listener with add_tool_listener. Give it cleanup code // if necessary to remove temporary UI elements. // * Make sure to set selected_tool to undefined when your tool's normal // workflow completes, so that the infowindow can use click events again. // (it got set to your tool's name by the code prepended to your callback). $(function() { // Set up the add text control add_tool("add-text", "Add Text...", function() { // We'll prompt the user for some text, and then put a label where they // next click. var text = prompt("Enter some text, and click anywhere on the " + "visualization to place it there", "Label Text"); if(!text) { // They don't want to put a label print("Not putting any text"); selected_tool = undefined; return; } // Add a tool listenerr that places the label. It fires on a click // anywhere on anything on the map, including the background. We keep a // handle to it so we can remove it when it fires, ensuring we get just // one label. See http://stackoverflow.com/a/1544185 var handle = add_tool_listener("click", function(event) { // Make a new MapLabel at the click position // See http://bit.ly/18MbLhR (the MapLabel library example page) var map_label = new MapLabel({ text: text, position: event.latLng, map: googlemap, fontSize: 10, align: "left" }); // Subscribe tool listeners to the label subscribe_tool_listeners(map_label); // Don't trigger again remove_tool_listener(handle); }, function() { // Cleanup: de-select ourselves. selected_tool = undefined; }); }); }); $(function() { // Set up the selection tool add_tool("select", "Select", function() { // Turn on a crosshair cursor googlemap.setOptions({ draggableCursor:"crosshair" }); // Add a listener to start the selection where the user clicks var start_handle = add_tool_listener("click", function(event) { // Don't trigger again remove_tool_listener(start_handle); // Turn on a crosshair cursor again googlemap.setOptions({ draggableCursor:"crosshair" }); // Store the start of the selection var selection_start = event.latLng; print("Selection started at " + selection_start); // Make a rectangle for the selection var rectangle = new google.maps.Rectangle({ fillColor: "#FFFFFF", strokeColor: "#FFFFFF", strokeWeight: 2, strokeOpacity: 1.0, fillOpacity: 0.5, // Don't give us a clickable cursor, or take mouse events. clickable: false, map: googlemap, bounds: new google.maps.LatLngBounds(selection_start, selection_start) }); // This holds a selection preview event handler that should happen // when we mouse over the map or the rectangle. var preview = function(event) { // Store the end of the selection (provisionally) var selection_end = event.latLng; if(selection_end.lng() < selection_start.lng()) { // The user has selected a backwards rectangle, which wraps // across the place where the globe is cut. None of our // selections ever need to do this. // Make the rectangle backwards rectangle.setBounds(new google.maps.LatLngBounds( selection_end, selection_start)); } else { // Make the rectangle forwards rectangle.setBounds(new google.maps.LatLngBounds( selection_start, selection_end)); } } // This holds a cleanup function to get rid of the rectangle when // the resizing listener goes away. var preview_cleanup = function() { // Remove the rectangle rectangle.setMap(undefined); // Remove the crosshair cursor googlemap.setOptions({ draggableCursor: undefined }); }; // Add a mouse move listener for interactivity // Works over the map, hexes, or the rectangle. var move_handle = add_tool_listener("mousemove", preview, preview_cleanup); // We need a listener to finish the selection var finish = function(event) { // Don't trigger again remove_tool_listener(stop_handle); // Also stop the dynamic updates. This removes the rectangle. remove_tool_listener(move_handle); // Store the end of the selection var selection_end = event.latLng; print("Selection ended at " + selection_end); // Select the rectangle by arbitrary corners. select_rectangle(selection_start, selection_end); }; // Attach the listener. // The listener can still use its own handle because variable // references are resolved at runtime. var stop_handle = add_tool_listener("click", finish, function() { // Cleanup: say this tool is no longer selected selected_tool = undefined; }); }, function() { // Remove the crosshair cursor googlemap.setOptions({ draggableCursor: undefined }); }); }); }); // A tool for importing a list of hexes as a selection $(function() { add_tool("import", "Import...", function() { // Make the import form var import_form = $("<form/>").attr("title", "Import List As Selection"); import_form.append($("<div/>").text("Input names, one per line:")); // A big text box var text_area = $("<textarea/>").addClass("import"); import_form.append(text_area); import_form.append($("<div/>").text( "Open a file:")); // This holds a file form element var file_picker = $("<input/>").attr("type", "file").addClass("import"); import_form.append(file_picker); file_picker.change(function(event) { // When a file is selected, read it in and populate the text box. // What file do we really want to read? var file = event.target.files[0]; // Make a FileReader to read the file var reader = new FileReader(); reader.onload = function(read_event) { // When we read with readAsText, we get a string. Just stuff it // in the text box for the user to see. text_area.text(reader.result); }; // Read the file, and, when it comes in, stick it in the textbox. reader.readAsText(file); }); import_form.dialog({ modal: true, buttons: { "Import": function() { // Do the import of the data. The data in question is always // in the textbox. // Select all the entered hexes select_string(text_area.val()); // Finally, close the dialog $(this).dialog("close"); // Done with the tool selected_tool = undefined; } }, close: function() { // They didn't want to use this tool. selected_tool = undefined; } }); }); }); // The actual text to selection import function used by that tool function select_string(string) { // Given a string of hex names, one per line, make a selection of all those // hexes. // This is an array of signature names entered. var to_select = []; // This holds the array of lines. Split on newlines (as seen in // jQuery.tsv.js) var lines = string.split(/\r?\n/); for(var i = 0; i < lines.length; i++) { // Trim and add to our requested selection to_select.push(lines[i].trim()); } // Add a selection with as many of the requested hexes as actually exist and // pass the current filters. select_list(to_select); } // And a tool for exporting selections as lists of hexes $(function() { add_tool("export", "Export...", function() { // Make the export form var export_form = $("<form/>").attr("title", "Export Selection As List"); export_form.append($("<div/>").text("Select a selection to export:")); // Make a select box for picking from all selections. var select_box = $("<select/>"); // Populate it with all existing selections for(var layer_name in layers) { if(layers[layer_name].selection) { // This is a selection, so add it to the dropdown. select_box.append($("<option/>").text(layer_name).attr("value", layer_name)); } } export_form.append(select_box); export_form.append($("<div/>").text("Exported data:")); // A big text box var text_area = $("<textarea/>").addClass("export"); text_area.prop("readonly", true); export_form.append(text_area); // Add a download as file link. The "download" attribute makes the // browser save it, and the href data URI holds the data. var download_link = $("<a/>").attr("download", "selection.txt"); download_link.attr("href", "data:text/plain;base64,"); download_link.text("Download As Text"); export_form.append(download_link); text_area.focus(function() { // Select all on focus. $(this).select(); }); text_area.mouseup(function(event) { // Don't change selection on mouseup. See // http://stackoverflow.com/a/5797700/402891 and // http://stackoverflow.com/q/3380458/402891 event.preventDefault(); }); select_box.change(function() { // Update the text area with the list of hexes in the selected // layer. // Get the layer name. var layer_name = select_box.val(); if(!have_layer(layer_name)) { // Not a real layer. // Probably just an empty select or something return; } // This holds our list. We build it in a string so we can escape it // with one .text() call when adding it to the page. var exported = ""; // Get the layer data to export var layer_data = layers[layer_name].data; for(var signature in layer_data) { if(layer_data[signature]) { // It's selected, put it in if(exported != "") { // If there's already text, put a newline first. exported += "\n"; } exported += signature; } } // Now we know all the signatures from the selection, so tell the // page. text_area.text(exported); // Also fill in the data URI for saving. We use the handy // window.bota encoding function. download_link.attr("href", "data:text/plain;base64," + window.btoa(exported)); }); // Trigger the change event on the select box for the first selected // thing, if any. select_box.change(); export_form.dialog({ modal: true, buttons: { "Done": function() { // First, close the dialog $(this).dialog("close"); // Done with the tool selected_tool = undefined; } }, close: function() { // They didn't want to use this tool. selected_tool = undefined; } }); }); });