fron 0.1.4 → 0.2.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 (120) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +3 -0
  3. data/.reek +11 -0
  4. data/.rubocop.yml +54 -0
  5. data/.travis.yml +11 -0
  6. data/.yardopts +4 -0
  7. data/Changelog.md +7 -0
  8. data/Gemfile +3 -1
  9. data/Gemfile.lock +106 -15
  10. data/Rakefile +19 -15
  11. data/Readme.md +23 -0
  12. data/fron.gemspec +2 -2
  13. data/lib/fron/version.rb +2 -1
  14. data/opal/fron.rb +5 -5
  15. data/opal/fron/core.rb +3 -10
  16. data/opal/fron/core/behaviors/components.rb +42 -0
  17. data/opal/fron/core/behaviors/events.rb +27 -0
  18. data/opal/fron/core/behaviors/routes.rb +59 -0
  19. data/opal/fron/core/component.rb +64 -90
  20. data/opal/fron/core/eventable.rb +18 -0
  21. data/opal/fron/core/logger.rb +10 -1
  22. data/opal/fron/core_ext.rb +9 -0
  23. data/opal/fron/core_ext/array.rb +12 -0
  24. data/opal/fron/core_ext/date.rb +57 -0
  25. data/opal/fron/core_ext/hash.rb +52 -0
  26. data/opal/fron/core_ext/kernel.rb +57 -0
  27. data/opal/fron/core_ext/nil.rb +7 -0
  28. data/opal/fron/core_ext/numeric.rb +19 -0
  29. data/opal/fron/core_ext/object.rb +11 -0
  30. data/opal/fron/core_ext/proc.rb +19 -0
  31. data/opal/fron/{core-ext → core_ext}/string.rb +4 -0
  32. data/opal/fron/dom.rb +15 -13
  33. data/opal/fron/dom/document.rb +22 -6
  34. data/opal/fron/dom/element.rb +105 -67
  35. data/opal/fron/dom/event.rb +110 -40
  36. data/opal/fron/dom/{file-reader.rb → file_reader.rb} +6 -1
  37. data/opal/fron/dom/fragment.rb +2 -0
  38. data/opal/fron/dom/modules/attributes.rb +43 -0
  39. data/opal/fron/dom/modules/classlist.rb +26 -13
  40. data/opal/fron/dom/modules/dimensions.rb +79 -9
  41. data/opal/fron/dom/modules/element_accessor.rb +35 -0
  42. data/opal/fron/dom/modules/events.rb +67 -20
  43. data/opal/fron/dom/node.rb +98 -39
  44. data/opal/fron/dom/nodelist.rb +9 -2
  45. data/opal/fron/dom/style.rb +23 -2
  46. data/opal/fron/dom/text.rb +4 -0
  47. data/opal/fron/dom/window.rb +31 -2
  48. data/opal/fron/event_mock.rb +54 -0
  49. data/opal/fron/js/syntetic_event.js +16 -0
  50. data/opal/fron/request.rb +2 -2
  51. data/opal/fron/request/request.rb +77 -14
  52. data/opal/fron/request/response.rb +33 -6
  53. data/opal/fron/storage.rb +1 -1
  54. data/opal/fron/storage/local_storage.rb +54 -0
  55. data/opal/fron/utils/drag.rb +135 -0
  56. data/opal/fron/utils/keyboard.rb +70 -0
  57. data/opal/fron/utils/point.rb +78 -0
  58. data/opal/fron/utils/render_proc.rb +27 -0
  59. data/spec/core-ext/array_spec.rb +15 -0
  60. data/spec/core-ext/date_spec.rb +54 -0
  61. data/spec/core-ext/hash_spec.rb +18 -2
  62. data/spec/core-ext/kernel_spec.rb +57 -0
  63. data/spec/core-ext/nil_spec.rb +9 -0
  64. data/spec/core-ext/numeric_spec.rb +25 -0
  65. data/spec/core-ext/proc_spec.rb +15 -0
  66. data/spec/core-ext/string_spec.rb +11 -0
  67. data/spec/core/behaviors/events_spec.rb +25 -0
  68. data/spec/core/behaviors/routes_spec.rb +59 -0
  69. data/spec/core/component_inheritance_spec.rb +26 -16
  70. data/spec/core/component_spec.rb +25 -29
  71. data/spec/core/eventable_spec.rb +19 -19
  72. data/spec/core/logger_spec.rb +5 -6
  73. data/spec/dom/document_spec.rb +4 -5
  74. data/spec/dom/element_spec.rb +106 -15
  75. data/spec/dom/event_spec.rb +101 -61
  76. data/spec/dom/file_reader_spec.rb +11 -0
  77. data/spec/dom/fragment_spec.rb +3 -4
  78. data/spec/dom/instance_retaining_spec.rb +58 -0
  79. data/spec/dom/modules/classlist_spec.rb +18 -19
  80. data/spec/dom/modules/dimensions_spec.rb +87 -22
  81. data/spec/dom/modules/events_spec.rb +22 -8
  82. data/spec/dom/node_spec.rb +25 -17
  83. data/spec/dom/nodelist_spec.rb +2 -3
  84. data/spec/dom/style_spec.rb +6 -5
  85. data/spec/dom/text_spec.rb +4 -3
  86. data/spec/dom/window_spec.rb +24 -9
  87. data/spec/js/mocks.js +14 -0
  88. data/spec/request/request_spec.rb +34 -15
  89. data/spec/request/response_spec.rb +9 -10
  90. data/spec/spec_helper.rb +11 -0
  91. data/spec/storage/{local-storage_spec.rb → local_storage_spec.rb} +6 -7
  92. data/spec/utils/drag_spec.rb +136 -0
  93. data/spec/utils/keyboard_spec.rb +75 -0
  94. data/spec/utils/point_spec.rb +55 -0
  95. data/spec/utils/render_proc_spec.rb +18 -0
  96. metadata +58 -36
  97. data/docs/application.md +0 -7
  98. data/docs/configuration.md +0 -29
  99. data/docs/controllers.md +0 -35
  100. data/docs/routing.md +0 -63
  101. data/opal/fron/core-ext.rb +0 -5
  102. data/opal/fron/core-ext/hash.rb +0 -31
  103. data/opal/fron/core-ext/kernel.rb +0 -10
  104. data/opal/fron/core-ext/numeric.rb +0 -9
  105. data/opal/fron/core-ext/proc.rb +0 -9
  106. data/opal/fron/core/adapters/local.rb +0 -43
  107. data/opal/fron/core/adapters/rails.rb +0 -65
  108. data/opal/fron/core/application.rb +0 -42
  109. data/opal/fron/core/configuration.rb +0 -29
  110. data/opal/fron/core/controller.rb +0 -41
  111. data/opal/fron/core/model.rb +0 -90
  112. data/opal/fron/core/router.rb +0 -86
  113. data/opal/fron/storage/local-storage.rb +0 -34
  114. data/spec/core/adapter/local_spec.rb +0 -65
  115. data/spec/core/adapter/rails_spec.rb +0 -77
  116. data/spec/core/application_spec.rb +0 -35
  117. data/spec/core/configuration_spec.rb +0 -20
  118. data/spec/core/controlller_spec.rb +0 -68
  119. data/spec/core/model_spec.rb +0 -125
  120. data/spec/core/router_spec.rb +0 -124
@@ -0,0 +1,135 @@
1
+ require 'fron/utils/point'
2
+
3
+ module Fron
4
+ # Class for dragging with pointer events.
5
+ class Drag
6
+ include Fron::Eventable
7
+ extend Fron::Eventable
8
+
9
+ # @return [DOM::Element] The base of the drag
10
+ attr_reader :base
11
+
12
+ # @return [DOM::Element] The documents body
13
+ attr_reader :body
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
30
+
31
+ # Creates a new drag instance.
32
+ #
33
+ # @param base [DOM::Element] The element to monitor
34
+ def initialize(base)
35
+ reset
36
+ @base = base
37
+ @body = DOM::Document.body
38
+
39
+ @base.on EVENTS[:down] do |event| start(event) end
40
+ end
41
+
42
+ # Returns the current difference position
43
+ # from the start position.
44
+ #
45
+ # @return [Fron::Point] The difference
46
+ def diff
47
+ @start_position - @position
48
+ end
49
+
50
+ private
51
+
52
+ # Runs when dragging starts.
53
+ #
54
+ # @param event [Event] The event
55
+ def start(event)
56
+ return stop if IS_TOUCH && `#{event.touches}.length != 1`
57
+
58
+ off if @pos_method
59
+
60
+ @position = position(event)
61
+ @target = event.target
62
+ @start_position = @position
63
+ @mouse_is_down = true
64
+
65
+ @pos_method = @body.on! EVENTS[:move] do |evt| pos(evt) end
66
+ @up_method = @body.on! EVENTS[:up] do |evt| up(evt) end
67
+
68
+ request_animation_frame do move end
69
+ end
70
+
71
+ # Runs when the pointer moves starts.
72
+ #
73
+ # @param event [Event] The event
74
+ def pos(event)
75
+ @position = position(event)
76
+ if diff.distance > 7 && !@started
77
+ @started = true
78
+ trigger 'start', @target
79
+ end
80
+ event.stop
81
+ end
82
+
83
+ # Stops the drag
84
+ def stop
85
+ off
86
+ reset
87
+ end
88
+
89
+ # Runs when pointer releases.
90
+ #
91
+ # @param event [Event] The event
92
+ def up(event)
93
+ off
94
+ trigger 'end' if @started
95
+ reset
96
+ return unless @started
97
+ event.preventDefault
98
+ event.stop
99
+ end
100
+
101
+ # Runs on animation frame when the mouse is down.
102
+ def move
103
+ request_animation_frame { move } if @mouse_is_down
104
+ return if !@position || !@started
105
+ trigger 'move', @position
106
+ end
107
+
108
+ # Removes event listeners
109
+ def off
110
+ @body.off EVENTS[:move], @pos_method
111
+ @body.off EVENTS[:up], @up_method
112
+ end
113
+
114
+ # Resets the drag
115
+ def reset
116
+ @started = false
117
+ @target = nil
118
+ @position = nil
119
+ @start_position = nil
120
+ @mouse_is_down = false
121
+ end
122
+
123
+ # Gets the position from the given event.
124
+ # @param event [Event] The event
125
+ #
126
+ # @return [Fron::Point] A point from the event.
127
+ def position(event)
128
+ if IS_TOUCH && event.touches
129
+ Point.new `#{event.touches}[0].pageX`, `#{event.touches}[0].pageY`
130
+ else
131
+ Point.new event.pageX, event.pageY
132
+ end
133
+ end
134
+ end
135
+ end
@@ -0,0 +1,70 @@
1
+ module Fron
2
+ # Keyboard class that handles matcing keyp presses to shortcuts.
3
+ class Keyboard
4
+ class << self
5
+ # @return [Array] The data for the shortcuts
6
+ attr_reader :shortcuts
7
+
8
+ # Delimeters to separate shortcut parts
9
+ DELIMETERS = /-|\+|:|_/
10
+
11
+ # Defines a shortcut. If a block given it will run that block on a match
12
+ # and not the action. Otherwise it will run the action named method on
13
+ # the instance.
14
+ #
15
+ # The shortcut order is not relevant, and it can have many delimiters.
16
+ #
17
+ # Exmaple shortcuts:
18
+ # * ctrl+click
19
+ # * ctrl:up
20
+ # * ctrl-down
21
+ # * ctrl-shift_up
22
+ #
23
+ # @param shortcut [String] The shortcut
24
+ # @param action [Symbol] The action to run
25
+ # @param block [Proc] The block to run
26
+ def sc(shortcut, action = nil, &block)
27
+ @shortcuts ||= []
28
+ @shortcuts << { parts: shortcut.split(DELIMETERS), action: action, block: block }
29
+ end
30
+ end
31
+
32
+ # Create a new instance
33
+ def initialize
34
+ DOM::Document.body.on 'keydown' do |event| keydown event end
35
+ end
36
+
37
+ # Handles keydown event, and shortcut matching.
38
+ #
39
+ # @param event [DOM::Event] The event
40
+ def keydown(event)
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!
47
+
48
+ self.class.shortcuts.each do |shortcut|
49
+ next unless shortcut[:parts].sort == combo.sort
50
+ handle_shortcut shortcut
51
+ event.stop
52
+ break
53
+ end
54
+ end
55
+
56
+ # Handles the shortcut.
57
+ #
58
+ # @param shortcut [Hash] The shortcut
59
+ def handle_shortcut(shortcut)
60
+ 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
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,78 @@
1
+ # rubocop:disable VariableName
2
+ require 'math'
3
+
4
+ module Fron
5
+ # Simple class for point with x and y coordinates.
6
+ class Point
7
+ # Sets / gets the x portion of the point
8
+ #
9
+ # @param value [Numeric] The value
10
+ # @return [Numeric] The value
11
+ attr_accessor :x
12
+
13
+ # Sets / gets the y portion of the point
14
+ #
15
+ # @param value [Numeric] The value
16
+ # @return [Numeric] The value
17
+ attr_accessor :y
18
+
19
+ # Creates a new instance
20
+ #
21
+ # @param x [Float] The x coordiante
22
+ # @param y [Float] The y coordiante
23
+ def initialize(x = 0, y = 0)
24
+ @x, @y = x, y
25
+ end
26
+
27
+ # Returns the difference from an other point.
28
+ #
29
+ # @param other [Core::Point] The point to caluclate the difference from
30
+ #
31
+ # @return [Core::Point] The difference
32
+ def -(other)
33
+ self.class.new x - other.x, y - other.y
34
+ end
35
+
36
+ # Adds two points together
37
+ #
38
+ # @param other [Core::Point] The other point
39
+ #
40
+ # @return [Core::Point] The result
41
+ def +(other)
42
+ self.class.new x + other.x, y + other.y
43
+ end
44
+
45
+ # Multiplies the point by given scalar value
46
+ #
47
+ # @param other [Numeric] The scalar value
48
+ #
49
+ # @return [Core::Point] The result
50
+ def *(other)
51
+ self.class.new x * other, y * other
52
+ end
53
+
54
+ # Divides the point by given scalar value
55
+ #
56
+ # @param other [Numeric] The scalar value
57
+ #
58
+ # @return [Core::Point] The result
59
+ def /(other)
60
+ self.class.new x / other, y / other
61
+ end
62
+
63
+ # Returns the distance between
64
+ # this point and 0, 0
65
+ #
66
+ # @return [Numeric] The distance
67
+ def distance
68
+ Math.sqrt(@x**2 + @y**2)
69
+ end
70
+
71
+ # Returns the string representation of the point
72
+ #
73
+ # @return [String] The representation
74
+ def to_s
75
+ "[#{x}, #{y}]"
76
+ end
77
+ end
78
+ end
@@ -0,0 +1,27 @@
1
+ module Fron
2
+ # Render Proc for rendering efficiently, it uses requestAnimationFrame
3
+ # to limit the number of cycles.
4
+ class RenderProc
5
+ # Initializes a render proc
6
+ #
7
+ # @param method [Method] The method
8
+ # @param verbose [Boolean] Whether or not to log render time
9
+ def initialize(method, verbose)
10
+ @running = false
11
+ @method = method
12
+ @verbose = verbose
13
+ end
14
+
15
+ # Runs the proc
16
+ def call
17
+ return if @running
18
+ @running = true
19
+ request_animation_frame do
20
+ time = Time.now
21
+ @method.call
22
+ logger.info "Rendered #{@method.owner} in #{(Time.now - time) * 1000}ms" if @verbose
23
+ @running = false
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,15 @@
1
+ require 'spec_helper'
2
+
3
+ describe Array do
4
+ subject { %w(a b) }
5
+
6
+ describe '#reverse_each_with_index' do
7
+ it 'should run in reverse' do
8
+ array = []
9
+ subject.reverse_each_with_index do |item, index|
10
+ array << [item, index]
11
+ end
12
+ array.should eq [['b', 1], ['a', 0]]
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,54 @@
1
+ require 'spec_helper'
2
+
3
+ describe Date do
4
+ context 'Class' do
5
+ subject { described_class }
6
+
7
+ describe '#this_week' do
8
+ it 'should return this week' do
9
+ week = subject.this_week
10
+ week.should be_a Range
11
+ week.count.should eq 7
12
+ end
13
+ end
14
+
15
+ describe '#last_week' do
16
+ it 'should return last week' do
17
+ week = subject.last_week
18
+ week.should be_a Range
19
+ week.count.should eq 7
20
+ end
21
+ end
22
+
23
+ describe '#monday' do
24
+ it 'should return monday' do
25
+ monday = subject.monday
26
+ monday.strftime('%A').should eq 'Monday'
27
+ end
28
+ end
29
+
30
+ describe '#week' do
31
+ it 'should return a week' do
32
+ week = subject.week
33
+ week.should be_a Range
34
+ week.count.should eq 7
35
+ end
36
+ end
37
+ end
38
+
39
+ subject { described_class.new 1987, 05, 28 }
40
+
41
+ describe '#beginning_of_month' do
42
+ it 'should return the beginning of the month' do
43
+ date = subject.beginning_of_month
44
+ date.to_s.should eq '1987-05-01'
45
+ end
46
+ end
47
+
48
+ describe '#end_of_month' do
49
+ it 'should return the end of the month' do
50
+ date = subject.end_of_month
51
+ date.to_s.should eq '1987-05-31'
52
+ end
53
+ end
54
+ end
@@ -1,10 +1,13 @@
1
- require 'fron/core-ext/hash'
1
+ require 'spec_helper'
2
2
 
