capybara 2.1.0 → 2.2.0.rc1
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
- checksums.yaml.gz.sig +0 -0
- data.tar.gz.sig +0 -0
- data/History.md +48 -1
- data/README.md +22 -18
- data/lib/capybara.rb +28 -3
- data/lib/capybara/cucumber.rb +0 -2
- data/lib/capybara/driver/base.rb +9 -1
- data/lib/capybara/empty.html +4 -0
- data/lib/capybara/node/actions.rb +1 -1
- data/lib/capybara/node/finders.rb +3 -3
- data/lib/capybara/node/matchers.rb +22 -18
- data/lib/capybara/node/simple.rb +5 -3
- data/lib/capybara/query.rb +1 -0
- data/lib/capybara/rack_test/browser.rb +5 -4
- data/lib/capybara/rack_test/form.rb +5 -2
- data/lib/capybara/rack_test/node.rb +2 -1
- data/lib/capybara/result.rb +2 -1
- data/lib/capybara/rspec.rb +7 -0
- data/lib/capybara/rspec/features.rb +2 -0
- data/lib/capybara/rspec/matchers.rb +6 -6
- data/lib/capybara/selector.rb +3 -1
- data/lib/capybara/selenium/driver.rb +14 -2
- data/lib/capybara/selenium/node.rb +18 -5
- data/lib/capybara/server.rb +3 -7
- data/lib/capybara/session.rb +59 -17
- data/lib/capybara/spec/public/test.js +1 -1
- data/lib/capybara/spec/session/assert_selector.rb +18 -0
- data/lib/capybara/spec/session/attach_file_spec.rb +5 -0
- data/lib/capybara/spec/session/check_spec.rb +14 -0
- data/lib/capybara/spec/session/choose_spec.rb +14 -0
- data/lib/capybara/spec/session/click_button_spec.rb +20 -1
- data/lib/capybara/spec/session/fill_in_spec.rb +18 -2
- data/lib/capybara/spec/session/go_back_spec.rb +10 -0
- data/lib/capybara/spec/session/go_forward_spec.rb +12 -0
- data/lib/capybara/spec/session/has_button_spec.rb +24 -0
- data/lib/capybara/spec/session/has_field_spec.rb +48 -0
- data/lib/capybara/spec/session/has_text_spec.rb +18 -0
- data/lib/capybara/spec/session/node_spec.rb +36 -1
- data/lib/capybara/spec/session/reset_session_spec.rb +17 -2
- data/lib/capybara/spec/session/save_page_spec.rb +10 -4
- data/lib/capybara/spec/session/visit_spec.rb +16 -0
- data/lib/capybara/spec/session/within_frame_spec.rb +7 -0
- data/lib/capybara/spec/session/within_window_spec.rb +7 -0
- data/lib/capybara/spec/test_app.rb +1 -0
- data/lib/capybara/spec/views/form.erb +40 -0
- data/lib/capybara/spec/views/with_html.erb +5 -0
- data/lib/capybara/spec/views/with_js.erb +8 -0
- data/lib/capybara/version.rb +1 -1
- data/spec/capybara_spec.rb +1 -1
- data/spec/result_spec.rb +14 -0
- data/spec/rspec/features_spec.rb +15 -0
- data/spec/rspec/matchers_spec.rb +24 -1
- data/spec/selenium_spec.rb +8 -1
- data/spec/server_spec.rb +13 -5
- metadata +78 -98
- metadata.gz.sig +0 -0
data/lib/capybara/query.rb
CHANGED
@@ -46,6 +46,7 @@ class Capybara::RackTest::Browser
|
|
46
46
|
method.downcase! unless method.is_a? Symbol
|
47
47
|
|
48
48
|
new_uri.path = request_path if path.start_with?("?")
|
49
|
+
new_uri.path = "/" if new_uri.path.empty?
|
49
50
|
new_uri.path = request_path.sub(%r(/[^/]*$), '/') + new_uri.path unless new_uri.path.start_with?('/')
|
50
51
|
new_uri.scheme ||= @current_scheme
|
51
52
|
new_uri.host ||= @current_host
|
@@ -77,7 +78,7 @@ class Capybara::RackTest::Browser
|
|
77
78
|
end
|
78
79
|
|
79
80
|
def dom
|
80
|
-
@dom ||=
|
81
|
+
@dom ||= Capybara::HTML(html)
|
81
82
|
end
|
82
83
|
|
83
84
|
def find(format, selector)
|
@@ -93,11 +94,11 @@ class Capybara::RackTest::Browser
|
|
93
94
|
rescue Rack::Test::Error
|
94
95
|
""
|
95
96
|
end
|
96
|
-
|
97
|
+
|
97
98
|
def title
|
98
99
|
dom.xpath("//title").text
|
99
100
|
end
|
100
|
-
|
101
|
+
|
101
102
|
protected
|
102
103
|
|
103
104
|
def build_rack_mock_session
|
@@ -108,6 +109,6 @@ protected
|
|
108
109
|
def request_path
|
109
110
|
last_request.path
|
110
111
|
rescue Rack::Test::Error
|
111
|
-
""
|
112
|
+
"/"
|
112
113
|
end
|
113
114
|
end
|
@@ -28,7 +28,10 @@ class Capybara::RackTest::Form < Capybara::RackTest::Node
|
|
28
28
|
case field.name
|
29
29
|
when 'input'
|
30
30
|
if %w(radio checkbox).include? field['type']
|
31
|
-
|
31
|
+
if field['checked']
|
32
|
+
node=Capybara::RackTest::Node.new(self.driver, field)
|
33
|
+
merge_param!(params, field['name'].to_s, node.value.to_s)
|
34
|
+
end
|
32
35
|
elsif %w(submit image).include? field['type']
|
33
36
|
# TO DO identify the click button here (in document order, rather
|
34
37
|
# than leaving until the end of the params)
|
@@ -60,7 +63,7 @@ class Capybara::RackTest::Form < Capybara::RackTest::Node
|
|
60
63
|
merge_param!(params, field['name'].to_s, (option['value'] || option.text).to_s) if option
|
61
64
|
end
|
62
65
|
when 'textarea'
|
63
|
-
merge_param!(params, field['name'].to_s, field.text.to_s)
|
66
|
+
merge_param!(params, field['name'].to_s, field.text.to_s.gsub(/\n/, "\r\n"))
|
64
67
|
end
|
65
68
|
end
|
66
69
|
merge_param!(params, button[:name], button[:value] || "") if button[:name]
|
@@ -52,7 +52,8 @@ class Capybara::RackTest::Node < Capybara::Driver::Node
|
|
52
52
|
driver.follow(method, self[:href].to_s)
|
53
53
|
elsif (tag_name == 'input' and %w(submit image).include?(type)) or
|
54
54
|
((tag_name == 'button') and type.nil? or type == "submit")
|
55
|
-
|
55
|
+
associated_form = form
|
56
|
+
Capybara::RackTest::Form.new(driver, associated_form).submit(self) if associated_form
|
56
57
|
end
|
57
58
|
end
|
58
59
|
|
data/lib/capybara/result.rb
CHANGED
@@ -29,7 +29,8 @@ module Capybara
|
|
29
29
|
@query = query
|
30
30
|
end
|
31
31
|
|
32
|
-
def_delegators :@result, :each, :[], :at, :size, :count, :length,
|
32
|
+
def_delegators :@result, :each, :[], :at, :size, :count, :length,
|
33
|
+
:first, :last, :values_at, :empty?, :inspect, :sample, :index
|
33
34
|
|
34
35
|
def matches_count?
|
35
36
|
Capybara::Helpers.matches_count?(@result.size, @query.options)
|
data/lib/capybara/rspec.rb
CHANGED
@@ -7,6 +7,12 @@ require 'capybara/rspec/features'
|
|
7
7
|
RSpec.configure do |config|
|
8
8
|
config.include Capybara::DSL, :type => :feature
|
9
9
|
config.include Capybara::RSpecMatchers, :type => :feature
|
10
|
+
|
11
|
+
# A work-around to support accessing the current example that works in both
|
12
|
+
# RSpec 2 and RSpec 3.
|
13
|
+
fetch_current_example = RSpec.respond_to?(:current_example) ?
|
14
|
+
proc { RSpec.current_example } : proc { |context| context.example }
|
15
|
+
|
10
16
|
# The before and after blocks must run instantaneously, because Capybara
|
11
17
|
# might not actually be used in all examples where it's included.
|
12
18
|
config.after do
|
@@ -17,6 +23,7 @@ RSpec.configure do |config|
|
|
17
23
|
end
|
18
24
|
config.before do
|
19
25
|
if self.class.include?(Capybara::DSL)
|
26
|
+
example = fetch_current_example.call(self)
|
20
27
|
Capybara.current_driver = Capybara.javascript_driver if example.metadata[:js]
|
21
28
|
Capybara.current_driver = example.metadata[:driver] if example.metadata[:driver]
|
22
29
|
end
|
@@ -7,11 +7,13 @@ module Capybara
|
|
7
7
|
alias :xscenario :xit
|
8
8
|
alias :given :let
|
9
9
|
alias :given! :let!
|
10
|
+
alias :feature :describe
|
10
11
|
end
|
11
12
|
end
|
12
13
|
end
|
13
14
|
end
|
14
15
|
|
16
|
+
|
15
17
|
def self.feature(*args, &block)
|
16
18
|
options = if args.last.is_a?(Hash) then args.pop else {} end
|
17
19
|
options[:capybara_feature] = true
|
@@ -126,20 +126,20 @@ module Capybara
|
|
126
126
|
HaveSelector.new(:link, locator, options)
|
127
127
|
end
|
128
128
|
|
129
|
-
def have_button(locator)
|
130
|
-
HaveSelector.new(:button, locator)
|
129
|
+
def have_button(locator, options={})
|
130
|
+
HaveSelector.new(:button, locator, options)
|
131
131
|
end
|
132
132
|
|
133
133
|
def have_field(locator, options={})
|
134
134
|
HaveSelector.new(:field, locator, options)
|
135
135
|
end
|
136
136
|
|
137
|
-
def have_checked_field(locator)
|
138
|
-
HaveSelector.new(:field, locator, :checked => true)
|
137
|
+
def have_checked_field(locator, options={})
|
138
|
+
HaveSelector.new(:field, locator, options.merge(:checked => true))
|
139
139
|
end
|
140
140
|
|
141
|
-
def have_unchecked_field(locator)
|
142
|
-
HaveSelector.new(:field, locator, :unchecked => true)
|
141
|
+
def have_unchecked_field(locator, options={})
|
142
|
+
HaveSelector.new(:field, locator, options.merge(:unchecked => true))
|
143
143
|
end
|
144
144
|
|
145
145
|
def have_select(locator, options={})
|
data/lib/capybara/selector.rb
CHANGED
@@ -103,7 +103,7 @@ Capybara.add_selector(:field) do
|
|
103
103
|
filter(:checked) { |node, value| not(value ^ node.checked?) }
|
104
104
|
filter(:unchecked) { |node, value| (value ^ node.checked?) }
|
105
105
|
filter(:disabled, :default => false) { |node, value| not(value ^ node.disabled?) }
|
106
|
-
filter(:with) { |node, with| node.value == with }
|
106
|
+
filter(:with) { |node, with| node.value == with.to_s }
|
107
107
|
filter(:type) do |node, type|
|
108
108
|
if ['textarea', 'select'].include?(type)
|
109
109
|
node.tag_name == type
|
@@ -146,6 +146,7 @@ Capybara.add_selector(:radio_button) do
|
|
146
146
|
xpath { |locator| XPath::HTML.radio_button(locator) }
|
147
147
|
filter(:checked) { |node, value| not(value ^ node.checked?) }
|
148
148
|
filter(:unchecked) { |node, value| (value ^ node.checked?) }
|
149
|
+
filter(:option) { |node, value| node.value == value.to_s }
|
149
150
|
filter(:disabled, :default => false) { |node, value| not(value ^ node.disabled?) }
|
150
151
|
end
|
151
152
|
|
@@ -153,6 +154,7 @@ Capybara.add_selector(:checkbox) do
|
|
153
154
|
xpath { |locator| XPath::HTML.checkbox(locator) }
|
154
155
|
filter(:checked) { |node, value| not(value ^ node.checked?) }
|
155
156
|
filter(:unchecked) { |node, value| (value ^ node.checked?) }
|
157
|
+
filter(:option) { |node, value| node.value == value.to_s }
|
156
158
|
filter(:disabled, :default => false) { |node, value| not(value ^ node.disabled?) }
|
157
159
|
end
|
158
160
|
|
@@ -1,3 +1,5 @@
|
|
1
|
+
require "uri"
|
2
|
+
|
1
3
|
class Capybara::Selenium::Driver < Capybara::Driver::Base
|
2
4
|
DEFAULT_OPTIONS = {
|
3
5
|
:browser => :firefox
|
@@ -43,6 +45,14 @@ class Capybara::Selenium::Driver < Capybara::Driver::Base
|
|
43
45
|
browser.navigate.to(path)
|
44
46
|
end
|
45
47
|
|
48
|
+
def go_back
|
49
|
+
browser.navigate.back
|
50
|
+
end
|
51
|
+
|
52
|
+
def go_forward
|
53
|
+
browser.navigate.forward
|
54
|
+
end
|
55
|
+
|
46
56
|
def html
|
47
57
|
browser.page_source
|
48
58
|
end
|
@@ -87,7 +97,9 @@ class Capybara::Selenium::Driver < Capybara::Driver::Base
|
|
87
97
|
# to about:blank, so we rescue this error and do nothing
|
88
98
|
# instead.
|
89
99
|
end
|
90
|
-
|
100
|
+
uri = URI(Capybara::EMPTY_HTML_FILE_PATH)
|
101
|
+
uri.scheme = "file"
|
102
|
+
@browser.navigate.to(uri.to_s)
|
91
103
|
end
|
92
104
|
end
|
93
105
|
|
@@ -137,7 +149,7 @@ class Capybara::Selenium::Driver < Capybara::Driver::Base
|
|
137
149
|
end
|
138
150
|
|
139
151
|
def quit
|
140
|
-
@browser.quit
|
152
|
+
@browser.quit if @browser
|
141
153
|
rescue Errno::ECONNREFUSED
|
142
154
|
# Browser must have already gone
|
143
155
|
end
|
@@ -37,8 +37,21 @@ class Capybara::Selenium::Node < Capybara::Driver::Node
|
|
37
37
|
path_names = value.to_s.empty? ? [] : value
|
38
38
|
native.send_keys(*path_names)
|
39
39
|
elsif tag_name == 'textarea' or tag_name == 'input'
|
40
|
-
|
41
|
-
|
40
|
+
if value.to_s.empty?
|
41
|
+
native.clear
|
42
|
+
else
|
43
|
+
#script can change a readonly element which user input cannot, so dont execute if readonly
|
44
|
+
driver.browser.execute_script "arguments[0].value = ''", native unless self[:readonly]
|
45
|
+
native.send_keys(value.to_s)
|
46
|
+
end
|
47
|
+
elsif native.attribute('isContentEditable')
|
48
|
+
#ensure we are focused on the element
|
49
|
+
script = <<-JS
|
50
|
+
var range = document.createRange();
|
51
|
+
range.selectNodeContents(arguments[0]);
|
52
|
+
window.getSelection().addRange(range);
|
53
|
+
JS
|
54
|
+
driver.browser.execute_script script, native
|
42
55
|
native.send_keys(value.to_s)
|
43
56
|
end
|
44
57
|
end
|
@@ -61,7 +74,7 @@ class Capybara::Selenium::Node < Capybara::Driver::Node
|
|
61
74
|
def hover
|
62
75
|
driver.browser.action.move_to(native).perform
|
63
76
|
end
|
64
|
-
|
77
|
+
|
65
78
|
def drag_to(element)
|
66
79
|
driver.browser.action.drag_and_drop(native, element.native).perform
|
67
80
|
end
|
@@ -89,11 +102,11 @@ class Capybara::Selenium::Node < Capybara::Driver::Node
|
|
89
102
|
def find_xpath(locator)
|
90
103
|
native.find_elements(:xpath, locator).map { |n| self.class.new(driver, n) }
|
91
104
|
end
|
92
|
-
|
105
|
+
|
93
106
|
def find_css(locator)
|
94
107
|
native.find_elements(:css, locator).map { |n| self.class.new(driver, n) }
|
95
108
|
end
|
96
|
-
|
109
|
+
|
97
110
|
def ==(other)
|
98
111
|
native == other.native
|
99
112
|
end
|
data/lib/capybara/server.rb
CHANGED
@@ -31,13 +31,13 @@ module Capybara
|
|
31
31
|
end
|
32
32
|
end
|
33
33
|
|
34
|
-
attr_reader :app, :port
|
34
|
+
attr_reader :app, :port, :host
|
35
35
|
|
36
|
-
def initialize(app, port=Capybara.server_port)
|
36
|
+
def initialize(app, port=Capybara.server_port, host=Capybara.server_host)
|
37
37
|
@app = app
|
38
38
|
@middleware = Middleware.new(@app)
|
39
39
|
@server_thread = nil # supress warnings
|
40
|
-
@port = port
|
40
|
+
@host, @port = host, port
|
41
41
|
@port ||= Capybara::Server.ports[@app.object_id]
|
42
42
|
@port ||= find_available_port
|
43
43
|
end
|
@@ -50,10 +50,6 @@ module Capybara
|
|
50
50
|
@middleware.error
|
51
51
|
end
|
52
52
|
|
53
|
-
def host
|
54
|
-
Capybara.server_host || "127.0.0.1"
|
55
|
-
end
|
56
|
-
|
57
53
|
def responsive?
|
58
54
|
return false if @server_thread && @server_thread.join(0)
|
59
55
|
|
data/lib/capybara/session.rb
CHANGED
@@ -37,10 +37,11 @@ module Capybara
|
|
37
37
|
:has_no_unchecked_field?, :query, :assert_selector, :assert_no_selector
|
38
38
|
]
|
39
39
|
SESSION_METHODS = [
|
40
|
-
:body, :html, :
|
41
|
-
:
|
42
|
-
:
|
43
|
-
:
|
40
|
+
:body, :html, :source, :current_url, :current_host, :current_path,
|
41
|
+
:execute_script, :evaluate_script, :visit, :go_back, :go_forward,
|
42
|
+
:within, :within_fieldset, :within_table, :within_frame, :within_window,
|
43
|
+
:save_page, :save_and_open_page, :save_screenshot,
|
44
|
+
:reset_session!, :response_headers, :status_code,
|
44
45
|
:title, :has_title?, :has_no_title?, :current_scope
|
45
46
|
]
|
46
47
|
DSL_METHODS = NODE_METHODS + SESSION_METHODS
|
@@ -74,8 +75,11 @@ module Capybara
|
|
74
75
|
# Reset the session, removing all cookies.
|
75
76
|
#
|
76
77
|
def reset!
|
77
|
-
|
78
|
-
|
78
|
+
if @touched
|
79
|
+
driver.reset!
|
80
|
+
@touched = false
|
81
|
+
assert_no_selector :xpath, "/html/body/*"
|
82
|
+
end
|
79
83
|
raise @server.error if Capybara.raise_server_errors and @server and @server.error
|
80
84
|
ensure
|
81
85
|
@server.reset_error! if @server
|
@@ -195,27 +199,54 @@ module Capybara
|
|
195
199
|
|
196
200
|
##
|
197
201
|
#
|
198
|
-
#
|
199
|
-
#
|
202
|
+
# Move back a single entry in the browser's history.
|
203
|
+
#
|
204
|
+
def go_back
|
205
|
+
driver.go_back
|
206
|
+
end
|
207
|
+
|
208
|
+
##
|
209
|
+
#
|
210
|
+
# Move forward a single entry in the browser's history.
|
211
|
+
#
|
212
|
+
def go_forward
|
213
|
+
driver.go_forward
|
214
|
+
end
|
215
|
+
|
216
|
+
##
|
217
|
+
#
|
218
|
+
# Executes the given block within the context of a node. `within` takes the
|
219
|
+
# same options as `find`, as well as a block. For the duration of the
|
220
|
+
# block, any command to Capybara will be handled as though it were scoped
|
221
|
+
# to the given element.
|
200
222
|
#
|
201
223
|
# within(:xpath, '//div[@id="delivery-address"]') do
|
202
224
|
# fill_in('Street', :with => '12 Main Street')
|
203
225
|
# end
|
204
226
|
#
|
205
|
-
#
|
206
|
-
#
|
227
|
+
# Just as with `find`, if multiple elements match the selector given to
|
228
|
+
# `within`, an error will be raised, and just as with `find`, this
|
229
|
+
# behaviour can be controlled through the `:match` and `:exact` options.
|
230
|
+
#
|
231
|
+
# It is possible to omit the first parameter, in that case, the selector is
|
232
|
+
# assumed to be of the type set in Capybara.default_selector.
|
207
233
|
#
|
208
234
|
# within('div#delivery-address') do
|
209
235
|
# fill_in('Street', :with => '12 Main Street')
|
210
236
|
# end
|
211
237
|
#
|
238
|
+
# Note that a lot of uses of `within` can be replaced more succinctly with
|
239
|
+
# chaining:
|
240
|
+
#
|
241
|
+
# find('div#delivery-address').fill_in('Street', :with => '12 Main Street')
|
242
|
+
#
|
212
243
|
# @overload within(*find_args)
|
213
244
|
# @param (see Capybara::Node::Finders#all)
|
214
245
|
#
|
215
246
|
# @overload within(a_node)
|
216
247
|
# @param [Capybara::Node::Base] a_node The node in whose scope the block should be evaluated
|
217
248
|
#
|
218
|
-
# @raise [Capybara::ElementNotFound]
|
249
|
+
# @raise [Capybara::ElementNotFound] If the scope can't be found before time expires
|
219
250
|
#
|
220
251
|
def within(*args)
|
221
252
|
new_scope = if args.first.is_a?(Capybara::Node::Base) then args.first else find(*args) end
|
@@ -262,9 +293,12 @@ module Capybara
|
|
262
293
|
# @param [String] name name of a frame
|
263
294
|
#
|
264
295
|
def within_frame(frame_handle)
|
296
|
+
scopes.push(nil)
|
265
297
|
driver.within_frame(frame_handle) do
|
266
298
|
yield
|
267
299
|
end
|
300
|
+
ensure
|
301
|
+
scopes.pop
|
268
302
|
end
|
269
303
|
|
270
304
|
##
|
@@ -275,7 +309,10 @@ module Capybara
|
|
275
309
|
# @param [String] handle of the window
|
276
310
|
#
|
277
311
|
def within_window(handle, &blk)
|
312
|
+
scopes.push(nil)
|
278
313
|
driver.within_window(handle, &blk)
|
314
|
+
ensure
|
315
|
+
scopes.pop
|
279
316
|
end
|
280
317
|
|
281
318
|
##
|
@@ -313,7 +350,7 @@ module Capybara
|
|
313
350
|
#
|
314
351
|
def save_page(path=nil)
|
315
352
|
path ||= "capybara-#{Time.new.strftime("%Y%m%d%H%M%S")}#{rand(10**10)}.html"
|
316
|
-
path = File.expand_path(path, Capybara.save_and_open_page_path)
|
353
|
+
path = File.expand_path(path, Capybara.save_and_open_page_path)
|
317
354
|
|
318
355
|
FileUtils.mkdir_p(File.dirname(path))
|
319
356
|
|
@@ -328,10 +365,15 @@ module Capybara
|
|
328
365
|
# @param [String] file_name The path to where it should be saved [optional]
|
329
366
|
#
|
330
367
|
def save_and_open_page(file_name=nil)
|
331
|
-
|
332
|
-
|
333
|
-
|
334
|
-
|
368
|
+
file_name = save_page(file_name)
|
369
|
+
|
370
|
+
begin
|
371
|
+
require "launchy"
|
372
|
+
Launchy.open(file_name)
|
373
|
+
rescue LoadError
|
374
|
+
warn "Page saved to #{file_name} with save_and_open_page."
|
375
|
+
warn "Please install the launchy gem to open page automatically."
|
376
|
+
end
|
335
377
|
end
|
336
378
|
|
337
379
|
##
|
@@ -382,7 +424,7 @@ module Capybara
|
|
382
424
|
end
|
383
425
|
|
384
426
|
def current_scope
|
385
|
-
scopes.last
|
427
|
+
scopes.last || document
|
386
428
|
end
|
387
429
|
|
388
430
|
private
|
@@ -35,7 +35,7 @@ $(function() {
|
|
35
35
|
$('body').append('<p id="focus_event_triggered">Focus Event triggered</p>');
|
36
36
|
});
|
37
37
|
$('#with_change_event').change(function() {
|
38
|
-
|
38
|
+
$('body').append($('<p class="change_event_triggered"></p>').text(this.value));
|
39
39
|
});
|
40
40
|
$('#checkbox_with_event').click(function() {
|
41
41
|
$('body').append('<p id="checkbox_event_triggered">Checkbox event triggered</p>');
|