SunRiseGC 3 years ago
parent
commit
453a2a8278
7 changed files with 39 additions and 27 deletions
  1. 2 2
      include/comboLookup.hrl
  2. 0 1
      lib/combo.ex
  3. 17 16
      lib/comboSearch.ex
  4. 1 1
      mix.exs
  5. 8 5
      priv/js/comboLookup.js
  6. 4 0
      src/elements/combo/element_comboLookup.erl
  7. 7 2
      src/nitro_pi.erl

+ 2 - 2
include/comboLookup.hrl

@@ -3,11 +3,11 @@
 
 -include_lib("nitro/include/nitro.hrl").
 
--record(comboKey,    { value=[], dom=[], feed=[], delegate=[]}).
+-record(comboKey,    { uid=[], value=[], dom=[], feed=[], delegate=[]}).
 -record(comboKeyup,  { value=[], dom=[], feed=[], delegate=[]}).
 -record(comboSelect, { value=[], dom=[], feed=[], delegate=[] }).
 -record(comboNext,   { pos=[],  count=[], feed=[]}).
--record(comboScroll, { dom=[], delegate=[] }).
+-record(comboScroll, { uid=[], dom=[], delegate=[] }).
 -record(comboInsert, { dom=[], rows=[], chunks=[], status=[], delegate=[], feed=[] }).
 -record(comboLookup, { ?ELEMENT_BASE(element_comboLookup),
     value=[],

+ 0 - 1
lib/combo.ex

@@ -45,7 +45,6 @@ defmodule NITRO.Combo do
   end
 
   def comboInsert(NITRO.comboInsert(chunks: 0, dom: field, status: :finished)) do
-    NITRO.Combo.Search.stop(field)
     :nitro.wire("activeCombo = undefined; currentItem = undefined;")
     :nitro.hide(:nitro.atom([:comboContainer, :nitro.to_list(field)]))
     :nitro.wire("comboOpenFormById('#{:nitro.atom([:nitro.to_list(field), 'form'])}');")

+ 17 - 16
lib/comboSearch.ex

@@ -2,19 +2,19 @@ defmodule NITRO.Combo.Search do
   require NITRO
   require Record
 
-  Record.defrecord(:state, pid: [], chunks: 0, value: [], reader: [], opts: [], feed: [])
+  Record.defrecord(:state, uid: [], pid: [], chunks: 0, value: [], reader: [], opts: [], feed: [])
 
-  def start(value, field, feed, opts) do
+  def start(uid, value, field, feed, opts) do
     Supervisor.start_link([], strategy: :one_for_one, name: NITRO.Combo.Search)
-    state = state(pid: self(), value: value, reader: :erlang.apply(:kvs, :reader, [feed]), opts: opts, feed: feed)
-    stop(field)
+    state = state(uid: uid, pid: self(), value: value, reader: :erlang.apply(:kvs, :reader, [feed]), opts: opts, feed: feed)
+    stop(uid, field)
     pi =
       NITRO.pi(
         module: NITRO.Combo.Search,
         table: :async,
         sup: NITRO.Combo.Search,
         state: state,
-        name: "#{field}",
+        name: "#{uid}#{field}",
         timeout: :brutal_kill,
         restart: :temporary
       )
@@ -24,38 +24,39 @@ defmodule NITRO.Combo.Search do
     end
   end
 
-  def stop(field) do
-    case :nitro_pi.pid(:async, "#{field}") do
+  def stop(uid, field) do
+    case :nitro_pi.pid(:async, "#{uid}#{field}") do
       [] -> :ok
       pid ->
         :erlang.exit(pid, :kill)
-         try do :nitro_pi.stop(:async, "#{field}") catch _,_ -> :skip end
+         try do :nitro_pi.stop(:async, "#{uid}#{field}") catch _,_ -> :skip end
     end
   end
 
-  def comboScroll(NITRO.comboScroll(dom: field)) do
-    case :nitro_pi.pid(:async, "#{field}") do
+  def comboScroll(NITRO.comboScroll(uid: uid, dom: field)) do
+    case :nitro_pi.pid(:async, "#{uid}#{field}") do
       [] -> []
       pid -> send(pid, {:filterComboValues, :append, []})
     end
   end
 
-  def keyUp(NITRO.comboKey(value: value, dom: field, feed: feed, delegate: module)) do
+  def keyUp(NITRO.comboKey(uid: uid, value: value, dom: field, feed: feed, delegate: module)) do
     opts = [index: NITRO.Combo.index(module), field: field, delegate: module]
     comboContainer = :nitro.atom([:comboContainer, :nitro.to_list(field)])
     :nitro.display(:nitro.atom([:comboContainer, field]), :block)
     :nitro.clear(comboContainer)
     :nitro.wire("comboCloseFormById('#{:nitro.atom([:nitro.to_list(field), 'form'])}');")
     :nitro.wire("comboLookupChange('#{field}');")
-    :nitro.wire(NITRO.bind(target: :nitro.to_binary(comboContainer), type: :scroll, postback: onscroll(field, module)))
-    start(value, field, feed, opts)
+    :nitro.wire(NITRO.bind(target: :nitro.to_binary(comboContainer), type: :scroll, postback: onscroll(uid, field, module)))
+    start(uid, value, field, feed, opts)
   end
 
-  def onscroll(field, delegate), do:
+  def onscroll(uid, field, delegate), do:
     :erlang.iolist_to_binary([
       "if (event.target && (event.target.scrollTop + event.target.offsetHeight + 10 >= event.target.scrollHeight)) {",
         "ws.send(enc(tuple(atom('direct'),
          tuple(atom('comboScroll'),",
+            "bin('#{uid}'),",
             "bin('#{field}'),",
             "atom('#{delegate}'))",
         ")));",
@@ -65,7 +66,7 @@ defmodule NITRO.Combo.Search do
   def proc(:init, NITRO.pi() = pi), do: {:ok, pi}
 
   def proc({:filterComboValues, cmd, value0}, NITRO.pi(state: state(chunks: chunks) = st) = pi) do
-    state(feed: feed, reader: r, value: prev, pid: pid, opts: opts) = st
+    state(uid: uid, feed: feed, reader: r, value: prev, pid: pid, opts: opts) = st
     m = Keyword.get(opts, :delegate, [])
     field = Keyword.get(opts, :field, [])
     value = case cmd do :append -> prev; _ -> :string.lowercase(:unicode.characters_to_list(value0, :unicode)) end
@@ -84,7 +85,7 @@ defmodule NITRO.Combo.Search do
         newChunks = chunks + length(filtered)
         send(pid, {:direct, NITRO.comboInsert(dom: field, delegate: m, chunks: newChunks, feed: feed, rows: filtered)})
         chunks < 100 and
-          case :nitro_pi.pid(:async, "#{field}") do [] -> []; pid -> send(pid, {:filterComboValues, cmd, value0}) end
+          case :nitro_pi.pid(:async, "#{uid}#{field}") do [] -> []; pid -> send(pid, {:filterComboValues, cmd, value0}) end
         {:noreply, NITRO.pi(pi, state: state(st, value: value, chunks: newChunks, reader: :erlang.apply(:kvs, :setfield, [r1, :args, []])))}
     end
   end

+ 1 - 1
mix.exs

@@ -4,7 +4,7 @@ defmodule NITRO.Mixfile do
   def project do
     [
       app: :nitro,
-      version: "6.11.8",
+      version: "6.11.9",
       description: "NITRO Nitrogen Web Framework",
       package: package(),
       deps: deps()

+ 8 - 5
priv/js/comboLookup.js

@@ -70,7 +70,7 @@ function comboLookupChange(dom) {
   }
 }
 
-function comboLookupClick(dom, feed, mod) {
+function comboLookupClick(uid, dom, feed, mod) {
   var dropdown = qi(dom).closest('.dropdown');
   var char = event.which || event.keyCode;
   if (char ==  1 && !activeCombo && qi(dom).value == '') {
@@ -80,7 +80,8 @@ function comboLookupClick(dom, feed, mod) {
     if (window.innerHeight - dropdown.getBoundingClientRect().bottom < 100)
       dropdown.classList.add('is-reversed');
     direct(tuple(atom('comboKey'),
-                atom('all'),
+                bin(uid),
+                bin('all'),
                 string(dom),
                 string(feed),
                 atom(mod)));
@@ -88,7 +89,7 @@ function comboLookupClick(dom, feed, mod) {
   } else if (char ==  1 && activeCombo == dom) { comboClear(dom); }
 }
 
-function comboLookupKeydown(dom, feed, mod) {
+function comboLookupKeydown(uid, dom, feed, mod) {
     var dropdown = qi(dom).closest('.dropdown');
     var char = event.which || event.keyCode;
     if (char == 40 && !activeCombo && qi(dom).value == '') {
@@ -98,7 +99,8 @@ function comboLookupKeydown(dom, feed, mod) {
         if (window.innerHeight - dropdown.getBoundingClientRect().bottom < 100)
           dropdown.classList.add('is-reversed');
         direct(tuple(atom('comboKey'),
-                     atom('all'),
+                     bin(uid),
+                     bin('all'),
                      string(dom),
                      string(feed),
                      atom(mod)));
@@ -119,7 +121,7 @@ function comboLookupKeydown(dom, feed, mod) {
     if (char == 13) { event.preventDefault(); return }
 }
 
-function comboLookupKeyup(dom, feed, mod) {
+function comboLookupKeyup(uid, dom, feed, mod) {
     var dropdown = qi(dom).closest('.dropdown')
     var char = event.which || event.keyCode;
     if (char == 27 || (char == 8 || char == 46) && qi(dom).value == '') { clearInput(dom); return }
@@ -133,6 +135,7 @@ function comboLookupKeyup(dom, feed, mod) {
         if (window.innerHeight - dropdown.getBoundingClientRect().bottom < 100)
           dropdown.classList.add('is-reversed');
         direct(tuple(atom('comboKey'),
+                     bin(uid),
                      bin(qi(dom).value),
                      string(dom),
                      string(feed),

+ 4 - 0
src/elements/combo/element_comboLookup.erl

@@ -11,15 +11,18 @@ proto(#comboInsert{delegate=Module}=Msg) -> Module:proto(Msg).
 
 render_element(#comboLookup{id=Id, style=Style, value = Val, bind = Object,
   feed = Feed, disabled = Disabled, delegate = Module, class = Class} = Data) ->
+  Uid = nitro_pi:uid([], []),
   nitro:render(
     #panel{id=form:atom([lookup, Id]), class=lists:flatten([dropdown, Class]),
            body=[#input{id=Id, disabled = Disabled, type="comboLookup",
                         autocomplete = "off",
                         onkeyup = nitro:jse("comboLookupKeyup('"
+                               ++ nitro:to_list(Uid) ++ "','"
                                ++ nitro:to_list(Id) ++ "','"
                                ++ nitro:to_list(Feed) ++ "','"
                                ++ nitro:to_list(Module) ++ "')"),
                         onkeydown= nitro:jse("comboLookupKeydown('"
+                               ++ nitro:to_list(Uid) ++ "','"
                                ++ nitro:to_list(Id) ++ "','"
                                ++ nitro:to_list(Feed) ++ "','"
                                ++ nitro:to_list(Module) ++ "')"),
@@ -33,6 +36,7 @@ render_element(#comboLookup{id=Id, style=Style, value = Val, bind = Object,
                           case Disabled of
                             true -> [];
                             _ -> nitro:jse("comboLookupClick('"
+                              ++ nitro:to_list(Uid) ++ "','"
                               ++ nitro:to_list(Id) ++ "','"
                               ++ nitro:to_list(Feed) ++ "','"
                               ++ nitro:to_list(Module) ++ "')")

+ 7 - 2
src/nitro_pi.erl

@@ -5,7 +5,7 @@
 -behaviour(gen_server).
 -export([start_link/1]).
 -export([init/1,handle_call/3,handle_cast/2,handle_info/2,terminate/2,code_change/3]).
--export([start/1,stop/2,send/2,send/3,cast/2,cast/3,pid/2,restart/2]).
+-export([start/1,stop/2,send/2,send/3,cast/2,cast/3,pid/2,restart/2,uid/2]).
 
 start(#pi{table=Tab,name=Name,module=Module,sup=Sup,timeout=Timeout,restart=Restart} = Async) ->
     ChildSpec = {{Tab,Name},{?MODULE,start_link,[Async]},Restart,Timeout,worker,[Module]},
@@ -42,6 +42,12 @@ cache(Tab, Key, undefined)   -> ets:delete(Tab,Key);
 cache(Tab, Key, Value)       -> cache(Tab, Key, Value, infinity).
 cache(Tab, Key, Value, Till) -> ets:insert(Tab,{Key,{Till,Value}}), Value.
 
+uid(_,_) ->
+  case os:type() of
+       {win32,nt} -> {Mega,Sec,Micro} = erlang:timestamp(), integer_to_list((Mega*1000000+Sec)*1000000+Micro);
+                _ -> erlang:integer_to_list(element(2,hd(lists:reverse(erlang:system_info(os_monotonic_time_source)))))
+  end.
+
 pid(Tab,Name) -> cache(Tab,{Tab,Name}).
 
 restart(Tab,Name) ->
@@ -83,4 +89,3 @@ init(#pi{module=Mod,table=Tab,name=Name}=Handler) ->
 terminate(_Reason, #pi{name=Name,sup=Sup,table=Tab}) ->
     spawn(fun() -> supervisor:delete_child(Sup,{Tab,Name}) end),
     catch cache(Tab,{Tab,Name},undefined), ok.
-