[Fixes #10597] Make course modules section more accessible

Issues:
* Screen readers cannot detect the indent, edit or delete buttons when navigating by keyboard.
* On the Edit Module Settings/Add Module box, none of the fields or dropdowns have labels. Additionally, the "Before students can view this module: No prerequisites defined" and "This module is complete when: You'll need to add items before you can specify how a user will complete this module No requirements defined" text is no detected by a screen reader.
* On the Add Item to Module box the text in the combo box is not detected. The screen reader can detect the dropdown lists but none of them are labeled.
* When creating a new item, the field to enter a name for the item also has no label.

Changes:
* Adds labels to all fields on 'add module' and 'add module item' dialog boxes
* Enables tab access to hidden hover icons on index for modules and module items by making elements visible but off screen (matching behavior of 'assignments' section)
* Adds alt text to icons that didn't used to have it
* Adds tabindex to non-label text that was being bypassed by JAWS
* Fixes unrelated bug - module icon controls not linked to hover state
* A few unrelated JS/CSS refactors
* Tweaks selenium tests to use new with_focus_icons_visible helper to show off-screen icons

Change-Id: Idb8151ef97c726b1f56d98270b6eb430f4dec5d4
Reviewed-on: https://gerrit.instructure.com/14322
Tested-by: Jenkins <jenkins@instructure.com>
Reviewed-by: Zach Pendleton <zachp@instructure.com>
Reviewed-by: Clare Hetherington <clare@instructure.com>
This commit is contained in:
Dave Donahue 2012-10-10 22:33:56 -04:00
parent be6093f9cd
commit 181d300e2d
9 changed files with 179 additions and 110 deletions

View File

@ -4,6 +4,14 @@ $context_module_bg_color: #f2f3f4
#context_modules
min-width: 20px
.hidden_tabbable
position: relative
left: -10000px
&:focus, &.focus
left: auto !important
.context_module
border:
top: 1px dotted $context_module_border_color
@ -16,8 +24,11 @@ $context_module_bg_color: #f2f3f4
+opacity(0.5)
&:hover
+opacity(1)
.reorder_module_link, .move_item_link
padding-left: 2px
.move_item_link
cursor: move
.links
padding-right: 10px
text-align: right
@ -29,17 +40,17 @@ $context_module_bg_color: #f2f3f4
color: #323232
.links
float: right
&:hover .hidden_tabbable
left: auto !important
.completion_status .complete_icon,
.locked_icon,
.progression_details_link,
.header .links,
.add_module_item_link,
.manage_module,
.delete_prerequisite_link,
.expand_module_link,
.collapsed,
.context_module_item .links
.collapsed
display: none
&.editable_context_module
.progression_details_link,
@ -239,10 +250,7 @@ $context_module_bg_color: #f2f3f4
font-size: 0.9em
.locked_title
display: none
width: 100%
.move_item_link
visibility: hidden
width: 100%
.locked_module &
.title
display: none
@ -261,14 +269,13 @@ $context_module_bg_color: #f2f3f4
font-weight: bold
color: #888
.links
visibility: hidden
width: 80px
vertical-align: top
padding-top: 2px
&.context_module_item_hover, &:hover
background-color: darken($context_module_bg_color, 2.5%)
.move_item_link, .links, .links a
visibility: visible
.hidden_tabbable
left: auto !important
td.points_possible_display, td.due_date_display
padding-top: 5px
@ -315,12 +322,8 @@ $context_module_bg_color: #f2f3f4
.context_module .context_module_items
border-collapse: collapse
.context_module_item
.move_item_link
display: none
.completion_status
display: inline
.links a
display: none
&.manageable
.context_module_item
.move_item_link

View File

@ -12,6 +12,7 @@ You can also sequence modules by defining criteria and prerequisites for each mo
To start organizing your course into modules, click the "%{button}" button to the right.
TEXT
#'
%>
<% else %>
<p><%= t('help.no_modules', %{No modules have been defined for this course.}) %></p>
@ -36,7 +37,7 @@ TEXT
<tr>
<td>
<div class="module_name">
<%= before_label('module_name', %{Name}) %>
<%= f.label :name, before_label('module_name', %{Name}) %>
</div>
</td><td>
<div class="module_name">
@ -45,21 +46,22 @@ TEXT
</td>
</tr><tr>
<td colspan="2">
<input type="checkbox" id="unlock_module_at"/>
<label for="unlock_module_at"><%= t('#labels.lock_module_until', %{lock module until a given date}) %></label>
<%- label = t("#labels.lock_module_until", %{lock module until a given date}) %>
<input type="checkbox" id="unlock_module_at" title="<%= label %>"/>
<label for="unlock_module_at"><%= label %></label>
</td>
</tr><tr class="unlock_module_at_details">
<td>
<%= before_label('unlock_at', %{Unlock At}) %>
<%= f.label :unlock_at, before_label('unlock_at', %{Unlock At}) %>
</td><td>
<%= f.text_field :unlock_at, :class => "datetime_field", :style => "width: 125px;" %>
</td>
</tr><tr>
<td colspan="2">
<div class="prerequisites_entry">
<b><%= before_label('modules.before_students_view', %{Before students can view this module}) %></b>
<b tabindex="0"><%= before_label('modules.before_students_view', %{Before students can view this module}) %></b>
<div style="margin: 2px 10px 5px 20px;" class="prerequisites_list">
<div class="no_prerequisites_message"><%= t('no_preprequisites', %{No prerequisites defined}) %></div>
<div class="no_prerequisites_message" tabindex="0"><%= t('no_preprequisites', %{No prerequisites defined}) %></div>
<div class="criteria_list" style="display: none;">
</div>
<div id="criterion_blank" class="criterion" style="display: none;">

View File

@ -7,7 +7,7 @@
<div class="context_module <%= 'editable_context_module' if editable %>" id="context_module_<%= context_module ? context_module.id : "blank" %>" style="<%= hidden unless context_module %>">
<a name="module_<%= context_module.id if context_module %>"></a>
<div class="header">
<span class="reorder_module_link" title="<%= t('reorder_modules', %{Drag to reorder modules}) %>" style="cursor: move; <%= 'hidden' unless @modules.length > 1 %>"><%= image_tag "move.png", :alt => t('reorder_modules', 'Drag to reorder modules') %></span>
<span class="reorder_module_link" title="<%= t('reorder_modules', %{Drag to reorder modules}) %>" style="cursor: move; <%= 'hidden' unless @modules.length > 1 %>"><%= image_tag "move.png", :alt => t('reorder_modules', 'Drag to reorder modules'), :tabindex => '0', :class => 'hidden_tabbable' %></span>
<span class="completion_status" style="<%= "visibility: hidden;" if !context_module || (context_module.completion_requirements || []).empty? %>">
<%= image_tag "pass.png", :alt => t('images.alt.complete', "done"), :title => t('images.title.complete', "Module Completed"), :class => "complete_icon" %>
<%= image_tag "blank.png", :alt => t('images.alt.incomplete', "incomplete"), :title => t('images.title.incomplete', "Module Incomplete"), :class => "incomplete_icon" %>
@ -19,8 +19,8 @@
<span class="id" style="display: none;"><%= context_module ? context_module.id : nbsp %></span>
<span class="unlock_at" style="display: none;"><%= datetime_string(context_module.try_rescue(:unlock_at)) || nbsp %></span>
<a href="<%= context_url(@context, :context_url) %>/modules/<%= context_module ? context_module.id : "{{ id }}" %>" class="edit_module_link edit_link no-hover" title="<%= t('links.title.edit_module', %{Edit module settings}) %>"><%= image_tag "edit.png" %></a>
<a href="<%= context_url(@context, :context_url) %>/modules/<%= context_module ? context_module.id : "{{ id }}" %>" class="delete_module_link delete_link no-hover" title="<%= t('links.title.delete_module', %{Delete this module}) %>"><%= image_tag "delete.png" %></a>
<a href="<%= context_url(@context, :context_url) %>/modules/<%= context_module ? context_module.id : "{{ id }}" %>" class="edit_module_link edit_link no-hover hidden_tabbable" title="<%= t('links.title.edit_module', %{Edit module settings}) %>"><%= image_tag "edit.png" %></a>
<a href="<%= context_url(@context, :context_url) %>/modules/<%= context_module ? context_module.id : "{{ id }}" %>" class="delete_module_link delete_link no-hover hidden_tabbable" title="<%= t('links.title.delete_module', %{Delete this module}) %>"><%= image_tag "delete.png" %></a>
</div>
<div class="clear"></div>
<div style="display: none;">

View File

@ -5,10 +5,10 @@
'must_view' => image_tag("preview_dim.png", :class => "image not_blank", :alt => t('images.alt.must_view', "must view"), :title => t('images.title.must_view', "Students must view this item before the module is considered complete"), :style => "vertical-align: top; padding-top: 2px;"),
'must_contribute' => image_tag("text_entry_dim.png", :class => "image not_blank", :alt => t('images.alt.must_contribute', "must contribute"), :title => t('images.title.must_contribute', "Students must contribute to this item before the module is considered complete"), :style => "vertical-align: top; padding-top: 2px;"),
'must_submit' => image_tag("text_entry_dim.png", :class => "image not_blank", :alt => t('images.alt.must_submit', "must submit"), :title => t('images.title.must_submit', "Students must submit this assignment before the module is considered complete"), :style => "vertical-align: top; padding-top: 2px;"),
'indent' => image_tag('indent_thin.png'),
'outdent' => image_tag('outdent_thin.png'),
'edit' => image_tag('edit.png'),
'delete' => image_tag('delete_circle.png'),
'indent' => image_tag('indent_thin.png', :alt => t('images.alt.indent', 'indent')),
'outdent' => image_tag('outdent_thin.png', :alt => t('images.alt.outdent', 'outdent')),
'edit' => image_tag('edit.png', :alt => t('images.alt.edit', 'edit')),
'delete' => image_tag('delete_circle.png', :alt => t('images.alt.delete', 'delete')),
'other' => image_tag("blank.png", :class => "image", :alt => '')
}
%>
@ -19,7 +19,10 @@
<tr>
<td class="module_item_icons">
<div class="nobr">
<span style="cursor: move;" title="<%= t('drag_to_reorder', %{Drag to reorder or move item to another module}) %>" class="move_item_link"><%= image_tag "move.png" %></span>
<%- title = t('drag_to_reorder', %{Drag to reorder or move item to another module}) %>
<span title="<%= title %>" class="move_item_link">
<%= image_tag "move.png", :class => 'hidden_tabbable', :alt => title, :tabindex => '0' %>
</span>
<span class="completion_status">
<%= image_tag "blank.png", :alt => t('images.alt.complete', "done"), :title => t('images.title.complete', "Module Item Completed"), :class => "complete_item_icon" %>
<%= image_tag "blank.png", :alt => t('images.alt.incomplete', "incomplete"), :title => t('images.title.incomplete', "Module Item Incomplete"), :class => "incomplete_item_icon" %>
@ -71,10 +74,10 @@
<td class="points_possible_display">&nbsp;</td>
<td class="links">
&nbsp;
<a href="<%= context_url(@context, :context_url) %>/modules/items/<%= tag ? tag.id : "{{ id }}" %>" class="outdent_item_link" title="<%= t('links.outdent', %{Outdent item}) %>"><%= @module_item_image_tags['outdent'] %></a>
<a href="<%= context_url(@context, :context_url) %>/modules/items/<%= tag ? tag.id : "{{ id }}" %>" class="indent_item_link" title="<%= t('links.indent', %{Indent item}) %>"><%= @module_item_image_tags['indent'] %></a>
<a href="<%= context_url(@context, :context_url) %>/modules/items/<%= tag ? tag.id : "{{ id }}" %>" class="edit_item_link edit_link" title="<%= t('links.edit_item', %{Edit item details}) %>"><%= @module_item_image_tags['edit'] %></a>
<a href="<%= context_url(@context, :context_url) %>/modules/items/<%= tag ? tag.id : "{{ id }}" %>" class="delete_item_link delete_link" title="<%= t('links.remove_item', %{Remove this item from the module}) %>"><%= @module_item_image_tags['delete'] %></a>
<a href="<%= context_url(@context, :context_url) %>/modules/items/<%= tag ? tag.id : "{{ id }}" %>" class="outdent_item_link hidden_tabbable" title="<%= t('links.outdent', %{Outdent item}) %>"><%= @module_item_image_tags['outdent'] %></a>
<a href="<%= context_url(@context, :context_url) %>/modules/items/<%= tag ? tag.id : "{{ id }}" %>" class="indent_item_link hidden_tabbable" title="<%= t('links.indent', %{Indent item}) %>"><%= @module_item_image_tags['indent'] %></a>
<a href="<%= context_url(@context, :context_url) %>/modules/items/<%= tag ? tag.id : "{{ id }}" %>" class="edit_item_link edit_link hidden_tabbable" title="<%= t('links.edit_item', %{Edit item details}) %>"><%= @module_item_image_tags['edit'] %></a>
<a href="<%= context_url(@context, :context_url) %>/modules/items/<%= tag ? tag.id : "{{ id }}" %>" class="delete_item_link delete_link hidden_tabbable" title="<%= t('links.remove_item', %{Remove this item from the module}) %>"><%= @module_item_image_tags['delete'] %></a>
</td>
</tr>
</table>

