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,5 +1,5 @@
1
1
  module Fron
2
- # Response
2
+ # Class for handling responses from requests.
3
3
  class Response
4
4
  # @return [String] The response body
5
5
  attr_reader :body
@@ -1 +1,3 @@
1
+ require 'fron/storage/store'
1
2
  require 'fron/storage/local_storage'
3
+ require 'fron/storage/session_storage'
@@ -2,52 +2,10 @@ module Fron
2
2
  module Storage
3
3
  # Local Storage wrapper and adapter
4
4
  module LocalStorage
5
- # Gets a value from local storage with the given key
6
- #
7
- # @param key [String] The key
8
- #
9
- # @return [Object] The value
10
- def self.get(key)
11
- value = `window.localStorage.getItem(#{key}) || false`
12
- value ? JSON.parse(value) : nil
13
- end
14
-
15
- # Sets a value to local storage with the given key
16
- #
17
- # @param key [String] The key
18
- # @param data [Object] The value
19
- def self.set(key, data)
20
- `window.localStorage.setItem(#{key},#{data.to_json})`
21
- end
22
-
23
- # Removes a value from local storage with the given key
24
- #
25
- # @param key [String] The key
26
- def self.remove(key)
27
- `window.localStorage.removeItem(#{key})`
28
- end
29
-
30
- # Returns the all keys present in local storage
31
- #
32
- # @return [Array] Array of keys
33
- def self.keys
34
- %x{
35
- ret = []
36
- for (var key in localStorage){ ret.push(key) }
37
- return ret
38
- }
39
- end
40
-
41
- # Returns all values from local storage
42
- #
43
- # @return [Array] Array of values
44
- def self.all
45
- keys.map { |key| get key }
46
- end
5
+ extend Store
47
6
 
48
- # Clears local storage removeing all values
49
- def self.clear
50
- `window.localStorage.clear()`
7
+ def self.store
8
+ `window.localStorage`
51
9
  end
52
10
  end
53
11
  end
