opal-jquery 0.3.0.beta1 → 0.3.0.beta2
Sign up to get free protection for your applications and to get access to all the features.
- 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
|