fron 0.1.4 → 0.2.0rc1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +3 -0
- data/.reek +11 -0
- data/.rubocop.yml +54 -0
- data/.travis.yml +11 -0
- data/.yardopts +4 -0
- data/Changelog.md +7 -0
- data/Gemfile +3 -1
- data/Gemfile.lock +106 -15
- data/Rakefile +19 -15
- data/Readme.md +23 -0
- data/fron.gemspec +2 -2
- data/lib/fron/version.rb +2 -1
- data/opal/fron.rb +5 -5
- data/opal/fron/core.rb +3 -10
- data/opal/fron/core/behaviors/components.rb +42 -0
- data/opal/fron/core/behaviors/events.rb +27 -0
- data/opal/fron/core/behaviors/routes.rb +59 -0
- data/opal/fron/core/component.rb +64 -90
- data/opal/fron/core/eventable.rb +18 -0
- data/opal/fron/core/logger.rb +10 -1
- data/opal/fron/core_ext.rb +9 -0
- data/opal/fron/core_ext/array.rb +12 -0
- data/opal/fron/core_ext/date.rb +57 -0
- data/opal/fron/core_ext/hash.rb +52 -0
- data/opal/fron/core_ext/kernel.rb +57 -0
- data/opal/fron/core_ext/nil.rb +7 -0
- data/opal/fron/core_ext/numeric.rb +19 -0
- data/opal/fron/core_ext/object.rb +11 -0
- data/opal/fron/core_ext/proc.rb +19 -0
- data/opal/fron/{core-ext → core_ext}/string.rb +4 -0
- data/opal/fron/dom.rb +15 -13
- data/opal/fron/dom/document.rb +22 -6
- data/opal/fron/dom/element.rb +105 -67
- data/opal/fron/dom/event.rb +110 -40
- data/opal/fron/dom/{file-reader.rb → file_reader.rb} +6 -1
- data/opal/fron/dom/fragment.rb +2 -0
- data/opal/fron/dom/modules/attributes.rb +43 -0
- data/opal/fron/dom/modules/classlist.rb +26 -13
- data/opal/fron/dom/modules/dimensions.rb +79 -9
- data/opal/fron/dom/modules/element_accessor.rb +35 -0
- data/opal/fron/dom/modules/events.rb +67 -20
- data/opal/fron/dom/node.rb +98 -39
- data/opal/fron/dom/nodelist.rb +9 -2
- data/opal/fron/dom/style.rb +23 -2
- data/opal/fron/dom/text.rb +4 -0
- data/opal/fron/dom/window.rb +31 -2
- data/opal/fron/event_mock.rb +54 -0
- data/opal/fron/js/syntetic_event.js +16 -0
- data/opal/fron/request.rb +2 -2
- data/opal/fron/request/request.rb +77 -14
- data/opal/fron/request/response.rb +33 -6
- data/opal/fron/storage.rb +1 -1
- data/opal/fron/storage/local_storage.rb +54 -0
- data/opal/fron/utils/drag.rb +135 -0
- data/opal/fron/utils/keyboard.rb +70 -0
- data/opal/fron/utils/point.rb +78 -0
- data/opal/fron/utils/render_proc.rb +27 -0
- data/spec/core-ext/array_spec.rb +15 -0
- data/spec/core-ext/date_spec.rb +54 -0
- data/spec/core-ext/hash_spec.rb +18 -2
- data/spec/core-ext/kernel_spec.rb +57 -0
- data/spec/core-ext/nil_spec.rb +9 -0
- data/spec/core-ext/numeric_spec.rb +25 -0
- data/spec/core-ext/proc_spec.rb +15 -0
- data/spec/core-ext/string_spec.rb +11 -0
- data/spec/core/behaviors/events_spec.rb +25 -0
- data/spec/core/behaviors/routes_spec.rb +59 -0
- data/spec/core/component_inheritance_spec.rb +26 -16
- data/spec/core/component_spec.rb +25 -29
- data/spec/core/eventable_spec.rb +19 -19
- data/spec/core/logger_spec.rb +5 -6
- data/spec/dom/document_spec.rb +4 -5
- data/spec/dom/element_spec.rb +106 -15
- data/spec/dom/event_spec.rb +101 -61
- data/spec/dom/file_reader_spec.rb +11 -0
- data/spec/dom/fragment_spec.rb +3 -4
- data/spec/dom/instance_retaining_spec.rb +58 -0
- data/spec/dom/modules/classlist_spec.rb +18 -19
- data/spec/dom/modules/dimensions_spec.rb +87 -22
- data/spec/dom/modules/events_spec.rb +22 -8
- data/spec/dom/node_spec.rb +25 -17
- data/spec/dom/nodelist_spec.rb +2 -3
- data/spec/dom/style_spec.rb +6 -5
- data/spec/dom/text_spec.rb +4 -3
- data/spec/dom/window_spec.rb +24 -9
- data/spec/js/mocks.js +14 -0
- data/spec/request/request_spec.rb +34 -15
- data/spec/request/response_spec.rb +9 -10
- data/spec/spec_helper.rb +11 -0
- data/spec/storage/{local-storage_spec.rb → local_storage_spec.rb} +6 -7
- data/spec/utils/drag_spec.rb +136 -0
- data/spec/utils/keyboard_spec.rb +75 -0
- data/spec/utils/point_spec.rb +55 -0
- data/spec/utils/render_proc_spec.rb +18 -0
- metadata +58 -36
- data/docs/application.md +0 -7
- data/docs/configuration.md +0 -29
- data/docs/controllers.md +0 -35
- data/docs/routing.md +0 -63
- data/opal/fron/core-ext.rb +0 -5
- data/opal/fron/core-ext/hash.rb +0 -31
- data/opal/fron/core-ext/kernel.rb +0 -10
- data/opal/fron/core-ext/numeric.rb +0 -9
- data/opal/fron/core-ext/proc.rb +0 -9
- data/opal/fron/core/adapters/local.rb +0 -43
- data/opal/fron/core/adapters/rails.rb +0 -65
- data/opal/fron/core/application.rb +0 -42
- data/opal/fron/core/configuration.rb +0 -29
- data/opal/fron/core/controller.rb +0 -41
- data/opal/fron/core/model.rb +0 -90
- data/opal/fron/core/router.rb +0 -86
- data/opal/fron/storage/local-storage.rb +0 -34
- data/spec/core/adapter/local_spec.rb +0 -65
- data/spec/core/adapter/rails_spec.rb +0 -77
- data/spec/core/application_spec.rb +0 -35
- data/spec/core/configuration_spec.rb +0 -20
- data/spec/core/controlller_spec.rb +0 -68
- data/spec/core/model_spec.rb +0 -125
- data/spec/core/router_spec.rb +0 -124
data/opal/fron/core-ext/proc.rb
DELETED
@@ -1,43 +0,0 @@
|
|
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 Fron::Storage::LocalStorage.all
|
13
|
-
end
|
14
|
-
|
15
|
-
def get(id, &block)
|
16
|
-
block.call Fron::Storage::LocalStorage.get id
|
17
|
-
end
|
18
|
-
|
19
|
-
def set(model, data, &block)
|
20
|
-
id = model.id
|
21
|
-
id = SecureRandom.uuid unless id
|
22
|
-
data[:id] = id
|
23
|
-
unless (errors = validate data)
|
24
|
-
Fron::Storage::LocalStorage.set id, data
|
25
|
-
block.call nil, data
|
26
|
-
else
|
27
|
-
block.call errors, {}
|
28
|
-
end
|
29
|
-
data
|
30
|
-
end
|
31
|
-
|
32
|
-
def validate(data = {})
|
33
|
-
errors = {}
|
34
|
-
@options[:fields].reject{|field| field == :id}.map do |field|
|
35
|
-
next if data[field] && data[field] != ""
|
36
|
-
errors[field] = ["can't be blank"]
|
37
|
-
valid = false
|
38
|
-
end
|
39
|
-
errors.keys.length == 0 ? nil : errors
|
40
|
-
end
|
41
|
-
end
|
42
|
-
end
|
43
|
-
end
|
@@ -1,65 +0,0 @@
|
|
1
|
-
module Fron
|
2
|
-
module Adapters
|
3
|
-
class RailsAdapter
|
4
|
-
|
5
|
-
def initialize(options)
|
6
|
-
@options = options
|
7
|
-
@request = Request.new
|
8
|
-
@request.headers = {'Content-Type' => 'application/json'}
|
9
|
-
end
|
10
|
-
|
11
|
-
def del(model,&block)
|
12
|
-
setUrl model
|
13
|
-
@request.request 'DELETE', transform({}) do
|
14
|
-
block.call
|
15
|
-
end
|
16
|
-
end
|
17
|
-
|
18
|
-
def all(data = nil, &block)
|
19
|
-
setUrl nil
|
20
|
-
@request.get(data) { |response| block.call response.json }
|
21
|
-
end
|
22
|
-
|
23
|
-
def get(id,&block)
|
24
|
-
setUrl id
|
25
|
-
@request.get { |response| block.call response.json }
|
26
|
-
end
|
27
|
-
|
28
|
-
def set(model,data,&block)
|
29
|
-
setUrl model
|
30
|
-
method = model.id ? 'put' : 'post'
|
31
|
-
@request.send(method,transform(data)) do |response|
|
32
|
-
error = case response.status
|
33
|
-
when 201, 204
|
34
|
-
nil
|
35
|
-
when 422
|
36
|
-
response.json
|
37
|
-
end
|
38
|
-
block.call error, response.json
|
39
|
-
end
|
40
|
-
end
|
41
|
-
|
42
|
-
private
|
43
|
-
|
44
|
-
def setUrl(model)
|
45
|
-
id = model.is_a?(Fron::Model) ? model.id : model
|
46
|
-
endpoint = if @options[:endpoint].is_a? Proc
|
47
|
-
model.instance_eval &@options[:endpoint]
|
48
|
-
else
|
49
|
-
@options[:endpoint]
|
50
|
-
end
|
51
|
-
base = endpoint + "/" + @options[:resources]
|
52
|
-
base += id ? "/" + id.to_s : ".json"
|
53
|
-
@request.url = base
|
54
|
-
end
|
55
|
-
|
56
|
-
def transform(data)
|
57
|
-
newdata = {}
|
58
|
-
meta = DOM::Document.head.find("meta[name=csrf-token]")
|
59
|
-
newdata[:authenticity_token] = meta['content'] if meta
|
60
|
-
newdata[@options[:resource]] = data.dup
|
61
|
-
newdata
|
62
|
-
end
|
63
|
-
end
|
64
|
-
end
|
65
|
-
end
|
@@ -1,42 +0,0 @@
|
|
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
|
-
instance_eval &config.routeBlock if config.routeBlock
|
12
|
-
@router = Router.new @routeMap, config
|
13
|
-
|
14
|
-
DOM::Window.on('load') { loadExternalStylesheets }
|
15
|
-
|
16
|
-
config.logger.info "Initialized Applicationation!"
|
17
|
-
config.logger.info "Inserting application to DOM!"
|
18
|
-
|
19
|
-
DOM::Document.title = config.title
|
20
|
-
DOM::Document.body << config.app
|
21
|
-
end
|
22
|
-
|
23
|
-
private
|
24
|
-
|
25
|
-
def loadExternalStylesheets
|
26
|
-
return unless config.stylesheets
|
27
|
-
config.stylesheets.map do |sheet|
|
28
|
-
link = DOM::Element.new "link[rel=stylesheet][type=text/css][href=#{sheet}]"
|
29
|
-
link.on('load') { config.logger.info "External stylesheet loaded: #{sheet}" }
|
30
|
-
DOM::Document.head << link
|
31
|
-
end
|
32
|
-
end
|
33
|
-
|
34
|
-
def map(*args)
|
35
|
-
@routeMap << Router.map(*args)
|
36
|
-
end
|
37
|
-
|
38
|
-
def config
|
39
|
-
self.class.config
|
40
|
-
end
|
41
|
-
end
|
42
|
-
end
|
@@ -1,29 +0,0 @@
|
|
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, :injectBlock
|
9
|
-
attr_reader :routeBlock, :main, :app
|
10
|
-
|
11
|
-
def initialize
|
12
|
-
@app = App.new
|
13
|
-
@main = Yield.new
|
14
|
-
@logger = Fron::Logger.new
|
15
|
-
end
|
16
|
-
|
17
|
-
def routes(&block)
|
18
|
-
@routeBlock = block
|
19
|
-
end
|
20
|
-
|
21
|
-
def layout(&block)
|
22
|
-
@app.instance_exec @main, &block
|
23
|
-
end
|
24
|
-
|
25
|
-
def customInject(&block)
|
26
|
-
@injectBlock = block
|
27
|
-
end
|
28
|
-
end
|
29
|
-
end
|
@@ -1,41 +0,0 @@
|
|
1
|
-
module Fron
|
2
|
-
class Controller
|
3
|
-
class << self
|
4
|
-
attr_reader :baseComponent, :routes, :beforeFilters, :events
|
5
|
-
|
6
|
-
def base(component)
|
7
|
-
@baseComponent = component
|
8
|
-
end
|
9
|
-
|
10
|
-
def route(*args)
|
11
|
-
@routes ||= []
|
12
|
-
@routes << Router.map(*args)
|
13
|
-
end
|
14
|
-
|
15
|
-
def on(name,action)
|
16
|
-
@events ||= []
|
17
|
-
@events << {name: name, action: action}
|
18
|
-
end
|
19
|
-
|
20
|
-
def before(method,actions)
|
21
|
-
@beforeFilters ||= []
|
22
|
-
@beforeFilters << {method: method, actions: actions}
|
23
|
-
end
|
24
|
-
end
|
25
|
-
|
26
|
-
attr_reader :base
|
27
|
-
|
28
|
-
def initialize
|
29
|
-
if self.class.baseComponent
|
30
|
-
@base = self.class.baseComponent.new
|
31
|
-
else
|
32
|
-
@base = DOM::Element.new 'div'
|
33
|
-
end
|
34
|
-
|
35
|
-
return unless self.class.events
|
36
|
-
self.class.events.each do |event|
|
37
|
-
Eventable.on event[:name] do self.send(event[:action]) end
|
38
|
-
end
|
39
|
-
end
|
40
|
-
end
|
41
|
-
end
|
data/opal/fron/core/model.rb
DELETED
@@ -1,90 +0,0 @@
|
|
1
|
-
module Fron
|
2
|
-
class Model
|
3
|
-
include Eventable
|
4
|
-
attr_reader :errors
|
5
|
-
|
6
|
-
class << self
|
7
|
-
attr_accessor :fields
|
8
|
-
attr_accessor :adapterObject
|
9
|
-
|
10
|
-
def adapter(adapter, options = {})
|
11
|
-
options.merge! fields: @fields if @fields
|
12
|
-
@adapterObject = adapter.new options
|
13
|
-
end
|
14
|
-
|
15
|
-
def field(name)
|
16
|
-
@fields ||= []
|
17
|
-
@fields << name
|
18
|
-
define_method(name) do
|
19
|
-
@data[name]
|
20
|
-
end
|
21
|
-
define_method(name+"=") do |value|
|
22
|
-
@data[name] = value
|
23
|
-
trigger 'change'
|
24
|
-
end
|
25
|
-
end
|
26
|
-
|
27
|
-
def all(data = nil, &block)
|
28
|
-
@adapterObject.all data do |items|
|
29
|
-
break unless block_given?
|
30
|
-
block.call items.map{ |item| self.new item }
|
31
|
-
end
|
32
|
-
end
|
33
|
-
|
34
|
-
def find(id, &block)
|
35
|
-
user = self.new
|
36
|
-
@adapterObject.get id do |data|
|
37
|
-
user.merge data
|
38
|
-
block.call user
|
39
|
-
end
|
40
|
-
user
|
41
|
-
end
|
42
|
-
end
|
43
|
-
|
44
|
-
def initialize(data = {})
|
45
|
-
self.class.field :id
|
46
|
-
@data = data
|
47
|
-
end
|
48
|
-
|
49
|
-
def update(attributes = {}, &block)
|
50
|
-
data = gather.merge! attributes
|
51
|
-
self.class.instance_variable_get("@adapterObject").set self, data do |errors,data|
|
52
|
-
@errors = errors
|
53
|
-
merge data
|
54
|
-
block.call if block_given?
|
55
|
-
end
|
56
|
-
end
|
57
|
-
|
58
|
-
def dirty?
|
59
|
-
!self.id
|
60
|
-
end
|
61
|
-
|
62
|
-
private
|
63
|
-
|
64
|
-
def clone(data = {})
|
65
|
-
cl = self.class.new @data.merge data
|
66
|
-
cl.instance_variable_set "@errors", self.errors
|
67
|
-
cl
|
68
|
-
end
|
69
|
-
|
70
|
-
def destroy(&block)
|
71
|
-
self.class.instance_variable_get("@adapterObject").del self do
|
72
|
-
block.call if block_given?
|
73
|
-
end
|
74
|
-
end
|
75
|
-
|
76
|
-
def gather
|
77
|
-
@data.dup.reject{|key| !self.class.fields.include?(key)}
|
78
|
-
end
|
79
|
-
|
80
|
-
def merge(data)
|
81
|
-
data.each_pair do |key,value|
|
82
|
-
if self.respond_to?(key+"=")
|
83
|
-
self.send(key+"=", value)
|
84
|
-
else
|
85
|
-
@data[key] = value
|
86
|
-
end
|
87
|
-
end
|
88
|
-
end
|
89
|
-
end
|
90
|
-
end
|
data/opal/fron/core/router.rb
DELETED
@@ -1,86 +0,0 @@
|
|
1
|
-
module Fron
|
2
|
-
class Router
|
3
|
-
def initialize(routes,config)
|
4
|
-
@config = config
|
5
|
-
@routes = routes
|
6
|
-
|
7
|
-
DOM::Window.on 'load' do
|
8
|
-
route
|
9
|
-
end
|
10
|
-
DOM::Window.on 'hashchange' do
|
11
|
-
route
|
12
|
-
end
|
13
|
-
end
|
14
|
-
|
15
|
-
def self.map(*args)
|
16
|
-
data = case args.length
|
17
|
-
when 1
|
18
|
-
action = args[0]
|
19
|
-
{path: "*"}
|
20
|
-
when 2
|
21
|
-
action = args[1]
|
22
|
-
{path: Router.pathToRegexp(args[0]) }
|
23
|
-
end
|
24
|
-
if action.is_a? Class
|
25
|
-
data[:controller] = action.new
|
26
|
-
else
|
27
|
-
data[:action] = action.to_s
|
28
|
-
end
|
29
|
-
data
|
30
|
-
end
|
31
|
-
|
32
|
-
def self.pathToRegexp(path)
|
33
|
-
return path if path == "*"
|
34
|
-
{regexp: Regexp.new('^'+path.gsub(/:([^\/]+)/, '([^\/]+)')), map: path.scan(/:([^\/]+)/).flatten }
|
35
|
-
end
|
36
|
-
|
37
|
-
def route(hash = DOM::Window.hash, controller = nil, startParams = {})
|
38
|
-
routes = controller ? (controller.class.routes || []) : @routes
|
39
|
-
routes.each do |r|
|
40
|
-
if r[:path] == '*'
|
41
|
-
if r[:controller]
|
42
|
-
break route(hash,r[:controller],startParams)
|
43
|
-
else
|
44
|
-
break applyRoute(controller,r,startParams)
|
45
|
-
end
|
46
|
-
else
|
47
|
-
matches = hash.match(r[:path][:regexp]).to_a[1..-1]
|
48
|
-
if matches
|
49
|
-
params = {}
|
50
|
-
if r[:path][:map]
|
51
|
-
r[:path][:map].each_with_index do |key, index|
|
52
|
-
params[key.to_sym] = matches[index]
|
53
|
-
end
|
54
|
-
end
|
55
|
-
if r[:action]
|
56
|
-
break applyRoute(controller,r,startParams.merge(params))
|
57
|
-
else
|
58
|
-
break route hash.gsub(r[:path][:regexp],''), r[:controller], startParams.merge(params)
|
59
|
-
end
|
60
|
-
end
|
61
|
-
end
|
62
|
-
end
|
63
|
-
end
|
64
|
-
|
65
|
-
private
|
66
|
-
|
67
|
-
def applyRoute(controller,route, params = {})
|
68
|
-
if controller.class.beforeFilters
|
69
|
-
controller.class.beforeFilters.each do |filter|
|
70
|
-
if filter[:actions].include?(route[:action])
|
71
|
-
controller.send(filter[:method], params)
|
72
|
-
end
|
73
|
-
end
|
74
|
-
end
|
75
|
-
controller.send(:empty) if controller.respond_to?(:empty)
|
76
|
-
controller.send(route[:action], params)
|
77
|
-
@config.logger.info "Navigate >> #{controller.class}##{route[:action]} with params #{params}"
|
78
|
-
@config.main.empty
|
79
|
-
if @config.injectBlock
|
80
|
-
@config.injectBlock.call controller.base
|
81
|
-
else
|
82
|
-
@config.main << controller.base
|
83
|
-
end
|
84
|
-
end
|
85
|
-
end
|
86
|
-
end
|
@@ -1,34 +0,0 @@
|
|
1
|
-
module Fron
|
2
|
-
module Storage
|
3
|
-
module LocalStorage
|
4
|
-
def self.get(key)
|
5
|
-
value = `window.localStorage.getItem(#{key}) || false`
|
6
|
-
value ? JSON.parse(value) : nil
|
7
|
-
end
|
8
|
-
|
9
|
-
def self.set(key, data)
|
10
|
-
`window.localStorage.setItem(#{key},#{data.to_json})`
|
11
|
-
end
|
12
|
-
|
13
|
-
def self.remove(key)
|
14
|
-
`window.localStorage.removeItem(#{key})`
|
15
|
-
end
|
16
|
-
|
17
|
-
def self.keys
|
18
|
-
%x{
|
19
|
-
ret = []
|
20
|
-
for (var key in localStorage){ ret.push(key) }
|
21
|
-
return ret
|
22
|
-
}
|
23
|
-
end
|
24
|
-
|
25
|
-
def self.all
|
26
|
-
self.keys.map{ |key| self.get key }
|
27
|
-
end
|
28
|
-
|
29
|
-
def self.clear
|
30
|
-
`window.localStorage.clear()`
|
31
|
-
end
|
32
|
-
end
|
33
|
-
end
|
34
|
-
end
|