2016-10-18 14 views
0

こんにちは、ここでは、jQueryコードの問題点を理解しようとしています。コードは地震情報をAPIから引き出してDOMに表示することになっています。問題は、DOMに重複した情報が表示されていることですが、その情報を表示するためにコンソール呼び出しを使用すると、すべて一意になります。DOMにプッシュされるとJSONデータが重複して表示される

HTML:

<div class="control-wrapper"> 
    <h2>Start date: <input type="text" id="datepicker"></h2> 
    <h2>End date: <input type="text" id="datepicker_2"></h2> 
    <button id="generate">Generate</button> 
</div> 

<h2>Total # of EQ's: <span id="total"></span></h2> 
<div class="wrapper" id="template"> 
    <h1>Name: <span id="title"></span></h1> 
    <h3>Magnitued: <span id="mag"></span></h3> 
    <h3>Tsunami Warning: <span id="tsunami"></span></h3> 
</div> 

のjQuery:

$(document).ready(function(){ 
    var scriptString = 'https://earthquake.usgs.gov/fdsnws/event/1/query?format=geojson&starttime='; 
    var button = $('#generate'); 

    /**DATEPICKER**/ 
    var startDate = 0; 
    var endDate = 0; 
    $('#datepicker').datepicker(); 
    $('#datepicker').datepicker('option', 'dateFormat', 'yy-mm-dd'); 
    $('#datepicker_2').datepicker(); 
    $('#datepicker_2').datepicker('option', 'dateFormat', 'yy-mm-dd'); 

    /** GENERATE BUTTON ON CLICK **/ 
    button.on('click', function(){ 
    startDate = $('#datepicker').val(); 
    endDate = $('#datepicker_2').val(); 
    scriptString = scriptString + startDate +'&endtime=' + endDate; 
    makeRequest(scriptString); 
    }); 
}); 

/** MAKEREQUEST EXECUTES AFTER THE GENERATE BUTTON IS CLICKED **/ 
function makeRequest(requestString){ 
    var myRequest; 
    var eqs = []; 

    var myRequest = window.XMLHttpRequest ? new XMLHttpRequest() : new ActiveXObject('Microsoft.XMLHTTP'); 
    myRequest.onreadystatechange = function(){ 
    if(myRequest.readyState === 4 && myRequest.status === 200){ 
     var jsonObj = JSON.parse(myRequest.responseText);//Grabs json object 
     var data = jsonObj.features; 
     pushToDOM(data); 
    } 
    } 
    myRequest.open("GET", requestString, true); 
    myRequest.send(); 
} 

/** RECIEVES ARRAY OF EQS AND PUSHES THE FIRST TO THE DOM **/ 
function pushToDOM(eqs){ 
    var tot = $('#total'); 
    tot.text(eqs.length); 

    /*ADDS EQs TO DOM*/ 
    for(x in eqs){ 
    var wrap = $('.wrapper').clone(); 
    wrap.attr('id', x); 
    var place = eqs[x].properties.place; 
    var mag = eqs[x].properties.mag; 
    var tsu = eqs[x].properties.tsunami; 
    wrap.find('#title').text(place); 
    wrap.find('#mag').text(mag); 
    if(tsu === 0){ 
     wrap.find('#tsunami').text('No'); 
    } 
    else{ 
     wrap.find('#tsunami').text('Yes'); 
    } 
    $('body').delay().append(wrap); 
    if(x === 10){ 
     break; 
    } 
    } 
} 

Codepen

PS:それはそう情報を表示する前にブラウザをロックアップするので、私は、スクリプトを書いた方法が問題のようです私のコード構造やアルゴリズムを改善する方法があれば教えてください。

ありがとうございました!

答えて

3

まず、コードにいくつかの問題があります。時間をかけていくつかのjQueryチュートリアルを実行する必要があります。

