opal-ferro 0.10.0 → 0.10.1

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.
@@ -1,12 +1,23 @@
1
- class FerroSequence
2
-
3
- def initialize(label = nil)
4
- @label = label
5
- @next_id = 0
6
- end
1
+ module Ferro
2
+ # A helper class to generate unique labels.
3
+ # These labels can be used to ensure
4
+ # unique instance variable names.
5
+ class Sequence
6
+
7
+ # Create a new sequence.
8
+ #
9
+ # @param [String] prefix a prefix for generated labels
10
+ def initialize(prefix = nil)
11
+ @prefix = prefix
12
+ @next_id = 0
13
+ end
7
14
 
8
- def next
9
- @next_id += 1
10
- "#{@label}#{@next_id}"
15
+ # Get the next label.
16
+ #
17
+ # @return [String] the unique label
18
+ def next
19
+ @next_id += 1
20
+ "#{@prefix}#{@next_id}"
21
+ end
11
22
  end
12
23
  end
@@ -1,82 +1,145 @@
1
- # Based on turbolinks/http_request
2
- require 'json'
3
- require 'native'
4
-
5
- class FerroXhr
6
-
7
- NETWORK_FAILURE = 'Network error'
8
- TIMEOUT_FAILURE = 'Timeout'
9
-
10
- def initialize(url, callback, error_callback, options = {})
11
- @url = url
12
- @callback = callback
13
- @error_callback = error_callback
14
- @referrer = options[:referrer] || 'Ferro'
15
- @timeout = options[:timeout] || 5000
16
- @accept = options[:accept] || 'application/json'
17
- @xhr = nil
18
- @sent = false
19
-
20
- createXHR
21
- send
22
- end
1
+ module Ferro
2
+ require 'json'
3
+ require 'native'
4
+
5
+ # Create and execute AJAX requests.
6
+ # Based on turbolinks/http_request.
7
+ # Specify the url for the request and two callbacks,
8
+ # one for succesful completion of the request and one
9
+ # for a failed request.
10
+ #
11
+ # It is safe to destroy the FerroXhr instance after
12
+ # one of it's callbacks have completed.
13
+ # Note that there are no private methods in Opal. Methods that
14
+ # should be private are marked in the docs with 'Internal method'.
15
+ #
16
+ # This class can only send and receive JSON.
17
+ # For non-get requests a csrf token can be specified or left
18
+ # blank. When blank this class will try to find the token in
19
+ # the header meta data.
20
+ class Xhr
21
+
22
+ # Error message for timeouts.
23
+ TIMEOUT_FAILURE = 'Timeout'
24
+
25
+ # Start AJAX request.
26
+ #
27
+ # Valid options are:
28
+ # * :timeout (Integer) Request-timout
29
+ # * :accept (String) Header-Accept
30
+ # * :method (Symbol) Html method, default: :get
31
+ # * :csrf (String) Csrf token, if blank and method is not :get,
32
+ # meta tag 'csrf-token' will be used
33
+ # * :body (Hash) Hash of parameters to be sent
34
+ #
35
+ # @param [String] url The url for the request
36
+ # @param [Method] callback Success callback method. The callback
37
+ # method should accept one parameter [Hash] containing the
38
+ # parsed json object returned by the AJAX call
39
+ # @param [Method] error_callback Failure callback method. The callback
40
+ # method should accept two parameters [Integer, String]
41
+ # containing the status and error message
42
+ # @param [Hash] options See valid options
43
+ def initialize(url, callback, error_callback, options = {})
44
+ @url = url
45
+ @callback = callback
46
+ @error_callback = error_callback
47
+ @timeout = options[:timeout] || 5000
48
+ @accept = options[:accept] || 'application/json'
49
+ @method = (options[:method] || :get).upcase
50
+ @csrf = options[:csrf]
51
+ @body = options[:body] ? options[:body].to_json.to_s : nil
52
+ @xhr = nil
53
+ @sent = false
23
54
 
