2016-04-29 3 views
0

Я изо всех сил пытаюсь сделать кусок текста интерактивным. Я мог бы сделать другой текст кликабельным, и функция вела себя так, как ожидалось, после нажатия этого текста. Тревожный текст был вложен внутри чего-то, я думаю, именно поэтому он не вел себя так же с .on(). Я добавил id к фрагменту текста, чтобы его было легко выбрать.d3.select() не работает сразу после перехода

Теперь у меня есть кусок кода, который делает текст кликабельным, и все работает так, как должно, - но только при входе в консоль разработчика Chrome! :

d3.select("#patext").on("click", function() {toggleLine();}) 

После этого вводится в Chrome консоли все работает отлично, но в файле index.html он ничего не делает. 'patext' - это идентификатор, который я дал ранее. index.html содержит раздел <style></style> вверху, затем под <body></body>. Внутри тела находятся два <script></script> первых нагрузок d3.js, второй - мой сценарий. Строка d3.select() приведена ниже определения функции toggleLine().

Уже прошли предложения here и here, а мой скрипт находится в теле, а скрипт для загрузки d3 - отдельный для основного скрипта. Есть идеи?

В соответствии с просьбой, вот 80 из первоначальных 240 линий это на основе сценария Босток надеюсь, что я не удалить ничего важного

<!DOCTYPE html> 
<meta charset="utf-8"> 
<style> 

body { 
    font: 10px sans-serif; 
/* background-color: #ffeda0;*/ 
} 
.axis path 
</style> 
<body> 
<script src="//d3js.org/d3.v3.min.js"></script> 
<script> 
var parseDate = d3.time.format("%Y-%m-%d").parse; 
var x = d3.time.scale().range([0, width]); 
var svg = d3.select("body").append("svg") 
    .attr("width", width + margin.left + margin.right) 
d3.csv("myfile.csv", function(error, data) { 
    if (error) throw error; 
    color.domain(d3.keys(data[0]).filter(function(key) { return key !== "date"; })); 
    data.forEach(function(d) { 
    d.date = parseDate(d.date); 
    }); 
    var cities = color.domain().map(function(name) { 
    return { 
     name: name, 
     values: data.map(function(d) { 
     return {date: d.date, temperature: +d[name]}; // plus casts a string '55' to a number 55 
     }) 
    }; 
    }); 

    x.domain(d3.extent(data, function(d) { return d.date; })); 

    y.domain([ 
    d3.min(cities, function(c) { return d3.min(c.values, function(v) { return v.temperature; }); }), 
    d3.max(cities, function(c) { return d3.max(c.values, function(v) { return v.temperature; }); }) 
    ]); 

    svg.append("rect")  // fill it a colour 
    .attr("width", 830) 
    .attr("height", "100%") 
    .attr("fill", "AliceBlue");  

    svg.append("g") 
    .classed("axis x", true) 
    .call(xAxis2); 

    var city = svg.selectAll(".city") 
     .data(cities) 
     .enter().append("g") 
     .attr("class", "city"); 

    city.append("path") 
     .style("stroke", function(d) {return color(d.name); })  
     .attr("class", "line") 
     .attr("id", function(d) {console.log((d.name).slice(0,3));return (d.name).slice(0,3);}) // for click fn below. 

    city.append("text") 
     .datum(function(d) { return {name: d.name, value: d.values[d.values.length - 1]}; }) 
     .style("stroke", function(d) {return color(d.name); }) 
     .transition()  
     .attr("x", 3) 
     .attr("dy", ".35em") 
     .text(function(d) { return d.name; }) 
     .attr("id", function(d) {console.log((d.name).slice(0,2)+"text");return ((d.name).slice(0,2)+"text");}) // for click fn 
}); 

function toggleLine() { 
    var active = gol.active ? false : true, 
       newOpacity = active ? 0 : 1; 
      d3.select("#gol").style("opacity", newOpacity); 
      gol.active = active;} 

document.addEventListener("DOMContentLoaded", function(event) { 
    //... your code 
    d3.select("#patext").on("click", function() {toggleLine();}); 
    //... more of your code 
}); 
</script> 
</body> 
+1

