# Browser

## Getting Started

To build/run a browser project, you only require two files: the html file used to load the ruby, and a ruby source file with your application code. By default the build tools will look in a `lib/` directory for your sources, so for simplicity sakes we will use that directory for our code. Also, by default the base-name for the directory is used for loading the main ruby file.

### Project Directory Structure

Create the following files/directories for our "browser_test" project:

    !!!plain
    browser_test/
      index.html
      lib/
        browser_test.rb

With the new fresh project, the build tools need to be run in the project root, so jump into the browser_test directory.

    !!!plain
    cd path/to/browser_test

### HTML file

Out html file simply needs to require the resulting javascript file from our build tools, which (by default) has the same name as our project, so edit index.html to contain the following simple HTML5 document.
    
    !!!plain
    <!DOCTYPE html>
    <html>
      <head>
        <script src="javascripts/browser_test.js"></script>
      </head>
    </html>

### Hello, World!

For a very simple program, "Hello world" seems appropriate. Change the contents of the browser_test.rb file to the following:

    puts "Hello, World!"
    
This, of course, is very simple ruby. We now need to use the build tools to build the project. This is simply done by running the following command in our root directory:

    !!!plain
    vn-build

The build tool will then generate our `javascripts/browser_test.js` file, which is loaded by our HTML document in the browser. Our generated javascript file also contains the runtime needed (which includes the ruby implementation, the core library, and the browser opal).

In any browser with a console (Firefox, Chrome, Safari, IE8 etc), open the HTML document and you will see the message in the console output:

    "Hello, World!"
    
## Browser API

### Document

The `Document` module represents the common `document` object in javascript. Its functionality is extended beyond the javascript offering to add common features found in javascript frameworks.

#### Document.ready?

Ruby code in opal begins running as soon as the source file downloads. This may mean that the document is not yet ready to be manipulated. This method takes a block (or many blocks) that will be executed when the document is ready. Placing code in here ensures that it will not be run before the document can be manipulated, which is sure to yield errors. Place the following code in the browser_test.rb file.

    puts "this should run first"
    
    Document.ready? do
      puts "this should run third"
    end
    
    puts "this should run second"

Rebuild the project (`vn-build`) and refresh the html page in your browser. You should observe the console results in the following order:

    "this should run first"
    "this should run second"
    "this should run third"
    
The puts statement in the block runs third because it is only then that the document is ready. Placing DOM manipulation code, or event handlers inside this `ready?` statement is recommended.

`Document#ready?` can also be called without a block, which simply returns a boolean whether the document is now ready or not.

    Document.ready?   # => false
    
    Document.ready? do
      Document.ready? # => true
    end
    
    Document.ready?   # => false
    
#### Document.[]

This method is used for searching for selectors in the DOM. Every {Element} instance has a `[]` method, which uses itself as the context. For the document, the document itself is the context. This method takes either a string or symbol. In the case of a symbol, the document is searched for an element whose id matches the symbol name, or `nil` if an element with that id cannot be found.
    
    !!!plain
    <div id="foo"></div>
    <div id="bar"></div>
    
The above example would produce the following results:

    Document[:foo]
    # => #<Element div, id="foo">
    
    Document [:baz]
    # => nil

The returned element is an instance of the {Element} class.

The second case, for a string, either returns a single element if the selector is for an id, or returns an array for any other selector type. Looking for an id will take the form `#element_id`. The hash indicates an id. As above, if the elements cannot be found, then `nil` is returned.

HTML:

    !!!plain
    <div id="foo" class="a"></div>
    <div class="b"></div>
    <div class="a"></div>

Ruby:
    
    Document['#foo']
    # => #<Element div, id="foo", class="a">
    Document['#bar']
    # => nil
    Document['.a']
    # => [#<Element div, id="foo", class="a">, #<Element div, class="a">]
    Document['.b']
    # => [#<Element div, class="b">]
    Document['.c']
    # => nil

## Implementation

This section discusses the low level implementation details for dealing with the opal runtime. Every class in the browser opal uses pure opal class instances and object instances. No native objects (elements, xmlhttprequests) are accessible from the ruby. Due to cross browser differences, relying on adding opal methods to these natives causes issues, so all references to object's native counterparts are stored purely as an instance variable on the ruby object, so that no addition properties can affect different browser implementations.

### Document

The {Document} module has a private instance variable called `__element__` which points to the javascript `document` object.

### Window

The {Window} module also has a private instance variable called `__element__` which point to the native `window` object.

### Element

Every {Element} instance has a private instance variable called `__element__` which points to the native javascript element that this ruby object represents. To create an {Element} instance with a native element, the class method {Element.from_native} is used, and the native element is passed as a parameter. The result is an instance, with the element set as the private `__element__` variable.

### Event

Every {Event} instance wraps a native event with a private variable `__event__`. To create an Opal event from a native event, the {Event.from_native} method should be used, which returns a new instance of the {Event} class.