24
- def send
25
- if @xhr && !@sent
26
- @xhr.JS.send
27
- @sent = true
55
+ createXHR
56
+ send
28
57
  end
29
- end
30
58
 
31
- def cancel
32
- @xhr.JS.abort if @xhr && @sent
33
- end
59
+ # Internal method to start the AJAX request.
60
+ def send
61
+ if @xhr && !@sent
62
+ @xhr.JS.send(@body)
63
+ @sent = true
64
+ end
65
+ end
34
66
 
35
- def createXHR
36
- @xhr = `new XMLHttpRequest`
37
- `#{@xhr}.open('GET', #{@url}, true)`
38
- `#{@xhr}.timeout = #{@timeout}`
39
- # `#{@xhr}.responseType = 'json'` if @accept == 'application/json'
40
- `#{@xhr}.setRequestHeader('Accept', #{@accept})`
41
- `#{@xhr}.setRequestHeader('Ferro-Referrer', #{@referrer})`
42
- `#{@xhr}.addEventListener('load', function(){#{requestLoaded}})`
43
- `#{@xhr}.addEventListener('error', function(){#{requestFailed}})`
44
- `#{@xhr}.addEventListener('timeout', function(){#{requestTimedOut}})`
45
- `#{@xhr}.addEventListener('abort', function(){#{requestCanceled}})`
46
- nil
47
- end
67
+ # Cancel a running AJAX request.
68
+ def cancel
69
+ @xhr.JS.abort if @xhr && @sent
70
+ end
48
71
 
49
- def destroy
50
- `#{@xhr} = null`
51
- end
72
+ # Internal method to set up the AJAX request.
73
+ def createXHR
74
+ @xhr = `new XMLHttpRequest`
52
75
 
53
- def requestLoaded
54
- begin
55
- status = Native(`#{@xhr}.status`)
56
- raise if status >= 300
57
- json = JSON.parse(`#{@xhr}.response`)
58
- @callback.call(json)
59
- rescue => error
60
- @failed = true
61
- @error_callback.call(status, error)
76
+ `#{@xhr}.open(#{@method}, #{@url}, true)`
77
+ `#{@xhr}.timeout = #{@timeout}`
78
+ `#{@xhr}.setRequestHeader('Accept', #{@accept})`
79
+
80
+ if @method != 'GET'
81
+ `#{@xhr}.setRequestHeader('X-CSRF-Token', #{csrf_token})`
82
+ if @body
83
+ `#{@xhr}.setRequestHeader('Content-Type', #{@accept})`
84
+ `#{@xhr}.setRequestHeader('Content-Length', #{@body.length})`
85
+ end
86
+ end
87
+
88
+ `#{@xhr}.addEventListener('load', function(){#{requestLoaded}})`
89
+ `#{@xhr}.addEventListener('error', function(){#{requestFailed}})`
90
+ `#{@xhr}.addEventListener('timeout', function(){#{requestTimedOut}})`
91
+ `#{@xhr}.addEventListener('abort', function(){#{requestCanceled}})`
92
+ nil
62
93
  end
63
94
 
64
- destroy
65
- end
95
+ # Internal method to get the csrf token from header meta data.
96
+ def csrf_token
97
+ return @csrf if @csrf
98
+ token = Native(`document.getElementsByName('csrf-token')`)
99
+ @csrf = token[0].content if token.length > 0
100
+ end
66
101
 
67
- def requestFailed
68
- @failed = true
69
- @error_callback.call(`#{@xhr}.status`, Native(`#{@xhr}.response`))
70
- destroy
71
- end
102
+ # Internal method to clean up the AJAX request.
103
+ def destroy
104
+ `#{@xhr} = null`
105
+ end
72
106
 
