fix ie 8 select clipping in quizzes, fixes #4681
the driver behind this change was to fix quizzes for IE 8 so that select options didn't get clipped when the contents were relatively long summary of changes: * replace all select controls in quizzes with ui.selectmenu's * upgrade ui.selectmenu * tweak active control background to use a gradient instead of an image * remove quiz select control bugfix hacks * clean up speedgrader selectmenu usuage, which incidentally fixes issue where the selectmenu wouldn't close on subsequent clicks * fix amd bug in app/views/quizzes/history.html.erb this change will make html answers in dropdowns fairly trivial to implement test plan: * create a quiz with matching questions and multiple dropdown questions, some with extremely long answer options * take the quiz * ensure that the selectmenu dropdowns appear and function correctly (e.g. all text should be visible for each option when the dropdown is expanded) * ensure that the selectmenu dropdowns appear and function correctly when viewing the quiz submission after the fact (as the student and via the teacher, e.g. in speedgrader) * use the speedgrader and ensure there are no regressions in the student dropdown behavior Change-Id: I9e50853d4bf1ff4e7e606de872577f374df93061 Reviewed-on: https://gerrit.instructure.com/8869 Reviewed-by: Jon Jensen <jon@instructure.com> Tested-by: Hudson <hudson@instructure.com>
This commit is contained in:
parent
be58ab1e54
commit
9f9b7695eb
|
@ -0,0 +1,19 @@
|
|||
define [
|
||||
'jquery'
|
||||
'vendor/ui.selectmenu'
|
||||
], ($) ->
|
||||
$ ->
|
||||
# css tweaks to ensure that it's sufficiently wide so the text doesn't
|
||||
# get clipped unnecessarily when we make it a selectmenu. we do this here
|
||||
# rather than in the css so as to avoid a flash of ugly content
|
||||
#
|
||||
# TODO: support HTML answers in dropdowns. to do this, we'll just need to
|
||||
# 1. get rid of the escapeHTML: true (default is false)
|
||||
# 2. in the views, double-escape any non-html answers going into dropdown
|
||||
# options (yes, really ... escapeHTML should more accurately be named
|
||||
# dontUnescapeAlreadyEscapedHTML)
|
||||
$('.question select').css
|
||||
'-webkit-appearance': 'none'
|
||||
'font-size': '100%'
|
||||
'padding-right': '40px'
|
||||
.selectmenu escapeHtml: true
|
|
@ -1,7 +1,7 @@
|
|||
@import environment.sass
|
||||
|
||||
fieldset.question, fieldset.display_question
|
||||
padding: 0
|
||||
div.question
|
||||
border-radius: 3px
|
||||
|
||||
#sort_questions
|
||||
:max-height 250px
|
||||
|
@ -852,3 +852,14 @@ ul#quiz_versions
|
|||
+border-radius(5px)
|
||||
padding: 16px
|
||||
text-shadow: 1px 1px 1px rgba(255, 255, 255, 0.75)
|
||||
|
||||
.ui-selectmenu-menu a, .ui-selectmenu
|
||||
color: #222 !important
|
||||
font-weight: normal
|
||||
text-decoration: none !important
|
||||
|
||||
.ui-selectmenu
|
||||
max-width: 100% !important
|
||||
|
||||
.question select
|
||||
max-width: 100%
|
||||
|
|
|
@ -19,14 +19,14 @@
|
|||
<div class="question_holder <%= "group" if in_group %>" id="<%= "question_template" unless question %>" style="<%= hidden unless question %>">
|
||||
<div style="display: block; height: 1px; overflow: hidden;"> </div>
|
||||
<a name="question_<%= hash_get(question, :id, "blank") %>"></a>
|
||||
<fieldset class="display_question question <%= question_type.question_type %> <%= "marked" if assessing && @stored_params && @stored_params["question_#{hash_get(question, :id)}_marked"] %> <%= "correct" if user_answer && hash_get(user_answer, :correct) == true %> <%= "incorrect" if user_answer && hash_get(user_answer, :correct) == false %>" id="question_<%= hash_get(question, :id, "new") %>">
|
||||
<div class="display_question question <%= question_type.question_type %> <%= "marked" if assessing && @stored_params && @stored_params["question_#{hash_get(question, :id)}_marked"] %> <%= "correct" if user_answer && hash_get(user_answer, :correct) == true %> <%= "incorrect" if user_answer && hash_get(user_answer, :correct) == false %>" id="question_<%= hash_get(question, :id, "new") %>">
|
||||
<div class="move"><%= image_tag "move.png", :class => "move_icon" %></div>
|
||||
<% if assessing %>
|
||||
<div class="flag_question">
|
||||
<%= image_tag "flag_question.png", :title => t('titles.mark_to_revisit', "Mark this question to come back to later"), :class => "flag_icon" %>
|
||||
</div>
|
||||
<% end %>
|
||||
<legend class="header" <%= hidden(true) if (assessing || assessment_results) && question_type && question_type.entry_type == "none" %>>
|
||||
<div class="header" <%= hidden(true) if (assessing || assessment_results) && question_type && question_type.entry_type == "none" %>>
|
||||
<span class="name question_name"><%= hash_get(question, :question_name) %></span>:
|
||||
<span class="question_points_holder" style="<%= hidden if question_type && question_type.entry_type == "none" %>">
|
||||
<%= t(:points_possible, "%{points_possible} pts", :points_possible => raw("<span class=\"points question_points\">#{hash_get(question, :points_possible, "0")}</span>")) %>
|
||||
|
@ -36,7 +36,7 @@
|
|||
<% else %>
|
||||
<a class='ui-helper-hidden-accessible' href="#question_<%= hash_get(question, :id, "new") %>_question_text"><%= t(:skip_question_text, "Skip to question text.") %></a>
|
||||
<% end %>
|
||||
</legend>
|
||||
</div>
|
||||
<div class="links" style="<%= hidden if user_answer || assessing %>">
|
||||
<a href="#" class="edit_question_link no-hover" title="<%= t 'links.edit_question', 'Edit this Question' %>"><%= image_tag "edit.png" %></a>
|
||||
<a href="#" class="delete_question_link no-hover" title="<%= t 'links.delete_question', 'Delete this Question' %>"><%= image_tag "delete.png" %></a>
|
||||
|
@ -339,5 +339,5 @@
|
|||
</div>
|
||||
<% end %>
|
||||
<div class="clear"></div>
|
||||
</fieldset>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -85,7 +85,8 @@
|
|||
<script>
|
||||
require([
|
||||
'i18nObj' /* I18n.t */,
|
||||
'jquery' /* $ */
|
||||
'jquery' /* $ */,
|
||||
'compiled/behaviors/quiz_selectmenu'
|
||||
], function(I18n, $) {
|
||||
|
||||
$(document).ready(function() {
|
||||
|
|
|
@ -128,8 +128,9 @@
|
|||
require([
|
||||
'jquery' /* $ */,
|
||||
'jquery.instructure_misc_plugins' /* fragmentChange */,
|
||||
'fragmentChangejquery.templateData' /* getTemplateData */,
|
||||
'vendor/jquery.scrollTo' /* /\.scrollTo/ */
|
||||
'jquery.templateData' /* getTemplateData */,
|
||||
'vendor/jquery.scrollTo' /* /\.scrollTo/ */,
|
||||
'compiled/behaviors/quiz_selectmenu'
|
||||
], function($) {
|
||||
|
||||
var data = $("#submission_details").getTemplateData({textValues: ['version_number', 'user_id']});
|
||||
|
|
|
@ -160,6 +160,7 @@ stylesheets:
|
|||
quizzes:
|
||||
- public/stylesheets/compiled/quizzes.css
|
||||
- public/stylesheets/compiled/message_students.css
|
||||
- public/stylesheets/static/ui.selectmenu.css
|
||||
moderate_quiz:
|
||||
- public/stylesheets/compiled/moderate_quiz.css
|
||||
full_assignment:
|
||||
|
|
|
@ -57,7 +57,7 @@ require([
|
|||
|
||||
// Determines whether or to show the "show question details" link.
|
||||
checkShowDetails: function() {
|
||||
var hasQuestions = this.$questions.find('fieldset:not(.essay_question, .text_only_question)').length;
|
||||
var hasQuestions = this.$questions.find('div.display_question:not(.essay_question, .text_only_question)').length;
|
||||
this.$showDetailsWrap[hasQuestions ? 'show' : 'hide'](200);
|
||||
},
|
||||
|
||||
|
|
|
@ -938,18 +938,16 @@ require([
|
|||
|
||||
goToStudent: function(student_id){
|
||||
var student = $.grep(jsonData.studentsWithSubmissions, function(o){
|
||||
return o.id === student_id;
|
||||
})[0];
|
||||
return o.id === student_id;
|
||||
})[0];
|
||||
|
||||
var indexOfStudentInOptions = $selectmenu.find('option').index($selectmenu.find('option[value="' + student.id + '"]'));
|
||||
if (!(indexOfStudentInOptions >= 0)) {
|
||||
throw "student not found";
|
||||
}
|
||||
$selectmenu.selectmenu("value", indexOfStudentInOptions);
|
||||
//this is lame but I have to manually tell $selectmenu to fire its 'change' event if has changed.
|
||||
if (!this.currentStudent || (this.currentStudent.id != student.id)) {
|
||||
$selectmenu.change();
|
||||
}
|
||||
if (student) {
|
||||
$selectmenu.selectmenu("value", student.id);
|
||||
//this is lame but I have to manually tell $selectmenu to fire its 'change' event if has changed.
|
||||
if (!this.currentStudent || (this.currentStudent.id != student.id)) {
|
||||
$selectmenu.change();
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
currentIndex: function(){
|
||||
|
|
|
@ -26,7 +26,8 @@ require([
|
|||
'jquery.instructure_misc_helpers' /* scrollSidebar */,
|
||||
'jquery.rails_flash_notifications' /* flashMessage */,
|
||||
'tinymce.editor_box' /* editorBox */,
|
||||
'vendor/jquery.scrollTo' /* /\.scrollTo/ */
|
||||
'vendor/jquery.scrollTo' /* /\.scrollTo/ */,
|
||||
'compiled/behaviors/quiz_selectmenu'
|
||||
], function(I18n, $, timing) {
|
||||
|
||||
var lastAnswerSelected = null;
|
||||
|
@ -188,9 +189,6 @@ require([
|
|||
});
|
||||
|
||||
$(function() {
|
||||
// prevent mousewheel from changing answers on dropdowns see #6143
|
||||
$('select').bind('mousewheel', false);
|
||||
|
||||
$.scrollSidebar();
|
||||
|
||||
if($("#preview_mode_link").length == 0) {
|
||||
|
@ -201,7 +199,7 @@ require([
|
|||
}
|
||||
};
|
||||
$(document).delegate('a', 'click', function(event) {
|
||||
if($(this).closest('.ui-dialog,.mceToolbar').length > 0) { return; }
|
||||
if($(this).closest('.ui-dialog,.mceToolbar,.ui-selectmenu').length > 0) { return; }
|
||||
if(!event.isDefaultPrevented()) {
|
||||
var url = $(this).attr('href') || "";
|
||||
var hashStripped = location.href;
|
||||
|
@ -258,33 +256,6 @@ require([
|
|||
}
|
||||
});
|
||||
|
||||
/* the intent of this is to ensure that the class doesn't ever change while
|
||||
the dropdown is open. in windows chrome, mouseleave events still fire
|
||||
for ancestors when a dropdown is open, and any style changes to them
|
||||
cause the dropdown to jump/reset. this effectively normalizes the
|
||||
mouseenter/mouseleave behavior across platforms and browsers, but the
|
||||
side effect is that the hover class is retained until the mouse has left
|
||||
and the select has blurred. */
|
||||
$questions.find('.question').bind({
|
||||
mouseenter: function(event) {
|
||||
var $container = $(this);
|
||||
var $activeSelect = $container.find($(document.activeElement)).filter("select");
|
||||
if ($activeSelect.length) $activeSelect.unbind('blur.unhoverQuestion');
|
||||
if (!$container.hasClass('hover')) $container.addClass('hover');
|
||||
},
|
||||
mouseleave: function(event) {
|
||||
var $container = $(this);
|
||||
var $activeSelect = $container.find($(document.activeElement)).filter("select");
|
||||
if ($activeSelect.length) {
|
||||
$activeSelect.one('blur.unhoverQuestion', function() {
|
||||
$(this).closest('.question').trigger('mouseleave');
|
||||
});
|
||||
} else {
|
||||
$container.removeClass('hover');
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
$questions
|
||||
.delegate(":checkbox,:radio,label", 'change mouseup', function(event) {
|
||||
var $answer = $(this).parents(".answer");
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -60,7 +60,7 @@
|
|||
----------------------------------*/
|
||||
.ui-state-default, .ui-widget-content .ui-state-default { border: 1px solid #cccccc; background: #f6f6f6 url(/images/jqueryui/ui-bg_glass_100_f6f6f6_1x400.png) 50% 50% repeat-x; font-weight: bold; color: #5F83B9; }
|
||||
.ui-state-default a, .ui-state-default a:link, .ui-state-default a:visited { color: #1c94c4; text-decoration: none; }
|
||||
.ui-state-hover, .ui-widget-content .ui-state-hover, .ui-state-focus, .ui-widget-content .ui-state-focus { border: 1px solid #749AAF; background: #fdf5ce url(/images/jqueryui/button_bg.png) 50% 50% repeat-x; font-weight: bold; color: #1C4257; text-shadow: 0 1px 0 rgba(255, 255, 255, 0.8); }
|
||||
.ui-state-hover, .ui-widget-content .ui-state-hover, .ui-state-focus, .ui-widget-content .ui-state-focus { border: 1px solid #749AAF; background-color: #9ec8df; background-image: -webkit-gradient(linear, left top, left bottom, from(#b9e0f5), to(#83b0ca)); background-image: -webkit-linear-gradient(top, #b9e0f5, #83b0ca); background-image: -moz-linear-gradient(top, #b9e0f5, #83b0ca); background-image: -ms-linear-gradient(top, #b9e0f5, #83b0ca); background-image: -o-linear-gradient(top, #b9e0f5, #83b0ca); background-image: linear-gradient(top, #b9e0f5, #83b0ca); -ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorStr='#b9e0f5',EndColorStr='#83b0ca')"; font-weight: bold; color: #1C4257; text-shadow: 0 1px 0 rgba(255, 255, 255, 0.8); }
|
||||
.ui-state-hover a, .ui-state-hover a:hover { color: #1C4257; text-decoration: none; }
|
||||
.ui-state-active, .ui-widget-content .ui-state-active { border: 1px solid #fbd850; background: #ffffff url(/images/jqueryui/ui-bg_glass_65_ffffff_1x400.png) 50% 50% repeat-x; font-weight: bold; color: #eb8f00; }
|
||||
.ui-state-active a, .ui-state-active a:link, .ui-state-active a:visited { color: #eb8f00; text-decoration: none; }
|
||||
|
|
|
@ -1,29 +1,27 @@
|
|||
/* Selectmenu
|
||||
----------------------------------*/
|
||||
.ui-selectmenu { display: block; position:relative; height:2em; text-decoration: none; overflow:hidden;}
|
||||
.ui-selectmenu { display: block; display: inline-block; position: relative; height: 2.2em; vertical-align: middle; text-decoration: none; overflow: hidden; zoom: 1; }
|
||||
.ui-selectmenu-icon { position:absolute; right:6px; margin-top:-8px; top: 50%; }
|
||||
.ui-selectmenu-menu { padding:0; margin:0; list-style:none; position:absolute; top: 0; visibility: hidden; display:none; overflow: auto; -moz-border-radius: 0; -webkit-border-radius: 0px; border-radius: 0;}
|
||||
.ui-selectmenu-open { visibility: visible; display:block; }
|
||||
.ui-selectmenu-menu { padding:0; margin:0; position:absolute; top: 0; display: none; z-index: 1005; background: #fff} /* z-index: 1005 to make selectmenu work with dialog */
|
||||
.ui-selectmenu-menu ul { padding:0; margin:0; list-style:none; position: relative; overflow: auto; overflow-y: auto ; overflow-x: hidden; }
|
||||
.ui-selectmenu-open { display: block; }
|
||||
.ui-selectmenu-menu-popup { margin-top: -1px; }
|
||||
.ui-selectmenu-menu-dropdown {
|
||||
background-color: white;
|
||||
border-color: #B5B8C8;
|
||||
}
|
||||
.ui-selectmenu-menu li { padding:0; margin:0; display: block; border-top: 1px dotted transparent; border-bottom: 1px dotted transparent; border-right-width: 0 !important; border-left-width: 0 !important; font-weight: normal !important; }
|
||||
.ui-selectmenu-menu li a,.ui-selectmenu-status {line-height: 1em; display:block; padding:.3em 1em; outline:none; text-decoration:none; }
|
||||
.ui-selectmenu-menu li a,.ui-selectmenu-status { line-height: 1.4em; display: block; padding: .405em 2.1em .405em 1em; outline:none; text-decoration:none; }
|
||||
.ui-selectmenu-menu li.ui-state-disabled a, .ui-state-disabled { cursor: default; }
|
||||
.ui-selectmenu-menu li.ui-selectmenu-hasIcon a,
|
||||
.ui-selectmenu-hasIcon .ui-selectmenu-status { padding-left: 20px; position: relative; margin-left: 5px; }
|
||||
.ui-selectmenu-menu li .ui-icon, .ui-selectmenu-status .ui-icon { position: absolute; top: 1em; margin-top: -8px; left: 0; }
|
||||
.ui-selectmenu-status { line-height: 1.4em; }
|
||||
.ui-selectmenu-open li.ui-selectmenu-item-focus a { background-color: transparent; }
|
||||
.ui-selectmenu-open li.ui-selectmenu-item-selected { }
|
||||
.ui-selectmenu-menu li span,.ui-selectmenu-status span { display:block; margin-bottom: 0; }
|
||||
.ui-selectmenu-menu li .ui-selectmenu-item-header { }
|
||||
.ui-selectmenu-menu li .ui-selectmenu-item-content { }
|
||||
.ui-selectmenu-menu li .ui-selectmenu-item-footer {
|
||||
margin-top: -2px;
|
||||
}
|
||||
/*for optgroups*/
|
||||
.ui-selectmenu-menu li span,.ui-selectmenu-status span { display:block; margin-bottom: .2em; }
|
||||
.ui-selectmenu-menu li .ui-selectmenu-item-header { font-weight: bold; }
|
||||
.ui-selectmenu-menu li .ui-selectmenu-item-footer { opacity: .8; }
|
||||
/* for optgroups */
|
||||
.ui-selectmenu-menu .ui-selectmenu-group { font-size: 1em; }
|
||||
.ui-selectmenu-menu .ui-selectmenu-group .ui-selectmenu-group-label { line-height: 1.4em; display:block; padding:.6em .5em 0; font-weight: bold; }
|
||||
.ui-selectmenu-menu .ui-selectmenu-group ul { margin: 0; padding: 0; }
|
||||
.ui-selectmenu-menu .ui-selectmenu-group .ui-selectmenu-group-label { line-height: 1.4em; display:block; padding: .6em .5em 0; font-weight: bold; }
|
||||
.ui-selectmenu-menu .ui-selectmenu-group ul { margin: 0; padding: 0; }
|
||||
/* IE6 workaround (dotted transparent borders) */
|
||||
* html .ui-selectmenu-menu li { border-color: pink; filter:chroma(color=pink); width:100%; }
|
||||
* html .ui-selectmenu-menu li a { position: relative }
|
||||
/* IE7 workaround (opacity disabled) */
|
||||
*+html .ui-state-disabled, *+html .ui-state-disabled a { color: silver; }
|
||||
|
|
|
@ -266,32 +266,13 @@ describe "quizzes questions" do
|
|||
end
|
||||
end
|
||||
|
||||
# see blur.unhoverQuestion in take_quiz.js. avoids a windows chrome display glitch
|
||||
it "should not unhover a question so long as one of its selects has focus" do
|
||||
container = driver.find_element(:css, '.question')
|
||||
driver.execute_script("$('.question').mouseenter()")
|
||||
container.attribute(:class).should match(/hover/)
|
||||
|
||||
container.find_element(:css, 'select').click
|
||||
|
||||
driver.execute_script("$('.question').mouseleave()")
|
||||
container.attribute(:class).should match(/hover/)
|
||||
|
||||
driver.execute_script("$('.question select').blur()")
|
||||
container.attribute(:class).should_not match(/hover/)
|
||||
end
|
||||
|
||||
it "should cancel mousewheel events on select elements" do
|
||||
skip_if_ie('Out of memory')
|
||||
driver.execute_script <<-EOF
|
||||
window.mousewheelprevented = false;
|
||||
jQuery('select').bind('mousewheel', function(event) {
|
||||
mousewheelprevented = event.isDefaultPrevented();
|
||||
}).trigger('mousewheel');
|
||||
EOF
|
||||
|
||||
is_prevented = driver.execute_script('return window.mousewheelprevented')
|
||||
is_prevented.should be_true
|
||||
it "should selectmenu-ify select elements" do
|
||||
select = driver.find_element(:css, '.question select')
|
||||
keep_trying_until { !select.displayed? }
|
||||
|
||||
driver.find_element(:css, 'a.ui-selectmenu').click
|
||||
driver.find_elements(:css, '.ui-selectmenu-open li')[1].click
|
||||
select[:selectedIndex].should eql "1"
|
||||
end
|
||||
end
|
||||
end
|
Loading…
Reference in New Issue