atome 0.5.7.5.4 → 0.5.7.5.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (99) hide show
  1. checksums.yaml +4 -4
  2. data/documentation/deep learning/basic_infos.txt +5 -0
  3. data/lib/atome/genesis/atomes.rb +12 -0
  4. data/lib/atome/genesis/particles/event.rb +141 -97
  5. data/lib/atome/genesis/particles/identity.rb +2 -1
  6. data/lib/atome/genesis/particles/spatial.rb +25 -0
  7. data/lib/atome/genesis/particles/utility.rb +13 -5
  8. data/lib/atome/utilities/essentials.rb +5 -2
  9. data/lib/atome/version.rb +1 -1
  10. data/lib/molecules/intuition/tools.rb +1 -1
  11. data/lib/molecules/intuition/utilities.rb +3 -0
  12. data/lib/platform_specific/opal/extensions/object.rb +3 -1
  13. data/lib/platform_specific/wasm/atome_wasm_extensions.rb +2 -1
  14. data/lib/renderers/html/event.rb +20 -6
  15. data/lib/renderers/html/html.rb +753 -446
  16. data/lib/renderers/html/identity.rb +33 -6
  17. data/lib/renderers/html/spatial.rb +27 -0
  18. data/lib/renderers/html/utility.rb +4 -0
  19. data/vendor/assets/application/examples/audio.rb +25 -9
  20. data/vendor/assets/application/examples/calendar.rb +186 -0
  21. data/vendor/assets/application/examples/drop.rb +1 -0
  22. data/vendor/assets/application/examples/editor.rb +139 -0
  23. data/vendor/assets/application/examples/inspector.rb +129 -0
  24. data/vendor/assets/application/examples/keyboard.rb +20 -10
  25. data/vendor/assets/application/examples/map.rb +42 -0
  26. data/vendor/assets/application/examples/meteo.rb +8 -0
  27. data/vendor/assets/application/examples/midi.rb +4 -0
  28. data/vendor/assets/application/examples/on_resize.rb +14 -0
  29. data/vendor/assets/application/examples/over.rb +0 -1
  30. data/vendor/assets/application/examples/overflow.rb +20 -5
  31. data/vendor/assets/application/examples/particles.rb +1 -1
  32. data/vendor/assets/application/examples/preset.rb +1 -1
  33. data/vendor/assets/application/examples/resize.rb +11 -0
  34. data/vendor/assets/application/examples/tick.rb +10 -0
  35. data/vendor/assets/application/examples/tools.rb +6 -1
  36. data/vendor/assets/application/examples/touch.rb +2 -14
  37. data/vendor/assets/application/examples/trigger_abstraction.rb +165 -0
  38. data/vendor/assets/application/examples/vr.rb +3 -0
  39. data/vendor/assets/src/css/codemirror.min.css +472 -0
  40. data/vendor/assets/src/css/fonts/tui/icon.eot +0 -0
  41. data/vendor/assets/src/css/fonts/tui/icon.svg +17 -0
  42. data/vendor/assets/src/css/fonts/tui/icon.ttf +0 -0
  43. data/vendor/assets/src/css/fonts/tui/icon.woff +0 -0
  44. data/vendor/assets/src/css/fonts/tui/noto.woff +72 -0
  45. data/vendor/assets/src/css/images/leaflet/layers-2x.png +0 -0
  46. data/vendor/assets/src/css/images/leaflet/layers.png +0 -0
  47. data/vendor/assets/src/css/images/leaflet/marker-icon-2x.png +0 -0
  48. data/vendor/assets/src/css/images/leaflet/marker-icon.png +0 -0
  49. data/vendor/assets/src/css/images/leaflet/marker-shadow.png +0 -0
  50. data/vendor/assets/src/css/images/tui/ic-arrow-line-left.png +0 -0
  51. data/vendor/assets/src/css/images/tui/ic-arrow-line-left@2x.png +0 -0
  52. data/vendor/assets/src/css/images/tui/ic-arrow-line-left@3x.png +0 -0
  53. data/vendor/assets/src/css/images/tui/ic-arrow-line-right.png +0 -0
  54. data/vendor/assets/src/css/images/tui/ic-arrow-line-right@2x.png +0 -0
  55. data/vendor/assets/src/css/images/tui/ic-arrow-line-right@3x.png +0 -0
  56. data/vendor/assets/src/css/images/tui/ic-traveltime-w.png +0 -0
  57. data/vendor/assets/src/css/images/tui/ic-view-day.png +0 -0
  58. data/vendor/assets/src/css/images/tui/ic-view-day@2x.png +0 -0
  59. data/vendor/assets/src/css/images/tui/ic-view-day@3x.png +0 -0
  60. data/vendor/assets/src/css/images/tui/ic-view-month.png +0 -0
  61. data/vendor/assets/src/css/images/tui/ic-view-month@2x.png +0 -0
  62. data/vendor/assets/src/css/images/tui/ic-view-month@3x.png +0 -0
  63. data/vendor/assets/src/css/images/tui/ic-view-week.png +0 -0
  64. data/vendor/assets/src/css/images/tui/ic-view-week@2x.png +0 -0
  65. data/vendor/assets/src/css/images/tui/ic-view-week@3x.png +0 -0
  66. data/vendor/assets/src/css/images/tui/icon.png +0 -0
  67. data/vendor/assets/src/css/images/tui/img-bi.png +0 -0
  68. data/vendor/assets/src/css/images/tui/img-bi@2x.png +0 -0
  69. data/vendor/assets/src/css/images/tui/img-bi@3x.png +0 -0
  70. data/vendor/assets/src/css/leaflet.css +664 -0
  71. data/vendor/assets/src/css/monokai.min.css +127 -0
  72. data/vendor/assets/src/css/style.css +1 -1
  73. data/vendor/assets/src/css/toastui-calendar.min.css +6 -0
  74. data/vendor/assets/src/index.html +12 -1
  75. data/vendor/assets/src/index_opal.html +16 -1
  76. data/vendor/assets/src/index_server.html +11 -1
  77. data/vendor/assets/src/index_server_wasm.html +10 -1
  78. data/vendor/assets/src/index_wasm.html +12 -1
  79. data/vendor/assets/src/js/atome/specific/tauri.js +32 -0
  80. data/vendor/assets/src/js/atome/utilities/importmap.js +9 -0
  81. data/vendor/assets/src/js/atome/utilities/three_module.js +88 -0
  82. data/vendor/assets/src/js/test.js +42 -0
  83. data/vendor/assets/src/js/third_parties/Three/build/three.cjs +54216 -0
  84. data/vendor/assets/src/js/third_parties/Three/build/three.module.min.js +6 -0
  85. data/vendor/assets/src/js/third_parties/Three/build/three.webgpu.min.js +6 -0
  86. data/vendor/assets/src/js/third_parties/Three/jsm/controls/OrbitControls.js +1532 -0
  87. data/vendor/assets/src/js/third_parties/codemirror.min.js +1 -0
  88. data/vendor/assets/src/js/third_parties/leaflet.js +6 -0
  89. data/vendor/assets/src/js/third_parties/leaflet.js.map +1 -0
  90. data/vendor/assets/src/js/third_parties/ruby.min.js +1 -0
  91. data/vendor/assets/src/js/third_parties/toastui-calendar.min.js +9 -0
  92. data/vendor/assets/src/medias/images/puydesancy.jpg +0 -0
  93. data/vendor/assets/src-tauri/Cargo.toml +6 -5
  94. data/vendor/assets/src-tauri/Info.plist +12 -0
  95. data/vendor/assets/src-tauri/src/main.rs +32 -3
  96. data/vendor/assets/src-tauri/src/midi.rs +25 -0
  97. data/vendor/assets/src-tauri/tauri.conf.json +4 -4
  98. metadata +60 -3
  99. data/vendor/assets/src/js/third_parties/three.min.js +0 -6
@@ -4,8 +4,6 @@
4
4
 
5
5
  class HTML
6
6
 
7
-
8
-
9
7
  def self.locate(selector, base_element = JS.global[:document][:body])
10
8
  return base_element if selector.empty?
11
9
 
@@ -41,8 +39,6 @@ class HTML
41
39
  @element
42
40
  end
43
41
 
44
-
45
-
46
42
  def hypertext(params)
47
43
  current_div = JS.global[:document].getElementById(@id.to_s)
48
44
  current_div[:innerHTML] = params
@@ -200,6 +196,26 @@ class HTML
200
196
  hash_result
201
197
  end
202
198
 