73
- def requestTimedOut
74
- @failed = true
75
- @error_callback.call(0, TIMEOUT_FAILURE)
76
- destroy
77
- end
107
+ # Internal callback method, will call the success callback specified
108
+ # in initialize or the failure callback if the html return status is
109
+ # 300 or higher.
110
+ def requestLoaded
111
+ begin
112
+ status = Native(`#{@xhr}.status`)
113
+ raise if status >= 300
114
+ json = JSON.parse(`#{@xhr}.response`)
115
+ @callback.call(json)
116
+ rescue => error
117
+ @failed = true
118
+ @error_callback.call(status, error)
119
+ end
78
120
 
79
- def requestCanceled
80
- destroy
121
+ destroy
122
+ end
123
+
124
+ # Internal callback method, will call the failure callback specified
125
+ # in initialize.
126
+ def requestFailed
127
+ @failed = true
128
+ @error_callback.call(`#{@xhr}.status`, Native(`#{@xhr}.response`))
129
+ destroy
130
+ end
131
+
132
+ # Internal callback method, will call the failure callback specified
133
+ # in initialize.
134
+ def requestTimedOut
135
+ @failed = true
136
+ @error_callback.call(0, TIMEOUT_FAILURE)
137
+ destroy
138
+ end
139
+
140
+ # Internal callback method.
141
+ def requestCanceled
142
+ destroy
143
+ end
81
144
  end
82
145
  end
data/opal/opal-ferro.rb CHANGED
@@ -1,11 +1,13 @@
1
1
  require 'opal'
2
2
  require 'opal-ferro/ferro_elementary'
3
- require 'opal-ferro/ferro_element'
3
+ require 'opal-ferro/ferro_base_element'
4
4
  require 'opal-ferro/ferro_document'
5
5
  require 'opal-ferro/ferro_factory'
6
6
  require 'opal-ferro/ferro_router'
7
7
  require 'opal-ferro/ferro_xhr'
8
8
  require 'opal-ferro/ferro_sequence'
9
- require 'opal-ferro/ferro_base_elements'
10
- require 'opal-ferro/ferro_form_elements'
11
- require 'opal-ferro/ferro_components'
9
+ require 'opal-ferro/elements/ferro_inline'
10
+ require 'opal-ferro/elements/ferro_components'
11
+ require 'opal-ferro/elements/ferro_form'
12
+ require 'opal-ferro/elements/ferro_misc'
13
+ require 'opal-ferro/elements/ferro_combos'
data/opal-ferro.gemspec CHANGED
@@ -21,7 +21,7 @@ Gem::Specification.new do |s|
21
21
 
22
22
  s.add_development_dependency 'bundler', '~> 1.16'
23
23
  s.add_development_dependency 'rake', '~> 10.0'
24
- # s.add_development_dependency 'yard', '~> 0.8.7'
24
+ s.add_development_dependency 'yard', '~> 0.9.12'
25
25
  s.add_development_dependency 'minitest', '~> 5.0'
26
26
  # s.add_development_dependency 'selenium-webdriver', '~> 3.8'
27
27
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: opal-ferro
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.10.0
4
+ version: 0.10.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ivo Herweijer
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-02-02 00:00:00.000000000 Z
11
+ date: 2018-03-28 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: opal
@@ -52,6 +52,20 @@ dependencies:
52
52
  - - "~>"
53
53
  - !ruby/object:Gem::Version
54
54
  version: '10.0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: yard
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: 0.9.12
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: 0.9.12
55
69
  - !ruby/object:Gem::Dependency
56
70
  name: minitest
57
71
  requirement: !ruby/object:Gem::Requirement
@@ -77,23 +91,28 @@ extra_rdoc_files: []
77
91
  files:
78
92
  - ".gitignore"
79
93
  - ".travis.yml"
94
+ - ".yardopts"
95
+ - CHANGELOG.md
80
96
  - CODE_OF_CONDUCT.md
81
97
  - Gemfile
82
98
  - LICENSE.txt
83
99
  - README.md
84
100
  - Rakefile
101
+ - docs/GettingStarted.md
85
102
  - lib/opal-ferro.rb
86
103
  - lib/opal-ferro/version.rb
87
104
  - lib/opal/ferro.rb
