Как я могу отправить сообщение, когда я перетаскиваю элемент

У меня есть довольно простое приложение elm

https://github.com/chrisortman/team-player

Я не могу понять, как реализовать что-то, что позволило бы мне щелкнуть ячейку таблицы и перетащить несколько других ячеек, чтобы выбрать их.

Кажется, что onMouseOver - это то, что я хотел бы, но я не уверен, как совместить это с сигналом Mouse.isDown. Я могу комбинировать Mouse.isDown и Mouse.position, но тогда я не знаю, как привязать позицию к ячейке таблицы.

Я думаю, что эта идея приближает меня...

import Mouse
import Html exposing(..)
import Html.Attributes exposing(style)
import Html.Events exposing(onMouseOver,onClick)
import Signal exposing(..)

positionWithButton2 = 
  Signal.map3 (,,) Mouse.isDown Mouse.position mouseEvents.signal
  |> Signal.filterMap positionIfDown (0,0)

--positionWithButton = 
--  Signal.map2 (,) Mouse.isDown Mouse.position
--  |> Signal.map positionIfDown

font : List (String, String)
font =
    [ ("font-family", "futura, sans-serif")
    , ("color", "red")
    , ("font-size", "2em")
    ]

type ElementAction 
  = Hover Int
  | NoHover

mouseEvents = Signal.mailbox NoHover

background : List (String, String)
background =
    [ ("background-color", "rgb(245, 245, 245)")
    ]

positionIfDown (isDown,position,hover) =
  case (isDown,hover) of
  (True, Hover x) -> Just (x,x)
  (True, NoHover) -> Just position
  (False, Hover x) -> Just position
  _ -> Nothing


view pos =
  div [ ] 
    [ p [ style (font ++ background)] [text (toString pos)]
    , h1 [onMouseOver mouseEvents.address (Hover 10)]
        [text "Magic"]
    , Html.button
        [ onClick mouseEvents.address NoHover]
        [text "Stop"]
    ]

main : Signal Html
main =
  Signal.map view positionWithButton2

elm
person chrisortman    schedule 24.10.2015    source источник


Ответы (1)


Боюсь, вам придется заняться чем-то более сложным.

Прежде чем даже пытаться использовать версию elm, мы должны действительно подумать о событиях javascript, которые будут срабатывать, когда пользователь пытается перетащить несколько ячеек.

___________________
|(0,1)|(1,1)|(2,1)|
|_____|_____|_____| 
|(0,0)|(1,0)|(2,0)|
|_____|_____|_____|

Допустим, кто-то начинает перетаскивать из ячейки (1,1). Мы получим начальное событие mousedown, а затем начнем получать события mousemove. Что происходит, когда мы продолжаем перетаскивать, скажем, в ячейку (1,2)? Что ж, (1,2) не будет получать событие "щелчок" или "нажатие мыши", но mouseenter и mouseover будут срабатывать, а mousemove должно продолжать срабатывать, и я думаю Атрибут target изменится на ячейку (1,2).

Итак, что нам нужно сделать, чтобы выяснить, что выделено в вязовой земле? К счастью, я вижу, что вы уже используете elm-html — нам придется довольно активно использовать его часть Events.

NB Я собрал это без помощи компилятора, поэтому могут быть некоторые ошибки; хотя форма кажется правильной.

Прежде всего, нам понадобится этот фрагмент:

import Json.Decode exposing ((:=), Decoder)
targetId : Decoder String
targetId = ("target" := ("id" := J.string))        

Это декодирует идентификатор целевого элемента из данного события.

Нам понадобится следующее определение события

data Event = SelectStart String
           | SelectContinue String
           | SelectCancel

и почтовый ящик, чтобы отправить их

events : Signal.Mailbox (Event)
events = Signal.mailbox SelectCancel

Каждой ячейке нужно будет указать id, в котором есть информация о координатах (cell-0-1, cell-1-1 и т. д.), и следующие события:

import Html.Events exposing (on)

on 'mousedown' targetId (\id -> Signal.message events.address (SelectStart id))
on 'mousemove' targetId (\id -> Signal.message events.address (SelectContinue id))

Это должно дать вам достаточно информации для определения того, что было выбрано, путем надлежащего реагирования на события, происходящие на events.signal. N.B. Вы также можете добавить к некоторым другим элементам возможность отменить существующий выбор, не начиная другой; Я не совсем уверен, чего вы пытаетесь достичь, хотя :-)

Ваша модель должна иметь поле, которое выглядит примерно так:

type alias SelectRange = ((Int, Int), (Int, Int)) 

type alias Model = {
    selectState : Maybe SelectRange
}

когда мы получаем первое событие SelectStart, мы вычисляем координату из строки id (скажем, это (0,0)) и меняем selectState на Just ((0,0), (0,0)). Затем начинают появляться SelectContinue события; мы будем игнорировать их, пока они все еще ссылаются на (0, 0), но когда они приходят на (0,1); мы проверяем существующее состояние выбора и решаем, что теперь оно должно быть Just ((0,0),(0,1)). Написание функции update в целом сложно (пользователь может перетаскивать в одном направлении, а затем в обратном), но не невозможно.

Предполагая, что выбранные ячейки отображаются иначе, чем невыбранные, мы можем передать selectState функции просмотра, и по мере отображения каждой ячейки она может проверять, выбрана она или нет, и вести себя соответствующим образом.

Я надеюсь, что информации достаточно, чтобы вы начали; если что непонятно, спрашивайте :-)

person grumpyjames    schedule 25.10.2015