fron 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: ee70da4161fdf883ebd912c124c53c5a8bb8ada5
4
+ data.tar.gz: ab1e9096d251fc25a772e8b9fcf9798b1b8deda4
5
+ SHA512:
6
+ metadata.gz: cdddc4a004ae3e9160e82fa001db6f41199038d72e47426a4953ce40dbf2f681c0ba2dacd4f9fd31e66a8140c372590fadbe6004a0049b4f5ad1fd51b3592698
7
+ data.tar.gz: d265e541022bfb84a9299c6b9ca24386738ba932f5679cfe37fe5b3bd959734aa2bf20f39ec3930cb101619a61d36dc754c84fa77a40daf5bea375b932fa3d07
@@ -0,0 +1,7 @@
1
+ # Application
2
+
3
+ * [Configuration]()
4
+ * [Controllers]()
5
+ * [Routers]()
6
+ * [Components]()
7
+ * [DOM]()
@@ -0,0 +1,29 @@
1
+ # Configuration
2
+ Application configuration utility.
3
+
4
+ ## Title
5
+ The layout of the application can be set with the 'title' DSL.
6
+
7
+ ## Layout
8
+ The layout of the application can be set with the 'layout' DSL.
9
+
10
+ This DSL takes a block and runs it in the context of the main application component, with the injection poin for controllers as the argument.
11
+
12
+ ## Routes
13
+ For using routes see the [routing documentation]().
14
+
15
+ ## Example
16
+ ```ruby
17
+ class TestApplication < Application
18
+ config.title = 'Test Application'
19
+
20
+ config.layout do |main|
21
+ component :header, 'header'
22
+ self << main
23
+ end
24
+
25
+ config.routes do
26
+ map SiteController
27
+ end
28
+ end
29
+ ```
@@ -0,0 +1,35 @@
1
+ # Controllers
2
+ Controllers are responsible for parts of the application, it handles state / view changes for itself only.
3
+
4
+ ## Base Component
5
+ The base component can be specified with the `base` DSL method.
6
+
7
+ The base component is the "page" wthich is injected into the document when a route matches this controller. It is accessible with the `@base` attribute. It must be a subclass of `Component`.
8
+
9
+ ## Global Events
10
+ A controller can listen on Global Events with the `on` DSL.
11
+
12
+ The first argument is the event to listen to and the second argument is the method to run when the event triggered. Globa Events can be trigger like so:
13
+ ```ruby
14
+ Eventable.trigger 'load'
15
+ ```
16
+
17
+ ## Routes
18
+ For using routes see the [routing documentation]().
19
+
20
+ ## Example
21
+ ```ruby
22
+ class TestController < Controller
23
+ base BaseComponent
24
+
25
+ on :load, :loaded
26
+
27
+ def loaded
28
+
29
+ end
30
+
31
+ def test
32
+ puts @base
33
+ end
34
+ end
35
+ ```
@@ -0,0 +1,63 @@
1
+ # Routing
2
+ There are two leves of routing:
3
+
4
+ * Application level: This defines which controller is responsibe for specified paths
5
+ * Controller level: This defines which actions / sub controllers on the controller are called for specified paths
6
+
7
+ ## Applications Routes
8
+ Routes are defined in the Application Configuration with the `routes` DSL method.
9
+
10
+ You can define controllers for specific paths, for example the following `map 'users/', UserController` will delegate all paths under the `users/` to the `UserController`. The controller only recieves the portion of the path which remains after the matched path.
11
+
12
+ ## Controller Routes
13
+ Routes are defined with the `route` DSL method.
14
+
15
+ The first argument is the path, the second argument is the action / sub controller to be called. The path can contain parameter identifiers such as `:name`. These will be passed along to the action as a hash in the first parameter.
16
+
17
+ ## Before Filters
18
+ Before filters can be added to the controllers actions with the `beforeFilter` DSL method.
19
+
20
+ The first argument is the action to be called, the second argument is an array of methods which before the action should be called.
21
+
22
+ ## Example
23
+ ```ruby
24
+ class TestApplication < Application
25
+ config.routes do
26
+ # Both 'users/new' and 'users/10' will be
27
+ # handled by an instance of UserController
28
+ map 'users/', UserController
29
+
30
+ # Anything else will be handled by
31
+ # an instance of IndexController
32
+ map IndexController
33
+ end
34
+ end
35
+
36
+ class CommentsController < Controller
37
+ ...
38
+ end
39
+
40
+ class UserController < Controller
41
+ # users/new -> UserController#authorize -> UserController#new
42
+ route 'new', :new
43
+ # users/10/comments -> CommentsController with params[:id] = 10
44
+ route ':id/comments/', CommentsController
45
+ # users/10 -> UserController#authorize -> USerController#user with params[:id] = 10
46
+ route ':id', :user
47
+
48
+ beforeFilter :authorize, [:new,:user]
49
+
50
+ def new
51
+ ...
52
+ end
53
+
54
+ def user(params)
55
+ puts params[:id]
56
+ ...
57
+ end
58
+
59
+ def authorize
60
+ ...
61
+ end
62
+ end
63
+ ```
@@ -0,0 +1,20 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require File.expand_path('../lib/fron/version', __FILE__)
3
+
4
+ Gem::Specification.new do |s|
5
+ s.name = 'fron'
6
+ s.version = Fron::VERSION
7
+ s.author = 'Gusztav Szikszai'
8
+ s.email = 'gusztav.szikszai@digitalnatives.hu'
9
+ s.homepage = ''
10
+ s.summary = 'Frontend Application Framework'
11
+ s.description = 'Frontend Application Framework that uses Opal'
12
+
13
+ s.files = `git ls-files`.split("\n")
14
+ s.executables = `git ls-files -- bin/*`.split("\n").map { |f| File.basename(f) }
15
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
16
+ s.require_paths = ['lib']
17
+
18
+ s.add_runtime_dependency 'opal', ['~> 0.6.2']
19
+ s.add_development_dependency 'opal-rspec', '~> 0.3.0.beta3'
20
+ end
@@ -0,0 +1,4 @@
1
+ require 'opal'
2
+ require 'fron/version'
3
+
4
+ Opal.append_path File.expand_path('../../opal', __FILE__).untaint
@@ -0,0 +1,3 @@
1
+ module Fron
2
+ VERSION = '0.1.0'
3
+ end
@@ -0,0 +1,5 @@
1
+ require 'opal'
2
+ require './fron/dom'
3
+ require './fron/request'
4
+ require './fron/storage'
5
+ require './fron/core'
@@ -0,0 +1,17 @@
1
+ class Hash
2
+ def to_query_string
3
+ r = []
4
+ each do |key,value|
5
+ r << `encodeURIComponent(#{key})+"="+encodeURIComponent(#{value})`
6
+ end
7
+ r.join "&"
8
+ end
9
+
10
+ def to_form_data
11
+ r = `new FormData()`
12
+ each do |key,value|
13
+ `r.append(#{key},#{value})`
14
+ end
15
+ r
16
+ end
17
+ end
@@ -0,0 +1,10 @@
1
+ require './core/logger'
2
+ require './core/component'
3
+ require './core/adapters/rails'
4
+ require './core/adapters/local-storage'
5
+ require './core/configuration'
6
+ require './core/eventable'
7
+ require './core/model'
8
+ require './core/router'
9
+ require './core/controller'
10
+ require './core/application'
@@ -0,0 +1,41 @@
1
+ require 'json'
2
+ require 'securerandom'
3
+
4
+ module Fron
5
+ module Adapters
6
+ class LocalAdapter
7
+ def initialize(options)
8
+ @options = options
9
+ end
10
+
11
+ def all(&block)
12
+ block.call LocalStorage.all
13
+ end
14
+
15
+ def get(id, &block)
16
+ block.call LocalStorage.get id
17
+ end
18
+
19
+ def set(id, data, &block)
20
+ id = SecureRandom.uuid unless id
21
+ data[:id] = id
22
+ unless (errors = validate data)
23
+ LocalStorage.set id, data
24
+ block.call nil
25
+ else
26
+ block.call errors
27
+ end
28
+ end
29
+
30
+ def validate(data)
31
+ errors = {}
32
+ @options[:fields].map do |field|
33
+ next unless data[field] == ""
34
+ errors[field] = ["can't be blank"]
35
+ valid = false
36
+ end
37
+ errors.keys.length == 0 ? nil : errors
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,48 @@
1
+ module Fron
2
+ module Adapters
3
+ class RailsAdapter
4
+
5
+ def initialize(options)
6
+ @options = options
7
+ @request = Request.new
8
+ end
9
+
10
+ def all(&block)
11
+ setUrl nil
12
+ @request.get { |response| block.call response.json }
13
+ end
14
+
15
+ def get(id,&block)
16
+ setUrl id
17
+ @request.get { |response| block.call response.json }
18
+ end
19
+
20
+ def set(id,data,&block)
21
+ setUrl id
22
+ method = id ? 'put' : 'post'
23
+ @request.send(method,transform(data)) do |response|
24
+ block.call case response.status
25
+ when 201, 204
26
+ nil
27
+ when 422
28
+ response.json
29
+ end
30
+ end
31
+ end
32
+
33
+ private
34
+
35
+ def setUrl(id)
36
+ base = @options[:endpoint] + "/" + @options[:resources]
37
+ base += id ? "/" + id.to_s : ".json"
38
+ @request.url = base
39
+ end
40
+
41
+ def transform(data)
42
+ newdata = data.dup
43
+ newdata.keys.each{ |key| newdata["#{@options[:resource]}[#{key}]"] = newdata.delete key}
44
+ newdata
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,39 @@
1
+ module Fron
2
+ class Application
3
+ class << self
4
+ def config
5
+ @configuration ||= Configuration.new
6
+ end
7
+ end
8
+
9
+ def initialize
10
+ @routeMap = []
11
+ DOM::Document.title = config.title
12
+ instance_eval &config.routeBlock
13
+ @router = Router.new @routeMap, config
14
+
15
+ DOM::Window.on 'load' do
16
+ config.stylesheets.map do |sheet|
17
+ link = DOM::Element.new("link[rel=stylesheet][type=text/css][href=#{sheet}]")
18
+ link.on 'load' do
19
+ config.logger.info "External stylesheet loaded: #{sheet}"
20
+ end
21
+ DOM::Document.head << link
22
+ end
23
+ end
24
+ config.logger.info "Initialized Applicationation!"
25
+ config.logger.info "Inserting application to DOM!"
26
+ DOM::Document.body << config.app
27
+ end
28
+
29
+ private
30
+
31
+ def map(*args)
32
+ @routeMap << Router.map(*args)
33
+ end
34
+
35
+ def config
36
+ self.class.config
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,81 @@
1
+ module Fron
2
+ class Component < DOM::Element
3
+ attr_reader :model
4
+
5
+ class << self
6
+ attr_accessor :events
7
+ attr_accessor :tagname
8
+ attr_accessor :components
9
+
10
+ def tag(tag)
11
+ @tagname = tag
12
+ end
13
+
14
+ def on(*args)
15
+ @events ||= []
16
+ @events << args
17
+ end
18
+
19
+ def component(*args,&block)
20
+ attr_reader args[0]
21
+ @components ||= []
22
+ @components << ( args << block )
23
+ end
24
+
25
+ def delegate(method,target)
26
+ define_method(method) do
27
+ instance_variable_get("@#{target}").send(method)
28
+ end
29
+
30
+ define_method(method+"=") do |value|
31
+ instance_variable_get("@#{target}").send(method+"=",value)
32
+ end
33
+ end
34
+ end
35
+
36
+ def initialize(*args)
37
+ case args.length
38
+ when 1
39
+ @model = args[0]
40
+ when 2
41
+ tag, @model = args
42
+ end
43
+
44
+ super tag || self.class.tagname || self.class.name.split("::").last
45
+
46
+ applyEvents
47
+ createComponents
48
+
49
+ return if !respond_to?(:render) || !@model
50
+ @model.on 'change' do render end
51
+ render
52
+ end
53
+
54
+ def component(name,comp,&block)
55
+ c = comp.is_a?(Class) ? comp.new(@model) : Component.new(comp, @model)
56
+ c.instance_eval(&block) if block
57
+ self << c
58
+ self.instance_variable_set "@#{name}", c
59
+ end
60
+
61
+ private
62
+
63
+ def createComponents
64
+ return unless self.class.components
65
+ self.class.components.each do |args|
66
+ component args[0], args[1], &args[2]
67
+ end
68
+ end
69
+
70
+ def applyEvents
71
+ return unless self.class.events
72
+ self.class.events.each do |args|
73
+ if args.length == 3
74
+ delegate(args[0], args[1]) { |e| self.method(args[2]).call e }
75
+ else
76
+ on(args[0]) { |e| self.method(args[1]).call e }
77
+ end
78
+ end
79
+ end
80
+ end
81
+ end
@@ -0,0 +1,26 @@
1
+ module Fron
2
+ class Configuration
3
+ class App < Component
4
+ end
5
+ class Yield < Component
6
+ end
7
+
8
+ attr_accessor :title, :stylesheets, :logger
9
+ attr_reader :routeBlock, :main, :app
10
+
11
+ def initialize
12
+ @main = Yield.new
13
+ @app = App.new
14
+
15
+ DOM::Document.body.empty
16
+ end
17
+
18
+ def routes(&block)
19
+ @routeBlock = block
20
+ end
21
+
22
+ def layout(&block)
23
+ @app.instance_exec @main, &block
24
+ end
25
+ end
26
+ end