fron 0.1.4 → 0.2.0rc1

Sign up to get free protection for your applications and to get access to all the features.
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