fron 0.2.0rc1 → 1.0.0rc1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (90) hide show
  1. checksums.yaml +4 -4
  2. data/.codeclimate.yml +20 -0
  3. data/.reek +2 -0
  4. data/.rubocop.yml +14 -11
  5. data/Gemfile +6 -3
  6. data/Gemfile.lock +73 -86
  7. data/Rakefile +11 -15
  8. data/Readme.md +1 -1
  9. data/fron.gemspec +2 -2
  10. data/lib/fron/version.rb +1 -1
  11. data/opal/fron.rb +2 -0
  12. data/opal/fron/core.rb +1 -0
  13. data/opal/fron/core/behaviors/components.rb +18 -10
  14. data/opal/fron/core/behaviors/events.rb +9 -10
  15. data/opal/fron/core/behaviors/routes.rb +6 -10
  16. data/opal/fron/core/behaviors/style.rb +30 -0
  17. data/opal/fron/core/component.rb +44 -23
  18. data/opal/fron/core/eventable.rb +3 -3
  19. data/opal/fron/core/logger.rb +1 -1
  20. data/opal/fron/core/sheet.rb +140 -0
  21. data/opal/fron/core_ext.rb +1 -0
  22. data/opal/fron/core_ext/array.rb +23 -0
  23. data/opal/fron/core_ext/hash.rb +6 -6
  24. data/opal/fron/core_ext/kernel.rb +10 -1
  25. data/opal/fron/core_ext/numeric.rb +7 -0
  26. data/opal/fron/core_ext/time.rb +6 -0
  27. data/opal/fron/dom/document.rb +6 -3
  28. data/opal/fron/dom/element.rb +79 -19
  29. data/opal/fron/dom/event.rb +5 -1
  30. data/opal/fron/dom/modules/dimensions.rb +0 -14
  31. data/opal/fron/dom/modules/element_accessor.rb +25 -0
  32. data/opal/fron/dom/modules/events.rb +1 -1
  33. data/opal/fron/dom/node.rb +7 -5
  34. data/opal/fron/dom/style.rb +0 -2
  35. data/opal/fron/dom/window.rb +14 -0
  36. data/opal/fron/event_mock.rb +24 -6
  37. data/opal/fron/js/scroll_into_view_if_needed.js +27 -0
  38. data/opal/fron/js/syntetic_event.js +20 -13
  39. data/opal/fron/request/request.rb +21 -19
  40. data/opal/fron/request/response.rb +1 -1
  41. data/opal/fron/storage.rb +2 -0
  42. data/opal/fron/storage/local_storage.rb +3 -45
  43. data/opal/fron/storage/session_storage.rb +12 -0
  44. data/opal/fron/storage/store.rb +54 -0
  45. data/opal/fron/utils/drag.rb +21 -18
  46. data/opal/fron/utils/keyboard.rb +14 -12
  47. data/opal/fron/utils/point.rb +12 -4
  48. data/opal/fron/utils/render_proc.rb +6 -2
  49. data/spec/core-ext/array_spec.rb +10 -2
  50. data/spec/core-ext/numeric_spec.rb +6 -0
  51. data/spec/core/behaviors/style_spec.rb +51 -0
  52. data/spec/core/component_inheritance_spec.rb +10 -15
  53. data/spec/core/component_spec.rb +10 -15
  54. data/spec/dom/element_spec.rb +12 -1
  55. data/spec/dom/modules/classlist_spec.rb +8 -9
  56. data/spec/dom/modules/dimensions_spec.rb +2 -1
  57. data/spec/dom/modules/events_spec.rb +42 -31
  58. data/spec/dom/style_spec.rb +1 -1
  59. data/spec/spec_helper.rb +0 -1
  60. data/spec/utils/drag_spec.rb +2 -2
  61. data/spec/utils/keyboard_spec.rb +4 -1
  62. data/website/application.rb +4 -0
  63. data/website/config.ru +30 -0
  64. data/website/examples/content_editable.rb +29 -0
  65. data/website/examples/converter.rb +49 -0
  66. data/website/examples/icon_button.rb +20 -0
  67. data/website/examples/image_paragraph.rb +33 -0
  68. data/website/examples/my_blue_box.rb +9 -0
  69. data/website/examples/my_box.rb +9 -0
  70. data/website/examples/my_button.rb +27 -0
  71. data/website/examples/my_green_box.rb +14 -0
  72. data/website/examples/source_reader.rb +32 -0
  73. data/website/examples/text_area.rb +42 -0
  74. data/website/pages/components.md.erb +16 -0
  75. data/website/pages/components/composition.md.erb +9 -0
  76. data/website/pages/components/events.md.erb +20 -0
  77. data/website/pages/components/inheritance.md.erb +19 -0
  78. data/website/pages/components/routes.md.erb +49 -0
  79. data/website/pages/components/styles.md.erb +38 -0
  80. data/website/pages/getting-started.md +8 -0
  81. data/website/pages/home.md +4 -0
  82. data/website/pages/intro.md +30 -0
  83. data/website/pages/utilities.md +10 -0
  84. data/website/pages/utilities/local-storage.md.erb +16 -0
  85. data/website/pages/utilities/request.md.erb +12 -0
  86. data/website/setup.rb +162 -0
  87. data/website/vendor/highlight.js +2 -0
  88. data/website/vendor/highlight.ruby.js +1 -0
  89. data/website/vendor/marked.min.js +6 -0
  90. metadata +43 -7
