fron 0.1.4 → 0.2.0rc1
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 +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
|