fron 0.1.4 → 0.2.0rc1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (120) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +3 -0
  3. data/.reek +11 -0
  4. data/.rubocop.yml +54 -0
  5. data/.travis.yml +11 -0
  6. data/.yardopts +4 -0
  7. data/Changelog.md +7 -0
  8. data/Gemfile +3 -1
  9. data/Gemfile.lock +106 -15
  10. data/Rakefile +19 -15
  11. data/Readme.md +23 -0
  12. data/fron.gemspec +2 -2
  13. data/lib/fron/version.rb +2 -1
  14. data/opal/fron.rb +5 -5
  15. data/opal/fron/core.rb +3 -10
  16. data/opal/fron/core/behaviors/components.rb +42 -0
  17. data/opal/fron/core/behaviors/events.rb +27 -0
  18. data/opal/fron/core/behaviors/routes.rb +59 -0
  19. data/opal/fron/core/component.rb +64 -90
  20. data/opal/fron/core/eventable.rb +18 -0
  21. data/opal/fron/core/logger.rb +10 -1
  22. data/opal/fron/core_ext.rb +9 -0
  23. data/opal/fron/core_ext/array.rb +12 -0
  24. data/opal/fron/core_ext/date.rb +57 -0
  25. data/opal/fron/core_ext/hash.rb +52 -0
  26. data/opal/fron/core_ext/kernel.rb +57 -0
  27. data/opal/fron/core_ext/nil.rb +7 -0
  28. data/opal/fron/core_ext/numeric.rb +19 -0
  29. data/opal/fron/core_ext/object.rb +11 -0
  30. data/opal/fron/core_ext/proc.rb +19 -0
  31. data/opal/fron/{core-ext → core_ext}/string.rb +4 -0
  32. data/opal/fron/dom.rb +15 -13
  33. data/opal/fron/dom/document.rb +22 -6
  34. data/opal/fron/dom/element.rb +105 -67
  35. data/opal/fron/dom/event.rb +110 -40
  36. data/opal/fron/dom/{file-reader.rb → file_reader.rb} +6 -1
  37. data/opal/fron/dom/fragment.rb +2 -0
  38. data/opal/fron/dom/modules/attributes.rb +43 -0
  39. data/opal/fron/dom/modules/classlist.rb +26 -13
  40. data/opal/fron/dom/modules/dimensions.rb +79 -9
  41. data/opal/fron/dom/modules/element_accessor.rb +35 -0
  42. data/opal/fron/dom/modules/events.rb +67 -20
  43. data/opal/fron/dom/node.rb +98 -39
  44. data/opal/fron/dom/nodelist.rb +9 -2
  45. data/opal/fron/dom/style.rb +23 -2
  46. data/opal/fron/dom/text.rb +4 -0
  47. data/opal/fron/dom/window.rb +31 -2
  48. data/opal/fron/event_mock.rb +54 -0
  49. data/opal/fron/js/syntetic_event.js +16 -0
  50. data/opal/fron/request.rb +2 -2
  51. data/opal/fron/request/request.rb +77 -14
  52. data/opal/fron/request/response.rb +33 -6
  53. data/opal/fron/storage.rb +1 -1
  54. data/opal/fron/storage/local_storage.rb +54 -0
  55. data/opal/fron/utils/drag.rb +135 -0
  56. data/opal/fron/utils/keyboard.rb +70 -0
  57. data/opal/fron/utils/point.rb +78 -0
  58. data/opal/fron/utils/render_proc.rb +27 -0
  59. data/spec/core-ext/array_spec.rb +15 -0
  60. data/spec/core-ext/date_spec.rb +54 -0
  61. data/spec/core-ext/hash_spec.rb +18 -2
  62. data/spec/core-ext/kernel_spec.rb +57 -0
  63. data/spec/core-ext/nil_spec.rb +9 -0
  64. data/spec/core-ext/numeric_spec.rb +25 -0
  65. data/spec/core-ext/proc_spec.rb +15 -0
  66. data/spec/core-ext/string_spec.rb +11 -0
  67. data/spec/core/behaviors/events_spec.rb +25 -0
  68. data/spec/core/behaviors/routes_spec.rb +59 -0
  69. data/spec/core/component_inheritance_spec.rb +26 -16
  70. data/spec/core/component_spec.rb +25 -29
  71. data/spec/core/eventable_spec.rb +19 -19
  72. data/spec/core/logger_spec.rb +5 -6
  73. data/spec/dom/document_spec.rb +4 -5
  74. data/spec/dom/element_spec.rb +106 -15
  75. data/spec/dom/event_spec.rb +101 -61
  76. data/spec/dom/file_reader_spec.rb +11 -0
  77. data/spec/dom/fragment_spec.rb +3 -4
  78. data/spec/dom/instance_retaining_spec.rb +58 -0
  79. data/spec/dom/modules/classlist_spec.rb +18 -19
  80. data/spec/dom/modules/dimensions_spec.rb +87 -22
  81. data/spec/dom/modules/events_spec.rb +22 -8
  82. data/spec/dom/node_spec.rb +25 -17
  83. data/spec/dom/nodelist_spec.rb +2 -3
  84. data/spec/dom/style_spec.rb +6 -5
  85. data/spec/dom/text_spec.rb +4 -3
  86. data/spec/dom/window_spec.rb +24 -9
  87. data/spec/js/mocks.js +14 -0
  88. data/spec/request/request_spec.rb +34 -15
  89. data/spec/request/response_spec.rb +9 -10
  90. data/spec/spec_helper.rb +11 -0
  91. data/spec/storage/{local-storage_spec.rb → local_storage_spec.rb} +6 -7
  92. data/spec/utils/drag_spec.rb +136 -0
  93. data/spec/utils/keyboard_spec.rb +75 -0
  94. data/spec/utils/point_spec.rb +55 -0
  95. data/spec/utils/render_proc_spec.rb +18 -0
  96. metadata +58 -36
  97. data/docs/application.md +0 -7
  98. data/docs/configuration.md +0 -29
  99. data/docs/controllers.md +0 -35
  100. data/docs/routing.md +0 -63
  101. data/opal/fron/core-ext.rb +0 -5
  102. data/opal/fron/core-ext/hash.rb +0 -31
  103. data/opal/fron/core-ext/kernel.rb +0 -10
  104. data/opal/fron/core-ext/numeric.rb +0 -9
  105. data/opal/fron/core-ext/proc.rb +0 -9
  106. data/opal/fron/core/adapters/local.rb +0 -43
  107. data/opal/fron/core/adapters/rails.rb +0 -65
  108. data/opal/fron/core/application.rb +0 -42
  109. data/opal/fron/core/configuration.rb +0 -29
  110. data/opal/fron/core/controller.rb +0 -41
  111. data/opal/fron/core/model.rb +0 -90
  112. data/opal/fron/core/router.rb +0 -86
  113. data/opal/fron/storage/local-storage.rb +0 -34
  114. data/spec/core/adapter/local_spec.rb +0 -65
  115. data/spec/core/adapter/rails_spec.rb +0 -77
  116. data/spec/core/application_spec.rb +0 -35
  117. data/spec/core/configuration_spec.rb +0 -20
  118. data/spec/core/controlller_spec.rb +0 -68
  119. data/spec/core/model_spec.rb +0 -125
  120. data/spec/core/router_spec.rb +0 -124
@@ -1,10 +0,0 @@
1
- module Kernel
2
- def requestAnimationFrame(&block)
3
- return unless `!!window.requestAnimationFrame`
4
- `window.requestAnimationFrame(function(){ #{block.call} })`
5
- end
6
-
7
- def timeout(ms = 0,&block)
8
- `setTimeout(function(){#{block.call}},#{ms})`
9
- end
10
- end
@@ -1,9 +0,0 @@
1
- class Numeric
2
- def clamp min, max
3
- [[self, max].min, min].max
4
- end
5
-
6
- def round(decimals = 0)
7
- `#{self}.toFixed(#{decimals})`.to_f
8
- end
9
- end
@@ -1,9 +0,0 @@
1
- class Proc
2
- def throttle(ms)
3
- Native `throttle(#{self},#{ms}, {leading: false})`
4
- end
5
-
6
- def debounce(ms, leading = false)
7
- Native `debounce(#{self},#{ms},#{leading})`
8
- end
9
- end
@@ -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
@@ -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
@@ -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