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
            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;
            }
        });
    });
});

$(function() {
    // Set up the link to this page control
    add_tool("link-to-page", "Link to this Page...", function() {
        
        // We will provide the user with an alert box with the link to the
		// hexagrap visualization map.

		var link = (window.location.protocol + "//" + window.location.host 
					+ "/" + window.location.pathname);
		
		alert(link);
		selected_tool = undefined;
     
    });
});