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,11 @@
1
+ # Object
2
+ # http://whytheluckystiff.net/articles/seeingMetaclassesClearly.html
3
+ class Object
4
+ # Defines a class method
5
+ #
6
+ # @param name [String] The name of the method
7
+ # @param blk [Block] The body of the method
8
+ def meta_def(name, &blk)
9
+ (class << self; self; end).instance_eval { define_method name, &blk }
10
+ end
11
+ end
@@ -0,0 +1,19 @@
1
+ # Proc
2
+ class Proc
3
+ # Runs the given block after the given wait period
4
+ # if called continously
5
+ #
6
+ # @param ms [Numeric] The wait period
7
+ def throttle(ms)
8
+ Native `throttle(#{self}, #{ms}, {leading: false})`
9
+ end
10
+
11
+ # Runs the given block after the given wait period
12
+ # if called continously. The wait period restarts with each call
13
+ #
14
+ # @param ms [Numeric] The wait period
15
+ # @param leading [Boolean] To run the function at the start or not
16
+ def debounce(ms, leading = false)
17
+ Native `debounce(#{self}, #{ms}, #{leading})`
18
+ end
19
+ end
@@ -1,4 +1,8 @@
1
+ # String
1
2
  class String
3
+ # Returns the camelized version of self
4
+ #
5
+ # @return [String] The camelized version
2
6
  def camelize
3
7
  `#{self}.replace(/(?:-|_|(\/))([a-z\d]*)/gi,function(m,first,second){
4
8
  return second.charAt(0).toUpperCase() + second.substr(1).toLowerCase()
@@ -1,13 +1,15 @@
1
- require './dom/modules/events'
2
- require './dom/modules/classlist'
3
- require './dom/modules/dimensions'
4
- require './dom/nodelist'
5
- require './dom/style'
6
- require './dom/node'
7
- require './dom/text'
8
- require './dom/element'
9
- require './dom/fragment'
10
- require './dom/document'
11
- require './dom/window'
12
- require './dom/event'
13
- require './dom/file-reader'
1
+ require 'fron/dom/modules/events'
2
+ require 'fron/dom/modules/classlist'
3
+ require 'fron/dom/modules/dimensions'
4
+ require 'fron/dom/modules/attributes'
5
+ require 'fron/dom/modules/element_accessor'
6
+ require 'fron/dom/nodelist'
7
+ require 'fron/dom/style'
8
+ require 'fron/dom/node'
9
+ require 'fron/dom/text'
10
+ require 'fron/dom/element'
11
+ require 'fron/dom/fragment'
12
+ require 'fron/dom/document'
13
+ require 'fron/dom/window'
14
+ require 'fron/dom/event'
15
+ require 'fron/dom/file_reader'
@@ -1,28 +1,44 @@
1
1
  module DOM
2
+ # This module is a wrapper for the native *document* object.
2
3
  module Document
3
- def self.activeElement
4
+ extend SingleForwardable
5
+ @doc = DOM::Element.new `document`
6
+
7
+ def_delegators :@doc, :find
8
+
9
+ # Returns the active element
10
+ #
11
+ # @return [DOM::Element] The element
12
+ def self.active_element
4
13
  find ':focus'
5
14
  end
6
15
 
16
+ # Returns the head element
17
+ #
18
+ # @return [DOM::Element] The head element
7
19
  def self.head
8
20
  @head ||= find 'head'
9
21
  end
10
22
 
23
+ # Returns the body element
24
+ #
25
+ # @return [DOM::Element] The body element
11
26
  def self.body
12
27
  @body ||= find 'body'
13
28
  end
14
29
 
30
+ # Returns the documents title
31
+ #
32
+ # @return [String] The title
15
33
  def self.title
16
34
  `document.title`
17
35
  end
18
36
 
37
+ # Sets the documents title with the given value
38
+ #
39
+ # @param value [String] The title
19
40
  def self.title=(value)
20
41
  `document.title = #{value}`
21
42
  end
22
-
23
- def self.find(selector)
24
- value = `document.querySelector(#{selector}) || false`
25
- value ? DOM::Element.new(value) : nil
26
- end
27
43
  end
28
44
  end
@@ -1,36 +1,60 @@
1
1
  module DOM
2
+ # Element
3
+ #
4
+ # TODO: Describe the element creation ways here
2
5
  class Element < NODE
6
+ extend ElementAccessor
7
+ include Attributes
3
8
  include ClassList
4
9
  include Dimensions
5
10
 
11
+ # @return [Style] The style object
6
12
  attr_reader :style
