Advertisement
daredevil82

CountyModule

Sep 26th, 2013
135
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. uboat.taxonomy.countyModule = function(){
  2.  
  3.     //internal module variables
  4.     var thisObj = {
  5.         //deals with map-centric elements and state variables
  6.         _mapElement : {
  7.             id : "#us_map",
  8.             width : 954,
  9.             height : 500,
  10.             projection : null,
  11.             path : null,
  12.             svg : null,
  13.             clicked : false,
  14.             centered : null,
  15.             scale : 1100,
  16.             loaded : false,
  17.             zoom : 4,
  18.         },
  19.         _currentCounty : {
  20.             id : null,
  21.             color : null,
  22.             name : null,
  23.         },
  24.         _previousCounty : {
  25.             color : null,
  26.             id : null
  27.         },
  28.         _fillColors : {
  29.             market : "#0000ff",
  30.             prospect : "#ff0000",
  31.             neutral : "#c0c0c0",
  32.             hover : "#4CD550"
  33.         },
  34.         //deals with tooltip data and variables
  35.         _tooltip : {
  36.             tooltip : null,
  37.             county : null,
  38.             open : false,
  39.             buttonTemplate : "<div id = 'tooltip_template'>" +
  40.                 "<div class = 'county_data'></div>" +
  41.                 "<img src = '/static/images/delete.png' width = '28' height = '28' class = " +
  42.         "'delete_logo' id = 'close_tooltip' />" +
  43.                 "<div id = 'no_client_message'></div>" +
  44.                 "<button id = 'add_prospective_market' class = 'tooltip_button'>" +
  45.         "Prospective Market</button>" +
  46.                 "<button id = 'add_market' class = 'tooltip_button'>Market County</button>" +
  47.                 "<button id = 'remove_market' class = 'tooltip_button'>Remove Market</button></div>",
  48.             hoverTemplate : "<div id = 'tooltip_template'><div class = 'county_data'></div>"
  49.         },
  50.         _clientSelect : $("#county_client_select"),
  51.         _countySearch : $("#county_search_autocomplete"),
  52.         _countySearchArray : [],
  53.         _currentClient : {
  54.             id : null,
  55.             name : null
  56.         },
  57.         _cachedCounties : false,
  58.     }
  59.  
  60.     //Need to initialize JS bindings and events
  61.     var initializeElements = function(){
  62.         $("#county_search_autocomplete").autocomplete({
  63.             minLength : 3,
  64.             //source : thisObj._countySearchArray
  65.             source : function(request, response){
  66.                 var results = $.ui.autocomplete.filter(thisObj._countySearchArray, request.term);
  67.                 response(results.slice(0, 10));
  68.             }
  69.         });
  70.  
  71.         thisObj._countySearch.keyup(countySearchHandler);
  72.         thisObj._clientSelect.change(countyClientHandler);
  73.  
  74.         //bind the tooltip event handlers to the body to avoid the event listener creation/destruction cycle
  75.         $("body")
  76.             .on("click", "#add_market", function(){
  77.                 if (thisObj._currentCounty.color != thisObj._fillColors.market)
  78.                     marketHandler(0);
  79.                 else
  80.                     $("#no_client_message").text("Market button has been disabled");
  81.             })
  82.             .on("click", "#add_prospective_market", function(){
  83.                 if (thisObj._currentCounty.color != thisObj._fillColors.prospect)
  84.                     marketHandler(1);
  85.                 else
  86.                     $("#no_client_message").text("Prospective market button has been disabled");
  87.             })
  88.             .on("click", "#remove_market", function(){
  89.                 marketHandler(2);
  90.             })
  91.             .on("click", "#close_tooltip", closeTooltipHandler)
  92.             .on("mouseover", "#close_tooltip", function(){
  93.                 $(this).css({"border-color" : "black", "opacity" : 1});
  94.             })
  95.             .on("mouseout", "#close_tooltip", function(){
  96.                 $(this).css({"border-color" : "black", "opacity" : 0.5});
  97.             });
  98.  
  99.     }
  100.  
  101.     //initialize the county search array, uses "label" and "value" to execute autocomplete searches
  102.     var initializeCountyArray = function(json){
  103.         for (var i = 0; i < json.length; i++) {
  104.             thisObj._countySearchArray.push({
  105.                 "id" : json[i].id,
  106.                 "name" : json[i].name,
  107.                 "state" : json[i].properties.StateCode,
  108.                 "label" : json[i].name + " "+ json[i].properties.StateCode, //used for jquery autocomplete
  109.                 "value" : json[i].name + " "+ json[i].properties.StateCode
  110.             });
  111.         }
  112.     }
  113.  
  114.     //Get all current clients in the db, initialize dropdown select list
  115.     var loadClientSelection = function(){
  116.         $.ajax({
  117.             url : "getClientorgList/",
  118.             type : "GET",
  119.             dataType : "json",
  120.             success : function(results){
  121.                 var appendString = "";
  122.  
  123.                 for (var i = 0; i < results.length; i++){
  124.                     appendString += "<option value = '" + results[i].id + "' " +
  125.             "id = 'county_client" + results[i].id +
  126.                         "' data-parentorg = '" + results[i].parentorg + "'>" +
  127.             results[i].name + "</option>";
  128.                 }
  129.  
  130.                 thisObj._clientSelect
  131.                     .empty()
  132.                     .append(appendString);
  133.  
  134.             }
  135.         })
  136.     }
  137.  
  138.     //autocomplete search handler, returns results only after 3 letters input
  139.     //An arrow up or down, or enter press highlights the selected county on the map
  140.     var countySearchHandler = function(e){
  141.  
  142.         if (thisObj._tooltip.open)
  143.             closeTooltipHandler();
  144.  
  145.         if (thisObj._currentCounty.id != null)
  146.             mapMouseOut({id : thisObj._currentCounty.id});
  147.        
  148.         if ($(this).val().length > 3){
  149.  
  150.             var key = $(this).val();
  151.  
  152.             for (var i = 0; i < thisObj._countySearchArray.length; i++){
  153.                 if ((thisObj._countySearchArray[i].name + " " +
  154.             thisObj._countySearchArray[i].state) == key){
  155.  
  156.                     //store previous county's id and fill color
  157.                     thisObj._previousCounty.id = thisObj._currentCounty.id;
  158.                     thisObj._previousCounty.color = rgb2hex($("#" +
  159.             thisObj._previousCounty.id).css("fill"));
  160.  
  161.                     //get the current id
  162.                     thisObj._currentCounty.id = thisObj._countySearchArray[i].id;
  163.                     thisObj._currentCounty.color = rgb2hex($("#" +
  164.             thisObj._currentCounty.id).css("fill"));
  165.                     break;
  166.                
  167.                 }
  168.             }
  169.            
  170.             //highlight on enter, up and down key presses
  171.             if (e.which == 13 || e.which == 38 || e.which == 40) {
  172.  
  173.                 if (thisObj._previousCounty.color != "#00000") {
  174.                     d3.selectAll($("#" + thisObj._previousCounty.id))
  175.                         .style("fill", thisObj._previousCounty.color);
  176.                 }
  177.  
  178.                 d3.selectAll($("#" + thisObj._currentCounty.id))
  179.                     .style("fill", thisObj._fillColors.hover);
  180.             }
  181.         }
  182.     }
  183.  
  184.     //Handles the client selection from the client dropdown list.  A valid result
  185.     //populates the map in red and green counties for market/prospective layout
  186.     var countyClientHandler = function(){
  187.         if ($(this).children(":selected").val() != "-" ){
  188.  
  189.             if (thisObj._tooltip.open)
  190.                 closeTooltipHandler();
  191.  
  192.             var client = thisObj._clientSelect.children(":selected");
  193.  
  194.             thisObj._currentClient.id = parseInt(client.val());
  195.             thisObj._currentClient.name = client.text()
  196.        
  197.             $.ajax({
  198.                 url : "getClientCounties/",
  199.                 type : "POST",
  200.                 data : {"data" :
  201.                     JSON.stringify({
  202.                         "id" : thisObj._currentClient.id
  203.                     })
  204.                 },
  205.                 success : function(results){
  206.                     if (results.success == "true"){
  207.                         showClientMarkets(results.results);
  208.                     } else
  209.                         alert(results.message);
  210.                 }
  211.             })
  212.  
  213.         }
  214.     }
  215.  
  216.     //executes ajax post request to add a new client-county relationship.  Type is 0 for
  217.     //new market, 1 for new prospective market and 2 for remove this client-county relationship
  218.     var marketHandler = function(type){
  219.         $.ajax({
  220.             url : "marketHandler/",
  221.             type : "POST",
  222.             data : {"data" : JSON.stringify({
  223.                                 "client" : thisObj._currentClient.id,
  224.                                 "county" : thisObj._currentCounty.id,
  225.                                 "type" : type
  226.                             })
  227.                     },
  228.             dataType : "json",
  229.             success : function(results){
  230.                 if (results.success == "true"){
  231.  
  232.                 /*
  233.                     console.log("Market handler type: " + type);
  234.  
  235.                     var fillColor = "";
  236.  
  237.                     if (type == 0)
  238.                         fillColor = thisObj._fillColors.market;
  239.  
  240.                     else if (type == 1)
  241.                         fillColor = thisObj._fillColors.prospect;
  242.  
  243.                     else
  244.                         fillColor = thisObj._fillColors.neutral;
  245.  
  246.                     d3.selectAll($("#" + thisObj._currentCounty.id))
  247.                         .style("fill", fillColor);
  248.  
  249.                     closeTooltipHandler();
  250.                 */
  251.                     //hack to get the fill color change to apply.  There is some conflict going
  252.                     //on between the jquery and d3 event handlers.  While the function executes,
  253.                     //the change of the fill is not applied on success.
  254.                     thisObj._clientSelect.trigger("change");
  255.                 } else
  256.                     alert(results.message);
  257.             }
  258.         })
  259.     }
  260.  
  261.  
  262.     //alters the selected client county mappings fill color in regard to their market status
  263.     var showClientMarkets = function(results){
  264.  
  265.         d3.selectAll("path")
  266.             .style("fill", "gray");
  267.  
  268.         for (var i = 0; i < results.length; i++){
  269.            
  270.             if (results[i].market == 1) {
  271.                 d3.selectAll($("#" + results[i].fips))
  272.                     .style("fill", thisObj._fillColors.market);
  273.             }
  274.  
  275.             if (results[i].prospect == 1){
  276.                 d3.selectAll($("#" + results[i].fips))
  277.                     .style("fill", thisObj._fillColors.prospect);
  278.             }
  279.         }
  280.     }
  281.  
  282.     var closeTooltipHandler = function(){
  283.         d3.selectAll($("#" + thisObj._tooltip.county))
  284.             .style("fill", thisObj._currentCounty.color);
  285.  
  286.         closeTooltip();
  287.         d3.select(thisObj._mapElement.id).on("click", mapClick);
  288.         thisObj._tooltip.open = false;
  289.     }
  290.  
  291.     //handles the zoom effect of a double click event.
  292.     var mapZoom = function(d){
  293.         var x, y, k;
  294.  
  295.         closeTooltipHandler();
  296.  
  297.         d3.event.stopPropagation()
  298.  
  299.         if (d && thisObj._mapElement.centered !== d && !thisObj._mapElement.clicked){
  300.             thisObj._tooltip.tooltip.transition()
  301.                 .duration(500)
  302.                 .style("opacity", 0)
  303.                 .style("pointer-events", "none");
  304.  
  305.             var centroid = thisObj._mapElement.path.centroid(d);
  306.             x = centroid[0];
  307.             y = centroid[1];
  308.             k = thisObj._mapElement.zoom;
  309.             thisObj._mapElement.centered = d;
  310.             thisObj._mapElement.clicked = true;
  311.        
  312.         } else {
  313.  
  314.             x = thisObj._mapElement.width / 2;
  315.             y = thisObj._mapElement.height / 2;
  316.             k = 1;
  317.             thisObj._mapElement.centered = null;
  318.             thisObj._mapElement.clicked = false;
  319.  
  320.             closeTooltip();
  321.         }
  322.  
  323.         thisObj._mapElement.svg.selectAll("path")
  324.             .classed("active", thisObj._mapElement.centered && function(d){
  325.                 return d === thisObj._mapElement.centered;
  326.             });
  327.  
  328.         thisObj._mapElement.svg.transition()
  329.             .duration(1000)
  330.             .attr("transform", "translate(" + thisObj._mapElement.width / 2 + ", " +
  331.         thisObj._mapElement.height / 2 + ")scale(" + k + ")translate(" + -x + "," + -y + ")")
  332.             .style("stroke-width", 5/k + "px");
  333.  
  334.     }
  335.  
  336.     //handles the click event on the map, which brings a button-filled tooltip into view
  337.     var mapClick = function(d){
  338.  
  339.         if (!thisObj._tooltip.open && d != undefined){
  340.  
  341.             d3.event.stopPropagation();
  342.  
  343.             //add tooltip HTML and styles to this element
  344.             thisObj._tooltip.tooltip.html(thisObj._tooltip.template)
  345.                 .style("left", (d3.event.pageX + 10) + "px")
  346.                 .style("top", (d3.event.pageY - 50) + "px")
  347.                 .style("pointer-events" , "auto")
  348.                 .style("width", "400px")
  349.                 .style("height", "150px");
  350.  
  351.             //generate jQuery UI button overlays for the tooltip buttons, and enable
  352.         //or disable as neccessary
  353.             $(".tooltip_button").button();
  354.  
  355.             if (thisObj._currentClient.id == null) {
  356.                 $("#no_client_message").text("No client has been selected");
  357.                 $(".tooltip_button").button("disable");
  358.             }
  359.            
  360.             else {
  361.                 var countyFillColor = rgb2hex($("#" + d.id).css("fill"));
  362.                 if (countyFillColor == thisObj._fillColors.market)
  363.                     $("#add_market").button("disable");
  364.  
  365.                 if (countyFillColor == thisObj._fillColors.prospect)
  366.                     $("#add_prospective_market").button("disable");
  367.             }
  368.  
  369.             //fade tooltip into view
  370.             thisObj._tooltip.tooltip
  371.                 .transition()
  372.                 .delay(300)
  373.                 .duration(500)
  374.                 .style("opacity", 1);
  375.  
  376.             //get county name and state for future use
  377.             thisObj._currentCounty.name = d.name + ", " + d.properties.StateCode
  378.  
  379.             //add in county name and state text
  380.             $(".county_data").text(thisObj._currentCounty.name);
  381.            
  382.             //disable all single click events on this map
  383.             d3.select(thisObj._mapElement.id).on("click", null);
  384.  
  385.             //update state variables.
  386.             thisObj._tooltip.open = true;
  387.             thisObj._tooltip.county = d.id;
  388.         }
  389.     }
  390.  
  391.     //Changes the fill of the current county to highlight its location
  392.     var mapMouseOver = function(d){
  393.  
  394.         if (!thisObj._tooltip.open) {
  395.        
  396.             thisObj._currentCounty.id = d.id;
  397.             thisObj._currentCounty.color = rgb2hex($("#" + d.id).css("fill"));
  398.  
  399.             d3.selectAll($("#" + d.id))
  400.                 .style("fill", thisObj._fillColors.hover);
  401.  
  402.             thisObj._tooltip.tooltip.html(thisObj._tooltip.hoverTemplate)
  403.                 .style("left", (d3.event.pageX + 10) + "px")
  404.                 .style("top", (d3.event.pageY - 50) + "px")
  405.                 .style("pointer-events", "none")
  406.                 .style("width", "150px")
  407.                 .style("height", "50px");
  408.  
  409.             $(".county_data").text(d.name + ", " d.properties.StateCode);
  410.  
  411.             thisObj._tooltip.tooltip.transition()
  412.                 .duration(200)
  413.                 .style("opacity", 1)
  414.  
  415.         }
  416.     }
  417.  
  418.     //Changes the fill of the county to its previous coloration
  419.     var mapMouseOut = function(d){
  420.  
  421.         if (!thisObj._tooltip.open){
  422.  
  423.             d3.selectAll($("#" + d.id))
  424.                 .style("fill", thisObj._currentCounty.color);
  425.  
  426.             closeTooltip();
  427.  
  428.         }
  429.     }
  430.  
  431.     //utility function to close the tooltip
  432.     var closeTooltip = function(){
  433.         thisObj._tooltip.tooltip.transition()
  434.             .duration(200)
  435.             .style("opacity", 0);
  436.  
  437.         thisObj._tooltip.open = false;
  438.     }
  439.  
  440.     //utility function to convert 'rgb(1, 2, 3)' color codes to hexadecimal
  441.     var rgb2hex = function (rgb) {
  442.         if (rgb != undefined) {
  443.             rgb = rgb.match(/^rgba?\((\d+),\s*(\d+),\s*(\d+)(?:,\s*(\d+))?\)$/);
  444.        
  445.             function hex(x) {
  446.                 return ("0" + parseInt(x).toString(16)).slice(-2);
  447.             }
  448.        
  449.             return "#" + hex(rgb[1]) + hex(rgb[2]) + hex(rgb[3]);
  450.         }
  451.  
  452.         return "#00000";
  453.     }
  454.  
  455.     //module initialization and event binder
  456.     var init = function(){
  457.         if (!thisObj._mapElement.loaded){
  458.  
  459.             //initialize client dropdown selection list
  460.             loadClientSelection();
  461.  
  462.             thisObj._mapElement.loaded = true;
  463.  
  464.             thisObj._mapElement.projection = d3.geo.albersUsa()
  465.                 .scale(thisObj._mapElement.scale)
  466.                 .translate([thisObj._mapElement.width / 2, thisObj._mapElement.height / 2]);
  467.  
  468.             thisObj._mapElement.path = d3.geo.path()
  469.                 .projection(thisObj._mapElement.projection);
  470.  
  471.             thisObj._mapElement.svg = d3.select(thisObj._mapElement.id).append("svg")
  472.                 .attr("width", thisObj._mapElement.width)
  473.                 .attr("height", thisObj._mapElement.height);
  474.  
  475.             thisObj._mapElement.svg.append("rect")
  476.                 .attr("class", "county_background")
  477.                 .attr("width", thisObj._mapElement.width)
  478.                 .attr("height", thisObj._mapElement.height)
  479.                 .on("mouseover", closeTooltip);
  480.  
  481.             thisObj._mapElement.svg.append("g");
  482.  
  483.             thisObj._tooltip.tooltip = d3.select("body")
  484.                 .append("div")
  485.                 .attr("class", "tooltip")
  486.                 .style("opacity", 0);
  487.  
  488.             d3.json("/static/js/json/us-counties.json", function(json){
  489.  
  490.                 //inititalize array for autocomplete search
  491.                 initializeCountyArray(json.features);
  492.  
  493.                 thisObj._mapElement.svg.selectAll("path")
  494.                     .data(json.features)
  495.                     .enter().append("path")
  496.                     .attr("d", thisObj._mapElement.path)
  497.                     .attr("class", "states")
  498.                     .attr("id", function(d){
  499.                         return d.id;
  500.                     })
  501.                     .style("fill", thisObj._fillColors.neutral)
  502.                     .style("stroke", "black")
  503.                     .style("stroke-width", "0.5px")
  504.                     .on("click", mapClick)
  505.                     .on("dblclick", mapZoom)
  506.                     .on("mouseover", mapMouseOver)
  507.                     .on("mouseout", mapMouseOut);
  508.             });
  509.            
  510.         }
  511.  
  512.         initializeElements();
  513.         return thisObj;
  514.     }
  515.  
  516.     return {
  517.         init : init
  518.     }
  519. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement