Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
E
edx-platform
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
edx
edx-platform
Commits
80dafc21
Commit
80dafc21
authored
Sep 25, 2015
by
Christine Lytwynec
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #9506 from edx/clytwynec/AC-157
Manage focus on delete component modal
parents
b98956bd
2dc5b8e8
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
134 additions
and
5 deletions
+134
-5
common/static/common/js/components/views/feedback.js
+47
-1
common/static/common/js/components/views/feedback_prompt.js
+9
-0
common/static/common/js/spec/components/feedback_spec.js
+52
-1
common/static/common/js/spec_helpers/view_helpers.js
+21
-2
common/static/js_test_requirejs.yml
+1
-0
common/test/acceptance/pages/common/utils.py
+4
-0
lms/djangoapps/teams/static/teams/js/views/team_profile.js
+0
-1
No files found.
common/static/common/js/components/views/feedback.js
View file @
80dafc21
...
@@ -6,6 +6,17 @@
...
@@ -6,6 +6,17 @@
"backbone"
,
"backbone"
,
"text!common/templates/components/system-feedback.underscore"
],
"text!common/templates/components/system-feedback.underscore"
],
function
(
$
,
_
,
str
,
Backbone
,
systemFeedbackTemplate
)
{
function
(
$
,
_
,
str
,
Backbone
,
systemFeedbackTemplate
)
{
var
tabbable_elements
=
[
"a[href]:not([tabindex='-1'])"
,
"area[href]:not([tabindex='-1'])"
,
"input:not([disabled]):not([tabindex='-1'])"
,
"select:not([disabled]):not([tabindex='-1'])"
,
"textarea:not([disabled]):not([tabindex='-1'])"
,
"button:not([disabled]):not([tabindex='-1'])"
,
"iframe:not([tabindex='-1'])"
,
"[tabindex]:not([tabindex='-1'])"
,
"[contentEditable=true]:not([tabindex='-1'])"
];
var
SystemFeedback
=
Backbone
.
View
.
extend
({
var
SystemFeedback
=
Backbone
.
View
.
extend
({
options
:
{
options
:
{
title
:
""
,
title
:
""
,
...
@@ -16,7 +27,8 @@
...
@@ -16,7 +27,8 @@
icon
:
true
,
// should we render an icon related to the message intent?
icon
:
true
,
// should we render an icon related to the message intent?
closeIcon
:
true
,
// should we render a close button in the top right corner?
closeIcon
:
true
,
// should we render a close button in the top right corner?
minShown
:
0
,
// length of time after this view has been shown before it can be hidden (milliseconds)
minShown
:
0
,
// length of time after this view has been shown before it can be hidden (milliseconds)
maxShown
:
Infinity
// length of time after this view has been shown before it will be automatically hidden (milliseconds)
maxShown
:
Infinity
,
// length of time after this view has been shown before it will be automatically hidden (milliseconds)
outFocusElement
:
null
// element to send focus to on hide
/* Could also have an "actions" hash: here is an example demonstrating
/* Could also have an "actions" hash: here is an example demonstrating
the expected structure. For each action, by default the framework
the expected structure. For each action, by default the framework
...
@@ -65,6 +77,40 @@
...
@@ -65,6 +77,40 @@
return
this
;
return
this
;
},
},
inFocus
:
function
()
{
this
.
options
.
outFocusElement
=
this
.
options
.
outFocusElement
||
document
.
activeElement
;
// Set focus to the container.
this
.
$
(
".wrapper"
).
first
().
focus
();
// Make tabs within the prompt loop rather than setting focus
// back to the main content of the page.
var
tabbables
=
this
.
$
(
tabbable_elements
.
join
());
tabbables
.
on
(
"keydown"
,
function
(
event
)
{
// On tab backward from the first tabbable item in the prompt
if
(
event
.
which
===
9
&&
event
.
shiftKey
&&
event
.
target
===
tabbables
.
first
()[
0
])
{
event
.
preventDefault
();
tabbables
.
last
().
focus
();
}
// On tab forward from the last tabbable item in the prompt
else
if
(
event
.
which
===
9
&&
!
event
.
shiftKey
&&
event
.
target
===
tabbables
.
last
()[
0
])
{
event
.
preventDefault
();
tabbables
.
first
().
focus
();
}
});
return
this
;
},
outFocus
:
function
()
{
var
tabbables
=
this
.
$
(
tabbable_elements
.
join
()).
off
(
"keydown"
);
if
(
this
.
options
.
outFocusElement
)
{
this
.
options
.
outFocusElement
.
focus
();
}
return
this
;
},
// public API: show() and hide()
// public API: show() and hide()
show
:
function
()
{
show
:
function
()
{
clearTimeout
(
this
.
hideTimeout
);
clearTimeout
(
this
.
hideTimeout
);
...
...
common/static/common/js/components/views/feedback_prompt.js
View file @
80dafc21
...
@@ -18,6 +18,15 @@
...
@@ -18,6 +18,15 @@
}
}
// super() in Javascript has awkward syntax :(
// super() in Javascript has awkward syntax :(
return
SystemFeedbackView
.
prototype
.
render
.
apply
(
this
,
arguments
);
return
SystemFeedbackView
.
prototype
.
render
.
apply
(
this
,
arguments
);
},
show
:
function
()
{
SystemFeedbackView
.
prototype
.
show
.
apply
(
this
,
arguments
);
return
this
.
inFocus
();
},
hide
:
function
()
{
SystemFeedbackView
.
prototype
.
hide
.
apply
(
this
,
arguments
);
return
this
.
outFocus
();
}
}
});
});
...
...
common/static/common/js/spec/components/feedback_spec.js
View file @
80dafc21
// Generated by CoffeeScript 1.6.1
// Generated by CoffeeScript 1.6.1
(
function
()
{
(
function
()
{
define
([
"jquery"
,
"common/js/components/views/feedback"
,
"common/js/components/views/feedback_notification"
,
"common/js/components/views/feedback_alert"
,
"common/js/components/views/feedback_prompt"
,
"sinon"
],
function
(
$
,
SystemFeedback
,
NotificationView
,
AlertView
,
PromptView
,
sinon
)
{
define
([
"jquery"
,
"common/js/components/views/feedback"
,
"common/js/components/views/feedback_notification"
,
"common/js/components/views/feedback_alert"
,
"common/js/components/views/feedback_prompt"
,
'common/js/spec_helpers/view_helpers'
,
"sinon"
,
"jquery.simulate"
],
function
(
$
,
SystemFeedback
,
NotificationView
,
AlertView
,
PromptView
,
ViewHelpers
,
sinon
)
{
var
tpl
;
var
tpl
;
tpl
=
readFixtures
(
'system-feedback.underscore'
);
tpl
=
readFixtures
(
'system-feedback.underscore'
);
beforeEach
(
function
()
{
beforeEach
(
function
()
{
...
@@ -114,6 +115,56 @@
...
@@ -114,6 +115,56 @@
});
});
});
});
describe
(
"PromptView"
,
function
()
{
describe
(
"PromptView"
,
function
()
{
beforeEach
(
function
()
{
this
.
options
=
{
title
:
"Confirming Something"
,
message
:
"Are you sure you want to do this?"
,
actions
:
{
primary
:
{
text
:
"Yes, I'm sure."
,
"class"
:
"confirm-button"
,
},
secondary
:
{
text
:
"Cancel"
,
"class"
:
"cancel-button"
,
}
}
}
this
.
inFocusSpy
=
spyOn
(
PromptView
.
Confirmation
.
prototype
,
'inFocus'
).
andCallThrough
();
return
this
.
outFocusSpy
=
spyOn
(
PromptView
.
Confirmation
.
prototype
,
'outFocus'
).
andCallThrough
();
});
it
(
"is focused on show"
,
function
()
{
var
view
;
view
=
new
PromptView
.
Confirmation
(
this
.
options
).
show
();
expect
(
this
.
inFocusSpy
).
toHaveBeenCalled
();
return
ViewHelpers
.
verifyElementInFocus
(
view
,
".wrapper-prompt"
)
});
it
(
"is not focused on hide"
,
function
()
{
var
view
;
view
=
new
PromptView
.
Confirmation
(
this
.
options
).
hide
();
expect
(
this
.
outFocusSpy
).
toHaveBeenCalled
();
return
ViewHelpers
.
verifyElementNotInFocus
(
view
,
".wrapper-prompt"
)
});
it
(
"traps keyboard focus when moving forward"
,
function
()
{
var
view
;
view
=
new
PromptView
.
Confirmation
(
this
.
options
).
show
();
expect
(
this
.
inFocusSpy
).
toHaveBeenCalled
();
$
(
'.action-secondary'
).
first
().
simulate
(
"keydown"
,
{
keyCode
:
$
.
simulate
.
keyCode
.
TAB
}
);
return
ViewHelpers
.
verifyElementInFocus
(
view
,
".action-primary"
)
});
it
(
"traps keyboard focus when moving backward"
,
function
()
{
var
view
;
view
=
new
PromptView
.
Confirmation
(
this
.
options
).
show
();
expect
(
this
.
inFocusSpy
).
toHaveBeenCalled
();
$
(
'.action-primary'
).
first
().
simulate
(
"keydown"
,
{
keyCode
:
$
.
simulate
.
keyCode
.
TAB
,
shiftKey
:
true
}
);
return
ViewHelpers
.
verifyElementInFocus
(
view
,
".action-secondary"
)
});
return
it
(
"changes class on body"
,
function
()
{
return
it
(
"changes class on body"
,
function
()
{
var
view
;
var
view
;
view
=
new
PromptView
.
Confirmation
({
view
=
new
PromptView
.
Confirmation
({
...
...
common/static/common/js/spec_helpers/view_helpers.js
View file @
80dafc21
...
@@ -10,7 +10,8 @@ define(["jquery", "common/js/components/views/feedback_notification", "common/js
...
@@ -10,7 +10,8 @@ define(["jquery", "common/js/components/views/feedback_notification", "common/js
verifyFeedbackHidden
,
createNotificationSpy
,
verifyNotificationShowing
,
verifyFeedbackHidden
,
createNotificationSpy
,
verifyNotificationShowing
,
verifyNotificationHidden
,
createPromptSpy
,
confirmPrompt
,
inlineEdit
,
verifyInlineEditChange
,
verifyNotificationHidden
,
createPromptSpy
,
confirmPrompt
,
inlineEdit
,
verifyInlineEditChange
,
installMockAnalytics
,
removeMockAnalytics
,
verifyPromptShowing
,
verifyPromptHidden
,
installMockAnalytics
,
removeMockAnalytics
,
verifyPromptShowing
,
verifyPromptHidden
,
clickDeleteItem
,
patchAndVerifyRequest
,
submitAndVerifyFormSuccess
,
submitAndVerifyFormError
;
clickDeleteItem
,
patchAndVerifyRequest
,
submitAndVerifyFormSuccess
,
submitAndVerifyFormError
,
verifyElementInFocus
,
verifyElementNotInFocus
;
installViewTemplates
=
function
()
{
installViewTemplates
=
function
()
{
appendSetFixtures
(
'<div id="page-notification"></div>'
);
appendSetFixtures
(
'<div id="page-notification"></div>'
);
...
@@ -127,6 +128,22 @@ define(["jquery", "common/js/components/views/feedback_notification", "common/js
...
@@ -127,6 +128,22 @@ define(["jquery", "common/js/components/views/feedback_notification", "common/js
verifyNotificationShowing
(
notificationSpy
,
/Saving/
);
verifyNotificationShowing
(
notificationSpy
,
/Saving/
);
};
};
verifyElementInFocus
=
function
(
view
,
selector
)
{
waitsFor
(
function
()
{
return
view
.
$
(
selector
+
':focus'
).
length
===
1
;
},
"element to have focus: "
+
selector
,
500
);
};
verifyElementNotInFocus
=
function
(
view
,
selector
)
{
waitsFor
(
function
()
{
return
view
.
$
(
selector
+
':focus'
).
length
===
0
;
},
"element to not have focus: "
+
selector
,
500
);
};
return
{
return
{
'installViewTemplates'
:
installViewTemplates
,
'installViewTemplates'
:
installViewTemplates
,
'createNotificationSpy'
:
createNotificationSpy
,
'createNotificationSpy'
:
createNotificationSpy
,
...
@@ -143,7 +160,9 @@ define(["jquery", "common/js/components/views/feedback_notification", "common/js
...
@@ -143,7 +160,9 @@ define(["jquery", "common/js/components/views/feedback_notification", "common/js
'clickDeleteItem'
:
clickDeleteItem
,
'clickDeleteItem'
:
clickDeleteItem
,
'patchAndVerifyRequest'
:
patchAndVerifyRequest
,
'patchAndVerifyRequest'
:
patchAndVerifyRequest
,
'submitAndVerifyFormSuccess'
:
submitAndVerifyFormSuccess
,
'submitAndVerifyFormSuccess'
:
submitAndVerifyFormSuccess
,
'submitAndVerifyFormError'
:
submitAndVerifyFormError
'submitAndVerifyFormError'
:
submitAndVerifyFormError
,
'verifyElementInFocus'
:
verifyElementInFocus
,
'verifyElementNotInFocus'
:
verifyElementNotInFocus
};
};
});
});
}).
call
(
this
,
define
||
RequireJS
.
define
);
}).
call
(
this
,
define
||
RequireJS
.
define
);
common/static/js_test_requirejs.yml
View file @
80dafc21
...
@@ -31,6 +31,7 @@ lib_paths:
...
@@ -31,6 +31,7 @@ lib_paths:
-
js/vendor/jquery.min.js
-
js/vendor/jquery.min.js
-
js/vendor/jasmine-jquery.js
-
js/vendor/jasmine-jquery.js
-
js/vendor/jasmine-imagediff.js
-
js/vendor/jasmine-imagediff.js
-
js/vendor/jquery.simulate.js
-
js/vendor/jquery.truncate.js
-
js/vendor/jquery.truncate.js
-
js/vendor/underscore-min.js
-
js/vendor/underscore-min.js
-
js/vendor/underscore.string.min.js
-
js/vendor/underscore.string.min.js
...
...
common/test/acceptance/pages/common/utils.py
View file @
80dafc21
...
@@ -56,6 +56,10 @@ def confirm_prompt(page, cancel=False, require_notification=None):
...
@@ -56,6 +56,10 @@ def confirm_prompt(page, cancel=False, require_notification=None):
cancel is True.
cancel is True.
"""
"""
page
.
wait_for_element_visibility
(
'.prompt'
,
'Prompt is visible'
)
page
.
wait_for_element_visibility
(
'.prompt'
,
'Prompt is visible'
)
page
.
wait_for_element_visibility
(
'.wrapper-prompt:focus'
,
'Prompt is in focus'
)
confirmation_button_css
=
'.prompt .action-'
+
(
'secondary'
if
cancel
else
'primary'
)
confirmation_button_css
=
'.prompt .action-'
+
(
'secondary'
if
cancel
else
'primary'
)
page
.
wait_for_element_visibility
(
confirmation_button_css
,
'Confirmation button is visible'
)
page
.
wait_for_element_visibility
(
confirmation_button_css
,
'Confirmation button is visible'
)
require_notification
=
(
not
cancel
)
if
require_notification
is
None
else
require_notification
require_notification
=
(
not
cancel
)
if
require_notification
is
None
else
require_notification
...
...
lms/djangoapps/teams/static/teams/js/views/team_profile.js
View file @
80dafc21
...
@@ -93,7 +93,6 @@
...
@@ -93,7 +93,6 @@
});
});
}
}
);
);
$
(
'.wrapper-prompt'
).
focus
();
}
}
});
});
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment