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.
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