7
13
 
8
- EVENT_TARGET_CLASS = self
14
+ # Attribute regexp
9
15
  ATTRIBUTE_REGEXP = /\[(.*?)=(.*?)\]/
16
+
17
+ # Tag regexp
10
18
  TAG_REGEXP = /(^[A-Za-z_\-0-9]+)(.*)/
19
+
20
+ # Modifier regexp
11
21
  MODIFIER_REGEXP = /(#|\.)(.+?)(?=#|\.| |$)/
12
22
 
23
+ element_accessor :value
24
+ element_accessor :innerHTML, as: :html
25
+
26
+ element_accessor :readonly, default: false
27
+ element_accessor :checked, default: false
28
+ element_accessor :disabled, default: false
29
+
30
+ element_method :focus
31
+ element_method :blur
32
+
33
+ # Initializes a new elment based on the data
34
+ #
35
+ # @param data [*] The data
13
36
  def initialize(data)
14
37
  if `typeof #{data} === 'string'`
15
- match, tag, rest = data.match(TAG_REGEXP).to_a
38
+ tag, rest = data.match(TAG_REGEXP).to_a[1..2]
16
39
  @el = `document.createElement(#{tag})`
40
+ `#{@el}._instance = #{self}`
17
41
  rest = rest.gsub ATTRIBUTE_REGEXP do |match|
18
- m,key,value = match.match(ATTRIBUTE_REGEXP).to_a
42
+ key, value = match.match(ATTRIBUTE_REGEXP).to_a[1..2]
19
43
  self[key] = value
20
44
  ''
21
45
  end
22
46
  rest = rest.gsub MODIFIER_REGEXP do |match|
23
- m,type,value = match.match(MODIFIER_REGEXP).to_a
47
+ type, value = match.match(MODIFIER_REGEXP).to_a[1..2]
24
48
  case type
25
- when "#"
49
+ when '#'
26
50
  self['id'] = value
27
- when "."
28
- addClass value
51
+ when '.'
52
+ add_class value
29
53
  end
30
54
  ''
31
55
  end
32
- if (m = rest.match /\s(.+)$/)
33
- self.text = m[0].strip
56
+ if (match = rest.match(/\s(.+)$/))
57
+ self.text = match[0].strip
34
58
  end
35
59
  else
36
60
  super data
@@ -38,6 +62,11 @@ module DOM
38
62
  @style = Style.new @el
39
63
  end
40
64
 
65
+ # Returns whether or not the element matches the given selector
66
+ #
67
+ # @param selector [String] The selector
68
+ #
69
+ # @return [Boolean] True if matches false if not
41
70
  def matches(selector)
42
71
  %x{
43
72
  var proto = Element.prototype
@@ -50,81 +79,90 @@ module DOM
50
79
  }
51
80
  end
52
81
 
53
- # Visiblity
54
- # --------------------------------
82
+ # Hides the element
55
83
  def hide
56
84
  @style.display = 'none'
57
85
  end
58
86
 
87
+ # Shows the element
59
88
  def show
60
- @style.display = 'block'
61
- end
62
-
63
- # Attribute access
64
- # --------------------------------
65
- def [](name)
66
- `#{@el}.getAttribute(#{name})`
67
- end
68
-
69
- def []=(name,value)
70
- `#{@el}.setAttribute(#{name},#{value})`
71
- end
72
-
73
- # Traversing
74
- # --------------------------------
75
- def find(selector)
76
- value = `#{@el}.querySelector(#{selector}) || false`
77
- value ? DOM::Element.new(value) : nil
78
- end
79
-
80
- # HTML Modification
81
- # --------------------------------
82
- def html
83
- `#{@el}.innerHTML`
84
- end
85
-
86
- def html=(value)
87
- `#{@el}.innerHTML = #{value}`
88
- end
89
-
90
- def value
91
- `#{@el}.value`
92
- end
93
-
94
- def value=(value)
95
- `#{@el}.value = #{value}`
96
- end
97
-
98
- def checked
99
- `!!#{@el}.checked`
100
- end
101
-
102
- def checked=(value)
103
- `#{@el}.checked = #{value}`
104
- end
105
-
106
- def disabled
107
- `#{@el}.disabled`
108
- end
109
-
110
- def disabled=(value)
111
- `#{@el}.disabled = #{value}`
112
- end
113
-
114
- def focus
115
- `#{@el}.focus()`
89
+ @style.display = ''
116
90
  end
117
91
 
92
+ # Return the files of the element
93
+ #
94
+ # @return [Array] The files
118
95
  def files
119
96
  Native `#{@el}.files`
120
97
  end
121
98
 
99
+ # Returns the lowercased tag name of the lement
100
+ #
101
+ # @return [String] The tag name
122
102
  def tag
123
103
  `#{@el}.tagName`.downcase
124
104
  end
125
105
 
106
+ # Returns the id of the element
107
+ #
108
+ # @return [String] The id
126
109
  def id
127
110
  self['id']
128
111
  end
112
+
113
+ # Returns the element matching the given selector or nil
114
+ #
115
+ # @param selector [String] The selector
116
+ #
117
+ # @return [DOM::Element] The element
118
+ def find(selector)
119
+ DOM::Element.from_node `#{@el}.querySelector(#{selector}) || Opal.nil`
120
+ end
121
+
122
+ # Finds all of the elements matching the selector.
123
+ #
124
+ # @param selector [String] The selector
125
+ #
126
+ # @return [NodeList] The elements
127
+ def find_all(selector)
128
+ DOM::NodeList.new `Array.prototype.slice.call(#{@el}.querySelectorAll(#{selector}))`
129
+ end
130
+
131
+ # Returns the next element sibling
132
+ #
133
+ # @return [DOM::Element] The element
134
+ def next
135
+ DOM::Element.from_node `#{@el}.nextElementSibling || Opal.nil`
136
+ end
137
+
138
+ # Returns the previous element sibling
139
+ #
140
+ # @return [DOM::Element] The element
141
+ def previous
142
+ DOM::Element.from_node `#{@el}.previousElementSibling || Opal.nil`
143
+ end
144
+
145
+ # Returns whether or not the given node
146
+ # is inside the node.
147
+ #
148
+ # @param other [DOM::NODE] The other node
149
+ #
150
+ # @return [Boolean] True if contains false if not
151
+ def include?(other)
152
+ `#{@el}.contains(#{DOM::NODE.get_element(other)})`
153
+ end
154
+
155
+ # Returns the path of the elemnt
156
+ #
157
+ # @return [String] The path
158
+ def path
159
+ element = self
160
+ items = [element.tag]
161
+ while element.parent
162
+ items.unshift element.parent.tag
163
+ element = element.parent
164
+ end
165
+ items.join ' '
166
+ end
129
167
  end
130
168
  end
@@ -1,6 +1,7 @@
1
1
  module DOM
2
+ # Event
2
3
  class Event
3
-
4
+ # Special keys for converions
4
5
  SPECIAL_KEYS = {
5
6
  8 => 'backspace',
6
7
  9 => 'tab',
@@ -94,95 +95,164 @@ module DOM
94
95
  221 => ']',
95
96
  222 => '\'',
96
97
  224 => 'cmd',
97
- 57392 => 'ctrl',
98
- 63289 => 'num'
98
+ 57_392 => 'ctrl',
99
+ 63_289 => 'num'
99
100
  }
100
101
 
101
- def initialize(e,targetClass)
102
- @e = e
103
- @targetClass = targetClass
102
+ # Initializes the event
103
+ #
104
+ # @param event [Event] The native event
105
+ def initialize(event)
106
+ @event = event
107
+ end
108
+
109
+ # Runs missing method calls
110
+ #
111
+ # @param name [String] The name of the method
112
+ def method_missing(name)
113
+ `#{@event}[#{name}]`
104
114
  end
105
115
 
116
+ # Returns the string represenation of the pressed key
117
+ #
118
+ # @return [String] The pressed key
106
119
  def key
107
- return SPECIAL_KEYS[keyCode] if SPECIAL_KEYS[keyCode]
108
- `String.fromCharCode(#{keyCode}).toLowerCase()`
120
+ return SPECIAL_KEYS[key_code] if SPECIAL_KEYS[key_code]
121
+ `String.fromCharCode(#{key_code}).toLowerCase()`
109
122
  end
110
123
 
111
- def stopImmediatePropagation
112
- `#{@e}.stopImmediatePropagation()`
124
+ # Stops the immediate propagation of the event
125
+ def stop_immediate_propagation
126
+ `#{@event}.stopImmediatePropagation()`
113
127
  end
114
128
 
115
- def dataTransfer
116
- Native `#{@e}.dataTransfer`
129
+ # Returns the native dataTransfrer object
130
+ #
131
+ # @return [Object] The object
132
+ def data_transfer
133
+ Native `#{@event}.dataTransfer`
117
134
  end
118
135
 
136
+ # Returns the index of the pressed mouse button
137
+ #
138
+ # @return [Numeric] The index
119
139
  def button
120
- `#{@e}.button`
140
+ `#{@event}.button`
121
141
  end
122
142
 
143
+ # Returns the target of the event
144
+ #
145
+ # @return [DOM::NODE] The target
123
146
  def target
124
- @targetClass.new `#{@e}.target`
147
+ DOM::Element.from_node `#{@event}.target`
125
148
  end
126
149
 
127
- def charCode
128
- `#{@e}.charCode`
150
+ # Returns the character code of the pressed key
151
+ #
152
+ # @return [Numeric] The code
153
+ def char_code
154
+ `#{@event}.charCode`
129
155
  end
130
156
 
131
- def keyCode
132
- `#{@e}.keyCode`
157
+ # Returns the key code of the pressed key
158
+ #
159
+ # @return [Numeric] The code
160
+ def key_code
161
+ `#{@event}.keyCode`
133
162
  end
134
163
 
164
+ # Stops the event
135
165
  def stop
136
- preventDefault
137
- stopPropagation
166
+ prevent_default
167
+ stop_immediate_propagation
168
+ stop_propagation
169
+ end
170
+
171
+ # Returns whether the default was prevented or not
172
+ #
173
+ # @return [Boolean] True if it has false if not
174
+ def default_prevented?
175
+ `#{@event}.defaultPrevented`
138
176
  end
139
177
 
140
- def preventDefault
141
- `#{@e}.preventDefault()`
178
+ # Prevents the default action of the event
179
+ def prevent_default
180
+ `#{@event}.preventDefault()`
142
181
  end
143
182
 
144
- def stopPropagation
145
- `#{@e}.stopPropagation()`
183
+ # Stops the propagation of the event
184
+ def stop_propagation
185
+ `#{@event}.stopPropagation()`
146
186
  end
147
187
 
148
- def pageX
149
- `#{@e}.pageX`
188
+ # Returns the pageX coordinate of the event
189
+ #
190
+ # @return [Numeric] The coordinate
191
+ def page_x
192
+ `#{@event}.pageX`
150
193
  end
151
194
 
152
- def pageY
153
- `#{@e}.pageY`
195
+ # Returns the pageY coordinate of the event
196
+ #
197
+ # @return [Numeric] The coordinate
198
+ def page_y
199
+ `#{@event}.pageY`
154
200
  end
155
201
 
156
- def screenX
157
- `#{@e}.screenX`
202
+ # Returns the screenX coordinate of the event
203
+ #
204
+ # @return [Numeric] The coordinate
205
+ def screen_x
206
+ `#{@event}.screenX`
158
207
  end
159
208
 
160
- def screenY
161
- `#{@e}.screenY`
209
+ # Returns the screenY coordinate of the event
210
+ #
211
+ # @return [Numeric] The coordinate
212
+ def screen_y
213
+ `#{@event}.screenY`
162
214
  end
163
215
 
164
- def clientX
165
- `#{@e}.clientX`
216
+ # Returns the clientX coordinate of the event
217
+ #
218
+ # @return [Numeric] The coordinate
219
+ def client_x
220
+ `#{@event}.clientX`
166
221
  end
167
222
 
168
- def clientY
169
- `#{@e}.clientY`
223
+ # Returns the clientY coordinate of the event
224
+ #
225
+ # @return [Numeric] The coordinate
226
+ def client_y
227
+ `#{@event}.clientY`
170
228
  end
171
229
 
230
+ # Returns whether the alt key has been pressed
231
+ #
232
+ # @return [Boolan] True if pressed false if not
172
233
  def alt?
173
- `#{@e}.altKey`
234
+ `#{@event}.altKey`
174
235
  end
175
236
 
237
+ # Returns whether the shift key has been pressed
238
+ #
239
+ # @return [Boolan] True if pressed false if not
176
240
  def shift?
177
- `#{@e}.shiftKey`
241
+ `#{@event}.shiftKey`
178
242
  end
179
243
 
244
+ # Returns whether the control key has been pressed
245
+ #
246
+ # @return [Boolan] True if pressed false if not
180
247
  def ctrl?
181
- `#{@e}.ctrlKey`
248
+ `#{@event}.ctrlKey`
182
249
  end
183
250
 
251
+ # Returns whether the meta (apple) key has been pressed
252
+ #
253
+ # @return [Boolan] True if pressed false if not
184
254
  def meta?
185
- `#{@e}.metaKey`
255
+ `#{@event}.metaKey`
186
256
  end
187
257
  end
188
258
  end