hatemile 2.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/CODE_OF_CONDUCT.md +46 -0
- data/Gemfile +9 -0
- data/LICENSE +202 -0
- data/Rakefile +64 -0
- data/hatemile.gemspec +37 -0
- data/lib/hatemile/accessible_association.rb +62 -0
- data/lib/hatemile/accessible_css.rb +43 -0
- data/lib/hatemile/accessible_display.rb +178 -0
- data/lib/hatemile/accessible_event.rb +95 -0
- data/lib/hatemile/accessible_form.rb +101 -0
- data/lib/hatemile/accessible_navigation.rb +82 -0
- data/lib/hatemile/helper.rb +58 -0
- data/lib/hatemile/implementation/accessible_association_implementation.rb +346 -0
- data/lib/hatemile/implementation/accessible_css_implementation.rb +772 -0
- data/lib/hatemile/implementation/accessible_display_implementation.rb +1362 -0
- data/lib/hatemile/implementation/accessible_event_implementation.rb +278 -0
- data/lib/hatemile/implementation/accessible_form_implementation.rb +386 -0
- data/lib/hatemile/implementation/accessible_navigation_implementation.rb +561 -0
- data/lib/hatemile/util/common_functions.rb +106 -0
- data/lib/hatemile/util/configure.rb +92 -0
- data/lib/hatemile/util/css/rcp/rcp_declaration.rb +77 -0
- data/lib/hatemile/util/css/rcp/rcp_parser.rb +115 -0
- data/lib/hatemile/util/css/rcp/rcp_rule.rb +86 -0
- data/lib/hatemile/util/css/style_sheet_declaration.rb +59 -0
- data/lib/hatemile/util/css/style_sheet_parser.rb +43 -0
- data/lib/hatemile/util/css/style_sheet_rule.rb +73 -0
- data/lib/hatemile/util/html/html_dom_element.rb +234 -0
- data/lib/hatemile/util/html/html_dom_node.rb +131 -0
- data/lib/hatemile/util/html/html_dom_parser.rb +150 -0
- data/lib/hatemile/util/html/html_dom_text_node.rb +43 -0
- data/lib/hatemile/util/html/nokogiri/nokogiri_html_dom_element.rb +302 -0
- data/lib/hatemile/util/html/nokogiri/nokogiri_html_dom_node.rb +112 -0
- data/lib/hatemile/util/html/nokogiri/nokogiri_html_dom_parser.rb +208 -0
- data/lib/hatemile/util/html/nokogiri/nokogiri_html_dom_text_node.rb +83 -0
- data/lib/hatemile/util/id_generator.rb +53 -0
- data/lib/js/common.js +98 -0
- data/lib/js/eventlistener.js +36 -0
- data/lib/js/include.js +292 -0
- data/lib/js/scriptlist_validation_fields.js +13 -0
- data/lib/js/validation.js +205 -0
- data/lib/locale/en-US.yml +388 -0
- data/lib/locale/pt-BR.yml +389 -0
- data/lib/skippers.xml +6 -0
- data/lib/symbols.xml +40 -0
- data/test/locale/en-US.yml +5 -0
- data/test/locale/pt-BR.yml +4 -0
- data/test/test_accessible_association_implementation.rb +258 -0
- data/test/test_accessible_css_implementation.rb +518 -0
- data/test/test_accessible_display_implementation.rb +873 -0
- data/test/test_accessible_form_implementation.rb +283 -0
- data/test/test_accessible_navigation_implementation.rb +228 -0
- data/test/test_common_functions.rb +128 -0
- data/test/test_configure.rb +73 -0
- data/test/test_nokogiri_html_dom_element.rb +586 -0
- data/test/test_nokogiri_html_dom_parser.rb +363 -0
- data/test/test_nokogiri_html_dom_text_node.rb +225 -0
- data/test/test_rcp_declaration.rb +103 -0
- data/test/test_rcp_parser.rb +86 -0
- data/test/test_rcp_rule.rb +89 -0
- metadata +199 -0
@@ -0,0 +1,561 @@
|
|
1
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
2
|
+
# you may not use this file except in compliance with the License.
|
3
|
+
# You may obtain a copy of the License at
|
4
|
+
#
|
5
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
6
|
+
#
|
7
|
+
# Unless required by applicable law or agreed to in writing, software
|
8
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
9
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
10
|
+
# See the License for the specific language governing permissions and
|
11
|
+
# limitations under the License.
|
12
|
+
|
13
|
+
require 'rexml/document'
|
14
|
+
require File.join(File.dirname(File.dirname(__FILE__)), 'accessible_navigation')
|
15
|
+
require File.join(File.dirname(File.dirname(__FILE__)), 'helper')
|
16
|
+
require File.join(
|
17
|
+
File.dirname(File.dirname(__FILE__)),
|
18
|
+
'util',
|
19
|
+
'common_functions'
|
20
|
+
)
|
21
|
+
require File.join(File.dirname(File.dirname(__FILE__)), 'util', 'configure')
|
22
|
+
require File.join(File.dirname(File.dirname(__FILE__)), 'util', 'id_generator')
|
23
|
+
require File.join(
|
24
|
+
File.dirname(File.dirname(__FILE__)),
|
25
|
+
'util',
|
26
|
+
'html',
|
27
|
+
'html_dom_parser'
|
28
|
+
)
|
29
|
+
|
30
|
+
##
|
31
|
+
# The Hatemile module contains the interfaces with the acessibility solutions.
|
32
|
+
module Hatemile
|
33
|
+
##
|
34
|
+
# The Hatemile::Implementation module contains the official implementation of
|
35
|
+
# interfaces solutions.
|
36
|
+
module Implementation
|
37
|
+
##
|
38
|
+
# The AccessibleNavigationImplementation class is official implementation of
|
39
|
+
# AccessibleNavigation interface.
|
40
|
+
class AccessibleNavigationImplementation < AccessibleNavigation
|
41
|
+
public_class_method :new
|
42
|
+
|
43
|
+
##
|
44
|
+
# The id of list element that contains the skippers.
|
45
|
+
ID_CONTAINER_SKIPPERS = 'container-skippers'.freeze
|
46
|
+
|
47
|
+
##
|
48
|
+
# The id of list element that contains the links for the headings, before
|
49
|
+
# the whole content of page.
|
50
|
+
ID_CONTAINER_HEADING_BEFORE = 'container-heading-before'.freeze
|
51
|
+
|
52
|
+
##
|
53
|
+
# The id of list element that contains the links for the headings, after
|
54
|
+
# the whole content of page.
|
55
|
+
ID_CONTAINER_HEADING_AFTER = 'container-heading-after'.freeze
|
56
|
+
|
57
|
+
##
|
58
|
+
# The HTML class of text of description of container of heading links.
|
59
|
+
CLASS_TEXT_HEADING = 'text-heading'.freeze
|
60
|
+
|
61
|
+
##
|
62
|
+
# The HTML class of anchor of skipper.
|
63
|
+
CLASS_SKIPPER_ANCHOR = 'skipper-anchor'.freeze
|
64
|
+
|
65
|
+
##
|
66
|
+
# The HTML class of anchor of heading link.
|
67
|
+
CLASS_HEADING_ANCHOR = 'heading-anchor'.freeze
|
68
|
+
|
69
|
+
##
|
70
|
+
# The HTML class of force link, before it.
|
71
|
+
CLASS_FORCE_LINK_BEFORE = 'force-link-before'.freeze
|
72
|
+
|
73
|
+
##
|
74
|
+
# The HTML class of force link, after it.
|
75
|
+
CLASS_FORCE_LINK_AFTER = 'force-link-after'.freeze
|
76
|
+
|
77
|
+
##
|
78
|
+
# The name of attribute that links the anchor of skipper with the element.
|
79
|
+
DATA_ANCHOR_FOR = 'data-anchorfor'.freeze
|
80
|
+
|
81
|
+
##
|
82
|
+
# The name of attribute that links the anchor of heading link with
|
83
|
+
# heading.
|
84
|
+
DATA_HEADING_ANCHOR_FOR = 'data-headinganchorfor'.freeze
|
85
|
+
|
86
|
+
##
|
87
|
+
# The name of attribute that indicates the level of heading of link.
|
88
|
+
DATA_HEADING_LEVEL = 'data-headinglevel'.freeze
|
89
|
+
|
90
|
+
##
|
91
|
+
# The name of attribute that link the anchor of long description with the
|
92
|
+
# image.
|
93
|
+
DATA_ATTRIBUTE_LONG_DESCRIPTION_OF =
|
94
|
+
'data-attributelongdescriptionof'.freeze
|
95
|
+
|
96
|
+
protected
|
97
|
+
|
98
|
+
##
|
99
|
+
# Generate the list of skippers of page.
|
100
|
+
#
|
101
|
+
# @return [Hatemile::Util::Html::HTMLDOMElement] The list of skippers of
|
102
|
+
# page.
|
103
|
+
def generate_list_skippers
|
104
|
+
container = @parser.find("##{ID_CONTAINER_SKIPPERS}").first_result
|
105
|
+
html_list = nil
|
106
|
+
if container.nil?
|
107
|
+
local = @parser.find('body').first_result
|
108
|
+
unless local.nil?
|
109
|
+
container = @parser.create_element('div')
|
110
|
+
container.set_attribute('id', ID_CONTAINER_SKIPPERS)
|
111
|
+
local.prepend_element(container)
|
112
|
+
end
|
113
|
+
end
|
114
|
+
unless container.nil?
|
115
|
+
html_list = @parser.find(container).find_children('ul').first_result
|
116
|
+
if html_list.nil?
|
117
|
+
html_list = @parser.create_element('ul')
|
118
|
+
container.append_element(html_list)
|
119
|
+
end
|
120
|
+
end
|
121
|
+
@list_skippers_added = true
|
122
|
+
|
123
|
+
html_list
|
124
|
+
end
|
125
|
+
|
126
|
+
##
|
127
|
+
# Generate the list of heading links of page.
|
128
|
+
def generate_list_heading
|
129
|
+
local = @parser.find('body').first_result
|
130
|
+
|
131
|
+
return if local.nil?
|
132
|
+
|
133
|
+
container_before = @parser.find(
|
134
|
+
"##{ID_CONTAINER_HEADING_BEFORE}"
|
135
|
+
).first_result
|
136
|
+
if container_before.nil? && !@elements_heading_before.empty?
|
137
|
+
container_before = @parser.create_element('div')
|
138
|
+
container_before.set_attribute('id', ID_CONTAINER_HEADING_BEFORE)
|
139
|
+
|
140
|
+
text_container_before = @parser.create_element('span')
|
141
|
+
text_container_before.set_attribute('class', CLASS_TEXT_HEADING)
|
142
|
+
text_container_before.append_text(@elements_heading_before)
|
143
|
+
|
144
|
+
container_before.append_element(text_container_before)
|
145
|
+
local.prepend_element(container_before)
|
146
|
+
end
|
147
|
+
unless container_before.nil?
|
148
|
+
@list_heading_before = @parser.find(
|
149
|
+
container_before
|
150
|
+
).find_children('ol').first_result
|
151
|
+
if @list_heading_before.nil?
|
152
|
+
@list_heading_before = @parser.create_element('ol')
|
153
|
+
container_before.append_element(@list_heading_before)
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
157
|
+
container_after = @parser.find(
|
158
|
+
"##{ID_CONTAINER_HEADING_AFTER}"
|
159
|
+
).first_result
|
160
|
+
if container_after.nil? && !@elements_heading_after.empty?
|
161
|
+
container_after = @parser.create_element('div')
|
162
|
+
container_after.set_attribute('id', ID_CONTAINER_HEADING_AFTER)
|
163
|
+
|
164
|
+
text_container_after = @parser.create_element('span')
|
165
|
+
text_container_after.set_attribute('class', CLASS_TEXT_HEADING)
|
166
|
+
text_container_after.append_text(@elements_heading_after)
|
167
|
+
|
168
|
+
container_after.append_element(text_container_after)
|
169
|
+
local.append_element(container_after)
|
170
|
+
end
|
171
|
+
unless container_after.nil?
|
172
|
+
@list_heading_after = @parser.find(
|
173
|
+
container_after
|
174
|
+
).find_children('ol').first_result
|
175
|
+
if @list_heading_after.nil?
|
176
|
+
@list_heading_after = @parser.create_element('ol')
|
177
|
+
container_after.append_element(@list_heading_after)
|
178
|
+
end
|
179
|
+
end
|
180
|
+
|
181
|
+
@list_heading_added = true
|
182
|
+
end
|
183
|
+
|
184
|
+
##
|
185
|
+
# Returns the level of heading.
|
186
|
+
#
|
187
|
+
# @param element [Hatemile::Util::Html::HTMLDOMElement] The heading.
|
188
|
+
# @return [Integer] The level of heading.
|
189
|
+
def get_heading_level(element)
|
190
|
+
tag = element.get_tag_name
|
191
|
+
return 1 if tag == 'H1'
|
192
|
+
return 2 if tag == 'H2'
|
193
|
+
return 3 if tag == 'H3'
|
194
|
+
return 4 if tag == 'H4'
|
195
|
+
return 5 if tag == 'H5'
|
196
|
+
return 6 if tag == 'H6'
|
197
|
+
-1
|
198
|
+
end
|
199
|
+
|
200
|
+
##
|
201
|
+
# Check that the headings of page are sintatic correct.
|
202
|
+
#
|
203
|
+
# @return [Boolean] True if the headings of page are sintatic correct or
|
204
|
+
# false if not.
|
205
|
+
def valid_heading?
|
206
|
+
elements = @parser.find('h1,h2,h3,h4,h5,h6').list_results
|
207
|
+
last_level = 0
|
208
|
+
count_main_heading = 0
|
209
|
+
@validate_heading = true
|
210
|
+
elements.each do |element|
|
211
|
+
level = get_heading_level(element)
|
212
|
+
if level == 1
|
213
|
+
return false if count_main_heading == 1
|
214
|
+
count_main_heading = 1
|
215
|
+
end
|
216
|
+
return false if (level - last_level) > 1
|
217
|
+
last_level = level
|
218
|
+
end
|
219
|
+
true
|
220
|
+
end
|
221
|
+
|
222
|
+
##
|
223
|
+
# Generate an anchor for the element.
|
224
|
+
#
|
225
|
+
# @param element [Hatemile::Util::Html::HTMLDOMElement] The element.
|
226
|
+
# @param data_attribute [String] The name of attribute that links the
|
227
|
+
# element with the anchor.
|
228
|
+
# @param anchor_class [String] The HTML class of anchor.
|
229
|
+
# @return [Hatemile::Util::Html::HTMLDOMElement] The anchor.
|
230
|
+
def generate_anchor_for(element, data_attribute, anchor_class)
|
231
|
+
@id_generator.generate_id(element)
|
232
|
+
anchor = nil
|
233
|
+
if @parser.find(
|
234
|
+
"[#{data_attribute}=\"#{element.get_attribute('id')}\"]"
|
235
|
+
).first_result.nil?
|
236
|
+
if element.get_tag_name == 'A'
|
237
|
+
anchor = element
|
238
|
+
else
|
239
|
+
anchor = @parser.create_element('a')
|
240
|
+
@id_generator.generate_id(anchor)
|
241
|
+
anchor.set_attribute('class', anchor_class)
|
242
|
+
element.insert_before(anchor)
|
243
|
+
end
|
244
|
+
unless anchor.has_attribute?('name')
|
245
|
+
anchor.set_attribute('name', anchor.get_attribute('id'))
|
246
|
+
end
|
247
|
+
anchor.set_attribute(data_attribute, element.get_attribute('id'))
|
248
|
+
end
|
249
|
+
anchor
|
250
|
+
end
|
251
|
+
|
252
|
+
##
|
253
|
+
# Replace the shortcut of elements, that has the shortcut passed.
|
254
|
+
#
|
255
|
+
# @param shortcut [String] The shortcut.
|
256
|
+
# @return [void]
|
257
|
+
def free_shortcut(shortcut)
|
258
|
+
found = false
|
259
|
+
alpha_numbers = '1234567890abcdefghijklmnopqrstuvwxyz'
|
260
|
+
elements = @parser.find('[accesskey]').list_results
|
261
|
+
elements.each do |element|
|
262
|
+
shortcuts = element.get_attribute('accesskey').downcase
|
263
|
+
|
264
|
+
unless Hatemile::Util::CommonFunctions.in_list?(shortcuts, shortcut)
|
265
|
+
next
|
266
|
+
end
|
267
|
+
|
268
|
+
(0..alpha_numbers.length - 1).each do |i|
|
269
|
+
key = alpha_numbers[i, i + 1]
|
270
|
+
found = true
|
271
|
+
elements.each do |element_with_shortcuts|
|
272
|
+
shortcuts = element_with_shortcuts.get_attribute(
|
273
|
+
'accesskey'
|
274
|
+
).downcase
|
275
|
+
|
276
|
+
unless Hatemile::Util::CommonFunctions.in_list?(shortcuts, key)
|
277
|
+
next
|
278
|
+
end
|
279
|
+
|
280
|
+
element.set_attribute('accesskey', key)
|
281
|
+
found = false
|
282
|
+
break
|
283
|
+
end
|
284
|
+
break if found
|
285
|
+
end
|
286
|
+
break if found
|
287
|
+
end
|
288
|
+
end
|
289
|
+
|
290
|
+
##
|
291
|
+
# Returns the skippers of configuration.
|
292
|
+
#
|
293
|
+
#
|
294
|
+
# @param configure [Hatemile::Util::Configure] The configuration of
|
295
|
+
# HaTeMiLe.
|
296
|
+
# @param file_name [String] The file path of skippers configuration.
|
297
|
+
# @return [Array<Hash>] The skippers of configuration.
|
298
|
+
def get_skippers(configure, file_name)
|
299
|
+
skippers = []
|
300
|
+
if file_name.nil?
|
301
|
+
file_name = File.join(
|
302
|
+
File.dirname(File.dirname(File.dirname(__FILE__))),
|
303
|
+
'skippers.xml'
|
304
|
+
)
|
305
|
+
end
|
306
|
+
document = REXML::Document.new(File.read(file_name))
|
307
|
+
document.elements.each('skippers/skipper') do |skipper_xml|
|
308
|
+
skipper = {}
|
309
|
+
skipper[:selector] = skipper_xml.attribute('selector').value
|
310
|
+
skipper[:description] = configure.get_parameter(
|
311
|
+
skipper_xml.attribute('description').value
|
312
|
+
)
|
313
|
+
skipper[:shortcut] = skipper_xml.attribute('shortcut').value
|
314
|
+
skippers.push(skipper)
|
315
|
+
end
|
316
|
+
skippers
|
317
|
+
end
|
318
|
+
|
319
|
+
public
|
320
|
+
|
321
|
+
##
|
322
|
+
# Initializes a new object that manipulate the accessibility of the
|
323
|
+
# navigation of parser.
|
324
|
+
#
|
325
|
+
# @param parser [Hatemile::Util::Html::HTMLDOMParser] The HTML parser.
|
326
|
+
# @param configure [Hatemile::Util::Configure] The configuration of
|
327
|
+
# HaTeMiLe.
|
328
|
+
# @param skipper_file_name [String] The file path of skippers
|
329
|
+
# configuration.
|
330
|
+
def initialize(parser, configure, skipper_file_name = nil)
|
331
|
+
Hatemile::Helper.require_not_nil(parser, configure)
|
332
|
+
Hatemile::Helper.require_valid_type(
|
333
|
+
parser,
|
334
|
+
Hatemile::Util::Html::HTMLDOMParser
|
335
|
+
)
|
336
|
+
Hatemile::Helper.require_valid_type(
|
337
|
+
configure,
|
338
|
+
Hatemile::Util::Configure
|
339
|
+
)
|
340
|
+
Hatemile::Helper.require_valid_type(skipper_file_name, String)
|
341
|
+
|
342
|
+
@parser = parser
|
343
|
+
@id_generator = Hatemile::Util::IDGenerator.new('navigation')
|
344
|
+
@elements_heading_before = configure.get_parameter(
|
345
|
+
'elements-heading-before'
|
346
|
+
)
|
347
|
+
@elements_heading_after = configure.get_parameter(
|
348
|
+
'elements-heading-after'
|
349
|
+
)
|
350
|
+
@attribute_long_description_prefix_before = configure.get_parameter(
|
351
|
+
'attribute-longdescription-prefix-before'
|
352
|
+
)
|
353
|
+
@attribute_long_description_suffix_before = configure.get_parameter(
|
354
|
+
'attribute-longdescription-suffix-before'
|
355
|
+
)
|
356
|
+
@attribute_long_description_prefix_after = configure.get_parameter(
|
357
|
+
'attribute-longdescription-prefix-after'
|
358
|
+
)
|
359
|
+
@attribute_long_description_suffix_after = configure.get_parameter(
|
360
|
+
'attribute-longdescription-suffix-after'
|
361
|
+
)
|
362
|
+
@skippers = get_skippers(configure, skipper_file_name)
|
363
|
+
@list_skippers_added = false
|
364
|
+
@list_heading_added = false
|
365
|
+
@validate_heading = false
|
366
|
+
@valid_heading = false
|
367
|
+
@list_skippers = nil
|
368
|
+
@list_heading_before = nil
|
369
|
+
@list_heading_after = nil
|
370
|
+
end
|
371
|
+
|
372
|
+
##
|
373
|
+
# @see Hatemile::AccessibleNavigation#provide_navigation_by_skipper
|
374
|
+
def provide_navigation_by_skipper(element)
|
375
|
+
skipper = nil
|
376
|
+
@skippers.each do |auxiliar_skipper|
|
377
|
+
elements = @parser.find(auxiliar_skipper[:selector]).list_results
|
378
|
+
if elements.include?(element)
|
379
|
+
skipper = auxiliar_skipper
|
380
|
+
break
|
381
|
+
end
|
382
|
+
end
|
383
|
+
|
384
|
+
return if skipper.nil?
|
385
|
+
|
386
|
+
@list_skippers = generate_list_skippers unless @list_skippers_added
|
387
|
+
|
388
|
+
return if @list_skippers.nil?
|
389
|
+
|
390
|
+
anchor = generate_anchor_for(
|
391
|
+
element,
|
392
|
+
DATA_ANCHOR_FOR,
|
393
|
+
CLASS_SKIPPER_ANCHOR
|
394
|
+
)
|
395
|
+
|
396
|
+
return if anchor.nil?
|
397
|
+
|
398
|
+
item_link = @parser.create_element('li')
|
399
|
+
link = @parser.create_element('a')
|
400
|
+
link.set_attribute('href', "##{anchor.get_attribute('name')}")
|
401
|
+
link.append_text(skipper[:description])
|
402
|
+
|
403
|
+
free_shortcut(skipper[:shortcut])
|
404
|
+
link.set_attribute('accesskey', skipper[:shortcut])
|
405
|
+
|
406
|
+
@id_generator.generate_id(link)
|
407
|
+
|
408
|
+
item_link.append_element(link)
|
409
|
+
@list_skippers.append_element(item_link)
|
410
|
+
end
|
411
|
+
|
412
|
+
##
|
413
|
+
# @see Hatemile::AccessibleNavigation#provide_navigation_by_all_skippers
|
414
|
+
def provide_navigation_by_all_skippers
|
415
|
+
@skippers.each do |skipper|
|
416
|
+
elements = @parser.find(skipper[:selector]).list_results
|
417
|
+
elements.each do |element|
|
418
|
+
next unless Hatemile::Util::CommonFunctions.is_valid_element?(
|
419
|
+
element
|
420
|
+
)
|
421
|
+
|
422
|
+
provide_navigation_by_skipper(element)
|
423
|
+
end
|
424
|
+
end
|
425
|
+
end
|
426
|
+
|
427
|
+
##
|
428
|
+
# @see Hatemile::AccessibleNavigation#provide_navigation_by_heading
|
429
|
+
def provide_navigation_by_heading(heading)
|
430
|
+
@valid_heading = valid_heading? unless @validate_heading
|
431
|
+
|
432
|
+
return unless @valid_heading
|
433
|
+
|
434
|
+
anchor = generate_anchor_for(
|
435
|
+
heading,
|
436
|
+
DATA_HEADING_ANCHOR_FOR,
|
437
|
+
CLASS_HEADING_ANCHOR
|
438
|
+
)
|
439
|
+
|
440
|
+
return if anchor.nil?
|
441
|
+
|
442
|
+
generate_list_heading unless @list_heading_added
|
443
|
+
list_before = nil
|
444
|
+
list_after = nil
|
445
|
+
level = get_heading_level(heading)
|
446
|
+
if level == 1
|
447
|
+
list_before = @list_heading_before
|
448
|
+
list_after = @list_heading_after
|
449
|
+
else
|
450
|
+
selector = "[#{DATA_HEADING_LEVEL}=\"#{level - 1}\"]"
|
451
|
+
unless @list_heading_before.nil?
|
452
|
+
super_item_before = @parser.find(
|
453
|
+
@list_heading_before
|
454
|
+
).find_descendants(selector).last_result
|
455
|
+
end
|
456
|
+
unless super_item_before.nil?
|
457
|
+
list_before = @parser.find(
|
458
|
+
super_item_before
|
459
|
+
).find_children('ol').first_result
|
460
|
+
if list_before.nil?
|
461
|
+
list_before = @parser.create_element('ol')
|
462
|
+
super_item_before.append_element(list_before)
|
463
|
+
end
|
464
|
+
end
|
465
|
+
unless @list_heading_after.nil?
|
466
|
+
super_item_after = @parser.find(
|
467
|
+
@list_heading_after
|
468
|
+
).find_descendants(selector).last_result
|
469
|
+
end
|
470
|
+
unless super_item_after.nil?
|
471
|
+
list_after = @parser.find(
|
472
|
+
super_item_after
|
473
|
+
).find_children('ol').first_result
|
474
|
+
if list_after.nil?
|
475
|
+
list_after = @parser.create_element('ol')
|
476
|
+
super_item_after.append_element(list_after)
|
477
|
+
end
|
478
|
+
end
|
479
|
+
end
|
480
|
+
|
481
|
+
item = @parser.create_element('li')
|
482
|
+
item.set_attribute(DATA_HEADING_LEVEL, level.to_s)
|
483
|
+
|
484
|
+
link = @parser.create_element('a')
|
485
|
+
link.set_attribute('href', "##{anchor.get_attribute('name')}")
|
486
|
+
link.append_text(heading.get_text_content)
|
487
|
+
item.append_element(link)
|
488
|
+
|
489
|
+
list_before.append_element(item.clone_element) unless list_before.nil?
|
490
|
+
list_after.append_element(item.clone_element) unless list_after.nil?
|
491
|
+
end
|
492
|
+
|
493
|
+
##
|
494
|
+
# @see Hatemile::AccessibleNavigation#provide_navigation_by_all_headings
|
495
|
+
def provide_navigation_by_all_headings
|
496
|
+
headings = @parser.find('h1,h2,h3,h4,h5,h6').list_results
|
497
|
+
headings.each do |heading|
|
498
|
+
if Hatemile::Util::CommonFunctions.is_valid_element?(heading)
|
499
|
+
provide_navigation_by_heading(heading)
|
500
|
+
end
|
501
|
+
end
|
502
|
+
end
|
503
|
+
|
504
|
+
##
|
505
|
+
# @see Hatemile::AccessibleNavigation#provide_navigation_to_long_description
|
506
|
+
def provide_navigation_to_long_description(image)
|
507
|
+
unless image.has_attribute?('longdesc') && image.has_attribute?('alt')
|
508
|
+
return
|
509
|
+
end
|
510
|
+
|
511
|
+
@id_generator.generate_id(image)
|
512
|
+
id = image.get_attribute('id')
|
513
|
+
|
514
|
+
selector = "[#{DATA_ATTRIBUTE_LONG_DESCRIPTION_OF}=\"#{id}\"]"
|
515
|
+
return unless @parser.find(selector).first_result.nil?
|
516
|
+
|
517
|
+
alternative_text = image.get_attribute('alt').gsub(
|
518
|
+
/[ \n\t\r]+/,
|
519
|
+
' '
|
520
|
+
).strip
|
521
|
+
unless @attribute_long_description_prefix_before.empty? &&
|
522
|
+
@attribute_long_description_suffix_before.empty?
|
523
|
+
before_text = "#{@attribute_long_description_prefix_before}" \
|
524
|
+
"#{alternative_text}" \
|
525
|
+
"#{@attribute_long_description_suffix_before}"
|
526
|
+
before_anchor = @parser.create_element('a')
|
527
|
+
before_anchor.set_attribute('href', image.get_attribute('longdesc'))
|
528
|
+
before_anchor.set_attribute('target', '_blank')
|
529
|
+
before_anchor.set_attribute(DATA_ATTRIBUTE_LONG_DESCRIPTION_OF, id)
|
530
|
+
before_anchor.set_attribute('class', CLASS_FORCE_LINK_BEFORE)
|
531
|
+
before_anchor.append_text(before_text)
|
532
|
+
image.insert_after(before_anchor)
|
533
|
+
end
|
534
|
+
unless @attribute_long_description_prefix_after.empty? &&
|
535
|
+
@attribute_long_description_suffix_after.empty?
|
536
|
+
after_text = "#{@attribute_long_description_prefix_after}" \
|
537
|
+
"#{alternative_text}" \
|
538
|
+
"#{@attribute_long_description_suffix_after}"
|
539
|
+
after_anchor = @parser.create_element('a')
|
540
|
+
after_anchor.set_attribute('href', image.get_attribute('longdesc'))
|
541
|
+
after_anchor.set_attribute('target', '_blank')
|
542
|
+
after_anchor.set_attribute(DATA_ATTRIBUTE_LONG_DESCRIPTION_OF, id)
|
543
|
+
after_anchor.set_attribute('class', CLASS_FORCE_LINK_AFTER)
|
544
|
+
after_anchor.append_text(after_text)
|
545
|
+
image.insert_after(after_anchor)
|
546
|
+
end
|
547
|
+
end
|
548
|
+
|
549
|
+
##
|
550
|
+
# @see Hatemile::AccessibleNavigation#provide_navigation_to_all_long_descriptions
|
551
|
+
def provide_navigation_to_all_long_descriptions
|
552
|
+
images = @parser.find('[alt][longdesc]').list_results
|
553
|
+
images.each do |image|
|
554
|
+
if Hatemile::Util::CommonFunctions.is_valid_element?(image)
|
555
|
+
provide_navigation_to_long_description(image)
|
556
|
+
end
|
557
|
+
end
|
558
|
+
end
|
559
|
+
end
|
560
|
+
end
|
561
|
+
end
|