2015-08-09 17 views

cevap

40

elm-lang/dom pakette focus fonksiyonu (herhangi bir port s veya JavaScript kullanmadan) bir Task ile odak ayarlamak için kullanılır.

Dahili olarak, hedeflenecek DOM düğümünü bulmaya çalışmadan önce yeni DOM güncellemelerinin oluşturulmasını sağlamak için requestAnimationFrame'u kullanır.

bir örnek kullanım:

type Msg 
    = FocusOn String 
    | FocusResult (Result Dom.Error()) 

update : Msg -> Model -> (Model, Cmd Msg) 
update msg model = 
    case msg of 
     FocusOn id -> 
      (model, Dom.focus id |> Task.attempt FocusResult) 

     FocusResult result -> 
      -- handle success or failure here 
      case result of 
       Err (Dom.NotFound id) -> 
        -- unable to find dom 'id' 
       Ok() -> 
        -- successfully focus the dom 

Full example on Ellie

+0

Not Bu * * does iş, ama eleman dinamik eklenirse o sessizce beklenmedik zamanlarda başarısız olabilir bulundu. – AdrianoFerrari

+0

Bunun başarısız olduğu bir örneğiniz var mı? – robertjlooby

+0

Maalesef, şu anda tekrarlanabilir bir örneğim yok. Başka bir tane bulursam gönderirim. Genel olarak, bu kesinlikle bunu yapmak için doğru bir yoldur, bu yüzden belirli bir durum bulana kadar yorumumun göz ardı edilmesi gerekir :) – AdrianoFerrari

4

Son zamanlarda bunu keşfetmek için epey zaman harcadım. Ne yazık ki, mevcut elm-html kütüphanesi ile mümkün olduğunu düşünmüyorum. Bununla birlikte, bir olayı tetiklemek ve bunu saf js içine gömmek için css animasyonlarını kullanan bir korsanla karşılaştım.

Elm'deki bir kesmek, script düğümünü ve style düğümünü kullanıyor. Benim düşüncem çok çirkin. Bunun için

import Html exposing (div, button, text, input, node) 
import Html.Events exposing (onClick) 
import Html.Attributes exposing (type', class) 
import StartApp.Simple 

main = 
    StartApp.Simple.start { model = model, view = view, update = update } 

model = [] 

view address model = 
    -- View now starts with a <style> and <script> (hacky) 
    (node "style" [] [ Html.text style ]) :: 
    (node "script" [] [Html.text script ]) :: 
    (button [ onClick address AddInput ] [ text "Add Input" ]) :: 
    model |> 
    div []  

type Action = AddInput 

update action model = 
    case action of 
    AddInput -> (Html.p [] [input [type' "text", class "focus"] []]) :: model 

-- Use pure string css (hacky) 

style = """ 
.focus { 
    animation-name: set-focus; 
    animation-duration: 0.001s; 
    -webkit-animation-name: set-focus; 
    -webkit-animation-duration: 0.001s; 
} 
@-webkit-keyframes set-focus { 
    0% {color: #fff} 
} 
@keyframes set-focus { 
    0% {color: #fff} 
} 
""" 

-- Cheating by embedding pure javascript... (hacky) 

script = """ 
var insertListener = function(event){ 
if (event.animationName == "set-focus") { 
    event.target.focus(); 
}    
} 
document.addEventListener("animationstart", insertListener, false); // standard + firefox 
document.addEventListener("MSAnimationStart", insertListener, false); // IE 
document.addEventListener("webkitAnimationStart", insertListener, false); // Chrome + Safari 
""" 
9

bir geçici çözüm Mutation Observers kullanmaktır. Ana HTML sayfasına veya Elm kodun temel görünümünde ya bu JavaScript ekleyin:

var observer = new MutationObserver(function(mutations) { 
    mutations.forEach(function(mutation) { 
    handleAutofocus(mutation.addedNodes); 
    }); 
}); 
var target = document.querySelector('body > div'); 
var config = { childList: true, subtree: true }; 
observer.observe(target, config); 

function handleAutofocus(nodeList) { 
    for (var i = 0; i < nodeList.length; i++) { 
    var node = nodeList[i]; 
    if (node instanceof Element && node.hasAttribute('data-autofocus')) { 
     node.focus(); 
     break; 
    } else { 
     handleAutofocus(node.childNodes); 
    } 
    } 
} 

Sonra Html.Attributes.attribute "data-autofocus" "" dahil ederek HTML öğelerini oluşturmak.

İlgili konular