aboutsummaryrefslogtreecommitdiffstats
path: root/actioncable/lib/assets
diff options
context:
space:
mode:
Diffstat (limited to 'actioncable/lib/assets')
-rw-r--r--actioncable/lib/assets/javascripts/action_cable.coffee.erb23
-rw-r--r--actioncable/lib/assets/javascripts/action_cable/connection.coffee81
-rw-r--r--actioncable/lib/assets/javascripts/action_cable/connection_monitor.coffee79
-rw-r--r--actioncable/lib/assets/javascripts/action_cable/consumer.coffee25
-rw-r--r--actioncable/lib/assets/javascripts/action_cable/subscription.coffee68
-rw-r--r--actioncable/lib/assets/javascripts/action_cable/subscriptions.coffee64
6 files changed, 0 insertions, 340 deletions
diff --git a/actioncable/lib/assets/javascripts/action_cable.coffee.erb b/actioncable/lib/assets/javascripts/action_cable.coffee.erb
deleted file mode 100644
index 7daea4ebcd..0000000000
--- a/actioncable/lib/assets/javascripts/action_cable.coffee.erb
+++ /dev/null
@@ -1,23 +0,0 @@
-#= require_self
-#= require action_cable/consumer
-
-@ActionCable =
- INTERNAL: <%= ActionCable::INTERNAL.to_json %>
-
- createConsumer: (url = @getConfig("url")) ->
- new ActionCable.Consumer @createWebSocketURL(url)
-
- getConfig: (name) ->
- element = document.head.querySelector("meta[name='action-cable-#{name}']")
- element?.getAttribute("content")
-
- createWebSocketURL: (url) ->
- if url and not /^wss?:/i.test(url)
- a = document.createElement("a")
- a.href = url
- # Fix populating Location properties in IE. Otherwise, protocol will be blank.
- a.href = a.href
- a.protocol = a.protocol.replace("http", "ws")
- a.href
- else
- url
diff --git a/actioncable/lib/assets/javascripts/action_cable/connection.coffee b/actioncable/lib/assets/javascripts/action_cable/connection.coffee
deleted file mode 100644
index fbd7dbd35b..0000000000
--- a/actioncable/lib/assets/javascripts/action_cable/connection.coffee
+++ /dev/null
@@ -1,81 +0,0 @@
-# Encapsulate the cable connection held by the consumer. This is an internal class not intended for direct user manipulation.
-
-{message_types} = ActionCable.INTERNAL
-
-class ActionCable.Connection
- @reopenDelay: 500
-
- constructor: (@consumer) ->
- @open()
-
- send: (data) ->
- if @isOpen()
- @webSocket.send(JSON.stringify(data))
- true
- else
- false
-
- open: =>
- if @webSocket and not @isState("closed")
- throw new Error("Existing connection must be closed before opening")
- else
- @webSocket = new WebSocket(@consumer.url)
- @installEventHandlers()
- true
-
- close: ->
- @webSocket?.close()
-
- reopen: ->
- if @isState("closed")
- @open()
- else
- try
- @close()
- finally
- setTimeout(@open, @constructor.reopenDelay)
-
- isOpen: ->
- @isState("open")
-
- # Private
-
- isState: (states...) ->
- @getState() in states
-
- getState: ->
- return state.toLowerCase() for state, value of WebSocket when value is @webSocket?.readyState
- null
-
- installEventHandlers: ->
- for eventName of @events
- handler = @events[eventName].bind(this)
- @webSocket["on#{eventName}"] = handler
- return
-
- events:
- message: (event) ->
- {identifier, message, type} = JSON.parse(event.data)
-
- switch type
- when message_types.confirmation
- @consumer.subscriptions.notify(identifier, "connected")
- when message_types.rejection
- @consumer.subscriptions.reject(identifier)
- else
- @consumer.subscriptions.notify(identifier, "received", message)
-
- open: ->
- @disconnected = false
- @consumer.subscriptions.reload()
-
- close: ->
- @disconnect()
-
- error: ->
- @disconnect()
-
- disconnect: ->
- return if @disconnected
- @disconnected = true
- @consumer.subscriptions.notifyAll("disconnected")
diff --git a/actioncable/lib/assets/javascripts/action_cable/connection_monitor.coffee b/actioncable/lib/assets/javascripts/action_cable/connection_monitor.coffee
deleted file mode 100644
index 99b9a1c6d5..0000000000
--- a/actioncable/lib/assets/javascripts/action_cable/connection_monitor.coffee
+++ /dev/null
@@ -1,79 +0,0 @@
-# Responsible for ensuring the cable connection is in good health by validating the heartbeat pings sent from the server, and attempting
-# revival reconnections if things go astray. Internal class, not intended for direct user manipulation.
-class ActionCable.ConnectionMonitor
- @pollInterval:
- min: 3
- max: 30
-
- @staleThreshold: 6 # Server::Connections::BEAT_INTERVAL * 2 (missed two pings)
-
- identifier: ActionCable.INTERNAL.identifiers.ping
-
- constructor: (@consumer) ->
- @consumer.subscriptions.add(this)
- @start()
-
- connected: ->
- @reset()
- @pingedAt = now()
- delete @disconnectedAt
-
- disconnected: ->
- @disconnectedAt = now()
-
- received: ->
- @pingedAt = now()
-
- reset: ->
- @reconnectAttempts = 0
-
- start: ->
- @reset()
- delete @stoppedAt
- @startedAt = now()
- @poll()
- document.addEventListener("visibilitychange", @visibilityDidChange)
-
- stop: ->
- @stoppedAt = now()
- document.removeEventListener("visibilitychange", @visibilityDidChange)
-
- poll: ->
- setTimeout =>
- unless @stoppedAt
- @reconnectIfStale()
- @poll()
- , @getInterval()
-
- getInterval: ->
- {min, max} = @constructor.pollInterval
- interval = 5 * Math.log(@reconnectAttempts + 1)
- clamp(interval, min, max) * 1000
-
- reconnectIfStale: ->
- if @connectionIsStale()
- @reconnectAttempts++
- unless @disconnectedRecently()
- @consumer.connection.reopen()
-
- connectionIsStale: ->
- secondsSince(@pingedAt ? @startedAt) > @constructor.staleThreshold
-
- disconnectedRecently: ->
- @disconnectedAt and secondsSince(@disconnectedAt) < @constructor.staleThreshold
-
- visibilityDidChange: =>
- if document.visibilityState is "visible"
- setTimeout =>
- if @connectionIsStale() or not @consumer.connection.isOpen()
- @consumer.connection.reopen()
- , 200
-
- now = ->
- new Date().getTime()
-
- secondsSince = (time) ->
- (now() - time) / 1000
-
- clamp = (number, min, max) ->
- Math.max(min, Math.min(max, number))
diff --git a/actioncable/lib/assets/javascripts/action_cable/consumer.coffee b/actioncable/lib/assets/javascripts/action_cable/consumer.coffee
deleted file mode 100644
index fcd8d0fb6c..0000000000
--- a/actioncable/lib/assets/javascripts/action_cable/consumer.coffee
+++ /dev/null
@@ -1,25 +0,0 @@
-#= require action_cable/connection
-#= require action_cable/connection_monitor
-#= require action_cable/subscriptions
-#= require action_cable/subscription
-
-# The ActionCable.Consumer establishes the connection to a server-side Ruby Connection object. Once established,
-# the ActionCable.ConnectionMonitor will ensure that its properly maintained through heartbeats and checking for stale updates.
-# The Consumer instance is also the gateway to establishing subscriptions to desired channels through the #createSubscription
-# method.
-#
-# The following example shows how this can be setup:
-#
-# @App = {}
-# App.cable = ActionCable.createConsumer "ws://example.com/accounts/1"
-# App.appearance = App.cable.subscriptions.create "AppearanceChannel"
-#
-# For more details on how you'd configure an actual channel subscription, see ActionCable.Subscription.
-class ActionCable.Consumer
- constructor: (@url) ->
- @subscriptions = new ActionCable.Subscriptions this
- @connection = new ActionCable.Connection this
- @connectionMonitor = new ActionCable.ConnectionMonitor this
-
- send: (data) ->
- @connection.send(data)
diff --git a/actioncable/lib/assets/javascripts/action_cable/subscription.coffee b/actioncable/lib/assets/javascripts/action_cable/subscription.coffee
deleted file mode 100644
index 339d676933..0000000000
--- a/actioncable/lib/assets/javascripts/action_cable/subscription.coffee
+++ /dev/null
@@ -1,68 +0,0 @@
-# A new subscription is created through the ActionCable.Subscriptions instance available on the consumer.
-# It provides a number of callbacks and a method for calling remote procedure calls on the corresponding
-# Channel instance on the server side.
-#
-# An example demonstrates the basic functionality:
-#
-# App.appearance = App.cable.subscriptions.create "AppearanceChannel",
-# connected: ->
-# # Called once the subscription has been successfully completed
-#
-# appear: ->
-# @perform 'appear', appearing_on: @appearingOn()
-#
-# away: ->
-# @perform 'away'
-#
-# appearingOn: ->
-# $('main').data 'appearing-on'
-#
-# The methods #appear and #away forward their intent to the remote AppearanceChannel instance on the server
-# by calling the `@perform` method with the first parameter being the action (which maps to AppearanceChannel#appear/away).
-# The second parameter is a hash that'll get JSON encoded and made available on the server in the data parameter.
-#
-# This is how the server component would look:
-#
-# class AppearanceChannel < ApplicationActionCable::Channel
-# def subscribed
-# current_user.appear
-# end
-#
-# def unsubscribed
-# current_user.disappear
-# end
-#
-# def appear(data)
-# current_user.appear on: data['appearing_on']
-# end
-#
-# def away
-# current_user.away
-# end
-# end
-#
-# The "AppearanceChannel" name is automatically mapped between the client-side subscription creation and the server-side Ruby class name.
-# The AppearanceChannel#appear/away public methods are exposed automatically to client-side invocation through the @perform method.
-class ActionCable.Subscription
- constructor: (@subscriptions, params = {}, mixin) ->
- @identifier = JSON.stringify(params)
- extend(this, mixin)
- @subscriptions.add(this)
- @consumer = @subscriptions.consumer
-
- # Perform a channel action with the optional data passed as an attribute
- perform: (action, data = {}) ->
- data.action = action
- @send(data)
-
- send: (data) ->
- @consumer.send(command: "message", identifier: @identifier, data: JSON.stringify(data))
-
- unsubscribe: ->
- @subscriptions.remove(this)
-
- extend = (object, properties) ->
- if properties?
- for key, value of properties
- object[key] = value
- object
diff --git a/actioncable/lib/assets/javascripts/action_cable/subscriptions.coffee b/actioncable/lib/assets/javascripts/action_cable/subscriptions.coffee
deleted file mode 100644
index ae041ffa2b..0000000000
--- a/actioncable/lib/assets/javascripts/action_cable/subscriptions.coffee
+++ /dev/null
@@ -1,64 +0,0 @@
-# Collection class for creating (and internally managing) channel subscriptions. The only method intended to be triggered by the user
-# us ActionCable.Subscriptions#create, and it should be called through the consumer like so:
-#
-# @App = {}
-# App.cable = ActionCable.createConsumer "ws://example.com/accounts/1"
-# App.appearance = App.cable.subscriptions.create "AppearanceChannel"
-#
-# For more details on how you'd configure an actual channel subscription, see ActionCable.Subscription.
-class ActionCable.Subscriptions
- constructor: (@consumer) ->
- @subscriptions = []
-
- create: (channelName, mixin) ->
- channel = channelName
- params = if typeof channel is "object" then channel else {channel}
- new ActionCable.Subscription this, params, mixin
-
- # Private
-
- add: (subscription) ->
- @subscriptions.push(subscription)
- @notify(subscription, "initialized")
- @sendCommand(subscription, "subscribe")
-
- remove: (subscription) ->
- @forget(subscription)
-
- unless @findAll(subscription.identifier).length
- @sendCommand(subscription, "unsubscribe")
-
- reject: (identifier) ->
- for subscription in @findAll(identifier)
- @forget(subscription)
- @notify(subscription, "rejected")
-
- forget: (subscription) ->
- @subscriptions = (s for s in @subscriptions when s isnt subscription)
-
- findAll: (identifier) ->
- s for s in @subscriptions when s.identifier is identifier
-
- reload: ->
- for subscription in @subscriptions
- @sendCommand(subscription, "subscribe")
-
- notifyAll: (callbackName, args...) ->
- for subscription in @subscriptions
- @notify(subscription, callbackName, args...)
-
- notify: (subscription, callbackName, args...) ->
- if typeof subscription is "string"
- subscriptions = @findAll(subscription)
- else
- subscriptions = [subscription]
-
- for subscription in subscriptions
- subscription[callbackName]?(args...)
-
- sendCommand: (subscription, command) ->
- {identifier} = subscription
- if identifier is ActionCable.INTERNAL.identifiers.ping
- @consumer.connection.isOpen()
- else
- @consumer.send({command, identifier})