View File

@ -6,7 +6,7 @@
<div style="<%= hidden if only && only.size == 1 %>">
<a href="<%= context_url(@context, :context_external_tool_resource_selection_url, "{{ id }}") %>" id="select_content_resource_selection_url" style="display: none;">&nbsp;</a>
<% ot :add_to_module, "Add %{item} to *module*", :item => capture { %>
<select id="add_module_item_select">
<select id="add_module_item_select" aria-label="<%= t('titles.add_item_to_module', "Add Item to Module") %>">
<% if !only || only.include?(:assignments) %>
<option value="assignment"><%= t :assignment_item, "Assignment" %></option>
<% end %>
@ -38,12 +38,14 @@
<% if !only || only.include?(:sub_headers) %>
<div id="context_module_sub_headers_select" class="module_item_option" style="margin: 5px 20px;">
<div style="font-size: 0.8em;">
<%= t :sub_header_notice, "Type the text you'd like to add as a *module* sub-header", :wrapper => '<span class="holder_type">\1</span>' %>
<span class="holder_type" id="sub_header_notice">
<%= t :sub_header_notice, "Type the text you'd like to add as a *module* sub-header" %>
</span>
</div>
<table>
<tr>
<td><label for="sub_header_title"><%= before_label :header, "Header" %></label></td>
<td><input type="text" name="title" id="sub_header_title" style="width: 200px;"/></td>
<td><label for="sub_header_title"><%= label_tag :sub_header_title, before_label(:header, "Header") %></label></td>
<td><input type="text" name="title" id="sub_header_title" style="width: 200px;" aria-describedby="sub_header_notice" /></td>
</tr>
</table>
</div>
@ -52,20 +54,22 @@
<div id="external_urls_select" class="module_item_option" style="margin: 5px 20px;">
<div style="font-size: 0.8em;">
<%= image_tag "link.png", :alt => t(:external_url_link_alt, "External URL") %>
<%= t :external_url_notice, "Enter a URL and page name to add a link to any website URL to this *module*.", :wrapper => '<span class="holder_type">\1</span>' %>
<span class="holder_type" id="external_url_notice">
<%= t :external_url_notice, "Enter a URL and page name to add a link to any website URL to this *module*." %>
</span>
</div>
<table>
<tr>
<td><label for="content_tag_create_url"><%= before_label :url, "URL" %></label></td>
<td><%= label_tag :content_tag_create_url, before_label(:url, "URL") %></td>
<td>
<input type="text" name="url" id="content_tag_create_url" style="width: 200px;"/>
<input type="text" name="url" id="content_tag_create_url" style="width: 200px;" aria-describedby="external_url_notice" />
<div id="content_tag_services">
</div>
</td>
</tr>
<tr class='select_item_name'>
<td><label for="content_tag_create_title"><%= before_label :page_name, "Page Name" %></label></td>
<td><%= label_tag :content_tag_create_title, before_label(:page_name, "Page Name") %></label></td>
<td><input type="text" name="title" id="content_tag_create_title" style="width: 120px;"/></td>
</tr>
</table>
@ -114,10 +118,12 @@
<div id="wiki_pages_select" class="module_item_option" style="margin: 5px 20px;">
<div style="font-size: 0.8em;">
<%= image_tag "file.png", :alt => t(:wiki_page_alt, "Wiki page") %>
<%= t :wiki_page_notice, 'Select the wiki page you want to associate with this *module*, or add a new page by selecting "New Page".', :wrapper => '<span class="holder_type">\1</span>' %>
<span class="holder_type">
<%= label_tag :wiki_select, t(:wiki_page_notice, 'Select the wiki page you want to associate with this *module*, or add a new page by selecting "New Page".') %>
</span>
</div>
<div style="margin-top: 5px;">
<select class="module_item_select" multiple>
<select class="module_item_select" id="wiki_select" multiple>
<%# cache on the context.wiki instead of just the context because even though it will require a db query, we will get a much better cache hit rate %>
<% cache([@context.wiki, 'active_wiki_pages']) do %>
<% @context.wiki.wiki_pages.active.scoped({:select => "id, title"}).each do |page| %>
@ -130,8 +136,8 @@
</select>
</div>
<div class="new" style="margin-top: 5px;">
<%= before_label :page_name, "Page Name" %>
<input type="text" name="wiki_page[title]" class="item_title"/>
<%= label_tag :wiki_page_title, before_label(:page_name, "Page Name") %>
<input type="text" name="wiki_page[title]" class="item_title" id="wiki_page_title"/>
<a href="<%= context_url(@context, :context_wiki_pages_url) %>" style="display: none;" class="add_item_url">&nbsp;</a>
</div>
</div>
@ -139,11 +145,15 @@
<% if !only || only.include?(:attachments) %>
<div id="attachments_select" class="module_item_option" style="margin: 5px 20px;">
<div style="font-size: 0.8em;">
<%= image_tag "file_download.png" %>
<%= t :file_notice, 'Select the file you want to associate with this *module*, or add a file by selecting "New File".', :wrapper => '<span class="holder_type">\1</span>' %>
<%= image_tag "file_download.png", :alt => "Upload" %>
<label for="module_item_select">
<span class="holder_type">
<%= label_tag :module_item_select, t(:file_notice, 'Select the file you want to associate with this *module*, or add a file by selecting "New File".') %>
</span>
</label>
</div>
<div style="margin-top: 5px;">
<select class="module_item_select" multiple>
<select class="module_item_select" id="module_item_select" multiple>
<% @context.folders.active.scoped({:limit => 200}).sort_by{|f| f.full_name}.each do |folder| %>
<optgroup label="<%= folder.full_name %>">
<%
@ -164,12 +174,12 @@
<div class="new" style="margin-top: 5px;">
<table>
<tr>
<td><%= before_label :file, "File" %></td>
<td><%= label_tag :module_attachment_uploaded_data, before_label(:file, "File") %></td>
<td><input id="module_attachment_uploaded_data" type="file" name="attachment[uploaded_data]" class="item_title"/></td>
</tr><tr>
<td>
<a href="<%= context_url(@context, :context_files_url, :format => :text) %>" style="display: none;" class="add_item_url">&nbsp;</a>
<%= before_label :folder, "Folder" %>
<%= label_tag :attachment_folder_id, before_label(:folder, "Folder") %>
</td><td>
<% Folder.root_folders(@context) %>
<% folders = @context.active_folders_with_sub_folders.by_position %>
@ -187,10 +197,12 @@
<div id="quizs_select" class="module_item_option" style="margin: 5px 20px;">
<div style="font-size: 0.8em;">
<%= image_tag "quiz.png", :alt => t(:quiz_alt, "Quiz") %>
<%= t :quiz_notice, 'Select the quiz you want to associate with this *module*, or add a new one by selecting "New Quiz".', :wrapper => '<span class="holder_type">\1</span>' %>
<span class="holder_type">
<%= label_tag :quiz_select, t(:quiz_notice, 'Select the quiz you want to associate with this *module*, or add a new one by selecting "New Quiz".') %>
</span>
</div>
<div style="margin-top: 5px;">
<select class="module_item_select" multiple>
<select class="module_item_select" id="quiz_select" multiple>
<% @context.quizzes.active.scoped({:limit => 400}).each do |quiz| %>
<option value="<%= quiz.id %>"><%= quiz.title %></option>
<% end %>
@ -201,12 +213,12 @@
<input type="hidden" name="quiz[quiz_type]" value="assignment" />
<table>
<tr>
<td><%= before_label :quiz_name, "Quiz Name" %></td>
<td><input type="text" name="quiz[title]" class="item_title"/></td>
<td><%= label_tag :quiz_title, before_label(:quiz_name, "Quiz Name") %></td>
<td><input type="text" name="quiz[title]" class="item_title" id="quiz_title"/></td>
</tr><tr>
<td><%= before_label :quiz_group, "Group" %></td>
<td><%= label_tag :quiz_assignment_group_id, before_label(:quiz_group, "Group") %></td>
<td>
<select name="quiz[assignment_group_id]">
<select name="quiz[assignment_group_id]" id="quiz_assignment_group_id">
<% cnt = 0 %>
<% @context.assignment_groups.active.each do |group| %>
<% cnt += 1 %>
@ -227,10 +239,12 @@
<div id="assignments_select" class="module_item_option" style="margin: 5px 20px;">
<div style="font-size: 0.8em;">
<%= image_tag "grading_icon.png", :alt => t(:assignment_alt, "Assignment") %>
<%= t :assignment_notice, 'Select the assignment you want to associate with this *module*, or add an assignment by selecting "New Assignment".', :wrapper => '<span class="holder_type">\1</span>' %>
<span class="holder_type">
<%= label_tag :assignment_select, t(:assignment_notice, 'Select the assignment you want to associate with this *module*, or add an assignment by selecting "New Assignment".') %>
</span>
</div>
<div style="margin-top: 5px;">
<select class="module_item_select" multiple>
<select class="module_item_select" id="assignment_select" multiple>
<% @context.assignment_groups.active.include_active_assignments.each do |group| %>
<optgroup label="<%= group.name %>">
<% group.active_assignments.no_graded_quizzes_or_topics.scoped({:limit => 200}).each do |assignment| %>
@ -242,8 +256,8 @@
</select>
</div>
<div class="new" style="margin-top: 5px;">
<%= before_label :assignment_name, "Assignment Name" %>
<input type="text" name="assignment[title]" class="item_title"/>
<%= label_tag :assignment_title, before_label(:assignment_name, "Assignment Name") %>
<input type="text" name="assignment[title]" class="item_title" id="assignment_title" />
<a href="<%= context_url(@context, :context_assignments_url) %>" style="display: none;" class="add_item_url">&nbsp;</a>
</div>
</div>
@ -252,10 +266,12 @@
<div id="discussion_topics_select" class="module_item_option" style="margin: 5px 20px;">
<div style="font-size: 0.8em;">
<%= image_tag "word_bubble.png", :alt => t(:topic_alt, "Topic") %>
<%= t :topic_notice, 'Select the topic you want to associate with this *module*, or add a topic by selecting "New Topic".', :wrapper => '<span class="holder_type">\1</span>' %>
<span class="holder_type">
<%= label_tag :topic_select, t(:topic_notice, 'Select the topic you want to associate with this *module*, or add a topic by selecting "New Topic".') %>
</span>
</div>
<div style="margin-top: 5px;">
<select class="module_item_select" multiple>
<select class="module_item_select" id="topic_select" multiple>
<% @context.discussion_topics.active.only_discussion_topics.scoped({:limit => 200}).each do |topic| %>
<option value="<%= topic.id %>"><%= topic.title %></option>
<% end %>
@ -263,15 +279,15 @@
</select>
</div>
<div class="new" style="margin-top: 5px;">
<%= before_label :topic_name, "Topic Name" %>
<input type="text" name="title" class="item_title"/>
<%= label_tag :topic_name, before_label(:topic_name, "Topic Name") %>
<input type="text" name="title" class="item_title" id="topic_name"/>
<a href="<%= context_url(@context, :api_v1_context_discussion_topics_url) %>" style="display: none;" class="add_item_url">&nbsp;</a>
</div>
</div>
<% end %>
<% if !only || only.include?(:indentation) %>
<div style="margin: 0px 20px 5px;" class="context_module_content">
<%= before_label :indentation, "Indentation" %>
<%= label_tag :content_tag_indent, before_label(:indentation, "Indentation") %>
<select name="content_tag[indent]" id="content_tag_indent">
<% (0..3).each do |level| %>
<%= t(:indent_level, { :zero => "*Don't Indent*", :one => "*Indent 1 Level*", :other => "*Indent %{count} levels*" }, :count => level, :wrapper => "<option value=\"#{level}\">\\1</option>") %>

View File

@ -852,14 +852,15 @@ define([
$(document).ready(function() {
$(".datetime_field").datetime_field();
$(".context_module").live('mouseover', function() {
$(".context_module_hover").removeClass('context_module_hover');
$(this).addClass('context_module_hover');
$("#context_modules").on('mouseenter mouseleave', '.context_module', function() {
$(this).toggleClass('context_module_hover');
});
$(".context_module_item").live('mouseover', function() {
$(".context_module_item_hover").removeClass('context_module_item_hover');
$(this).addClass('context_module_item_hover');
$("#context_modules").on('mouseenter mouseleave', '.context_module_item', function() {
$(this).toggleClass('context_module_item_hover');
});
var $currentElem = null;
var hover = function($elem) {
if($elem.hasClass('context_module')) {

View File

@ -149,7 +149,10 @@ describe "context_modules" do
a2_img = fj('.context_module_items .context_module_item:last .move_item_link img')
#performs the change position
driver.action.drag_and_drop(a2_img, a1_img).perform
with_focus_icons_visible do
driver.action.drag_and_drop(a2_img, a1_img).perform
end
wait_for_ajax_requests
#validates the assignments switched, the number convention doesn't make sense, should be assignment == 2 and assignment2 == 1 but this is working
@ -172,7 +175,10 @@ describe "context_modules" do
a2_img = fj('#context_modules .context_module:last-child .context_module_items .context_module_item:first .move_item_link img')
#performs the change position
driver.action.drag_and_drop(a2_img, a1_img).perform
with_focus_icons_visible do
driver.action.drag_and_drop(a2_img, a1_img).perform
end
wait_for_ajax_requests
#validates the module 1 assignments are in the expected places and that module 2 context_module_items isn't present
@ -235,10 +241,13 @@ describe "context_modules" do
it "should delete a module" do
add_module('Delete Module')
driver.execute_script("$('.context_module').addClass('context_module_hover')")
f('.delete_module_link').click
driver.switch_to.alert.should_not be_nil
driver.switch_to.alert.accept
with_focus_icons_visible do
f('.delete_module_link').click
driver.switch_to.alert.should_not be_nil
driver.switch_to.alert.accept
end
wait_for_ajaximations
refresh_page
f('#no_context_modules_message').should be_displayed
@ -249,7 +258,9 @@ describe "context_modules" do
add_module('Edit Module')
context_module = f('.context_module')
driver.action.move_to(context_module).perform
f('.edit_module_link').click
with_focus_icons_visible do
f('.edit_module_link').click
end
f('.ui-dialog').should be_displayed
edit_form = f('#add_context_module_form')
edit_form.find_element(:id, 'context_module_name').send_keys(edit_text)
@ -265,7 +276,9 @@ describe "context_modules" do
# add completion criterion
context_module = f('.context_module')
driver.action.move_to(context_module).perform
f('.edit_module_link').click
with_focus_icons_visible do
f('.edit_module_link').click
end
f('.ui-dialog').should be_displayed
edit_form = f('#add_context_module_form')
f('.add_completion_criterion_link', edit_form).click
@ -285,7 +298,11 @@ describe "context_modules" do
# delete the criterion, then cancel the form
driver.action.move_to(context_module).perform
f('.edit_module_link').click
with_focus_icons_visible do
f('.edit_module_link').click
end
f('.ui-dialog').should be_displayed
edit_form = f('#add_context_module_form')
f('.completion_entry .delete_criterion_link', edit_form).click
@ -296,7 +313,11 @@ describe "context_modules" do
# now delete the criterion frd
# (if the previous step did even though it shouldn't have, this will error)
driver.action.move_to(context_module).perform
f('.edit_module_link').click
with_focus_icons_visible do
f('.edit_module_link').click
end
f('.ui-dialog').should be_displayed
edit_form = f('#add_context_module_form')
f('.completion_entry .delete_criterion_link', edit_form).click
@ -310,7 +331,11 @@ describe "context_modules" do
# and also make sure the form remembers that it's gone (#8329)
driver.action.move_to(context_module).perform
f('.edit_module_link').click
with_focus_icons_visible do
f('.edit_module_link').click
end
f('.ui-dialog').should be_displayed
edit_form = f('#add_context_module_form')
ff('.completion_entry .delete_criterion_link', edit_form).should be_empty
@ -515,7 +540,11 @@ describe "context_modules" do
m1_img = fj('#context_modules .context_module:first-child .reorder_module_link img')
m2_img = fj('#context_modules .context_module:last-child .reorder_module_link img')
driver.action.drag_and_drop(m2_img, m1_img).perform
with_focus_icons_visible do
driver.action.drag_and_drop(m2_img, m1_img).perform
end
wait_for_ajax_requests
m1.reload
@ -594,7 +623,11 @@ describe "context_modules" do
# add completion criterion
context_module = f('.context_module')
driver.action.move_to(context_module).perform
f('.edit_module_link').click
with_focus_icons_visible do
f('.edit_module_link').click
end
edit_form = f('#add_context_module_form')
f('.add_completion_criterion_link', edit_form).click
wait_for_ajaximations
@ -619,6 +652,37 @@ describe "context_modules" do
f('.criterion', module_item).attribute('class').split.should include 'defined'
driver.execute_script("return $('#context_module_item_#{tag.id} .criterion_type').text()").should == "must_contribute"
end
it "should allow editing external tools settings for a tool in a module" do
# moved from external_tools_spec
@module = @course.context_modules.create!(:name => "module")
@tag = @module.add_item({
:type => 'context_external_tool',
:title => 'Example',
:url => 'http://www.example.com',
:new_tab => '1'
})
get "/courses/#{@course.id}/modules"
keep_trying_until { driver.execute_script("return window.modules.refreshed == true") }
with_focus_icons_visible do
f("#context_module_item_#{@tag.id} .edit_item_link").click
end
f("#edit_item_form").should be_displayed
replace_content(f("#edit_item_form #content_tag_title"), "Example 2")
f("#edit_item_form #content_tag_new_tab").click
submit_form("#edit_item_form")
wait_for_ajax_requests
@tag.reload
@tag.should_not be_nil
@tag.title.should == "Example 2"
@tag.new_tab.should == false
@tag.url.should == "http://www.example.com"
end
end
describe "files" do

View File

@ -283,33 +283,6 @@ describe "editing external tools" do
f("#external_tool_create_title").should have_value "bob"
end
it "should allow editing the settings for a tool in a module" do
@module = @course.context_modules.create!(:name => "module")
@tag = @module.add_item({
:type => 'context_external_tool',
:title => 'Example',
:url => 'http://www.example.com',
:new_tab => '1'
})
get "/courses/#{@course.id}/modules"
keep_trying_until { driver.execute_script("return window.modules.refreshed == true") }
f("#context_module_item_#{@tag.id}").click
f("#context_module_item_#{@tag.id} .edit_item_link").click
f("#edit_item_form").should be_displayed
replace_content(f("#edit_item_form #content_tag_title"), "Example 2")
f("#edit_item_form #content_tag_new_tab").click
submit_form("#edit_item_form")
wait_for_ajax_requests
@tag.reload
@tag.should_not be_nil
@tag.title.should == "Example 2"
@tag.new_tab.should == false
@tag.url.should == "http://www.example.com"
end
it "should launch assignment external tools when viewing assignment" do
@tool = @course.context_external_tools.create!(:name => "new tool", :consumer_key => "key", :shared_secret => "secret", :domain => 'example.com', :custom_fields => {'a' => '1', 'b' => '2'})

View File

@ -93,4 +93,11 @@ shared_examples_for "context module tests" do
submit_form(edit_form)
wait_for_ajaximations
end
def with_focus_icons_visible(&block)
# reveals 'hidden_tabbable' icons that are only visible on focus or hover for the duration of the block
driver.execute_script("$('.hidden_tabbable').addClass('focus');")
yield(block)
driver.execute_script("$('.hidden_tabbable').removeClass('focus');")
end
end