<commit_before>/* Copyright 2015 Bloomberg Finance L.P.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

define(["widgets/js/manager", "widgets/js/widget", "d3", "d3topojson", "./Figure", "base/js/utils", "./MapData", "less!./worldmap"], function(WidgetManager, Widget, d3, topojson, FigureView, utils, mapdata) {

    var world = mapdata.world;
    var countries = mapdata.countries;

    function cloneAll(selector) {
        var nodes = d3.selectAll(selector);
        nodes.each(function(d, i) {
            nodes[0][i] = (this.cloneNode(true));
        });
        return nodes;
    }

    var baseFigure = FigureView[0];

    var Map = baseFigure.extend({

        render: function() {
            this.map_id = utils.uuid();
            this.margin = this.model.get("fig_margin");
            this.enable_hover = this.model.get("enable_hover");
            this.hover_fill = this.model.get("hover_fill");
            this.stroke_color = this.model.get("stroke_color");
            this.map_color = this.model.get("color");
            this.x_offset = (this.options.x) ? this.options.x : 0;
            this.y_offset = (this.options.y) ? this.options.y : 0;

            this.margin.left += this.x_offset;
            this.margin.top += this.y_offset;

            this.def_wt = this.options.width;
            this.def_ht = this.options.height;

            this.title = this.model.get("title");
            this.width = this.model.get("min_width") - this.margin.left - this.margin.right;
            this.height = this.model.get("min_height") - this.margin.top - this.margin.bottom;

            this.$el.css({"flex-grow": "1",
                          "flex-shrink": "1",
                          "align-self": "stretch",
                          "min-width": this.width,
                          "min-height": this.height});

            var that = this;

            this.fmt = d3.format(this.model.get("tooltip_format"));

            var scales = this.model.get("color_scale");
            this.color_data = this.model.get("color_data");

            if (!this.is_object_empty(that.color_data)){

                that.create_child_view(scales).then(function(view) {
                    that.color_scale = view;
                    var z_data = Object.keys(that.color_data).map(function (d) {
                        return that.color_data[d];
                    });

                    if (that.color_scale) {
                        that.color_scale.compute_and_set_domain(z_data, 0);
                        that.color_scale.set_range();
                        that.color_scale.on("color_scale_range_changed", function() {
                                that.color_change(that)
                        }, that);

                        //TODO: I am forcing the map to update colors by
                        //calling the function below after the color scale is
                        //created. Bad way to do this. See if the draw can be
                        //called in the resolve handler.
                        that.color_change(that);
                    }
                    // Trigger the displayed event of the child view.
                    that.after_displayed(function() {
                        view.trigger("displayed");
                    });

                });
            }

            $('#world_tooltip #'+this.map_id).remove();
            this.draw_map();
            this.update_layout();
            this.create_listeners();
            this.create_tooltip_widget(this);

        },
        create_tooltip_widget: function(self) {
            this.tooltip_widget = this.model.get("tooltip_widget");

            if (self.tooltip_view) {
                self.tooltip_view.remove();
            }

            if(this.tooltip_widget) {
                var tooltip_widget_creation_promise = this.create_child_view(this.tooltip_widget);
                tooltip_widget_creation_promise.then(function(view) {
                    self.tooltip_view = view;
                    self.tooltip_div.node().appendChild(d3.select(view.el).node());
                });
            }
        },
        remove_map: function(that) {
            $('.world_map .'+that.map_id).remove();
            //$('#world_tooltip').remove();
            $('.world_viewbox .'+that.map_id).remove();
            $('.'+that.map_id).remove();
        },
        draw_map: function() {

            var that = this;
            var w = this.width;
            var h = this.height;

            //Define default path generator
			var path = d3.geo.path();
			var projection = d3.geo.mercator().center([0,60]).scale(190);
			path = path.projection(projection);

			this.svg = d3.select(this.el)

            this.svg.attr("viewBox", "0 0 "+ this.width +' '+ this.height);

            this.svg_over = d3.select(this.el).append("svg")
                .attr("viewBox", "0 0 1075 750")
                .attr("width", "100%")
                .attr("class", "world_viewbox "+this.map_id)
                .on("click", function(d) { that.ocean_clicked(that); });

            if (this.model.get("axis")!=null){
                this.svg_over.attr("height", "85%");

                that.ax_g = this.svg.append("g")
                                    .attr("class", "color_axis "+this.map_id)

                this.create_child_view(this.model.get("axis")).then(function(view) {
                    that.axes_view = view;
                    that.ax_g.node().appendChild(view.el.node());

                that.after_displayed(function() {
                        view.trigger("displayed");
                    });
                });
            }
            else {
                this.svg_over.attr("height", "100%");
            }

            this.transformed_g = this.svg_over.append("g")
                                              .attr("class", "world_map "+this.map_id);

            this.fill_g = this.transformed_g.append("g");
            this.highlight_g = this.transformed_g.append("g");
            this.stroke_g = this.transformed_g.append("g");

            if ($('#world_tooltip').length===0) {
                this.tooltip_div = d3.select("body").append("div")
                .attr("id", "world_tooltip "+this.map_id)
                .style("pointer-events", "none")
                .style("z-index", 1001);
            } else {
                this.tooltip_div = d3.select('#world_tooltip #'+this.map_id)
            }

            //Bind data and create one path per GeoJSON feature
            this.fill_g.selectAll("path")
			    .data(topojson.feature(world, world.objects.countries).features)
				.enter()
				.append("path")
				.attr("d", path)
				.style("fill", function(d, i) {
                    return that.fill_g_colorfill(d, i, that);
                });

            this.stroke_g.selectAll("path")
			    .data(topojson.feature(world, world.objects.countries).features)
				.enter()
				.append("path")
				.attr("d", path)
                .style("fill-opacity", 0.0)
				.on("mouseover", function(d){
                    if(!that.model.get("enable_hover")){
                        return;
                    }

                    var that2 = this;

                    var select = that.model.get("selected").slice();

                    if((that.model.get("hover_stroke")!="" &&
                        that.model.get("hover_stroke")!=null) &&
                        select.indexOf(d.id)==-1) {
                        that.highlight_g.append(function() {
                            return that2.cloneNode(true)
                        }).style("stroke", that.model.get("hover_stroke"))
                          .classed("hovered", true)
                          .style("stroke-width", that.model.get("hover_stroke_width"));
                    }
                    if((that.model.get("hover_stroke")=="" ||
                        that.model.get("hover_stroke")==null) &&
                        (that.model.get("hover_fill")!="" &&
                        that.model.get("hover_fill")!=null) &&
                        select.indexOf(d.id)==-1) {

                        that.highlight_g.append(function() {
                            return that2.cloneNode(true)
                        }).classed("hovered", true)
                          .style("fill-opacity", 1.0)
                          .style("fill", function() {
                              return that.model.get("hover_fill");
                          });

                    }
                    if((that.model.get("hover_fill")!="" &&
                        that.model.get("hover_fill")!=null) &&
                        (that.model.get("hover_stroke")!="" &&
                        that.model.get("hover_stroke")!=null) &&
                        select.indexOf(d.id)==-1) {

                        that.highlight_g.selectAll(".hovered")
                                        .style("fill-opacity", 1.0)
                                        .style("fill", function() {
                                            return that.model.get("hover_fill");
                                        });
                    }

                })
				.on("mousemove", function(d){
                    if(!that.model.get("enable_hover")) {
                        return;
                    }

					var name;

					for(var i = 0; i< countries.length; i++) {
						if(d.id == countries[i].id){
							name = countries[i].Name;
						}
					};

				    d3.select("#world_tooltip").classed("hidden", false);

                    if (that.model.get("display_tooltip")) {
                        if (that.tooltip_widget) {
                            d3.select("#world_tooltip")
                              .style("background-color", "transparent")
				              .style({"left":(d3.event.x+5)+"px", "top":(d3.event.y-5)+"px", "width":"300px", "height":"200px"});

                    } else {
                            //Update the tooltip position and value

                        if (that.is_object_empty(that.model.get("text_data"))) {
                            if (that.color_data[d.id]!==undefined &&
                                that.color_data[d.id]!==null) {
                                d3.select("#world_tooltip")
                                  .style("background-color", that.model.get("tooltip_color"))
                                  .style("color", that.model.get("text_color"))
				                  .style({"left":(d3.event.x+5)+"px", "top":(d3.event.y-5)+"px"})
				                  .text(name + ": " + that.fmt(that.model.get("color_data")[d.id]));
                            } else {
                                d3.select("#world_tooltip")
                                  .style("background-color", that.model.get("tooltip_color"))
                                  .style("color", that.model.get("text_color"))
				                  .style({"left":(d3.event.x+5)+"px", "top":(d3.event.y-5)+"px"})
				                  .text(name);
                                }
                        } else {
                            d3.select("#world_tooltip")
                              .style("background-color", that.model.get("tooltip_color"))
                              .style("color", that.model.get("text_color"))
				              .style({"left":(d3.event.x+5)+"px", "top":(d3.event.y-5)+"px"});

                            if(that.model.get("text_data")[d.id]!==undefined &&
                                that.model.get("text_data")[d.id]!==null) {
				                d3.select("#world_tooltip")
                                  .text(name + ": " + that.fmt(that.model.get("text_data")[d.id]));
                            } else {
                                d3.select("#world_tooltip")
                                  .text(name);
                            }
                        }
                    }
                }
				    //Show the tooltip

                that.send({event:'hover', country:name, id:d.id});

                })
				.on("mouseout", function(d) {
                    if (!that.model.get("enable_hover")) {
                        return;
                    }

                    d3.select("#world_tooltip").classed("hidden", true);

					d3.select(this).transition().style("fill", function(d, i) {
                        return that.fill_g_colorfill(d, i, that);
                    });

                    d3.select(this).transition()
                      .style("stroke", function(d, i) {
                          return that.hoverfill(d, i, that);
                      });

                    that.highlight_g.selectAll(".hovered").remove();
				})
				.on("click", function(d) {
                    return that.click_highlight(d, this);
                })

            if(that.stroke_color!=null &&
               that.stroke_color!=undefined && that.stroke_color!="") {
                that.stroke_g.selectAll("path")<commit_msg>update to fix tooltip bugs<commit_after>/* Copyright 2015 <NAME>.P.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

define(["widgets/js/manager", "widgets/js/widget", "d3", "d3topojson", "./Figure", "base/js/utils", "./MapData", "less!./worldmap"], function(WidgetManager, Widget, d3, topojson, FigureView, utils, mapdata) {

    var world = mapdata.world;
    var countries = mapdata.countries;

    function cloneAll(selector) {
        var nodes = d3.selectAll(selector);
        nodes.each(function(d, i) {
            nodes[0][i] = (this.cloneNode(true));
        });
        return nodes;
    }

    var baseFigure = FigureView[0];

    var Map = baseFigure.extend({

        render: function() {
            this.map_id = utils.uuid();
            this.margin = this.model.get("fig_margin");
            this.enable_hover = this.model.get("enable_hover");
            this.hover_fill = this.model.get("hover_fill");
            this.stroke_color = this.model.get("stroke_color");
            this.map_color = this.model.get("color");
            this.x_offset = (this.options.x) ? this.options.x : 0;
            this.y_offset = (this.options.y) ? this.options.y : 0;

            this.margin.left += this.x_offset;
            this.margin.top += this.y_offset;

            this.def_wt = this.options.width;
            this.def_ht = this.options.height;

            this.title = this.model.get("title");
            this.width = this.model.get("min_width") - this.margin.left - this.margin.right;
            this.height = this.model.get("min_height") - this.margin.top - this.margin.bottom;

            this.$el.css({"flex-grow": "1",
                          "flex-shrink": "1",
                          "align-self": "stretch",
                          "min-width": this.width,
                          "min-height": this.height});

            var that = this;

            this.fmt = d3.format(this.model.get("tooltip_format"));

            var scales = this.model.get("color_scale");
            this.color_data = this.model.get("color_data");

            if (!this.is_object_empty(that.color_data)){

                that.create_child_view(scales).then(function(view) {
                    that.color_scale = view;
                    var z_data = Object.keys(that.color_data).map(function (d) {
                        return that.color_data[d];
                    });

                    if (that.color_scale) {
                        that.color_scale.compute_and_set_domain(z_data, 0);
                        that.color_scale.set_range();
                        that.color_scale.on("color_scale_range_changed", function() {
                                that.color_change(that)
                        }, that);

                        //TODO: I am forcing the map to update colors by
                        //calling the function below after the color scale is
                        //created. Bad way to do this. See if the draw can be
                        //called in the resolve handler.
                        that.color_change(that);
                    }
                    // Trigger the displayed event of the child view.
                    that.after_displayed(function() {
                        view.trigger("displayed");
                    });

                });
            }

            this.after_displayed(function() {
                d3.select(this.el.parentNode).selectAll('#world_tooltip').remove();
                this.draw_map();
                this.update_layout();
                this.create_listeners();
                this.create_tooltip_widget(this);
            });

        },
        create_tooltip_widget: function(self) {
            this.tooltip_widget = this.model.get("tooltip_widget");

            if (self.tooltip_view) {
                self.tooltip_view.remove();
            }

            if(this.tooltip_widget) {
                var tooltip_widget_creation_promise = this.create_child_view(this.tooltip_widget);
                tooltip_widget_creation_promise.then(function(view) {
                    self.tooltip_view = view;
                    self.tooltip_div.node().appendChild(d3.select(view.el).node());
                });
            }
        },
        remove_map: function(that) {
            $('.world_map .'+that.map_id).remove();
            $('.world_viewbox .'+that.map_id).remove();
            $('.'+that.map_id).remove();
        },
        draw_map: function() {

            var that = this;
            var w = this.width;
            var h = this.height;

            //Define default path generator
			var path = d3.geo.path();
			var projection = d3.geo.mercator().center([0,60]).scale(190);
			path = path.projection(projection);

			this.svg = d3.select(this.el)

            this.svg.attr("viewBox", "0 0 "+ this.width +' '+ this.height);

            this.svg_over = d3.select(this.el).append("svg")
                .attr("viewBox", "0 0 1075 750")
                .attr("width", "100%")
                .attr("class", "world_viewbox "+this.map_id)
                .on("click", function(d) { that.ocean_clicked(that); });

            if (this.model.get("axis")!=null){
                this.svg_over.attr("height", "85%");

                that.ax_g = this.svg.append("g")
                                    .attr("class", "color_axis "+this.map_id)

                this.create_child_view(this.model.get("axis")).then(function(view) {
                    that.axes_view = view;
                    that.ax_g.node().appendChild(view.el.node());

                that.after_displayed(function() {
                        view.trigger("displayed");
                    });
                });
            }
            else {
                this.svg_over.attr("height", "100%");
            }

            this.transformed_g = this.svg_over.append("g")
                                              .attr("class", "world_map "+this.map_id);

            this.fill_g = this.transformed_g.append("g");
            this.highlight_g = this.transformed_g.append("g");
            this.stroke_g = this.transformed_g.append("g");

            if (!this.tooltip_div) {
                this.tooltip_div = d3.select(this.el.parentNode).append("div")
                .attr("id", "world_tooltip")
                .style("pointer-events", "none")
                .style("z-index", 1001)
                .classed("hidden", true);
            } else {
                this.tooltip_div = d3.select(this.el.parentNode)
                                     .select('#world_tooltip')
            }

            //Bind data and create one path per GeoJSON feature
            this.fill_g.selectAll("path")
			    .data(topojson.feature(world, world.objects.countries).features)
				.enter()
				.append("path")
				.attr("d", path)
				.style("fill", function(d, i) {
                    return that.fill_g_colorfill(d, i, that);
                });

            this.stroke_g.selectAll("path")
			    .data(topojson.feature(world, world.objects.countries).features)
				.enter()
				.append("path")
				.attr("d", path)
                .style("fill-opacity", 0.0)
				.on("mouseover", function(d){
                    if(!that.model.get("enable_hover")){
                        return;
                    }

                    var that2 = this;

                    var select = that.model.get("selected").slice();

                    if((that.model.get("hover_stroke")!="" &&
                        that.model.get("hover_stroke")!=null) &&
                        select.indexOf(d.id)==-1) {
                        that.highlight_g.append(function() {
                            return that2.cloneNode(true)
                        }).style("stroke", that.model.get("hover_stroke"))
                          .classed("hovered", true)
                          .style("stroke-width", that.model.get("hover_stroke_width"));
                    }
                    if((that.model.get("hover_stroke")=="" ||
                        that.model.get("hover_stroke")==null) &&
                        (that.model.get("hover_fill")!="" &&
                        that.model.get("hover_fill")!=null) &&
                        select.indexOf(d.id)==-1) {

                        that.highlight_g.append(function() {
                            return that2.cloneNode(true)
                        }).classed("hovered", true)
                          .style("fill-opacity", 1.0)
                          .style("fill", function() {
                              return that.model.get("hover_fill");
                          });

                    }
                    if((that.model.get("hover_fill")!="" &&
                        that.model.get("hover_fill")!=null) &&
                        (that.model.get("hover_stroke")!="" &&
                        that.model.get("hover_stroke")!=null) &&
                        select.indexOf(d.id)==-1) {

                        that.highlight_g.selectAll(".hovered")
                                        .style("fill-opacity", 1.0)
                                        .style("fill", function() {
                                            return that.model.get("hover_fill");
                                        });
                    }

                })
				.on("mousemove", function(d){
                    if(!that.model.get("enable_hover")) {
                        return;
                    }

					var name;

					for(var i = 0; i< countries.length; i++) {
						if(d.id == countries[i].id){
							name = countries[i].Name;
						}
					};

                    var mouse_pos = d3.mouse(that.el);

				    d3.select(that.el.parentNode).select("#world_tooltip").classed("hidden", false);

                    if (that.model.get("display_tooltip")) {
                        if (that.tooltip_widget) {
                            d3.select(that.el.parentNode)
                              .select("#world_tooltip")
                              .style("background-color", "transparent")
				              .style({"left":(mouse_pos[0] + that.el.offsetLeft + 5) + "px", "top":(mouse_pos[1] + that.el.offsetTop + 5) + "px", "width":"300px", "height":"200px"});

                    } else {
                            //Update the tooltip position and value

                        if (that.is_object_empty(that.model.get("text_data"))) {
                            if (that.color_data[d.id]!==undefined &&
                                that.color_data[d.id]!==null) {
                                d3.select(that.el.parentNode)
                                  .select("#world_tooltip")
                                  .style("background-color", that.model.get("tooltip_color"))
                                  .style("color", that.model.get("text_color"))
                                  .style({"left":(mouse_pos[0] + that.el.offsetLeft + 5) + "px", "top":(mouse_pos[1] + that.el.offsetTop + 5) + "px"})
				                  .text(name + ": " + that.fmt(that.model.get("color_data")[d.id]));
                            } else {
                                d3.select(that.el.parentNode)
                                  .select("#world_tooltip")
                                  .style("background-color", that.model.get("tooltip_color"))
                                  .style("color", that.model.get("text_color"))
				                  .style({"left":(mouse_pos[0] + that.el.offsetLeft + 5) + "px", "top":(mouse_pos[1] + that.el.offsetTop + 5) + "px"})
				                  .text(name);
                                }
                        } else {
                            d3.select(that.el.parentNode)
                              .select("#world_tooltip")
                              .style("background-color", that.model.get("tooltip_color"))
                              .style("color", that.model.get("text_color"))
				              .style({"left":(mouse_pos[0] + that.el.offsetLeft + 5) + "px", "top":(mouse_pos[1] + that.el.offsetTop + 5) + "px"})

                            if(that.model.get("text_data")[d.id]!==undefined &&
                                that.model.get("text_data")[d.id]!==null) {
				                d3.select(that.el.parentNode)
                                  .select("#world_tooltip")
                                  .text(name + ": " + that.fmt(that.model.get("text_data")[d.id]));
                            } else {
                                d3.select(that.el.parentNode)
                                  .select("#world_tooltip")
                                  .text(name);
                            }
                        }
                    }
                }
				    //Show the tooltip

                that.send({event:'hover', country:name, id:d.id});

                })
				.on("mouseout", function(d) {
                    if (!that.model.get("enable_hover")) {
                        return;
                    }

                    d3.select(that.el.parentNode)
                      .select("#world_tooltip").classed("hidden", true);

					d3.select(this).transition().style("fill", function(d, i) {
                        return that.fill_g_colorfill(d, i, that);
                    });

                    d3.select(this).transition()
                      .style("stroke", function(d, i) {
                          return that.hoverfill(d, i, that);
                      });

                    that.highlight_g.selectAll(".hovered").remove();
				})
				.on("click", function(d) {
                    return that.click_highlight(d, this);
                })

            if(that.stroke_color!=null &&
               that.stroke_color!=undefined && that.stroke_color!="") {
                that.stroke_g.selectAll("path")
{'fraction_non_alphanumeric': 0.1403477261297507, 'fraction_numerical': 0.007364034772612975, 'mean_word_length': 1.3158639048332086, 'pattern_counts': {'":': 34, '<': 6, '<?xml version=': 0, '>': 4, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 34, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4593203', 'n_tokens_mistral': 7959, 'n_tokens_neox': 7248, 'n_words': 1159}