live 0.6.0 → 0.8.0

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7df6409f470eb90e1f1f68cd70dabcf23cf56c2cbcbcc5707222bcac7d721338
4
- data.tar.gz: faac890736a9dc375e683405d29c534a55b7628e37abbcd64cfae0922ebdeda8
3
+ metadata.gz: 01e0a2e5881cd9cb589f93184b159a022a884a3b6549d6da54764ebe05bd8b81
4
+ data.tar.gz: 3cc1bd067307955f663cd9318bf60ec80dce9a4759df0935d3b00176c0183c85
5
5
  SHA512:
6
- metadata.gz: d1f0603af15f67f6db3677126f45f1c766bccecf99d93aaae0fc9018c0da5deaaa5f0156fe187ea9d90cac5bf813540de62e084c840bbe28eedfdc18a69fe4af
7
- data.tar.gz: 5db6880399468684e09034225faa3a63929563177d28b32ae67bbe9022158d15b98fc2ba0a967c6bd88177cb1b9518b85a45caeb3ef07309f446fe2b2b639862
6
+ metadata.gz: b74fd0f4365c5eb0fcf8ed1b8064ad5efd39ebcd56a12b4cb9e144a6dce0a503eb14f054fb16332b20abe905c364b36486b594ab9f4992fb645d41fff860be21
7
+ data.tar.gz: 80a79b3466c52e0cc0989416c547c06e39d9059a910489a16c713ab046a83480b10c645e33420fc31fa262894c02d9bcef01a7c9e3fe17e86f571524bc1eb519
checksums.yaml.gz.sig CHANGED
Binary file
data/lib/live/element.rb CHANGED
@@ -4,13 +4,18 @@
4
4
  # Copyright, 2021-2024, by Samuel Williams.
5
5
 
6
6
  require 'json'
7
+ require 'securerandom'
7
8
 
8
9
  module Live
9
10
  # Represents a single dynamic content area on the page.
10
11
  class Element
12
+ def self.unique_id
13
+ SecureRandom.uuid
14
+ end
15
+
11
16
  # @parameter id [String] The unique identifier within the page.
12
17
  # @parameter data [Hash] The data associated with the element, typically stored as `data-` attributes.
13
- def initialize(id, **data)
18
+ def initialize(id = Element.unique_id, **data)
14
19
  @id = id
15
20
  @data = data
16
21
  @data[:class] ||= self.class.name
@@ -21,13 +26,24 @@ module Live
21
26
  # The unique id within the bound page.
22
27
  attr :id
23
28
 
29
+ # The data associated with the element.
30
+ attr :data
31
+
24
32
  # Generate a JavaScript string which forwards the specified event to the server.
25
- # @parameter details [Hash] The details associated with the forwarded event.
26
- def forward(details = nil)
27
- if details
28
- "live.forward(#{JSON.dump(@id)}, event, #{JSON.dump(details)})"
33
+ # @parameter detail [Hash] The detail associated with the forwarded event.
34
+ def forward_event(detail = nil)
35
+ if detail
36
+ "live.forwardEvent(#{JSON.dump(@id)}, event, #{JSON.dump(detail)})"
37
+ else
38
+ "live.forwardEvent(#{JSON.dump(@id)}, event)"
39
+ end
40
+ end
41
+
42
+ def forward_form_event(detail = nil)
43
+ if detail
44
+ "live.forwardFormEvent(#{JSON.dump(@id)}, event, #{JSON.dump(detail)})"
29
45
  else
30
- "live.forward(#{JSON.dump(@id)}, event)"
46
+ "live.forwardFormEvent(#{JSON.dump(@id)}, event)"
31
47
  end
32
48
  end
33
49
 
@@ -49,9 +65,9 @@ module Live
49
65
  # Enqueue a remote procedure call to the currently bound page.
50
66
  # @parameter method [Symbol] The name of the remote functio to invoke.
51
67
  # @parameter arguments [Array]
52
- def rpc(method, arguments)
68
+ def rpc(*arguments)
53
69
  # This update might not be sent right away. Therefore, mutable arguments may be serialized to JSON at a later time (or never). This could be a race condition:
54
- @page.updates.enqueue([method, arguments])
70
+ @page.updates.enqueue(arguments)
55
71
  end
56
72
  end
57
73
  end
data/lib/live/page.rb CHANGED
@@ -43,14 +43,13 @@ module Live
43
43
  # Handle an event from the client. If the element could not be found, it is silently ignored.
44
44
  # @parameter id [String] The unique identifier of the element which forwarded the event.
45
45
  # @parameter event [String] The type of the event.
46
- # @parameter details [Hash] The associated details if any.
47
46
  # @returns [Object] The result of the element handler, if the element was found.
48
47
  # @returns [Nil] If the element could not be found.
49
48
  def handle(id, event)
50
49
  if element = @elements[id]
51
50
  return element.handle(event)
52
51
  else
53
- Console.logger.warn(self, "Could not handle event:", event, details)
52
+ Console.warn(self, "Could not handle event:", id:, event:)
54
53
  end
55
54
 
56
55
  return nil
@@ -64,16 +63,28 @@ module Live
64
63
 
65
64
  # Process a single incoming message from the network.
66
65
  def process_message(message)
67
- if id = message[:bind] and data = message[:data]
68
- if element = self.resolve(id, data)
66
+ case message[0]
67
+ when 'bind'
68
+ # Bind a client-side element to a server-side element.
69
+ if element = self.resolve(message[1], message[2])
69
70
  self.bind(element)