@@ -0,0 +1,12 @@
1
+ module Fron
2
+ module Storage
3
+ # Local Storage wrapper and adapter
4
+ module SessionStorage
5
+ extend Store
6
+
7
+ def self.store
8
+ `window.sessionStorage`
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,54 @@
1
+ module Fron
2
+ module Storage
3
+ # Abstract wrapper and adapter for the Storage API
4
+ module Store
5
+ # Gets a value from the store with the given key
6
+ #
7
+ # @param key [String] The key
8
+ #
9
+ # @return [Object] The value
10
+ def get(key)
11
+ value = `#{store}.getItem(#{key}) || false`
12
+ value ? JSON.parse(value) : nil
13
+ end
14
+
15
+ # Sets a value to the store with the given key
16
+ #
17
+ # @param key [String] The key
18
+ # @param data [Object] The value
19
+ def set(key, data)
20
+ `#{store}.setItem(#{key},#{data.to_json})`
21
+ end
22
+
23
+ # Removes a value from the store with the given key
24
+ #
25
+ # @param key [String] The key
26
+ def remove(key)
27
+ `#{store}.removeItem(#{key})`
28
+ end
29
+
30
+ # Returns the all keys present in store
31
+ #
32
+ # @return [Array] Array of keys
33
+ def keys
34
+ %x{
35
+ ret = []
36
+ for (var key in #{store}){ ret.push(key) }
37
+ return ret
38
+ }
39
+ end
40
+
41
+ # Returns all values from the store
42
+ #
43
+ # @return [Array] Array of values
44
+ def all
45
+ keys.map { |key| get key }
46
+ end
47
+
48
+ # Clears the store, removeing all values
49
+ def clear
50
+ `#{store}.clear()`
51
+ end
52
+ end
53
+ end
54
+ end
@@ -12,29 +12,30 @@ module Fron
12
12
  # @return [DOM::Element] The documents body
13
13
  attr_reader :body
14
14
 
15
- IS_TOUCH = `'ontouchstart' in window && !window._phantom`
16
-
17
- if IS_TOUCH
18
- EVENTS = {
19
- down: 'touchstart',
20
- move: 'touchmove',
21
- up: 'touchend'
22
- }
23
- else
24
- EVENTS = {
25
- down: 'mousedown',
26
- move: 'mousemove',
27
- up: 'mouseup'
28
- }
29
- end
15
+ IS_TOUCH = false
16
+
17
+ EVENTS = if IS_TOUCH
18
+ {
19
+ down: 'touchstart',
20
+ move: 'touchmove',
21
+ up: 'touchend'
22
+ }
23
+ else
24
+ {
25
+ down: 'mousedown',
26
+ move: 'mousemove',
27
+ up: 'mouseup'
28
+ }
29
+ end
30
30
 
31
31
  # Creates a new drag instance.
32
32
  #
33
33
  # @param base [DOM::Element] The element to monitor
34
- def initialize(base)
34
+ def initialize(base, start_distance = 7)
35
35
  reset
36
36
  @base = base
37
37
  @body = DOM::Document.body
38
+ @start_distance = start_distance
38
39
 
39
40
  @base.on EVENTS[:down] do |event| start(event) end
40
41
  end
@@ -66,6 +67,8 @@ module Fron
66
67
  @up_method = @body.on! EVENTS[:up] do |evt| up(evt) end
67
68
 
68
69
  request_animation_frame do move end
70
+
71
+ pos(event) if @start_distance == 0
69
72
  end
70
73
 
71
74
  # Runs when the pointer moves starts.
@@ -73,7 +76,7 @@ module Fron
73
76
  # @param event [Event] The event
74
77
  def pos(event)
75
78
  @position = position(event)
76
- if diff.distance > 7 && !@started
79
+ if diff.distance >= @start_distance.to_i && !@started
77
80
  @started = true
78
81
  trigger 'start', @target
79
82
  end
@@ -128,7 +131,7 @@ module Fron
128
131
  if IS_TOUCH && event.touches
129
132
  Point.new `#{event.touches}[0].pageX`, `#{event.touches}[0].pageY`
130
133
  else
131
- Point.new event.pageX, event.pageY
134
+ Point.new event.page_x, event.page_y
132
135
  end
133
136
  end
134
137
  end
@@ -39,11 +39,8 @@ module Fron
39
39
  # @param event [DOM::Event] The event
40
40
  def keydown(event)
41
41
  return if DOM::Document.active_element
42
- combo = [event.key]
43
- combo << 'ctrl' if event.ctrl?
44
- combo << 'shift' if event.shift?
45
- combo << 'alt' if event.alt?
46
- combo.uniq!
42
+
43
+ combo = Keyboard.calculate_shortcut event
47
44
 
48
45
  self.class.shortcuts.each do |shortcut|
49
46
  next unless shortcut[:parts].sort == combo.sort
@@ -53,18 +50,23 @@ module Fron
53
50
  end
54
51
  end
55
52
 
53
+ def self.calculate_shortcut(event)
54
+ combo = [event.key]
55
+ combo << 'ctrl' if event.ctrl?
56
+ combo << 'shift' if event.shift?
57
+ combo << 'alt' if event.alt?
58
+ combo << 'meta' if event.meta?
59
+ combo.uniq
60
+ end
61
+
56
62
  # Handles the shortcut.
57
63
  #
58
64
  # @param shortcut [Hash] The shortcut
59
65
  def handle_shortcut(shortcut)
60
66
  action = shortcut[:action]
61
- if shortcut[:block]
62
- instance_exec(&shortcut[:block])
63
- elsif respond_to? action
64
- send action
65
- else
66
- warn self.class.name + " - shortcut #{shortcut[:parts].join('+')}:#{action} is not implemented!"
67
- end
67
+ return instance_exec(&shortcut[:block]) if shortcut[:block]
68
+ return send(action) if respond_to? action
69
+ warn self.class.name + " - shortcut #{shortcut[:parts].join('+')}:#{action} is not implemented!"
68
70
  end
69
71
  end
70
72
  end
@@ -1,6 +1,3 @@
1
- # rubocop:disable VariableName
2
- require 'math'
3
-
4
1
  module Fron
5
2
  # Simple class for point with x and y coordinates.
6
3
  class Point
@@ -21,7 +18,8 @@ module Fron
21
18
  # @param x [Float] The x coordiante
22
19
  # @param y [Float] The y coordiante
23
20
  def initialize(x = 0, y = 0)
24
- @x, @y = x, y
21
+ @x = x
22
+ @y = y
25
23
  end
26
24
 
27
25
  # Returns the difference from an other point.
@@ -74,5 +72,15 @@ module Fron
74
72
  def to_s
75
73
  "[#{x}, #{y}]"
76
74
  end
75
+
76
+ def clamp(width, height)
77
+ @x = @x.clamp(0, width)
78
+ @y = @y.clamp(0, height)
79
+ self
80
+ end
81
+
82
+ def to_h
83
+ { x: x, y: y }
84
+ end
77
85
  end
78
86
  end
@@ -6,10 +6,11 @@ module Fron
6
6
  #
7
7
  # @param method [Method] The method
8
8
  # @param verbose [Boolean] Whether or not to log render time
9
- def initialize(method, verbose)
9
+ def initialize(method, verbose, message)
10
10
  @running = false
11
11
  @method = method
12
12
  @verbose = verbose
13
+ @message = message
13
14
  end
14
15
 
15
16
  # Runs the proc
@@ -19,7 +20,10 @@ module Fron
19
20
  request_animation_frame do
20
21
  time = Time.now
21
22
  @method.call
22
- logger.info "Rendered #{@method.owner} in #{(Time.now - time) * 1000}ms" if @verbose
23
+ if @verbose
24
+ message = @message || "Rendered #{@method.owner}"
25
+ logger.info "[#{(Time.now - time) * 1000}ms] #{message}"
26
+ end
23
27
  @running = false
24
28
  end
25
29
  end
@@ -1,7 +1,7 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe Array do
4
- subject { %w(a b) }
4
+ subject { %w(a b a) }
5
5
 
6
6
  describe '#reverse_each_with_index' do
7
7
  it 'should run in reverse' do
@@ -9,7 +9,15 @@ describe Array do
9
9
  subject.reverse_each_with_index do |item, index|
10
10
  array << [item, index]
11
11
  end
12
- array.should eq [['b', 1], ['a', 0]]
12
+ array.should eq [['a', 2], ['b', 1], ['a', 0]]
13
+ end
14
+ end
15
+
16
+ describe '#sort_by!' do
17
+ it 'should sort the array in place' do
18
+ result = subject.sort_by! { |item| item }
19
+ result.should eq subject
20
+ subject.should eq %w(a a b)
13
21
  end
14
22
  end
15
23
  end
@@ -22,4 +22,10 @@ describe Numeric do
22
22
  subject.px.should eq '1px'
23
23
  end
24
24
  end
25
+
26
+ describe '#em' do
27
+ it 'should return the em representation' do
28
+ subject.em.should eq '0.5em'
29
+ end
30
+ end
25
31
  end
@@ -0,0 +1,51 @@
1
+ require 'spec_helper'
2
+
3
+ # Test Component
4
+ class StyleTest < Fron::Component
5
+ tag 'style-test'
6
+
7
+ stylesheet 'http://test.com/index.css'
8
+
9
+ keyframes 'test', from: { color: :red },
10
+ to: { color: :blue }
11
+
12
+ style background: :red,
13
+ img: {
14
+ width: 200.px
15
+ },
16
+ '&:hover' => {
17
+ color: :blue
18
+ }
19
+ end
20
+
21
+ describe StyleTest do
22
+ let(:style) { Fron::Sheet.render }
23
+
24
+ before do
25
+ subject
26
+ end
27
+
28
+ it 'should create style tag' do
29
+ style.should_not be_nil
30
+ end
31
+
32
+ it 'should set css for component' do
33
+ style.should match('style-test')
34
+ end
35
+
36
+ it 'should set css for sub rulest' do
37
+ style.should match('style-test img')
38
+ end
39
+
40
+ it 'should set css for hover' do
41
+ style.should match('style-test:hover')
42
+ end
43
+
44
+ it 'should create keyframes rule' do
45
+ style.should match('@keyframes test')
46
+ end
47
+
48
+ it 'should create styleheet link tag' do
49
+ style.should match('test.com')
50
+ end
51
+ end
@@ -26,28 +26,23 @@ end
26
26
  describe SuperComponent do
27
27
  subject { described_class }
28
28
 
29
- let(:components) { subject.instance_variable_get('@component') }
29
+ let(:registry) { subject.instance_variable_get('@registry') }
30
30
 
31
- it 'should inherit components in order' do
32
- components.should_not be nil
33
- components[0].should eq [:text, 'text']
34
- components[1].should eq [:title, 'title']
31
+ it 'should inherit registry in order' do
32
+ registry.should_not be nil
33
+ registry[0][:args].should eq [:text, 'text']
34
+ registry[2][:args].should eq [:title, 'title']
35
35
  end
36
36
  end
37
37
 
38
38
  describe InheritedComponent do
39
39
  subject { described_class }
40
40
 
41
- let(:components) { subject.instance_variable_get('@component') }
42
- let(:events) { subject.instance_variable_get('@on') }
41
+ let(:registry) { subject.instance_variable_get('@registry') }
43
42
 
44
- it 'should inherit components' do
45
- components.should_not be nil
46
- components[0].should eq [:text, 'text']
47
- end
48
-
49
- it 'should inherit events' do
50
- events.should_not be nil
51
- events[0].should eq [:click, :render]
43
+ it 'should inherit registry' do
44
+ registry.should_not be nil
45
+ registry[0][:args].should eq [:text, 'text']
46
+ registry[1][:args].should eq [:click, :render]
52
47
  end
53
48
  end
@@ -10,11 +10,10 @@ class TestComponent < Fron::Component
10
10
  end
11
11
 
12
12
  describe Fron::Component do
13
- subject { TestComponent.new }
13
+ subject { TestComponent.new }
14
14
 
15
15
  let(:listeners) { subject.instance_variable_get '@listeners' }
16
- let(:components) { subject.instance_variable_get('@component') }
17
- let(:events) { subject.instance_variable_get('@on') }
16
+ let(:registry) { subject.instance_variable_get('@registry') }
18
17
 
19
18
  describe 'DSL' do
20
19
  subject { TestComponent }
@@ -34,22 +33,18 @@ describe Fron::Component do
34
33
  end
35
34
 
36
35
  describe '#on' do
37
- it 'should create events array' do
38
- subject.on :click, :test
39
- events.should_not be nil
40
- end
41
-
42
- it 'should push event into the events array' do
43
- subject.on :click, :test
44
- events.length.should be 2
36
+ it 'should add to registry' do
37
+ expect {
38
+ subject.on :click, :test
39
+ }.to change { registry.count }.by 1
45
40
  end
46
41
  end
47
42
 
48
43
  describe '#component' do
49
44
  it 'should create components array' do
50
- subject.component :test, 'test'
51
- components.should_not be nil
52
- components.length.should be 1
45
+ expect {
46
+ subject.component :test, 'test'
47
+ }.to change { registry.count }.by 1
53
48
  end
54
49
 
55
50
  it 'should create attr_reader for component' do
@@ -65,7 +60,7 @@ describe Fron::Component do
65
60
  end
66
61
 
67
62
  it 'should apply events' do
68
- listeners[:click].length.should eq 2
63
+ listeners[:click].length.should eq 1
69
64
  end
70
65
 
71
66
  it 'should create components' do