Merge pull request #2822 from edx/valera/convert_collapsible_to_js
Converting Collapsible module to JS.
This commit is contained in:
@@ -40,11 +40,16 @@ class AnnotatableFields(object):
|
||||
|
||||
|
||||
class AnnotatableModule(AnnotatableFields, XModule):
|
||||
js = {'coffee': [resource_string(__name__, 'js/src/javascript_loader.coffee'),
|
||||
resource_string(__name__, 'js/src/collapsible.coffee'),
|
||||
resource_string(__name__, 'js/src/html/display.coffee'),
|
||||
resource_string(__name__, 'js/src/annotatable/display.coffee')],
|
||||
'js': []}
|
||||
js = {
|
||||
'coffee': [
|
||||
resource_string(__name__, 'js/src/javascript_loader.coffee'),
|
||||
resource_string(__name__, 'js/src/html/display.coffee'),
|
||||
resource_string(__name__, 'js/src/annotatable/display.coffee'),
|
||||
],
|
||||
'js': [
|
||||
resource_string(__name__, 'js/src/collapsible.js'),
|
||||
]
|
||||
}
|
||||
js_module_name = "Annotatable"
|
||||
css = {'scss': [resource_string(__name__, 'css/annotatable/display.scss')]}
|
||||
icon_class = 'annotatable'
|
||||
|
||||
@@ -23,13 +23,17 @@ class CapaModule(CapaMixin, XModule):
|
||||
"""
|
||||
icon_class = 'problem'
|
||||
|
||||
js = {'coffee': [resource_string(__name__, 'js/src/capa/display.coffee'),
|
||||
resource_string(__name__, 'js/src/collapsible.coffee'),
|
||||
resource_string(__name__, 'js/src/javascript_loader.coffee'),
|
||||
],
|
||||
'js': [resource_string(__name__, 'js/src/capa/imageinput.js'),
|
||||
resource_string(__name__, 'js/src/capa/schematic.js')
|
||||
]}
|
||||
js = {
|
||||
'coffee': [
|
||||
resource_string(__name__, 'js/src/capa/display.coffee'),
|
||||
resource_string(__name__, 'js/src/javascript_loader.coffee'),
|
||||
],
|
||||
'js': [
|
||||
resource_string(__name__, 'js/src/collapsible.js'),
|
||||
resource_string(__name__, 'js/src/capa/imageinput.js'),
|
||||
resource_string(__name__, 'js/src/capa/schematic.js'),
|
||||
]
|
||||
}
|
||||
|
||||
js_module_name = "Problem"
|
||||
css = {'scss': [resource_string(__name__, 'css/capa/display.scss')]}
|
||||
|
||||
@@ -395,12 +395,13 @@ class CombinedOpenEndedModule(CombinedOpenEndedFields, XModule):
|
||||
icon_class = 'problem'
|
||||
|
||||
js = {
|
||||
'coffee':
|
||||
[
|
||||
resource_string(__name__, 'js/src/combinedopenended/display.coffee'),
|
||||
resource_string(__name__, 'js/src/collapsible.coffee'),
|
||||
resource_string(__name__, 'js/src/javascript_loader.coffee'),
|
||||
]
|
||||
'coffee': [
|
||||
resource_string(__name__, 'js/src/combinedopenended/display.coffee'),
|
||||
resource_string(__name__, 'js/src/javascript_loader.coffee'),
|
||||
],
|
||||
'js': [
|
||||
resource_string(__name__, 'js/src/collapsible.js'),
|
||||
]
|
||||
}
|
||||
js_module_name = "CombinedOpenEnded"
|
||||
|
||||
|
||||
@@ -63,10 +63,15 @@ class ConditionalModule(ConditionalFields, XModule):
|
||||
|
||||
"""
|
||||
|
||||
js = {'coffee': [resource_string(__name__, 'js/src/javascript_loader.coffee'),
|
||||
resource_string(__name__, 'js/src/conditional/display.coffee'),
|
||||
resource_string(__name__, 'js/src/collapsible.coffee'),
|
||||
]}
|
||||
js = {
|
||||
'coffee': [
|
||||
resource_string(__name__, 'js/src/javascript_loader.coffee'),
|
||||
resource_string(__name__, 'js/src/conditional/display.coffee'),
|
||||
],
|
||||
'js': [
|
||||
resource_string(__name__, 'js/src/collapsible.js'),
|
||||
]
|
||||
}
|
||||
|
||||
js_module_name = "Conditional"
|
||||
css = {'scss': [resource_string(__name__, 'css/capa/display.scss')]}
|
||||
|
||||
@@ -42,12 +42,12 @@ class HtmlModule(HtmlFields, XModule):
|
||||
js = {
|
||||
'coffee': [
|
||||
resource_string(__name__, 'js/src/javascript_loader.coffee'),
|
||||
resource_string(__name__, 'js/src/collapsible.coffee'),
|
||||
resource_string(__name__, 'js/src/html/display.coffee')
|
||||
resource_string(__name__, 'js/src/html/display.coffee'),
|
||||
],
|
||||
'js': [
|
||||
resource_string(__name__, 'js/src/collapsible.js'),
|
||||
resource_string(__name__, 'js/src/html/imageModal.js'),
|
||||
resource_string(__name__, 'js/common_static/js/vendor/draggabilly.pkgd.js')
|
||||
resource_string(__name__, 'js/common_static/js/vendor/draggabilly.pkgd.js'),
|
||||
]
|
||||
}
|
||||
js_module_name = "HTMLModule"
|
||||
|
||||
@@ -5,3 +5,4 @@
|
||||
|
||||
# Tests for Time are written in pure JavaScript.
|
||||
!time_spec.js
|
||||
!collapsible_spec.js
|
||||
|
||||
@@ -1,115 +0,0 @@
|
||||
describe 'Collapsible', ->
|
||||
html = custom_labels = html_custom = el = undefined
|
||||
|
||||
initialize = (template) =>
|
||||
setFixtures(template)
|
||||
el = $('.collapsible')
|
||||
Collapsible.setCollapsibles(el)
|
||||
|
||||
disableFx = () =>
|
||||
$.fx.off = true
|
||||
|
||||
enableFx = () =>
|
||||
$.fx.off = false
|
||||
|
||||
beforeEach ->
|
||||
html = '''
|
||||
<section class="collapsible">
|
||||
<div class="shortform">
|
||||
shortform message
|
||||
</div>
|
||||
<div class="longform">
|
||||
<p>longform is visible</p>
|
||||
</div>
|
||||
</section>
|
||||
'''
|
||||
html_custom = '''
|
||||
<section class="collapsible">
|
||||
<div class="shortform-custom" data-open-text="Show shortform-custom" data-close-text="Hide shortform-custom">
|
||||
shortform message
|
||||
</div>
|
||||
<div class="longform">
|
||||
<p>longform is visible</p>
|
||||
</div>
|
||||
</section>
|
||||
'''
|
||||
|
||||
describe 'setCollapsibles', ->
|
||||
|
||||
it 'Default container initialized correctly', ->
|
||||
initialize(html)
|
||||
|
||||
expect(el.find('.shortform')).toContain '.full-top'
|
||||
expect(el.find('.shortform')).toContain '.full-bottom'
|
||||
expect(el.find('.longform')).toBeHidden()
|
||||
expect(el.find('.full')).toHandle('click')
|
||||
|
||||
it 'Custom container initialized correctly', ->
|
||||
initialize(html_custom)
|
||||
|
||||
expect(el.find('.shortform-custom')).toContain '.full-custom'
|
||||
expect(el.find('.full-custom')).toHaveText "Show shortform-custom"
|
||||
expect(el.find('.longform')).toBeHidden()
|
||||
expect(el.find('.full-custom')).toHandle('click')
|
||||
|
||||
describe 'toggleFull', ->
|
||||
|
||||
beforeEach ->
|
||||
disableFx()
|
||||
|
||||
afterEach ->
|
||||
enableFx()
|
||||
|
||||
it 'Default container', ->
|
||||
initialize(html)
|
||||
|
||||
event = jQuery.Event('click', {
|
||||
target: el.find('.full').get(0)
|
||||
})
|
||||
|
||||
assertChanges = (state='closed') =>
|
||||
anchors = el.find('.full')
|
||||
|
||||
if state is 'closed'
|
||||
expect(el.find('.longform')).toBeHidden()
|
||||
expect(el).not.toHaveClass('open')
|
||||
text = "See full output"
|
||||
else
|
||||
expect(el.find('.longform')).toBeVisible()
|
||||
expect(el).toHaveClass('open')
|
||||
text = "Hide output"
|
||||
|
||||
$.each anchors, (index, el) =>
|
||||
expect(el).toHaveText text
|
||||
|
||||
Collapsible.toggleFull(event, "See full output", "Hide output")
|
||||
assertChanges('opened')
|
||||
Collapsible.toggleFull(event, "See full output", "Hide output")
|
||||
assertChanges('closed')
|
||||
|
||||
it 'Custom container', ->
|
||||
initialize(html_custom)
|
||||
|
||||
event = jQuery.Event('click', {
|
||||
target: el.find('.full-custom').get(0)
|
||||
})
|
||||
|
||||
assertChanges = (state='closed') =>
|
||||
anchors = el.find('.full-custom')
|
||||
|
||||
if state is 'closed'
|
||||
expect(el.find('.longform')).toBeHidden()
|
||||
expect(el).not.toHaveClass('open')
|
||||
text = "Show shortform-custom"
|
||||
else
|
||||
expect(el.find('.longform')).toBeVisible()
|
||||
expect(el).toHaveClass('open')
|
||||
text = "Hide shortform-custom"
|
||||
|
||||
$.each anchors, (index, el) =>
|
||||
expect(el).toHaveText text
|
||||
|
||||
Collapsible.toggleFull(event, "Show shortform-custom", "Hide shortform-custom")
|
||||
assertChanges('opened')
|
||||
Collapsible.toggleFull(event, "Show shortform-custom", "Hide shortform-custom")
|
||||
assertChanges('closed')
|
||||
125
common/lib/xmodule/xmodule/js/spec/collapsible_spec.js
Normal file
125
common/lib/xmodule/xmodule/js/spec/collapsible_spec.js
Normal file
@@ -0,0 +1,125 @@
|
||||
(function (undefined) {
|
||||
'use strict';
|
||||
|
||||
describe('Collapsible', function () {
|
||||
var el, html, html_custom,
|
||||
initialize = function (template) {
|
||||
setFixtures(template);
|
||||
el = $('.collapsible');
|
||||
Collapsible.setCollapsibles(el);
|
||||
},
|
||||
disableFx = function () {
|
||||
$.fx.off = true;
|
||||
},
|
||||
enableFx = function () {
|
||||
$.fx.off = false;
|
||||
};
|
||||
|
||||
beforeEach(function () {
|
||||
html = '' +
|
||||
'<section class="collapsible">' +
|
||||
'<div class="shortform">shortform message</div>' +
|
||||
'<div class="longform">' +
|
||||
'<p>longform is visible</p>' +
|
||||
'</div>' +
|
||||
'</section>';
|
||||
html_custom = '' +
|
||||
'<section class="collapsible">' +
|
||||
'<div ' +
|
||||
'class="shortform-custom" ' +
|
||||
'data-open-text="Show shortform-custom" ' +
|
||||
'data-close-text="Hide shortform-custom"' +
|
||||
'>shortform message</div>' +
|
||||
'<div class="longform">' +
|
||||
'<p>longform is visible</p>' +
|
||||
'</div>' +
|
||||
'</section>';
|
||||
});
|
||||
|
||||
describe('setCollapsibles', function () {
|
||||
it('Default container initialized correctly', function () {
|
||||
initialize(html);
|
||||
|
||||
expect(el.find('.shortform')).toContain('.full-top');
|
||||
expect(el.find('.shortform')).toContain('.full-bottom');
|
||||
expect(el.find('.longform')).toBeHidden();
|
||||
expect(el.find('.full')).toHandle('click');
|
||||
});
|
||||
|
||||
it('Custom container initialized correctly', function () {
|
||||
initialize(html_custom);
|
||||
|
||||
expect(el.find('.shortform-custom')).toContain('.full-custom');
|
||||
expect(el.find('.full-custom')).toHaveText('Show shortform-custom');
|
||||
expect(el.find('.longform')).toBeHidden();
|
||||
expect(el.find('.full-custom')).toHandle('click');
|
||||
});
|
||||
});
|
||||
|
||||
describe('toggleFull', function () {
|
||||
var assertChanges = function (state, anchorsElClass, showText, hideText) {
|
||||
var anchors, text;
|
||||
|
||||
if (state == null) {
|
||||
state = 'closed';
|
||||
}
|
||||
|
||||
anchors = el.find('.' + anchorsElClass);
|
||||
|
||||
if (state === 'closed') {
|
||||
expect(el.find('.longform')).toBeHidden();
|
||||
expect(el).not.toHaveClass('open');
|
||||
text = showText;
|
||||
} else {
|
||||
expect(el.find('.longform')).toBeVisible();
|
||||
expect(el).toHaveClass('open');
|
||||
text = hideText;
|
||||
}
|
||||
|
||||
$.each(anchors, function (index, el) {
|
||||
expect(el).toHaveText(text);
|
||||
});
|
||||
};
|
||||
|
||||
beforeEach(function () {
|
||||
disableFx();
|
||||
});
|
||||
|
||||
afterEach(function () {
|
||||
enableFx();
|
||||
});
|
||||
|
||||
it('Default container', function () {
|
||||
var event;
|
||||
|
||||
initialize(html);
|
||||
|
||||
event = jQuery.Event('click', {
|
||||
target: el.find('.full').get(0)
|
||||
});
|
||||
|
||||
Collapsible.toggleFull(event, 'See full output', 'Hide output');
|
||||
assertChanges('opened', 'full', 'See full output', 'Hide output');
|
||||
|
||||
Collapsible.toggleFull(event, 'See full output', 'Hide output');
|
||||
assertChanges('closed', 'full', 'See full output', 'Hide output');
|
||||
});
|
||||
|
||||
it('Custom container', function () {
|
||||
var event;
|
||||
|
||||
initialize(html_custom);
|
||||
|
||||
event = jQuery.Event('click', {
|
||||
target: el.find('.full-custom').get(0)
|
||||
});
|
||||
|
||||
Collapsible.toggleFull(event, 'Show shortform-custom', 'Hide shortform-custom');
|
||||
assertChanges('opened', 'full-custom', 'Show shortform-custom', 'Hide shortform-custom');
|
||||
|
||||
Collapsible.toggleFull(event, 'Show shortform-custom', 'Hide shortform-custom');
|
||||
assertChanges('closed', 'full-custom', 'Show shortform-custom', 'Hide shortform-custom');
|
||||
});
|
||||
});
|
||||
});
|
||||
}).call(this);
|
||||
1
common/lib/xmodule/xmodule/js/src/.gitignore
vendored
1
common/lib/xmodule/xmodule/js/src/.gitignore
vendored
@@ -11,3 +11,4 @@
|
||||
|
||||
# Converted to JS from CoffeeScript.
|
||||
!time.js
|
||||
!collapsible.js
|
||||
|
||||
@@ -1,53 +0,0 @@
|
||||
class @Collapsible
|
||||
|
||||
# Set of library functions that provide a simple way to add collapsible
|
||||
# functionality to elements.
|
||||
|
||||
# setCollapsibles:
|
||||
# Scan element's content for generic collapsible containers
|
||||
@setCollapsibles: (el) =>
|
||||
###
|
||||
el: container
|
||||
###
|
||||
linkTop = '<a href="#" class="full full-top">See full output</a>'
|
||||
linkBottom = '<a href="#" class="full full-bottom">See full output</a>'
|
||||
|
||||
# standard longform + shortfom pattern
|
||||
el.find('.longform').hide()
|
||||
el.find('.shortform').append(linkTop, linkBottom)
|
||||
|
||||
# custom longform + shortform text pattern
|
||||
short_custom = el.find('.shortform-custom')
|
||||
# set up each one individually
|
||||
short_custom.each (index, elt) =>
|
||||
open_text = $(elt).data('open-text')
|
||||
close_text = $(elt).data('close-text')
|
||||
$(elt).append("<a href='#' class='full-custom'>"+ open_text + "</a>")
|
||||
$(elt).find('.full-custom').click (event) => @toggleFull(event, open_text, close_text)
|
||||
|
||||
# collapsible pattern
|
||||
el.find('.collapsible header + section').hide()
|
||||
|
||||
# set up triggers
|
||||
el.find('.full').click (event) => @toggleFull(event, "See full output", "Hide output")
|
||||
el.find('.collapsible header a').click @toggleHint
|
||||
|
||||
@toggleFull: (event, open_text, close_text) =>
|
||||
event.preventDefault()
|
||||
parent = $(event.target).parent()
|
||||
parent.siblings().slideToggle()
|
||||
parent.parent().toggleClass('open')
|
||||
if $(event.target).text() == open_text
|
||||
new_text = close_text
|
||||
else
|
||||
new_text = open_text
|
||||
if $(event.target).hasClass('full')
|
||||
el = parent.find('.full')
|
||||
else
|
||||
el = $(event.target)
|
||||
el.text(new_text)
|
||||
|
||||
@toggleHint: (event) =>
|
||||
event.preventDefault()
|
||||
$(event.target).parent().siblings().slideToggle()
|
||||
$(event.target).parent().parent().toggleClass('open')
|
||||
110
common/lib/xmodule/xmodule/js/src/collapsible.js
Normal file
110
common/lib/xmodule/xmodule/js/src/collapsible.js
Normal file
@@ -0,0 +1,110 @@
|
||||
(function (undefined) {
|
||||
'use strict';
|
||||
|
||||
// [module Collapsible]
|
||||
//
|
||||
// [description]
|
||||
// Set of library functions that provide a simple way to add
|
||||
// collapsible functionality to elements.
|
||||
this.Collapsible = {
|
||||
setCollapsibles: setCollapsibles,
|
||||
toggleFull: toggleFull,
|
||||
toggleHint: toggleHint
|
||||
};
|
||||
|
||||
return;
|
||||
|
||||
// [function setCollapsibles]
|
||||
//
|
||||
// [description]
|
||||
// Scan element's content for generic collapsible containers.
|
||||
//
|
||||
// [params]
|
||||
// el: container
|
||||
function setCollapsibles(el) {
|
||||
var linkBottom, linkTop, short_custom;
|
||||
|
||||
linkTop = '<a href="#" class="full full-top">See full output</a>';
|
||||
linkBottom = '<a href="#" class="full full-bottom">See full output</a>';
|
||||
|
||||
// Standard longform + shortfom pattern.
|
||||
el.find('.longform').hide();
|
||||
el.find('.shortform').append(linkTop, linkBottom);
|
||||
|
||||
// Custom longform + shortform text pattern.
|
||||
short_custom = el.find('.shortform-custom');
|
||||
|
||||
// Set up each one individually.
|
||||
short_custom.each(function (index, elt) {
|
||||
var close_text, open_text;
|
||||
|
||||
open_text = $(elt).data('open-text');
|
||||
close_text = $(elt).data('close-text');
|
||||
$(elt).append("<a href='#' class='full-custom'>" + open_text + "</a>");
|
||||
|
||||
$(elt).find('.full-custom').click(function (event) {
|
||||
Collapsible.toggleFull(event, open_text, close_text);
|
||||
});
|
||||
});
|
||||
|
||||
// Collapsible pattern.
|
||||
el.find('.collapsible header + section').hide();
|
||||
|
||||
// Set up triggers.
|
||||
el.find('.full').click(function (event) {
|
||||
Collapsible.toggleFull(event, "See full output", "Hide output");
|
||||
});
|
||||
el.find('.collapsible header a').click(Collapsible.toggleHint);
|
||||
}
|
||||
|
||||
// [function toggleFull]
|
||||
//
|
||||
// [description]
|
||||
// Toggle the display of full text for a collapsible element.
|
||||
//
|
||||
// [params]
|
||||
// event: jQuery event object associated with the event that
|
||||
// triggered this callback function.
|
||||
// open_text: text that should be displayed when the collapsible
|
||||
// is open.
|
||||
// close_text: text that should be displayed when the collapsible
|
||||
// is closed.
|
||||
function toggleFull(event, open_text, close_text) {
|
||||
var el, new_text, parent;
|
||||
|
||||
event.preventDefault();
|
||||
|
||||
parent = $(event.target).parent();
|
||||
parent.siblings().slideToggle();
|
||||
parent.parent().toggleClass('open');
|
||||
|
||||
if ($(event.target).text() === open_text) {
|
||||
new_text = close_text;
|
||||
} else {
|
||||
new_text = open_text;
|
||||
}
|
||||
|
||||
if ($(event.target).hasClass('full')) {
|
||||
el = parent.find('.full');
|
||||
} else {
|
||||
el = $(event.target);
|
||||
}
|
||||
|
||||
el.text(new_text);
|
||||
}
|
||||
|
||||
// [function toggleHint]
|
||||
//
|
||||
// [description]
|
||||
// Toggle the collapsible open to show the hint.
|
||||
//
|
||||
// [params]
|
||||
// event: jQuery event object associated with the event that
|
||||
// triggered this callback function.
|
||||
function toggleHint(event) {
|
||||
event.preventDefault();
|
||||
|
||||
$(event.target).parent().siblings().slideToggle();
|
||||
$(event.target).parent().parent().toggleClass('open');
|
||||
}
|
||||
}).call(this);
|
||||
@@ -100,8 +100,10 @@ class PeerGradingModule(PeerGradingFields, XModule):
|
||||
'coffee': [
|
||||
resource_string(__name__, 'js/src/peergrading/peer_grading.coffee'),
|
||||
resource_string(__name__, 'js/src/peergrading/peer_grading_problem.coffee'),
|
||||
resource_string(__name__, 'js/src/collapsible.coffee'),
|
||||
resource_string(__name__, 'js/src/javascript_loader.coffee'),
|
||||
],
|
||||
'js': [
|
||||
resource_string(__name__, 'js/src/collapsible.js'),
|
||||
]
|
||||
}
|
||||
js_module_name = "PeerGrading"
|
||||
@@ -718,4 +720,3 @@ class PeerGradingDescriptor(PeerGradingFields, RawDescriptor):
|
||||
show_calibration_essay = module_attr('show_calibration_essay')
|
||||
use_for_single_location_local = module_attr('use_for_single_location_local')
|
||||
_find_corresponding_module_for_location = module_attr('_find_corresponding_module_for_location')
|
||||
|
||||
|
||||
@@ -35,12 +35,16 @@ class AnnotatableFields(object):
|
||||
|
||||
class VideoAnnotationModule(AnnotatableFields, XModule):
|
||||
'''Video Annotation Module'''
|
||||
js = {'coffee': [resource_string(__name__, 'js/src/javascript_loader.coffee'),
|
||||
resource_string(__name__, 'js/src/collapsible.coffee'),
|
||||
resource_string(__name__, 'js/src/html/display.coffee'),
|
||||
resource_string(__name__, 'js/src/annotatable/display.coffee')
|
||||
],
|
||||
'js': []}
|
||||
js = {
|
||||
'coffee': [
|
||||
resource_string(__name__, 'js/src/javascript_loader.coffee'),
|
||||
resource_string(__name__, 'js/src/html/display.coffee'),
|
||||
resource_string(__name__, 'js/src/annotatable/display.coffee'),
|
||||
],
|
||||
'js': [
|
||||
resource_string(__name__, 'js/src/collapsible.js'),
|
||||
]
|
||||
}
|
||||
css = {'scss': [resource_string(__name__, 'css/annotatable/display.scss')]}
|
||||
icon_class = 'videoannotation'
|
||||
|
||||
|
||||
Reference in New Issue
Block a user