2017-09-12 3 views
1

2つのイベントハンドラを使用する小さなScala.Jsアプリケーションを作成しています.1つは入力フィールドのonkeyupイベント用で、もう1つはボタンのonclickイベント用です。Scala.jsイベント処理

2つのイベントハンドラは共通のコーディングを共有しますが、イベントハンドラ関数を返す単一の関数にイベントハンドラのコーディングを最適化しようとすると正しくコンパイルされますが、イベントはもはやトラップされませんブラウザ。

mainの次のコードでは、btn.onclickのイベントハンドラは正常に動作しますが、cityNameInput.onkeyupのイベントハンドラは機能しなくなりました。私がしたのは、イベントハンドラに直接割り当てられたコーディングをコピーして、Function1[dom.Event, _]を返すkeystrokeHandlerという関数に入れたものでした。これでOKはコンパイルされますが、onkeyupイベントはブラウザにトラップされなくなりました。

def keystrokeHandler(userInput: String, responseDiv: dom.Element): Function1[dom.Event,_] = 
(e: dom.Event) => { 
    // The city name must be at least 4 characters long 
    if (userInput.length > 3) { 
    responseDiv.innerHTML = "" 

    val xhr = buildXhrRequest(userInput, searchEndpoint) 

    xhr.onload = (e: dom.Event) => { 
     val data: js.Dynamic = js.JSON.parse(xhr.responseText) 

     // Can any cities be found? 
     if (data.count == 0) 
     // Nope, so show error message 
     responseDiv.appendChild(p(s"Cannot find any city names starting with ${userInput}").render) 
     else { 
     // Build a list of weather reports 
     buildSearchList(data, responseDiv) 
     } 
    } 

    // Send XHR request to OpenWeather 
    xhr.send() 
    } 
} 
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
// Main program 
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
@JSExport 
def main(container: dom.html.Div): Unit = { 
    container.innerHTML = "" 

    val cityNameInput = input.render 
    val btn   = button.render 
    val weatherDiv = div.render 

    cityNameInput.defaultValue = owmQueryParams.get("q").get 
    btn.textContent   = "Go" 

    // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
    // Button onclick event handler 
    // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
    btn.onclick = (e: dom.Event) => { 
    if (cityNameInput.value.length > 3) { 
     weatherDiv.innerHTML = "" 

     val xhr = buildXhrRequest(cityNameInput.value, weatherEndpoint) 

     xhr.onload = (e: dom.Event) => { 
     val data = js.JSON.parse(xhr.responseText) 

     // Can the city be found? 
     if (data.cod == "404") 
     // Nope, so show error message 
      weatherDiv.appendChild(p(s"City ${cityNameInput.value} not found").render) 
     else { 
      // So first add the div containing both the weather information 
      // and the empty div that will hold the slippy map. 
      // This is needed because Leaflet writes the map information to an 
      // existing DOM element 
      val report = new WeatherReportBuilder(data) 
      weatherDiv.appendChild(buildWeatherReport(report, 0)) 

      buildSlippyMap("mapDiv0", report) 
     } 
     } 

     // Send XHR request to OpenWeather 
     xhr.send() 
    } 
    } 

    // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
    // Input field onkeyup event handler 
    // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
    cityNameInput.onkeyup = keystrokeHandler(cityNameInput.value, weatherDiv) 

    // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
    // Write HTML to the screen 
    // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
    container.appendChild(
    div(
     h1("Weather Report"), 
     table(
     tr(td("Enter a city name (min 4 characters)"), td(cityNameInput)), 
     tr(td(), td(style := "text-align: right", btn)) 
    ), 
     weatherDiv 
    ).render 
) 
} 

ここで問題は何ですか?

keystrokeHandler関数は、特別なScala.Jsイベントハンドラ型を返す必要がありますか?それとも別のことですか?

おかげ

クリスW

答えて

1

私はこの問題はここにあると思う:

cityNameInput.onkeyup = keystrokeHandler(cityNameInput.value, weatherDiv) 

イベントハンドラがトリガですが、userInputは、ハンドラ時cityNameInput.valueに凍結されていますcityNameInput.valueの現在の値で変化する代わりに、が作成されました。確かに、その行は、それが明らかcityNameInput.valueは一度だけ評価されることになり

val userInput = cityNameInput.value 
cityNameInput.onkeyup = keystrokeHandler(userInput, weatherDiv) 

に相当します。

代わりに、keystrokeHandlerにパラメータとしてcityNameInputを指定し、関数(ハンドラ)が呼び出されるたびに評価されるように、匿名関数内でcityNameInput.valueにアクセスしてください。

+0

ああ、それです。ありがとう –