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.
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