3
3
  describe Hash do
4
+ let(:base) { { a: 'test', b: 'asd', c: { test: 'asd' } } }
5
+ let(:other) { { a: 'test', b: 'user', c: { test: 'wtf' } } }
6
+ let(:diff) { { b: %w(asd user), c: { test: %w(asd wtf) } } }
4
7
 
5
8
  subject { { a: 'test', b: 'user' } }
6
9
 
7
- describe "#to_query_string" do
10
+ describe '#to_query_string' do
8
11
  it 'should return the hash in query string format' do
9
12
  subject.to_query_string.should eq 'a=test&b=user'
10
13
  end
@@ -15,4 +18,17 @@ describe Hash do
15
18
  `#{subject.to_form_data} instanceof FormData`.should be true
16
19
  end
17
20
  end
21
+
22
+ describe '#deep_diff' do
23
+ it 'should return a diff of the two objects' do
24
+ base.deep_diff(other).should eq diff
25
+ end
26
+ end
27
+
28
+ describe '#difference' do
29
+ it 'should return the difference of the two objects' do
30
+ (base - other).should eq b: 'asd', c: { test: 'asd' }
31
+ (other - base).should eq b: 'user', c: { test: 'wtf' }
32
+ end
33
+ end
18
34
  end
@@ -0,0 +1,57 @@
1
+ require 'spec_helper'
2
+
3
+ describe Kernel do
4
+ describe '#request_animation_frame' do
5
+ it 'should return nil if no block given' do
6
+ request_animation_frame.should eq nil
7
+ end
8
+
9
+ it 'should run the block inside requestAnimationFrame' do
10
+ value = nil
11
+ request_animation_frame do
12
+ value = true
13
+ end
14
+ value.should eq true
15
+ end
16
+ end
17
+
18
+ describe '#timeout' do
19
+ it 'should run the provided block' do
20
+ value = nil
21
+ timeout do
22
+ value = true
23
+ end
24
+ value.should eq true
25
+ end
26
+ end
27
+
28
+ describe '#prompt' do
29
+ it 'should show the window' do
30
+ prompt('test', 'value').should eq 'value'
31
+ end
32
+ end
33
+
34
+ describe '#alert' do
35
+ it 'should show the window' do
36
+ alert('test').should eq 'alert'
37
+ end
38
+ end
39
+
40
+ describe '#confirm' do
41
+ it 'should show the window' do
42
+ confirm('test').should eq true
43
+ end
44
+ end
45
+
46
+ describe '#clear_timeout' do
47
+ it 'should clear the timeout' do
48
+ clear_timeout(0).should eq true
49
+ end
50
+ end
51
+
52
+ describe '#logger' do
53
+ it 'should return logger' do
54
+ logger.should be_a Fron::Logger
55
+ end
56
+ end
57
+ end