Вы можете разместить весь свой html-файл, чтобы показать структуру? Я подозреваю, что ваш код выполняется до инициализации DOM. – paradite

+1

Скорее всего, DOM не готов, когда ваш скрипт запускается. Попробуйте поместить его в событие 'DOMContentLoaded'. – JCOC611

+0

Я просто добавил это в нижней части, как вы сказали @ JCOC611: ' 'это вызвало выражение« DOM полностью загружено и проанализировано »для печати в консоли разработчика, но, к сожалению, мой текст не стал доступен для кликов. Просто чтобы проверить, что я не представлял, что я копировал и вставлял эту последнюю строку в консоль, и нажал кнопку ввода, и он был кликабельным и функциональным, как описано выше. – cardamom

ответ

1

Оказывается, там был transition и задерживает DOM манипуляции, что делает привязка прослушивателя событий до создания элемента DOM.

A transition is a special type of selection where the operators apply smoothly over time rather than instantaneously. You derive a transition from a selection using the transition operator. While transitions generally support the same operators as selections (such as attr and style), not all operators are supported; for example, you must append elements before a transition starts. A remove operator is provided for convenient removal of elements when the transition ends.

Решение состоит в том, чтобы связать click слушателя, прежде чем transition().

<body> 
 
    <script src="//d3js.org/d3.v3.min.js"></script> 
 
    <script> 
 

 
    function toggleLine() { 
 
     var active = gol.active ? false : true, 
 
     newOpacity = active ? 0 : 1; 
 
     d3.select("#gol").style("opacity", newOpacity); 
 
     gol.active = active; 
 
    } 
 

 
    document.addEventListener("DOMContentLoaded", function(event) { 
 
     var parseDate = d3.time.format("%Y-%m-%d").parse; 
 
     var x = d3.time.scale().range([0, width]); 
 
     var svg = d3.select("body").append("svg") 
 
     .attr("width", width + margin.left + margin.right) 
 
     d3.csv("myfile.csv", function(error, data) { 
 
     if (error) throw error; 
 
     // ... 
 

 
     city.append("text") 
 
      .datum(function(d) { 
 
      return { 
 
       name: d.name, 
 
       value: d.values[d.values.length - 1] 
 
      }; 
 
      }) 
 
      .attr("id", function(d) { 
 
      console.log((d.name).slice(0, 2) + "text"); 
 
      return ((d.name).slice(0, 2) + "text"); 
 
      }); // for click fn 
 
      // bind listener before transition 
 
      .on("click", function(d){ 
 
       if(d3.select(this).attr('id') === "patext") { 
 
       toggleLine(); 
 
      } 
 
      .style("stroke", function(d) { 
 
      return color(d.name); 
 
      }) 
 
      .transition() 
 
      .attr("x", 3) 
 
      .attr("dy", ".35em") 
 
      .text(function(d) { 
 
      return d.name; 
 
      }) 
 
     }); 
 

 
    }); 
 
    </script> 
 
</body>

Это позволяет ваш код, который будет выполняться после того, как DOM полностью загружена.

Для получения дополнительной информации см. $(document).ready equivalent without jQuery.

+0

Спасибо @paradite Я скопировал и вставил ** точно **, что у вас выше над двумя последними строками моего файла, которые являются закрывающими тегами '' и запускали его. Не генерировал никаких сообщений об ошибках, но текст печально не был доступен. Затем вставили одну строку в консоль браузера и нажали кнопку ввода, и все было хорошо. Вы проверите свою ссылку сейчас. – cardamom

+0

Спасибо, что функция 'toggleLine()' 'должна находиться внутри этой упаковки' DOMContentLoaded'? Я переместил 'd3.select (" # patext "). On (" click ", function() {toggleLine();});' к строке сразу под 'd3.csv()' – cardamom

+0

@cardamom вы можете 't переместить 'd3.select (" # patext "). on (" click ", function() {toggleLine();});' непосредственно под 'd3.csv()', потому что элемент '# patext' еще не находится внутри DOM. Вы должны использовать его прямо в конце блока 'd3.vsv()', как показано выше. – paradite

Смежные вопросы