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