opal-jquery
offers a nicer ruby-like syntax for JQuery. It is useful for projects which cannot use opal-browser
due to a reliance on jquery for plugins or other libraries.
foos = Element.find('.foo')
# => [<div class="foo">, ...]
foos.class
# => JQuery
foos.on(:click) do
alert "element was clicked"
end
opal-jquery
is distributed as a gem, and needs to be added to your Gemfile
:
# Gemfile
gem 'opal'
gem 'opal-jquery'
opal-jquery
can now be easily added to your opal application sources:
# app/application.rb
# Remember to compile opal-jquery with your javascript application.
# See "Compiling" below for an example on compiling dependencies.
require 'opal/jquery'
alert "Hello from jquery + opal"
The #alert
method is provided by opal-jquery
. If the message displays, then
jquery
support should be working.
When compiling your application to javascript, you must be sure to include both Opal and Opal-JQuery so they'll be available to your application:
require 'opal'
require 'opal-jquery'
builder = Opal::Builder.new
builder.build('opal')
builder.build('opal-jquery')
builder.build('./app/application.rb')
File.binwrite('application.js', builder.to_s) # must use binary mode for writing
then simply load the compiled file in your html:
<!DOCTYPE html>
<html>
<head>
<script src='https://code.jquery.com/jquery-3.3.1.min.js' integrity='sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8=' crossorigin='anonymous'></script>
<script type='text/javascript' src='./application.js'></script>
</head>
<body></body>
</html>
opal-jquery expects a jquery library to be loaded. This example loads it remotely from jquery.com, but a locally downloaded copy works just as well, or- if you're using rails- jquery may be included automatically.
This example builds opal, opal-jquery and the application into a single .js
file,
but you may build them separately, if you so choose. Just remember to include
each respective script in your html!
opal-jquery
provides an Element
class, whose instances are toll-free
bridged instances of jquery objects. Just like ruby arrays are just javascript
arrays, Element
instances are just jquery objects. This makes interaction
with jquery plugins much easier.
opal-jquery provides the Element
class, which can be used to find elements in
the current document:
Element.find('#header')
Element.find
is aliased to Element[]
:
Element['.my-class']
These methods acts just like $('selector')
, and can use any jQuery
compatible selector:
Element.find('#navigation li:last')
The result is just a jQuery instance, which is toll-free bridged to
instances of the Element
class in ruby:
Element.find('.foo').class
# => Element
Instances of Element
also have the #find
method available for
finding elements within the scope of each DOM node represented by
the instance:
el = Element.find('#header')
el.find '.foo'
# => #<Element .... >
Just like jQuery, opal-jquery requires the document to be ready to
be able to fully interact with the page. Any top level access should
use the ready?
method:
Document.ready? do
alert "document is ready to go!"
end
The Kernel#alert
method is shown above too.
The Element#on
method is used to attach event handlers to elements:
Element.find('#header').on :click do
puts "The header was clicked!"
end
Selectors can also be passed as a second argument to handle events on certain children:
Element.find('#header').on(:click, '.foo') do
puts "An element with a 'foo' class was clicked"
end
An Event
instance is optionally passed to block handlers as well,
which is toll-free bridged to jquery events:
Element.find('#my_link').on(:click) do |evt|
evt.stop_propagation
puts "stopped the event!"
end
You can access the element which triggered the event by #current_target
.
Document.on :click do |evt|
puts "clicked on: #{evt.current_target}"
end
The various jQuery methods are available on Element
instances:
foo = Element.find('.foo')
foo.add_class 'blue'
foo.remove_class 'foo'
foo.toggle_class 'selected'
There are also added convenience methods for opal-jquery:
foo = Element.find('#header')
foo.class_name
# => 'red lorry'
foo.class_name = 'yellow house'
foo.class_name
# => 'yellow house'
Element#css
also exists for getting/setting css styles:
el = Element.find('#container')
el.css 'color', 'blue'
el.css 'color'
# => 'blue'
jQuery's Ajax implementation is also wrapped in the top level HTTP class.
HTTP.get("/users/1.json") do |response|
puts response.body
# => "{\"name\": \"Adam Beynon\"}"
end
The block passed to this method is used as the handler when the request
succeeds, as well as when it fails. To determine whether the request
was successful, use the ok?
method:
HTTP.get("/users/2.json") do |response|
if response.ok?
alert "successful!"
else
alert "request failed :("
end
end
It is also possible to use a different handler for each case:
request = HTTP.get("/users/3.json")
request.callback {
puts "Request worked!"
}
request.errback {
puts "Request didn't work :("
}
The request is actually triggered inside the HTTP.get
method, but due
to the async nature of the request, the callback and errback handlers can
be added anytime before the request returns.
Web apps deal with JSON responses quite frequently, so there is a useful
#json
helper method to get the JSON content from a request:
HTTP.get("/users.json") do |response|
puts response.body
puts response.json
end
# => "[{\"name\": \"Adam\"},{\"name\": \"Ben\"}]"
# => [{"name" => "Adam"}, {"name" => "Ben"}]
The #body
method will always return the raw response string.
If an error is encountered, then the #status_code
method will hold the
specific error code from the underlying request:
request = HTTP.get("/users/3.json")
request.callback { puts "it worked!" }
request.errback { |response|
puts "failed with status #{response.status_code}"
}