Class: Ferro::Xhr

Inherits:
Object
  • Object
show all
Defined in:
opal/opal-ferro/ferro_xhr.js.rb

Overview

Create and execute AJAX requests. Based on turbolinks/http_request. Specify the url for the request and two callbacks, one for succesful completion of the request and one for a failed request.

It is safe to destroy the FerroXhr instance after one of it’s callbacks have completed. Note that there are no private methods in Opal. Methods that should be private are marked in the docs with ‘Internal method’.

This class can only send and receive JSON. For non-get requests a csrf token can be specified or left blank. When blank this class will try to find the token in the header meta data.

Constant Summary collapse

TIMEOUT_FAILURE =

Error message for timeouts.

'Timeout'

Instance Method Summary collapse

Constructor Details

#initialize(url, callback, error_callback, options = {}) ⇒ Xhr

Start AJAX request.

Valid options are:

  • :timeout (Integer) Request-timout

  • :accept (String) Header-Accept

  • :method (Symbol) Html method, default: :get

  • :csrf (String) Csrf token, if blank and method is not :get, meta tag ‘csrf-token’ will be used

  • :body (Hash) Hash of parameters to be sent

Parameters:

  • url (String)

    The url for the request

  • callback (Method)

    Success callback method. The callback method should accept one parameter [Hash] containing the parsed json object returned by the AJAX call

  • error_callback (Method)

    Failure callback method. The callback method should accept two parameters [Integer, String] containing the status and error message

  • options (Hash) (defaults to: {})

    See valid options



43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
# File 'opal/opal-ferro/ferro_xhr.js.rb', line 43

def initialize(url, callback, error_callback, options = {})
  @url            = url
  @callback       = callback
  @error_callback = error_callback
  @timeout        = options[:timeout]  || 5000
  @accept         = options[:accept]   || 'application/json'
  @method         = (options[:method] || :get).upcase
  @csrf           = options[:csrf]
  @body           = options[:body] ? options[:body].to_json.to_s : nil
  @xhr            = nil
  @sent           = false

  createXHR
  send
end

Instance Method Details

#cancelObject

Cancel a running AJAX request.



68
69
70
# File 'opal/opal-ferro/ferro_xhr.js.rb', line 68

def cancel
  @xhr.JS.abort if @xhr && @sent
end

#createXHRObject

Internal method to set up the AJAX request.



73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
# File 'opal/opal-ferro/ferro_xhr.js.rb', line 73

def createXHR
  @xhr = `new XMLHttpRequest`

  `#{@xhr}.open(#{@method}, #{@url}, true)`
  `#{@xhr}.timeout = #{@timeout}`
  `#{@xhr}.setRequestHeader('Accept', #{@accept})`

  if @method != 'GET'
    `#{@xhr}.setRequestHeader('X-CSRF-Token', #{csrf_token})`
    if @body
      `#{@xhr}.setRequestHeader('Content-Type', #{@accept})`
      `#{@xhr}.setRequestHeader('Content-Length', #{@body.length})`
    end
  end

  `#{@xhr}.addEventListener('load',    function(){#{requestLoaded}})`
  `#{@xhr}.addEventListener('error',   function(){#{requestFailed}})`
  `#{@xhr}.addEventListener('timeout', function(){#{requestTimedOut}})`
  `#{@xhr}.addEventListener('abort',   function(){#{requestCanceled}})`
  nil
end

#csrf_tokenObject

Internal method to get the csrf token from header meta data.



96
97
98
99
100
# File 'opal/opal-ferro/ferro_xhr.js.rb', line 96

def csrf_token
  return @csrf if @csrf
  token = Native(`document.getElementsByName('csrf-token')`)
  @csrf = token[0].content if token.length > 0
end

#destroyObject

Internal method to clean up the AJAX request.



103
104
105
# File 'opal/opal-ferro/ferro_xhr.js.rb', line 103

def destroy
  `#{@xhr} = null`
end

#requestCanceledObject

Internal callback method.



141
142
143
# File 'opal/opal-ferro/ferro_xhr.js.rb', line 141

def requestCanceled
  destroy
end

#requestFailedObject

Internal callback method, will call the failure callback specified in initialize.



126
127
128
129
130
# File 'opal/opal-ferro/ferro_xhr.js.rb', line 126

def requestFailed
  @failed = true
  @error_callback.call(`#{@xhr}.status`, Native(`#{@xhr}.response`))
  destroy
end

#requestLoadedObject

Internal callback method, will call the success callback specified in initialize or the failure callback if the html return status is 300 or higher.



110
111
112
113
114
115
116
117
118
119
120
121
122
# File 'opal/opal-ferro/ferro_xhr.js.rb', line 110

def requestLoaded
  begin
    status = Native(`#{@xhr}.status`)
    raise if status >= 300
    json = JSON.parse(`#{@xhr}.response`)
    @callback.call(json)
  rescue => error
    @failed = true
    @error_callback.call(status, error)
  end

  destroy
end

#requestTimedOutObject

Internal callback method, will call the failure callback specified in initialize.



134
135
136
137
138
# File 'opal/opal-ferro/ferro_xhr.js.rb', line 134

def requestTimedOut
  @failed = true
  @error_callback.call(0, TIMEOUT_FAILURE)
  destroy
end

#sendObject

Internal method to start the AJAX request.



60
61
62
63
64
65
# File 'opal/opal-ferro/ferro_xhr.js.rb', line 60

def send
  if @xhr && !@sent
    @xhr.JS.send(@body)
    @sent = true
  end
end