Проблема присоединения событий JavaScript с использованием вариаций в шаблоне модуля

Я пытаюсь прикрепить события javascript к элементам svg, используя код, который находится внутри "шаблона модуля". Я очень noob в javascript, так как я уверен, это будет видно из кода ниже. Я попытался воссоздать ситуацию, используя гораздо более простую версию кода, который я на самом деле использую. По иронии судьбы, я на самом деле далек от того, чтобы заставить его работать с этим примером, но мой мозг болит от попыток заставить его работать и исследовать другие места на этом сайте. Итак, я обращаюсь ко всем умным людям, чтобы посмотреть, смогут ли они помочь. Проблема, с которой я сталкиваюсь (когда я заставляю ее работать!), Заключается в том, что события javascript не связаны с элементами DOM и просто запускаются при загрузке страницы. Когда я снова запускаю событие (перемещая мышь), я получаю ошибку javascript, вызванную библиотекой D3 "Uncaught TypeError: n.apply не является функцией"

Если кто-то сможет забыть о срочном стремлении воссоздать шаблон модуля и заставить этот пример работать - надеюсь, я смогу включить его в свой реальный код (единственное реальное отличие между примером и реальным кодом состоит в том, что существует множество модулей "расширителя", а не всего, что в одном).

С уважением

<!DOCTYPE html>

<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
    <meta charset="utf-8" />
    <script src="http://d3js.org/d3.v3.min.js" charset="utf-8"></script>
</head>
<body>
    <div id="box1"></div>
    <div id="box2"></div>

    <script>

        function mouseOver(i) {
            return this.targets[i].select("#" + this.targets[i].container).select("circle").attr("fill", "blue");
        }

        function mouseOut(i) {
            return this.targets[i].select("#" + this.targets[i].container).select("circle").attr("fill", "green");
        }

        var example = (function () {

            return {

                addRect: function addRect(container) {
                    this.box = d3.select("#" + container).append("svg");

                    this.rect = this.box.append("rect")
                        .attr({
                            "fill": "red",
                            "width": 50,
                            "height": 50,
                        });

                },

                addCircle: function addControl(targets) {
                    this.targets = targets

                    for (target in this.targets) {
                        tt = this.targets[target]

                        tt.circle = tt.box.append("circle")
                            .attr({
                                "fill": "green",
                                "cx": -10,
                                "cy":-10,
                                "r": 10,
                                "transform": "translate(30,30)"
                            })
                    };
                },

                addControl: function addControl(targets) {
                    this.targets = targets

                    for (target in this.targets) {
                        tt = this.targets[target]

                        tt.control = tt.box.append("rect")
                            .attr({
                                "fill": "none",
                                "width": 50,
                                "height": 50,
                            })
                            .on("mouseover", mouseOver(target))
                            .on("mouseout", mouseOut(target))
                    };  

                },

            };
        })();


        var first = new example.addRect("box1");
        var second = new example.addRect("box2");

        var circs = new example.addCircle([first, second]);
        var controls = new example.addControl([first, second]);


    </script>
</body>
</html>

1 ответ

Решение

Проблема 1:событие запускается при загрузке страницы

Причина:

Ты делаешь

.on("mouseover", mouseOver(target)) //this is wrong the second parameter should have been a function.

что-то вроде этого

.on("mouseover", function(){mouseOver(target)})

Проблема 2:

tt.control = tt.box.append("rect")
                            .attr({
                                "fill": "none",//this should not be none else mouse over will not work as you expect
                                "width": 50,
                                "height": 50,
                            })
                            .on("mouseover", mouseOver(target))
                            .on("mouseout", mouseOut(target))

Это должно быть сделано с непрозрачностью 0, чтобы его не видно

for (target in this.targets) {
            tt = this.targets[target]
            tt.control = tt.box.append("rect")
              .attr({
                "fill": "blue",
                "width": 50,
                "height": 50,
                "opacity": 0
              })

Проблема 3:

Вы можете установить параметр для DOM, а не передавать его в функцию. Что-то вроде этого

  for (target in this.targets) {
    tt = this.targets[target]
    tt.control = tt.box.append("rect")
      .attr({
        "fill": "blue",
        "width": 50,
        "height": 50,
        "opacity": 0
      })

      .on("mouseover", function() {
        mouseOver(tt)
      })
      .on("mouseout", function() {
        mouseOut(tt)
      });
      tt.control.node().dataset = tt;//binding the data to the dom
  };

И в случае мыши получить связанный объект, как это:

function mouseOver(target) {
      //gettting the data from the dom
      event.target.dataset.circle.attr("fill", "blue");
    }

    function mouseOut(target) {
      event.target.dataset.circle.attr("fill", "green");
    }

Рабочий код здесь.

Другие вопросы по тегам