199
+ def markup(new_tag, _usr_bloc)
200
+ element_id = @id.to_s
201
+ js_code = <<~JAVASCRIPT
202
+ let element = document.getElementById('#{element_id}');
203
+ if (!element) {
204
+ console.error(`Element with id "${'#{element_id}'}" not found.`);
205
+ return;
206
+ }
207
+ let newElement = document.createElement('#{new_tag}');
208
+
209
+ newElement.style.cssText = element.style.cssText;
210
+ Array.from(element.attributes).forEach(attr => {
211
+ newElement.setAttribute(attr.name, attr.value);
212
+ });
213
+ newElement.innerHTML = element.innerHTML;
214
+ element.parentNode.replaceChild(newElement, element);
215
+ JAVASCRIPT
216
+ JS.eval(js_code)
217
+ end
218
+
203
219
  def hyperedit(params, usr_bloc)
204
220
  html_object = JS.global[:document].getElementById(params.to_s)
205
221
  particles_from_style = {}
@@ -264,6 +280,163 @@ class HTML
264
280
  @websocket.close
265
281
  end
266
282
 
283
+ # map
284
+ def location(loc_found)
285
+ if loc_found[:longitude] && loc_found[:latitude]
286
+ long_f = loc_found[:longitude]
287
+ lat_f = loc_found[:latitude]
288
+ js_code = <<~JAVASCRIPT
289
+ const locatorElement = document.getElementById('#{@id}');
290
+ if (!locatorElement._leaflet_map) {
291
+ const map = L.map('#{@id}').setView([51.505, -0.09], 2); // Centrer initialement sur une position par défaut
292
+ L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
293
+ attribution: '&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
294
+ }).addTo(map);
295
+ locatorElement._leaflet_map = map;
296
+
297
+ if ('#{long_f}' === 'auto' || '#{lat_f}' === 'auto') {
298
+ function onLocationFound(e) {
299
+ const radius = e.accuracy / 2;
300
+ const locationMarker = L.marker(e.latlng).addTo(map)
301
+ .bindPopup(`You are within ${radius} meters from this point`).openPopup();
302
+
303
+ // Ajouter un ID au marqueur
304
+ locationMarker._icon.id = '#{@id}_locator';
305
+
306
+ locationMarker.on('click', function() {
307
+ alert(`You clicked the location marker at ${e.latlng.toString()}`);
308
+ });
309
+
310
+ const locationCircle = L.circle(e.latlng, radius).addTo(map);
311
+ map.setView(e.latlng, map.getZoom()); // Centrer la carte sur la position trouvée en conservant le zoom actuel
312
+ }
313
+
314
+ function onLocationError(e) {
315
+ console.log(e.message);
316
+ }
317
+
318
+ map.on('locationfound', onLocationFound);
319
+ map.on('locationerror', onLocationError);
320
+
321
+ map.locate({ setView: true }); // Tenter de localiser l'utilisateur sans modifier le zoom
322
+ } else {
323
+ const lat = parseFloat('#{lat_f}');
324
+ const long = parseFloat('#{long_f}');
325
+ map.setView([lat, long], map.getZoom()); // Centrer la carte sur les coordonnées fournies en conservant le zoom actuel
326
+
327
+ const locationMarker = L.marker([lat, long]).addTo(map)
328
+ .bindPopup('This is your point').openPopup();
329
+
330
+ // Ajouter un ID au marqueur
331
+ locationMarker._icon.id = '#{@id}_locator';
332
+
333
+ locationMarker.on('click', function() {
334
+ alert(`You clicked the location marker at [${lat}, ${long}]`);
335
+ });
336
+ }
337
+
338
+ // Ecouter l'événement 'load' de la carte pour rafraîchir l'écran et afficher une alerte
339
+ map.whenReady(function() {
340
+ map.invalidateSize();
341
+ // important setimout re-center the view else the view is incorrect (map.invalidateSize() refresh the view)
342
+ setTimeout(function() {
343
+ map.invalidateSize();
344
+ }, 0001);
345
+ });
346
+ } else {
347
+ const map = locatorElement._leaflet_map;
348
+ if ('#{long_f}' !== 'auto' && '#{lat_f}' !== 'auto') {
349
+ const lat = parseFloat('#{lat_f}');
350
+ const long = parseFloat('#{long_f}');
351
+ map.setView([lat, long], map.getZoom()); // Centrer la carte sur les coordonnées fournies en conservant le zoom actuel
352
+
353
+ const locationMarker = L.marker([lat, long]).addTo(map)
354
+ .bindPopup('This is your point').openPopup();
355
+
356
+ // Ajouter un ID au marqueur
357
+ locationMarker._icon.id = '#{@id}_locator';
358
+
359
+ locationMarker.on('click', function() {
360
+ alert(`You clicked the location marker at [${lat}, ${long}]`);
361
+ });
362
+ }
363
+
364
+ // Ecouter l'événement 'load' de la carte pour rafraîchir l'écran et afficher une alerte
365
+ map.whenReady(function() {
366
+
367
+ setTimeout(function() {
368
+ map.invalidateSize();
369
+ }, 0001);
370
+ });
371
+ }
372
+
373
+ // Ecouter l'événement de redimensionnement de la fenêtre pour réinitialiser la taille de la carte et la vue
374
+ window.addEventListener('resize', () => {
375
+ const map = locatorElement._leaflet_map;
376
+ setTimeout(function() {
377
+ map.invalidateSize();
378
+ }, 0001);
379
+ });
380
+
381
+
382
+
383
+ JAVASCRIPT
384
+ JS.eval(js_code)
385
+
386
+ end
387
+ end
388
+
389
+ def map_zoom(params)
390
+ js_code = <<~JAVASCRIPT
391
+ const locatorElement = document.getElementById('#{@id}');
392
+ const map = locatorElement._leaflet_map;
393
+ map.setZoom(#{params});
394
+ JAVASCRIPT
395
+ JS.eval(js_code)
396
+ end
397
+
398
+ def map_pan(params)
399
+ left_found = params[:left] || 0
400
+ top_found = params[:top] || 0
401
+ js_code = <<~JAVASCRIPT
402
+ const locatorElement = document.getElementById('#{@id}');
403
+ const map = locatorElement._leaflet_map;
404
+ map.panBy([#{left_found}, #{top_found}], { animate: true });
405
+ JAVASCRIPT
406
+ JS.eval(js_code)
407
+ end
408
+
409
+ # meteo
410
+ def meteo_helper(data)
411
+ grab(@id).instance_variable_get('@meteo_code')[:meteo].call(data)
412
+ end
413
+
414
+ def meteo(location)
415
+ js_code = <<~JAVASCRIPT
416
+ const url = 'https://api.openweathermap.org/data/2.5/weather?q=#{location},fr&appid=c21a75b667d6f7abb81f118dcf8d4611&units=metric';
417
+ async function fetchWeather() {
418
+ try {
419
+ let response = await fetch(url);
420
+
421
+ if (!response.ok) {
422
+ throw new Error('Erreur HTTP ! statut : ' + response.status);
423
+ }
424
+
425
+ let data = await response.json();
426
+
427
+
428
+ let jsonString = JSON.stringify(data);
429
+ atomeJsToRuby("grab('#{@id}').html.meteo_helper("+jsonString+")");
430
+ } catch (error) {
431
+ console.log('Error getting meteo : ' + error.message);
432
+ }
433
+ }
434
+
435
+ fetchWeather();
436
+ JAVASCRIPT
437
+ JS.eval(js_code)
438
+ end
439
+
267
440
  def attr(attribute, value)
268
441
  @element.setAttribute(attribute.to_s, value.to_s)
269
442
  self
@@ -290,6 +463,39 @@ class HTML
290
463
  delete(id) unless element_to_delete.inspect == 'null'
291
464
  end
292
465
 
466
+ def editor(id)
467
+ check_double(id)
468
+ editor_id = "#{id}_editor"
469
+ check_double(editor_id)
470
+ markup_found = @original_atome.markup || :textarea
471
+ @element_type = markup_found.to_s
472
+ @element = JS.global[:document].createElement(@element_type)
473
+ JS.global[:document][:body].appendChild(@element)
474
+ add_class('atome')
475
+ id(id)
476
+ self
477
+ end
478
+
479
+ # def editor(id)
480
+ # check_double(id)
481
+ # editor_id = "#{id}_editor"
482
+ # check_double(editor_id)
483
+ # markup_found = @original_atome.markup || :div
484
+ # @element_type = markup_found.to_s
485
+ # @element = JS.global[:document].createElement(@element_type)
486
+ # @element.setAttribute('style', 'font-size: 12px;')
487
+ #
488
+ # JS.global[:document][:body].appendChild(@element)
489
+ # add_class('atome')
490
+ # id(id)
491
+ # textarea = JS.global[:document].createElement('textarea')
492
+ # textarea.setAttribute('id', editor_id)
493
+ # wait 0.1 do
494
+ # @element.appendChild(textarea)
495
+ # end
496
+ # self
497
+ # end
498
+
293
499
  def shape(id)
294
500
  # we remove any element if the id already exist
295
501
  check_double(id)
@@ -373,6 +579,49 @@ class HTML
373
579
  self
374
580
  end
375
581
 
582
+ def vr(id)
583
+ # we remove any element if the id already exist
584
+ check_double(id)
585
+ markup_found = @original_atome.markup || :div
586
+ @element_type = markup_found.to_s
587
+ @element = JS.global[:document].createElement(@element_type)
588
+ JS.global[:document][:body].appendChild(@element)
589
+ add_class('atome')
590
+ self.id(id)
591
+
592
+ self
593
+ end
594
+
595
+ def vr_path(objet_path)
596
+ js_code = <<~JAVASCRIPT
597
+ initWithParam('#{objet_path}', '#{@id}', 'method', 'params');
598
+ JAVASCRIPT
599
+
600
+ JS.eval(js_code)
601
+ # tags = <<~HTML
602
+ # <a-scene embedded>
603
+ # <a-sky src="#{objet_path}" rotation="0 -130 0"></a-sky>
604
+ # <a-text font="kelsonsans" value="Puy de Sancy, France" width="6" position="-2.5 0.25 -1.5" rotation="0 15 0"></a-text>
605
+ # <!-- Hotspot -->
606
+ # <a-sphere id="clickable" color="#FF0000" radius="0.1" position="0 1 -2"
607
+ # event-set__mouseenter="_event: mouseenter; color: green"
608
+ # event-set__mouseleave="_event: mouseleave; color: red"></a-sphere>
609
+ # <!-- Camera with cursor to detect clicks -->
610
+ # </a-scene>
611
+ # HTML
612
+ # @element[:innerHTML] = tags
613
+ #
614
+ # # Ajouter un écouteur d'événement pour le hotspot
615
+ # cursor = JS.global[:document].getElementById('cursor')
616
+ # cursor.addEventListener('click', -> {
617
+ # target = cursor.components.cursor.intersectedEl
618
+ # if target && target.id == 'clickable'
619
+ # alert :yes
620
+ # end
621
+ # })
622
+
623
+ end
624
+
376
625
  def www(id)
377
626
  # we remove any element if the id already exist
378
627
  check_double(id)
@@ -607,7 +856,9 @@ class HTML
607
856
 
608
857
  def delete(id_to_delete)
609
858
  element_to_delete = JS.global[:document].getElementById(id_to_delete.to_s)
610
- element_to_delete.remove if element_to_delete
859
+ return unless element_to_delete.to_s != 'null'
860
+ return unless element_to_delete
861
+ element_to_delete.remove
611
862
  end
612
863
 
613
864
  def append(child_id_found)
@@ -618,7 +869,6 @@ class HTML
618
869
 
619
870
  # events handlers
620
871
  def on(property, _option)
621
- bloc = @original_atome.instance_variable_get('@on_code')[:view_resize]
622
872
  property = property.to_s
623
873
 
624
874
  if property.start_with?('media:')
@@ -628,6 +878,7 @@ class HTML
628
878
  mql = JS.global[:window].matchMedia(media_query)
629
879
 
630
880
  event_handler = ->(event) do
881
+ bloc = @original_atome.instance_variable_get('@on_code')[:view_resize]
631
882
  proc_content = bloc.call({ matches: event[:matches] }) if event_validation(bloc)
632
883
  if proc_content.instance_of? Hash
633
884
  proc_content.each do |k, v|
@@ -640,18 +891,27 @@ class HTML
640
891
  mql.addListener(event_handler)
641
892
 
642
893
  elsif property == 'resize'
643
- event_handler = ->(event) do
644
- width = JS.global[:window][:innerWidth]
645
- height = JS.global[:window][:innerHeight]
646
- proc_content = bloc.call({ width: width, height: height }) if event_validation(bloc)
647
- if proc_content.instance_of? Hash
648
- proc_content.each do |k, v|
649
- @original_atome.send(k, v)
894
+ unless @on_resize_already_set
895
+ event_handler = ->(event) do
896
+ width = JS.global[:window][:innerWidth]
897
+ height = JS.global[:window][:innerHeight]
898
+ blocs = @original_atome.instance_variable_get('@on_code')[:view_resize]
899
+ blocs.each do |bloc|
900
+ proc_content = bloc.call({ width: width, height: height }) if event_validation(bloc)
901
+ if proc_content.instance_of? Hash
902
+ proc_content.each do |k, v|
903
+ @original_atome.send(k, v)
904
+ end
905
+ end
650
906
  end
651
907
  end
652
- end
653
908
 
654
- JS.global[:window].addEventListener('resize', event_handler)
909
+ JS.global[:window].addEventListener('resize', event_handler)
910
+ end
911
+ @on_resize_already_set = true
912
+ elsif property == 'remove'
913
+ alert 'ok'
914
+ @original_atome.instance_variable_get('@on_code')[:view_resize] = []
655
915
  else
656
916
  event_handler = ->(event) do
657
917
  proc_content = bloc.call(event) if event_validation(bloc)
@@ -733,14 +993,13 @@ class HTML
733
993
  end
734
994
  end
735
995
 
736
- def drag_code(params=nil)
737
- #FIXME : this method is an ugly patch when refreshing an atome twice, else it crash
738
- # and lose it's drag
739
- drag_move(params)
740
- end
996
+ # def drag_code(params = nil)
997
+ # # FIXME : this method is an ugly patch when refreshing an atome twice, else it crash
998
+ # # and lose it's drag
999
+ # drag_move(params)
1000
+ # end
741
1001
 
742
1002
  def event(action, variance, option = nil)
743
- # puts " remove 'if option', if unable ti unbind# : #{action} _ #{variance}"
744
1003
  send("#{action}_#{variance}", option)
745
1004
  end
746
1005
 
@@ -749,210 +1008,260 @@ class HTML
749
1008
  @original_atome.top(restricted_y)
750
1009
  end
751
1010
 
752
- def drag_remove(option)
1011
+ def drag_move(_option)
753
1012
 
754
- @draggable = nil
755
- interact = JS.eval("return interact('##{@id}')")
1013
+ unless @drag_move_already_set
1014
+ # the condition below prevent drag accumulation
1015
+ interact = JS.eval("return interact('##{@id}')")
1016
+
1017
+ unless @draggable
1018
+ interact.draggable({
1019
+ drag: true,
1020
+ inertia: { resistance: 12,
1021
+ minSpeed: 200,
1022
+ endSpeed: 100 },
1023
+ })
1024
+ unless @first_drag
1025
+ interact.on('dragmove') do |native_event|
1026
+ drag_moves = @original_atome.instance_variable_get('@drag_code')[:move]
1027
+
1028
+ # the use of Native is only for Opal (look at lib/platform_specific/atome_wasm_extensions.rb for more infos)
1029
+ event = Native(native_event)
1030
+ # we use .call instead of instance_eval because instance_eval bring the current object as context
1031
+ # and it's lead to a problem of context and force the use of grab(:view) when suing atome method such as shape ,
1032
+ # group etc..
1033
+ drag_moves.each do |drag_move|
1034
+ proc_content = drag_move.call(event) if event_validation(drag_move)
1035
+ if proc_content.instance_of? Hash
1036
+ proc_content.each do |k, v|
1037
+ @original_atome.send(k, v)
1038
+ end
1039
+ end
1040
+ end
756
1041
 
757
- case option
758
- when :start
759
- @drag_start = ''
760
- when :end, :stop
761
- @drag_end = ''
762
- when :move
763
- interact.draggable(false)
764
- # interact.unset
765
- @drag_move = nil
766
-
767
- when :locked
768
- @drag_locked = ''
769
- when :restrict
770
- @drag_restrict = ''
771
- else
772
- # to remove all interact event ( touch, drag, scale, ... uncomment below)
773
- @drag_start = ''
774
- @drag_end = ''
775
- @drag_locked = ''
776
- @drag_restrict = ''
777
- @drag_move = nil
778
- interact.draggable(false)
779
- # interact.unset
1042
+ Universe.allow_tool_operations = false
1043
+ dx = event[:dx]
1044
+ dy = event[:dy]
1045
+ x = (@original_atome.left || 0) + dx.to_f
1046
+ y = (@original_atome.top || 0) + dy.to_f
1047
+ @original_atome.left(x)
1048
+ @original_atome.top(y)
1049
+ end
1050
+
1051
+ end
1052
+ end
1053
+ @first_drag = true
1054
+ @draggable = true
1055
+ end
1056
+ @drag_move_already_set = true
1057
+
1058
+ end
1059
+
1060
+ def drag_restrict(option)
1061
+
1062
+ unless @drag_restrict_already_set
1063
+ interact = JS.eval("return interact('##{@id}')")
1064
+ interact.draggable({
1065
+ drag: true,
1066
+ inertia: { resistance: 12,
1067
+ minSpeed: 200,
1068
+ endSpeed: 100 },
1069
+ })
1070
+
1071
+ if option.instance_of? Hash
1072
+ max_left = grab(:view).to_px(:width)
1073
+ max_top = grab(:view).to_px(:height)
1074
+ min_left = 0
1075
+ min_top = 0
1076
+
1077
+ if option[:max]
1078
+ max_left = option[:max][:left] || max_left
1079
+ max_top = option[:max][:top] || max_top
1080
+ else
1081
+ max_left
1082
+ max_top
1083
+ end
1084
+ if option[:min]
1085
+ min_left = option[:min][:left] || min_left
1086
+ min_top = option[:min][:top] || min_top
1087
+ else
1088
+ min_left
1089
+ min_top
1090
+ end
1091
+ else
1092
+ parent_found = grab(option)
1093
+ min_left = parent_found.left
1094
+ min_top = parent_found.top
1095
+ parent_width = parent_found.compute({ particle: :width })[:value]
1096
+ parent_height = parent_found.compute({ particle: :height })[:value]
1097
+ original_width = @original_atome.width
1098
+ original_height = @original_atome.height
1099
+ max_left = min_left + parent_width - original_width
1100
+ max_top = min_top + parent_height - original_height
1101
+ end
1102
+
1103
+ interact.on('dragmove') do |native_event|
1104
+ drag_moves = @original_atome.instance_variable_get('@drag_code')[:restrict]
1105
+
1106
+ # the use of Native is only for Opal (look at lib/platform_specific/atome_wasm_extensions.rb for more infos)
1107
+ event = Native(native_event)
1108
+ # we use .call instead of instance_eval because instance_eval bring the current object as context
1109
+ # and it's lead to a problem of context and force the use of grab(:view) when suing atome method such as shape ,
1110
+ # group etc..
1111
+ drag_moves.each do |drag_move|
1112
+ proc_content = drag_move.call(event) if event_validation(drag_move)
1113
+ if proc_content.instance_of? Hash
1114
+ proc_content.each do |k, v|
1115
+ @original_atome.send(k, v)
1116
+ end
1117
+ end
1118
+ end
1119
+
1120
+ dx = event[:dx]
1121
+ dy = event[:dy]
1122
+ x = (@original_atome.left || 0) + dx.to_f
1123
+ y = (@original_atome.top || 0) + dy.to_f
1124
+ restricted_x = [[x, min_left].max, max_left].min
1125
+ restricted_y = [[y, min_top].max, max_top].min
1126
+ restrict_movement(restricted_x, restricted_y)
1127
+ end
780
1128
  end
1129
+ @drag_restrict_already_set = true
781
1130
 
782
1131
  end
783
1132
 
784
1133
  def drag_start(_option)
785
- interact = JS.eval("return interact('##{@id}')")
786
- @drag_start = @original_atome.instance_variable_get('@drag_code')[:start]
787
- interact.on('dragstart') do |native_event|
788
- event = Native(native_event)
789
- # we use .call instead of instance_eval because instance_eval bring the current object as context
790
- # and it's lead to a problem of context and force the use of grab(:view) when suing atome method such as shape ,
791
- # group etc..
792
- proc_content = @drag_start.call(event) if event_validation(@drag_start)
793
- if proc_content.instance_of? Hash
794
- proc_content.each do |k, v|
795
- @original_atome.send(k, v)
1134
+ unless @drag_start_already_set
1135
+ interact = JS.eval("return interact('##{@id}')")
1136
+ interact.on('dragstart') do |native_event|
1137
+ drag_starts = @original_atome.instance_variable_get('@drag_code')[:start]
1138
+ event = Native(native_event)
1139
+ # we use .call instead of instance_eval because instance_eval bring the current object as context
1140
+ # and it's lead to a problem of context and force the use of grab(:view) when suing atome method such as shape ,
1141
+ # group etc..
1142
+ drag_starts.each do |drag_start|
1143
+ proc_content = drag_start.call(event) if event_validation(drag_start)
1144
+ if proc_content.instance_of? Hash
1145
+ proc_content.each do |k, v|
1146
+ @original_atome.send(k, v)
1147
+ end
1148
+ end
796
1149
  end
797
1150
  end
798
1151
  end
1152
+ @drag_start_already_set = true
799
1153
  end
800
1154
 
801
1155
  def drag_end(_option)
802
- interact = JS.eval("return interact('##{@id}')")
803
- @drag_end = @original_atome.instance_variable_get('@drag_code')[:end]
804
- interact.on('dragend') do |native_event|
805
- event = Native(native_event)
806
- # we use .call instead of instance_eval because instance_eval bring the current object as context
807
- # and it's lead to a problem of context and force the use of grab(:view) when suing atome method such as shape ,
808
- # group etc..
809
- proc_content = @drag_end.call(event) if event_validation(@drag_end)
810
- if proc_content.instance_of? Hash
811
- proc_content.each do |k, v|
812
- @original_atome.send(k, v)
1156
+
1157
+ unless @drag_end_already_set
1158
+ interact = JS.eval("return interact('##{@id}')")
1159
+ interact.on('dragend') do |native_event|
1160
+ drag_ends = @original_atome.instance_variable_get('@drag_code')[:end]
1161
+ event = Native(native_event)
1162
+ # we use .call instead of instance_eval because instance_eval bring the current object as context
1163
+ # and it's lead to a problem of context and force the use of grab(:view) when suing atome method such as shape ,
1164
+ # group etc..
1165
+ drag_ends.each do |drag_end|
1166
+ proc_content = drag_end.call(event) if event_validation(drag_end)
1167
+ if proc_content.instance_of? Hash
1168
+ proc_content.each do |k, v|
1169
+ @original_atome.send(k, v)
1170
+ end
1171
+ end
813
1172
  end
1173
+
814
1174
  end
815
1175
  end
816
- end
1176
+ @drag_end_already_set = true
817
1177
 
818
- def drag_move(_option)
819
- # the condition below prevent drag accumulation
820
- interact = JS.eval("return interact('##{@id}')")
1178
+ end
821
1179
 
822
- unless @draggable
1180
+ def drag_locked(_option)
1181
+ unless @drag_locked_already_set
1182
+ interact = JS.eval("return interact('##{@id}')")
823
1183
  interact.draggable({
824
1184
  drag: true,
825
1185
  inertia: { resistance: 12,
826
1186
  minSpeed: 200,
827
- endSpeed: 100 },
1187
+ endSpeed: 100 }
828
1188
  })
829
- @drag_move = @original_atome.instance_variable_get('@drag_code')[:move]
830
- unless @first_drag
831
- interact.on('dragmove') do |native_event|
832
- # the use of Native is only for Opal (look at lib/platform_specific/atome_wasm_extensions.rb for more infos)
833
- event = Native(native_event)
834
- # we use .call instead of instance_eval because instance_eval bring the current object as context
835
- # and it's lead to a problem of context and force the use of grab(:view) when suing atome method such as shape ,
836
- # group etc..
837
- proc_content = @drag_move.call(event) if event_validation(@drag_move)
1189
+
1190
+ interact.on('dragmove') do |native_event|
1191
+ drag_locks = @original_atome.instance_variable_get('@drag_code')[:locked]
1192
+ # the use of Native is only for Opal (look at lib/platform_specific/atome_wasm_extensions.rb for more infos)
1193
+ event = Native(native_event)
1194
+ # we use .call instead of instance_eval because instance_eval bring the current object as context
1195
+ # and it's lead to a problem of context and force the use of grab(:view) when suing atome method such as shape ,
1196
+ # group etc..
1197
+ drag_locks.each do |drag_lock|
1198
+ proc_content = drag_lock.call(event) if event_validation(drag_lock)
838
1199
  if proc_content.instance_of? Hash
839
1200
  proc_content.each do |k, v|
840
1201
  @original_atome.send(k, v)
841
1202
  end
842
1203
  end
843
- Universe.allow_tool_operations = false
844
- dx = event[:dx]
845
- dy = event[:dy]
846
- x = (@original_atome.left || 0) + dx.to_f
847
- y = (@original_atome.top || 0) + dy.to_f
848
- @original_atome.left(x)
849
- @original_atome.top(y)
850
1204
  end
851
-
852
1205
  end
853
1206
  end
854
- @first_drag = true
855
- @draggable = true
1207
+ @drag_locked_already_set = true
1208
+
856
1209
  end
857
1210
 
858
- def drag_restrict(option)
1211
+ def remove_this_drag(option)
1212
+ @original_atome.instance_variable_get('@drag_code')[option] = [] if @original_atome.instance_variable_get('@drag_code')
1213
+ end
1214
+
1215
+ def drag_remove(_opt)
1216
+
859
1217
  interact = JS.eval("return interact('##{@id}')")
860
- interact.draggable({
861
- drag: true,
862
- inertia: { resistance: 12,
863
- minSpeed: 200,
864
- endSpeed: 100 },
865
- })
866
-
867
- @drag_move = @original_atome.instance_variable_get('@drag_code')[:restrict]
868
- if option.instance_of? Hash
869
- max_left = grab(:view).to_px(:width)
870
- max_top = grab(:view).to_px(:height)
871
- min_left = 0
872
- min_top = 0
873
-
874
- if option[:max]
875
- max_left = option[:max][:left] || max_left
876
- max_top = option[:max][:top] || max_top
877
- else
878
- max_left
879
- max_top
880
- end
881
- if option[:min]
882
- min_left = option[:min][:left] || min_left
883
- min_top = option[:min][:top] || min_top
884
- else
885
- min_left
886
- min_top
887
- end
1218
+ if @original_atome.instance_variable_get('@drag_code')
1219
+ options = @original_atome.instance_variable_get('@drag_code')[:remove]
888
1220
  else
889
- parent_found = grab(option)
890
- min_left = parent_found.left
891
- min_top = parent_found.top
892
- parent_width = parent_found.compute({ particle: :width })[:value]
893
- parent_height = parent_found.compute({ particle: :height })[:value]
894
- original_width = @original_atome.width
895
- original_height = @original_atome.height
896
- max_left = min_left + parent_width - original_width
897
- max_top = min_top + parent_height - original_height
898
- end
899
-
900
- interact.on('dragmove') do |native_event|
901
- # the use of Native is only for Opal (look at lib/platform_specific/atome_wasm_extensions.rb for more infos)
902
- event = Native(native_event)
903
- # we use .call instead of instance_eval because instance_eval bring the current object as context
904
- # and it's lead to a problem of context and force the use of grab(:view) when suing atome method such as shape ,
905
- # group etc..
906
- proc_content = @drag_move.call(event) if event_validation(@drag_move)
907
- if proc_content.instance_of? Hash
908
- proc_content.each do |k, v|
909
- @original_atome.send(k, v)
910
- end
911
- end
912
- dx = event[:dx]
913
- dy = event[:dy]
914
- x = (@original_atome.left || 0) + dx.to_f
915
- y = (@original_atome.top || 0) + dy.to_f
916
- restricted_x = [[x, min_left].max, max_left].min
917
- restricted_y = [[y, min_top].max, max_top].min
918
- restrict_movement(restricted_x, restricted_y)
1221
+ options = false
919
1222
  end
920
- end
921
1223
 
922
- def drag_locked(_option)
923
- interact = JS.eval("return interact('##{@id}')")
924
- interact.draggable({
925
- drag: true,
926
- inertia: { resistance: 12,
927
- minSpeed: 200,
928
- endSpeed: 100 }
929
- })
930
-
931
- @drag_lock = @original_atome.instance_variable_get('@drag_code')[:locked]
932
- interact.on('dragmove') do |native_event|
933
- # the use of Native is only for Opal (look at lib/platform_specific/atome_wasm_extensions.rb for more infos)
934
- event = Native(native_event)
935
- # we use .call instead of instance_eval because instance_eval bring the current object as context
936
- # and it's lead to a problem of context and force the use of grab(:view) when suing atome method such as shape ,
937
- # group etc..
938
- proc_content = @drag_lock.call(event) if event_validation(@drag_lock)
939
- if proc_content.instance_of? Hash
940
- proc_content.each do |k, v|
941
- @original_atome.send(k, v)
1224
+ options.each do |option|
1225
+ if option.instance_of? Array
1226
+ option.each do |opt|
1227
+ remove_this_drag(opt)
942
1228
  end
1229
+ return false
1230
+ end
1231
+ @element[:style][:cursor] = 'default'
1232
+
1233
+ @draggable = nil
1234
+ case option
1235
+ when :start
1236
+ remove_this_drag(:start)
1237
+ when :end, :stop
1238
+ remove_this_drag(:end)
1239
+ remove_this_drag(:stop)
1240
+ when :move
1241
+ remove_this_drag(:move)
1242
+ when :locked
1243
+ remove_this_drag(:locked)
1244
+ when :restrict
1245
+ remove_this_drag(:restrict)
1246
+ else
1247
+ interact.draggable(false)
1248
+
943
1249
  end
944
1250
  end
1251
+
945
1252
  end
946
1253
 
947
- def drop_action(native_event, bloc)
1254
+ def drop_common(method, native_event)
948
1255
  event = Native(native_event)
949
1256
  draggable_element = event[:relatedTarget][:id].to_s
950
1257
  dropzone_element = event[:target][:id].to_s
951
1258
  # we use .call instead of instance_eval because instance_eval bring the current object as context
952
1259
  # and it's lead to a problem of context and force the use of grab(:view) when suing atome method such as shape ,
953
1260
  # group etc..
954
- proc_content = bloc.call({ source: draggable_element, destination: dropzone_element }) if event_validation(bloc)
955
- if proc_content.instance_of? Hash
1261
+ proc_contents = @original_atome.instance_variable_get('@drop_code')[method]
1262
+ proc_contents.each do |proc_content|
1263
+ proc_content = proc_content.call({ source: draggable_element, destination: dropzone_element }) if event_validation(proc_content)
1264
+ return unless proc_content.instance_of? Hash
956
1265
  proc_content.each do |k, v|
957
1266
  @original_atome.send(k, v)
958
1267
  end
@@ -960,97 +1269,108 @@ class HTML
960
1269
  end
961
1270
 
962
1271
  def drop_activate(_option)
963
- interact = JS.eval("return interact('##{@id}')")
964
- @drop_activate = @original_atome.instance_variable_get('@drop_code')[:activate]
965
-
966
- interact.dropzone({
967
- accept: nil, # Accept any element
968
- overlap: 0.75,
969
- ondropactivate: lambda do |native_event|
970
- drop_action(native_event, @drop_activate) if event_validation(@drop_activate)
971
- end
972
- })
973
- end
1272
+ unless @drop_activate_already_set
1273
+ interact = JS.eval("return interact('##{@id}')")
1274
+ interact.dropzone({
1275
+ accept: nil, # Accept any element
1276
+ overlap: 0.75,
1277
+ ondropactivate: lambda do |native_event|
1278
+ drop_common(:activate, native_event)
1279
+ end
1280
+ })
1281
+ end
974
1282
 
975
- def drop_deactivate(_option)
976
- interact = JS.eval("return interact('##{@id}')")
977
- @drop_deactivate = @original_atome.instance_variable_get('@drop_code')[:deactivate]
978
- interact.dropzone({
979
- # accept: nil, # Accept any element
980
- # FIXME : remove because os an opal bug since 1.8 reactivate when opal will be debbuged
981
- ondropdeactivate: lambda do |native_event|
982
- drop_action(native_event, @drop_deactivate) if event_validation(@drop_deactivate)
983
- end
984
- })
1283
+ @drop_activate_already_set = true
985
1284
  end
986
1285
 
987
1286
  def drop_dropped(_option)
988
- @drop_dropped = @original_atome.instance_variable_get('@drop_code')[:dropped]
989
- interact = JS.eval("return interact('##{@id}')")
990
- interact.dropzone({
991
- # accept: nil, # Accept any element
992
- overlap: 0.75,
993
- # FIXME : remove because os an opal bug since 1.8 reactivate when opal will be debbuged
994
- ondrop: lambda do |native_event|
995
- drop_action(native_event, @drop_dropped) if event_validation(@drop_dropped)
996
- end
997
- })
1287
+ unless @drop_dropped_already_set
1288
+ interact = JS.eval("return interact('##{@id}')")
1289
+ interact.dropzone({
1290
+ overlap: 0.75,
1291
+ # FIXME : remove because os an opal bug since 1.8 reactivate when opal will be debbuged
1292
+ ondrop: lambda do |native_event|
1293
+ drop_common(:dropped, native_event)
1294
+ end
1295
+ })
1296
+
1297
+ end
1298
+ @drop_dropped_already_set = true
998
1299
  end
999
1300
 
1000
1301
  def drop_enter(_option)
1001
- interact = JS.eval("return interact('##{@id}')")
1302
+ unless @drop_enter_already_set
1303
+ interact = JS.eval("return interact('##{@id}')")
1304
+ interact.dropzone({
1305
+ overlap: 0.001,
1306
+ # FIXME : remove because os an opal bug since 1.8 reactivate when opal will be debbuged
1307
+ ondragenter: lambda do |native_event|
1308
+ drop_common(:enter, native_event)
1309
+ end
1310
+ })
1311
+ end
1312
+ @drop_enter_already_set = true
1313
+ end
1314
+
1315
+ def drop_leave(_option)
1316
+ unless @drop_leave_already_set
1317
+ interact = JS.eval("return interact('##{@id}')")
1318
+ interact.dropzone({
1319
+ # FIXME : remove because os an opal bug since 1.8 reactivate when opal will be debbuged
1320
+ ondragleave: lambda do |native_event|
1321
+ drop_common(:leave, native_event)
1322
+ end
1323
+ })
1324
+ end
1002
1325
 
1003
- @drop_enter = @original_atome.instance_variable_get('@drop_code')[:enter]
1326
+ @drop_leave_already_set = true
1004
1327
 
1005
- interact.dropzone({
1006
- overlap: 0.001,
1007
- # FIXME : remove because os an opal bug since 1.8 reactivate when opal will be debbuged
1008
- ondragenter: lambda do |native_event|
1009
- drop_action(native_event, @drop_enter) if event_validation(@drop_enter)
1010
- end
1011
- })
1012
1328
  end
1013
1329
 
1014
- def drop_leave(_option)
1015
- interact = JS.eval("return interact('##{@id}')")
1016
- @drop_leave = @original_atome.instance_variable_get('@drop_code')[:leave]
1330
+ def drop_deactivate(_option)
1331
+ unless @drop_remove_already_set
1017
1332
 
1018
- interact.dropzone({
1019
- # FIXME : remove because os an opal bug since 1.8 reactivate when opal will be debbuged
1020
- ondragleave: lambda do |native_event|
1021
- drop_action(native_event, @drop_leave) if event_validation(@drop_enter)
1022
- end
1023
- })
1333
+ interact = JS.eval("return interact('##{@id}')")
1334
+ interact.dropzone({
1335
+ # accept: nil, # Accept any element
1336
+ # FIXME : remove because os an opal bug since 1.8 reactivate when opal will be debbuged
1337
+ ondropdeactivate: lambda do |native_event|
1338
+ drop_common(:deactivate, native_event)
1339
+ end
1340
+ })
1024
1341
 
1342
+ end
1343
+ @drop_remove_already_set = true
1025
1344
  end
1026
1345
 
1027
1346
  def drop_remove(option)
1028
1347
  case option
1029
1348
  when :activate
1030
- @drop_activate = ''
1349
+ @original_atome.instance_variable_get('@drop_code')[:activate] = []
1031
1350
  when :deactivate
1032
- @drop_deactivate = ''
1351
+ @original_atome.instance_variable_get('@drop_code')[:deactivate] = []
1033
1352
  when :dropped
1034
- @drop_dropped = ''
1353
+ @original_atome.instance_variable_get('@drop_code')[:dropped] = []
1035
1354
  when :enter
1036
- @drop_enter = ''
1355
+ @original_atome.instance_variable_get('@drop_code')[:enter] = []
1037
1356
  when :leave
1038
- @drop_leave = ''
1357
+ @original_atome.instance_variable_get('@drop_code')[:leave] = []
1039
1358
  else
1040
- # to remove all interact event ( touch, drag, scale, ... uncomment below)
1041
- # interact.unset
1042
- @drop_activate = ''
1043
- @drop_deactivate = ''
1044
- @drop_dropped = ''
1045
- @drop_enter = ''
1046
- @drop_leave = ''
1047
-
1359
+ drop_remove(:activate)
1360
+ drop_remove(:deactivate)
1361
+ drop_remove(:dropped)
1362
+ drop_remove(:enter)
1363
+ drop_remove(:leave)
1048
1364
  end
1049
1365
 
1050
1366
  end
1051
1367
 
1052
1368
  def resize(params, options)
1053
1369
  interact = JS.eval("return interact('##{@id}')")
1370
+
1371
+ # Désactiver explicitement le déplacement
1372
+ # interact.draggable(false)
1373
+
1054
1374
  if params == :remove
1055
1375
  @resize = ''
1056
1376
  interact.resizable(false)
@@ -1060,6 +1380,7 @@ class HTML
1060
1380
  max_width = options[:max][:width] || 3000
1061
1381
  max_height = options[:max][:height] || 3000
1062
1382
  @resize = @original_atome.instance_variable_get('@resize_code')[:resize]
1383
+
1063
1384
  interact.resizable({
1064
1385
  edges: { left: true, right: true, top: true, bottom: true },
1065
1386
  inertia: true,
@@ -1067,12 +1388,8 @@ class HTML
1067
1388
  listeners: {
1068
1389
  move: lambda do |native_event|
1069
1390
  Universe.allow_tool_operations = false
1070
- # if @resize.is_a?(Proc)
1391
+
1071
1392
  event = Native(native_event)
1072
- # we use .call instead of instance_eval because instance_eval bring the current object as context
1073
- # and it's lead to a problem of context and force the use of grab(:view) when suing atome method such as shape ,
1074
- # group etc..
1075
- # @resize.call(event) if event_validation(@resize)
1076
1393
  proc_content = @resize.call(event) if event_validation(@resize)
1077
1394
  if proc_content.instance_of? Hash
1078
1395
  proc_content.each do |k, v|
@@ -1084,18 +1401,19 @@ class HTML
1084
1401
  y = (@element[:offsetTop].to_i || 0)
1085
1402
  width = event[:rect][:width]
1086
1403
  height = event[:rect][:height]
1404
+
1087
1405
  # Translate when resizing from any corner
1088
1406
  x += event[:deltaRect][:left].to_f
1089
1407
  y += event[:deltaRect][:top].to_f
1408
+
1090
1409
  @original_atome.width width.to_i if width.to_i.between?(min_width, max_width)
1091
1410
  @original_atome.height height.to_i if height.to_i.between?(min_height, max_height)
1092
1411
  @original_atome.left(x)
1093
1412
  @original_atome.top(y)
1094
- end
1095
- # end
1413
+ end,
1096
1414
  },
1097
-
1098
1415
  })
1416
+
1099
1417
  end
1100
1418
 
1101
1419
  end
@@ -1121,87 +1439,112 @@ class HTML
1121
1439
  end
1122
1440
 
1123
1441
  def over_over(_option)
1124
- interact = JS.eval("return interact('##{@id}')")
1125
- @over_over = @original_atome.over_code[:over]
1126
- interact.on('mouseover') do |native_event|
1127
- JS.global[:myRubyMouseOverCallback] = Proc.new { @original_atome.over_code[:over].call }
1442
+ return if @over_over_already_set
1443
+ @element.addEventListener('mouseover') do |native_event|
1444
+ over_options = @original_atome.instance_variable_get('@over_code')[:flyover]
1128
1445
  event = Native(native_event)
1129
- # we use .call instead of instance_eval because instance_eval bring the current object as context
1130
- # and it's lead to a problem of context and force the use of grab(:view) when suing atome method such as shape ,
1131
- # group etc..
1132
-
1133
- proc_content = @over_over.call(event) if event_validation(@over_over)
1134
- if proc_content.instance_of? Hash
1135
- proc_content.each do |k, v|
1136
- @original_atome.send(k, v)
1446
+ over_options.each do |over_option|
1447
+ proc_content = over_option.call(event) if event_validation(over_option)
1448
+ if proc_content.instance_of? Hash
1449
+ proc_content.each do |k, v|
1450
+ @original_atome.send(k, v)
1451
+ end
1137
1452
  end
1138
1453
  end
1139
1454
  end
1455
+ @over_over_already_set = true
1456
+ # unless @over_over_already_set
1457
+ # interact = JS.eval("return interact('##{@id}')")
1458
+ # over_overs = @original_atome.instance_variable_get('@over_code')[:flyover]
1459
+ # # return unless over_overs
1460
+ # over_overs.each do |over_over|
1461
+ # interact.on('mouseover') do |native_event|
1462
+ # over_over_event = Native(native_event)
1463
+ # # we use .call instead of instance_eval because instance_eval bring the current object as context
1464
+ # # and it's lead to a problem of context and force the use of grab(:view) when suing atome method such as shape ,
1465
+ # # group etc..
1466
+ #
1467
+ # proc_content = over_over.call(over_over_event) if event_validation(over_over)
1468
+ # if proc_content.instance_of? Hash
1469
+ # proc_content.each do |k, v|
1470
+ # @original_atome.send(k, v)
1471
+ # end
1472
+ # end
1473
+ # end
1474
+ # end
1475
+ # end
1476
+ # @over_over_already_set = true
1140
1477
  end
1141
1478
 
1142
1479
  def over_enter(_option)
1143
- @over_enter = @original_atome.instance_variable_get('@over_code')[:enter]
1144
- return unless @over_enter
1145
-
1146
- @over_enter_callback = lambda do |event|
1147
- # we use .call instead of instance_eval because instance_eval bring the current object as context
1148
- # and it's lead to a problem of context and force the use of grab(:view) when suing atome method such as shape ,
1149
- # group etc..
1150
- proc_content = @over_enter.call(event) if event_validation(@over_enter)
1151
- if proc_content.instance_of? Hash
1152
- proc_content.each do |k, v|
1153
- @original_atome.send(k, v)
1480
+ return if @over_enter_already_set
1481
+ @element.addEventListener('mouseenter') do |native_event|
1482
+ over_options = @original_atome.instance_variable_get('@over_code')[:enter]
1483
+ event = Native(native_event)
1484
+ over_options.each do |over_option|
1485
+ proc_content = over_option.call(event) if event_validation(over_option)
1486
+ if proc_content.instance_of? Hash
1487
+ proc_content.each do |k, v|
1488
+ @original_atome.send(k, v)
1489
+ end
1154
1490
  end
1155
1491
  end
1156
1492
  end
1157
- @element.addEventListener('mouseenter', @over_enter_callback)
1493
+ @over_enter_already_set = true
1494
+ # unless @over_enter_already_set
1495
+ # over_enters = @original_atome.instance_variable_get('@over_code')[:enter]
1496
+ # # return unless over_enters
1497
+ #
1498
+ # over_enters.each do |over_enter|
1499
+ # @over_enter_callback = lambda do |event|
1500
+ # # we use .call instead of instance_eval because instance_eval bring the current object as context
1501
+ # # and it's lead to a problem of context and force the use of grab(:view) when suing atome method such as shape ,
1502
+ # # group etc..
1503
+ # proc_content = over_enter.call(event) if event_validation(over_enter)
1504
+ # if proc_content.instance_of? Hash
1505
+ # proc_content.each do |k, v|
1506
+ # @original_atome.send(k, v)
1507
+ # end
1508
+ # end
1509
+ # end
1510
+ # @element.addEventListener('mouseenter', @over_enter_callback)
1511
+ #
1512
+ # end
1513
+ #
1514
+ # end
1515
+ # @over_enter_already_set = true
1158
1516
 
1159
1517
  end
1160
1518
 
1161
1519
  def over_leave(_option)
1162
-
1163
- @over_leave = @original_atome.instance_variable_get('@over_code')[:leave]
1164
- return unless @over_leave
1165
-
1166
- @over_leave_callback = lambda do |event|
1167
-
1168
- # we use .call instead of instance_eval because instance_eval bring the current object as context
1169
- # and it's lead to a problem of context and force the use of grab(:view) when suing atome method such as shape ,
1170
- # group etc..
1171
- proc_content = @over_leave.call(event) if event_validation(@over_leave)
1172
- if proc_content.instance_of? Hash
1173
- proc_content.each do |k, v|
1174
- @original_atome.send(k, v)
1520
+ return if @over_leave_already_set
1521
+ @element.addEventListener('mouseleave') do |native_event|
1522
+ over_leaves = @original_atome.instance_variable_get('@over_code')[:leave]
1523
+ event = Native(native_event)
1524
+ over_leaves.each do |over_leave|
1525
+ proc_content = over_leave.call(event) if event_validation(over_leave)
1526
+ if proc_content.instance_of? Hash
1527
+ proc_content.each do |k, v|
1528
+ @original_atome.send(k, v)
1529
+ end
1175
1530
  end
1176
1531
  end
1177
1532
  end
1178
- @element.addEventListener('mouseleave', @over_leave_callback)
1179
-
1533
+ @over_leave_already_set = true
1180
1534
  end
1181
1535
 
1182
1536
  def over_remove(option)
1183
1537
  case option
1184
1538
  when :enter
1185
- if @over_enter_callback
1186
- # Remove the event listener using the same lambda
1187
- @element.removeEventListener('mouseenter', @over_enter_callback)
1188
- @over_enter_callback = nil
1189
- @over_enter = nil
1190
- end
1539
+ @original_atome.instance_variable_get('@over_code')[:enter] = []
1191
1540
  when :leave
1192
- @element.removeEventListener('mouseleave', @over_leave_callback)
1193
- @over_leave_callback = nil
1194
- @over_leave = nil
1541
+ @original_atome.instance_variable_get('@over_code')[:leave] = []
1195
1542
  when :over
1196
- @over_over = ''
1543
+ @original_atome.instance_variable_get('@over_code')[:flyover] = []
1197
1544
  else
1198
- @element.removeEventListener('mouseenter', @over_enter_callback)
1199
- @over_enter_callback = nil
1200
- @over_enter = nil
1201
- @element.removeEventListener('mouseleave', @over_leave_callback)
1202
- @over_leave_callback = nil
1203
- @over_leave = nil
1204
- @over_over = ''
1545
+ over_remove(:enter)
1546
+ over_remove(:leave)
1547
+ over_remove(:over)
1205
1548
  end
1206
1549
  end
1207
1550
 
@@ -1209,155 +1552,119 @@ class HTML
1209
1552
  action_proc.is_a?(Proc) && (!Universe.edit_mode || @original_atome.tag[:system])
1210
1553
  end
1211
1554
 
1212
- def touch_down(_option)
1213
- @element[:style][:cursor] = 'pointer'
1214
- @touch_down = @original_atome.instance_variable_get('@touch_code')[:down]
1215
- interact = JS.eval("return interact('##{@id}')")
1216
- # unless @touch_removed[:down]
1217
- interact.on('down') do |native_event|
1218
- @touch_down_event = Native(native_event)
1219
- # we use .call instead of instance_eval because instance_eval bring the current object as context
1220
- # and it's lead to a problem of context and force the use of grab(:view) when suing atome method such as shape ,
1221
- # group etc..
1222
- proc_content = @touch_down.call(@touch_down_event) if event_validation(@touch_down)
1223
- if proc_content.instance_of? Hash
1224
- proc_content.each do |k, v|
1225
- @original_atome.send(k, v)
1226
- end
1227
- end
1228
- # end
1229
- # end
1230
- end
1231
- end
1232
-
1233
- def touch_tap(_option)
1234
- @element[:style][:cursor] = 'pointer'
1235
- interact = JS.eval("return interact('##{@id}')")
1236
- @touch_tap = @original_atome.instance_variable_get('@touch_code')[:tap]
1237
- # unless @touch_removed[:tap]
1238
- interact.on('tap') do |native_event|
1239
-
1240
- @touch_tap_event = Native(native_event)
1241
- # we use .call instead of instance_eval because instance_eval bring the current object as context
1242
- # and it's lead to a problem of context and force the use of grab(:view) when suing atome method such as shape ,
1243
- # group etc..
1244
- proc_content = @touch_tap.call(@touch_tap_event) if event_validation(@touch_tap)
1245
- if proc_content.instance_of? Hash
1246
- proc_content.each do |k, v|
1247
- # alert "(#{@original_atome.id}, #{k}, #{v}, #{_option})"
1248
- @original_atome.send(k, v)
1249
- end
1250
- end
1251
- end
1252
- # end
1253
- end
1555
+ def setup_touch_event(event_type, _option)
1556
+ instance_variable = "@touch_#{event_type}_already_set"
1557
+ unless instance_variable_get(instance_variable)
1558
+ @element[:style][:cursor] = 'pointer'
1559
+ interact = JS.eval("return interact('##{@id}')")
1560
+ interact.on(event_type) do |native_event|
1561
+ touch_event = Native(native_event)
1562
+ touch_needed = @original_atome.instance_variable_get('@touch_code')[event_type.to_sym]
1254
1563
 
1255
- def touch_up(_option)
1256
- @element[:style][:cursor] = 'pointer'
1257
- interact = JS.eval("return interact('##{@id}')")
1258
- @touch_up = @original_atome.instance_variable_get('@touch_code')[:up]
1259
- # unless @touch_removed[:up]
1260
- interact.on('up') do |native_event|
1261
- @touch_up_event = Native(native_event)
1262
- # we use .call instead of instance_eval because instance_eval bring the current object as context
1263
- # and it's lead to a problem of context and force the use of grab(:view) when suing atome method such as shape ,
1264
- # group etc..
1265
- proc_content = @touch_up.call(@touch_up_event) if event_validation(@touch_up)
1266
- if proc_content.instance_of? Hash
1267
- proc_content.each do |k, v|
1268
- @original_atome.send(k, v)
1269
- end
1270
- end
1271
- end
1272
- end
1273
-
1274
- def touch_double(_option)
1275
- @element[:style][:cursor] = 'pointer'
1276
- interact = JS.eval("return interact('##{@id}')")
1277
- @touch_double = @original_atome.instance_variable_get('@touch_code')[:double]
1278
- # unless @touch_removed[:double]
1279
- interact.on('doubletap') do |native_event|
1280
- @touch_double_event = Native(native_event)
1281
- # we use .call instead of instance_eval because instance_eval bring the current object as context
1282
- # and it's lead to a problem of context and force the use of grab(:view) when suing atome method such as shape ,
1283
- # group etc..
1284
- proc_content = @touch_double.call(@touch_double_event) if event_validation(@touch_double)
1285
- if proc_content.instance_of? Hash
1286
- proc_content.each do |k, v|
1287
- @original_atome.send(k, v)
1564
+ touch_needed.each do |proc_found|
1565
+ proc_content = proc_found.call(touch_event) if event_validation(proc_found)
1566
+ if proc_content.instance_of? Hash
1567
+ proc_content.each do |k, v|
1568
+ @original_atome.send(k, v)
1569
+ end
1570
+ end
1288
1571
  end
1289
1572
  end
1290
1573
  end
1291
-
1292
- end
1293
-
1294
- def touch_long(_option)
1295
- @element[:style][:cursor] = 'pointer'
1296
- @touch_long = @original_atome.instance_variable_get('@touch_code')[:long]
1297
- interact = JS.eval("return interact('##{@id}')")
1298
- # unless @touch_removed[:long]
1299
- interact.on('hold') do |native_event|
1300
- @touch_long_event = Native(native_event)
1301
- # we use .call instead of instance_eval because instance_eval bring the current object as context
1302
- # and it's lead to a problem of context and force the use of grab(:view) when suing atome method such as shape ,
1303
- # group etc..
1304
- proc_content = @touch_long.call(@touch_long_event) if event_validation(@touch_long)
1305
- if proc_content.instance_of? Hash
1306
- proc_content.each do |k, v|
1307
- @original_atome.send(k, v)
1308
- end
1309
- end
1574
+ instance_variable_set(instance_variable, true)
1575
+ end
1576
+
1577
+ def touch_down(option)
1578
+ setup_touch_event('down', option)
1579
+ end
1580
+
1581
+ def touch_up(option)
1582
+ setup_touch_event('up', option)
1583
+ end
1584
+
1585
+ def touch_tap(option)
1586
+ setup_touch_event('tap', option)
1587
+ end
1588
+
1589
+ def touch_double(option)
1590
+ setup_touch_event('doubletap', option)
1591
+ end
1592
+
1593
+ def touch_long(option)
1594
+ setup_touch_event('hold', option)
1595
+ end
1596
+
1597
+ # def touch_double(_option)
1598
+ # @element[:style][:cursor] = 'pointer'
1599
+ # interact = JS.eval("return interact('##{@id}')")
1600
+ # @touch_double = @original_atome.instance_variable_get('@touch_code')[:double]
1601
+ # # unless @touch_removed[:double]
1602
+ # interact.on('doubletap') do |native_event|
1603
+ # # we use an instance variable below instead of a local variable to be able to kill the event
1604
+ # @touch_double_event = Native(native_event)
1605
+ # # we use .call instead of instance_eval because instance_eval bring the current object as context
1606
+ # # and it's lead to a problem of context and force the use of grab(:view) when suing atome method such as shape ,
1607
+ # # group etc..
1608
+ # proc_content = @touch_double.call(@touch_double_event) if event_validation(@touch_double)
1609
+ # if proc_content.instance_of? Hash
1610
+ # proc_content.each do |k, v|
1611
+ # @original_atome.send(k, v)
1612
+ # end
1613
+ # end
1614
+ # end
1615
+ #
1616
+ # end
1617
+
1618
+ # def touch_long(_option)
1619
+ # @element[:style][:cursor] = 'pointer'
1620
+ # @touch_long = @original_atome.instance_variable_get('@touch_code')[:long]
1621
+ # interact = JS.eval("return interact('##{@id}')")
1622
+ # # unless @touch_removed[:long]
1623
+ # interact.on('hold') do |native_event|
1624
+ # @touch_long_event = Native(native_event)
1625
+ # # we use .call instead of instance_eval because instance_eval bring the current object as context
1626
+ # # and it's lead to a problem of context and force the use of grab(:view) when suing atome method such as shape ,
1627
+ # # group etc..
1628
+ # proc_content = @touch_long.call(@touch_long_event) if event_validation(@touch_long)
1629
+ # if proc_content.instance_of? Hash
1630
+ # proc_content.each do |k, v|
1631
+ # @original_atome.send(k, v)
1632
+ # end
1633
+ # end
1634
+ # end
1635
+ # end
1636
+ def remove_this_touch(option)
1637
+ @original_atome.instance_variable_get('@touch_code')[option] = [] if @original_atome.instance_variable_get('@touch_code')
1638
+ end
1639
+
1640
+ def touch_remove(_opt)
1641
+ if @original_atome.instance_variable_get('@touch_code')
1642
+ option = @original_atome.instance_variable_get('@touch_code')[:remove]
1643
+ else
1644
+ option = false
1310
1645
  end
1311
- end
1312
1646
 
1313
- def touch_remove(option)
1314
1647
  @element[:style][:cursor] = 'default'
1315
1648
  case option
1316
1649
  when :double
1317
- @touch_double = ''
1318
- @touch_removed[:double] = true
1319
- @touch_double_event= nil
1650
+ remove_this_touch(:double)
1320
1651
  when :down
1321
- @touch_down = ''
1322
- @touch_removed[:down] = true
1323
- @touch_down_event= nil
1652
+ remove_this_touch(:down)
1324
1653
  when :long
1325
- @touch_removed[:long] = true
1326
- @touch_long = ''
1327
- @touch_long_event= nil
1654
+ remove_this_touch(:long)
1328
1655
  when :tap
1329
- @touch_removed[:tap] = true
1330
- @touch_tap = ''
1331
- @touch_removed[:touch] = true
1332
- @touch_touch = ''
1333
- @touch_tap_event= nil
1334
-
1656
+ remove_this_touch(:tap)
1335
1657
  when :touch
1336
- @touch_removed[:tap] = true
1337
- @touch_tap = ''
1338
- @touch_removed[:touch] = true
1339
- @touch_touch = ''
1340
- @touch_tap_event= nil
1341
-
1658
+ remove_this_touch(:touch)
1342
1659
  when :up
1343
- @touch_removed[:up] = true
1344
- @touch_up = ''
1345
- @touch_up_event= nil
1660
+ remove_this_touch(:up)
1346
1661
  else
1347
- touch_remove(:double)
1348
- @touch_double_event= nil
1349
-
1350
- touch_remove(:down)
1351
- @touch_down_event= nil
1352
-
1353
- touch_remove(:long)
1354
- @touch_long_event= nil
1355
-
1356
- touch_remove(:tap)
1357
- touch_remove(:touch)
1358
- @touch_tap_event= nil
1359
- touch_remove(:up)
1360
- @touch_up_event= nil
1662
+ remove_this_touch(:double)
1663
+ remove_this_touch(:down)
1664
+ remove_this_touch(:long)
1665
+ remove_this_touch(:touch)
1666
+ remove_this_touch(:double)
1667
+ remove_this_touch(:up)
1361
1668
  end
1362
1669
 
1363
1670
  end
@@ -1740,12 +2047,12 @@ class HTML
1740
2047
 
1741
2048
  apply_centering(@center_options, @parent)
1742
2049
 
1743
- if @center_options[:dynamic]
1744
- event_handler = ->(event) do
1745
- apply_centering(@center_options, @parent)
1746
- end
1747
- JS.global[:window].addEventListener('resize', event_handler)
2050
+ return unless @center_options[:dynamic]
2051
+ event_handler = ->(event) do
2052
+ apply_centering(@center_options, @parent)
1748
2053
  end
2054
+ JS.global[:window].addEventListener('resize', event_handler)
2055
+
1749
2056
  end
1750
2057
 
1751
2058
  def record_audio(params)
@@ -1780,10 +2087,10 @@ class HTML
1780
2087
  @original_atome.left(x_position)
1781
2088
  end
1782
2089
 
1783
- if options[:y]
1784
- y_position = calculate_position(options[:y], parent.to_px(:height), @original_atome.to_px(:height))
1785
- @original_atome.top(y_position)
1786
- end
2090
+ return unless options[:y]
2091
+ y_position = calculate_position(options[:y], parent.to_px(:height), @original_atome.to_px(:height))
2092
+ @original_atome.top(y_position)
2093
+
1787
2094
  end
1788
2095
 
1789
2096
  def calculate_position(option, parent_dimension, self_dimension)