今のところ、これらは私が以下で特定し、修正した問題です。

  • jQueryは、常に一致するすべての要素にアクションを適用します。したがって、日付ピッカーを個別に初期化する必要はありません。
  • jQueryはbuilt-in Ajax supportです。手巻きのXmlHttpRequestコードを使用しないでください。特に、一部のWebサイトからコピーしたコードは使用しないでください(これは一般的に真です。理解しにくいコードはコピー&ペーストしないでください)。
  • jQueryがURLを処理します。パラメータのエンコーディングでは、以下のようにパラメータをオブジェクトとして渡すことができます。
  • jQueryはJSON解析を行いますので、問題はありません。
  • HTML要素を複製するときは、属性にidという属性が含まれていないことを確認してください。 IDはドキュメント全体で一意であると考えられ、重複したIDは物を壊します。 CSSクラスを使用して要素のタイプを識別します。
  • ボタンをもう一度クリックすると、以前に追加された要素をすべて削除する必要があります。これは複製の問題を解決します。
  • データの読み込み中にボタンを無効にすると、日付フィールドのデフォルト値が設定されます。
  • $.getJSON()コールに何らかのエラー処理を追加する必要があります(documentation for the jQuery XHR object.fail()の使用方法を参照)。

以下のRunnableのサンプルコード:

$(function() { 
 
    $('.datepicker').datepicker({dateFormat: 'yy-mm-dd'}); 
 
    $('#starttime').datepicker("setDate", "-1d"); 
 
    $('#endtime').datepicker("setDate", "0d"); 
 

 
    $('#generate').on('click', function() { 
 
    $('#generate').text("loading...").prop("disabled", true); 
 
    $('#total').text(""); 
 

 
    $.getJSON('https://earthquake.usgs.gov/fdsnws/event/1/query?format=geojson', { 
 
     starttime: $('#starttime').val(), 
 
     endtime: $('#endtime').val() 
 
    }).done(function (geoJson) { 
 
     $('#total').text(geoJson.features.length); 
 
     $('.earthquake').remove(); 
 

 
     $.each(geoJson.features, function (i, feature) { 
 
     var $item = $('#earthquake-template').clone().removeAttr("id").addClass("earthquake"); 
 

 
     $item.find('.place').text(feature.properties.place); 
 
     $item.find('.tsunami').text(feature.properties.tsunami ? 'Yes' : 'No'); 
 
     $item.find('.mag').text(feature.properties.mag); 
 
     $item.appendTo('body'); 
 
     }); 
 
    }).fail(function (jqXhr, status, error) { 
 
     alert("Could not fetch earthquake info - " + error); 
 
    }).always(function() { 
 
     $('#generate').text('Generate').prop('disabled', false); 
 
    }); 
 
    }); 
 
});
h1, h2, h3 { font-size: small; } 
 
#earthquake-template { display: none; } 
 
.earthquake { border: 1px solid silver; margin-top: 5px; } 
 
div.ui-datepicker { font-size:10px; }
<link href="https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.css" rel="stylesheet"/> 
 
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.0.3/jquery.min.js"></script> 
 
<script src="https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.js"></script> 
 

 
<div class="control-wrapper"> 
 
    <h2>Start date: <input type="text" class="datepicker" id="starttime"></h2> 
 
    <h2>End date: <input type="text" class="datepicker" id="endtime"></h2> 
 
    <button id="generate">Generate</button> 
 
</div> 
 

 
<h2>Total # of EQ's: <span id="total"></span></h2> 
 
<div id="earthquake-template"> 
 
    <h1>Name: <span class="place"></span></h1> 
 
    <h3>Magnitude: <span class="mag"></span></h3> 
 
    <h3>Tsunami Warning: <span class="tsunami"></span></h3> 
 
</div>

+0

は、この答えを書くために時間を割いてありがとうございました。私は間違いなく、あなたのコードを見てからもっとjQueryチュートリアルを進めていきます。しかし、私はあなたの応答で、最初にこの問題の原因を正確に教えてくれる答えは見当たりませんでした。ちょうどひどいコード構造ですか?ありがとうTomalak! – Froy

+0

どの問題?このコードではまだ発生しますか? – Tomalak

+0

提供したコードは正しく動作しません。私が得たアウトプットには重複した地震情報が示され、時には同じ情報で最大4つの地震が示されました。あなたの例は、繰り返されることなく各地震情報を表示します。 – Froy

関連する問題