xpath 0.1.4 → 1.0.0.beta1
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.
- data/README.rdoc +61 -4
- data/lib/xpath.rb +6 -57
- data/lib/xpath/dsl.rb +104 -0
- data/lib/xpath/expression.rb +8 -298
- data/lib/xpath/html.rb +101 -62
- data/lib/xpath/literal.rb +8 -0
- data/lib/xpath/renderer.rb +146 -0
- data/lib/xpath/union.rb +10 -12
- data/lib/xpath/version.rb +1 -1
- data/spec/fixtures/form.html +49 -7
- data/spec/html_spec.rb +45 -47
- data/spec/union_spec.rb +14 -13
- data/spec/xpath_spec.rb +35 -88
- metadata +78 -69
data/lib/xpath/html.rb
CHANGED
@@ -3,112 +3,151 @@ module XPath
|
|
3
3
|
include XPath
|
4
4
|
extend self
|
5
5
|
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
end
|
15
|
-
|
6
|
+
# Match an `a` link element.
|
7
|
+
#
|
8
|
+
# @param [String] locator
|
9
|
+
# Text, id, title, or image alt attribute of the link
|
10
|
+
#
|
11
|
+
def link(locator)
|
12
|
+
link = descendant(:a)[attr(:href)]
|
13
|
+
link[attr(:id).equals(locator) | string.n.contains(locator) | attr(:title).contains(locator) | descendant(:img)[attr(:alt).contains(locator)]]
|
14
|
+
end
|
15
|
+
|
16
|
+
# Match a `submit`, `image`, or `button` element.
|
17
|
+
#
|
18
|
+
# @param [String] locator
|
19
|
+
# Value, title, id, or image alt attribute of the button
|
20
|
+
#
|
16
21
|
def button(locator)
|
17
|
-
button = descendant(:input)[attr(:type).one_of('submit', 'image', 'button')][attr(:id).equals(locator) | attr(:value).
|
18
|
-
button += descendant(:button)[attr(:id).equals(locator) | attr(:value).
|
19
|
-
button += descendant(:input)[attr(:type).equals('image')][attr(:alt).
|
22
|
+
button = descendant(:input)[attr(:type).one_of('submit', 'reset', 'image', 'button')][attr(:id).equals(locator) | attr(:value).contains(locator) | attr(:title).contains(locator)]
|
23
|
+
button += descendant(:button)[attr(:id).equals(locator) | attr(:value).contains(locator) | string.n.contains(locator) | attr(:title).contains(locator)]
|
24
|
+
button += descendant(:input)[attr(:type).equals('image')][attr(:alt).contains(locator)]
|
20
25
|
end
|
21
26
|
|
27
|
+
|
28
|
+
# Match anything returned by either {#link} or {#button}.
|
29
|
+
#
|
30
|
+
# @param [String] locator
|
31
|
+
# Text, id, title, or image alt attribute of the link or button
|
32
|
+
#
|
22
33
|
def link_or_button(locator)
|
23
34
|
link(locator) + button(locator)
|
24
35
|
end
|
25
36
|
|
37
|
+
|
38
|
+
# Match any `fieldset` element.
|
39
|
+
#
|
40
|
+
# @param [String] locator
|
41
|
+
# Legend or id of the fieldset
|
42
|
+
#
|
26
43
|
def fieldset(locator)
|
27
|
-
descendant(:fieldset)[attr(:id).equals(locator) |
|
44
|
+
descendant(:fieldset)[attr(:id).equals(locator) | child(:legend)[string.n.contains(locator)]]
|
28
45
|
end
|
29
46
|
|
30
|
-
|
47
|
+
|
48
|
+
# Match any `input`, `textarea`, or `select` element that doesn't have a
|
49
|
+
# type of `submit`, `image`, or `hidden`.
|
50
|
+
#
|
51
|
+
# @param [String] locator
|
52
|
+
# Label, id, or name of field to match
|
53
|
+
#
|
54
|
+
def field(locator)
|
31
55
|
xpath = descendant(:input, :textarea, :select)[~attr(:type).one_of('submit', 'image', 'hidden')]
|
32
56
|
xpath = locate_field(xpath, locator)
|
33
|
-
xpath = xpath[attr(:checked)] if options[:checked]
|
34
|
-
xpath = xpath[~attr(:checked)] if options[:unchecked]
|
35
|
-
xpath = xpath[field_value(options[:with])] if options.has_key?(:with)
|
36
57
|
xpath
|
37
58
|
end
|
38
59
|
|
39
|
-
|
60
|
+
|
61
|
+
# Match any `input` or `textarea` element that can be filled with text.
|
62
|
+
# This excludes any inputs with a type of `submit`, `image`, `radio`,
|
63
|
+
# `checkbox`, `hidden`, or `file`.
|
64
|
+
#
|
65
|
+
# @param [String] locator
|
66
|
+
# Label, id, or name of field to match
|
67
|
+
#
|
68
|
+
def fillable_field(locator)
|
40
69
|
xpath = descendant(:input, :textarea)[~attr(:type).one_of('submit', 'image', 'radio', 'checkbox', 'hidden', 'file')]
|
41
70
|
xpath = locate_field(xpath, locator)
|
42
|
-
xpath = xpath[field_value(options[:with])] if options.has_key?(:with)
|
43
71
|
xpath
|
44
72
|
end
|
45
73
|
|
46
|
-
def select(locator, options={})
|
47
|
-
xpath = locate_field(descendant(:select), locator)
|
48
74
|
|
49
|
-
|
50
|
-
|
51
|
-
|
75
|
+
# Match any `select` element.
|
76
|
+
#
|
77
|
+
# @param [String] locator
|
78
|
+
# Label, id, or name of the field to match
|
79
|
+
#
|
80
|
+
def select(locator)
|
81
|
+
locate_field(descendant(:select), locator)
|
82
|
+
end
|
52
83
|
|
53
|
-
[options[:selected]].flatten.each do |option|
|
54
|
-
xpath = xpath[descendant(:option)[attr(:selected)].equals(option)]
|
55
|
-
end if options[:selected]
|
56
84
|
|
57
|
-
|
85
|
+
# Match any `input` element of type `checkbox`.
|
86
|
+
#
|
87
|
+
# @param [String] locator
|
88
|
+
# Label, id, or name of the checkbox to match
|
89
|
+
#
|
90
|
+
def checkbox(locator)
|
91
|
+
locate_field(descendant(:input)[attr(:type).equals('checkbox')], locator)
|
58
92
|
end
|
59
93
|
|
60
|
-
def checkbox(locator, options={})
|
61
|
-
xpath = locate_field(descendant(:input)[attr(:type).equals('checkbox')], locator)
|
62
|
-
end
|
63
94
|
|
64
|
-
|
95
|
+
# Match any `input` element of type `radio`.
|
96
|
+
#
|
97
|
+
# @param [String] locator
|
98
|
+
# Label, id, or name of the radio button to match
|
99
|
+
#
|
100
|
+
def radio_button(locator)
|
65
101
|
locate_field(descendant(:input)[attr(:type).equals('radio')], locator)
|
66
102
|
end
|
67
103
|
|
68
|
-
|
104
|
+
|
105
|
+
# Match any `input` element of type `file`.
|
106
|
+
#
|
107
|
+
# @param [String] locator
|
108
|
+
# Label, id, or name of the file field to match
|
109
|
+
#
|
110
|
+
def file_field(locator)
|
69
111
|
locate_field(descendant(:input)[attr(:type).equals('file')], locator)
|
70
112
|
end
|
71
113
|
|
114
|
+
|
115
|
+
# Match an `optgroup` element.
|
116
|
+
#
|
117
|
+
# @param [String] name
|
118
|
+
# Label for the option group
|
119
|
+
#
|
72
120
|
def optgroup(name)
|
73
|
-
descendant(:optgroup)[attr(:label).
|
121
|
+
descendant(:optgroup)[attr(:label).contains(name)]
|
74
122
|
end
|
75
123
|
|
76
|
-
def option(name)
|
77
|
-
descendant(:option)[string.n.is(name)]
|
78
|
-
end
|
79
124
|
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
125
|
+
# Match an `option` element.
|
126
|
+
#
|
127
|
+
# @param [String] name
|
128
|
+
# Visible text of the option
|
129
|
+
#
|
130
|
+
def option(name)
|
131
|
+
descendant(:option)[string.n.equals(name)]
|
84
132
|
end
|
85
133
|
|
86
|
-
def table_rows(rows)
|
87
|
-
row_conditions = descendant(:tr)[table_row(rows.first)]
|
88
|
-
rows.drop(1).each do |row|
|
89
|
-
row_conditions = row_conditions.next_sibling(:tr)[table_row(row)]
|
90
|
-
end
|
91
|
-
row_conditions
|
92
|
-
end
|
93
134
|
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
135
|
+
# Match any `table` element.
|
136
|
+
#
|
137
|
+
# @param [String] locator
|
138
|
+
# Caption or id of the table to match
|
139
|
+
# @option options [Array] :rows
|
140
|
+
# Content of each cell in each row to match
|
141
|
+
#
|
142
|
+
def table(locator)
|
143
|
+
descendant(:table)[attr(:id).equals(locator) | descendant(:caption).contains(locator)]
|
100
144
|
end
|
101
145
|
|
102
146
|
protected
|
103
147
|
|
104
148
|
def locate_field(xpath, locator)
|
105
|
-
locate_field = xpath[attr(:id).equals(locator) | attr(:name).equals(locator) | attr(:id).equals(anywhere(:label)[string.n.
|
106
|
-
locate_field += descendant(:label)[string.n.
|
149
|
+
locate_field = xpath[attr(:id).equals(locator) | attr(:name).equals(locator) | attr(:placeholder).equals(locator) | attr(:id).equals(anywhere(:label)[string.n.contains(locator)].attr(:for))]
|
150
|
+
locate_field += descendant(:label)[string.n.contains(locator)].descendant(xpath)
|
107
151
|
end
|
108
|
-
|
109
|
-
def field_value(value)
|
110
|
-
(string.n.is(value) & tag(:textarea)) | (attr(:value).equals(value) & ~tag(:textarea))
|
111
|
-
end
|
112
|
-
|
113
152
|
end
|
114
153
|
end
|
@@ -0,0 +1,146 @@
|
|
1
|
+
module XPath
|
2
|
+
class Renderer
|
3
|
+
def self.render(node)
|
4
|
+
new.render(node)
|
5
|
+
end
|
6
|
+
|
7
|
+
def render(node)
|
8
|
+
arguments = node.arguments.map { |argument| convert_argument(argument) }
|
9
|
+
send(node.expression, *arguments)
|
10
|
+
end
|
11
|
+
|
12
|
+
def convert_argument(argument)
|
13
|
+
case argument
|
14
|
+
when Expression, Union then render(argument)
|
15
|
+
when Array then argument.map { |element| convert_argument(element) }
|
16
|
+
when String then string_literal(argument)
|
17
|
+
when Literal then argument.value
|
18
|
+
else argument.to_s
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def string_literal(string)
|
23
|
+
if string.include?("'")
|
24
|
+
string = string.split("'", -1).map do |substr|
|
25
|
+
"'#{substr}'"
|
26
|
+
end.join(%q{,"'",})
|
27
|
+
"concat(#{string})"
|
28
|
+
else
|
29
|
+
"'#{string}'"
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def this_node
|
34
|
+
'.'
|
35
|
+
end
|
36
|
+
|
37
|
+
def descendant(parent, element_names)
|
38
|
+
if element_names.length == 1
|
39
|
+
"#{parent}//#{element_names.first}"
|
40
|
+
elsif element_names.length > 1
|
41
|
+
"#{parent}//*[#{element_names.map { |e| "self::#{e}" }.join(" | ")}]"
|
42
|
+
else
|
43
|
+
"#{parent}//*"
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def child(parent, element_names)
|
48
|
+
if element_names.length == 1
|
49
|
+
"#{parent}/#{element_names.first}"
|
50
|
+
elsif element_names.length > 1
|
51
|
+
"#{parent}/*[#{element_names.map { |e| "self::#{e}" }.join(" | ")}]"
|
52
|
+
else
|
53
|
+
"#{parent}/*"
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def axis(parent, name, tag_name)
|
58
|
+
"#{parent}/#{name}::#{tag_name}"
|
59
|
+
end
|
60
|
+
|
61
|
+
def node_name(current)
|
62
|
+
"name(#{current})"
|
63
|
+
end
|
64
|
+
|
65
|
+
def where(on, condition)
|
66
|
+
"#{on}[#{condition}]"
|
67
|
+
end
|
68
|
+
|
69
|
+
def attribute(current, name)
|
70
|
+
"#{current}/@#{name}"
|
71
|
+
end
|
72
|
+
|
73
|
+
def equality(one, two)
|
74
|
+
"#{one} = #{two}"
|
75
|
+
end
|
76
|
+
|
77
|
+
def variable(name)
|
78
|
+
"%{#{name}}"
|
79
|
+
end
|
80
|
+
|
81
|
+
def text(current)
|
82
|
+
"#{current}/text()"
|
83
|
+
end
|
84
|
+
|
85
|
+
def normalized_space(current)
|
86
|
+
"normalize-space(#{current})"
|
87
|
+
end
|
88
|
+
|
89
|
+
def literal(node)
|
90
|
+
node
|
91
|
+
end
|
92
|
+
|
93
|
+
def css(current, selector)
|
94
|
+
paths = Nokogiri::CSS.xpath_for(selector).map do |xpath_selector|
|
95
|
+
"#{current}#{xpath_selector}"
|
96
|
+
end
|
97
|
+
union(paths)
|
98
|
+
end
|
99
|
+
|
100
|
+
def union(*expressions)
|
101
|
+
expressions.join(' | ')
|
102
|
+
end
|
103
|
+
|
104
|
+
def anywhere(tag_name)
|
105
|
+
"//#{tag_name}"
|
106
|
+
end
|
107
|
+
|
108
|
+
def contains(current, value)
|
109
|
+
"contains(#{current}, #{value})"
|
110
|
+
end
|
111
|
+
|
112
|
+
def starts_with(current, value)
|
113
|
+
"starts-with(#{current}, #{value})"
|
114
|
+
end
|
115
|
+
|
116
|
+
def and(one, two)
|
117
|
+
"(#{one} and #{two})"
|
118
|
+
end
|
119
|
+
|
120
|
+
def or(one, two)
|
121
|
+
"(#{one} or #{two})"
|
122
|
+
end
|
123
|
+
|
124
|
+
def one_of(current, values)
|
125
|
+
values.map { |value| "#{current} = #{value}" }.join(' or ')
|
126
|
+
end
|
127
|
+
|
128
|
+
def next_sibling(current, element_names)
|
129
|
+
if element_names.length == 1
|
130
|
+
"#{current}/following-sibling::*[1]/self::#{element_names.first}"
|
131
|
+
elsif element_names.length > 1
|
132
|
+
"#{current}/following-sibling::*[1]/self::*[#{element_names.map { |e| "self::#{e}" }.join(" | ")}]"
|
133
|
+
else
|
134
|
+
"#{current}/following-sibling::*[1]/self::*"
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
def inverse(current)
|
139
|
+
"not(#{current})"
|
140
|
+
end
|
141
|
+
|
142
|
+
def string_function(current)
|
143
|
+
"string(#{current})"
|
144
|
+
end
|
145
|
+
end
|
146
|
+
end
|
data/lib/xpath/union.rb
CHANGED
@@ -3,29 +3,27 @@ module XPath
|
|
3
3
|
include Enumerable
|
4
4
|
|
5
5
|
attr_reader :expressions
|
6
|
+
alias_method :arguments, :expressions
|
6
7
|
|
7
8
|
def initialize(*expressions)
|
8
9
|
@expressions = expressions
|
9
10
|
end
|
10
11
|
|
11
|
-
def
|
12
|
-
|
13
|
-
end
|
14
|
-
|
15
|
-
def to_s
|
16
|
-
to_xpaths.join(' | ')
|
12
|
+
def expression
|
13
|
+
:union
|
17
14
|
end
|
18
15
|
|
19
|
-
def
|
20
|
-
|
16
|
+
def each(&block)
|
17
|
+
arguments.each(&block)
|
21
18
|
end
|
22
19
|
|
23
|
-
def
|
24
|
-
|
20
|
+
def method_missing(*args)
|
21
|
+
XPath::Union.new(*arguments.map { |e| e.send(*args) })
|
25
22
|
end
|
26
23
|
|
27
|
-
def
|
28
|
-
|
24
|
+
def to_xpath
|
25
|
+
Renderer.render(self)
|
29
26
|
end
|
27
|
+
alias_method :to_s, :to_xpath
|
30
28
|
end
|
31
29
|
end
|
data/lib/xpath/version.rb
CHANGED
data/spec/fixtures/form.html
CHANGED
@@ -28,7 +28,15 @@
|
|
28
28
|
<input type="submit" title="My submit title" value="submit-with-title" data="title-submit">
|
29
29
|
<input type="submit" title="Exact submit title" value="exact title submit" data="exact-title-submit">
|
30
30
|
<input type="submit" title="Not Exact submit title" value="exact title submit" data="not-exact-title-submit">
|
31
|
-
|
31
|
+
|
32
|
+
<input type="reset" id="reset-with-id" data="id-reset" value="Has ID"/>
|
33
|
+
<input type="reset" value="reset-with-value" data="value-reset"/>
|
34
|
+
<input type="reset" value="not exact value reset" data="not-exact-value-reset"/>
|
35
|
+
<input type="reset" value="exact value reset" data="exact-value-reset"/>
|
36
|
+
<input type="reset" title="My reset title" value="reset-with-title" data="title-reset">
|
37
|
+
<input type="reset" title="Exact reset title" value="exact title reset" data="exact-title-reset">
|
38
|
+
<input type="reset" title="Not Exact reset title" value="exact title reset" data="not-exact-title-reset">
|
39
|
+
|
32
40
|
<input type="button" id="button-with-id" data="id-button" value="Has ID"/>
|
33
41
|
<input type="button" value="button-with-value" data="value-button"/>
|
34
42
|
<input type="button" value="not exact value button" data="not-exact-value-button"/>
|
@@ -46,10 +54,10 @@
|
|
46
54
|
<input type="image" title="Not Exact imgbut title" value="not exact title imgbut" data="not-exact-title-imgbut">
|
47
55
|
<input type="image" title="Exact imgbut title" value="exact title imgbut" data="exact-title-imgbut">
|
48
56
|
|
49
|
-
<button id="btag-with-id" data="id-btag" value="Has ID"
|
50
|
-
<button value="btag-with-value" data="value-btag"
|
51
|
-
<button value="not exact value btag" data="not-exact-value-btag"
|
52
|
-
<button value="exact value btag" data="exact-value-btag"
|
57
|
+
<button id="btag-with-id" data="id-btag" value="Has ID"></button>
|
58
|
+
<button value="btag-with-value" data="value-btag"></button>
|
59
|
+
<button value="not exact value btag" data="not-exact-value-btag"></button>
|
60
|
+
<button value="exact value btag" data="exact-value-btag"></button>
|
53
61
|
|
54
62
|
<button data="text-btag">btag-with-text</button>
|
55
63
|
<button data="not-exact-text-btag">not exact text btag</button>
|
@@ -77,16 +85,30 @@
|
|
77
85
|
<fieldset data="fieldset-legend-span"><legend><span>Span Legend</span></legend></fieldset>
|
78
86
|
<fieldset data="fieldset-fuzzy"><legend>Long legend yo</legend></fieldset>
|
79
87
|
<fieldset data="fieldset-exact"><legend>Long legend</legend></fieldset>
|
88
|
+
<fieldset data="fieldset-outer"><legend>Outer legend</legend>
|
89
|
+
<fieldset data="fieldset-inner"><legend>Inner legend</legend></fieldset>
|
90
|
+
</fieldset>
|
80
91
|
</p>
|
81
92
|
|
82
93
|
<p>
|
83
94
|
<select>
|
84
95
|
<optgroup label="Group A" data="optgroup-a"></optgroup>
|
85
96
|
<optgroup label="Group B" data="optgroup-b"></optgroup>
|
97
|
+
<option data="option-with-text-data">Option with text</option>
|
86
98
|
</select>
|
87
99
|
</p>
|
88
100
|
|
89
|
-
<
|
101
|
+
<h2>Tables</h2>
|
102
|
+
|
103
|
+
<table id="table-with-id" data="table-with-id-data">
|
104
|
+
<tr><td>First</td><td>Second</td></tr>
|
105
|
+
</table>
|
106
|
+
|
107
|
+
<table data="table-with-caption-data">
|
108
|
+
<caption>Table with caption</caption>
|
109
|
+
<tr><td>First</td><td>Second</td></tr>
|
110
|
+
</table>
|
111
|
+
|
90
112
|
<table id="whitespaced-table" data="table-with-whitespace">
|
91
113
|
<tr>
|
92
114
|
<td data="cell-whitespaced">I have
|
@@ -95,7 +117,7 @@
|
|
95
117
|
<td>I don't</td>
|
96
118
|
</tr>
|
97
119
|
</table>
|
98
|
-
|
120
|
+
|
99
121
|
|
100
122
|
<p>
|
101
123
|
<h2>Fields</h2>
|
@@ -103,6 +125,7 @@
|
|
103
125
|
<h4>With id</h4>
|
104
126
|
<input id="input-with-id" value="correct-value" data="input-with-id-data"/>
|
105
127
|
<input type="text" id="input-text-with-id" data="input-text-with-id-data"/>
|
128
|
+
<input type="file" id="input-file-with-id" data="input-file-with-id-data"/>
|
106
129
|
<input type="password" id="input-password-with-id" data="input-password-with-id-data"/>
|
107
130
|
<input type="custom" id="input-custom-with-id" data="input-custom-with-id-data"/>
|
108
131
|
<textarea id="textarea-with-id" data="textarea-with-id-data">Correct value</textarea>
|
@@ -110,10 +133,13 @@
|
|
110
133
|
<input type="submit" id="input-submit-with-id" data="input-submit-with-id-data"/>
|
111
134
|
<input type="image" id="input-image-with-id" data="input-image-with-id-data"/>
|
112
135
|
<input type="hidden" id="input-hidden-with-id" data="input-hidden-with-id-data"/>
|
136
|
+
<input type="checkbox" id="input-checkbox-with-id" data="input-checkbox-with-id-data"/>
|
137
|
+
<input type="radio" id="input-radio-with-id" data="input-radio-with-id-data"/>
|
113
138
|
|
114
139
|
<h4>With name</h4>
|
115
140
|
<input name="input-with-name" data="input-with-name-data"/>
|
116
141
|
<input type="text" name="input-text-with-name" data="input-text-with-name-data"/>
|
142
|
+
<input type="file" name="input-file-with-name" data="input-file-with-name-data"/>
|
117
143
|
<input type="password" name="input-password-with-name" data="input-password-with-name-data"/>
|
118
144
|
<input type="custom" name="input-custom-with-name" data="input-custom-with-name-data"/>
|
119
145
|
<textarea name="textarea-with-name" data="textarea-with-name-data"></textarea>
|
@@ -121,10 +147,21 @@
|
|
121
147
|
<input type="submit" name="input-submit-with-name" data="input-submit-with-name-data"/>
|
122
148
|
<input type="image" name="input-image-with-name" data="input-image-with-name-data"/>
|
123
149
|
<input type="hidden" name="input-hidden-with-name" data="input-hidden-with-name-data"/>
|
150
|
+
<input type="checkbox" name="input-checkbox-with-name" data="input-checkbox-with-name-data"/>
|
151
|
+
<input type="radio" name="input-radio-with-name" data="input-radio-with-name-data"/>
|
152
|
+
|
153
|
+
<h4>With placeholder</h4>
|
154
|
+
<input name="input-with-placeholder" data="input-with-placeholder-data"/>
|
155
|
+
<input type="text" placeholder="input-text-with-placeholder" data="input-text-with-placeholder-data"/>
|
156
|
+
<input type="password" placeholder="input-password-with-placeholder" data="input-password-with-placeholder-data"/>
|
157
|
+
<input type="custom" placeholder="input-custom-with-placeholder" data="input-custom-with-placeholder-data"/>
|
158
|
+
<textarea placeholder="textarea-with-placeholder" data="textarea-with-placeholder-data"></textarea>
|
159
|
+
<input type="hidden" placeholder="input-hidden-with-placeholder" data="input-hidden-with-placeholder-data"/>
|
124
160
|
|
125
161
|
<h4>With referenced label</h4>
|
126
162
|
<label for="input-with-label">Input with label</label><input id="input-with-label" data="input-with-label-data"/>
|
127
163
|
<label for="input-text-with-label">Input text with label</label><input type="text" id="input-text-with-label" data="input-text-with-label-data"/>
|
164
|
+
<label for="input-file-with-label">Input file with label</label><input type="file" id="input-file-with-label" data="input-file-with-label-data"/>
|
128
165
|
<label for="input-password-with-label">Input password with label</label><input type="password" id="input-password-with-label" data="input-password-with-label-data"/>
|
129
166
|
<label for="input-custom-with-label">Input custom with label</label><input type="custom" id="input-custom-with-label" data="input-custom-with-label-data"/>
|
130
167
|
<label for="textarea-with-label">Textarea with label</label><textarea id="textarea-with-label" data="textarea-with-label-data"></textarea>
|
@@ -132,10 +169,13 @@
|
|
132
169
|
<label for="input-submit-with-label">Input submit with label</label><input type="submit" id="input-submit-with-label" data="input-submit-with-label-data"/>
|
133
170
|
<label for="input-image-with-label">Input image with label</label><input type="image" id="input-image-with-label" data="input-image-with-label-data"/>
|
134
171
|
<label for="input-hidden-with-label">Input hidden with label</label><input type="hidden" id="input-hidden-with-label" data="input-hidden-with-label-data"/>
|
172
|
+
<label for="input-checkbox-with-label">Input checkbox with label</label><input type="checkbox" id="input-checkbox-with-label" data="input-checkbox-with-label-data"/>
|
173
|
+
<label for="input-radio-with-label">Input radio with label</label><input type="radio" id="input-radio-with-label" data="input-radio-with-label-data"/>
|
135
174
|
|
136
175
|
<h4>With parent label</h4>
|
137
176
|
<label>Input with parent label<input data="input-with-parent-label-data"/></label>
|
138
177
|
<label>Input text with parent label<input type="text" data="input-text-with-parent-label-data"/></label>
|
178
|
+
<label>Input file with parent label<input type="file" data="input-file-with-parent-label-data"/></label>
|
139
179
|
<label>Input password with parent label<input type="password" data="input-password-with-parent-label-data"/></label>
|
140
180
|
<label>Input custom with parent label<input type="custom" data="input-custom-with-parent-label-data"/></label>
|
141
181
|
<label>Textarea with parent label<textarea data="textarea-with-parent-label-data"></textarea></label>
|
@@ -143,4 +183,6 @@
|
|
143
183
|
<label>Input submit with parent label<input type="submit" data="input-submit-with-parent-label-data"/></label>
|
144
184
|
<label>Input image with parent label<input type="image" data="input-image-with-parent-label-data"/></label>
|
145
185
|
<label>Input hidden with parent label<input type="hidden" data="input-hidden-with-parent-label-data"/></label>
|
186
|
+
<label>Input checkbox with parent label<input type="checkbox" data="input-checkbox-with-parent-label-data"/></label>
|
187
|
+
<label>Input radio with parent label<input type="radio" data="input-radio-with-parent-label-data"/></label>
|
146
188
|
</p>
|