opal-jquery 0.3.0.beta1 → 0.3.0.beta2
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 +4 -4
- data/.gitignore +1 -0
- data/.travis.yml +1 -2
- data/.yardopts +3 -0
- data/CHANGELOG.md +21 -8
- data/Gemfile +2 -2
- data/README.md +85 -68
- data/lib/opal/jquery.rb +12 -3
- data/{opal/opal-jquery → lib/opal/jquery}/constants.rb +0 -0
- data/lib/opal/jquery/document.rb +93 -0
- data/lib/opal/jquery/element.rb +669 -0
- data/lib/opal/jquery/event.rb +205 -0
- data/lib/opal/jquery/http.rb +270 -0
- data/lib/opal/jquery/kernel.rb +11 -0
- data/lib/opal/jquery/local_storage.rb +87 -0
- data/lib/opal/jquery/rspec.rb +65 -0
- data/lib/opal/jquery/version.rb +1 -1
- data/lib/opal/jquery/window.rb +40 -0
- data/opal-jquery.gemspec +2 -2
- data/spec/element/after_spec.rb +10 -10
- data/spec/element/animations_spec.rb +34 -13
- data/spec/element/attributes_spec.rb +27 -14
- data/spec/element/to_s_spec.rb +14 -0
- data/spec/http_spec.rb +25 -22
- data/spec/local_storage_spec.rb +1 -1
- data/spec/spec_helper.rb +6 -28
- metadata +19 -16
- data/opal/opal-jquery.rb +0 -6
- data/opal/opal-jquery/document.rb +0 -31
- data/opal/opal-jquery/element.rb +0 -339
- data/opal/opal-jquery/event.rb +0 -96
- data/opal/opal-jquery/http.rb +0 -164
- data/opal/opal-jquery/kernel.rb +0 -6
- data/opal/opal-jquery/local_storage.rb +0 -31
- data/opal/opal-jquery/window.rb +0 -4
@@ -0,0 +1,87 @@
|
|
1
|
+
module Browser
|
2
|
+
# {Browser::LocalStorage} is a simple wrapper around `localStorage` in the
|
3
|
+
# browser.
|
4
|
+
#
|
5
|
+
# Instead of using the class directly, the main instance {LocalStorage}
|
6
|
+
# should be used instead. This class can be used to wrap an instance from
|
7
|
+
# another window or iframe if required.
|
8
|
+
#
|
9
|
+
# ## Usage
|
10
|
+
#
|
11
|
+
# LocalStorage is not included by default when you require opal-jquery, so
|
12
|
+
# you will need to require it explicitly in your code:
|
13
|
+
#
|
14
|
+
# require 'opal/jquery'
|
15
|
+
# require 'opal/jquery/local_storage'
|
16
|
+
#
|
17
|
+
# puts LocalStorage
|
18
|
+
# # => #<LocalStorage>
|
19
|
+
#
|
20
|
+
# ## Example Usage
|
21
|
+
#
|
22
|
+
# LocalStorage['foo'] = 'hello world'
|
23
|
+
#
|
24
|
+
# LocalStorage['foo'] # => "hello world"
|
25
|
+
# LocalStorage['bar'] # => nil
|
26
|
+
#
|
27
|
+
# @see LocalStorage
|
28
|
+
#
|
29
|
+
class LocalStorage
|
30
|
+
def initialize(storage)
|
31
|
+
@storage = storage
|
32
|
+
end
|
33
|
+
|
34
|
+
# Set a value in storage.
|
35
|
+
#
|
36
|
+
# Values stored in {LocalStorage} will be stored as strings. To store any
|
37
|
+
# other type of object, you will need to convert them to a string first,
|
38
|
+
# and then convert them back from {#[]}. For this reason it is recommended
|
39
|
+
# to only store {JSON} based objects in storage, so they can be easily
|
40
|
+
# converted back and forth.
|
41
|
+
#
|
42
|
+
# @param key [String] string key
|
43
|
+
# @param value [String, #to_s] string or explicitly converted object
|
44
|
+
def []=(key, value)
|
45
|
+
%x{
|
46
|
+
#@storage.setItem(key, value);
|
47
|
+
return value;
|
48
|
+
}
|
49
|
+
end
|
50
|
+
|
51
|
+
# Retrieve an object from {LocalStorage}.
|
52
|
+
#
|
53
|
+
# Only string values can be stored, so any object will be returned as a
|
54
|
+
# string. You will need to handle any conversion back into a normal
|
55
|
+
# object. {JSON.parse} could be used, for example, to parse back into
|
56
|
+
# arrays or hashes.
|
57
|
+
#
|
58
|
+
# If a key is not present in the storage, then `nil` will be returned.
|
59
|
+
#
|
60
|
+
# @param key [String] key to lookup
|
61
|
+
# @return [String, nil]
|
62
|
+
def [](key)
|
63
|
+
%x{
|
64
|
+
var value = #@storage.getItem(key);
|
65
|
+
return value == null ? nil : value;
|
66
|
+
}
|
67
|
+
end
|
68
|
+
|
69
|
+
# Removes a specific `key` from storage. If the key does not exist then
|
70
|
+
# there is no side effect.
|
71
|
+
#
|
72
|
+
# @param key [String] key to remove
|
73
|
+
def delete(key)
|
74
|
+
`#@storage.removeItem(key)`
|
75
|
+
end
|
76
|
+
|
77
|
+
# Remove all key/values from storage
|
78
|
+
def clear
|
79
|
+
`#@storage.clear()`
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
# {LocalStorage} is the top level instance of {Browser::LocalStorage} that
|
85
|
+
# wraps `window.localStorage`, aka the `localStorage` object available on
|
86
|
+
# the main window.
|
87
|
+
LocalStorage = Browser::LocalStorage.new(`window.localStorage`)
|
@@ -0,0 +1,65 @@
|
|
1
|
+
module Browser
|
2
|
+
# When testing (using rspec), this module provides some helper methods to
|
3
|
+
# try and make testing a little easier.
|
4
|
+
#
|
5
|
+
# ## Usage
|
6
|
+
#
|
7
|
+
# Simply require this file somewher (usualy in `spec_helper.rb`):
|
8
|
+
#
|
9
|
+
# require 'application'
|
10
|
+
# require 'opal-rspec'
|
11
|
+
# require 'opal/jquery/rspec'
|
12
|
+
#
|
13
|
+
# Once required, the module is registered with `rspec` for all example
|
14
|
+
# groups.
|
15
|
+
#
|
16
|
+
# ## Adding html to DOM
|
17
|
+
#
|
18
|
+
# It is often convenient to have some `HTML` code ready in the dom for
|
19
|
+
# testing. This helper method adds the given html string. More so, the html
|
20
|
+
# is then removed at the end of each test. This is cruicial as it ensures
|
21
|
+
# that the specified html code is inserted before each test, therefore
|
22
|
+
# ensuring that html code changed by a test will not affect any other tests
|
23
|
+
# in the same scope.
|
24
|
+
#
|
25
|
+
# describe "Check DOM code" do
|
26
|
+
# html '<div id="foo"></div>'
|
27
|
+
#
|
28
|
+
# it "foo should exist" do
|
29
|
+
# expect(Document['#foo']).to_not be_empty
|
30
|
+
# end
|
31
|
+
# end
|
32
|
+
#
|
33
|
+
module RSpecHelpers
|
34
|
+
# Add some html code to the body tag ready for testing. This will
|
35
|
+
# be added before each test, then removed after each test. It is
|
36
|
+
# convenient for adding html setup quickly. The code is wrapped
|
37
|
+
# inside a div, which is directly inside the body element.
|
38
|
+
#
|
39
|
+
# describe "DOM feature" do
|
40
|
+
# html <<-HTML
|
41
|
+
# <div id="foo"></div>
|
42
|
+
# HTML
|
43
|
+
#
|
44
|
+
# it "foo should exist" do
|
45
|
+
# Document["#foo"]
|
46
|
+
# end
|
47
|
+
# end
|
48
|
+
#
|
49
|
+
# @param [String] html_string html content to add
|
50
|
+
def html(html_string='')
|
51
|
+
html = %Q{<div id="opal-jquery-test-div">#{html_string}</div>}
|
52
|
+
|
53
|
+
before do
|
54
|
+
@_spec_html = Element.parse(html)
|
55
|
+
@_spec_html.append_to_body
|
56
|
+
end
|
57
|
+
|
58
|
+
after { @_spec_html.remove }
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
RSpec.configure do |config|
|
64
|
+
config.extend Browser::RSpecHelpers
|
65
|
+
end
|
data/lib/opal/jquery/version.rb
CHANGED
@@ -0,0 +1,40 @@
|
|
1
|
+
require 'opal/jquery/element'
|
2
|
+
|
3
|
+
module Browser
|
4
|
+
# {Window} instances are {Native} objects used to wrap native window instances.
|
5
|
+
#
|
6
|
+
# Generally, you will want to use the top level {::Window} instance, which
|
7
|
+
# wraps `window` from the main page.
|
8
|
+
class Window
|
9
|
+
include Native
|
10
|
+
|
11
|
+
# Returns this {Window} instance wrapped as an {Element}. Useful for
|
12
|
+
# delegating jQuery events, which allows the use of `window` as target.
|
13
|
+
#
|
14
|
+
# @return [Element]
|
15
|
+
def element
|
16
|
+
@element ||= Element.find(`window`)
|
17
|
+
end
|
18
|
+
|
19
|
+
# @see Element#on
|
20
|
+
def on(*args, &block)
|
21
|
+
element.on(*args, &block)
|
22
|
+
end
|
23
|
+
|
24
|
+
# @see Element#off
|
25
|
+
def off(*args, &block)
|
26
|
+
element.off(*args, &block)
|
27
|
+
end
|
28
|
+
|
29
|
+
# @see Element#trigger
|
30
|
+
def trigger(*args)
|
31
|
+
element.trigger(*args)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
# Top level {Browser::Window} instance.
|
37
|
+
Window = Browser::Window.new(`window`)
|
38
|
+
|
39
|
+
# TODO: this will be removed soon.
|
40
|
+
$window = Window
|
data/opal-jquery.gemspec
CHANGED
@@ -15,8 +15,8 @@ Gem::Specification.new do |s|
|
|
15
15
|
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
16
16
|
s.require_paths = ['lib']
|
17
17
|
|
18
|
-
s.add_runtime_dependency 'opal', '~> 0.7.0.
|
19
|
-
s.add_development_dependency 'opal-rspec', '~> 0.4.0.
|
18
|
+
s.add_runtime_dependency 'opal', '~> 0.7.0.beta3'
|
19
|
+
s.add_development_dependency 'opal-rspec', '~> 0.4.0.beta4'
|
20
20
|
s.add_development_dependency 'yard'
|
21
21
|
s.add_development_dependency 'rake'
|
22
22
|
end
|
data/spec/element/after_spec.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
|
-
require
|
1
|
+
require 'spec_helper'
|
2
2
|
|
3
|
-
describe
|
3
|
+
describe 'Element#after' do
|
4
4
|
html <<-HTML
|
5
5
|
<div id="some-header" class="kapow"></div>
|
6
6
|
<div id="foo" class="after-spec-first"></div>
|
@@ -8,18 +8,18 @@ describe "Element#after" do
|
|
8
8
|
<div id="baz"></div>
|
9
9
|
HTML
|
10
10
|
|
11
|
-
it
|
12
|
-
el =
|
13
|
-
el.size.
|
11
|
+
it 'should insert the given html string after each element' do
|
12
|
+
el = find '.after-spec-first'
|
13
|
+
expect(el.size).to eq(2)
|
14
14
|
|
15
15
|
el.after '<p class="woosh"></p>'
|
16
16
|
|
17
|
-
|
18
|
-
|
17
|
+
expect(find('#foo').next.class_name).to eq('woosh')
|
18
|
+
expect(find('#bar').next.class_name).to eq('woosh')
|
19
19
|
end
|
20
20
|
|
21
|
-
it
|
22
|
-
|
23
|
-
|
21
|
+
it 'should insert the given DOM element after this element' do
|
22
|
+
find('#baz').after find('#some-header')
|
23
|
+
expect(find('#baz').next.id).to eq('some-header')
|
24
24
|
end
|
25
25
|
end
|
@@ -10,12 +10,12 @@ describe "Element animation methods" do
|
|
10
10
|
# jQUery's animate method doesn't *always* finish on time
|
11
11
|
# so the values are being compared using greater than
|
12
12
|
|
13
|
-
|
13
|
+
async "should animate a set of properties and values" do
|
14
14
|
foo = Element.find "#animate-foo"
|
15
15
|
foo.animate :width => "200px"
|
16
16
|
|
17
|
-
|
18
|
-
(foo.css("width").to_f > 199).should eq(true)
|
17
|
+
delay 0.4 do
|
18
|
+
async { (foo.css("width").to_f > 199).should eq(true) }
|
19
19
|
end
|
20
20
|
end
|
21
21
|
|
@@ -23,11 +23,9 @@ describe "Element animation methods" do
|
|
23
23
|
foo = Element.find "#animate-foo"
|
24
24
|
foo.animate :width => "200px", :speed => 100
|
25
25
|
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
end
|
30
|
-
}
|
26
|
+
delay 0.150 do
|
27
|
+
async { (foo.css("width").to_f > 199).should eq(true) }
|
28
|
+
end
|
31
29
|
end
|
32
30
|
|
33
31
|
async "should accept a block as a callback" do
|
@@ -36,11 +34,34 @@ describe "Element animation methods" do
|
|
36
34
|
foo.add_class "finished"
|
37
35
|
end
|
38
36
|
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
end
|
43
|
-
}
|
37
|
+
delay 0.405 do
|
38
|
+
async { foo.class_name.should eq("finished") }
|
39
|
+
end
|
44
40
|
end
|
45
41
|
end
|
46
42
|
end
|
43
|
+
|
44
|
+
describe "Element effects methods" do
|
45
|
+
html <<-HTML
|
46
|
+
<div id="effects-foo"></div>
|
47
|
+
HTML
|
48
|
+
|
49
|
+
describe "#fadeout / #fadein" do
|
50
|
+
async "should fade the element out first" do
|
51
|
+
foo = Element.find "#effects-foo"
|
52
|
+
foo.effect(:fade_out)
|
53
|
+
|
54
|
+
delay 1 do
|
55
|
+
async {
|
56
|
+
foo.css("display").should eq("none")
|
57
|
+
foo.effect(:fade_in)
|
58
|
+
}
|
59
|
+
end
|
60
|
+
end
|
61
|
+
async "should fade the element back in" do
|
62
|
+
delay 2 do
|
63
|
+
async { Element["#effects-foo"].css("display").should eq("block") }
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
@@ -45,19 +45,30 @@ describe Element do
|
|
45
45
|
Element.find('#attr-foo')[:title].should == "Hello there!"
|
46
46
|
end
|
47
47
|
|
48
|
-
it 'should return
|
49
|
-
Element.find('#attr-bar')[:title].
|
50
|
-
Element.find('#attr-baz')[:title].
|
48
|
+
it 'should return nil for an empty attribute' do
|
49
|
+
expect(Element.find('#attr-bar')[:title]).to be_nil
|
50
|
+
expect(Element.find('#attr-baz')[:title]).to be_nil
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
describe '#attr' do
|
55
|
+
it 'returns attributes from elements' do
|
56
|
+
expect(Element.find('#attr-foo').attr(:title)).to eq('Hello there!')
|
57
|
+
end
|
58
|
+
|
59
|
+
it 'returns nil for empty attributes' do
|
60
|
+
expect(Element.find('#attr-bar').attr(:title)).to be_nil
|
61
|
+
expect(Element.find('#attr-baz').attr(:title)).to be_nil
|
51
62
|
end
|
52
63
|
end
|
53
64
|
|
54
65
|
describe '#[]=' do
|
55
66
|
it 'should set the attr value on the element' do
|
56
67
|
woosh = Element.find '#attr-woosh'
|
57
|
-
woosh[:title].
|
68
|
+
expect(woosh[:title]).to be_nil
|
58
69
|
|
59
70
|
woosh[:title] = "Oranges"
|
60
|
-
woosh[:title].
|
71
|
+
expect(woosh[:title]).to eq('Oranges')
|
61
72
|
end
|
62
73
|
|
63
74
|
it 'should replace the old value for the attribute' do
|
@@ -72,30 +83,32 @@ describe Element do
|
|
72
83
|
describe "#add_class" do
|
73
84
|
it "should add the given class name to the element" do
|
74
85
|
foo = Element.find '#foo'
|
75
|
-
foo.
|
86
|
+
expect(foo).to_not have_class('lemons')
|
87
|
+
|
76
88
|
foo.add_class 'lemons'
|
77
|
-
foo.
|
89
|
+
expect(foo).to have_class('lemons')
|
78
90
|
end
|
79
91
|
|
80
92
|
it "should not duplicate class names on an element" do
|
81
93
|
bar = Element.find '#bar'
|
82
|
-
bar.
|
94
|
+
expect(bar).to have_class('apples')
|
95
|
+
|
83
96
|
bar.add_class 'apples'
|
84
|
-
bar.class_name.
|
97
|
+
expect(bar.class_name).to eq('apples')
|
85
98
|
end
|
86
99
|
|
87
100
|
it "should return self" do
|
88
101
|
baz = Element.find '#baz'
|
89
|
-
baz.add_class('oranges').
|
90
|
-
baz.add_class('oranges').should equal(baz)
|
102
|
+
expect(baz.add_class('oranges')).to eq(baz)
|
91
103
|
end
|
92
104
|
end
|
93
105
|
|
94
106
|
describe '#has_class?' do
|
95
107
|
it "should return true if the element has the given class" do
|
96
|
-
Element.find('#has-foo')
|
97
|
-
Element.find('#has-
|
98
|
-
|
108
|
+
expect(Element.find('#has-foo')).to have_class('apples')
|
109
|
+
expect(Element.find('#has-bar')).to have_class('lemons')
|
110
|
+
|
111
|
+
expect(Element.find('#has-foo')).to_not have_class('oranges')
|
99
112
|
end
|
100
113
|
end
|
101
114
|
|
@@ -0,0 +1,14 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe "Element#to_s" do
|
4
|
+
html <<-HTML
|
5
|
+
<div id="foo">hi</div>
|
6
|
+
<div class="bar"></div>
|
7
|
+
<p id="lol" class="bar"></div>
|
8
|
+
HTML
|
9
|
+
|
10
|
+
it "returns a string representation of the elements" do
|
11
|
+
Element.find('#foo').to_s.should == '<div id="foo">hi</div>'
|
12
|
+
Element.find('.bar').to_s.should == '<div class="bar"></div>, <p id="lol" class="bar"></p>'
|
13
|
+
end
|
14
|
+
end
|
data/spec/http_spec.rb
CHANGED
@@ -1,46 +1,49 @@
|
|
1
1
|
require "spec_helper"
|
2
2
|
|
3
3
|
describe HTTP do
|
4
|
+
let(:good_url) { '/spec/fixtures/simple.txt' }
|
5
|
+
let(:json_url) { '/spec/fixtures/user.json' }
|
6
|
+
let(:bad_url) { '/spec/fixtures/does_not_exist.txt' }
|
7
|
+
|
4
8
|
describe ".setup" do
|
5
9
|
it 'presents the $.ajaxSetup() object as a Hash' do
|
6
|
-
HTTP.setup.
|
10
|
+
expect(HTTP.setup).to be_a Hash
|
7
11
|
end
|
8
12
|
end
|
9
13
|
|
10
14
|
describe ".get" do
|
11
|
-
|
15
|
+
describe "with a block" do
|
12
16
|
it "returns the http object instance" do
|
13
|
-
HTTP.get(
|
14
|
-
end.should be_a HTTP
|
17
|
+
expect(HTTP.get(good_url) {}).to be_a HTTP
|
15
18
|
end
|
16
19
|
|
17
20
|
async "block gets called on success" do
|
18
|
-
HTTP.get(
|
19
|
-
|
21
|
+
HTTP.get(good_url) do |response|
|
22
|
+
async { expect(response).to be_ok }
|
20
23
|
end
|
21
24
|
end
|
22
25
|
|
23
26
|
async "block gets called on failure" do
|
24
|
-
HTTP.get(
|
25
|
-
|
27
|
+
HTTP.get(bad_url) do |response|
|
28
|
+
async { expect(response).to_not be_ok }
|
26
29
|
end
|
27
30
|
end
|
28
31
|
end
|
29
32
|
|
30
|
-
|
33
|
+
describe "without a block" do
|
31
34
|
it "returns a promise" do
|
32
|
-
HTTP.get(
|
35
|
+
expect(HTTP.get(good_url)).to be_a Promise
|
33
36
|
end
|
34
37
|
|
35
38
|
async "returns a promise which accepts a then-block for successful response" do
|
36
|
-
HTTP.get(
|
37
|
-
|
39
|
+
HTTP.get(good_url).then do |response|
|
40
|
+
async { expect(response).to be_ok }
|
38
41
|
end
|
39
42
|
end
|
40
43
|
|
41
44
|
async "returns a promise which accepts a fail-block for failing response" do
|
42
|
-
HTTP.get(
|
43
|
-
|
45
|
+
HTTP.get(bad_url).fail do |response|
|
46
|
+
async { expect(response).to_not be_ok }
|
44
47
|
end
|
45
48
|
end
|
46
49
|
end
|
@@ -48,30 +51,30 @@ describe HTTP do
|
|
48
51
|
|
49
52
|
describe '#body' do
|
50
53
|
async 'returns the response body as a string' do
|
51
|
-
HTTP.get(
|
52
|
-
|
54
|
+
HTTP.get(good_url) do |response|
|
55
|
+
async { expect(response.body).to eq('hey') }
|
53
56
|
end
|
54
57
|
end
|
55
58
|
end
|
56
59
|
|
57
60
|
describe '#json' do
|
58
61
|
async 'returns the json converted into native ruby objects' do
|
59
|
-
HTTP.get(
|
60
|
-
|
62
|
+
HTTP.get(json_url) do |response|
|
63
|
+
async { expect(response.json).to eq({ 'name' => 'Adam', 'age' => 26 }) }
|
61
64
|
end
|
62
65
|
end
|
63
66
|
end
|
64
67
|
|
65
68
|
describe '#ok?' do
|
66
69
|
async 'returns true when the request was a sucess' do
|
67
|
-
HTTP.get(
|
68
|
-
|
70
|
+
HTTP.get(good_url) do |response|
|
71
|
+
async { expect(response).to be_ok }
|
69
72
|
end
|
70
73
|
end
|
71
74
|
|
72
75
|
async 'returns false when the request failed' do
|
73
|
-
HTTP.get(
|
74
|
-
|
76
|
+
HTTP.get(bad_url) do |response|
|
77
|
+
async { expect(response).to_not be_ok }
|
75
78
|
end
|
76
79
|
end
|
77
80
|
end
|