88
105
  - opal-ferro.gemspec
89
106
  - opal/opal-ferro.rb
90
- - opal/opal-ferro/ferro_base_elements.js.rb
91
- - opal/opal-ferro/ferro_components.js.rb
107
+ - opal/opal-ferro/elements/ferro_combos.js.rb
108
+ - opal/opal-ferro/elements/ferro_components.js.rb
109
+ - opal/opal-ferro/elements/ferro_form.js.rb
110
+ - opal/opal-ferro/elements/ferro_inline.js.rb
111
+ - opal/opal-ferro/elements/ferro_misc.js.rb
112
+ - opal/opal-ferro/ferro_base_element.js.rb
92
113
  - opal/opal-ferro/ferro_document.js.rb
93
- - opal/opal-ferro/ferro_element.js.rb
94
114
  - opal/opal-ferro/ferro_elementary.js.rb
95
115
  - opal/opal-ferro/ferro_factory.js.rb
96
- - opal/opal-ferro/ferro_form_elements.js.rb
97
116
  - opal/opal-ferro/ferro_router.js.rb
98
117
  - opal/opal-ferro/ferro_sequence.js.rb
99
118
  - opal/opal-ferro/ferro_xhr.js.rb
@@ -117,7 +136,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
117
136
  version: '0'
118
137
  requirements: []
119
138
  rubyforge_project:
120
- rubygems_version: 2.6.14
139
+ rubygems_version: 2.7.6
121
140
  signing_key:
122
141
  specification_version: 4
123
142
  summary: 'Simplifying web-development: no more html, just beautiful and simple Ruby
