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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: f56567922f613ccb4b5dc4bf3dae7ea52c67f24b
4
- data.tar.gz: 9214aa5989306aacd55e435d43161ba60ac26a30
2
+ SHA256:
3
+ metadata.gz: 0cf34d1239b6886601737690e639cadd7e0fd9971a73cb233eed18faf78ba764
4
+ data.tar.gz: 9d6f89cbc0c4fc22c095d0b3d057e1255ccbc28f2b6ae8da7cdca3222d6fae39
5
5
  SHA512:
6
- metadata.gz: 66c1f60432258923680daddeef451abecfae6cf9b77d94877f088cd574f8d59385c4210cbe073614e1164b65c0e676c64de8646d6f1d9c9ce3069a4b454d54a1
7
- data.tar.gz: d82fc2be389ff2954bf55f086ffc1f3bef427017c6dd534d0d35b63425dd702673617290a8339f6fe874367a5aa84b4142ffeb2d49f84c08707a7ae20aa6a8f2
6
+ metadata.gz: 4e92a9b4a555a1a8c9ae937b222a43880b3d650aefb5400fe08766cb8cdf7f4e3f95351ba8b267c3f7f6e1d08dc5967c465056bf911572cd2fd2c6a1c94b3e4d
7
+ data.tar.gz: 7de1f758372345527f612eeb744727c4c97282f706154979edc439f230f00a4fa043403c2785570dee947f625212b9041c9e691c8019c03ee8a34704074b386a
data/.gitignore CHANGED
@@ -8,3 +8,4 @@
8
8
  /spec/reports/
9
9
  /tmp/
10
10
  /.ruby-version
11
+ *.gem
data/.yardopts ADDED
@@ -0,0 +1,8 @@
1
+ opal/**/*.rb
2
+ lib/**/*.rb
3
+ -
4
+ README.md
5
+ docs/GettingStarted.md
6
+ CHANGELOG.md
7
+ LICENSE.txt
8
+ CODE_OF_CONDUCT.md
data/CHANGELOG.md ADDED
@@ -0,0 +1,23 @@
1
+ # 0.10.1 - March 31, 2018
2
+
3
+ - Added documentation (using Yard)
4
+ - Modularized Ferro (breaking change), see below
5
+ - AJAX can now handle any type of request (not just get)
6
+
7
+ To upgrade from 0.10.0 to 0.10.1:
8
+
9
+ - replace FerroDocument with Ferro::Document
10
+ - replace FerroXhr with Ferro::Xhr
11
+ - replace FerroSequence with Ferro::Sequence
12
+ - replace FerroElementForm with Ferro::Form::Base
13
+ - replace FerroElementForm... with Ferro::Form::...
14
+ - replace FerroElementComponent with Ferro::Component::Base
15
+ - replace FerroElementComponent... with Ferro::Component::...
16
+ - replace FerroSearch with Ferro::Combo::Search
17
+ - replace FerroPullDown with Ferro::Combo::PullDown
18
+ - replace FerroElement... with Ferro::Element::...
19
+
20
+
21
+ # 0.10.0 - February 2, 2018
22
+
23
+ Initial version
data/README.md CHANGED
@@ -1,4 +1,9 @@
1
1
  # Opal-Ferro
