combo.ex 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199
  1. defmodule NITRO.Combo do
  2. require NITRO
  3. require Record
  4. def to_list(fld) when is_atom(fld), do: fld
  5. def to_list(fld), do: :unicode.characters_to_list(fld, :unicode)
  6. def new(_name, obj, module, options) do
  7. dom = :proplists.get_value(:dom, options)
  8. feed = :proplists.get_value(:feed, options)
  9. dropDown(obj, dom, module, feed)
  10. end
  11. def proto(NITRO.comboKey(value: :all) = msg), do: keyUp(msg)
  12. def proto(NITRO.comboKey(delegate: []) = msg), do: keyUp(msg)
  13. def proto(NITRO.comboKey(delegate: module) = msg) do
  14. case has_function(module, :keyUp) do
  15. true -> module.keyUp(msg)
  16. false -> keyUp(msg)
  17. end
  18. end
  19. def proto(NITRO.comboSelect(delegate: module) = msg) do
  20. case has_function(module, :select) do
  21. true -> module.select(msg)
  22. false -> :skip
  23. end
  24. end
  25. def keyUp(NITRO.comboKey(value: :all, dom: field0, feed: feed, delegate: module)) do
  26. field = :nitro.to_list(field0)
  27. all = apply(:kvs,:all,[feed])
  28. :nitro.clear(:nitro.atom([:comboContainer, field]))
  29. dropDownList0(all, field, module, feed)
  30. end
  31. def keyUp(NITRO.comboKey(value: value0, dom: field0, feed: feed, delegate: module)) do
  32. value = :string.lowercase(:unicode.characters_to_list(value0, :unicode))
  33. field = :nitro.to_list(field0)
  34. all = apply(:kvs,:all,[feed])
  35. index = index(module)
  36. :nitro.clear(:nitro.atom([:comboContainer, field]))
  37. :nitro.wire("comboLookupChange('#{field0}');")
  38. filtered =
  39. Enum.filter(all, fn x ->
  40. Enum.any?(index, fn i ->
  41. fld0 =
  42. if is_function(i) do
  43. i.(x)
  44. else
  45. f0 = apply(:kvs,:field, [x, i])
  46. tab = elem(x, 0)
  47. if f0 == tab do
  48. :nitro.to_list(f0)
  49. else
  50. f0
  51. end
  52. end
  53. fld = to_list(fld0)
  54. fld != elem(x, 0) and :string.rstr(:string.lowercase(:nitro.to_list(fld)), value) > 0
  55. end)
  56. end)
  57. dropDownList0(filtered, field, module, feed)
  58. end
  59. def dropDownList0(filtered, field, module, feed) do
  60. if has_function(module, :dropDownList) do
  61. module.dropDownList(filtered, field, module, feed)
  62. else
  63. dropDownList(filtered, field, module, feed)
  64. end
  65. end
  66. def dropDownList(filtered, field, module, feed) do
  67. formId = :nitro.atom([field, "form"])
  68. if filtered == [] do
  69. :nitro.wire("activeCombo = undefined; currentItem = undefined;")
  70. :nitro.hide(:nitro.atom([:comboContainer, field]))
  71. :nitro.wire("comboOpenFormById('#{formId}');")
  72. else
  73. :nitro.display(:nitro.atom([:comboContainer, field]), :block)
  74. :nitro.wire("comboCloseFormById('#{formId}');")
  75. end
  76. Enum.each(filtered, fn obj ->
  77. form = dropDown0(obj, field, module, feed)
  78. :nitro.insert_top(
  79. :nitro.atom([:comboContainer, field]),
  80. :nitro.render(form)
  81. )
  82. end)
  83. end
  84. def dropDown0(obj, dom0, module, feed) do
  85. case has_function(module, :dropDown) do
  86. true ->
  87. module.dropDown(obj, dom0, feed)
  88. false ->
  89. dropDown(obj, dom0, module, feed)
  90. end
  91. end
  92. def view_value(obj, _, _) when obj in ["", [], :undefined], do: []
  93. def view_value(obj, module, feed) do
  94. case :erlang.function_exported(module, :view_value, 2) do
  95. true ->
  96. module.view_value(obj, feed)
  97. false ->
  98. if has_function(module, :view_value) do
  99. module.view_value(obj)
  100. else
  101. view_value(obj)
  102. end
  103. end
  104. end
  105. def view_value(obj) when obj in ["", [], :undefined], do: []
  106. def view_value(obj), do: :nitro.jse(:erlang.iolist_to_binary(apply(:kvs,:field,[obj, hd(index([]))])))
  107. def dropDown(obj, dom0, module, feed) do
  108. view_value = view_value(obj, module, feed)
  109. dom = :nitro.to_list(dom0)
  110. id = :nitro.jse(:erlang.iolist_to_binary(:nitro.atom([dom, :erlang.element(2, obj)])))
  111. item = :nitro.to_list(item(obj, module))
  112. source = :erlang.iolist_to_binary(feed)
  113. click = :nitro.jse("comboSelect('#{dom}', '#{view_value}', '#{source}', '#{module}', '#{id}')")
  114. move = :nitro.jse("comboLookupMouseMove('#{dom}')")
  115. NITRO.panel(
  116. id: id,
  117. class: ['dropdown-item'],
  118. bind: :base64.encode(:erlang.term_to_binary(obj)),
  119. onclick: click,
  120. onmousemove: move,
  121. body: [
  122. NITRO.p(body: item)
  123. ]
  124. )
  125. end
  126. def index([]), do: [:name, :id]
  127. def index(module) do
  128. case has_function(module, :index) do
  129. true -> module.index()
  130. false -> index([])
  131. end
  132. end
  133. def item(obj, []), do: view_value(obj)
  134. def item(obj, module) do
  135. case has_function(module, :item) do
  136. true -> module.item(obj)
  137. false -> item(obj, [])
  138. end
  139. end
  140. def update_comboVec(_parent, dom, feed, module, default, elem) do
  141. vector = view_value(default, module, feed)
  142. clear = "createSortable('##{dom}_list');"
  143. append = :lists.map(fn emp -> bind = emp |> :erlang.term_to_binary |> :base64.encode
  144. "appendItemFromBind('#{dom}_list','#{module.cn(emp)}','#{bind}');" end, vector)
  145. |> :erlang.iolist_to_binary
  146. render = :nitro.render elem
  147. command = "elem = qi('#{dom}'); elem.outerHTML = '#{render}';"
  148. :nitro.wire(command <> append <> clear) # reverse
  149. end
  150. def update_combo(id, feed, module), do: :nitro.update(:nitro.atom([:lookup, id]), NITRO.comboLookup(id: id, feed: feed, delegate: module))
  151. def update_combo_value(dom, value, feed, module) do
  152. view_value = view_value(value, module, feed)
  153. update_combo_value(dom, value, feed, module, view_value)
  154. end
  155. def update_combo_value(dom, value, feed, module, view_value) do
  156. bind = :base64.encode(:erlang.term_to_binary(value))
  157. update_combo(dom, feed, module)
  158. command = "elem = qi('#{dom}'); elem.setAttribute('data-bind', '#{bind}'); elem.value = '#{view_value}';"
  159. :nitro.wire(command)
  160. end
  161. def has_function(m, f) do
  162. functions = apply(m, :module_info, [:exports])
  163. isF = Keyword.get(functions, f, -1)
  164. isF != -1
  165. end
  166. end