@@ -1,158 +0,0 @@
1
- class FerroElementComponent < FerroElement
2
- def component
3
- self
4
- end
5
- end
6
-
7
- # Semantical elements
8
- class FerroElementHeader < FerroElementComponent
9
- def _before_create
10
- @domtype = :header
11
- end
12
- end
13
-
14
- class FerroElementNavigation < FerroElementComponent
15
- def _before_create
16
- @domtype = :nav
17
- end
18
- end
19
-
20
- class FerroElementSection < FerroElementComponent
21
- def _before_create
22
- @domtype = :section
23
- end
24
- end
25
-
26
- class FerroElementArticle < FerroElementComponent
27
- def _before_create
28
- @domtype = :article
29
- end
30
- end
31
-
32
- class FerroElementAside < FerroElementComponent
33
- def _before_create
34
- @domtype = :aside
35
- end
36
- end
37
-
38
- class FerroElementFooter < FerroElementComponent
39
- def _before_create
40
- @domtype = :footer
41
- end
42
- end
43
-
44
- FerroElementBlock = FerroElement
45
-
46
- # Inline elements
47
- class FerroElementText < FerroElement
48
- def _before_create
49
- @size = option_replace :size, 0
50
- @domtype = @size == 0 ? :p : "h#{@size}"
51
- end
52
- end
53
-
54
- class FerroElementList < FerroElement
55
- def _before_create
56
- @domtype = @options.has_key?(:type) ? :ol : :ul
57
- @items = []
58
- @id = FerroSequence.new 'list_'
59
- end
60
-
61
- def add_item(element_class, options = {})
62
- @items << add_child(@id.next, element_class, options).sym
63
- end
64
-
65
- def item_count
66
- @items.length
67
- end
68
-
69
- def first_item
70
- @children[@items.first]
71
- end
72
-
73
- def last_item
74
- @children[@items.last]
75
- end
76
-
77
- def unlist_item(sym)
78
- @items.delete_if { |item| item == sym }
79
- end
80
- end
81
-
82
- class FerroElementListItem < FerroElement
83
- def _before_create
84
- @domtype = :li
85
- end
86
-
87
- def destroy
88
- super
89
- parent.unlist_item(@sym)
90
- end
91
- end
92
-
93
- class FerroElementAnchor < FerroElement
94
- def _before_create
95
- @domtype = :a
96
- @href = @options[:href]
97
- end
98
-
99
- def _after_create
100
- `#{@element}.addEventListener("click",function(e){e.preventDefault();history.pushState(null,null,#{@href});#{clicked};document.activeElement.blur();})`
101
- end
102
-
103
- def update_href(value)
104
- @href = value
105
- set_attribute('href', @href)
106
- end
107
-
108
- def clicked
109
- router.navigated
110
- end
111
- end
112
-
113
- class FerroElementExternalLink < FerroElement
114
- def _before_create
115
- @domtype = :a
116
- @options[:target] ||= '_blank'
117
- end
118
- end
119
-
120
- # Miscellaneous elements
121
- class FerroElementImage < FerroElement
122
-
123
- # Todo use:
124
- # <figure>
125
- # <figcaption>
126
-
127
- def _before_create
128
- @domtype = :img
129
- @options[:alt] ||= @options[:src]
130
- end
131
- end
132
-
133
- class FerroElementCanvas < FerroElement
134
- def _before_create
135
- @domtype = :canvas
136
- end
137
- end
138
-
139
- class FerroElementScript < FerroElement
140
- def _before_create
141
- @domtype = :script
142
- @run = option_replace :invoke, true
143
- end
144
-
145
- def _after_create
146
- load
147
- invoke if @run
148
- end
149
-
150
- def load;end
151
- def invoke;end
152
- end
153
-
154
- class FerroElementVar < FerroElement
155
- def _before_create
156
- @domtype = option_replace :domtype, :div
157
- end
158
- end
@@ -1,92 +0,0 @@
1
- # A component with a text entry field and submit button
2
- class FerroFormSearch < FerroForm
3
-
4
- def _before_create
5
- @button_text = option_replace :button_text, ' '
6
- @placeholder = option_replace :placeholder, ' Search...'
7
- end
8
-
9
- def cascade
10
- add_child :entry, FerroFormSearchInput, { placeholder: @placeholder }
11
- add_child :submit, FerroFormSearchSubmit, { content: @button_text }
12
- end
13
-
14
- def do_submit
15
- value = entry.value.strip
16
- submitted(value) if !value.empty?
17
-
18
- entry.toggle_state :search_input_open
19
- submit.toggle_state :search_submit_open
20
-
21
- entry.value = nil
22
- entry.set_focus if entry.state_active?(:search_input_open)
23
- end
24
-
25
- def submitted(value);end
26
- end
27
-
28
- class FerroFormSearchInput < FerroFormInput
29
-
30
- def _after_create
31
- add_state :search_input_open
32
- super
33
- end
34
-
35
- def entered
36
- parent.do_submit
37
- end
38
- end
39
-
40
- class FerroFormSearchSubmit < FerroFormButton
41
-
42
- def _after_create
43
- add_state :search_submit_open
44
- super
45
- end
46
-
47
- def clicked
48
- parent.do_submit
49
- end
50
- end
51
-
52
- # A simple pull-down menu
53
- # @option[items]: a list of classes
54
- class FerroPullDown < FerroElementBlock
55
-
56
- def _before_create
57
- @title_text = option_replace :title, '='
58
- @items = option_replace :items, []
59
- super
60
- end
61
-
62
- def _after_create
63
- add_state :pull_down_open
64
- super
65
- end
66
-
67
- def cascade
68
- add_child :title, FerroPullDownTitle, { content: @title_text }
69
- add_child :items, FerroPullDownItems, { items: @items }
70
- end
71
- end
72
-
73
- class FerroPullDownTitle < FerroFormBlock
74
- def clicked
75
- parent.toggle_state :pull_down_open
76
- end
77
- end
78
-
79
- class FerroPullDownItems < FerroElementBlock
80
-
81
- def _before_create
82
- @id = FerroSequence.new 'pdi_'
83
- @itemlist = option_replace :items, []
84
- super
85
- end
86
-
87
- def cascade
88
- @items = @itemlist.map do |item|
89
- add_child @id.next, item
90
- end
91
- end
92
- end