Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
5924835
commit 98697c8
Showing
16 changed files
with
728 additions
and
30 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
opal/**/*.rb | ||
lib/**/*.rb | ||
- | ||
README.md | ||
docs/GettingStarted.md | ||
CHANGELOG.md | ||
LICENSE.txt | ||
CODE_OF_CONDUCT.md |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
# 0.10.1 - March 31, 2018 | ||
|
||
- Added documentation (using Yard) | ||
|
||
# 0.10.0 - February 2, 2018 | ||
|
||
Initial version |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,187 @@ | ||
# @title Getting started with Opal-Ferro | ||
|
||
# Getting started with Opal-Ferro | ||
|
||
Ferro is a small Ruby library on top of [Opal](http://opalrb.com/) | ||
that enables an object-oriented programming style for creating code | ||
that runs in the webbrowser. | ||
No more distractions like HTML and searching for DOM elements, | ||
just beautiful and simple Ruby code. Front-End-Ruby-ROcks! | ||
|
||
|
||
* [How does Ferro work](#ferro) | ||
* [Creating the Master Object Model](#mom) | ||
* [Adding elements](#demo) | ||
* [Creation lifecycle](#lifecycle) | ||
* [Navigating the Master Object Model](#navigating) | ||
* [Styling Ferro elements](#styling) | ||
* [More information](#more) | ||
|
||
<a name="ferro"></a> | ||
|
||
## How does Ferro work? | ||
Ferro uses an object oriented programming style. You instantiate an object, that object | ||
in turn instantiates more child objects and add these as instance variables to itself. | ||
And so on, producing a hierarchy of object instances. | ||
This is called the Master Object Model (MOM). | ||
|
||
When an object is instanciated in the MOM, Ferro will add an element to the webbrowsers | ||
Document Object Model (DOM). The MOM keeps a reference to every DOM element. | ||
This erradicates the need for element lookups (jquery $ searches). | ||
If you need an element you know where to find it in the MOM. | ||
Getter methods are automatically added by Ferro for easy access to instance variables. | ||
|
||
Each object in the MOM inherits from a Ferro class. | ||
Which Ferro class you use determines what type of DOM element will be created. | ||
All Ferro classes inherit from one base class: FerroElement. | ||
For most DOM elements in the html specs there is a corresponding Ferro class. | ||
For instance if you need a html5 `<header>` element you would create a class that inherits | ||
from FerroElementHeader. | ||
Other html elements have a more abstract counterpart: | ||
all text elements (`<p>`, `<h1>` .. `<h6>`) have one Ferro class `FerroElementText`. | ||
The size of the text element is an option when you instantiate the object. | ||
|
||
<a name="mom"></a> | ||
|
||
## Creating the Master Object Model | ||
|
||
First we need a class that inherits from FerroDocument. | ||
This is the staring point for any Ferro application. | ||
The Document instance will attach itself in the DOM to | ||
`document.body`. | ||
|
||
In the example below, the Document instance will create one child element. | ||
|
||
class Document < FerroDocument | ||
|
||
# The cascade method is called after the Document | ||
# has been created and is ready to create child | ||
# objects. | ||
def cascade | ||
add_child :demo, Demo | ||
end | ||
end | ||
|
||
To start the application one instance of the Document must be created. | ||
In the `application.js` file (if you are using Rails for instance) | ||
`Document.new` is called when the browser has loaded the necessary | ||
files. | ||
|
||
`document.addEventListener("DOMContentLoaded", function() {#{Document.new};})` | ||
|
||
The backticks are Opal's way of entering _raw_ Javascript. Using | ||
familiar Ruby string interpolation `#{}` a reference to `Document.new` can | ||
be inserted. | ||
This is the first and last line of Javascript that is needed. | ||
Everyting else is Ruby code. | ||
|
||
<a name="demo"></a> | ||
|
||
## Adding elements | ||
|
||
Let's look at a very simple example. We will define a small component | ||
with a title and a button. The button should change the title text when clicked. | ||
|
||
class Demo < FerroElementComponent | ||
def cascade | ||
# Add a title | ||
add_child :title, FerroElementText, size: 4, content: 'Title' | ||
|
||
# Add a button | ||
add_child :btn, DemoButton, content: 'Click me' | ||
end | ||
|
||
def rotate_title | ||
# We have access to the 'title' instance variable | ||
txt = title.get_text | ||
title.set_text (txt[1..-1] + txt[0]).capitalize | ||
end | ||
end | ||
|
||
class DemoButton < FerroFormButton | ||
def clicked | ||
# Every element knows its parent | ||
parent.rotate_title | ||
end | ||
end | ||
|
||
The code in Demo _cascade_ method is equivalent to something like this, | ||
which should look more familiar to a Ruby programmer: | ||
|
||
class Demo | ||
def initialize | ||
@title = FerroElementText.new(size: 4, content: 'Title') | ||
@btn = DemoButton.new(content: 'Click me') | ||
end | ||
end | ||
|
||
Just like above, the `add_child` method will create instance variables | ||
`@title` and `@btn`. In Ferro we don't need to use the @. | ||
|
||
<a name="lifecycle"></a> | ||
|
||
## Creation lifecycle | ||
|
||
Every Ferro class has 3 hooks into the object creation lifecycle: | ||
|
||
- before_create | ||
- after_create | ||
- cascade | ||
|
||
The first two are called just before and after the object itself | ||
is created. The cascade hook is called when the object is ready | ||
to create child objects. | ||
In this example most of the action happens in the _cascade_ method. | ||
|
||
By inheriting from _FerroFormButton_, _DemoButton_ has access | ||
to the click event handler. After a click occurred, it signals | ||
its parent (_Demo_) to rotate the title text. | ||
|
||
<a name="navigating"></a> | ||
|
||
## Navigating the Master Object Model | ||
|
||
There are two ways to navigate around the MOM: upward and downward. | ||
Every object in the MOM knows its parent. If an event is received by an | ||
object like a button, the parent of that object usually can handle the | ||
event. The parent element can be accessed using the `parent` method. | ||
|
||
Searching upward further than one parent quickly becomes difficult to | ||
follow. So you can always search downward starting from the top. | ||
Every object in the MOM can access the root object using the `root` | ||
method. From the root you can access all MOM objects. | ||
|
||
There is a shortcut to find an object starting from the nearest element | ||
in the hierarchy that is a component. All semantical elements | ||
(like header and section) are components. All objects that are children | ||
of a component have immediate access to that component using the | ||
`component` method. | ||
|
||
<a name="styling"></a> | ||
|
||
## Styling Ferro elements | ||
|
||
The created elements still need some styling. Ferro uses a handy | ||
naming convention: CSS classnames match Ruby classnames. | ||
For example: | ||
|
||
class DemoButton < FerroFormButton | ||
end | ||
|
||
When we create this button in the MOM, its DOM counterpart receives | ||
two classnames. One matching the Ruby classname `DemoButton` and | ||
one for its Ruby superclass `FerroFormButton`. | ||
These classnames are _dasherized_. In CSS you can reference these | ||
classnames as `demo-button` and `ferro-form-button`. | ||
|
||
<a name="more"></a> | ||
|
||
## More information | ||
|
||
Please see the [Ferro website](https://easydatawarehousing.github.io/ferro/) | ||
for more information and examples. | ||
The [source code](https://github.com/easydatawarehousing/ferro) | ||
for that webapp is a good Ferro example in itself. | ||
|
||
For some simple boilerplate code to get started with Ferro you can use | ||
[this Rails example](https://github.com/easydatawarehousing/ferro-example-todolist). |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,10 @@ | ||
module Opal | ||
module Ferro | ||
# Opal-Ferro follows the versioning scheme of Opal. | ||
# The first two parts of the version number of Ferro imply | ||
# compatibility with the Opal version with that same number. | ||
# So Ferro 0.10.x should be compatible with and dependant | ||
# on Opal 0.10.x. | ||
VERSION = "0.10.0" | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.