nice 0.0.7 → 0.1.0
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 +7 -0
- data/.rspec +3 -0
- data/CHANGELOG.md +8 -0
- data/Gemfile +6 -0
- data/Gemfile.lock +162 -0
- data/LICENSE +21 -0
- data/README.md +93 -99
- data/Rakefile +4 -45
- data/lib/nice/client.rb +51 -0
- data/lib/nice/version.rb +1 -1
- data/lib/nice.rb +30 -2
- data/nice.gemspec +43 -0
- metadata +144 -67
- data/MIT-LICENSE +0 -20
- data/lib/assets/javascripts/event_dispatcher.coffee +0 -34
- data/lib/assets/javascripts/nice_imp_jquery.js.coffee +0 -136
- data/lib/assets/javascripts/nice_jquery.js +0 -15
- data/lib/nice/config.rb +0 -3
- data/lib/nice/engine.rb +0 -4
- data/lib/nice/html_parser.rb +0 -184
- data/lib/nice/js/caller.rb +0 -48
- data/lib/nice/logic.rb +0 -99
- data/lib/nice/middleware.rb +0 -100
- data/lib/tasks/nice_tasks.rake +0 -4
- data/test/integration/nice_test.rb +0 -25
- data/test/test_helper.rb +0 -30
data/lib/nice/js/caller.rb
DELETED
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
module Nice
|
|
2
|
-
module Js
|
|
3
|
-
class Caller
|
|
4
|
-
|
|
5
|
-
# DOM Manipulation
|
|
6
|
-
def self.generate_js_insert_after new_node, reference_node_ref
|
|
7
|
-
"NiceEventDispatcher.dispatch_event(\'nice.dom.InsertAfterEvent\',{new_node:\'#{new_node}\', ref_node:\"#{reference_node_ref}\"});"
|
|
8
|
-
end
|
|
9
|
-
|
|
10
|
-
def self.generate_js_insert_inside new_node, reference_node_ref
|
|
11
|
-
"NiceEventDispatcher.dispatch_event(\'nice.dom.InsertInsideEvent\',{new_node:\'#{new_node}\', ref_node:\"#{reference_node_ref}\"});"
|
|
12
|
-
end
|
|
13
|
-
|
|
14
|
-
def self.replace_node new_node, reference_node_ref
|
|
15
|
-
"NiceEventDispatcher.dispatch_event(\'nice.dom.ReplaceEvent\',{new_node:\'#{new_node}\', ref_node:\"#{reference_node_ref}\"});"
|
|
16
|
-
end
|
|
17
|
-
|
|
18
|
-
def self.generate_js_remove curr_state
|
|
19
|
-
"NiceEventDispatcher.dispatch_event(\'nice.dom.RemoveStateEvent\',{curr_state:\'#{curr_state}\'});"
|
|
20
|
-
end
|
|
21
|
-
|
|
22
|
-
def self.clean_root_tree
|
|
23
|
-
"NiceEventDispatcher.dispatch_event(\'nice.dom.CleanRootEvent\',{});"
|
|
24
|
-
end
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
# History Manipulation
|
|
28
|
-
def self.move_to_url url, title
|
|
29
|
-
"NiceEventDispatcher.dispatch_event(\'nice.hist.ChangeURLEvent\',{url:\'#{url}\', title:\'#{title}\'});"
|
|
30
|
-
end
|
|
31
|
-
|
|
32
|
-
def self.insert_or_update_back_listener url
|
|
33
|
-
"NiceEventDispatcher.dispatch_event(\'nice.hist.PopHistoryEvent\',{url:\'#{url}\'});"
|
|
34
|
-
end
|
|
35
|
-
|
|
36
|
-
# events for UI
|
|
37
|
-
def self.state_did_change prev_state, new_state
|
|
38
|
-
"NiceEventDispatcher.dispatch_event(\'nice.ui.StateDidChangeEvent\',{prev_state:\'#{prev_state}\', new_state:\"#{new_state}\"});"
|
|
39
|
-
end
|
|
40
|
-
|
|
41
|
-
# Change Body Css Class to reflect current state
|
|
42
|
-
def self.change_top_css new_state_name
|
|
43
|
-
"NiceEventDispatcher.dispatch_event(\'nice.dom.ChangeTopCssEvent\',{new_state_name:\'#{new_state_name}\'});"
|
|
44
|
-
end
|
|
45
|
-
|
|
46
|
-
end
|
|
47
|
-
end
|
|
48
|
-
end
|
data/lib/nice/logic.rb
DELETED
|
@@ -1,99 +0,0 @@
|
|
|
1
|
-
require 'nice/html_parser'
|
|
2
|
-
require 'nice/js/caller'
|
|
3
|
-
require 'uri'
|
|
4
|
-
|
|
5
|
-
module Nice
|
|
6
|
-
|
|
7
|
-
# The nice state engine is tighthly integrated with restful routes. Each route can be a state
|
|
8
|
-
# and states are only identified by their corresponding route. In effect, no state names
|
|
9
|
-
# must be created and no parameters indicating the state transitions are needed as this
|
|
10
|
-
# information is already contained in the http header.
|
|
11
|
-
|
|
12
|
-
## case 1: this is the first call of the component -> no previous state
|
|
13
|
-
|
|
14
|
-
# => remove elements not belonging to the start state, generate UID for reference
|
|
15
|
-
# nodes ({ref_element}_ref) and respond with HTML
|
|
16
|
-
|
|
17
|
-
## case 2: this is an ordinary call of another state
|
|
18
|
-
|
|
19
|
-
# => respond with JS with assignments to remove elements not included
|
|
20
|
-
# in current state and assignments to insert elements of current state.
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
## case 3: curr_state == prev_state
|
|
24
|
-
|
|
25
|
-
# => respond with JS which either first removes all elements of the current state and
|
|
26
|
-
# later inserts new content OR directly replaces elements
|
|
27
|
-
|
|
28
|
-
## case 4: the controller changed
|
|
29
|
-
# => replace all contents under the "container yield" mentioned in the application layout file
|
|
30
|
-
|
|
31
|
-
class Logic
|
|
32
|
-
|
|
33
|
-
def self.run current_method, current_path, referer, doc, is_js
|
|
34
|
-
|
|
35
|
-
ref_c = Rails.application.routes.recognize_path(referer)[:controller]
|
|
36
|
-
ref_a = Rails.application.routes.recognize_path(referer)[:action]
|
|
37
|
-
curr_c = Rails.application.routes.recognize_path(current_path)[:controller]
|
|
38
|
-
curr_a = Rails.application.routes.recognize_path(current_path)[:action]
|
|
39
|
-
|
|
40
|
-
current_state = "#{current_method.downcase}_#{curr_c}_#{curr_a}"
|
|
41
|
-
|
|
42
|
-
prev_state = referer.gsub("/","_") unless referer.nil?
|
|
43
|
-
|
|
44
|
-
referenced_doc = Nice::HtmlParser.annotate_referencing_nodes doc
|
|
45
|
-
|
|
46
|
-
cleaned_doc = Nice::HtmlParser.remove_elements_not_of_state current_state, referenced_doc
|
|
47
|
-
|
|
48
|
-
controller_same = (ref_c == curr_c)
|
|
49
|
-
|
|
50
|
-
# case 1
|
|
51
|
-
if !is_js then
|
|
52
|
-
|
|
53
|
-
response = Nice::HtmlParser.add_top_css(cleaned_doc, current_state).to_html
|
|
54
|
-
|
|
55
|
-
# case 2
|
|
56
|
-
elsif controller_same && is_js then
|
|
57
|
-
js_stack = ["// remove elements not present in the following state"]
|
|
58
|
-
js_stack << Nice::Js::Caller.generate_js_remove(current_state)
|
|
59
|
-
|
|
60
|
-
js_stack << "// add new elements"
|
|
61
|
-
js_stack += Nice::HtmlParser.add_elements_of_current_state(cleaned_doc,current_state).compact
|
|
62
|
-
|
|
63
|
-
# case 4
|
|
64
|
-
elsif !controller_same && is_js then
|
|
65
|
-
js_stack = ["// remove elements not present in the following state"]
|
|
66
|
-
js_stack << Nice::Js::Caller.generate_js_remove(current_state)
|
|
67
|
-
|
|
68
|
-
js_stack << ["// remove elements below root"]
|
|
69
|
-
js_stack << Nice::Js::Caller.clean_root_tree
|
|
70
|
-
|
|
71
|
-
js_stack << "// add new content tree blow root tag"
|
|
72
|
-
js_stack += Nice::HtmlParser.add_root_content(cleaned_doc).compact
|
|
73
|
-
|
|
74
|
-
js_stack << "// add elements of the current state above root"
|
|
75
|
-
js_stack += Nice::HtmlParser.add_elements_of_current_state(cleaned_doc,current_state,true).compact
|
|
76
|
-
end
|
|
77
|
-
|
|
78
|
-
# add completing js
|
|
79
|
-
if is_js then
|
|
80
|
-
js_stack << "// add browser history scripts"
|
|
81
|
-
js_stack << Nice::Js::Caller.move_to_url(current_path,"title")
|
|
82
|
-
js_stack << Nice::Js::Caller.insert_or_update_back_listener(referer)
|
|
83
|
-
|
|
84
|
-
js_stack << "// inform ui on state change"
|
|
85
|
-
js_stack << Nice::Js::Caller.state_did_change(prev_state,current_state)
|
|
86
|
-
|
|
87
|
-
js_stack << "// switch body css class"
|
|
88
|
-
js_stack << Nice::Js::Caller.change_top_css(current_state)
|
|
89
|
-
|
|
90
|
-
js_stack << "// AJAX RAILS ENGINE (nice.codebility.com)"
|
|
91
|
-
|
|
92
|
-
response = js_stack.join("\n")
|
|
93
|
-
end
|
|
94
|
-
|
|
95
|
-
response
|
|
96
|
-
end
|
|
97
|
-
|
|
98
|
-
end
|
|
99
|
-
end
|
data/lib/nice/middleware.rb
DELETED
|
@@ -1,100 +0,0 @@
|
|
|
1
|
-
require 'nokogiri'
|
|
2
|
-
require 'nice/logic'
|
|
3
|
-
|
|
4
|
-
module Nice
|
|
5
|
-
class Middleware
|
|
6
|
-
|
|
7
|
-
## case 1: this is the first call of the component -> no previous state
|
|
8
|
-
|
|
9
|
-
# => remove elements not belonging to the start state, generate UID for reference
|
|
10
|
-
# nodes ({ref_element}_ref) and respond with HTML
|
|
11
|
-
|
|
12
|
-
## case 2: this is an ordinary call of another state
|
|
13
|
-
|
|
14
|
-
# => respond with JS with assignments to remove elements not included
|
|
15
|
-
# in current state and assignments to insert elements of current state.
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
## case 3: curr_state == prev_state
|
|
19
|
-
|
|
20
|
-
# => respond with JS which either first removes all elements of the current state and
|
|
21
|
-
# later inserts new content OR directly replaces elements
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
## case 4: this is a normal ajax request responding with javascript from rails
|
|
25
|
-
|
|
26
|
-
# => ignore any NICE handling and return body unfiltered
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
def initialize(app)
|
|
30
|
-
@app = app
|
|
31
|
-
end
|
|
32
|
-
|
|
33
|
-
def call(env)
|
|
34
|
-
@doc = nil
|
|
35
|
-
@referer = nil
|
|
36
|
-
|
|
37
|
-
status, @headers, @body = @app.call(env)
|
|
38
|
-
|
|
39
|
-
p ""
|
|
40
|
-
p "!!!!!!!! RAILS RESPONSE HEADERS: #{@headers}"
|
|
41
|
-
p ""
|
|
42
|
-
|
|
43
|
-
@call_is_js = Rack::Request.new(env).xhr?
|
|
44
|
-
@app_resp_is_js = js?
|
|
45
|
-
|
|
46
|
-
if !@app_resp_is_js && (html? || @call_is_js)
|
|
47
|
-
|
|
48
|
-
@referer = env["HTTP_REFERER"]
|
|
49
|
-
@method = env["REQUEST_METHOD"]
|
|
50
|
-
@path = env["PATH_INFO"]
|
|
51
|
-
|
|
52
|
-
# in case 2+3 the response will be plain javascript
|
|
53
|
-
if @call_is_js
|
|
54
|
-
@headers = {"Content-Type" => "text/javascript"}
|
|
55
|
-
end
|
|
56
|
-
|
|
57
|
-
[status, @headers, self]
|
|
58
|
-
|
|
59
|
-
else
|
|
60
|
-
[status, @headers, @body]
|
|
61
|
-
end
|
|
62
|
-
end
|
|
63
|
-
|
|
64
|
-
def each(&block)
|
|
65
|
-
|
|
66
|
-
if !@app_resp_is_js && (html? || @call_is_js)
|
|
67
|
-
block.call("<!-- NICE Interception -->\n")
|
|
68
|
-
block.call( Nice::Logic.run( @method, @path, @referer, doc, @call_is_js) )
|
|
69
|
-
else
|
|
70
|
-
block.call(@body)
|
|
71
|
-
end
|
|
72
|
-
|
|
73
|
-
end
|
|
74
|
-
|
|
75
|
-
# Helper
|
|
76
|
-
private
|
|
77
|
-
|
|
78
|
-
def html?
|
|
79
|
-
@headers["Content-Type"] && @headers["Content-Type"].include?("text/html")
|
|
80
|
-
end
|
|
81
|
-
|
|
82
|
-
def js?
|
|
83
|
-
@headers["Content-Type"] && ( @headers["Content-Type"].include?("text/javascript") || @headers["Content-Type"].include?("application/json") )
|
|
84
|
-
end
|
|
85
|
-
|
|
86
|
-
def doc
|
|
87
|
-
@doc ||= Nokogiri::HTML(body_to_string)
|
|
88
|
-
end
|
|
89
|
-
|
|
90
|
-
def body_to_string
|
|
91
|
-
s = ""
|
|
92
|
-
@body.each { |x| s << x }
|
|
93
|
-
s
|
|
94
|
-
end
|
|
95
|
-
|
|
96
|
-
def update_content_length
|
|
97
|
-
@headers['Content-Length'] = Rack::Utils.bytesize(@body).to_s
|
|
98
|
-
end
|
|
99
|
-
end
|
|
100
|
-
end
|
data/lib/tasks/nice_tasks.rake
DELETED
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
require 'test_helper'
|
|
2
|
-
|
|
3
|
-
class NiceTest < ActionDispatch::IntegrationTest
|
|
4
|
-
#fixtures :all
|
|
5
|
-
|
|
6
|
-
test "HTML response should not contain any non relevant state elements" do
|
|
7
|
-
# given we make an initial call
|
|
8
|
-
visit a_basic_index_path
|
|
9
|
-
|
|
10
|
-
# then the html response should not contain any elements only owned by other states
|
|
11
|
-
assert_have_no_selector "[data-state]:not([data-state~=get_basic_a])"
|
|
12
|
-
end
|
|
13
|
-
|
|
14
|
-
test "state change should remove all not relevant elements" do
|
|
15
|
-
# given we make an initial call
|
|
16
|
-
visit a_basic_index_path
|
|
17
|
-
|
|
18
|
-
# when switching the state from A -> B
|
|
19
|
-
click_link "State B"
|
|
20
|
-
|
|
21
|
-
# then the resulting page should not contain elements only owned by other states
|
|
22
|
-
assert_have_no_selector "[data-state]:not([data-state~=get_basic_b])"
|
|
23
|
-
end
|
|
24
|
-
|
|
25
|
-
end
|
data/test/test_helper.rb
DELETED
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
# Configure Rails Environment
|
|
2
|
-
ENV["RAILS_ENV"] = "test"
|
|
3
|
-
|
|
4
|
-
require File.expand_path("../nizzaTestApp/config/environment", __FILE__)
|
|
5
|
-
require "rails/test_help"
|
|
6
|
-
require "haml"
|
|
7
|
-
|
|
8
|
-
Rails.backtrace_cleaner.remove_silencers!
|
|
9
|
-
|
|
10
|
-
# Load support files
|
|
11
|
-
Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each { |f| require f }
|
|
12
|
-
|
|
13
|
-
# load test applications
|
|
14
|
-
Dir[File.expand_path('../nizzaTestApp/*.rb', __FILE__)].each do |f|
|
|
15
|
-
require f
|
|
16
|
-
end
|
|
17
|
-
|
|
18
|
-
# Load fixtures from the engine
|
|
19
|
-
if ActiveSupport::TestCase.method_defined?(:fixture_path=)
|
|
20
|
-
ActiveSupport::TestCase.fixture_path = File.expand_path("../fixtures", __FILE__)
|
|
21
|
-
end
|
|
22
|
-
|
|
23
|
-
require "webrat"
|
|
24
|
-
|
|
25
|
-
Webrat.configure do |config|
|
|
26
|
-
config.mode = :rack
|
|
27
|
-
# config.application_framework = :rails
|
|
28
|
-
# config.selenium_server_address = "127.0.0.1"
|
|
29
|
-
# config.selenium_server_port = "3000"
|
|
30
|
-
end
|