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
20290d2b
Commit
20290d2b
authored
Dec 15, 2016
by
Brian Jacobel
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Convert display.js to javascript, preserving comments
parent
be18f9e9
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
462 additions
and
287 deletions
+462
-287
common/lib/xmodule/xmodule/js/src/sequence/display.js
+462
-287
No files found.
common/lib/xmodule/xmodule/js/src/sequence/display.js
View file @
20290d2b
class
@
Sequence
constructor
:
(
element
)
->
@
updatedProblems
=
{}
@
requestToken
=
$
(
element
).
data
(
'request-token'
)
@
el
=
$
(
element
).
find
(
'.sequence'
)
@
path
=
$
(
'.path'
)
@
contents
=
@
$
(
'.seq_contents'
)
@
content_container
=
@
$
(
'#seq_content'
)
@
sr_container
=
@
$
(
'.sr-is-focusable'
)
@
num_contents
=
@
contents
.
length
@
id
=
@
el
.
data
(
'id'
)
@
ajaxUrl
=
@
el
.
data
(
'ajax-url'
)
@
nextUrl
=
@
el
.
data
(
'next-url'
)
@
prevUrl
=
@
el
.
data
(
'prev-url'
)
@
base_page_title
=
" | "
+
document
.
title
@
initProgress
()
@
bind
()
@
render
parseInt
(@
el
.
data
(
'position'
))
$
:
(
selector
)
->
$
(
selector
,
@
el
)
bind
:
->
@
$
(
'#sequence-list .nav-item'
).
click
@
goto
@
el
.
on
'bookmark:add'
,
@
addBookmarkIconToActiveNavItem
@
el
.
on
'bookmark:remove'
,
@
removeBookmarkIconFromActiveNavItem
@
$
(
'#sequence-list .nav-item'
).
on
(
'focus mouseenter'
,
@
displayTabTooltip
)
@
$
(
'#sequence-list .nav-item'
).
on
(
'blur mouseleave'
,
@
hideTabTooltip
)
displayTabTooltip
:
(
event
)
=>
$
(
event
.
currentTarget
).
find
(
'.sequence-tooltip'
).
removeClass
(
'sr'
)
hideTabTooltip
:
(
event
)
=>
$
(
event
.
currentTarget
).
find
(
'.sequence-tooltip'
).
addClass
(
'sr'
)
initProgress
:
->
@
progressTable
=
{}
#
"#problem_#{id}"
->
progress
updatePageTitle
:
->
#
update
the
page
title
to
include
the
current
section
position_link
=
@
link_for
(@
position
)
if
position_link
and
position_link
.
data
(
'page-title'
)
document
.
title
=
position_link
.
data
(
'page-title'
)
+
@
base_page_title
hookUpContentStateChangeEvent
:
->
$
(
'.problems-wrapper'
).
bind
(
'contentChanged'
,
(
event
,
problem_id
,
new_content_state
,
new_state
)
=>
@
addToUpdatedProblems
problem_id
,
new_content_state
,
new_state
)
addToUpdatedProblems
:
(
problem_id
,
new_content_state
,
new_state
)
=>
#
Used
to
keep
updated
problem
's state temporarily.
# params:
# '
problem_id
' is problem id.
# '
new_content_state
' is the updated content of the problem.
# '
new_state
' is the updated state of the problem.
# initialize for the current sequence if there isn'
t
any
updated
problem
#
for
this
position
.
if
not
@
anyUpdatedProblems
@
position
@
updatedProblems
[@
position
]
=
{}
#
Now
,
put
problem
content
and
score
against
problem
id
for
current
active
sequence
.
@
updatedProblems
[@
position
][
problem_id
]
=
[
new_content_state
,
new_state
]
anyUpdatedProblems
:(
position
)
->
#
check
for
the
updated
problems
for
given
sequence
position
.
#
params
:
#
'position'
can
be
any
sequence
position
.
return
@
updatedProblems
[
position
]
!=
undefined
hookUpProgressEvent
:
->
$
(
'.problems-wrapper'
).
bind
'progressChanged'
,
@
updateProgress
mergeProgress
:
(
p1
,
p2
)
->
#
if
either
is
"NA"
,
return
the
other
one
if
p1
==
"NA"
return
p2
if
p2
==
"NA"
return
p1
#
Both
real
progresses
if
p1
==
"done"
and
p2
==
"done"
return
"done"
#
not
done
,
so
if
any
progress
on
either
,
in_progress
w1
=
p1
==
"done"
or
p1
==
"in_progress"
w2
=
p2
==
"done"
or
p2
==
"in_progress"
if
w1
or
w2
return
"in_progress"
return
"none"
updateProgress
:
=>
new_progress
=
"NA"
_this
=
this
$
(
'.problems-wrapper'
).
each
(
index
)
->
progress
=
$
(
this
).
data
'progress_status'
new_progress
=
_this
.
mergeProgress
progress
,
new_progress
@
progressTable
[@
position
]
=
new_progress
enableButton
:
(
button_class
,
button_action
)
->
@
$
(
button_class
).
removeClass
(
'disabled'
).
removeAttr
(
'disabled'
).
click
(
button_action
)
disableButton
:
(
button_class
)
->
@
$
(
button_class
).
addClass
(
'disabled'
).
attr
(
'disabled'
,
true
)
setButtonLabel
:
(
button_class
,
button_label
)
->
@
$
(
button_class
+
' .sr'
).
html
(
button_label
)
updateButtonState
:
(
button_class
,
button_action
,
action_label_prefix
,
is_at_boundary
,
boundary_url
)
->
if
is_at_boundary
and
boundary_url
==
'None'
@
disableButton
(
button_class
)
else
button_label
=
action_label_prefix
+
(
if
is_at_boundary
then
' Subsection'
else
' Unit'
)
@
setButtonLabel
(
button_class
,
button_label
)
@
enableButton
(
button_class
,
button_action
)
toggleArrows
:
=>
@
$
(
'.sequence-nav-button'
).
unbind
(
'click'
)
#
previous
button
is_first_tab
=
@
position
==
1
previous_button_class
=
'.sequence-nav-button.button-previous'
@
updateButtonState
(
previous_button_class
,
@
selectPrevious
,
'Previous'
,
is_first_tab
,
@
prevUrl
)
#
next
button
is_last_tab
=
@
position
>=
@
contents
.
length
#
use
inequality
in
case
contents
.
length
is
0
and
position
is
1
.
next_button_class
=
'.sequence-nav-button.button-next'
@
updateButtonState
(
next_button_class
,
@
selectNext
,
'Next'
,
is_last_tab
,
@
nextUrl
)
render
:
(
new_position
)
->
if
@
position
!=
new_position
if
@
position
!=
undefined
@
mark_visited
@
position
modx_full_url
=
"#{@ajaxUrl}/goto_position"
$
.
postWithPrefix
modx_full_url
,
position
:
new_position
#
On
Sequence
change
,
fire
custom
event
"sequence:change"
on
element
.
#
Added
for
aborting
video
bufferization
,
see
..
/
video
/
10
_main
.
js
@
el
.
trigger
"sequence:change"
@
mark_active
new_position
current_tab
=
@
contents
.
eq
(
new_position
-
1
)
bookmarked
=
if
@
el
.
find
(
'.active .bookmark-icon'
).
hasClass
(
'bookmarked'
)
then
true
else
false
@
content_container
.
html
(
current_tab
.
text
()).
attr
(
"aria-labelledby"
,
current_tab
.
attr
(
"aria-labelledby"
)).
data
(
'bookmarked'
,
bookmarked
)
#
update
the
data
-
attributes
with
latest
contents
only
for
updated
problems
.
if
@
anyUpdatedProblems
new_position
$
.
each
@
updatedProblems
[
new_position
],
(
problem_id
,
latest_data
)
=>
latest_content
=
latest_data
[
0
]
latest_response
=
latest_data
[
1
]
@
content_container
.
find
(
"[data-problem-id='#{ problem_id }']"
)
.
data
(
'content'
,
latest_content
)
.
data
(
'problem-score'
,
latest_response
.
current_score
)
.
data
(
'problem-total-possible'
,
latest_response
.
total_possible
)
.
data
(
'attempts-used'
,
latest_response
.
attempts_used
)
XBlock
.
initializeBlocks
(@
content_container
,
@
requestToken
)
window
.
update_schematics
()
#
For
embedded
circuit
simulator
exercises
in
6.002
x
@
position
=
new_position
@
toggleArrows
()
@
hookUpContentStateChangeEvent
()
@
hookUpProgressEvent
()
@
updatePageTitle
()
sequence_links
=
@
content_container
.
find
(
'a.seqnav'
)
sequence_links
.
click
@
goto
@
path
.
text
(@
el
.
find
(
'.nav-item.active'
).
data
(
'path'
))
@
sr_container
.
focus
()
goto
:
(
event
)
=>
event
.
preventDefault
()
if
$
(
event
.
currentTarget
).
hasClass
'seqnav'
#
Links
from
courseware
<
a
class
=
'seqnav'
href
=
'n'
>
...
<
/a>, was .targe
t
new_position
=
$
(
event
.
currentTarget
).
attr
(
'href'
)
else
#
Tab
links
generated
by
backend
template
new_position
=
$
(
event
.
currentTarget
).
data
(
'element'
)
if
(
1
<=
new_position
)
and
(
new_position
<=
@
num_contents
)
is_bottom_nav
=
$
(
event
.
target
).
closest
(
'nav[class="sequence-bottom"]'
).
length
>
0
if
is_bottom_nav
widget_placement
=
'bottom'
else
widget_placement
=
'top'
Logger
.
log
"edx.ui.lms.sequence.tab_selected"
,
#
Formerly
known
as
seq_goto
current_tab
:
@
position
target_tab
:
new_position
tab_count
:
@
num_contents
id
:
@
id
// Generated by CoffeeScript 1.6.1
(
function
()
{
var
_this
=
this
;
this
.
Sequence
=
(
function
()
{
function
Sequence
(
element
)
{
var
_this
=
this
;
this
.
removeBookmarkIconFromActiveNavItem
=
function
(
event
)
{
return
Sequence
.
prototype
.
removeBookmarkIconFromActiveNavItem
.
apply
(
_this
,
arguments
);
};
this
.
addBookmarkIconToActiveNavItem
=
function
(
event
)
{
return
Sequence
.
prototype
.
addBookmarkIconToActiveNavItem
.
apply
(
_this
,
arguments
);
};
this
.
_change_sequential
=
function
(
direction
,
event
)
{
return
Sequence
.
prototype
.
_change_sequential
.
apply
(
_this
,
arguments
);
};
this
.
selectPrevious
=
function
(
event
)
{
return
Sequence
.
prototype
.
selectPrevious
.
apply
(
_this
,
arguments
);
};
this
.
selectNext
=
function
(
event
)
{
return
Sequence
.
prototype
.
selectNext
.
apply
(
_this
,
arguments
);
};
this
.
goto
=
function
(
event
)
{
return
Sequence
.
prototype
.
goto
.
apply
(
_this
,
arguments
);
};
this
.
toggleArrows
=
function
()
{
return
Sequence
.
prototype
.
toggleArrows
.
apply
(
_this
,
arguments
);
};
this
.
updateProgress
=
function
()
{
return
Sequence
.
prototype
.
updateProgress
.
apply
(
_this
,
arguments
);
};
this
.
addToUpdatedProblems
=
function
(
problem_id
,
new_content_state
,
new_state
)
{
return
Sequence
.
prototype
.
addToUpdatedProblems
.
apply
(
_this
,
arguments
);
};
this
.
hideTabTooltip
=
function
(
event
)
{
return
Sequence
.
prototype
.
hideTabTooltip
.
apply
(
_this
,
arguments
);
};
this
.
displayTabTooltip
=
function
(
event
)
{
return
Sequence
.
prototype
.
displayTabTooltip
.
apply
(
_this
,
arguments
);
};
this
.
updatedProblems
=
{};
this
.
requestToken
=
$
(
element
).
data
(
'request-token'
);
this
.
el
=
$
(
element
).
find
(
'.sequence'
);
this
.
path
=
$
(
'.path'
);
this
.
contents
=
this
.
$
(
'.seq_contents'
);
this
.
content_container
=
this
.
$
(
'#seq_content'
);
this
.
sr_container
=
this
.
$
(
'.sr-is-focusable'
);
this
.
num_contents
=
this
.
contents
.
length
;
this
.
id
=
this
.
el
.
data
(
'id'
);
this
.
ajaxUrl
=
this
.
el
.
data
(
'ajax-url'
);
this
.
nextUrl
=
this
.
el
.
data
(
'next-url'
);
this
.
prevUrl
=
this
.
el
.
data
(
'prev-url'
);
this
.
base_page_title
=
" | "
+
document
.
title
;
this
.
initProgress
();
this
.
bind
();
this
.
render
(
parseInt
(
this
.
el
.
data
(
'position'
)));
}
Sequence
.
prototype
.
$
=
function
(
selector
)
{
return
$
(
selector
,
this
.
el
);
};
Sequence
.
prototype
.
bind
=
function
()
{
this
.
$
(
'#sequence-list .nav-item'
).
click
(
this
.
goto
);
this
.
el
.
on
(
'bookmark:add'
,
this
.
addBookmarkIconToActiveNavItem
);
this
.
el
.
on
(
'bookmark:remove'
,
this
.
removeBookmarkIconFromActiveNavItem
);
this
.
$
(
'#sequence-list .nav-item'
).
on
(
'focus mouseenter'
,
this
.
displayTabTooltip
);
return
this
.
$
(
'#sequence-list .nav-item'
).
on
(
'blur mouseleave'
,
this
.
hideTabTooltip
);
};
Sequence
.
prototype
.
displayTabTooltip
=
function
(
event
)
{
return
$
(
event
.
currentTarget
).
find
(
'.sequence-tooltip'
).
removeClass
(
'sr'
);
};
Sequence
.
prototype
.
hideTabTooltip
=
function
(
event
)
{
return
$
(
event
.
currentTarget
).
find
(
'.sequence-tooltip'
).
addClass
(
'sr'
);
};
Sequence
.
prototype
.
initProgress
=
function
()
{
/*
"#problem_#{id}" -> progress
*/
return
this
.
progressTable
=
{};
};
Sequence
.
prototype
.
updatePageTitle
=
function
()
{
/*
update the page title to include the current section
*/
var
position_link
;
position_link
=
this
.
link_for
(
this
.
position
);
if
(
position_link
&&
position_link
.
data
(
'page-title'
))
{
return
document
.
title
=
position_link
.
data
(
'page-title'
)
+
this
.
base_page_title
;
}
};
Sequence
.
prototype
.
hookUpContentStateChangeEvent
=
function
()
{
var
_this
=
this
;
return
$
(
'.problems-wrapper'
).
bind
(
'contentChanged'
,
function
(
event
,
problem_id
,
new_content_state
,
new_state
)
{
return
_this
.
addToUpdatedProblems
(
problem_id
,
new_content_state
,
new_state
);
});
};
Sequence
.
prototype
.
addToUpdatedProblems
=
function
(
problem_id
,
new_content_state
,
new_state
)
{
/*
Used to keep updated problem's state temporarily.
*/
/*
params:
*/
/*
'problem_id' is problem id.
*/
/*
'new_content_state' is the updated content of the problem.
*/
/*
'new_state' is the updated state of the problem.
*/
/*
initialize for the current sequence if there isn't any updated problem
*/
/*
for this position.
*/
if
(
!
this
.
anyUpdatedProblems
(
this
.
position
))
{
this
.
updatedProblems
[
this
.
position
]
=
{};
}
/*
Now, put problem content and score against problem id for current active sequence.
*/
return
this
.
updatedProblems
[
this
.
position
][
problem_id
]
=
[
new_content_state
,
new_state
];
};
Sequence
.
prototype
.
anyUpdatedProblems
=
function
(
position
)
{
/*
check for the updated problems for given sequence position.
*/
/*
params:
*/
/*
'position' can be any sequence position.
*/
return
this
.
updatedProblems
[
position
]
!==
void
0
;
};
Sequence
.
prototype
.
hookUpProgressEvent
=
function
()
{
return
$
(
'.problems-wrapper'
).
bind
(
'progressChanged'
,
this
.
updateProgress
);
};
Sequence
.
prototype
.
mergeProgress
=
function
(
p1
,
p2
)
{
/*
if either is "NA", return the other one
*/
var
w1
,
w2
;
if
(
p1
===
"NA"
)
{
return
p2
;
}
if
(
p2
===
"NA"
)
{
return
p1
;
}
/*
Both real progresses
*/
if
(
p1
===
"done"
&&
p2
===
"done"
)
{
return
"done"
;
}
/*
not done, so if any progress on either, in_progress
*/
w1
=
p1
===
"done"
||
p1
===
"in_progress"
;
w2
=
p2
===
"done"
||
p2
===
"in_progress"
;
if
(
w1
||
w2
)
{
return
"in_progress"
;
}
return
"none"
;
};
Sequence
.
prototype
.
updateProgress
=
function
()
{
var
new_progress
;
new_progress
=
"NA"
;
_this
=
this
;
$
(
'.problems-wrapper'
).
each
(
function
(
index
)
{
var
progress
;
progress
=
$
(
this
).
data
(
'progress_status'
);
return
new_progress
=
_this
.
mergeProgress
(
progress
,
new_progress
);
});
return
this
.
progressTable
[
this
.
position
]
=
new_progress
;
};
Sequence
.
prototype
.
enableButton
=
function
(
button_class
,
button_action
)
{
return
this
.
$
(
button_class
).
removeClass
(
'disabled'
).
removeAttr
(
'disabled'
).
click
(
button_action
);
};
Sequence
.
prototype
.
disableButton
=
function
(
button_class
)
{
return
this
.
$
(
button_class
).
addClass
(
'disabled'
).
attr
(
'disabled'
,
true
);
};
Sequence
.
prototype
.
setButtonLabel
=
function
(
button_class
,
button_label
)
{
return
this
.
$
(
button_class
+
' .sr'
).
html
(
button_label
);
};
Sequence
.
prototype
.
updateButtonState
=
function
(
button_class
,
button_action
,
action_label_prefix
,
is_at_boundary
,
boundary_url
)
{
var
button_label
;
if
(
is_at_boundary
&&
boundary_url
===
'None'
)
{
return
this
.
disableButton
(
button_class
);
}
else
{
button_label
=
action_label_prefix
+
(
is_at_boundary
?
' Subsection'
:
' Unit'
);
this
.
setButtonLabel
(
button_class
,
button_label
);
return
this
.
enableButton
(
button_class
,
button_action
);
}
};
Sequence
.
prototype
.
toggleArrows
=
function
()
{
var
is_first_tab
,
is_last_tab
,
next_button_class
,
previous_button_class
;
this
.
$
(
'.sequence-nav-button'
).
unbind
(
'click'
);
/*
previous button
*/
is_first_tab
=
this
.
position
===
1
;
previous_button_class
=
'.sequence-nav-button.button-previous'
;
this
.
updateButtonState
(
previous_button_class
,
this
.
selectPrevious
,
'Previous'
,
is_first_tab
,
this
.
prevUrl
);
/*
next button
*/
/*
use inequality in case contents.length is 0 and position is 1.
*/
is_last_tab
=
this
.
position
>=
this
.
contents
.
length
;
next_button_class
=
'.sequence-nav-button.button-next'
;
return
this
.
updateButtonState
(
next_button_class
,
this
.
selectNext
,
'Next'
,
is_last_tab
,
this
.
nextUrl
);
};
Sequence
.
prototype
.
render
=
function
(
new_position
)
{
var
bookmarked
,
current_tab
,
modx_full_url
,
sequence_links
,
_this
=
this
;
if
(
this
.
position
!==
new_position
)
{
if
(
this
.
position
!==
void
0
)
{
this
.
mark_visited
(
this
.
position
);
modx_full_url
=
""
+
this
.
ajaxUrl
+
"/goto_position"
;
$
.
postWithPrefix
(
modx_full_url
,
{
position
:
new_position
});
}
/*
On Sequence change, fire custom event "sequence:change" on element.
*/
/*
Added for aborting video bufferization, see ../video/10_main.js
*/
this
.
el
.
trigger
(
"sequence:change"
);
this
.
mark_active
(
new_position
);
current_tab
=
this
.
contents
.
eq
(
new_position
-
1
);
bookmarked
=
this
.
el
.
find
(
'.active .bookmark-icon'
).
hasClass
(
'bookmarked'
)
?
true
:
false
;
this
.
content_container
.
html
(
current_tab
.
text
()).
attr
(
"aria-labelledby"
,
current_tab
.
attr
(
"aria-labelledby"
)).
data
(
'bookmarked'
,
bookmarked
);
/*
update the data-attributes with latest contents only for updated problems.
*/
if
(
this
.
anyUpdatedProblems
(
new_position
))
{
$
.
each
(
this
.
updatedProblems
[
new_position
],
function
(
problem_id
,
latest_data
)
{
var
latest_content
,
latest_response
;
latest_content
=
latest_data
[
0
];
latest_response
=
latest_data
[
1
];
return
_this
.
content_container
.
find
(
"[data-problem-id='"
+
problem_id
+
"']"
).
data
(
'content'
,
latest_content
).
data
(
'problem-score'
,
latest_response
.
current_score
).
data
(
'problem-total-possible'
,
latest_response
.
total_possible
).
data
(
'attempts-used'
,
latest_response
.
attempts_used
);
});
}
XBlock
.
initializeBlocks
(
this
.
content_container
,
this
.
requestToken
);
/*
For embedded circuit simulator exercises in 6.002x
*/
window
.
update_schematics
();
this
.
position
=
new_position
;
this
.
toggleArrows
();
this
.
hookUpContentStateChangeEvent
();
this
.
hookUpProgressEvent
();
this
.
updatePageTitle
();
sequence_links
=
this
.
content_container
.
find
(
'a.seqnav'
);
sequence_links
.
click
(
this
.
goto
);
this
.
path
.
text
(
this
.
el
.
find
(
'.nav-item.active'
).
data
(
'path'
));
return
this
.
sr_container
.
focus
();
}
};
Sequence
.
prototype
.
goto
=
function
(
event
)
{
var
alert_template
,
alert_text
,
is_bottom_nav
,
new_position
,
widget_placement
;
event
.
preventDefault
();
/*
Links from courseware <a class='seqnav' href='n'>...</a>, was .target
*/
if
(
$
(
event
.
currentTarget
).
hasClass
(
'seqnav'
))
{
new_position
=
$
(
event
.
currentTarget
).
attr
(
'href'
);
/*
Tab links generated by backend template
*/
}
else
{
new_position
=
$
(
event
.
currentTarget
).
data
(
'element'
);
}
if
((
1
<=
new_position
)
&&
(
new_position
<=
this
.
num_contents
))
{
is_bottom_nav
=
$
(
event
.
target
).
closest
(
'nav[class="sequence-bottom"]'
).
length
>
0
;
if
(
is_bottom_nav
)
{
widget_placement
=
'bottom'
;
}
else
{
widget_placement
=
'top'
;
}
/*
Formerly known as seq_goto
*/
Logger
.
log
(
"edx.ui.lms.sequence.tab_selected"
,
{
current_tab
:
this
.
position
,
target_tab
:
new_position
,
tab_count
:
this
.
num_contents
,
id
:
this
.
id
,
widget_placement
:
widget_placement
});
/*
On Sequence change, destroy any existing polling thread
*/
/*
for queued submissions, see ../capa/display.js
*/
if
(
window
.
queuePollerID
)
{
window
.
clearTimeout
(
window
.
queuePollerID
);
delete
window
.
queuePollerID
;
}
return
this
.
render
(
new_position
);
}
else
{
alert_template
=
gettext
(
"Sequence error! Cannot navigate to %(tab_name)s in the current SequenceModule. Please contact the course staff."
);
alert_text
=
interpolate
(
alert_template
,
{
tab_name
:
new_position
},
true
);
return
alert
(
alert_text
);
}
};
Sequence
.
prototype
.
selectNext
=
function
(
event
)
{
return
this
.
_change_sequential
(
'next'
,
event
);
};
Sequence
.
prototype
.
selectPrevious
=
function
(
event
)
{
return
this
.
_change_sequential
(
'previous'
,
event
);
};
/*
`direction` can be 'previous' or 'next'
*/
Sequence
.
prototype
.
_change_sequential
=
function
(
direction
,
event
)
{
/*
silently abort if direction is invalid.
*/
var
analytics_event_name
,
is_bottom_nav
,
new_position
,
offset
,
widget_placement
;
if
(
direction
!==
'previous'
&&
direction
!==
'next'
)
{
return
;
}
event
.
preventDefault
();
analytics_event_name
=
"edx.ui.lms.sequence."
+
direction
+
"_selected"
;
is_bottom_nav
=
$
(
event
.
target
).
closest
(
'nav[class="sequence-bottom"]'
).
length
>
0
;
if
(
is_bottom_nav
)
{
widget_placement
=
'bottom'
;
}
else
{
widget_placement
=
'top'
;
}
/*
Formerly known as seq_next and seq_prev
*/
Logger
.
log
(
analytics_event_name
,
{
id
:
this
.
id
,
current_tab
:
this
.
position
,
tab_count
:
this
.
num_contents
,
widget_placement
:
widget_placement
#
On
Sequence
change
,
destroy
any
existing
polling
thread
#
for
queued
submissions
,
see
..
/
capa
/
display
.
js
if
window
.
queuePollerID
window
.
clearTimeout
(
window
.
queuePollerID
)
delete
window
.
queuePollerID
@
render
new_position
else
alert_template
=
gettext
(
"Sequence error! Cannot navigate to %(tab_name)s in the current SequenceModule. Please contact the course staff."
)
alert_text
=
interpolate
(
alert_template
,
{
tab_name
:
new_position
},
true
)
alert
alert_text
selectNext
:
(
event
)
=>
@
_change_sequential
'next'
,
event
selectPrevious
:
(
event
)
=>
@
_change_sequential
'previous'
,
event
#
`direction`
can
be
'previous'
or
'next'
_change_sequential
:
(
direction
,
event
)
=>
#
silently
abort
if
direction
is
invalid
.
return
unless
direction
in
[
'previous'
,
'next'
]
event
.
preventDefault
()
analytics_event_name
=
"edx.ui.lms.sequence.#{direction}_selected"
is_bottom_nav
=
$
(
event
.
target
).
closest
(
'nav[class="sequence-bottom"]'
).
length
>
0
if
is_bottom_nav
widget_placement
=
'bottom'
else
widget_placement
=
'top'
Logger
.
log
analytics_event_name
,
#
Formerly
known
as
seq_next
and
seq_prev
id
:
@
id
current_tab
:
@
position
tab_count
:
@
num_contents
widget_placement
:
widget_placement
if
(
direction
==
'next'
)
and
(@
position
>=
@
contents
.
length
)
window
.
location
.
href
=
@
nextUrl
else
if
(
direction
==
'previous'
)
and
(@
position
==
1
)
window
.
location
.
href
=
@
prevUrl
else
#
If
the
bottom
nav
is
used
,
scroll
to
the
top
of
the
page
on
change
.
if
is_bottom_nav
$
.
scrollTo
0
,
150
offset
=
next
:
1
previous
:
-
1
new_position
=
@
position
+
offset
[
direction
]
@
render
new_position
link_for
:
(
position
)
->
@
$
(
"#sequence-list .nav-item[data-element=#{position}]"
)
mark_visited
:
(
position
)
->
#
Don
't overwrite class attribute to avoid changing Progress class
element = @link_for(position)
element.removeClass("inactive")
.removeClass("active")
.addClass("visited")
mark_active: (position) ->
# Don'
t
overwrite
class
attribute
to
avoid
changing
Progress
class
element
=
@
link_for
(
position
)
element
.
removeClass
(
"inactive"
)
.
removeClass
(
"visited"
)
.
addClass
(
"active"
)
addBookmarkIconToActiveNavItem
:
(
event
)
=>
event
.
preventDefault
()
@
el
.
find
(
'.nav-item.active .bookmark-icon'
).
removeClass
(
'is-hidden'
).
addClass
(
'bookmarked'
)
@
el
.
find
(
'.nav-item.active .bookmark-icon-sr'
).
text
(
gettext
(
'Bookmarked'
))
removeBookmarkIconFromActiveNavItem
:
(
event
)
=>
event
.
preventDefault
()
@
el
.
find
(
'.nav-item.active .bookmark-icon'
).
removeClass
(
'bookmarked'
).
addClass
(
'is-hidden'
)
@
el
.
find
(
'.nav-item.active .bookmark-icon-sr'
).
text
(
''
)
});
if
((
direction
===
'next'
)
&&
(
this
.
position
>=
this
.
contents
.
length
))
{
return
window
.
location
.
href
=
this
.
nextUrl
;
}
else
if
((
direction
===
'previous'
)
&&
(
this
.
position
===
1
))
{
return
window
.
location
.
href
=
this
.
prevUrl
;
}
else
{
/*
If the bottom nav is used, scroll to the top of the page on change.
*/
if
(
is_bottom_nav
)
{
$
.
scrollTo
(
0
,
150
);
}
offset
=
{
next
:
1
,
previous
:
-
1
};
new_position
=
this
.
position
+
offset
[
direction
];
return
this
.
render
(
new_position
);
}
};
Sequence
.
prototype
.
link_for
=
function
(
position
)
{
return
this
.
$
(
"#sequence-list .nav-item[data-element="
+
position
+
"]"
);
};
Sequence
.
prototype
.
mark_visited
=
function
(
position
)
{
/*
Don't overwrite class attribute to avoid changing Progress class
*/
var
element
;
element
=
this
.
link_for
(
position
);
return
element
.
removeClass
(
"inactive"
).
removeClass
(
"active"
).
addClass
(
"visited"
);
};
Sequence
.
prototype
.
mark_active
=
function
(
position
)
{
/*
Don't overwrite class attribute to avoid changing Progress class
*/
var
element
;
element
=
this
.
link_for
(
position
);
return
element
.
removeClass
(
"inactive"
).
removeClass
(
"visited"
).
addClass
(
"active"
);
};
Sequence
.
prototype
.
addBookmarkIconToActiveNavItem
=
function
(
event
)
{
event
.
preventDefault
();
this
.
el
.
find
(
'.nav-item.active .bookmark-icon'
).
removeClass
(
'is-hidden'
).
addClass
(
'bookmarked'
);
return
this
.
el
.
find
(
'.nav-item.active .bookmark-icon-sr'
).
text
(
gettext
(
'Bookmarked'
));
};
Sequence
.
prototype
.
removeBookmarkIconFromActiveNavItem
=
function
(
event
)
{
event
.
preventDefault
();
this
.
el
.
find
(
'.nav-item.active .bookmark-icon'
).
removeClass
(
'bookmarked'
).
addClass
(
'is-hidden'
);
return
this
.
el
.
find
(
'.nav-item.active .bookmark-icon-sr'
).
text
(
''
);
};
return
Sequence
;
})();
}).
call
(
this
);
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