70
71
  else
71
- Console.logger.warn(self, "Could not resolve element:", message)
72
+ Console.warn(self, "Could not resolve element:", message)
73
+ # @updates.enqueue(['error', message[1], "Could not resolve element!"])
72
74
  end
73
- elsif id = message[:id]
74
- self.handle(id, message[:event])
75
+ when 'unbind'
76
+ # Unbind a client-side element from a server-side element.
77
+ if element = @elements.delete(message[1])
78
+ element.close
79
+ else
80
+ Console.warn(self, "Could not unbind element:", message)
81
+ @updates.enqueue(['error', message[1], "Could not unbind element!"])
82
+ end
83
+ when 'event'
84
+ # Handle an event from the client.
85
+ self.handle(message[1], message[2])
75
86
  else
76
- Console.logger.warn(self, "Unhandled message:", message)
87
+ Console.warn(self, "Unhandled message:", message)
77
88
  end
78
89
  end
79
90
 
@@ -82,7 +93,7 @@ module Live
82
93
  def run(connection)
83
94
  queue_task = Async do
84
95
  while update = @updates.dequeue
85
- Console.logger.debug(self, "Sending update:", update)
96
+ Console.debug(self, "Sending update:", update)
86
97
 
87
98
  connection.write(::Protocol::WebSocket::JSONMessage.generate(update))
88
99
  connection.flush if @updates.empty?
@@ -90,12 +101,12 @@ module Live
90
101
  end
91
102
 
92
103
  while message = connection.read
93
- Console.logger.debug(self, "Reading message:", message)
104
+ Console.debug(self, "Reading message:", message)
94
105
 
95
106
  if json_message = ::Protocol::WebSocket::JSONMessage.wrap(message)
96
107
  process_message(json_message.parse)
97
108
  else
98
- Console.logger.warn(self, "Unhandled message:", message)
109
+ Console.warn(self, "Unhandled message:", message)
99
110
  end
100
111
  end
101
112
  ensure
data/lib/live/version.rb CHANGED
@@ -4,5 +4,5 @@
4
4
  # Copyright, 2021-2024, by Samuel Williams.
5
5
 
6
6
  module Live
7
- VERSION = "0.6.0"
7
+ VERSION = "0.8.0"
8
8
  end
data/lib/live/view.rb CHANGED
@@ -9,21 +9,40 @@ require 'xrb/builder'
9
9
  module Live
10
10
  # Represents a single division of content on the page an provides helpers for rendering the content.
11
11
  class View < Element
12
+ # Update the content of the client-side element by rendering this view.
13
+ def update!(**options)
14
+ rpc(:update, @id, self.to_html, options)
15
+ end
16
+
12
17
  # Replace the content of the client-side element by rendering this view.
13
- def replace!
14
- rpc(:replace, [@id, self.to_html])
18
+ # @parameter selector [String] The CSS selector to replace.
19
+ # @parameter node [String] The HTML to replace.
20
+ def replace(selector, node, **options)
21
+ rpc(:replace, selector, node.to_s, options)
22
+ end
23
+
24
+ # Prepend to the content of the client-side element by appending the specified element.
25
+ # @parameter selector [String] The CSS selector to prepend to.
26
+ # @parameter node [String] The HTML to prepend.
27
+ def prepend(selector, node, **options)
28
+ rpc(:prepend, selector, node.to_s, options)
15
29
  end
16
30
 
17
31
  # Append to the content of the client-side element by appending the specified element.
18
- # @parameter node [Live::Element] The element to append.
19
- def append!(element)
20
- rpc(:append, [@id, element.to_html])
32
+ # @parameter selector [String] The CSS selector to append to.
33
+ # @parameter node [String] The HTML to prepend.
34
+ def append(selector, node, **options)
35
+ rpc(:append, selector, node.to_s, options)
21
36
  end
22
37
 
23
- # Prepend to the content of the client-side element by appending the specified element.
24
- # @parameter node [Live::Element] The element to prepend.
25
- def prepend!(element)
26
- rpc(:prepend, [@id, element.to_html])
38
+ # Remove the specified element from the client-side element.
39
+ # @parameter selector [String] The CSS selector to remove.
40
+ def remove(selector, **options)
41
+ rpc(:remove, selector, options)
42
+ end
43
+
44
+ def dispatch_event(selector, type, **options)
45
+ rpc(:dispatch_event, selector, event, options)
27
46
  end
28
47
 
29
48
  # Render the element.
data/lib/live.rb CHANGED
@@ -7,4 +7,4 @@ require_relative "live/version"
7
7
 
8
8
  require_relative 'live/page'
9
9
  require_relative 'live/view'
10
-
10
+ require_relative 'live/resolver'
data.tar.gz.sig CHANGED
Binary file
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: live
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.0
4
+ version: 0.8.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Samuel Williams
@@ -38,7 +38,7 @@ cert_chain:
38
38
  Q2K9NVun/S785AP05vKkXZEFYxqG6EW012U4oLcFl5MySFajYXRYbuUpH6AY+HP8
39
39
  voD0MPg1DssDLKwXyt1eKD/+Fq0bFWhwVM/1XiAXL7lyYUyOq24KHgQ2Csg=
40
40
  -----END CERTIFICATE-----
41
- date: 2024-04-28 00:00:00.000000000 Z
41
+ date: 2024-05-05 00:00:00.000000000 Z
42
42
  dependencies:
43
43
  - !ruby/object:Gem::Dependency
44
44
  name: async-websocket
metadata.gz.sig CHANGED
Binary file