2
+
3
+ [![Documentation](http://img.shields.io/badge/docs-rdoc.info-blue.svg)](http://rubydoc.org/gems/opal-ferro)
4
+ [![Gem Version](https://img.shields.io/badge/gem%20version-0.10.1-blue.svg)](https://github.com/easydatawarehousing/opal-ferro/releases)
5
+ [![License](http://img.shields.io/badge/license-MIT-yellowgreen.svg)](#license)
6
+
2
7
  Ferro is a small Ruby library on top of [Opal](http://opalrb.com/)
3
8
  that enables an object-oriented programming style for creating code
4
9
  that runs in the webbrowser.
@@ -24,6 +29,17 @@ Or install it yourself:
24
29
  Please see the [Ferro website](https://easydatawarehousing.github.io/ferro/)
25
30
  for background information and examples.
26
31
 
32
+ ## Versioning
33
+ Opal-Ferro follows the versioning scheme of [Opal](https://github.com/opal/opal).
34
+ The first two parts of the version number of Ferro imply compatibility
35
+ with the Opal version with that same number.
36
+ So Ferro 0.10.x should be compatible with and dependant on Opal 0.10.x.
37
+
38
+ ## Roadmap
39
+ Please see the development roadmap
40
+ [here](https://github.com/easydatawarehousing/opal-ferro/wiki/Development-roadmap)
41
+ for the current wishlist of features to be added to Ferro.
42
+
27
43
  ## Development
28
44
  To install this gem onto your local machine, run `bundle exec rake install`.
29
45
  To release a new version, update the version number in `version.rb`
@@ -38,6 +54,19 @@ This project is intended to be a safe, welcoming space for collaboration
38
54
  and contributors are expected to adhere to the
39
55
  [Contributor Covenant](http://contributor-covenant.org) code of conduct.
40
56
 
57
+ ## Documentation
58
+ Yard is used to generate documentation. In development start yard using:
59
+
60
+ yard server -r
61
+
62
+ Use this to list all undocumented items:
63
+
64
+ yard stats --list-undoc
65
+
66
+ To generate documentation for publication, cd into project root and use:
67
+
68
+ yardoc
69
+
41
70
  ## License
42
71
  The gem is available as open source under the terms of the MIT License.
43
72
  See LICENSE.txt
@@ -0,0 +1,187 @@
1
+ # @title Getting started with Opal-Ferro
2
+
3
+ # Getting started with Opal-Ferro
4
+
5
+ Ferro is a small Ruby library on top of [Opal](http://opalrb.com/)
6
+ that enables an object-oriented programming style for creating code
7
+ that runs in the webbrowser.
8
+ No more distractions like HTML and searching for DOM elements,
9
+ just beautiful and simple Ruby code. Front-End-Ruby-ROcks!
10
+
11
+
12
+ * [How does Ferro work](#ferro)
13
+ * [Creating the Master Object Model](#mom)
14
+ * [Adding elements](#demo)
15
+ * [Creation lifecycle](#lifecycle)
16
+ * [Navigating the Master Object Model](#navigating)
17
+ * [Styling Ferro elements](#styling)
18
+ * [More information](#more)
19
+
20
+ <a name="ferro"></a>
21
+
22
+ ## How does Ferro work?
23
+ Ferro uses an object oriented programming style. You instantiate an object, that object
24
+ in turn instantiates more child objects and add these as instance variables to itself.
25
+ And so on, producing a hierarchy of object instances.
26
+ This is called the Master Object Model (MOM).
27
+
28
+ When an object is instanciated in the MOM, Ferro will add an element to the webbrowsers
29
+ Document Object Model (DOM). The MOM keeps a reference to every DOM element.
30
+ This erradicates the need for element lookups (jquery $ searches).
31
+ If you need an element you know where to find it in the MOM.
32
+ Getter methods are automatically added by Ferro for easy access to instance variables.
33
+
34
+ Each object in the MOM inherits from a Ferro class.
35
+ Which Ferro class you use determines what type of DOM element will be created.
36
+ All Ferro classes inherit from one base class: Ferro::BaseElement.
37
+ For most DOM elements in the html specs there is a corresponding Ferro class.
38
+ For instance if you need a html5 `<header>` element you would create a class that inherits
39
+ from Ferro::Component::Header.
40
+ Other html elements have a more abstract counterpart:
41
+ all text elements (`<p>`, `<h1>` .. `<h6>`) have one Ferro class `Ferro::Element::Text`.
42
+ The size of the text element is an option when you instantiate the object.
43
+
44
+ <a name="mom"></a>
45
+
46
+ ## Creating the Master Object Model
47
+
48
+ First we need a class that inherits from FerroDocument.
49
+ This is the staring point for any Ferro application.
50
+ The Document instance will attach itself in the DOM to
51
+ `document.body`.
52
+
53
+ In the example below, the Document instance will create one child element.
54
+
55
+ class Document < Ferro::Document
56
+
57
+ # The cascade method is called after the Document
58
+ # has been created and is ready to create child
59
+ # objects.
60
+ def cascade
61
+ add_child :demo, Demo
62
+ end
63
+ end
64
+
65
+ To start the application one instance of the Document must be created.
66
+ In the `application.js` file (if you are using Rails for instance)
67
+ `Document.new` is called when the browser has loaded the necessary
68
+ files.
69
+
70
+ `document.addEventListener("DOMContentLoaded", function() {#{Document.new};})`
71
+
72
+ The backticks are Opal's way of entering _raw_ Javascript. Using
73
+ familiar Ruby string interpolation `#{}` a reference to `Document.new` can
74
+ be inserted.
75
+ This is the first and last line of Javascript that is needed.
76
+ Everyting else is Ruby code.
77
+
78
+ <a name="demo"></a>
79
+
80
+ ## Adding elements
81
+
82
+ Let's look at a very simple example. We will define a small component
83
+ with a title and a button. The button should change the title text when clicked.
84
+
85
+ class Demo < Ferro::Component::Base
86
+ def cascade
87
+ # Add a title
88
+ add_child :title, Ferro::Element::Text, size: 4, content: 'Title'
89
+
90
+ # Add a button
91
+ add_child :btn, DemoButton, content: 'Click me'
92
+ end
93
+
94
+ def rotate_title
95
+ # We have access to the 'title' instance variable
96
+ txt = title.get_text
97
+ title.set_text (txt[1..-1] + txt[0]).capitalize
98
+ end
99
+ end
100
+
101
+ class DemoButton < Ferro::Form::Button
102
+ def clicked
103
+ # Every element knows its parent
104
+ parent.rotate_title
105
+ end
106
+ end
107
+
108
+ The code in Demo _cascade_ method is equivalent to something like this,
109
+ which should look more familiar to a Ruby programmer:
110
+
111
+ class Demo
112
+ def initialize
113
+ @title = Ferro::Element::Text.new(size: 4, content: 'Title')
114
+ @btn = DemoButton.new(content: 'Click me')
115
+ end
116
+ end
117
+
118
+ Just like above, the `add_child` method will create instance variables
119
+ `@title` and `@btn`. In Ferro we don't need to use the @.
120
+
121
+ <a name="lifecycle"></a>
122
+
123
+ ## Creation lifecycle
124
+
125
+ Every Ferro class has 3 hooks into the object creation lifecycle:
126
+
127
+ - before_create
128
+ - after_create
129
+ - cascade
130
+
131
+ The first two are called just before and after the object itself
132
+ is created. The cascade hook is called when the object is ready
133
+ to create child objects.
134
+ In this example most of the action happens in the _cascade_ method.
135
+
136
+ By inheriting from _Ferro::Form::Button_, _DemoButton_ has access
137
+ to the click event handler. After a click occurred, it signals
138
+ its parent (_Demo_) to rotate the title text.
139
+
140
+ <a name="navigating"></a>
141
+
142
+ ## Navigating the Master Object Model
143
+
144
+ There are two ways to navigate around the MOM: upward and downward.
145
+ Every object in the MOM knows its parent. If an event is received by an
146
+ object like a button, the parent of that object usually can handle the
147
+ event. The parent element can be accessed using the `parent` method.
148
+
149
+ Searching upward further than one parent quickly becomes difficult to
150
+ follow. So you can always search downward starting from the top.
151
+ Every object in the MOM can access the root object using the `root`
152
+ method. From the root you can access all MOM objects.
153
+
154
+ There is a shortcut to find an object starting from the nearest element
155
+ in the hierarchy that is a component. All semantical elements
156
+ (like header and section) are components. All objects that are children
157
+ of a component have immediate access to that component using the
158
+ `component` method.
159
+
160
+ <a name="styling"></a>
161
+
162
+ ## Styling Ferro elements
163
+
164
+ The created elements still need some styling. Ferro uses a handy
165
+ naming convention: CSS classnames match Ruby classnames.
166
+ For example:
167
+
168
+ class DemoButton < Ferro::Form::Button
169
+ end
170
+
171
+ When we create this button in the MOM, its DOM counterpart receives
172
+ two classnames. One matching the Ruby classname `DemoButton` and
173
+ one for its Ruby superclass `FerroFormButton`.
174
+ These classnames are _dasherized_. In CSS you can reference these
175
+ classnames as `demo-button` and `ferro-form-button`.
176
+
177
+ <a name="more"></a>
178
+
179
+ ## More information
180
+
181
+ Please see the [Ferro website](https://easydatawarehousing.github.io/ferro/)
182
+ for more information and examples.
183
+ The [source code](https://github.com/easydatawarehousing/ferro)
184
+ for that webapp is a good Ferro example in itself.
185
+
186
+ For some simple boilerplate code to get started with Ferro you can use
187
+ [this Rails example](https://github.com/easydatawarehousing/ferro-example-todolist).
@@ -1,5 +1,13 @@
1
+ # Ferro relies on Opal to run in the webbrowser.
1
2
  module Opal
3
+
4
+ # This module contains all Ferro functionality.
2
5
  module Ferro
3
- VERSION = "0.10.0"
6
+ # Opal-Ferro follows the versioning scheme of Opal.
7
+ # The first two parts of the version number of Ferro imply
8
+ # compatibility with the Opal version with that same number.
9
+ # So Ferro 0.10.x should be compatible with and dependant
10
+ # on Opal 0.10.x.
11
+ VERSION = "0.10.1"
4
12
  end
5
- end
13
+ end
@@ -0,0 +1,130 @@
1
+ module Ferro
2
+
3
+ # This module contains some combined elements.
4
+ module Combo
5
+ # Creates a form with a text input and a submit button.
6
+ # Specify option :button_text to set the submit button text.
7
+ # Specify option :placeholder to set a placeholder text for the input.
8
+ # Two states are defined: search-input-open, search-submit-open
9
+ # to define CSS rules.
10
+ class Search < Form::Base
11
+
12
+ # Internal method.
13
+ def _before_create
14
+ @button_text = option_replace :button_text, ' '
15
+ @placeholder = option_replace :placeholder, ' Search...'
16
+ end
17
+
18
+ # Internal method.
19
+ def cascade
20
+ add_child :entry, SearchInput, { placeholder: @placeholder }
21
+ add_child :submit, SearchSubmit, { content: @button_text }
22
+ end
23
+
24
+ # Internal method.
25
+ def do_submit
26
+ value = entry.value.strip
27
+ submitted(value) if !value.empty?
28
+
29
+ entry.toggle_state :search_input_open
30
+ submit.toggle_state :search_submit_open
31
+
32
+ entry.value = nil
33
+ entry.set_focus if entry.state_active?(:search_input_open)
34
+ end
35
+
36
+ # Override this method to specify what happens when
37
+ # submit button is clicked or enter key is pressed.
38
+ #
39
+ # @param [String] value The value of the text input.
40
+ def submitted(value);end
41
+ end
42
+
43
+ # Internal class for use with {Search}.
44
+ class SearchInput < Form::Input
45
+
46
+ # Internal method.
47
+ def _after_create
48
+ add_state :search_input_open
49
+ super
50
+ end
51
+
52
+ # Internal method.
53
+ def entered
54
+ parent.do_submit
55
+ end
56
+ end
57
+
58
+ # Internal class for use with {Search}.
59
+ class SearchSubmit < Form::Button
60
+
61
+ # Internal method.
62
+ def _after_create
63
+ add_state :search_submit_open
64
+ super
65
+ end
66
+
67
+ # Internal method.
68
+ def clicked
69
+ parent.do_submit
70
+ end
71
+ end
72
+
73
+ # Creates a simple pull-down menu.
74
+ # Specify option :title to set the menu title text.
75
+ # Specify option :items as an Array of Ferro classes.
76
+ # Each class should be something clickable, for instance a
77
+ # FormBlock. These classes will be instanciated by
78
+ # this element.
79
+ class PullDown < BaseElement
80
+
81
+ # Internal method.
82
+ def _before_create
83
+ @title_text = option_replace :title, '='
84
+ @items = option_replace :items, []
85
+ super
86
+ end
87
+
88
+ # Internal method.
89
+ def _after_create
90
+ add_state :pull_down_open
91
+ super
92
+ end
93
+
94
+ # Internal method.
95
+ def cascade
96
+ add_child :title, PullDownTitle, { content: @title_text }
97
+ add_child :items, PullDownItems, { items: @items }
98
+ end
99
+ end
100
+
101
+ # Internal class for use with {PullDown}.
102
+ # This element has a state: pull-down-open
103
+ # to define CSS rules.
104
+ class PullDownTitle < Form::Block
105
+
106
+ # Internal method.
107
+ def clicked
108
+ parent.toggle_state :pull_down_open
109
+ end
110
+ end
111
+
112
+ # Internal class for use with {PullDown}.
113
+ class PullDownItems < BaseElement
114
+
115
+ # Internal method.
116
+ def _before_create
117
+ @id = Sequence.new 'pdi_'
118
+ @itemlist = option_replace :items, []
119
+ super
120
+ end
121
+
122
+ # Internal method.
123
+ def cascade
124
+ @items = @itemlist.map do |item|
125
+ add_child @id.next, item
126
+ end
127
+ end
128
+ end
129
+ end
130
+ end
@@ -0,0 +1,82 @@
1
+ module Ferro
2
+
3
+ # This module contains all semantic elements.
4
+ module Component
5
+ # A generic component element.
6
+ # In the DOM creates a: <div>.
7
+ # All semantical elements inherit from this class.
8
+ class Base < BaseElement
9
+
10
+ # Return self when called by children / descendants.
11
+ def component
12
+ self
13
+ end
14
+ end
15
+
16
+ # Creates a semantical element.
17
+ # This is a component.
18
+ # In the DOM creates a: <header>.
19
+ class Header < Base
20
+
21
+ # Internal method.
22
+ def _before_create
23
+ @domtype = :header
24
+ end
25
+ end
26
+
27
+ # Creates a semantical element.
28
+ # This is a component.
29
+ # In the DOM creates a: <nav>.
30
+ class Navigation < Base
31
+
32
+ # Internal method.
33
+ def _before_create
34
+ @domtype = :nav
35
+ end
36
+ end
37
+
38
+ # Creates a semantical element.
39
+ # This is a component.
40
+ # In the DOM creates a: <section>.
41
+ class Section < Base
42
+
43
+ # Internal method.
44
+ def _before_create
45
+ @domtype = :section
46
+ end
47
+ end
48
+
49
+ # Creates a semantical element.
50
+ # This is a component.
51
+ # In the DOM creates a: <article>.
52
+ class Article < Base
53
+
54
+ # Internal method.
55
+ def _before_create
56
+ @domtype = :article
57
+ end
58
+ end
59
+
60
+ # Creates a semantical element.
61
+ # This is a component.
62
+ # In the DOM creates a: <aside>.
63
+ class Aside < Base
64
+
65
+ # Internal method.
66
+ def _before_create
67
+ @domtype = :aside
68
+ end
69
+ end
70
+
71
+ # Creates a semantical element.
72
+ # This is a component.
73
+ # In the DOM creates a: <footer>.
74
+ class Footer < Base
75
+
76
+ # Internal method.
77
+ def _before_create
78
+ @domtype = :footer
79
+ end
80
+ end
81
+ end
82
+ end