@@ -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
- subject.should eq 'test'
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
- subject.should eq 'test help'
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
- subject.should eq 'help'
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
- subject.should eq nil
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
- subject.should eq nil
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
- subject.should eq 'test help'
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
- subject.should eq 'test help'
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
- subject.should eq nil
67
+ element['class'].should eq nil
69
68
  end
70
69
  end
71
70
  end
@@ -81,7 +81,8 @@ describe DOM::Dimensions do
81
81
  end
82
82
 
83
83
  context 'not in viewport' do
84
- height, width = `window.innerHeight`, `window.innerWidth`
84
+ height = `window.innerHeight`
85
+ width = `window.innerWidth`
85
86
  [
86
87
  [-80, -100], # Top Left
87
88
  [-80, 0], # Top
@@ -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
- async 'should register for event' do
7
+ it 'should register for event' do
8
+ promise = Promise.new
9
9
  listener = element.on 'click' do
10
- run_async do
11
- subject.should_not be nil
12
- subject[:click].should_not be nil
13
- subject[:click].length.should eq 1
14
- subject[:click].include?(listener).should eq true
15
- element.off 'click'
16
- end
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
- async 'should register for event' do
24
+ it 'should register for event' do
25
+ promise = Promise.new
24
26
  listener = element.on! 'click' do
25
- run_async do
26
- subject.should_not be nil
27
- subject[:click].should_not be nil
28
- subject[:click].length.should eq 1
29
- subject[:click].include?(listener).should eq true
30
- element.off 'click'
31
- end
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
- subject[:click].include?(listener).should eq true
44
+ element.instance_variable_get('@listeners')[:click]
45
+ .include?(listener).should eq true
42
46
  element.off 'click', listener
43
- subject[:click].include?(listener).should eq false
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
- subject[:click].include?(listener).should eq true
55
+ element.instance_variable_get('@listeners')[:click]
56
+ .include?(listener).should eq true
51
57
  element.off 'click'
52
- subject[:click].include?(listener).should eq false
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
- subject[:click].include?(listener).should eq true
66
+ element.instance_variable_get('@listeners')[:click]
67
+ .include?(listener).should eq true
60
68
  element.off
61
- subject[:click].include?(listener).should eq false
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
- async 'should call the listener if the element matches the selector' do
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
- run_async do
70
- element.off 'click'
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
- async 'should trigger the event' do
88
+ it 'should trigger the event' do
89
+ promise = Promise.new
79
90
  element.on 'click' do
80
- run_async do
81
- element.off 'click'
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
@@ -23,7 +23,7 @@ describe DOM::Style do
23
23
  end
24
24
  end
25
25
 
26
- describe '[]'do
26
+ describe '[]' do
27
27
  it 'should return with the value of the given style' do
28
28
  `#{el}.style.display = 'block'`
29
29
  subject.style['display'].should eq 'block'
@@ -1,4 +1,3 @@
1
- require 'rspec_coverage_helper'
2
1
  require 'js/mocks'
3
2
  require 'fron'
4
3
  require 'fron/event_mock'
@@ -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(pageX: 0, pageY: 0, preventDefult: true, stop: true, target: true) }
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 }
@@ -7,7 +7,10 @@ class TestKeyboard < Fron::Keyboard
7
7
  end
8
8
 
9
9
  describe TestKeyboard do
10
- let(:event) { DOM::Event.new `{ctrlKey: true, altKey: true, shiftKey: true, keyCode: 38}` }
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
@@ -0,0 +1,4 @@
1
+ require 'setup'
2
+
3
+ DOM::Document.body << Main.new
4
+ DOM::Window.trigger :popstate
@@ -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
@@ -0,0 +1,9 @@
1
+ # My sweet red box is gone....NOOOOOOOO!!!
2
+ class MyBlueBox < MyBox
3
+ tag 'my-blue-box'
4
+
5
+ # This is only needed if no style DSL is used
6
+ ensure_styles!
7
+
8
+ style background: :blue
9
+ end