fron 0.2.0rc1 → 1.0.0rc1
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/.codeclimate.yml +20 -0
- data/.reek +2 -0
- data/.rubocop.yml +14 -11
- data/Gemfile +6 -3
- data/Gemfile.lock +73 -86
- data/Rakefile +11 -15
- data/Readme.md +1 -1
- data/fron.gemspec +2 -2
- data/lib/fron/version.rb +1 -1
- data/opal/fron.rb +2 -0
- data/opal/fron/core.rb +1 -0
- data/opal/fron/core/behaviors/components.rb +18 -10
- data/opal/fron/core/behaviors/events.rb +9 -10
- data/opal/fron/core/behaviors/routes.rb +6 -10
- data/opal/fron/core/behaviors/style.rb +30 -0
- data/opal/fron/core/component.rb +44 -23
- data/opal/fron/core/eventable.rb +3 -3
- data/opal/fron/core/logger.rb +1 -1
- data/opal/fron/core/sheet.rb +140 -0
- data/opal/fron/core_ext.rb +1 -0
- data/opal/fron/core_ext/array.rb +23 -0
- data/opal/fron/core_ext/hash.rb +6 -6
- data/opal/fron/core_ext/kernel.rb +10 -1
- data/opal/fron/core_ext/numeric.rb +7 -0
- data/opal/fron/core_ext/time.rb +6 -0
- data/opal/fron/dom/document.rb +6 -3
- data/opal/fron/dom/element.rb +79 -19
- data/opal/fron/dom/event.rb +5 -1
- data/opal/fron/dom/modules/dimensions.rb +0 -14
- data/opal/fron/dom/modules/element_accessor.rb +25 -0
- data/opal/fron/dom/modules/events.rb +1 -1
- data/opal/fron/dom/node.rb +7 -5
- data/opal/fron/dom/style.rb +0 -2
- data/opal/fron/dom/window.rb +14 -0
- data/opal/fron/event_mock.rb +24 -6
- data/opal/fron/js/scroll_into_view_if_needed.js +27 -0
- data/opal/fron/js/syntetic_event.js +20 -13
- data/opal/fron/request/request.rb +21 -19
- data/opal/fron/request/response.rb +1 -1
- data/opal/fron/storage.rb +2 -0
- data/opal/fron/storage/local_storage.rb +3 -45
- data/opal/fron/storage/session_storage.rb +12 -0
- data/opal/fron/storage/store.rb +54 -0
- data/opal/fron/utils/drag.rb +21 -18
- data/opal/fron/utils/keyboard.rb +14 -12
- data/opal/fron/utils/point.rb +12 -4
- data/opal/fron/utils/render_proc.rb +6 -2
- data/spec/core-ext/array_spec.rb +10 -2
- data/spec/core-ext/numeric_spec.rb +6 -0
- data/spec/core/behaviors/style_spec.rb +51 -0
- data/spec/core/component_inheritance_spec.rb +10 -15
- data/spec/core/component_spec.rb +10 -15
- data/spec/dom/element_spec.rb +12 -1
- data/spec/dom/modules/classlist_spec.rb +8 -9
- data/spec/dom/modules/dimensions_spec.rb +2 -1
- data/spec/dom/modules/events_spec.rb +42 -31
- data/spec/dom/style_spec.rb +1 -1
- data/spec/spec_helper.rb +0 -1
- data/spec/utils/drag_spec.rb +2 -2
- data/spec/utils/keyboard_spec.rb +4 -1
- data/website/application.rb +4 -0
- data/website/config.ru +30 -0
- data/website/examples/content_editable.rb +29 -0
- data/website/examples/converter.rb +49 -0
- data/website/examples/icon_button.rb +20 -0
- data/website/examples/image_paragraph.rb +33 -0
- data/website/examples/my_blue_box.rb +9 -0
- data/website/examples/my_box.rb +9 -0
- data/website/examples/my_button.rb +27 -0
- data/website/examples/my_green_box.rb +14 -0
- data/website/examples/source_reader.rb +32 -0
- data/website/examples/text_area.rb +42 -0
- data/website/pages/components.md.erb +16 -0
- data/website/pages/components/composition.md.erb +9 -0
- data/website/pages/components/events.md.erb +20 -0
- data/website/pages/components/inheritance.md.erb +19 -0
- data/website/pages/components/routes.md.erb +49 -0
- data/website/pages/components/styles.md.erb +38 -0
- data/website/pages/getting-started.md +8 -0
- data/website/pages/home.md +4 -0
- data/website/pages/intro.md +30 -0
- data/website/pages/utilities.md +10 -0
- data/website/pages/utilities/local-storage.md.erb +16 -0
- data/website/pages/utilities/request.md.erb +12 -0
- data/website/setup.rb +162 -0
- data/website/vendor/highlight.js +2 -0
- data/website/vendor/highlight.ruby.js +1 -0
- data/website/vendor/marked.min.js +6 -0
- metadata +43 -7
data/spec/dom/element_spec.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe DOM::Element do
|
4
|
-
subject { described_class.new 'div' }
|
4
|
+
subject { described_class.new 'div[tabindex=0]' }
|
5
5
|
let(:el) { subject.instance_variable_get('@el') }
|
6
6
|
let(:a) { described_class.new 'a' }
|
7
7
|
let(:a2) { described_class.new 'a' }
|
@@ -54,6 +54,17 @@ describe DOM::Element do
|
|
54
54
|
end
|
55
55
|
end
|
56
56
|
|
57
|
+
describe '#tabindex' do
|
58
|
+
it 'should return tabindex' do
|
59
|
+
subject.tabindex.should eq '0'
|
60
|
+
end
|
61
|
+
|
62
|
+
it 'should set tabindex' do
|
63
|
+
subject.tabindex = 1
|
64
|
+
subject[:tabindex].should eq '1'
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
57
68
|
describe '#disabled' do
|
58
69
|
it 'should return the disabled state of the element' do
|
59
70
|
`#{el}.disabled = true`
|
@@ -2,17 +2,16 @@ require 'spec_helper'
|
|
2
2
|
|
3
3
|
describe DOM::ClassList do
|
4
4
|
let(:element) { DOM::Element.new 'div' }
|
5
|
-
subject { element['class'] }
|
6
5
|
|
7
6
|
describe '#add_class' do
|
8
7
|
it 'should add a class' do
|
9
8
|
element.add_class 'test'
|
10
|
-
|
9
|
+
element['class'].should eq 'test'
|
11
10
|
end
|
12
11
|
|
13
12
|
it 'should add multiple classes' do
|
14
13
|
element.add_class 'test', 'help'
|
15
|
-
|
14
|
+
element['class'].should eq 'test help'
|
16
15
|
end
|
17
16
|
end
|
18
17
|
|
@@ -23,12 +22,12 @@ describe DOM::ClassList do
|
|
23
22
|
|
24
23
|
it 'should add a class' do
|
25
24
|
element.remove_class 'test'
|
26
|
-
|
25
|
+
element['class'].should eq 'help'
|
27
26
|
end
|
28
27
|
|
29
28
|
it 'should add multiple classes' do
|
30
29
|
element.remove_class 'test', 'help'
|
31
|
-
|
30
|
+
element['class'].should eq nil
|
32
31
|
end
|
33
32
|
end
|
34
33
|
|
@@ -50,22 +49,22 @@ describe DOM::ClassList do
|
|
50
49
|
|
51
50
|
it 'should remove class if the element has the given class' do
|
52
51
|
element.toggle_class 'test'
|
53
|
-
|
52
|
+
element['class'].should eq nil
|
54
53
|
end
|
55
54
|
|
56
55
|
it 'should add class if the element does not have the given class' do
|
57
56
|
element.toggle_class 'help'
|
58
|
-
|
57
|
+
element['class'].should eq 'test help'
|
59
58
|
end
|
60
59
|
|
61
60
|
it 'should add class if the second argument is true' do
|
62
61
|
element.toggle_class 'help', true
|
63
|
-
|
62
|
+
element['class'].should eq 'test help'
|
64
63
|
end
|
65
64
|
|
66
65
|
it 'should remove class if the second argument if false' do
|
67
66
|
element.toggle_class 'test', false
|
68
|
-
|
67
|
+
element['class'].should eq nil
|
69
68
|
end
|
70
69
|
end
|
71
70
|
end
|
@@ -2,35 +2,38 @@ require 'spec_helper'
|
|
2
2
|
|
3
3
|
describe DOM::Events do
|
4
4
|
let(:element) { DOM::Element.new 'div' }
|
5
|
-
subject { element.instance_variable_get '@listeners' }
|
6
5
|
|
7
6
|
describe '#on' do
|
8
|
-
|
7
|
+
it 'should register for event' do
|
8
|
+
promise = Promise.new
|
9
9
|
listener = element.on 'click' do
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
10
|
+
listeners = element.instance_variable_get '@listeners'
|
11
|
+
listeners.should_not be nil
|
12
|
+
listeners[:click].should_not be nil
|
13
|
+
listeners[:click].length.should eq 1
|
14
|
+
listeners[:click].include?(listener).should eq true
|
15
|
+
promise.resolve
|
16
|
+
element.off 'click'
|
17
17
|
end
|
18
18
|
element.trigger 'click'
|
19
|
+
promise
|
19
20
|
end
|
20
21
|
end
|
21
22
|
|
22
23
|
describe '#on!' do
|
23
|
-
|
24
|
+
it 'should register for event' do
|
25
|
+
promise = Promise.new
|
24
26
|
listener = element.on! 'click' do
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
27
|
+
listeners = element.instance_variable_get '@listeners'
|
28
|
+
listeners.should_not be nil
|
29
|
+
listeners[:click].should_not be_nil
|
30
|
+
listeners[:click].length.should eq 1
|
31
|
+
listeners[:click].include?(listener).should eq true
|
32
|
+
promise.resolve
|
33
|
+
element.off 'click'
|
32
34
|
end
|
33
35
|
element.trigger 'click'
|
36
|
+
promise
|
34
37
|
end
|
35
38
|
end
|
36
39
|
|
@@ -38,50 +41,58 @@ describe DOM::Events do
|
|
38
41
|
context 'two arguments' do
|
39
42
|
it 'should unregister for event' do
|
40
43
|
listener = element.on 'click' do end
|
41
|
-
|
44
|
+
element.instance_variable_get('@listeners')[:click]
|
45
|
+
.include?(listener).should eq true
|
42
46
|
element.off 'click', listener
|
43
|
-
|
47
|
+
element.instance_variable_get('@listeners')[:click]
|
48
|
+
.include?(listener).should eq false
|
44
49
|
end
|
45
50
|
end
|
46
51
|
|
47
52
|
context 'one argument' do
|
48
53
|
it 'should unregister all events for type' do
|
49
54
|
listener = element.on 'click' do end
|
50
|
-
|
55
|
+
element.instance_variable_get('@listeners')[:click]
|
56
|
+
.include?(listener).should eq true
|
51
57
|
element.off 'click'
|
52
|
-
|
58
|
+
element.instance_variable_get('@listeners')[:click]
|
59
|
+
.include?(listener).should eq false
|
53
60
|
end
|
54
61
|
end
|
55
62
|
|
56
63
|
context 'no argument' do
|
57
64
|
it 'should unregister all events' do
|
58
65
|
listener = element.on 'click' do end
|
59
|
-
|
66
|
+
element.instance_variable_get('@listeners')[:click]
|
67
|
+
.include?(listener).should eq true
|
60
68
|
element.off
|
61
|
-
|
69
|
+
element.instance_variable_get('@listeners')[:click]
|
70
|
+
.include?(listener).should eq false
|
62
71
|
end
|
63
72
|
end
|
64
73
|
end
|
65
74
|
|
66
75
|
describe '#delegate' do
|
67
|
-
|
76
|
+
it 'should call the listener if the element matches the selector' do
|
77
|
+
promise = Promise.new
|
68
78
|
element.delegate 'click', 'div' do
|
69
|
-
|
70
|
-
|
71
|
-
end
|
79
|
+
promise.resolve
|
80
|
+
element.off 'click'
|
72
81
|
end
|
73
82
|
element.trigger 'click'
|
83
|
+
promise
|
74
84
|
end
|
75
85
|
end
|
76
86
|
|
77
87
|
describe '#trigger' do
|
78
|
-
|
88
|
+
it 'should trigger the event' do
|
89
|
+
promise = Promise.new
|
79
90
|
element.on 'click' do
|
80
|
-
|
81
|
-
|
82
|
-
end
|
91
|
+
promise.resolve
|
92
|
+
element.off 'click'
|
83
93
|
end
|
84
94
|
element.trigger 'click'
|
95
|
+
promise
|
85
96
|
end
|
86
97
|
end
|
87
98
|
end
|
data/spec/dom/style_spec.rb
CHANGED
data/spec/spec_helper.rb
CHANGED
data/spec/utils/drag_spec.rb
CHANGED
@@ -2,8 +2,8 @@ require 'spec_helper'
|
|
2
2
|
require 'fron/utils/drag'
|
3
3
|
|
4
4
|
describe Fron::Drag do
|
5
|
-
let(:event) { double(
|
6
|
-
let(:base) { DOM::Element.new 'div'
|
5
|
+
let(:event) { double(page_x: 0, page_y: 0, preventDefult: true, stop: true, target: true) }
|
6
|
+
let(:base) { DOM::Element.new 'div' }
|
7
7
|
let(:position) { double }
|
8
8
|
|
9
9
|
subject { described_class.new base }
|
data/spec/utils/keyboard_spec.rb
CHANGED
@@ -7,7 +7,10 @@ class TestKeyboard < Fron::Keyboard
|
|
7
7
|
end
|
8
8
|
|
9
9
|
describe TestKeyboard do
|
10
|
-
let(:event) {
|
10
|
+
let(:event) {
|
11
|
+
DOM::Event.new `{ ctrlKey: true, altKey: true, shiftKey: true,
|
12
|
+
metaKey: false, keyCode: 38 }`
|
13
|
+
}
|
11
14
|
|
12
15
|
describe Fron::Keyboard do
|
13
16
|
it 'should work on its own' do
|
data/website/config.ru
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
require 'fron'
|
2
|
+
require 'active_support/core_ext/string/inflections'
|
3
|
+
|
4
|
+
# Proxy
|
5
|
+
class Proxy
|
6
|
+
def initialize(app)
|
7
|
+
@app = app
|
8
|
+
end
|
9
|
+
|
10
|
+
def call(env)
|
11
|
+
env['PATH_INFO'] = '/' if !(env['PATH_INFO'] =~ /\..*$/) && !(env['PATH_INFO'] =~ /^\/(pages)/)
|
12
|
+
@app.call env
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
use Proxy
|
17
|
+
|
18
|
+
module Helpers
|
19
|
+
def example(klass)
|
20
|
+
source = File.read(File.join(File.dirname(__FILE__), "examples/#{klass.underscore}.rb"))
|
21
|
+
"<example class='#{klass}'></example>\n```ruby\n#{source}\n```"
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
run Opal::Server.new { |s|
|
26
|
+
s.append_path 'website'
|
27
|
+
s.source_map = false
|
28
|
+
s.main = 'application'
|
29
|
+
s.sprockets.context_class.send(:include, Helpers)
|
30
|
+
}
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# We start a by extending from Fron::Component
|
2
|
+
class ContentEditable < Fron::Component
|
3
|
+
# Set the tag
|
4
|
+
tag 'content-editable'
|
5
|
+
|
6
|
+
# When the element is blurred call the change method
|
7
|
+
on :blur, :change
|
8
|
+
|
9
|
+
# Set styles
|
10
|
+
style background: '#F9F9F9',
|
11
|
+
borderRadius: 5.px,
|
12
|
+
display: :block,
|
13
|
+
padding: 10.px
|
14
|
+
|
15
|
+
# Initializes the compontent:
|
16
|
+
# * Sets the contenteditable attribute to true
|
17
|
+
# * Sets the spellcheck to false
|
18
|
+
def initialize
|
19
|
+
super
|
20
|
+
self.contenteditable = true
|
21
|
+
self.spellcheck = false
|
22
|
+
self.text = 'Some default content...'
|
23
|
+
end
|
24
|
+
|
25
|
+
# Run on the blur event
|
26
|
+
def change
|
27
|
+
logger.info "The content is now: #{text}"
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
# Celsius to Fahrenheit Converter
|
2
|
+
class Converter < Fron::Component
|
3
|
+
# Celsius part
|
4
|
+
component :celcius, :div do
|
5
|
+
component :label, 'label', text: 'Celsius: '
|
6
|
+
component :input, 'input', value: 0
|
7
|
+
end
|
8
|
+
|
9
|
+
# Fahrenheit part
|
10
|
+
component :fahrenheit, :div do
|
11
|
+
component :label, 'label', text: 'Fahrenheit:'
|
12
|
+
component :result, 'span', text: '32'
|
13
|
+
end
|
14
|
+
|
15
|
+
# Button
|
16
|
+
component :button, 'button', text: 'Convert'
|
17
|
+
|
18
|
+
# We will convert on click of the button
|
19
|
+
on :click, 'button', :convert
|
20
|
+
# or on change of the input
|
21
|
+
on :change, :convert
|
22
|
+
|
23
|
+
# Styling
|
24
|
+
style background: '#F9F9F9',
|
25
|
+
alignItems: 'flex-end',
|
26
|
+
display: :flex,
|
27
|
+
padding: 10.px,
|
28
|
+
label: { display: :block },
|
29
|
+
div: { flexDirection: :column,
|
30
|
+
marginRight: 5.px,
|
31
|
+
display: :flex },
|
32
|
+
button: { position: :relative,
|
33
|
+
height: 30.px,
|
34
|
+
top: -1.px },
|
35
|
+
'input, span' => {
|
36
|
+
display: 'inline-block',
|
37
|
+
border: '1px solid #ddd',
|
38
|
+
lineHeight: 20.px,
|
39
|
+
fontSize: 14.px,
|
40
|
+
padding: 5.px,
|
41
|
+
height: 30.px,
|
42
|
+
width: 200.px
|
43
|
+
}
|
44
|
+
|
45
|
+
# Converting Logic
|
46
|
+
def convert
|
47
|
+
@fahrenheit.result.text = @celcius.input.value.to_i * 9 / 5 + 32
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# Extend MyButton
|
2
|
+
class IconButton < MyButton
|
3
|
+
extend Forwardable
|
4
|
+
|
5
|
+
# Set the tag
|
6
|
+
tag 'icon-button'
|
7
|
+
|
8
|
+
# Add child components
|
9
|
+
component :icon, :icon
|
10
|
+
component :span, :span
|
11
|
+
|
12
|
+
# Delegate methods
|
13
|
+
def_delegators :span, :text=, :text
|
14
|
+
|
15
|
+
# Style the icon, everything else is inherited
|
16
|
+
style 'icon:before' => { fontFamily: 'FontAwesome',
|
17
|
+
display: 'inline-block',
|
18
|
+
marginRight: 10.px,
|
19
|
+
content: '"\f0f4"' }
|
20
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# Paragraph component with an image.
|
2
|
+
class ImageParagraph < Fron::Component
|
3
|
+
tag 'image-paragraph'
|
4
|
+
|
5
|
+
# Define components
|
6
|
+
component :image, :img
|
7
|
+
component :content, :content
|
8
|
+
|
9
|
+
# Set Styling
|
10
|
+
style border: '1px solid #EEE',
|
11
|
+
display: :block,
|
12
|
+
padding: 20.px,
|
13
|
+
img: { float: :left,
|
14
|
+
marginRight: 20.px },
|
15
|
+
'&:after' => { display: :block,
|
16
|
+
content: '""',
|
17
|
+
clear: :both }
|
18
|
+
|
19
|
+
# Set data
|
20
|
+
def initialize
|
21
|
+
super
|
22
|
+
@image[:src] = 'http://placehold.it/180/f9f9f9/666'
|
23
|
+
@content.text = 'Lorem ipsum dolor sit amet, consectetur adipiscing
|
24
|
+
elit. Vivamus molestie placerat sem a ultrices.
|
25
|
+
Cras ultricies enim luctus enim aliquam convallis.
|
26
|
+
Sed et felis volutpat, suscipit urna et, malesuada
|
27
|
+
tellus. Nunc et tellus fringilla, tristique eros
|
28
|
+
et, aliquam nisi. Quisque faucibus porta odio non
|
29
|
+
mollis. Donec volutpat convallis blandit. Donec
|
30
|
+
non nisl elit. Quisque orci neque, consequat
|
31
|
+
interdum elit eu, auctor elementum magna.'
|
32
|
+
end
|
33
|
+
end
|