Drop remaining coffee use
This basically commits the transpiled CoffeeScript JS (with minor cleanup) and removes coffee build support. A tiny amount of support for xblocks exists, because external users may have xblocks with coffee. But no coffee in our tree anyway.
This commit is contained in:
committed by
Michael Terry
parent
2abbd1eb83
commit
a34c8c8233
@@ -20,13 +20,6 @@ test_root/staticfiles
|
|||||||
common/static/xmodule
|
common/static/xmodule
|
||||||
|
|
||||||
|
|
||||||
# Coffeescript directories (don't lint autogenerated files)
|
|
||||||
cms/static/coffee
|
|
||||||
lms/static/coffee
|
|
||||||
common/static/coffee
|
|
||||||
common/lib/capa/capa/tests/test_files/js
|
|
||||||
|
|
||||||
|
|
||||||
# Symlinks into common/lib/xmodule/xmodule/js
|
# Symlinks into common/lib/xmodule/xmodule/js
|
||||||
cms/static/xmodule_js
|
cms/static/xmodule_js
|
||||||
lms/static/xmodule_js
|
lms/static/xmodule_js
|
||||||
@@ -36,27 +29,40 @@ lms/static/xmodule_js
|
|||||||
cms/djangoapps/pipeline_js/templates
|
cms/djangoapps/pipeline_js/templates
|
||||||
|
|
||||||
|
|
||||||
# This directory is about half Coffee and half JS, things get messy here so just ignore all existing coffee paths
|
# These are es2015 spec files that used to be in an ignored path.
|
||||||
|
# Now they live with the rest of the code, but we want to ignore them
|
||||||
|
# until the surrounding code is es2015 and we have a chance to clean them.
|
||||||
|
# We need to ignore them here, because es2015 will cause a parse error
|
||||||
|
# even if we add an eslint-disable line to the file.
|
||||||
|
cms/static/js/spec/models/course_spec.js
|
||||||
|
cms/static/js/spec/models/metadata_spec.js
|
||||||
|
cms/static/js/spec/models/section_spec.js
|
||||||
|
cms/static/js/spec/models/settings_course_grader_spec.js
|
||||||
|
cms/static/js/spec/models/settings_grading_spec.js
|
||||||
|
cms/static/js/spec/models/textbook_spec.js
|
||||||
|
cms/static/js/spec/models/upload_spec.js
|
||||||
|
cms/static/js/spec/views/assets_squire_spec.js
|
||||||
|
cms/static/js/spec/views/course_info_spec.js
|
||||||
|
cms/static/js/spec/views/metadata_edit_spec.js
|
||||||
|
cms/static/js/spec/views/textbook_spec.js
|
||||||
|
cms/static/js/spec/views/upload_spec.js
|
||||||
|
common/lib/capa/capa/tests/test_files/js/test_problem_display.js
|
||||||
|
common/lib/capa/capa/tests/test_files/js/test_problem_generator.js
|
||||||
|
common/lib/capa/capa/tests/test_files/js/test_problem_grader.js
|
||||||
|
common/lib/capa/capa/tests/test_files/js/xproblem.js
|
||||||
common/lib/xmodule/xmodule/js/spec/annotatable/display_spec.js
|
common/lib/xmodule/xmodule/js/spec/annotatable/display_spec.js
|
||||||
common/lib/xmodule/xmodule/js/spec/capa/display_spec.js
|
common/lib/xmodule/xmodule/js/spec/capa/display_spec.js
|
||||||
common/lib/xmodule/xmodule/js/spec/html/edit_spec.js
|
common/lib/xmodule/xmodule/js/spec/html/edit_spec.js
|
||||||
common/lib/xmodule/xmodule/js/spec/problem/edit_spec.js
|
|
||||||
common/lib/xmodule/xmodule/js/spec/problem/edit_spec_hint.js
|
common/lib/xmodule/xmodule/js/spec/problem/edit_spec_hint.js
|
||||||
|
common/lib/xmodule/xmodule/js/spec/problem/edit_spec.js
|
||||||
common/lib/xmodule/xmodule/js/spec/tabs/edit.js
|
common/lib/xmodule/xmodule/js/spec/tabs/edit.js
|
||||||
|
lms/static/js/spec/calculator_spec.js
|
||||||
|
lms/static/js/spec/courseware_spec.js
|
||||||
|
lms/static/js/spec/feedback_form_spec.js
|
||||||
|
lms/static/js/spec/helper.js
|
||||||
|
lms/static/js/spec/histogram_spec.js
|
||||||
|
lms/static/js/spec/modules/tab_spec.js
|
||||||
|
lms/static/js/spec/requirejs_spec.js
|
||||||
|
|
||||||
common/lib/xmodule/xmodule/js/src/annotatable/display.js
|
|
||||||
common/lib/xmodule/xmodule/js/src/conditional/display.js
|
|
||||||
common/lib/xmodule/xmodule/js/src/discussion/display.js
|
|
||||||
common/lib/xmodule/xmodule/js/src/html/display.js
|
|
||||||
common/lib/xmodule/xmodule/js/src/html/edit.js
|
|
||||||
common/lib/xmodule/xmodule/js/src/raw/edit/json.js
|
|
||||||
common/lib/xmodule/xmodule/js/src/raw/edit/metadata-only.js
|
|
||||||
common/lib/xmodule/xmodule/js/src/raw/edit/xml.js
|
|
||||||
common/lib/xmodule/xmodule/js/src/sequence/edit.js
|
|
||||||
common/lib/xmodule/xmodule/js/src/tabs/tabs-aggregator.js
|
|
||||||
common/lib/xmodule/xmodule/js/src/vertical/edit.js
|
|
||||||
|
|
||||||
# This file is responsible for almost half of the repo's total issues.
|
|
||||||
common/lib/xmodule/xmodule/js/src/capa/schematic.js
|
|
||||||
|
|
||||||
!**/.eslintrc.js
|
!**/.eslintrc.js
|
||||||
|
|||||||
@@ -810,10 +810,7 @@ PIPELINE_JS = {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
PIPELINE_COMPILERS = (
|
PIPELINE_COMPILERS = ()
|
||||||
'pipeline.compilers.coffee.CoffeeScriptCompiler',
|
|
||||||
)
|
|
||||||
|
|
||||||
PIPELINE_CSS_COMPRESSOR = None
|
PIPELINE_CSS_COMPRESSOR = None
|
||||||
PIPELINE_JS_COMPRESSOR = None
|
PIPELINE_JS_COMPRESSOR = None
|
||||||
|
|
||||||
@@ -829,10 +826,6 @@ STATICFILES_IGNORE_PATTERNS = (
|
|||||||
"sass/*/*.scss",
|
"sass/*/*.scss",
|
||||||
"sass/*/*/*.scss",
|
"sass/*/*/*.scss",
|
||||||
"sass/*/*/*/*.scss",
|
"sass/*/*/*/*.scss",
|
||||||
"coffee/*.coffee",
|
|
||||||
"coffee/*/*.coffee",
|
|
||||||
"coffee/*/*/*.coffee",
|
|
||||||
"coffee/*/*/*/*.coffee",
|
|
||||||
|
|
||||||
# Ignore tests
|
# Ignore tests
|
||||||
"spec",
|
"spec",
|
||||||
|
|||||||
@@ -104,7 +104,7 @@
|
|||||||
'jquery.fileupload-validate': 'js/vendor/jQuery-File-Upload/js/jquery.fileupload-validate',
|
'jquery.fileupload-validate': 'js/vendor/jQuery-File-Upload/js/jquery.fileupload-validate',
|
||||||
'jquery.iframe-transport': 'js/vendor/jQuery-File-Upload/js/jquery.iframe-transport',
|
'jquery.iframe-transport': 'js/vendor/jQuery-File-Upload/js/jquery.iframe-transport',
|
||||||
'jquery.inputnumber': 'js/vendor/html5-input-polyfills/number-polyfill',
|
'jquery.inputnumber': 'js/vendor/html5-input-polyfills/number-polyfill',
|
||||||
'jquery.immediateDescendents': 'coffee/src/jquery.immediateDescendents',
|
'jquery.immediateDescendents': 'js/src/jquery.immediateDescendents',
|
||||||
'datepair': 'js/vendor/timepicker/datepair',
|
'datepair': 'js/vendor/timepicker/datepair',
|
||||||
'date': 'js/vendor/date',
|
'date': 'js/vendor/date',
|
||||||
moment: 'common/js/vendor/moment-with-locales',
|
moment: 'common/js/vendor/moment-with-locales',
|
||||||
@@ -304,11 +304,11 @@
|
|||||||
deps: ['xblock/core']
|
deps: ['xblock/core']
|
||||||
},
|
},
|
||||||
'cms/js/main': {
|
'cms/js/main': {
|
||||||
deps: ['coffee/src/ajax_prefix']
|
deps: ['js/src/ajax_prefix']
|
||||||
},
|
},
|
||||||
'js/src/logger': {
|
'js/src/logger': {
|
||||||
exports: 'Logger',
|
exports: 'Logger',
|
||||||
deps: ['coffee/src/ajax_prefix']
|
deps: ['js/src/ajax_prefix']
|
||||||
},
|
},
|
||||||
|
|
||||||
// the following are all needed for annotation tools
|
// the following are all needed for annotation tools
|
||||||
|
|||||||
@@ -44,7 +44,7 @@
|
|||||||
'jquery.fileupload-validate': 'xmodule_js/common_static/js/vendor/jQuery-File-Upload/js/jquery.fileupload-validate', // eslint-disable-line max-len
|
'jquery.fileupload-validate': 'xmodule_js/common_static/js/vendor/jQuery-File-Upload/js/jquery.fileupload-validate', // eslint-disable-line max-len
|
||||||
'jquery.iframe-transport': 'xmodule_js/common_static/js/vendor/jQuery-File-Upload/js/jquery.iframe-transport', // eslint-disable-line max-len
|
'jquery.iframe-transport': 'xmodule_js/common_static/js/vendor/jQuery-File-Upload/js/jquery.iframe-transport', // eslint-disable-line max-len
|
||||||
'jquery.inputnumber': 'xmodule_js/common_static/js/vendor/html5-input-polyfills/number-polyfill',
|
'jquery.inputnumber': 'xmodule_js/common_static/js/vendor/html5-input-polyfills/number-polyfill',
|
||||||
'jquery.immediateDescendents': 'xmodule_js/common_static/coffee/src/jquery.immediateDescendents',
|
'jquery.immediateDescendents': 'xmodule_js/common_static/js/src/jquery.immediateDescendents',
|
||||||
'jquery.simulate': 'xmodule_js/common_static/js/vendor/jquery.simulate',
|
'jquery.simulate': 'xmodule_js/common_static/js/vendor/jquery.simulate',
|
||||||
'datepair': 'xmodule_js/common_static/js/vendor/timepicker/datepair',
|
'datepair': 'xmodule_js/common_static/js/vendor/timepicker/datepair',
|
||||||
'date': 'xmodule_js/common_static/js/vendor/date',
|
'date': 'xmodule_js/common_static/js/vendor/date',
|
||||||
@@ -72,7 +72,7 @@
|
|||||||
'mock-ajax': 'xmodule_js/common_static/js/vendor/mock-ajax',
|
'mock-ajax': 'xmodule_js/common_static/js/vendor/mock-ajax',
|
||||||
mathjax: '//cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.1/MathJax.js?config=TeX-MML-AM_SVG&delayStartupUntil=configured', // eslint-disable-line max-len
|
mathjax: '//cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.1/MathJax.js?config=TeX-MML-AM_SVG&delayStartupUntil=configured', // eslint-disable-line max-len
|
||||||
'youtube': '//www.youtube.com/player_api?noext',
|
'youtube': '//www.youtube.com/player_api?noext',
|
||||||
'coffee/src/ajax_prefix': 'xmodule_js/common_static/coffee/src/ajax_prefix',
|
'js/src/ajax_prefix': 'xmodule_js/common_static/js/src/ajax_prefix',
|
||||||
'js/spec/test_utils': 'js/spec/test_utils'
|
'js/spec/test_utils': 'js/spec/test_utils'
|
||||||
},
|
},
|
||||||
shim: {
|
shim: {
|
||||||
@@ -218,9 +218,9 @@
|
|||||||
deps: ['jquery']
|
deps: ['jquery']
|
||||||
},
|
},
|
||||||
'cms/js/main': {
|
'cms/js/main': {
|
||||||
deps: ['coffee/src/ajax_prefix']
|
deps: ['js/src/ajax_prefix']
|
||||||
},
|
},
|
||||||
'coffee/src/ajax_prefix': {
|
'js/src/ajax_prefix': {
|
||||||
deps: ['jquery']
|
deps: ['jquery']
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -231,17 +231,17 @@
|
|||||||
testFiles = [
|
testFiles = [
|
||||||
'cms/js/spec/main_spec',
|
'cms/js/spec/main_spec',
|
||||||
'cms/js/spec/xblock/cms.runtime.v1_spec',
|
'cms/js/spec/xblock/cms.runtime.v1_spec',
|
||||||
'coffee/spec/models/course_spec',
|
'js/spec/models/course_spec',
|
||||||
'coffee/spec/models/metadata_spec',
|
'js/spec/models/metadata_spec',
|
||||||
'coffee/spec/models/section_spec',
|
'js/spec/models/section_spec',
|
||||||
'coffee/spec/models/settings_course_grader_spec',
|
'js/spec/models/settings_course_grader_spec',
|
||||||
'coffee/spec/models/settings_grading_spec',
|
'js/spec/models/settings_grading_spec',
|
||||||
'coffee/spec/models/textbook_spec',
|
'js/spec/models/textbook_spec',
|
||||||
'coffee/spec/models/upload_spec',
|
'js/spec/models/upload_spec',
|
||||||
'coffee/spec/views/course_info_spec',
|
'js/spec/views/course_info_spec',
|
||||||
'coffee/spec/views/metadata_edit_spec',
|
'js/spec/views/metadata_edit_spec',
|
||||||
'coffee/spec/views/textbook_spec',
|
'js/spec/views/textbook_spec',
|
||||||
'coffee/spec/views/upload_spec',
|
'js/spec/views/upload_spec',
|
||||||
'js/spec/video/transcripts/utils_spec',
|
'js/spec/video/transcripts/utils_spec',
|
||||||
'js/spec/video/transcripts/editor_spec',
|
'js/spec/video/transcripts/editor_spec',
|
||||||
'js/spec/video/transcripts/videolist_spec',
|
'js/spec/video/transcripts/videolist_spec',
|
||||||
|
|||||||
@@ -27,7 +27,7 @@
|
|||||||
'jquery.fileupload-validate': 'xmodule_js/common_static/js/vendor/jQuery-File-Upload/js/jquery.fileupload-validate', // eslint-disable-line max-len
|
'jquery.fileupload-validate': 'xmodule_js/common_static/js/vendor/jQuery-File-Upload/js/jquery.fileupload-validate', // eslint-disable-line max-len
|
||||||
'jquery.iframe-transport': 'xmodule_js/common_static/js/vendor/jQuery-File-Upload/js/jquery.iframe-transport', // eslint-disable-line max-len
|
'jquery.iframe-transport': 'xmodule_js/common_static/js/vendor/jQuery-File-Upload/js/jquery.iframe-transport', // eslint-disable-line max-len
|
||||||
'jquery.inputnumber': 'xmodule_js/common_static/js/vendor/html5-input-polyfills/number-polyfill',
|
'jquery.inputnumber': 'xmodule_js/common_static/js/vendor/html5-input-polyfills/number-polyfill',
|
||||||
'jquery.immediateDescendents': 'xmodule_js/common_static/coffee/src/jquery.immediateDescendents',
|
'jquery.immediateDescendents': 'xmodule_js/common_static/js/src/jquery.immediateDescendents',
|
||||||
'datepair': 'xmodule_js/common_static/js/vendor/timepicker/datepair',
|
'datepair': 'xmodule_js/common_static/js/vendor/timepicker/datepair',
|
||||||
'date': 'xmodule_js/common_static/js/vendor/date',
|
'date': 'xmodule_js/common_static/js/vendor/date',
|
||||||
'text': 'xmodule_js/common_static/js/vendor/requirejs/text',
|
'text': 'xmodule_js/common_static/js/vendor/requirejs/text',
|
||||||
@@ -49,7 +49,7 @@
|
|||||||
'URI': 'xmodule_js/common_static/js/vendor/URI.min',
|
'URI': 'xmodule_js/common_static/js/vendor/URI.min',
|
||||||
mathjax: '//cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.1/MathJax.js?config=TeX-MML-AM_SVG&delayStartupUntil=configured', // eslint-disable-line max-len
|
mathjax: '//cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.1/MathJax.js?config=TeX-MML-AM_SVG&delayStartupUntil=configured', // eslint-disable-line max-len
|
||||||
'youtube': '//www.youtube.com/player_api?noext',
|
'youtube': '//www.youtube.com/player_api?noext',
|
||||||
'coffee/src/ajax_prefix': 'xmodule_js/common_static/coffee/src/ajax_prefix'
|
'js/src/ajax_prefix': 'xmodule_js/common_static/js/src/ajax_prefix'
|
||||||
},
|
},
|
||||||
shim: {
|
shim: {
|
||||||
'gettext': {
|
'gettext': {
|
||||||
@@ -174,9 +174,9 @@
|
|||||||
deps: ['xblock/core']
|
deps: ['xblock/core']
|
||||||
},
|
},
|
||||||
'cms/js/main': {
|
'cms/js/main': {
|
||||||
deps: ['coffee/src/ajax_prefix']
|
deps: ['js/src/ajax_prefix']
|
||||||
},
|
},
|
||||||
'coffee/src/ajax_prefix': {
|
'js/src/ajax_prefix': {
|
||||||
deps: ['jquery']
|
deps: ['jquery']
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -185,7 +185,7 @@
|
|||||||
jasmine.getFixtures().fixturesPath = '/base/templates';
|
jasmine.getFixtures().fixturesPath = '/base/templates';
|
||||||
|
|
||||||
testFiles = [
|
testFiles = [
|
||||||
'coffee/spec/views/assets_spec',
|
'js/spec/views/assets_squire_spec',
|
||||||
'js/spec/video/translations_editor_spec',
|
'js/spec/video/translations_editor_spec',
|
||||||
'js/spec/video/file_uploader_editor_spec',
|
'js/spec/video/file_uploader_editor_spec',
|
||||||
'js/spec/models/group_configuration_spec'
|
'js/spec/models/group_configuration_spec'
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
define(['backbone'], function(Backbone) {
|
define(['backbone'], function(Backbone) {
|
||||||
/**
|
/**
|
||||||
* Model used for metadata setting editors. This model does not do its own saving,
|
* Model used for metadata setting editors. This model does not do its own saving,
|
||||||
* as that is done by module_edit.coffee.
|
* as that is done by module_edit.js.
|
||||||
*/
|
*/
|
||||||
var Metadata = Backbone.Model.extend({
|
var Metadata = Backbone.Model.extend({
|
||||||
defaults: {
|
defaults: {
|
||||||
|
|||||||
@@ -22,13 +22,11 @@ var options = {
|
|||||||
// Otherwise Istanbul which is used for coverage tracking will cause tests to not run.
|
// Otherwise Istanbul which is used for coverage tracking will cause tests to not run.
|
||||||
sourceFiles: [
|
sourceFiles: [
|
||||||
{pattern: 'cms/**/!(*spec|djangojs).js'},
|
{pattern: 'cms/**/!(*spec|djangojs).js'},
|
||||||
{pattern: 'coffee/src/**/!(*spec).js'},
|
|
||||||
{pattern: 'js/**/!(*spec|djangojs).js'}
|
{pattern: 'js/**/!(*spec|djangojs).js'}
|
||||||
],
|
],
|
||||||
|
|
||||||
specFiles: [
|
specFiles: [
|
||||||
{pattern: 'cms/**/*spec.js'},
|
{pattern: 'cms/**/*spec.js'},
|
||||||
{pattern: 'coffee/spec/**/*spec.js'},
|
|
||||||
{pattern: 'js/certificates/spec/**/*spec.js'},
|
{pattern: 'js/certificates/spec/**/*spec.js'},
|
||||||
{pattern: 'js/spec/**/*spec.js'}
|
{pattern: 'js/spec/**/*spec.js'}
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -21,18 +21,15 @@ var options = {
|
|||||||
// Make sure the patterns in sourceFiles and specFiles do not match the same file.
|
// Make sure the patterns in sourceFiles and specFiles do not match the same file.
|
||||||
// Otherwise Istanbul which is used for coverage tracking will cause tests to not run.
|
// Otherwise Istanbul which is used for coverage tracking will cause tests to not run.
|
||||||
sourceFiles: [
|
sourceFiles: [
|
||||||
{pattern: 'coffee/src/**/!(*spec).js'},
|
|
||||||
{pattern: 'cms/js/**/!(*spec|djangojs).js'},
|
{pattern: 'cms/js/**/!(*spec|djangojs).js'},
|
||||||
{pattern: 'js/**/!(*spec|djangojs).js'}
|
{pattern: 'js/**/!(*spec|djangojs).js'}
|
||||||
],
|
],
|
||||||
|
|
||||||
specFiles: [
|
specFiles: [
|
||||||
{pattern: 'coffee/spec/**/*spec.js'},
|
|
||||||
{pattern: 'js/spec/**/*spec.js'}
|
{pattern: 'js/spec/**/*spec.js'}
|
||||||
],
|
],
|
||||||
|
|
||||||
fixtureFiles: [
|
fixtureFiles: [
|
||||||
{pattern: 'coffee/fixtures/**/*.*'},
|
|
||||||
{pattern: 'templates/**/*.*'}
|
{pattern: 'templates/**/*.*'}
|
||||||
],
|
],
|
||||||
|
|
||||||
|
|||||||
@@ -64,6 +64,7 @@
|
|||||||
email: m-mat @ math.sci.hiroshima-u.ac.jp (remove space)
|
email: m-mat @ math.sci.hiroshima-u.ac.jp (remove space)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/* eslint-disable */
|
||||||
var MersenneTwister = function(seed) {
|
var MersenneTwister = function(seed) {
|
||||||
if (seed == undefined) {
|
if (seed == undefined) {
|
||||||
seed = new Date().getTime();
|
seed = new Date().getTime();
|
||||||
|
|||||||
@@ -47,11 +47,9 @@ class AnnotatableFields(object):
|
|||||||
|
|
||||||
class AnnotatableModule(AnnotatableFields, XModule):
|
class AnnotatableModule(AnnotatableFields, XModule):
|
||||||
js = {
|
js = {
|
||||||
'coffee': [
|
|
||||||
resource_string(__name__, 'js/src/html/display.coffee'),
|
|
||||||
resource_string(__name__, 'js/src/annotatable/display.coffee'),
|
|
||||||
],
|
|
||||||
'js': [
|
'js': [
|
||||||
|
resource_string(__name__, 'js/src/html/display.js'),
|
||||||
|
resource_string(__name__, 'js/src/annotatable/display.js'),
|
||||||
resource_string(__name__, 'js/src/javascript_loader.js'),
|
resource_string(__name__, 'js/src/javascript_loader.js'),
|
||||||
resource_string(__name__, 'js/src/collapsible.js'),
|
resource_string(__name__, 'js/src/collapsible.js'),
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -116,10 +116,8 @@ class ConditionalModule(ConditionalFields, XModule, StudioEditableModule):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
js = {
|
js = {
|
||||||
'coffee': [
|
|
||||||
resource_string(__name__, 'js/src/conditional/display.coffee'),
|
|
||||||
],
|
|
||||||
'js': [
|
'js': [
|
||||||
|
resource_string(__name__, 'js/src/conditional/display.js'),
|
||||||
resource_string(__name__, 'js/src/javascript_loader.js'),
|
resource_string(__name__, 'js/src/javascript_loader.js'),
|
||||||
resource_string(__name__, 'js/src/collapsible.js'),
|
resource_string(__name__, 'js/src/collapsible.js'),
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -58,8 +58,8 @@ class TabsEditingDescriptor(EditingFields, MakoModuleDescriptor):
|
|||||||
"""
|
"""
|
||||||
mako_template = "widgets/tabs-aggregator.html"
|
mako_template = "widgets/tabs-aggregator.html"
|
||||||
css = {'scss': [resource_string(__name__, 'css/tabs/tabs.scss')]}
|
css = {'scss': [resource_string(__name__, 'css/tabs/tabs.scss')]}
|
||||||
js = {'coffee': [resource_string(
|
js = {'js': [resource_string(
|
||||||
__name__, 'js/src/tabs/tabs-aggregator.coffee')]}
|
__name__, 'js/src/tabs/tabs-aggregator.js')]}
|
||||||
js_module_name = "TabsEditingDescriptor"
|
js_module_name = "TabsEditingDescriptor"
|
||||||
tabs = []
|
tabs = []
|
||||||
|
|
||||||
@@ -93,7 +93,7 @@ class XMLEditingDescriptor(EditingDescriptor):
|
|||||||
|
|
||||||
css = {'scss': [resource_string(__name__, 'css/codemirror/codemirror.scss')]}
|
css = {'scss': [resource_string(__name__, 'css/codemirror/codemirror.scss')]}
|
||||||
|
|
||||||
js = {'coffee': [resource_string(__name__, 'js/src/raw/edit/xml.coffee')]}
|
js = {'js': [resource_string(__name__, 'js/src/raw/edit/xml.js')]}
|
||||||
js_module_name = "XMLEditingDescriptor"
|
js_module_name = "XMLEditingDescriptor"
|
||||||
|
|
||||||
|
|
||||||
@@ -103,7 +103,7 @@ class MetadataOnlyEditingDescriptor(EditingDescriptor):
|
|||||||
not expose a UI for editing the module data
|
not expose a UI for editing the module data
|
||||||
"""
|
"""
|
||||||
|
|
||||||
js = {'coffee': [resource_string(__name__, 'js/src/raw/edit/metadata-only.coffee')]}
|
js = {'js': [resource_string(__name__, 'js/src/raw/edit/metadata-only.js')]}
|
||||||
js_module_name = "MetadataOnlyEditingDescriptor"
|
js_module_name = "MetadataOnlyEditingDescriptor"
|
||||||
|
|
||||||
mako_template = "widgets/metadata-only-edit.html"
|
mako_template = "widgets/metadata-only-edit.html"
|
||||||
@@ -117,5 +117,5 @@ class JSONEditingDescriptor(EditingDescriptor):
|
|||||||
|
|
||||||
css = {'scss': [resource_string(__name__, 'css/codemirror/codemirror.scss')]}
|
css = {'scss': [resource_string(__name__, 'css/codemirror/codemirror.scss')]}
|
||||||
|
|
||||||
js = {'coffee': [resource_string(__name__, 'js/src/raw/edit/json.coffee')]}
|
js = {'js': [resource_string(__name__, 'js/src/raw/edit/json.js')]}
|
||||||
js_module_name = "JSONEditingDescriptor"
|
js_module_name = "JSONEditingDescriptor"
|
||||||
|
|||||||
@@ -107,10 +107,8 @@ class HtmlModuleMixin(HtmlBlock, XModule):
|
|||||||
Attributes and methods used by HtmlModules internally.
|
Attributes and methods used by HtmlModules internally.
|
||||||
"""
|
"""
|
||||||
js = {
|
js = {
|
||||||
'coffee': [
|
|
||||||
resource_string(__name__, 'js/src/html/display.coffee'),
|
|
||||||
],
|
|
||||||
'js': [
|
'js': [
|
||||||
|
resource_string(__name__, 'js/src/html/display.js'),
|
||||||
resource_string(__name__, 'js/src/javascript_loader.js'),
|
resource_string(__name__, 'js/src/javascript_loader.js'),
|
||||||
resource_string(__name__, 'js/src/collapsible.js'),
|
resource_string(__name__, 'js/src/collapsible.js'),
|
||||||
resource_string(__name__, 'js/src/html/imageModal.js'),
|
resource_string(__name__, 'js/src/html/imageModal.js'),
|
||||||
@@ -139,7 +137,7 @@ class HtmlDescriptor(HtmlBlock, XmlDescriptor, EditingDescriptor): # pylint: di
|
|||||||
template_dir_name = "html"
|
template_dir_name = "html"
|
||||||
show_in_read_only_mode = True
|
show_in_read_only_mode = True
|
||||||
|
|
||||||
js = {'coffee': [resource_string(__name__, 'js/src/html/edit.coffee')]}
|
js = {'js': [resource_string(__name__, 'js/src/html/edit.js')]}
|
||||||
js_module_name = "HTMLEditingDescriptor"
|
js_module_name = "HTMLEditingDescriptor"
|
||||||
css = {'scss': [resource_string(__name__, 'css/editor/edit.scss'), resource_string(__name__, 'css/html/edit.scss')]}
|
css = {'scss': [resource_string(__name__, 'css/editor/edit.scss'), resource_string(__name__, 'css/html/edit.scss')]}
|
||||||
|
|
||||||
|
|||||||
@@ -91,11 +91,9 @@ class AnnotatableFields(object):
|
|||||||
class ImageAnnotationModule(AnnotatableFields, XModule):
|
class ImageAnnotationModule(AnnotatableFields, XModule):
|
||||||
'''Image Annotation Module'''
|
'''Image Annotation Module'''
|
||||||
js = {
|
js = {
|
||||||
'coffee': [
|
|
||||||
resource_string(__name__, 'js/src/html/display.coffee'),
|
|
||||||
resource_string(__name__, 'js/src/annotatable/display.coffee'),
|
|
||||||
],
|
|
||||||
'js': [
|
'js': [
|
||||||
|
resource_string(__name__, 'js/src/html/display.js'),
|
||||||
|
resource_string(__name__, 'js/src/annotatable/display.js'),
|
||||||
resource_string(__name__, 'js/src/javascript_loader.js'),
|
resource_string(__name__, 'js/src/javascript_loader.js'),
|
||||||
resource_string(__name__, 'js/src/collapsible.js'),
|
resource_string(__name__, 'js/src/collapsible.js'),
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ var options = {
|
|||||||
// Avoid adding files to this list. Use RequireJS.
|
// Avoid adding files to this list. Use RequireJS.
|
||||||
libraryFilesToInclude: [
|
libraryFilesToInclude: [
|
||||||
// Load the core JavaScript dependencies
|
// Load the core JavaScript dependencies
|
||||||
{pattern: 'common_static/coffee/src/ajax_prefix.js', included: true},
|
{pattern: 'common_static/js/src/ajax_prefix.js', included: true},
|
||||||
{pattern: 'common_static/common/js/vendor/underscore.js', included: true},
|
{pattern: 'common_static/common/js/vendor/underscore.js', included: true},
|
||||||
{pattern: 'common_static/common/js/vendor/backbone.js', included: true},
|
{pattern: 'common_static/common/js/vendor/backbone.js', included: true},
|
||||||
{pattern: 'common_static/js/vendor/CodeMirror/codemirror.js', included: true},
|
{pattern: 'common_static/js/vendor/CodeMirror/codemirror.js', included: true},
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ describe('Problem', function() {
|
|||||||
spyOn(SR, 'readText');
|
spyOn(SR, 'readText');
|
||||||
spyOn(SR, 'readTexts');
|
spyOn(SR, 'readTexts');
|
||||||
|
|
||||||
// Load this function from spec/helper.coffee
|
// Load this function from spec/helper.js
|
||||||
// Note that if your test fails with a message like:
|
// Note that if your test fails with a message like:
|
||||||
// 'External request attempted for blah, which is not defined.'
|
// 'External request attempted for blah, which is not defined.'
|
||||||
// this msg is coming from the stubRequests function else clause.
|
// this msg is coming from the stubRequests function else clause.
|
||||||
|
|||||||
@@ -885,8 +885,6 @@ hint
|
|||||||
);
|
);
|
||||||
|
|
||||||
describe('Markdown to xml extended hint with tricky syntax cases', function() {
|
describe('Markdown to xml extended hint with tricky syntax cases', function() {
|
||||||
// I'm entering this as utf-8 in this file.
|
|
||||||
// I cannot find a way to set the encoding for .coffee files but it seems to work.
|
|
||||||
it('produces xml with unicode', function() {
|
it('produces xml with unicode', function() {
|
||||||
const data = MarkdownEditingDescriptor.markdownToXml(`\
|
const data = MarkdownEditingDescriptor.markdownToXml(`\
|
||||||
>>á and Ø<<
|
>>á and Ø<<
|
||||||
|
|||||||
16
common/lib/xmodule/xmodule/js/src/.gitignore
vendored
16
common/lib/xmodule/xmodule/js/src/.gitignore
vendored
@@ -1,16 +0,0 @@
|
|||||||
# Ignore .js files in this folder as they are compiled from coffeescript
|
|
||||||
# For each of the xmodules subdirectories, add a .gitignore file that
|
|
||||||
# will version any *.js file that is specifically written, not compiled.
|
|
||||||
*.js
|
|
||||||
|
|
||||||
|
|
||||||
# Video are written in pure JavaScript.
|
|
||||||
!video/*.js
|
|
||||||
!video/transcripts/*.js
|
|
||||||
|
|
||||||
|
|
||||||
# Converted to JS from CoffeeScript.
|
|
||||||
!time.js
|
|
||||||
!collapsible.js
|
|
||||||
!xmodule.js
|
|
||||||
!javascript_loader.js
|
|
||||||
@@ -1,261 +1,443 @@
|
|||||||
class @Annotatable
|
// Once generated by CoffeeScript 1.9.3, but now lives as pure JS
|
||||||
_debug: false
|
/* eslint-disable */
|
||||||
|
// TODO: Examine all of the xss-lint exceptions (https://openedx.atlassian.net/browse/PLAT-2084)
|
||||||
|
(function() {
|
||||||
|
var bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; };
|
||||||
|
|
||||||
# selectors for the annotatable xmodule
|
this.Annotatable = (function() {
|
||||||
wrapperSelector: '.annotatable-wrapper'
|
Annotatable.prototype._debug = false;
|
||||||
toggleAnnotationsSelector: '.annotatable-toggle-annotations'
|
|
||||||
toggleInstructionsSelector: '.annotatable-toggle-instructions'
|
|
||||||
instructionsSelector: '.annotatable-instructions'
|
|
||||||
sectionSelector: '.annotatable-section'
|
|
||||||
spanSelector: '.annotatable-span'
|
|
||||||
replySelector: '.annotatable-reply'
|
|
||||||
|
|
||||||
# these selectors are for responding to events from the annotation capa problem type
|
|
||||||
problemXModuleSelector: '.xmodule_CapaModule'
|
|
||||||
problemSelector: 'div.problem'
|
|
||||||
problemInputSelector: 'div.problem .annotation-input'
|
|
||||||
problemReturnSelector: 'div.problem .annotation-return'
|
|
||||||
|
|
||||||
constructor: (el) ->
|
/*
|
||||||
console.log 'loaded Annotatable' if @_debug
|
selectors for the annotatable xmodule
|
||||||
@el = el
|
*/
|
||||||
@$el = $(el)
|
|
||||||
@init()
|
|
||||||
|
|
||||||
$: (selector) ->
|
Annotatable.prototype.wrapperSelector = '.annotatable-wrapper';
|
||||||
$(selector, @el)
|
|
||||||
|
|
||||||
init: () ->
|
Annotatable.prototype.toggleAnnotationsSelector = '.annotatable-toggle-annotations';
|
||||||
@initEvents()
|
|
||||||
@initTips()
|
|
||||||
|
|
||||||
initEvents: () ->
|
Annotatable.prototype.toggleInstructionsSelector = '.annotatable-toggle-instructions';
|
||||||
# Initialize toggle handlers for the instructions and annotations sections
|
|
||||||
[@annotationsHidden, @instructionsHidden] = [false, false]
|
|
||||||
@$(@toggleAnnotationsSelector).bind 'click', @onClickToggleAnnotations
|
|
||||||
@$(@toggleInstructionsSelector).bind 'click', @onClickToggleInstructions
|
|
||||||
|
|
||||||
# Initialize handler for 'reply to annotation' events that scroll to
|
Annotatable.prototype.instructionsSelector = '.annotatable-instructions';
|
||||||
# the associated problem. The reply buttons are part of the tooltip
|
|
||||||
# content. It's important that the tooltips be configured to render
|
|
||||||
# as descendants of the annotation module and *not* the document.body.
|
|
||||||
@$el.on 'click', @replySelector, @onClickReply
|
|
||||||
|
|
||||||
# Initialize handler for 'return to annotation' events triggered from problems.
|
Annotatable.prototype.sectionSelector = '.annotatable-section';
|
||||||
# 1) There are annotationinput capa problems rendered on the page
|
|
||||||
# 2) Each one has an embedded return link (see annotation capa problem template).
|
|
||||||
# Since the capa problem injects HTML content via AJAX, the best we can do is
|
|
||||||
# is let the click events bubble up to the body and handle them there.
|
|
||||||
$(document).on 'click', @problemReturnSelector, @onClickReturn
|
|
||||||
|
|
||||||
initTips: () ->
|
Annotatable.prototype.spanSelector = '.annotatable-span';
|
||||||
# tooltips are used to display annotations for highlighted text spans
|
|
||||||
@$(@spanSelector).each (index, el) =>
|
|
||||||
$(el).qtip(@getSpanTipOptions el)
|
|
||||||
|
|
||||||
getSpanTipOptions: (el) ->
|
Annotatable.prototype.replySelector = '.annotatable-reply';
|
||||||
content:
|
|
||||||
title:
|
|
||||||
text: @makeTipTitle(el)
|
|
||||||
text: @makeTipContent(el)
|
|
||||||
position:
|
|
||||||
my: 'bottom center' # of tooltip
|
|
||||||
at: 'top center' # of target
|
|
||||||
target: $(el) # where the tooltip was triggered (i.e. the annotation span)
|
|
||||||
container: @$(@wrapperSelector)
|
|
||||||
adjust:
|
|
||||||
y: -5
|
|
||||||
show:
|
|
||||||
event: 'click mouseenter'
|
|
||||||
solo: true
|
|
||||||
hide:
|
|
||||||
event: 'click mouseleave'
|
|
||||||
delay: 500,
|
|
||||||
fixed: true # don't hide the tooltip if it is moused over
|
|
||||||
style:
|
|
||||||
classes: 'ui-tooltip-annotatable'
|
|
||||||
events:
|
|
||||||
show: @onShowTip
|
|
||||||
move: @onMoveTip
|
|
||||||
|
|
||||||
onClickToggleAnnotations: (e) => @toggleAnnotations()
|
|
||||||
|
|
||||||
onClickToggleInstructions: (e) => @toggleInstructions()
|
/*
|
||||||
|
these selectors are for responding to events from the annotation capa problem type
|
||||||
|
*/
|
||||||
|
|
||||||
onClickReply: (e) => @replyTo(e.currentTarget)
|
Annotatable.prototype.problemXModuleSelector = '.xmodule_CapaModule';
|
||||||
|
|
||||||
onClickReturn: (e) => @returnFrom(e.currentTarget)
|
Annotatable.prototype.problemSelector = 'div.problem';
|
||||||
|
|
||||||
onShowTip: (event, api) =>
|
Annotatable.prototype.problemInputSelector = 'div.problem .annotation-input';
|
||||||
event.preventDefault() if @annotationsHidden
|
|
||||||
|
|
||||||
onMoveTip: (event, api, position) =>
|
Annotatable.prototype.problemReturnSelector = 'div.problem .annotation-return';
|
||||||
###
|
|
||||||
This method handles a vertical positioning bug in Firefox as
|
|
||||||
well as an edge case in which a tooltip is displayed above a
|
|
||||||
non-overlapping span like this:
|
|
||||||
|
|
||||||
(( TOOLTIP ))
|
function Annotatable(el) {
|
||||||
\/
|
this.onMoveTip = bind(this.onMoveTip, this);
|
||||||
text text text ... text text text ...... <span span span>
|
this.onShowTip = bind(this.onShowTip, this);
|
||||||
<span span span>
|
this.onClickReturn = bind(this.onClickReturn, this);
|
||||||
|
this.onClickReply = bind(this.onClickReply, this);
|
||||||
|
this.onClickToggleInstructions = bind(this.onClickToggleInstructions, this);
|
||||||
|
this.onClickToggleAnnotations = bind(this.onClickToggleAnnotations, this);
|
||||||
|
if (this._debug) {
|
||||||
|
console.log('loaded Annotatable');
|
||||||
|
}
|
||||||
|
this.el = el;
|
||||||
|
this.$el = $(el);
|
||||||
|
this.init();
|
||||||
|
}
|
||||||
|
|
||||||
The problem is that the tooltip looks disconnected from both spans, so
|
Annotatable.prototype.$ = function(selector) {
|
||||||
we should re-position the tooltip to appear above the span.
|
return $(selector, this.el);
|
||||||
###
|
};
|
||||||
|
|
||||||
tip = api.elements.tooltip
|
Annotatable.prototype.init = function() {
|
||||||
adjust_y = api.options.position?.adjust?.y || 0
|
this.initEvents();
|
||||||
container = api.options.position?.container || $('body')
|
return this.initTips();
|
||||||
target = api.elements.target
|
};
|
||||||
|
|
||||||
rects = $(target).get(0).getClientRects()
|
Annotatable.prototype.initEvents = function() {
|
||||||
is_non_overlapping = (rects?.length == 2 and rects[0].left > rects[1].right)
|
|
||||||
|
|
||||||
if is_non_overlapping
|
/*
|
||||||
# we want to choose the largest of the two non-overlapping spans and display
|
Initialize toggle handlers for the instructions and annotations sections
|
||||||
# the tooltip above the center of it (see api.options.position settings)
|
*/
|
||||||
focus_rect = (if rects[0].width > rects[1].width then rects[0] else rects[1])
|
var ref;
|
||||||
else
|
ref = [false, false], this.annotationsHidden = ref[0], this.instructionsHidden = ref[1];
|
||||||
# always compute the new position because Firefox doesn't
|
this.$(this.toggleAnnotationsSelector).bind('click', this.onClickToggleAnnotations);
|
||||||
# properly vertically position the tooltip
|
this.$(this.toggleInstructionsSelector).bind('click', this.onClickToggleInstructions);
|
||||||
focus_rect = rects[0]
|
|
||||||
|
|
||||||
rect_center = focus_rect.left + (focus_rect.width / 2)
|
/*
|
||||||
rect_top = focus_rect.top
|
Initialize handler for 'reply to annotation' events that scroll to
|
||||||
tip_width = $(tip).width()
|
the associated problem. The reply buttons are part of the tooltip
|
||||||
tip_height = $(tip).height()
|
content. It's important that the tooltips be configured to render
|
||||||
|
as descendants of the annotation module and *not* the document.body.
|
||||||
|
*/
|
||||||
|
this.$el.on('click', this.replySelector, this.onClickReply);
|
||||||
|
|
||||||
# tooltip is positioned relative to its container, so we need to factor in offsets
|
/*
|
||||||
container_offset = $(container).offset()
|
Initialize handler for 'return to annotation' events triggered from problems.
|
||||||
offset_left = -container_offset.left
|
1) There are annotationinput capa problems rendered on the page
|
||||||
offset_top = $(document).scrollTop() - container_offset.top
|
2) Each one has an embedded return link (see annotation capa problem template).
|
||||||
|
Since the capa problem injects HTML content via AJAX, the best we can do is
|
||||||
|
is let the click events bubble up to the body and handle them there.
|
||||||
|
*/
|
||||||
|
return $(document).on('click', this.problemReturnSelector, this.onClickReturn);
|
||||||
|
};
|
||||||
|
|
||||||
tip_left = offset_left + rect_center - (tip_width / 2)
|
Annotatable.prototype.initTips = function() {
|
||||||
tip_top = offset_top + rect_top - tip_height + adjust_y
|
|
||||||
|
|
||||||
# make sure the new tip position doesn't clip the edges of the screen
|
/*
|
||||||
win_width = $(window).width()
|
tooltips are used to display annotations for highlighted text spans
|
||||||
if tip_left < offset_left
|
*/
|
||||||
tip_left = offset_left
|
return this.$(this.spanSelector).each((function(_this) {
|
||||||
else if tip_left + tip_width > win_width + offset_left
|
return function(index, el) {
|
||||||
tip_left = win_width + offset_left - tip_width
|
return $(el).qtip(_this.getSpanTipOptions(el));
|
||||||
|
};
|
||||||
|
})(this));
|
||||||
|
};
|
||||||
|
|
||||||
# final step: update the position object (used by qtip2 to show the tip after the move event)
|
Annotatable.prototype.getSpanTipOptions = function(el) {
|
||||||
$.extend position, 'left': tip_left, 'top': tip_top
|
return {
|
||||||
|
content: {
|
||||||
|
title: {
|
||||||
|
text: this.makeTipTitle(el)
|
||||||
|
},
|
||||||
|
text: this.makeTipContent(el)
|
||||||
|
},
|
||||||
|
position: {
|
||||||
|
|
||||||
getSpanForProblemReturn: (el) ->
|
/*
|
||||||
problem_id = $(@problemReturnSelector).index(el)
|
of tooltip
|
||||||
@$(@spanSelector).filter("[data-problem-id='#{problem_id}']")
|
*/
|
||||||
|
my: 'bottom center',
|
||||||
|
|
||||||
getProblem: (el) ->
|
/*
|
||||||
problem_id = @getProblemId(el)
|
of target
|
||||||
$(@problemInputSelector).eq(problem_id)
|
*/
|
||||||
|
at: 'top center',
|
||||||
|
|
||||||
getProblemId: (el) ->
|
/*
|
||||||
$(el).data('problem-id')
|
where the tooltip was triggered (i.e. the annotation span)
|
||||||
|
*/
|
||||||
|
target: $(el),
|
||||||
|
container: this.$(this.wrapperSelector),
|
||||||
|
adjust: {
|
||||||
|
y: -5
|
||||||
|
}
|
||||||
|
},
|
||||||
|
show: {
|
||||||
|
event: 'click mouseenter',
|
||||||
|
solo: true
|
||||||
|
},
|
||||||
|
hide: {
|
||||||
|
event: 'click mouseleave',
|
||||||
|
delay: 500,
|
||||||
|
|
||||||
toggleAnnotations: () ->
|
/*
|
||||||
hide = (@annotationsHidden = not @annotationsHidden)
|
don't hide the tooltip if it is moused over
|
||||||
@toggleAnnotationButtonText hide
|
*/
|
||||||
@toggleSpans hide
|
fixed: true
|
||||||
@toggleTips hide
|
},
|
||||||
|
style: {
|
||||||
|
classes: 'ui-tooltip-annotatable'
|
||||||
|
},
|
||||||
|
events: {
|
||||||
|
show: this.onShowTip,
|
||||||
|
move: this.onMoveTip
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
toggleTips: (hide) ->
|
Annotatable.prototype.onClickToggleAnnotations = function(e) {
|
||||||
visible = @findVisibleTips()
|
return this.toggleAnnotations();
|
||||||
@hideTips visible
|
};
|
||||||
|
|
||||||
toggleAnnotationButtonText: (hide) ->
|
Annotatable.prototype.onClickToggleInstructions = function(e) {
|
||||||
if hide
|
return this.toggleInstructions();
|
||||||
buttonText = gettext('Show Annotations')
|
};
|
||||||
else
|
|
||||||
buttonText = gettext('Hide Annotations')
|
|
||||||
@$(@toggleAnnotationsSelector).text(buttonText)
|
|
||||||
|
|
||||||
toggleInstructions: () ->
|
Annotatable.prototype.onClickReply = function(e) {
|
||||||
hide = (@instructionsHidden = not @instructionsHidden)
|
return this.replyTo(e.currentTarget);
|
||||||
@toggleInstructionsButton hide
|
};
|
||||||
@toggleInstructionsText hide
|
|
||||||
|
|
||||||
toggleInstructionsButton: (hide) ->
|
Annotatable.prototype.onClickReturn = function(e) {
|
||||||
if hide
|
return this.returnFrom(e.currentTarget);
|
||||||
txt = gettext('Expand Instructions')
|
};
|
||||||
else
|
|
||||||
txt = gettext('Collapse Instructions')
|
|
||||||
cls = (if hide then ['expanded', 'collapsed'] else ['collapsed','expanded'])
|
|
||||||
@$(@toggleInstructionsSelector).text(txt).removeClass(cls[0]).addClass(cls[1])
|
|
||||||
|
|
||||||
toggleInstructionsText: (hide) ->
|
Annotatable.prototype.onShowTip = function(event, api) {
|
||||||
slideMethod = (if hide then 'slideUp' else 'slideDown')
|
if (this.annotationsHidden) {
|
||||||
@$(@instructionsSelector)[slideMethod]()
|
return event.preventDefault();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
toggleSpans: (hide) ->
|
Annotatable.prototype.onMoveTip = function(event, api, position) {
|
||||||
@$(@spanSelector).toggleClass 'hide', hide, 250
|
|
||||||
|
|
||||||
replyTo: (buttonEl) ->
|
/*
|
||||||
offset = -20
|
This method handles a vertical positioning bug in Firefox as
|
||||||
el = @getProblem buttonEl
|
well as an edge case in which a tooltip is displayed above a
|
||||||
if el.length > 0
|
non-overlapping span like this:
|
||||||
@scrollTo(el, @afterScrollToProblem, offset)
|
|
||||||
else
|
(( TOOLTIP ))
|
||||||
console.log('problem not found. event: ', e) if @_debug
|
\/
|
||||||
|
text text text ... text text text ...... <span span span>
|
||||||
|
<span span span>
|
||||||
|
|
||||||
|
The problem is that the tooltip looks disconnected from both spans, so
|
||||||
|
we should re-position the tooltip to appear above the span.
|
||||||
|
*/
|
||||||
|
var adjust_y, container, container_offset, focus_rect, is_non_overlapping, offset_left, offset_top, rect_center, rect_top, rects, ref, ref1, ref2, target, tip, tip_height, tip_left, tip_top, tip_width, win_width;
|
||||||
|
tip = api.elements.tooltip;
|
||||||
|
adjust_y = ((ref = api.options.position) != null ? (ref1 = ref.adjust) != null ? ref1.y : void 0 : void 0) || 0;
|
||||||
|
container = ((ref2 = api.options.position) != null ? ref2.container : void 0) || $('body');
|
||||||
|
target = api.elements.target;
|
||||||
|
rects = $(target).get(0).getClientRects();
|
||||||
|
is_non_overlapping = (rects != null ? rects.length : void 0) === 2 && rects[0].left > rects[1].right;
|
||||||
|
if (is_non_overlapping) {
|
||||||
|
|
||||||
returnFrom: (buttonEl) ->
|
/*
|
||||||
offset = -200
|
we want to choose the largest of the two non-overlapping spans and display
|
||||||
el = @getSpanForProblemReturn buttonEl
|
the tooltip above the center of it (see api.options.position settings)
|
||||||
if el.length > 0
|
*/
|
||||||
@scrollTo(el, @afterScrollToSpan, offset)
|
focus_rect = (rects[0].width > rects[1].width ? rects[0] : rects[1]);
|
||||||
else
|
} else {
|
||||||
console.log('span not found. event:', e) if @_debug
|
|
||||||
|
|
||||||
scrollTo: (el, after, offset = -20) ->
|
/*
|
||||||
$('html,body').scrollTo(el, {
|
always compute the new position because Firefox doesn't
|
||||||
duration: 500
|
properly vertically position the tooltip
|
||||||
onAfter: @_once => after?.call this, el
|
*/
|
||||||
offset: offset
|
focus_rect = rects[0];
|
||||||
}) if $(el).length > 0
|
}
|
||||||
|
rect_center = focus_rect.left + (focus_rect.width / 2);
|
||||||
|
rect_top = focus_rect.top;
|
||||||
|
tip_width = $(tip).width();
|
||||||
|
tip_height = $(tip).height();
|
||||||
|
|
||||||
afterScrollToProblem: (problem_el) ->
|
/*
|
||||||
problem_el.effect 'highlight', {}, 500
|
tooltip is positioned relative to its container, so we need to factor in offsets
|
||||||
|
*/
|
||||||
|
container_offset = $(container).offset();
|
||||||
|
offset_left = -container_offset.left;
|
||||||
|
offset_top = $(document).scrollTop() - container_offset.top;
|
||||||
|
tip_left = offset_left + rect_center - (tip_width / 2);
|
||||||
|
tip_top = offset_top + rect_top - tip_height + adjust_y;
|
||||||
|
|
||||||
afterScrollToSpan: (span_el) ->
|
/*
|
||||||
span_el.addClass 'selected', 400, 'swing', ->
|
make sure the new tip position doesn't clip the edges of the screen
|
||||||
span_el.removeClass 'selected', 400, 'swing'
|
*/
|
||||||
|
win_width = $(window).width();
|
||||||
|
if (tip_left < offset_left) {
|
||||||
|
tip_left = offset_left;
|
||||||
|
} else if (tip_left + tip_width > win_width + offset_left) {
|
||||||
|
tip_left = win_width + offset_left - tip_width;
|
||||||
|
}
|
||||||
|
|
||||||
makeTipContent: (el) ->
|
/*
|
||||||
(api) =>
|
final step: update the position object (used by qtip2 to show the tip after the move event)
|
||||||
text = $(el).data('comment-body')
|
*/
|
||||||
comment = @createComment(text)
|
return $.extend(position, {
|
||||||
problem_id = @getProblemId(el)
|
'left': tip_left,
|
||||||
reply = @createReplyLink(problem_id)
|
'top': tip_top
|
||||||
$(comment).add(reply)
|
});
|
||||||
|
};
|
||||||
|
|
||||||
makeTipTitle: (el) ->
|
Annotatable.prototype.getSpanForProblemReturn = function(el) {
|
||||||
(api) =>
|
var problem_id;
|
||||||
title = $(el).data('comment-title')
|
problem_id = $(this.problemReturnSelector).index(el);
|
||||||
(if title then title else gettext('Commentary'))
|
return this.$(this.spanSelector).filter("[data-problem-id='" + problem_id + "']");
|
||||||
|
};
|
||||||
|
|
||||||
createComment: (text) ->
|
Annotatable.prototype.getProblem = function(el) {
|
||||||
$("<div class=\"annotatable-comment\">#{text}</div>")
|
var problem_id;
|
||||||
|
problem_id = this.getProblemId(el);
|
||||||
|
return $(this.problemInputSelector).eq(problem_id);
|
||||||
|
};
|
||||||
|
|
||||||
createReplyLink: (problem_id) ->
|
Annotatable.prototype.getProblemId = function(el) {
|
||||||
linktxt = gettext('Reply to Annotation')
|
return $(el).data('problem-id');
|
||||||
$("<a class=\"annotatable-reply\" href=\"javascript:void(0);\" data-problem-id=\"#{problem_id}\">#{linktxt}</a>")
|
};
|
||||||
|
|
||||||
findVisibleTips: () ->
|
Annotatable.prototype.toggleAnnotations = function() {
|
||||||
visible = []
|
var hide;
|
||||||
@$(@spanSelector).each (index, el) ->
|
hide = (this.annotationsHidden = !this.annotationsHidden);
|
||||||
api = $(el).qtip('api')
|
this.toggleAnnotationButtonText(hide);
|
||||||
tip = $(api?.elements.tooltip)
|
this.toggleSpans(hide);
|
||||||
if tip.is(':visible')
|
return this.toggleTips(hide);
|
||||||
visible.push el
|
};
|
||||||
visible
|
|
||||||
|
|
||||||
hideTips: (elements) ->
|
Annotatable.prototype.toggleTips = function(hide) {
|
||||||
$(elements).qtip('hide')
|
var visible;
|
||||||
|
visible = this.findVisibleTips();
|
||||||
|
return this.hideTips(visible);
|
||||||
|
};
|
||||||
|
|
||||||
_once: (fn) ->
|
Annotatable.prototype.toggleAnnotationButtonText = function(hide) {
|
||||||
done = false
|
var buttonText;
|
||||||
return =>
|
if (hide) {
|
||||||
fn.call this unless done
|
buttonText = gettext('Show Annotations');
|
||||||
done = true
|
} else {
|
||||||
|
buttonText = gettext('Hide Annotations');
|
||||||
|
}
|
||||||
|
return this.$(this.toggleAnnotationsSelector).text(buttonText);
|
||||||
|
};
|
||||||
|
|
||||||
|
Annotatable.prototype.toggleInstructions = function() {
|
||||||
|
var hide;
|
||||||
|
hide = (this.instructionsHidden = !this.instructionsHidden);
|
||||||
|
this.toggleInstructionsButton(hide);
|
||||||
|
return this.toggleInstructionsText(hide);
|
||||||
|
};
|
||||||
|
|
||||||
|
Annotatable.prototype.toggleInstructionsButton = function(hide) {
|
||||||
|
var cls, txt;
|
||||||
|
if (hide) {
|
||||||
|
txt = gettext('Expand Instructions');
|
||||||
|
} else {
|
||||||
|
txt = gettext('Collapse Instructions');
|
||||||
|
}
|
||||||
|
cls = (hide ? ['expanded', 'collapsed'] : ['collapsed', 'expanded']);
|
||||||
|
return this.$(this.toggleInstructionsSelector).text(txt).removeClass(cls[0]).addClass(cls[1]);
|
||||||
|
};
|
||||||
|
|
||||||
|
Annotatable.prototype.toggleInstructionsText = function(hide) {
|
||||||
|
var slideMethod;
|
||||||
|
slideMethod = (hide ? 'slideUp' : 'slideDown');
|
||||||
|
return this.$(this.instructionsSelector)[slideMethod]();
|
||||||
|
};
|
||||||
|
|
||||||
|
Annotatable.prototype.toggleSpans = function(hide) {
|
||||||
|
return this.$(this.spanSelector).toggleClass('hide', hide, 250);
|
||||||
|
};
|
||||||
|
|
||||||
|
Annotatable.prototype.replyTo = function(buttonEl) {
|
||||||
|
var el, offset;
|
||||||
|
offset = -20;
|
||||||
|
el = this.getProblem(buttonEl);
|
||||||
|
if (el.length > 0) {
|
||||||
|
return this.scrollTo(el, this.afterScrollToProblem, offset);
|
||||||
|
} else {
|
||||||
|
if (this._debug) {
|
||||||
|
return console.log('problem not found. event: ', e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Annotatable.prototype.returnFrom = function(buttonEl) {
|
||||||
|
var el, offset;
|
||||||
|
offset = -200;
|
||||||
|
el = this.getSpanForProblemReturn(buttonEl);
|
||||||
|
if (el.length > 0) {
|
||||||
|
return this.scrollTo(el, this.afterScrollToSpan, offset);
|
||||||
|
} else {
|
||||||
|
if (this._debug) {
|
||||||
|
return console.log('span not found. event:', e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Annotatable.prototype.scrollTo = function(el, after, offset) {
|
||||||
|
if (offset == null) {
|
||||||
|
offset = -20;
|
||||||
|
}
|
||||||
|
if ($(el).length > 0) {
|
||||||
|
return $('html,body').scrollTo(el, {
|
||||||
|
duration: 500,
|
||||||
|
onAfter: this._once((function(_this) {
|
||||||
|
return function() {
|
||||||
|
return after != null ? after.call(_this, el) : void 0;
|
||||||
|
};
|
||||||
|
})(this)),
|
||||||
|
offset: offset
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Annotatable.prototype.afterScrollToProblem = function(problem_el) {
|
||||||
|
return problem_el.effect('highlight', {}, 500);
|
||||||
|
};
|
||||||
|
|
||||||
|
Annotatable.prototype.afterScrollToSpan = function(span_el) {
|
||||||
|
return span_el.addClass('selected', 400, 'swing', function() {
|
||||||
|
return span_el.removeClass('selected', 400, 'swing');
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
Annotatable.prototype.makeTipContent = function(el) {
|
||||||
|
return (function(_this) {
|
||||||
|
return function(api) {
|
||||||
|
var comment, problem_id, reply, text;
|
||||||
|
text = $(el).data('comment-body');
|
||||||
|
comment = _this.createComment(text);
|
||||||
|
problem_id = _this.getProblemId(el);
|
||||||
|
reply = _this.createReplyLink(problem_id);
|
||||||
|
return $(comment).add(reply);
|
||||||
|
};
|
||||||
|
})(this);
|
||||||
|
};
|
||||||
|
|
||||||
|
Annotatable.prototype.makeTipTitle = function(el) {
|
||||||
|
return (function(_this) {
|
||||||
|
return function(api) {
|
||||||
|
var title;
|
||||||
|
title = $(el).data('comment-title');
|
||||||
|
if (title) {
|
||||||
|
return title;
|
||||||
|
} else {
|
||||||
|
return gettext('Commentary');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
})(this);
|
||||||
|
};
|
||||||
|
|
||||||
|
Annotatable.prototype.createComment = function(text) {
|
||||||
|
return $("<div class=\"annotatable-comment\">" + text + "</div>"); // xss-lint: disable=javascript-concat-html
|
||||||
|
};
|
||||||
|
|
||||||
|
Annotatable.prototype.createReplyLink = function(problem_id) {
|
||||||
|
var linktxt;
|
||||||
|
linktxt = gettext('Reply to Annotation');
|
||||||
|
return $("<a class=\"annotatable-reply\" href=\"javascript:void(0);\" data-problem-id=\"" + problem_id + "\">" + linktxt + "</a>"); // xss-lint: disable=javascript-concat-html
|
||||||
|
};
|
||||||
|
|
||||||
|
Annotatable.prototype.findVisibleTips = function() {
|
||||||
|
var visible;
|
||||||
|
visible = [];
|
||||||
|
this.$(this.spanSelector).each(function(index, el) {
|
||||||
|
var api, tip;
|
||||||
|
api = $(el).qtip('api');
|
||||||
|
tip = $(api != null ? api.elements.tooltip : void 0);
|
||||||
|
if (tip.is(':visible')) {
|
||||||
|
return visible.push(el);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return visible;
|
||||||
|
};
|
||||||
|
|
||||||
|
Annotatable.prototype.hideTips = function(elements) {
|
||||||
|
return $(elements).qtip('hide');
|
||||||
|
};
|
||||||
|
|
||||||
|
Annotatable.prototype._once = function(fn) {
|
||||||
|
var done;
|
||||||
|
done = false;
|
||||||
|
return (function(_this) {
|
||||||
|
return function() {
|
||||||
|
if (!done) {
|
||||||
|
fn.call(_this);
|
||||||
|
}
|
||||||
|
return done = true;
|
||||||
|
};
|
||||||
|
})(this);
|
||||||
|
};
|
||||||
|
|
||||||
|
return Annotatable;
|
||||||
|
|
||||||
|
})();
|
||||||
|
|
||||||
|
}).call(this);
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
/* eslint-disable */
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
//
|
//
|
||||||
// Circuit simulator
|
// Circuit simulator
|
||||||
|
|||||||
@@ -1,38 +1,60 @@
|
|||||||
class @Conditional
|
// Once generated by CoffeeScript 1.9.3, but now lives as pure JS
|
||||||
|
/* eslint-disable */
|
||||||
|
(function() {
|
||||||
|
this.Conditional = (function() {
|
||||||
|
function Conditional(element, callerElId) {
|
||||||
|
var dependencies;
|
||||||
|
this.el = $(element).find('.conditional-wrapper');
|
||||||
|
this.callerElId = callerElId;
|
||||||
|
if (callerElId !== void 0) {
|
||||||
|
dependencies = this.el.data('depends');
|
||||||
|
if ((typeof dependencies === 'string') && (dependencies.length > 0) && (dependencies.indexOf(callerElId) === -1)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.url = this.el.data('url');
|
||||||
|
if (this.url) {
|
||||||
|
this.render(element);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
constructor: (element, callerElId) ->
|
Conditional.prototype.render = function(element) {
|
||||||
@el = $(element).find('.conditional-wrapper')
|
return $.postWithPrefix(this.url + "/conditional_get", (function(_this) {
|
||||||
|
return function(response) {
|
||||||
|
var i, j, len, parentEl, parentId, ref;
|
||||||
|
_this.el.html('');
|
||||||
|
ref = response.html;
|
||||||
|
for (j = 0, len = ref.length; j < len; j++) {
|
||||||
|
i = ref[j];
|
||||||
|
_this.el.append(i);
|
||||||
|
}
|
||||||
|
parentEl = $(element).parent();
|
||||||
|
parentId = parentEl.attr('id');
|
||||||
|
if (response.message === false) {
|
||||||
|
if (parentEl.hasClass('vert')) {
|
||||||
|
parentEl.hide();
|
||||||
|
} else {
|
||||||
|
$(element).hide();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (parentEl.hasClass('vert')) {
|
||||||
|
parentEl.show();
|
||||||
|
} else {
|
||||||
|
$(element).show();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@callerElId = callerElId
|
/*
|
||||||
|
The children are rendered with a new request, so they have a different request-token.
|
||||||
|
Use that token instead of @requestToken by simply not passing a token into initializeBlocks.
|
||||||
|
*/
|
||||||
|
return XBlock.initializeBlocks(_this.el);
|
||||||
|
};
|
||||||
|
})(this));
|
||||||
|
};
|
||||||
|
|
||||||
if callerElId isnt undefined
|
return Conditional;
|
||||||
dependencies = @el.data('depends')
|
|
||||||
if (typeof dependencies is 'string') and (dependencies.length > 0) and (dependencies.indexOf(callerElId) is -1)
|
|
||||||
return
|
|
||||||
|
|
||||||
@url = @el.data('url')
|
})();
|
||||||
if @url
|
|
||||||
@render(element)
|
|
||||||
|
|
||||||
render: (element) ->
|
}).call(this);
|
||||||
$.postWithPrefix "#{@url}/conditional_get", (response) =>
|
|
||||||
@el.html ''
|
|
||||||
@el.append(i) for i in response.html
|
|
||||||
|
|
||||||
parentEl = $(element).parent()
|
|
||||||
parentId = parentEl.attr 'id'
|
|
||||||
|
|
||||||
if response.message is false
|
|
||||||
if parentEl.hasClass('vert')
|
|
||||||
parentEl.hide()
|
|
||||||
else
|
|
||||||
$(element).hide()
|
|
||||||
else
|
|
||||||
if parentEl.hasClass('vert')
|
|
||||||
parentEl.show()
|
|
||||||
else
|
|
||||||
$(element).show()
|
|
||||||
|
|
||||||
# The children are rendered with a new request, so they have a different request-token.
|
|
||||||
# Use that token instead of @requestToken by simply not passing a token into initializeBlocks.
|
|
||||||
XBlock.initializeBlocks(@el)
|
|
||||||
|
|||||||
@@ -1,4 +1,21 @@
|
|||||||
class @InlineDiscussion extends XModule.Descriptor
|
// Once generated by CoffeeScript 1.9.3, but now lives as pure JS
|
||||||
constructor: (element) ->
|
/* eslint-disable */
|
||||||
@el = $(element).find('.discussion-module')
|
(function() {
|
||||||
@view = new DiscussionInlineView(el: @el)
|
var extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
|
||||||
|
hasProp = {}.hasOwnProperty;
|
||||||
|
|
||||||
|
this.InlineDiscussion = (function(superClass) {
|
||||||
|
extend(InlineDiscussion, superClass);
|
||||||
|
|
||||||
|
function InlineDiscussion(element) {
|
||||||
|
this.el = $(element).find('.discussion-module');
|
||||||
|
this.view = new DiscussionInlineView({
|
||||||
|
el: this.el
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return InlineDiscussion;
|
||||||
|
|
||||||
|
})(XModule.Descriptor);
|
||||||
|
|
||||||
|
}).call(this);
|
||||||
|
|||||||
@@ -1,13 +1,26 @@
|
|||||||
class @HTMLModule
|
// Once generated by CoffeeScript 1.9.3, but now lives as pure JS
|
||||||
|
/* eslint-disable */
|
||||||
|
(function() {
|
||||||
|
this.HTMLModule = (function() {
|
||||||
|
function HTMLModule(element) {
|
||||||
|
this.element = element;
|
||||||
|
this.el = $(this.element);
|
||||||
|
JavascriptLoader.executeModuleScripts(this.el);
|
||||||
|
Collapsible.setCollapsibles(this.el);
|
||||||
|
if (typeof MathJax !== "undefined" && MathJax !== null) {
|
||||||
|
MathJax.Hub.Queue(["Typeset", MathJax.Hub, this.el[0]]);
|
||||||
|
}
|
||||||
|
if (typeof setupFullScreenModal !== "undefined" && setupFullScreenModal !== null) {
|
||||||
|
setupFullScreenModal();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
constructor: (@element) ->
|
HTMLModule.prototype.$ = function(selector) {
|
||||||
@el = $(@element)
|
return $(selector, this.el);
|
||||||
JavascriptLoader.executeModuleScripts(@el)
|
};
|
||||||
Collapsible.setCollapsibles(@el)
|
|
||||||
if MathJax?
|
|
||||||
MathJax.Hub.Queue ["Typeset", MathJax.Hub, @el[0]]
|
|
||||||
if setupFullScreenModal?
|
|
||||||
setupFullScreenModal()
|
|
||||||
|
|
||||||
$: (selector) ->
|
return HTMLModule;
|
||||||
$(selector, @el)
|
|
||||||
|
})();
|
||||||
|
|
||||||
|
}).call(this);
|
||||||
|
|||||||
@@ -1,92 +1,141 @@
|
|||||||
class @HTMLEditingDescriptor
|
// Once generated by CoffeeScript 1.9.3, but now lives as pure JS
|
||||||
|
/* eslint-disable */
|
||||||
|
(function() {
|
||||||
|
var bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; };
|
||||||
|
|
||||||
# custom fonts are prepended to font selection dropdown
|
this.HTMLEditingDescriptor = (function() {
|
||||||
CUSTOM_FONTS = "Default='Open Sans', Verdana, Arial, Helvetica, sans-serif;"
|
|
||||||
|
|
||||||
# list of standard tinyMCE fonts: http://www.tinymce.com/wiki.php/Configuration:font_formats
|
/*
|
||||||
STANDARD_FONTS = "Andale Mono=andale mono,times;"+
|
custom fonts are prepended to font selection dropdown
|
||||||
"Arial=arial,helvetica,sans-serif;"+
|
*/
|
||||||
"Arial Black=arial black,avant garde;"+
|
var CUSTOM_FONTS, STANDARD_FONTS, _getFonts;
|
||||||
"Book Antiqua=book antiqua,palatino;"+
|
|
||||||
"Comic Sans MS=comic sans ms,sans-serif;"+
|
|
||||||
"Courier New=courier new,courier;"+
|
|
||||||
"Georgia=georgia,palatino;"+
|
|
||||||
"Helvetica=helvetica;"+
|
|
||||||
"Impact=impact,chicago;"+
|
|
||||||
"Symbol=symbol;"+
|
|
||||||
"Tahoma=tahoma,arial,helvetica,sans-serif;"+
|
|
||||||
"Terminal=terminal,monaco;"+
|
|
||||||
"Times New Roman=times new roman,times;"+
|
|
||||||
"Trebuchet MS=trebuchet ms,geneva;"+
|
|
||||||
"Verdana=verdana,geneva;"+
|
|
||||||
"Webdings=webdings;"+
|
|
||||||
"Wingdings=wingdings,zapf dingbats"
|
|
||||||
|
|
||||||
_getFonts = () ->
|
CUSTOM_FONTS = "Default='Open Sans', Verdana, Arial, Helvetica, sans-serif;";
|
||||||
CUSTOM_FONTS + STANDARD_FONTS
|
|
||||||
|
|
||||||
constructor: (element) ->
|
/*
|
||||||
@element = element
|
list of standard tinyMCE fonts: http://www.tinymce.com/wiki.php/Configuration:font_formats
|
||||||
@base_asset_url = @element.find("#editor-tab").data('base-asset-url')
|
*/
|
||||||
@editor_choice = @element.find("#editor-tab").data('editor')
|
STANDARD_FONTS = "Andale Mono=andale mono,times;" +
|
||||||
@new_image_modal = window.STUDIO_FRONTEND_IN_CONTEXT_IMAGE_SELECTION
|
"Arial=arial,helvetica,sans-serif;" +
|
||||||
if @base_asset_url == undefined
|
"Arial Black=arial black,avant garde;" +
|
||||||
@base_asset_url = null
|
"Book Antiqua=book antiqua,palatino;" +
|
||||||
|
"Comic Sans MS=comic sans ms,sans-serif;" +
|
||||||
|
"Courier New=courier new,courier;" +
|
||||||
|
"Georgia=georgia,palatino;" +
|
||||||
|
"Helvetica=helvetica;" +
|
||||||
|
"Impact=impact,chicago;" +
|
||||||
|
"Symbol=symbol;" +
|
||||||
|
"Tahoma=tahoma,arial,helvetica,sans-serif;" +
|
||||||
|
"Terminal=terminal,monaco;" +
|
||||||
|
"Times New Roman=times new roman,times;" +
|
||||||
|
"Trebuchet MS=trebuchet ms,geneva;" +
|
||||||
|
"Verdana=verdana,geneva;" +
|
||||||
|
"Webdings=webdings;" +
|
||||||
|
"Wingdings=wingdings,zapf dingbats";
|
||||||
|
|
||||||
# We always create the "raw editor" so we can get the text out of it if necessary on save.
|
_getFonts = function() {
|
||||||
@advanced_editor = CodeMirror.fromTextArea($(".edit-box", @element)[0], {
|
return CUSTOM_FONTS + STANDARD_FONTS;
|
||||||
mode: "text/html"
|
};
|
||||||
lineNumbers: true
|
|
||||||
|
function HTMLEditingDescriptor(element) {
|
||||||
|
this.initInstanceCallback = bind(this.initInstanceCallback, this);
|
||||||
|
this.saveCodeEditor = bind(this.saveCodeEditor, this);
|
||||||
|
this.showCodeEditor = bind(this.showCodeEditor, this);
|
||||||
|
this.saveLink = bind(this.saveLink, this);
|
||||||
|
this.editLink = bind(this.editLink, this);
|
||||||
|
this.editImageSubmit = bind(this.editImageSubmit, this);
|
||||||
|
this.saveImageFromModal = bind(this.saveImageFromModal, this);
|
||||||
|
this.closeImageModal = bind(this.closeImageModal, this);
|
||||||
|
this.openImageModal = bind(this.openImageModal, this);
|
||||||
|
this.saveImage = bind(this.saveImage, this);
|
||||||
|
this.editImage = bind(this.editImage, this);
|
||||||
|
this.setupTinyMCE = bind(this.setupTinyMCE, this);
|
||||||
|
var tiny_mce_css_links;
|
||||||
|
this.element = element;
|
||||||
|
this.base_asset_url = this.element.find("#editor-tab").data('base-asset-url');
|
||||||
|
this.editor_choice = this.element.find("#editor-tab").data('editor');
|
||||||
|
this.new_image_modal = window.STUDIO_FRONTEND_IN_CONTEXT_IMAGE_SELECTION;
|
||||||
|
if (this.base_asset_url === void 0) {
|
||||||
|
this.base_asset_url = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
We always create the "raw editor" so we can get the text out of it if necessary on save.
|
||||||
|
*/
|
||||||
|
this.advanced_editor = CodeMirror.fromTextArea($(".edit-box", this.element)[0], {
|
||||||
|
mode: "text/html",
|
||||||
|
lineNumbers: true,
|
||||||
lineWrapping: true
|
lineWrapping: true
|
||||||
})
|
});
|
||||||
|
if (this.editor_choice === 'visual') {
|
||||||
|
this.$advancedEditorWrapper = $(this.advanced_editor.getWrapperElement());
|
||||||
|
this.$advancedEditorWrapper.addClass('is-inactive');
|
||||||
|
|
||||||
if @editor_choice == 'visual'
|
/*
|
||||||
@$advancedEditorWrapper = $(@advanced_editor.getWrapperElement())
|
Create an array of all content CSS links to use in and pass to Tiny MCE.
|
||||||
@$advancedEditorWrapper.addClass('is-inactive')
|
We create this dynamically in order to support hashed files from our Django pipeline.
|
||||||
# Create an array of all content CSS links to use in and pass to Tiny MCE.
|
CSS files that are to be used by Tiny MCE should contain the string "tinymce" so
|
||||||
# We create this dynamically in order to support hashed files from our Django pipeline.
|
they can be found by the search below.
|
||||||
# CSS files that are to be used by Tiny MCE should contain the string "tinymce" so
|
We filter for only those files that are "content" files (as opposed to "skin" files).
|
||||||
# they can be found by the search below.
|
*/
|
||||||
# We filter for only those files that are "content" files (as opposed to "skin" files).
|
tiny_mce_css_links = [];
|
||||||
tiny_mce_css_links = []
|
$("link[rel=stylesheet][href*='tinymce']").filter("[href*='content']").each(function() {
|
||||||
$("link[rel=stylesheet][href*='tinymce']").filter("[href*='content']").each ->
|
tiny_mce_css_links.push($(this).attr("href"));
|
||||||
tiny_mce_css_links.push $(this).attr("href")
|
});
|
||||||
return
|
|
||||||
|
|
||||||
# This is a workaround for the fact that tinyMCE's baseURL property is not getting correctly set on AWS
|
/*
|
||||||
# instances (like sandbox). It is not necessary to explicitly set baseURL when running locally.
|
This is a workaround for the fact that tinyMCE's baseURL property is not getting correctly set on AWS
|
||||||
tinyMCE.baseURL = "#{baseUrl}/js/vendor/tinymce/js/tinymce"
|
instances (like sandbox). It is not necessary to explicitly set baseURL when running locally.
|
||||||
# This is necessary for the LMS bulk e-mail acceptance test. In that particular scenario,
|
*/
|
||||||
# tinyMCE incorrectly decides that the suffix should be "", which means it fails to load files.
|
tinyMCE.baseURL = baseUrl + "/js/vendor/tinymce/js/tinymce";
|
||||||
tinyMCE.suffix = ".min"
|
|
||||||
@tiny_mce_textarea = $(".tiny-mce", @element).tinymce({
|
/*
|
||||||
script_url : "#{baseUrl}/js/vendor/tinymce/js/tinymce/tinymce.full.min.js",
|
This is necessary for the LMS bulk e-mail acceptance test. In that particular scenario,
|
||||||
font_formats : _getFonts(),
|
tinyMCE incorrectly decides that the suffix should be "", which means it fails to load files.
|
||||||
theme : "modern",
|
*/
|
||||||
skin: 'studio-tmce4',
|
tinyMCE.suffix = ".min";
|
||||||
schema: "html5",
|
this.tiny_mce_textarea = $(".tiny-mce", this.element).tinymce({
|
||||||
# Necessary to preserve relative URLs to our images.
|
script_url: baseUrl + "/js/vendor/tinymce/js/tinymce/tinymce.full.min.js",
|
||||||
convert_urls : false,
|
font_formats: _getFonts(),
|
||||||
# Sniff UI direction from `.wrapper-view` in studio or `.window-wrap` in LMS
|
theme: "modern",
|
||||||
directionality: $(".wrapper-view, .window-wrap").prop('dir'),
|
skin: 'studio-tmce4',
|
||||||
content_css : tiny_mce_css_links.join(", "),
|
schema: "html5",
|
||||||
formats : {
|
|
||||||
# tinyMCE does block level for code by default
|
/*
|
||||||
code: {inline: 'code'}
|
Necessary to preserve relative URLs to our images.
|
||||||
},
|
*/
|
||||||
# Disable visual aid on borderless table.
|
convert_urls: false,
|
||||||
visual: false,
|
|
||||||
plugins: "textcolor, link, image, codemirror",
|
/*
|
||||||
codemirror: {
|
Sniff UI direction from `.wrapper-view` in studio or `.window-wrap` in LMS
|
||||||
path: "#{baseUrl}/js/vendor"
|
*/
|
||||||
},
|
directionality: $(".wrapper-view, .window-wrap").prop('dir'),
|
||||||
image_advtab: true,
|
content_css: tiny_mce_css_links.join(", "),
|
||||||
# We may want to add "styleselect" when we collect all styles used throughout the LMS
|
formats: {
|
||||||
toolbar: "formatselect | fontselect | bold italic underline forecolor wrapAsCode | " +
|
// tinyMCE does block level for code by default
|
||||||
"alignleft aligncenter alignright alignjustify | " +
|
code: {
|
||||||
"bullist numlist outdent indent blockquote | link unlink " +
|
inline: 'code'
|
||||||
"#{if @new_image_modal then 'insertImage' else 'image'} | code",
|
}
|
||||||
block_formats: interpolate("%(paragraph)s=p;%(preformatted)s=pre;%(heading3)s=h3;%(heading4)s=h4;%(heading5)s=h5;%(heading6)s=h6", {
|
},
|
||||||
|
|
||||||
|
/*
|
||||||
|
Disable visual aid on borderless table.
|
||||||
|
*/
|
||||||
|
visual: false,
|
||||||
|
plugins: "textcolor, link, image, codemirror",
|
||||||
|
codemirror: {
|
||||||
|
path: baseUrl + "/js/vendor"
|
||||||
|
},
|
||||||
|
image_advtab: true,
|
||||||
|
|
||||||
|
/*
|
||||||
|
We may want to add "styleselect" when we collect all styles used throughout the LMS
|
||||||
|
*/
|
||||||
|
toolbar: "formatselect | fontselect | bold italic underline forecolor wrapAsCode | " +
|
||||||
|
"alignleft aligncenter alignright alignjustify | " +
|
||||||
|
"bullist numlist outdent indent blockquote | link unlink " +
|
||||||
|
((this.new_image_modal ? 'insertImage' : 'image') + " | code"),
|
||||||
|
block_formats: interpolate("%(paragraph)s=p;%(preformatted)s=pre;%(heading3)s=h3;%(heading4)s=h4;%(heading5)s=h5;%(heading6)s=h6", {
|
||||||
paragraph: gettext("Paragraph"),
|
paragraph: gettext("Paragraph"),
|
||||||
preformatted: gettext("Preformatted"),
|
preformatted: gettext("Preformatted"),
|
||||||
heading3: gettext("Heading 3"),
|
heading3: gettext("Heading 3"),
|
||||||
@@ -94,961 +143,1246 @@ class @HTMLEditingDescriptor
|
|||||||
heading5: gettext("Heading 5"),
|
heading5: gettext("Heading 5"),
|
||||||
heading6: gettext("Heading 6")
|
heading6: gettext("Heading 6")
|
||||||
}, true),
|
}, true),
|
||||||
width: '100%',
|
width: '100%',
|
||||||
height: '400px',
|
height: '400px',
|
||||||
menubar: false,
|
menubar: false,
|
||||||
statusbar: false,
|
statusbar: false,
|
||||||
|
|
||||||
# Necessary to avoid stripping of style tags.
|
/*
|
||||||
valid_children : "+body[style]",
|
Necessary to avoid stripping of style tags.
|
||||||
|
*/
|
||||||
|
valid_children: "+body[style]",
|
||||||
|
|
||||||
# Allow any elements to be used, e.g. link, script, math
|
/*
|
||||||
valid_elements: "*[*]",
|
Allow any elements to be used, e.g. link, script, math
|
||||||
extended_valid_elements: "*[*]",
|
*/
|
||||||
invalid_elements: "",
|
valid_elements: "*[*]",
|
||||||
|
extended_valid_elements: "*[*]",
|
||||||
|
invalid_elements: "",
|
||||||
|
setup: this.setupTinyMCE,
|
||||||
|
|
||||||
setup: @setupTinyMCE,
|
/*
|
||||||
# Cannot get access to tinyMCE Editor instance (for focusing) until after it is rendered.
|
Cannot get access to tinyMCE Editor instance (for focusing) until after it is rendered.
|
||||||
# The tinyMCE callback passes in the editor as a parameter.
|
The tinyMCE callback passes in the editor as a parameter.
|
||||||
init_instance_callback: @initInstanceCallback,
|
*/
|
||||||
|
init_instance_callback: this.initInstanceCallback,
|
||||||
|
browser_spellcheck: true
|
||||||
|
});
|
||||||
|
tinymce.addI18n('en', {
|
||||||
|
|
||||||
browser_spellcheck: true
|
/*
|
||||||
})
|
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
||||||
tinymce.addI18n('en', {
|
*/
|
||||||
###
|
"Add to Dictionary": gettext("Add to Dictionary"),
|
||||||
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
|
||||||
###
|
|
||||||
"Add to Dictionary": gettext("Add to Dictionary"),
|
|
||||||
###
|
|
||||||
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
|
||||||
###
|
|
||||||
"Advanced": gettext("Advanced"),
|
|
||||||
###
|
|
||||||
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
|
||||||
###
|
|
||||||
"Align center": gettext("Align center"),
|
|
||||||
###
|
|
||||||
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
|
||||||
###
|
|
||||||
"Align left": gettext("Align left"),
|
|
||||||
###
|
|
||||||
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
|
||||||
###
|
|
||||||
"Align right": gettext("Align right"),
|
|
||||||
###
|
|
||||||
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
|
||||||
###
|
|
||||||
"Alignment": gettext("Alignment"),
|
|
||||||
###
|
|
||||||
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
|
||||||
###
|
|
||||||
"Alternative source": gettext("Alternative source"),
|
|
||||||
###
|
|
||||||
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
|
||||||
###
|
|
||||||
"Anchor": gettext("Anchor"),
|
|
||||||
###
|
|
||||||
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
|
||||||
###
|
|
||||||
"Anchors": gettext("Anchors"),
|
|
||||||
###
|
|
||||||
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
|
||||||
###
|
|
||||||
"Author": gettext("Author"),
|
|
||||||
###
|
|
||||||
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
|
||||||
###
|
|
||||||
"Background color": gettext("Background color"),
|
|
||||||
###
|
|
||||||
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
|
||||||
###
|
|
||||||
"Blockquote": gettext("Blockquote"),
|
|
||||||
###
|
|
||||||
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
|
||||||
###
|
|
||||||
"Blocks": gettext("Blocks"),
|
|
||||||
###
|
|
||||||
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
|
||||||
###
|
|
||||||
"Body": gettext("Body"),
|
|
||||||
###
|
|
||||||
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
|
||||||
###
|
|
||||||
"Bold": gettext("Bold"),
|
|
||||||
###
|
|
||||||
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
|
||||||
###
|
|
||||||
"Border color": gettext("Border color"),
|
|
||||||
###
|
|
||||||
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
|
||||||
###
|
|
||||||
"Border": gettext("Border"),
|
|
||||||
###
|
|
||||||
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
|
||||||
###
|
|
||||||
"Bottom": gettext("Bottom"),
|
|
||||||
###
|
|
||||||
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
|
||||||
###
|
|
||||||
"Bullet list": gettext("Bullet list"),
|
|
||||||
###
|
|
||||||
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
|
||||||
###
|
|
||||||
"Cancel": gettext("Cancel"),
|
|
||||||
###
|
|
||||||
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
|
||||||
###
|
|
||||||
"Caption": gettext("Caption"),
|
|
||||||
###
|
|
||||||
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
|
||||||
###
|
|
||||||
"Cell padding": gettext("Cell padding"),
|
|
||||||
###
|
|
||||||
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
|
||||||
###
|
|
||||||
"Cell properties": gettext("Cell properties"),
|
|
||||||
###
|
|
||||||
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
|
||||||
###
|
|
||||||
"Cell spacing": gettext("Cell spacing"),
|
|
||||||
###
|
|
||||||
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
|
||||||
###
|
|
||||||
"Cell type": gettext("Cell type"),
|
|
||||||
###
|
|
||||||
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
|
||||||
###
|
|
||||||
"Cell": gettext("Cell"),
|
|
||||||
###
|
|
||||||
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
|
||||||
###
|
|
||||||
"Center": gettext("Center"),
|
|
||||||
###
|
|
||||||
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
|
||||||
###
|
|
||||||
"Circle": gettext("Circle"),
|
|
||||||
###
|
|
||||||
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
|
||||||
###
|
|
||||||
"Clear formatting": gettext("Clear formatting"),
|
|
||||||
###
|
|
||||||
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
|
||||||
###
|
|
||||||
"Close": gettext("Close"),
|
|
||||||
###
|
|
||||||
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
|
||||||
###
|
|
||||||
"Code block": gettext("Code block"),
|
|
||||||
###
|
|
||||||
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
|
||||||
###
|
|
||||||
"Code": gettext("Code"),
|
|
||||||
###
|
|
||||||
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
|
||||||
###
|
|
||||||
"Color": gettext("Color"),
|
|
||||||
###
|
|
||||||
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
|
||||||
###
|
|
||||||
"Cols": gettext("Cols"),
|
|
||||||
###
|
|
||||||
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
|
||||||
###
|
|
||||||
"Column group": gettext("Column group"),
|
|
||||||
###
|
|
||||||
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
|
||||||
###
|
|
||||||
"Column": gettext("Column"),
|
|
||||||
###
|
|
||||||
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
|
||||||
###
|
|
||||||
"Constrain proportions": gettext("Constrain proportions"),
|
|
||||||
###
|
|
||||||
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
|
||||||
###
|
|
||||||
"Copy row": gettext("Copy row"),
|
|
||||||
###
|
|
||||||
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
|
||||||
###
|
|
||||||
"Copy": gettext("Copy"),
|
|
||||||
###
|
|
||||||
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
|
||||||
###
|
|
||||||
"Could not find the specified string.": gettext("Could not find the specified string."),
|
|
||||||
###
|
|
||||||
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
|
||||||
###
|
|
||||||
"Custom color": gettext("Custom color"),
|
|
||||||
###
|
|
||||||
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
|
||||||
###
|
|
||||||
"Custom...": gettext("Custom..."),
|
|
||||||
###
|
|
||||||
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
|
||||||
###
|
|
||||||
"Cut row": gettext("Cut row"),
|
|
||||||
###
|
|
||||||
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
|
||||||
###
|
|
||||||
"Cut": gettext("Cut"),
|
|
||||||
###
|
|
||||||
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
|
||||||
###
|
|
||||||
"Decrease indent": gettext("Decrease indent"),
|
|
||||||
###
|
|
||||||
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
|
||||||
###
|
|
||||||
"Default": gettext("Default"),
|
|
||||||
###
|
|
||||||
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
|
||||||
###
|
|
||||||
"Delete column": gettext("Delete column"),
|
|
||||||
###
|
|
||||||
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
|
||||||
###
|
|
||||||
"Delete row": gettext("Delete row"),
|
|
||||||
###
|
|
||||||
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
|
||||||
###
|
|
||||||
"Delete table": gettext("Delete table"),
|
|
||||||
###
|
|
||||||
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
|
||||||
###
|
|
||||||
"Description": gettext("Description"),
|
|
||||||
###
|
|
||||||
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
|
||||||
###
|
|
||||||
"Dimensions": gettext("Dimensions"),
|
|
||||||
###
|
|
||||||
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
|
||||||
###
|
|
||||||
"Disc": gettext("Disc"),
|
|
||||||
###
|
|
||||||
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
|
||||||
###
|
|
||||||
"Div": gettext("Div"),
|
|
||||||
###
|
|
||||||
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
|
||||||
###
|
|
||||||
"Document properties": gettext("Document properties"),
|
|
||||||
###
|
|
||||||
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
|
||||||
###
|
|
||||||
"Edit HTML": gettext("Edit HTML"),
|
|
||||||
###
|
|
||||||
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
|
||||||
###
|
|
||||||
"Edit": gettext("Edit"),
|
|
||||||
###
|
|
||||||
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
|
||||||
###
|
|
||||||
"Embed": gettext("Embed"),
|
|
||||||
###
|
|
||||||
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
|
||||||
###
|
|
||||||
"Emoticons": gettext("Emoticons"),
|
|
||||||
###
|
|
||||||
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
|
||||||
###
|
|
||||||
"Encoding": gettext("Encoding"),
|
|
||||||
###
|
|
||||||
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
|
||||||
###
|
|
||||||
"File": gettext("File"),
|
|
||||||
###
|
|
||||||
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
|
||||||
###
|
|
||||||
"Find and replace": gettext("Find and replace"),
|
|
||||||
###
|
|
||||||
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
|
||||||
###
|
|
||||||
"Find next": gettext("Find next"),
|
|
||||||
###
|
|
||||||
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
|
||||||
###
|
|
||||||
"Find previous": gettext("Find previous"),
|
|
||||||
###
|
|
||||||
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
|
||||||
###
|
|
||||||
"Find": gettext("Find"),
|
|
||||||
###
|
|
||||||
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
|
||||||
###
|
|
||||||
"Finish": gettext("Finish"),
|
|
||||||
###
|
|
||||||
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
|
||||||
###
|
|
||||||
"Font Family": gettext("Font Family"),
|
|
||||||
###
|
|
||||||
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
|
||||||
###
|
|
||||||
"Font Sizes": gettext("Font Sizes"),
|
|
||||||
###
|
|
||||||
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
|
||||||
###
|
|
||||||
"Footer": gettext("Footer"),
|
|
||||||
###
|
|
||||||
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
|
||||||
###
|
|
||||||
"Format": gettext("Format"),
|
|
||||||
###
|
|
||||||
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
|
||||||
###
|
|
||||||
"Formats": gettext("Formats"),
|
|
||||||
###
|
|
||||||
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
|
||||||
###
|
|
||||||
"Fullscreen": gettext("Fullscreen"),
|
|
||||||
###
|
|
||||||
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
|
||||||
###
|
|
||||||
"General": gettext("General"),
|
|
||||||
###
|
|
||||||
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
|
||||||
###
|
|
||||||
"H Align": gettext("H Align"),
|
|
||||||
###
|
|
||||||
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
|
||||||
###
|
|
||||||
"Header 1": gettext("Header 1"),
|
|
||||||
###
|
|
||||||
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
|
||||||
###
|
|
||||||
"Header 2": gettext("Header 2"),
|
|
||||||
###
|
|
||||||
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
|
||||||
###
|
|
||||||
"Header 3": gettext("Header 3"),
|
|
||||||
###
|
|
||||||
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
|
||||||
###
|
|
||||||
"Header 4": gettext("Header 4"),
|
|
||||||
###
|
|
||||||
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
|
||||||
###
|
|
||||||
"Header 5": gettext("Header 5"),
|
|
||||||
###
|
|
||||||
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
|
||||||
###
|
|
||||||
"Header 6": gettext("Header 6"),
|
|
||||||
###
|
|
||||||
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
|
||||||
###
|
|
||||||
"Header cell": gettext("Header cell"),
|
|
||||||
###
|
|
||||||
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
|
||||||
###
|
|
||||||
"Header": gettext("Header"),
|
|
||||||
###
|
|
||||||
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
|
||||||
###
|
|
||||||
"Headers": gettext("Headers"),
|
|
||||||
###
|
|
||||||
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
|
||||||
###
|
|
||||||
"Heading 1": gettext("Heading 1"),
|
|
||||||
###
|
|
||||||
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
|
||||||
###
|
|
||||||
"Heading 2": gettext("Heading 2"),
|
|
||||||
###
|
|
||||||
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
|
||||||
###
|
|
||||||
"Heading 3": gettext("Heading 3"),
|
|
||||||
###
|
|
||||||
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
|
||||||
###
|
|
||||||
"Heading 4": gettext("Heading 4"),
|
|
||||||
###
|
|
||||||
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
|
||||||
###
|
|
||||||
"Heading 5": gettext("Heading 5"),
|
|
||||||
###
|
|
||||||
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
|
||||||
###
|
|
||||||
"Heading 6": gettext("Heading 6"),
|
|
||||||
###
|
|
||||||
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
|
||||||
###
|
|
||||||
"Headings": gettext("Headings"),
|
|
||||||
###
|
|
||||||
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
|
||||||
###
|
|
||||||
"Height": gettext("Height"),
|
|
||||||
###
|
|
||||||
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
|
||||||
###
|
|
||||||
"Horizontal line": gettext("Horizontal line"),
|
|
||||||
###
|
|
||||||
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
|
||||||
###
|
|
||||||
"Horizontal space": gettext("Horizontal space"),
|
|
||||||
###
|
|
||||||
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
|
||||||
###
|
|
||||||
"HTML source code": gettext("HTML source code"),
|
|
||||||
###
|
|
||||||
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
|
||||||
###
|
|
||||||
"Ignore all": gettext("Ignore all"),
|
|
||||||
###
|
|
||||||
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
|
||||||
###
|
|
||||||
"Ignore": gettext("Ignore"),
|
|
||||||
###
|
|
||||||
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
|
||||||
###
|
|
||||||
"Image description": gettext("Image description"),
|
|
||||||
###
|
|
||||||
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
|
||||||
###
|
|
||||||
"Increase indent": gettext("Increase indent"),
|
|
||||||
###
|
|
||||||
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
|
||||||
###
|
|
||||||
"Inline": gettext("Inline"),
|
|
||||||
###
|
|
||||||
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
|
||||||
###
|
|
||||||
"Insert column after": gettext("Insert column after"),
|
|
||||||
###
|
|
||||||
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
|
||||||
###
|
|
||||||
"Insert column before": gettext("Insert column before"),
|
|
||||||
###
|
|
||||||
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
|
||||||
###
|
|
||||||
"Insert date/time": gettext("Insert date/time"),
|
|
||||||
###
|
|
||||||
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
|
||||||
###
|
|
||||||
"Insert image": gettext("Insert image"),
|
|
||||||
###
|
|
||||||
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
|
||||||
###
|
|
||||||
"Insert link": gettext("Insert link"),
|
|
||||||
###
|
|
||||||
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
|
||||||
###
|
|
||||||
"Insert row after": gettext("Insert row after"),
|
|
||||||
###
|
|
||||||
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
|
||||||
###
|
|
||||||
"Insert row before": gettext("Insert row before"),
|
|
||||||
###
|
|
||||||
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
|
||||||
###
|
|
||||||
"Insert table": gettext("Insert table"),
|
|
||||||
###
|
|
||||||
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
|
||||||
###
|
|
||||||
"Insert template": gettext("Insert template"),
|
|
||||||
###
|
|
||||||
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
|
||||||
###
|
|
||||||
"Insert video": gettext("Insert video"),
|
|
||||||
###
|
|
||||||
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
|
||||||
###
|
|
||||||
"Insert": gettext("Insert"),
|
|
||||||
###
|
|
||||||
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
|
||||||
###
|
|
||||||
"Insert/edit image": gettext("Insert/edit image"),
|
|
||||||
###
|
|
||||||
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
|
||||||
###
|
|
||||||
"Insert/edit link": gettext("Insert/edit link"),
|
|
||||||
###
|
|
||||||
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
|
||||||
###
|
|
||||||
"Insert/edit video": gettext("Insert/edit video"),
|
|
||||||
###
|
|
||||||
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
|
||||||
###
|
|
||||||
"Italic": gettext("Italic"),
|
|
||||||
###
|
|
||||||
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
|
||||||
###
|
|
||||||
"Justify": gettext("Justify"),
|
|
||||||
###
|
|
||||||
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
|
||||||
###
|
|
||||||
"Keywords": gettext("Keywords"),
|
|
||||||
###
|
|
||||||
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
|
||||||
###
|
|
||||||
"Left to right": gettext("Left to right"),
|
|
||||||
###
|
|
||||||
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
|
||||||
###
|
|
||||||
"Left": gettext("Left"),
|
|
||||||
###
|
|
||||||
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
|
||||||
###
|
|
||||||
"Lower Alpha": gettext("Lower Alpha"),
|
|
||||||
###
|
|
||||||
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
|
||||||
###
|
|
||||||
"Lower Greek": gettext("Lower Greek"),
|
|
||||||
###
|
|
||||||
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
|
||||||
###
|
|
||||||
"Lower Roman": gettext("Lower Roman"),
|
|
||||||
###
|
|
||||||
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
|
||||||
###
|
|
||||||
"Match case": gettext("Match case"),
|
|
||||||
###
|
|
||||||
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
|
||||||
###
|
|
||||||
"Merge cells": gettext("Merge cells"),
|
|
||||||
###
|
|
||||||
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
|
||||||
###
|
|
||||||
"Middle": gettext("Middle"),
|
|
||||||
###
|
|
||||||
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
|
||||||
###
|
|
||||||
"Name": gettext("Name"),
|
|
||||||
###
|
|
||||||
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
|
||||||
###
|
|
||||||
"New document": gettext("New document"),
|
|
||||||
###
|
|
||||||
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
|
||||||
###
|
|
||||||
"New window": gettext("New window"),
|
|
||||||
###
|
|
||||||
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
|
||||||
###
|
|
||||||
"Next": gettext("Next"),
|
|
||||||
###
|
|
||||||
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
|
||||||
###
|
|
||||||
"No color": gettext("No color"),
|
|
||||||
###
|
|
||||||
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
|
||||||
###
|
|
||||||
"Nonbreaking space": gettext("Nonbreaking space"),
|
|
||||||
###
|
|
||||||
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
|
||||||
###
|
|
||||||
"None": gettext("None"),
|
|
||||||
###
|
|
||||||
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
|
||||||
###
|
|
||||||
"Numbered list": gettext("Numbered list"),
|
|
||||||
###
|
|
||||||
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
|
||||||
###
|
|
||||||
"Ok": gettext("Ok"),
|
|
||||||
###
|
|
||||||
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
|
||||||
###
|
|
||||||
"OK": gettext("OK"),
|
|
||||||
###
|
|
||||||
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
|
||||||
###
|
|
||||||
"Page break": gettext("Page break"),
|
|
||||||
###
|
|
||||||
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
|
||||||
###
|
|
||||||
"Paragraph": gettext("Paragraph"),
|
|
||||||
###
|
|
||||||
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
|
||||||
###
|
|
||||||
"Paste as text": gettext("Paste as text"),
|
|
||||||
###
|
|
||||||
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
|
||||||
###
|
|
||||||
"Paste is now in plain text mode. Contents will now be pasted as plain text until you toggle this option off.": gettext("Paste is now in plain text mode. Contents will now be pasted as plain text until you toggle this option off."),
|
|
||||||
###
|
|
||||||
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
|
||||||
###
|
|
||||||
"Paste row after": gettext("Paste row after"),
|
|
||||||
###
|
|
||||||
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
|
||||||
###
|
|
||||||
"Paste row before": gettext("Paste row before"),
|
|
||||||
###
|
|
||||||
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
|
||||||
###
|
|
||||||
"Paste your embed code below:": gettext("Paste your embed code below:"),
|
|
||||||
###
|
|
||||||
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
|
||||||
###
|
|
||||||
"Paste": gettext("Paste"),
|
|
||||||
###
|
|
||||||
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
|
||||||
###
|
|
||||||
"Poster": gettext("Poster"),
|
|
||||||
###
|
|
||||||
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
|
||||||
###
|
|
||||||
"Pre": gettext("Pre"),
|
|
||||||
###
|
|
||||||
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
|
||||||
###
|
|
||||||
"Prev": gettext("Prev"),
|
|
||||||
###
|
|
||||||
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
|
||||||
###
|
|
||||||
"Preview": gettext("Preview"),
|
|
||||||
###
|
|
||||||
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
|
||||||
###
|
|
||||||
"Print": gettext("Print"),
|
|
||||||
###
|
|
||||||
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
|
||||||
###
|
|
||||||
"Redo": gettext("Redo"),
|
|
||||||
###
|
|
||||||
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
|
||||||
###
|
|
||||||
"Remove link": gettext("Remove link"),
|
|
||||||
###
|
|
||||||
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
|
||||||
###
|
|
||||||
"Replace all": gettext("Replace all"),
|
|
||||||
###
|
|
||||||
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
|
||||||
###
|
|
||||||
"Replace all": gettext("Replace all"),
|
|
||||||
###
|
|
||||||
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
|
||||||
###
|
|
||||||
"Replace with": gettext("Replace with"),
|
|
||||||
###
|
|
||||||
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
|
||||||
###
|
|
||||||
"Replace": gettext("Replace"),
|
|
||||||
###
|
|
||||||
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
|
||||||
###
|
|
||||||
"Replace": gettext("Replace"),
|
|
||||||
###
|
|
||||||
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
|
||||||
###
|
|
||||||
"Restore last draft": gettext("Restore last draft"),
|
|
||||||
###
|
|
||||||
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
|
||||||
###
|
|
||||||
"Rich Text Area. Press ALT-F9 for menu. Press ALT-F10 for toolbar. Press ALT-0 for help": gettext("Rich Text Area. Press ALT-F9 for menu. Press ALT-F10 for toolbar. Press ALT-0 for help"),
|
|
||||||
###
|
|
||||||
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
|
||||||
###
|
|
||||||
"Right to left": gettext("Right to left"),
|
|
||||||
###
|
|
||||||
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
|
||||||
###
|
|
||||||
"Right": gettext("Right"),
|
|
||||||
###
|
|
||||||
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
|
||||||
###
|
|
||||||
"Robots": gettext("Robots"),
|
|
||||||
###
|
|
||||||
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
|
||||||
###
|
|
||||||
"Row group": gettext("Row group"),
|
|
||||||
###
|
|
||||||
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
|
||||||
###
|
|
||||||
"Row properties": gettext("Row properties"),
|
|
||||||
###
|
|
||||||
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
|
||||||
###
|
|
||||||
"Row type": gettext("Row type"),
|
|
||||||
###
|
|
||||||
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
|
||||||
###
|
|
||||||
"Row": gettext("Row"),
|
|
||||||
###
|
|
||||||
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
|
||||||
###
|
|
||||||
"Rows": gettext("Rows"),
|
|
||||||
###
|
|
||||||
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
|
||||||
###
|
|
||||||
"Save": gettext("Save"),
|
|
||||||
###
|
|
||||||
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
|
||||||
###
|
|
||||||
"Scope": gettext("Scope"),
|
|
||||||
###
|
|
||||||
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
|
||||||
###
|
|
||||||
"Select all": gettext("Select all"),
|
|
||||||
###
|
|
||||||
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
|
||||||
###
|
|
||||||
"Show blocks": gettext("Show blocks"),
|
|
||||||
###
|
|
||||||
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
|
||||||
###
|
|
||||||
"Show invisible characters": gettext("Show invisible characters"),
|
|
||||||
###
|
|
||||||
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
|
||||||
###
|
|
||||||
"Source code": gettext("Source code"),
|
|
||||||
###
|
|
||||||
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
|
||||||
###
|
|
||||||
"Source": gettext("Source"),
|
|
||||||
###
|
|
||||||
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
|
||||||
###
|
|
||||||
"Special character": gettext("Special character"),
|
|
||||||
###
|
|
||||||
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
|
||||||
###
|
|
||||||
"Spellcheck": gettext("Spellcheck"),
|
|
||||||
###
|
|
||||||
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
|
||||||
###
|
|
||||||
"Split cell": gettext("Split cell"),
|
|
||||||
###
|
|
||||||
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
|
||||||
###
|
|
||||||
"Square": gettext("Square"),
|
|
||||||
###
|
|
||||||
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
|
||||||
###
|
|
||||||
"Start search": gettext("Start search"),
|
|
||||||
###
|
|
||||||
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
|
||||||
###
|
|
||||||
"Strikethrough": gettext("Strikethrough"),
|
|
||||||
###
|
|
||||||
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
|
||||||
###
|
|
||||||
"Style": gettext("Style"),
|
|
||||||
###
|
|
||||||
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
|
||||||
###
|
|
||||||
"Subscript": gettext("Subscript"),
|
|
||||||
###
|
|
||||||
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
|
||||||
###
|
|
||||||
"Superscript": gettext("Superscript"),
|
|
||||||
###
|
|
||||||
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
|
||||||
###
|
|
||||||
"Table properties": gettext("Table properties"),
|
|
||||||
###
|
|
||||||
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
|
||||||
###
|
|
||||||
"Table": gettext("Table"),
|
|
||||||
###
|
|
||||||
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
|
||||||
###
|
|
||||||
"Target": gettext("Target"),
|
|
||||||
###
|
|
||||||
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
|
||||||
###
|
|
||||||
"Templates": gettext("Templates"),
|
|
||||||
###
|
|
||||||
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
|
||||||
###
|
|
||||||
"Text color": gettext("Text color"),
|
|
||||||
###
|
|
||||||
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
|
||||||
###
|
|
||||||
"Text to display": gettext("Text to display"),
|
|
||||||
###
|
|
||||||
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
|
||||||
###
|
|
||||||
"The URL you entered seems to be an email address. Do you want to add the required mailto: prefix?": gettext("The URL you entered seems to be an email address. Do you want to add the required mailto: prefix?"),
|
|
||||||
###
|
|
||||||
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
|
||||||
###
|
|
||||||
"The URL you entered seems to be an external link. Do you want to add the required http:// prefix?": gettext("The URL you entered seems to be an external link. Do you want to add the required http:// prefix?"),
|
|
||||||
###
|
|
||||||
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
|
||||||
###
|
|
||||||
"Title": gettext("Title"),
|
|
||||||
###
|
|
||||||
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
|
||||||
###
|
|
||||||
"Tools": gettext("Tools"),
|
|
||||||
###
|
|
||||||
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
|
||||||
###
|
|
||||||
"Top": gettext("Top"),
|
|
||||||
###
|
|
||||||
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
|
||||||
###
|
|
||||||
"Underline": gettext("Underline"),
|
|
||||||
###
|
|
||||||
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
|
||||||
###
|
|
||||||
"Undo": gettext("Undo"),
|
|
||||||
###
|
|
||||||
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
|
||||||
###
|
|
||||||
"Upper Alpha": gettext("Upper Alpha"),
|
|
||||||
###
|
|
||||||
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
|
||||||
###
|
|
||||||
"Upper Roman": gettext("Upper Roman"),
|
|
||||||
###
|
|
||||||
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
|
||||||
###
|
|
||||||
"Url": gettext("Url"),
|
|
||||||
###
|
|
||||||
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
|
||||||
###
|
|
||||||
"V Align": gettext("V Align"),
|
|
||||||
###
|
|
||||||
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
|
||||||
###
|
|
||||||
"Vertical space": gettext("Vertical space"),
|
|
||||||
###
|
|
||||||
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
|
||||||
###
|
|
||||||
"View": gettext("View"),
|
|
||||||
###
|
|
||||||
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
|
||||||
###
|
|
||||||
"Visual aids": gettext("Visual aids"),
|
|
||||||
###
|
|
||||||
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
|
||||||
###
|
|
||||||
"Whole words": gettext("Whole words"),
|
|
||||||
###
|
|
||||||
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
|
||||||
###
|
|
||||||
"Width": gettext("Width"),
|
|
||||||
###
|
|
||||||
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
|
||||||
###
|
|
||||||
"Words: {0}": gettext("Words: {0}"),
|
|
||||||
###
|
|
||||||
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
|
||||||
###
|
|
||||||
"You have unsaved changes are you sure you want to navigate away?": gettext("You have unsaved changes are you sure you want to navigate away?"),
|
|
||||||
###
|
|
||||||
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
|
||||||
###
|
|
||||||
"Your browser doesn't support direct access to the clipboard. Please use the Ctrl+X/C/V keyboard shortcuts instead.": gettext("Your browser doesn't support direct access to the clipboard. Please use the Ctrl+X/C/V keyboard shortcuts instead."),
|
|
||||||
})
|
|
||||||
|
|
||||||
setupTinyMCE: (ed) =>
|
/*
|
||||||
ed.addButton('wrapAsCode', {
|
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
||||||
###
|
*/
|
||||||
Translators: this is a toolbar button tooltip from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
"Advanced": gettext("Advanced"),
|
||||||
###
|
|
||||||
title : gettext('Code block'),
|
|
||||||
image : "#{baseUrl}/images/ico-tinymce-code.png",
|
|
||||||
onclick : () ->
|
|
||||||
ed.formatter.toggle('code')
|
|
||||||
})
|
|
||||||
|
|
||||||
ed.addButton('insertImage', {
|
/*
|
||||||
###
|
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
||||||
Translators: this is a toolbar button tooltip from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
*/
|
||||||
###
|
"Align center": gettext("Align center"),
|
||||||
title : gettext('Insert/Edit Image'),
|
|
||||||
icon: 'image',
|
|
||||||
onclick : @openImageModal
|
|
||||||
})
|
|
||||||
|
|
||||||
@visualEditor = ed
|
/*
|
||||||
@imageModal = $('#edit-image-modal .modal')
|
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
||||||
|
*/
|
||||||
|
"Align left": gettext("Align left"),
|
||||||
|
|
||||||
# These events were added to the plugin code as the TinyMCE PluginManager
|
/*
|
||||||
# does not fire any events when plugins are opened or closed.
|
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
||||||
ed.on('SaveImage', @saveImage)
|
*/
|
||||||
ed.on('EditImage', @editImage)
|
"Align right": gettext("Align right"),
|
||||||
ed.on('SaveLink', @saveLink)
|
|
||||||
ed.on('EditLink', @editLink)
|
|
||||||
ed.on('ShowCodeEditor', @showCodeEditor)
|
|
||||||
ed.on('SaveCodeEditor', @saveCodeEditor)
|
|
||||||
|
|
||||||
@imageModal.on('submitForm', @editImageSubmit)
|
/*
|
||||||
|
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
||||||
|
*/
|
||||||
|
"Alignment": gettext("Alignment"),
|
||||||
|
|
||||||
editImage: (data) =>
|
/*
|
||||||
# Called when the image plugin will be shown. Input arg is the JSON version of the image data.
|
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
||||||
if data['src']
|
*/
|
||||||
data['src'] = rewriteStaticLinks(data['src'], @base_asset_url, '/static/')
|
"Alternative source": gettext("Alternative source"),
|
||||||
|
|
||||||
saveImage: (data) =>
|
/*
|
||||||
# Called when the image plugin is saved. Input arg is the JSON version of the image data.
|
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
||||||
if data['src']
|
*/
|
||||||
data['src'] = rewriteStaticLinks(data['src'], '/static/', @base_asset_url)
|
"Anchor": gettext("Anchor"),
|
||||||
|
|
||||||
openImageModal: () =>
|
/*
|
||||||
img = $(@visualEditor.selection.getNode())
|
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
||||||
imgAttrs =
|
*/
|
||||||
baseAssetUrl: @base_asset_url
|
"Anchors": gettext("Anchors"),
|
||||||
if img && img.is('img')
|
|
||||||
imgAttrs['src'] = rewriteStaticLinks(img.attr('src'), @base_asset_url, '/static/')
|
|
||||||
imgAttrs['alt'] = img.attr('alt')
|
|
||||||
imgAttrs['width'] = parseInt(img.attr('width'), 10) || img[0].naturalWidth
|
|
||||||
imgAttrs['height'] = parseInt(img.attr('height'), 10) || img[0].naturalHeight
|
|
||||||
imgAttrs['style'] = img.attr('style')
|
|
||||||
@imageModal[0].dispatchEvent(new CustomEvent('openModal', {bubbles: true, detail: imgAttrs}))
|
|
||||||
|
|
||||||
closeImageModal: () =>
|
/*
|
||||||
@imageModal[0].dispatchEvent(new CustomEvent('closeModal', {bubbles: true}))
|
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
||||||
|
*/
|
||||||
|
"Author": gettext("Author"),
|
||||||
|
|
||||||
saveImageFromModal: (data) =>
|
/*
|
||||||
# Insert img node from studio-frontend modal form data passed as a javascript object
|
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
||||||
if data['src']
|
*/
|
||||||
data['src'] = rewriteStaticLinks(data['src'], '/static/', @base_asset_url)
|
"Background color": gettext("Background color"),
|
||||||
|
|
||||||
@visualEditor.insertContent(@visualEditor.dom.createHTML('img', data))
|
/*
|
||||||
|
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
||||||
|
*/
|
||||||
|
"Blockquote": gettext("Blockquote"),
|
||||||
|
|
||||||
editImageSubmit: (event) =>
|
/*
|
||||||
if event.detail
|
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
||||||
@saveImageFromModal(event.detail)
|
*/
|
||||||
|
"Blocks": gettext("Blocks"),
|
||||||
|
|
||||||
editLink: (data) =>
|
/*
|
||||||
# Called when the link plugin will be shown. Input arg is the JSON version of the link data.
|
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
||||||
if data['href']
|
*/
|
||||||
data['href'] = rewriteStaticLinks(data['href'], @base_asset_url, '/static/')
|
"Body": gettext("Body"),
|
||||||
|
|
||||||
saveLink: (data) =>
|
/*
|
||||||
# Called when the link plugin is saved. Input arg is the JSON version of the link data.
|
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
||||||
if data['href']
|
*/
|
||||||
data['href'] = rewriteStaticLinks(data['href'], '/static/', @base_asset_url)
|
"Bold": gettext("Bold"),
|
||||||
|
|
||||||
showCodeEditor: (source) =>
|
/*
|
||||||
# Called when the CodeMirror Editor is displayed to convert links to show static prefix.
|
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
||||||
# The input argument is a dict with the text content.
|
*/
|
||||||
content = rewriteStaticLinks(source.content, @base_asset_url, '/static/')
|
"Border color": gettext("Border color"),
|
||||||
source.content = content
|
|
||||||
|
|
||||||
saveCodeEditor: (source) =>
|
/*
|
||||||
# Called when the CodeMirror Editor is saved to convert links back to the full form.
|
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
||||||
# The input argument is a dict with the text content.
|
*/
|
||||||
content = rewriteStaticLinks(source.content, '/static/', @base_asset_url)
|
"Border": gettext("Border"),
|
||||||
source.content = content
|
|
||||||
|
|
||||||
initInstanceCallback: (visualEditor) =>
|
/*
|
||||||
visualEditor.setContent(rewriteStaticLinks(visualEditor.getContent({no_events: 1}), '/static/', @base_asset_url))
|
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
||||||
# Unfortunately, just setting visualEditor.isNortDirty = true is not enough to convince TinyMCE we
|
*/
|
||||||
# haven't dirtied the Editor. Store the raw content so we can compare it later.
|
"Bottom": gettext("Bottom"),
|
||||||
@starting_content = visualEditor.getContent({format:"raw", no_events: 1})
|
|
||||||
visualEditor.focus()
|
|
||||||
|
|
||||||
getVisualEditor: () ->
|
/*
|
||||||
###
|
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
||||||
Returns the instance of TinyMCE.
|
*/
|
||||||
|
"Bullet list": gettext("Bullet list"),
|
||||||
|
|
||||||
Pulled out as a helper method for unit test.
|
/*
|
||||||
###
|
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
||||||
return @visualEditor
|
*/
|
||||||
|
"Cancel": gettext("Cancel"),
|
||||||
|
|
||||||
save: ->
|
/*
|
||||||
text = undefined
|
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
||||||
if @editor_choice == 'visual'
|
*/
|
||||||
visualEditor = @getVisualEditor()
|
"Caption": gettext("Caption"),
|
||||||
raw_content = visualEditor.getContent({format:"raw", no_events: 1})
|
|
||||||
if @starting_content != raw_content
|
|
||||||
text = rewriteStaticLinks(visualEditor.getContent({no_events: 1}), @base_asset_url, '/static/')
|
|
||||||
|
|
||||||
if text == undefined
|
/*
|
||||||
text = @advanced_editor.getValue()
|
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
||||||
|
*/
|
||||||
|
"Cell padding": gettext("Cell padding"),
|
||||||
|
|
||||||
data: text
|
/*
|
||||||
|
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
||||||
|
*/
|
||||||
|
"Cell properties": gettext("Cell properties"),
|
||||||
|
|
||||||
|
/*
|
||||||
|
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
||||||
|
*/
|
||||||
|
"Cell spacing": gettext("Cell spacing"),
|
||||||
|
|
||||||
|
/*
|
||||||
|
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
||||||
|
*/
|
||||||
|
"Cell type": gettext("Cell type"),
|
||||||
|
|
||||||
|
/*
|
||||||
|
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
||||||
|
*/
|
||||||
|
"Cell": gettext("Cell"),
|
||||||
|
|
||||||
|
/*
|
||||||
|
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
||||||
|
*/
|
||||||
|
"Center": gettext("Center"),
|
||||||
|
|
||||||
|
/*
|
||||||
|
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
||||||
|
*/
|
||||||
|
"Circle": gettext("Circle"),
|
||||||
|
|
||||||
|
/*
|
||||||
|
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
||||||
|
*/
|
||||||
|
"Clear formatting": gettext("Clear formatting"),
|
||||||
|
|
||||||
|
/*
|
||||||
|
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
||||||
|
*/
|
||||||
|
"Close": gettext("Close"),
|
||||||
|
|
||||||
|
/*
|
||||||
|
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
||||||
|
*/
|
||||||
|
"Code block": gettext("Code block"),
|
||||||
|
|
||||||
|
/*
|
||||||
|
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
||||||
|
*/
|
||||||
|
"Code": gettext("Code"),
|
||||||
|
|
||||||
|
/*
|
||||||
|
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
||||||
|
*/
|
||||||
|
"Color": gettext("Color"),
|
||||||
|
|
||||||
|
/*
|
||||||
|
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
||||||
|
*/
|
||||||
|
"Cols": gettext("Cols"),
|
||||||
|
|
||||||
|
/*
|
||||||
|
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
||||||
|
*/
|
||||||
|
"Column group": gettext("Column group"),
|
||||||
|
|
||||||
|
/*
|
||||||
|
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
||||||
|
*/
|
||||||
|
"Column": gettext("Column"),
|
||||||
|
|
||||||
|
/*
|
||||||
|
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
||||||
|
*/
|
||||||
|
"Constrain proportions": gettext("Constrain proportions"),
|
||||||
|
|
||||||
|
/*
|
||||||
|
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
||||||
|
*/
|
||||||
|
"Copy row": gettext("Copy row"),
|
||||||
|
|
||||||
|
/*
|
||||||
|
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
||||||
|
*/
|
||||||
|
"Copy": gettext("Copy"),
|
||||||
|
|
||||||
|
/*
|
||||||
|
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
||||||
|
*/
|
||||||
|
"Could not find the specified string.": gettext("Could not find the specified string."),
|
||||||
|
|
||||||
|
/*
|
||||||
|
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
||||||
|
*/
|
||||||
|
"Custom color": gettext("Custom color"),
|
||||||
|
|
||||||
|
/*
|
||||||
|
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
||||||
|
*/
|
||||||
|
"Custom...": gettext("Custom..."),
|
||||||
|
|
||||||
|
/*
|
||||||
|
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
||||||
|
*/
|
||||||
|
"Cut row": gettext("Cut row"),
|
||||||
|
|
||||||
|
/*
|
||||||
|
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
||||||
|
*/
|
||||||
|
"Cut": gettext("Cut"),
|
||||||
|
|
||||||
|
/*
|
||||||
|
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
||||||
|
*/
|
||||||
|
"Decrease indent": gettext("Decrease indent"),
|
||||||
|
|
||||||
|
/*
|
||||||
|
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
||||||
|
*/
|
||||||
|
"Default": gettext("Default"),
|
||||||
|
|
||||||
|
/*
|
||||||
|
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
||||||
|
*/
|
||||||
|
"Delete column": gettext("Delete column"),
|
||||||
|
|
||||||
|
/*
|
||||||
|
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
||||||
|
*/
|
||||||
|
"Delete row": gettext("Delete row"),
|
||||||
|
|
||||||
|
/*
|
||||||
|
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
||||||
|
*/
|
||||||
|
"Delete table": gettext("Delete table"),
|
||||||
|
|
||||||
|
/*
|
||||||
|
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
||||||
|
*/
|
||||||
|
"Description": gettext("Description"),
|
||||||
|
|
||||||
|
/*
|
||||||
|
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
||||||
|
*/
|
||||||
|
"Dimensions": gettext("Dimensions"),
|
||||||
|
|
||||||
|
/*
|
||||||
|
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
||||||
|
*/
|
||||||
|
"Disc": gettext("Disc"),
|
||||||
|
|
||||||
|
/*
|
||||||
|
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
||||||
|
*/
|
||||||
|
"Div": gettext("Div"),
|
||||||
|
|
||||||
|
/*
|
||||||
|
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
||||||
|
*/
|
||||||
|
"Document properties": gettext("Document properties"),
|
||||||
|
|
||||||
|
/*
|
||||||
|
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
||||||
|
*/
|
||||||
|
"Edit HTML": gettext("Edit HTML"),
|
||||||
|
|
||||||
|
/*
|
||||||
|
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
||||||
|
*/
|
||||||
|
"Edit": gettext("Edit"),
|
||||||
|
|
||||||
|
/*
|
||||||
|
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
||||||
|
*/
|
||||||
|
"Embed": gettext("Embed"),
|
||||||
|
|
||||||
|
/*
|
||||||
|
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
||||||
|
*/
|
||||||
|
"Emoticons": gettext("Emoticons"),
|
||||||
|
|
||||||
|
/*
|
||||||
|
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
||||||
|
*/
|
||||||
|
"Encoding": gettext("Encoding"),
|
||||||
|
|
||||||
|
/*
|
||||||
|
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
||||||
|
*/
|
||||||
|
"File": gettext("File"),
|
||||||
|
|
||||||
|
/*
|
||||||
|
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
||||||
|
*/
|
||||||
|
"Find and replace": gettext("Find and replace"),
|
||||||
|
|
||||||
|
/*
|
||||||
|
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
||||||
|
*/
|
||||||
|
"Find next": gettext("Find next"),
|
||||||
|
|
||||||
|
/*
|
||||||
|
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
||||||
|
*/
|
||||||
|
"Find previous": gettext("Find previous"),
|
||||||
|
|
||||||
|
/*
|
||||||
|
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
||||||
|
*/
|
||||||
|
"Find": gettext("Find"),
|
||||||
|
|
||||||
|
/*
|
||||||
|
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
||||||
|
*/
|
||||||
|
"Finish": gettext("Finish"),
|
||||||
|
|
||||||
|
/*
|
||||||
|
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
||||||
|
*/
|
||||||
|
"Font Family": gettext("Font Family"),
|
||||||
|
|
||||||
|
/*
|
||||||
|
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
||||||
|
*/
|
||||||
|
"Font Sizes": gettext("Font Sizes"),
|
||||||
|
|
||||||
|
/*
|
||||||
|
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
||||||
|
*/
|
||||||
|
"Footer": gettext("Footer"),
|
||||||
|
|
||||||
|
/*
|
||||||
|
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
||||||
|
*/
|
||||||
|
"Format": gettext("Format"),
|
||||||
|
|
||||||
|
/*
|
||||||
|
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
||||||
|
*/
|
||||||
|
"Formats": gettext("Formats"),
|
||||||
|
|
||||||
|
/*
|
||||||
|
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
||||||
|
*/
|
||||||
|
"Fullscreen": gettext("Fullscreen"),
|
||||||
|
|
||||||
|
/*
|
||||||
|
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
||||||
|
*/
|
||||||
|
"General": gettext("General"),
|
||||||
|
|
||||||
|
/*
|
||||||
|
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
||||||
|
*/
|
||||||
|
"H Align": gettext("H Align"),
|
||||||
|
|
||||||
|
/*
|
||||||
|
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
||||||
|
*/
|
||||||
|
"Header 1": gettext("Header 1"),
|
||||||
|
|
||||||
|
/*
|
||||||
|
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
||||||
|
*/
|
||||||
|
"Header 2": gettext("Header 2"),
|
||||||
|
|
||||||
|
/*
|
||||||
|
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
||||||
|
*/
|
||||||
|
"Header 3": gettext("Header 3"),
|
||||||
|
|
||||||
|
/*
|
||||||
|
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
||||||
|
*/
|
||||||
|
"Header 4": gettext("Header 4"),
|
||||||
|
|
||||||
|
/*
|
||||||
|
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
||||||
|
*/
|
||||||
|
"Header 5": gettext("Header 5"),
|
||||||
|
|
||||||
|
/*
|
||||||
|
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
||||||
|
*/
|
||||||
|
"Header 6": gettext("Header 6"),
|
||||||
|
|
||||||
|
/*
|
||||||
|
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
||||||
|
*/
|
||||||
|
"Header cell": gettext("Header cell"),
|
||||||
|
|
||||||
|
/*
|
||||||
|
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
||||||
|
*/
|
||||||
|
"Header": gettext("Header"),
|
||||||
|
|
||||||
|
/*
|
||||||
|
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
||||||
|
*/
|
||||||
|
"Headers": gettext("Headers"),
|
||||||
|
|
||||||
|
/*
|
||||||
|
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
||||||
|
*/
|
||||||
|
"Heading 1": gettext("Heading 1"),
|
||||||
|
|
||||||
|
/*
|
||||||
|
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
||||||
|
*/
|
||||||
|
"Heading 2": gettext("Heading 2"),
|
||||||
|
|
||||||
|
/*
|
||||||
|
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
||||||
|
*/
|
||||||
|
"Heading 3": gettext("Heading 3"),
|
||||||
|
|
||||||
|
/*
|
||||||
|
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
||||||
|
*/
|
||||||
|
"Heading 4": gettext("Heading 4"),
|
||||||
|
|
||||||
|
/*
|
||||||
|
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
||||||
|
*/
|
||||||
|
"Heading 5": gettext("Heading 5"),
|
||||||
|
|
||||||
|
/*
|
||||||
|
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
||||||
|
*/
|
||||||
|
"Heading 6": gettext("Heading 6"),
|
||||||
|
|
||||||
|
/*
|
||||||
|
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
||||||
|
*/
|
||||||
|
"Headings": gettext("Headings"),
|
||||||
|
|
||||||
|
/*
|
||||||
|
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
||||||
|
*/
|
||||||
|
"Height": gettext("Height"),
|
||||||
|
|
||||||
|
/*
|
||||||
|
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
||||||
|
*/
|
||||||
|
"Horizontal line": gettext("Horizontal line"),
|
||||||
|
|
||||||
|
/*
|
||||||
|
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
||||||
|
*/
|
||||||
|
"Horizontal space": gettext("Horizontal space"),
|
||||||
|
|
||||||
|
/*
|
||||||
|
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
||||||
|
*/
|
||||||
|
"HTML source code": gettext("HTML source code"),
|
||||||
|
|
||||||
|
/*
|
||||||
|
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
||||||
|
*/
|
||||||
|
"Ignore all": gettext("Ignore all"),
|
||||||
|
|
||||||
|
/*
|
||||||
|
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
||||||
|
*/
|
||||||
|
"Ignore": gettext("Ignore"),
|
||||||
|
|
||||||
|
/*
|
||||||
|
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
||||||
|
*/
|
||||||
|
"Image description": gettext("Image description"),
|
||||||
|
|
||||||
|
/*
|
||||||
|
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
||||||
|
*/
|
||||||
|
"Increase indent": gettext("Increase indent"),
|
||||||
|
|
||||||
|
/*
|
||||||
|
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
||||||
|
*/
|
||||||
|
"Inline": gettext("Inline"),
|
||||||
|
|
||||||
|
/*
|
||||||
|
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
||||||
|
*/
|
||||||
|
"Insert column after": gettext("Insert column after"),
|
||||||
|
|
||||||
|
/*
|
||||||
|
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
||||||
|
*/
|
||||||
|
"Insert column before": gettext("Insert column before"),
|
||||||
|
|
||||||
|
/*
|
||||||
|
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
||||||
|
*/
|
||||||
|
"Insert date/time": gettext("Insert date/time"),
|
||||||
|
|
||||||
|
/*
|
||||||
|
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
||||||
|
*/
|
||||||
|
"Insert image": gettext("Insert image"),
|
||||||
|
|
||||||
|
/*
|
||||||
|
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
||||||
|
*/
|
||||||
|
"Insert link": gettext("Insert link"),
|
||||||
|
|
||||||
|
/*
|
||||||
|
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
||||||
|
*/
|
||||||
|
"Insert row after": gettext("Insert row after"),
|
||||||
|
|
||||||
|
/*
|
||||||
|
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
||||||
|
*/
|
||||||
|
"Insert row before": gettext("Insert row before"),
|
||||||
|
|
||||||
|
/*
|
||||||
|
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
||||||
|
*/
|
||||||
|
"Insert table": gettext("Insert table"),
|
||||||
|
|
||||||
|
/*
|
||||||
|
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
||||||
|
*/
|
||||||
|
"Insert template": gettext("Insert template"),
|
||||||
|
|
||||||
|
/*
|
||||||
|
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
||||||
|
*/
|
||||||
|
"Insert video": gettext("Insert video"),
|
||||||
|
|
||||||
|
/*
|
||||||
|
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
||||||
|
*/
|
||||||
|
"Insert": gettext("Insert"),
|
||||||
|
|
||||||
|
/*
|
||||||
|
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
||||||
|
*/
|
||||||
|
"Insert/edit image": gettext("Insert/edit image"),
|
||||||
|
|
||||||
|
/*
|
||||||
|
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
||||||
|
*/
|
||||||
|
"Insert/edit link": gettext("Insert/edit link"),
|
||||||
|
|
||||||
|
/*
|
||||||
|
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
||||||
|
*/
|
||||||
|
"Insert/edit video": gettext("Insert/edit video"),
|
||||||
|
|
||||||
|
/*
|
||||||
|
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
||||||
|
*/
|
||||||
|
"Italic": gettext("Italic"),
|
||||||
|
|
||||||
|
/*
|
||||||
|
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
||||||
|
*/
|
||||||
|
"Justify": gettext("Justify"),
|
||||||
|
|
||||||
|
/*
|
||||||
|
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
||||||
|
*/
|
||||||
|
"Keywords": gettext("Keywords"),
|
||||||
|
|
||||||
|
/*
|
||||||
|
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
||||||
|
*/
|
||||||
|
"Left to right": gettext("Left to right"),
|
||||||
|
|
||||||
|
/*
|
||||||
|
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
||||||
|
*/
|
||||||
|
"Left": gettext("Left"),
|
||||||
|
|
||||||
|
/*
|
||||||
|
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
||||||
|
*/
|
||||||
|
"Lower Alpha": gettext("Lower Alpha"),
|
||||||
|
|
||||||
|
/*
|
||||||
|
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
||||||
|
*/
|
||||||
|
"Lower Greek": gettext("Lower Greek"),
|
||||||
|
|
||||||
|
/*
|
||||||
|
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
||||||
|
*/
|
||||||
|
"Lower Roman": gettext("Lower Roman"),
|
||||||
|
|
||||||
|
/*
|
||||||
|
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
||||||
|
*/
|
||||||
|
"Match case": gettext("Match case"),
|
||||||
|
|
||||||
|
/*
|
||||||
|
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
||||||
|
*/
|
||||||
|
"Merge cells": gettext("Merge cells"),
|
||||||
|
|
||||||
|
/*
|
||||||
|
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
||||||
|
*/
|
||||||
|
"Middle": gettext("Middle"),
|
||||||
|
|
||||||
|
/*
|
||||||
|
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
||||||
|
*/
|
||||||
|
"Name": gettext("Name"),
|
||||||
|
|
||||||
|
/*
|
||||||
|
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
||||||
|
*/
|
||||||
|
"New document": gettext("New document"),
|
||||||
|
|
||||||
|
/*
|
||||||
|
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
||||||
|
*/
|
||||||
|
"New window": gettext("New window"),
|
||||||
|
|
||||||
|
/*
|
||||||
|
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
||||||
|
*/
|
||||||
|
"Next": gettext("Next"),
|
||||||
|
|
||||||
|
/*
|
||||||
|
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
||||||
|
*/
|
||||||
|
"No color": gettext("No color"),
|
||||||
|
|
||||||
|
/*
|
||||||
|
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
||||||
|
*/
|
||||||
|
"Nonbreaking space": gettext("Nonbreaking space"),
|
||||||
|
|
||||||
|
/*
|
||||||
|
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
||||||
|
*/
|
||||||
|
"None": gettext("None"),
|
||||||
|
|
||||||
|
/*
|
||||||
|
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
||||||
|
*/
|
||||||
|
"Numbered list": gettext("Numbered list"),
|
||||||
|
|
||||||
|
/*
|
||||||
|
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
||||||
|
*/
|
||||||
|
"Ok": gettext("Ok"),
|
||||||
|
|
||||||
|
/*
|
||||||
|
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
||||||
|
*/
|
||||||
|
"OK": gettext("OK"),
|
||||||
|
|
||||||
|
/*
|
||||||
|
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
||||||
|
*/
|
||||||
|
"Page break": gettext("Page break"),
|
||||||
|
|
||||||
|
/*
|
||||||
|
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
||||||
|
*/
|
||||||
|
"Paragraph": gettext("Paragraph"),
|
||||||
|
|
||||||
|
/*
|
||||||
|
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
||||||
|
*/
|
||||||
|
"Paste as text": gettext("Paste as text"),
|
||||||
|
|
||||||
|
/*
|
||||||
|
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
||||||
|
*/
|
||||||
|
"Paste is now in plain text mode. Contents will now be pasted as plain text until you toggle this option off.": gettext("Paste is now in plain text mode. Contents will now be pasted as plain text until you toggle this option off."),
|
||||||
|
|
||||||
|
/*
|
||||||
|
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
||||||
|
*/
|
||||||
|
"Paste row after": gettext("Paste row after"),
|
||||||
|
|
||||||
|
/*
|
||||||
|
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
||||||
|
*/
|
||||||
|
"Paste row before": gettext("Paste row before"),
|
||||||
|
|
||||||
|
/*
|
||||||
|
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
||||||
|
*/
|
||||||
|
"Paste your embed code below:": gettext("Paste your embed code below:"),
|
||||||
|
|
||||||
|
/*
|
||||||
|
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
||||||
|
*/
|
||||||
|
"Paste": gettext("Paste"),
|
||||||
|
|
||||||
|
/*
|
||||||
|
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
||||||
|
*/
|
||||||
|
"Poster": gettext("Poster"),
|
||||||
|
|
||||||
|
/*
|
||||||
|
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
||||||
|
*/
|
||||||
|
"Pre": gettext("Pre"),
|
||||||
|
|
||||||
|
/*
|
||||||
|
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
||||||
|
*/
|
||||||
|
"Prev": gettext("Prev"),
|
||||||
|
|
||||||
|
/*
|
||||||
|
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
||||||
|
*/
|
||||||
|
"Preview": gettext("Preview"),
|
||||||
|
|
||||||
|
/*
|
||||||
|
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
||||||
|
*/
|
||||||
|
"Print": gettext("Print"),
|
||||||
|
|
||||||
|
/*
|
||||||
|
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
||||||
|
*/
|
||||||
|
"Redo": gettext("Redo"),
|
||||||
|
|
||||||
|
/*
|
||||||
|
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
||||||
|
*/
|
||||||
|
"Remove link": gettext("Remove link"),
|
||||||
|
|
||||||
|
/*
|
||||||
|
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
||||||
|
*/
|
||||||
|
"Replace all": gettext("Replace all"),
|
||||||
|
|
||||||
|
/*
|
||||||
|
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
||||||
|
*/
|
||||||
|
"Replace all": gettext("Replace all"),
|
||||||
|
|
||||||
|
/*
|
||||||
|
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
||||||
|
*/
|
||||||
|
"Replace with": gettext("Replace with"),
|
||||||
|
|
||||||
|
/*
|
||||||
|
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
||||||
|
*/
|
||||||
|
"Replace": gettext("Replace"),
|
||||||
|
|
||||||
|
/*
|
||||||
|
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
||||||
|
*/
|
||||||
|
"Replace": gettext("Replace"),
|
||||||
|
|
||||||
|
/*
|
||||||
|
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
||||||
|
*/
|
||||||
|
"Restore last draft": gettext("Restore last draft"),
|
||||||
|
|
||||||
|
/*
|
||||||
|
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
||||||
|
*/
|
||||||
|
"Rich Text Area. Press ALT-F9 for menu. Press ALT-F10 for toolbar. Press ALT-0 for help": gettext("Rich Text Area. Press ALT-F9 for menu. Press ALT-F10 for toolbar. Press ALT-0 for help"),
|
||||||
|
|
||||||
|
/*
|
||||||
|
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
||||||
|
*/
|
||||||
|
"Right to left": gettext("Right to left"),
|
||||||
|
|
||||||
|
/*
|
||||||
|
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
||||||
|
*/
|
||||||
|
"Right": gettext("Right"),
|
||||||
|
|
||||||
|
/*
|
||||||
|
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
||||||
|
*/
|
||||||
|
"Robots": gettext("Robots"),
|
||||||
|
|
||||||
|
/*
|
||||||
|
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
||||||
|
*/
|
||||||
|
"Row group": gettext("Row group"),
|
||||||
|
|
||||||
|
/*
|
||||||
|
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
||||||
|
*/
|
||||||
|
"Row properties": gettext("Row properties"),
|
||||||
|
|
||||||
|
/*
|
||||||
|
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
||||||
|
*/
|
||||||
|
"Row type": gettext("Row type"),
|
||||||
|
|
||||||
|
/*
|
||||||
|
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
||||||
|
*/
|
||||||
|
"Row": gettext("Row"),
|
||||||
|
|
||||||
|
/*
|
||||||
|
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
||||||
|
*/
|
||||||
|
"Rows": gettext("Rows"),
|
||||||
|
|
||||||
|
/*
|
||||||
|
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
||||||
|
*/
|
||||||
|
"Save": gettext("Save"),
|
||||||
|
|
||||||
|
/*
|
||||||
|
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
||||||
|
*/
|
||||||
|
"Scope": gettext("Scope"),
|
||||||
|
|
||||||
|
/*
|
||||||
|
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
||||||
|
*/
|
||||||
|
"Select all": gettext("Select all"),
|
||||||
|
|
||||||
|
/*
|
||||||
|
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
||||||
|
*/
|
||||||
|
"Show blocks": gettext("Show blocks"),
|
||||||
|
|
||||||
|
/*
|
||||||
|
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
||||||
|
*/
|
||||||
|
"Show invisible characters": gettext("Show invisible characters"),
|
||||||
|
|
||||||
|
/*
|
||||||
|
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
||||||
|
*/
|
||||||
|
"Source code": gettext("Source code"),
|
||||||
|
|
||||||
|
/*
|
||||||
|
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
||||||
|
*/
|
||||||
|
"Source": gettext("Source"),
|
||||||
|
|
||||||
|
/*
|
||||||
|
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
||||||
|
*/
|
||||||
|
"Special character": gettext("Special character"),
|
||||||
|
|
||||||
|
/*
|
||||||
|
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
||||||
|
*/
|
||||||
|
"Spellcheck": gettext("Spellcheck"),
|
||||||
|
|
||||||
|
/*
|
||||||
|
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
||||||
|
*/
|
||||||
|
"Split cell": gettext("Split cell"),
|
||||||
|
|
||||||
|
/*
|
||||||
|
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
||||||
|
*/
|
||||||
|
"Square": gettext("Square"),
|
||||||
|
|
||||||
|
/*
|
||||||
|
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
||||||
|
*/
|
||||||
|
"Start search": gettext("Start search"),
|
||||||
|
|
||||||
|
/*
|
||||||
|
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
||||||
|
*/
|
||||||
|
"Strikethrough": gettext("Strikethrough"),
|
||||||
|
|
||||||
|
/*
|
||||||
|
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
||||||
|
*/
|
||||||
|
"Style": gettext("Style"),
|
||||||
|
|
||||||
|
/*
|
||||||
|
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
||||||
|
*/
|
||||||
|
"Subscript": gettext("Subscript"),
|
||||||
|
|
||||||
|
/*
|
||||||
|
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
||||||
|
*/
|
||||||
|
"Superscript": gettext("Superscript"),
|
||||||
|
|
||||||
|
/*
|
||||||
|
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
||||||
|
*/
|
||||||
|
"Table properties": gettext("Table properties"),
|
||||||
|
|
||||||
|
/*
|
||||||
|
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
||||||
|
*/
|
||||||
|
"Table": gettext("Table"),
|
||||||
|
|
||||||
|
/*
|
||||||
|
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
||||||
|
*/
|
||||||
|
"Target": gettext("Target"),
|
||||||
|
|
||||||
|
/*
|
||||||
|
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
||||||
|
*/
|
||||||
|
"Templates": gettext("Templates"),
|
||||||
|
|
||||||
|
/*
|
||||||
|
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
||||||
|
*/
|
||||||
|
"Text color": gettext("Text color"),
|
||||||
|
|
||||||
|
/*
|
||||||
|
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
||||||
|
*/
|
||||||
|
"Text to display": gettext("Text to display"),
|
||||||
|
|
||||||
|
/*
|
||||||
|
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
||||||
|
*/
|
||||||
|
"The URL you entered seems to be an email address. Do you want to add the required mailto: prefix?": gettext("The URL you entered seems to be an email address. Do you want to add the required mailto: prefix?"),
|
||||||
|
|
||||||
|
/*
|
||||||
|
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
||||||
|
*/
|
||||||
|
"The URL you entered seems to be an external link. Do you want to add the required http:// prefix?": gettext("The URL you entered seems to be an external link. Do you want to add the required http:// prefix?"),
|
||||||
|
|
||||||
|
/*
|
||||||
|
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
||||||
|
*/
|
||||||
|
"Title": gettext("Title"),
|
||||||
|
|
||||||
|
/*
|
||||||
|
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
||||||
|
*/
|
||||||
|
"Tools": gettext("Tools"),
|
||||||
|
|
||||||
|
/*
|
||||||
|
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
||||||
|
*/
|
||||||
|
"Top": gettext("Top"),
|
||||||
|
|
||||||
|
/*
|
||||||
|
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
||||||
|
*/
|
||||||
|
"Underline": gettext("Underline"),
|
||||||
|
|
||||||
|
/*
|
||||||
|
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
||||||
|
*/
|
||||||
|
"Undo": gettext("Undo"),
|
||||||
|
|
||||||
|
/*
|
||||||
|
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
||||||
|
*/
|
||||||
|
"Upper Alpha": gettext("Upper Alpha"),
|
||||||
|
|
||||||
|
/*
|
||||||
|
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
||||||
|
*/
|
||||||
|
"Upper Roman": gettext("Upper Roman"),
|
||||||
|
|
||||||
|
/*
|
||||||
|
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
||||||
|
*/
|
||||||
|
"Url": gettext("Url"),
|
||||||
|
|
||||||
|
/*
|
||||||
|
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
||||||
|
*/
|
||||||
|
"V Align": gettext("V Align"),
|
||||||
|
|
||||||
|
/*
|
||||||
|
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
||||||
|
*/
|
||||||
|
"Vertical space": gettext("Vertical space"),
|
||||||
|
|
||||||
|
/*
|
||||||
|
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
||||||
|
*/
|
||||||
|
"View": gettext("View"),
|
||||||
|
|
||||||
|
/*
|
||||||
|
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
||||||
|
*/
|
||||||
|
"Visual aids": gettext("Visual aids"),
|
||||||
|
|
||||||
|
/*
|
||||||
|
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
||||||
|
*/
|
||||||
|
"Whole words": gettext("Whole words"),
|
||||||
|
|
||||||
|
/*
|
||||||
|
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
||||||
|
*/
|
||||||
|
"Width": gettext("Width"),
|
||||||
|
|
||||||
|
/*
|
||||||
|
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
||||||
|
*/
|
||||||
|
"Words: {0}": gettext("Words: {0}"),
|
||||||
|
|
||||||
|
/*
|
||||||
|
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
||||||
|
*/
|
||||||
|
"You have unsaved changes are you sure you want to navigate away?": gettext("You have unsaved changes are you sure you want to navigate away?"),
|
||||||
|
|
||||||
|
/*
|
||||||
|
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
||||||
|
*/
|
||||||
|
"Your browser doesn't support direct access to the clipboard. Please use the Ctrl+X/C/V keyboard shortcuts instead.": gettext("Your browser doesn't support direct access to the clipboard. Please use the Ctrl+X/C/V keyboard shortcuts instead.")
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
HTMLEditingDescriptor.prototype.setupTinyMCE = function(ed) {
|
||||||
|
ed.addButton('wrapAsCode', {
|
||||||
|
|
||||||
|
/*
|
||||||
|
Translators: this is a toolbar button tooltip from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
||||||
|
*/
|
||||||
|
title: gettext('Code block'),
|
||||||
|
image: baseUrl + "/images/ico-tinymce-code.png",
|
||||||
|
onclick: function() {
|
||||||
|
return ed.formatter.toggle('code');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
ed.addButton('insertImage', {
|
||||||
|
|
||||||
|
/*
|
||||||
|
Translators: this is a toolbar button tooltip from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
||||||
|
*/
|
||||||
|
title: gettext('Insert/Edit Image'),
|
||||||
|
icon: 'image',
|
||||||
|
onclick: this.openImageModal
|
||||||
|
});
|
||||||
|
this.visualEditor = ed;
|
||||||
|
this.imageModal = $('#edit-image-modal .modal');
|
||||||
|
|
||||||
|
/*
|
||||||
|
These events were added to the plugin code as the TinyMCE PluginManager
|
||||||
|
does not fire any events when plugins are opened or closed.
|
||||||
|
*/
|
||||||
|
ed.on('SaveImage', this.saveImage);
|
||||||
|
ed.on('EditImage', this.editImage);
|
||||||
|
ed.on('SaveLink', this.saveLink);
|
||||||
|
ed.on('EditLink', this.editLink);
|
||||||
|
ed.on('ShowCodeEditor', this.showCodeEditor);
|
||||||
|
ed.on('SaveCodeEditor', this.saveCodeEditor);
|
||||||
|
return this.imageModal.on('submitForm', this.editImageSubmit);
|
||||||
|
};
|
||||||
|
|
||||||
|
HTMLEditingDescriptor.prototype.editImage = function(data) {
|
||||||
|
|
||||||
|
/*
|
||||||
|
Called when the image plugin will be shown. Input arg is the JSON version of the image data.
|
||||||
|
*/
|
||||||
|
if (data['src']) {
|
||||||
|
return data['src'] = rewriteStaticLinks(data['src'], this.base_asset_url, '/static/');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
HTMLEditingDescriptor.prototype.saveImage = function(data) {
|
||||||
|
|
||||||
|
/*
|
||||||
|
Called when the image plugin is saved. Input arg is the JSON version of the image data.
|
||||||
|
*/
|
||||||
|
if (data['src']) {
|
||||||
|
return data['src'] = rewriteStaticLinks(data['src'], '/static/', this.base_asset_url);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
HTMLEditingDescriptor.prototype.openImageModal = function() {
|
||||||
|
var img, imgAttrs;
|
||||||
|
img = $(this.visualEditor.selection.getNode());
|
||||||
|
imgAttrs = {
|
||||||
|
baseAssetUrl: this.base_asset_url
|
||||||
|
};
|
||||||
|
if (img && img.is('img')) {
|
||||||
|
imgAttrs['src'] = rewriteStaticLinks(img.attr('src'), this.base_asset_url, '/static/');
|
||||||
|
imgAttrs['alt'] = img.attr('alt');
|
||||||
|
imgAttrs['width'] = parseInt(img.attr('width'), 10) || img[0].naturalWidth;
|
||||||
|
imgAttrs['height'] = parseInt(img.attr('height'), 10) || img[0].naturalHeight;
|
||||||
|
imgAttrs['style'] = img.attr('style');
|
||||||
|
}
|
||||||
|
return this.imageModal[0].dispatchEvent(new CustomEvent('openModal', {
|
||||||
|
bubbles: true,
|
||||||
|
detail: imgAttrs
|
||||||
|
}));
|
||||||
|
};
|
||||||
|
|
||||||
|
HTMLEditingDescriptor.prototype.closeImageModal = function() {
|
||||||
|
return this.imageModal[0].dispatchEvent(new CustomEvent('closeModal', {
|
||||||
|
bubbles: true
|
||||||
|
}));
|
||||||
|
};
|
||||||
|
|
||||||
|
HTMLEditingDescriptor.prototype.saveImageFromModal = function(data) {
|
||||||
|
|
||||||
|
/*
|
||||||
|
Insert img node from studio-frontend modal form data passed as a javascript object
|
||||||
|
*/
|
||||||
|
if (data['src']) {
|
||||||
|
data['src'] = rewriteStaticLinks(data['src'], '/static/', this.base_asset_url);
|
||||||
|
}
|
||||||
|
return this.visualEditor.insertContent(this.visualEditor.dom.createHTML('img', data));
|
||||||
|
};
|
||||||
|
|
||||||
|
HTMLEditingDescriptor.prototype.editImageSubmit = function(event) {
|
||||||
|
if (event.detail) {
|
||||||
|
return this.saveImageFromModal(event.detail);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
HTMLEditingDescriptor.prototype.editLink = function(data) {
|
||||||
|
|
||||||
|
/*
|
||||||
|
Called when the link plugin will be shown. Input arg is the JSON version of the link data.
|
||||||
|
*/
|
||||||
|
if (data['href']) {
|
||||||
|
return data['href'] = rewriteStaticLinks(data['href'], this.base_asset_url, '/static/');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
HTMLEditingDescriptor.prototype.saveLink = function(data) {
|
||||||
|
|
||||||
|
/*
|
||||||
|
Called when the link plugin is saved. Input arg is the JSON version of the link data.
|
||||||
|
*/
|
||||||
|
if (data['href']) {
|
||||||
|
return data['href'] = rewriteStaticLinks(data['href'], '/static/', this.base_asset_url);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
HTMLEditingDescriptor.prototype.showCodeEditor = function(source) {
|
||||||
|
|
||||||
|
/*
|
||||||
|
Called when the CodeMirror Editor is displayed to convert links to show static prefix.
|
||||||
|
The input argument is a dict with the text content.
|
||||||
|
*/
|
||||||
|
var content;
|
||||||
|
content = rewriteStaticLinks(source.content, this.base_asset_url, '/static/');
|
||||||
|
return source.content = content;
|
||||||
|
};
|
||||||
|
|
||||||
|
HTMLEditingDescriptor.prototype.saveCodeEditor = function(source) {
|
||||||
|
|
||||||
|
/*
|
||||||
|
Called when the CodeMirror Editor is saved to convert links back to the full form.
|
||||||
|
The input argument is a dict with the text content.
|
||||||
|
*/
|
||||||
|
var content;
|
||||||
|
content = rewriteStaticLinks(source.content, '/static/', this.base_asset_url);
|
||||||
|
return source.content = content;
|
||||||
|
};
|
||||||
|
|
||||||
|
HTMLEditingDescriptor.prototype.initInstanceCallback = function(visualEditor) {
|
||||||
|
visualEditor.setContent(rewriteStaticLinks(visualEditor.getContent({
|
||||||
|
no_events: 1
|
||||||
|
}), '/static/', this.base_asset_url));
|
||||||
|
|
||||||
|
/*
|
||||||
|
Unfortunately, just setting visualEditor.isNortDirty = true is not enough to convince TinyMCE we
|
||||||
|
haven't dirtied the Editor. Store the raw content so we can compare it later.
|
||||||
|
*/
|
||||||
|
this.starting_content = visualEditor.getContent({
|
||||||
|
format: "raw",
|
||||||
|
no_events: 1
|
||||||
|
});
|
||||||
|
return visualEditor.focus();
|
||||||
|
};
|
||||||
|
|
||||||
|
HTMLEditingDescriptor.prototype.getVisualEditor = function() {
|
||||||
|
/*
|
||||||
|
Returns the instance of TinyMCE.
|
||||||
|
Pulled out as a helper method for unit test.
|
||||||
|
*/
|
||||||
|
return this.visualEditor;
|
||||||
|
};
|
||||||
|
|
||||||
|
HTMLEditingDescriptor.prototype.save = function() {
|
||||||
|
var raw_content, text, visualEditor;
|
||||||
|
text = void 0;
|
||||||
|
if (this.editor_choice === 'visual') {
|
||||||
|
visualEditor = this.getVisualEditor();
|
||||||
|
raw_content = visualEditor.getContent({
|
||||||
|
format: "raw",
|
||||||
|
no_events: 1
|
||||||
|
});
|
||||||
|
if (this.starting_content !== raw_content) {
|
||||||
|
text = rewriteStaticLinks(visualEditor.getContent({
|
||||||
|
no_events: 1
|
||||||
|
}), this.base_asset_url, '/static/');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (text === void 0) {
|
||||||
|
text = this.advanced_editor.getValue();
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
data: text
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
return HTMLEditingDescriptor;
|
||||||
|
|
||||||
|
})();
|
||||||
|
|
||||||
|
}).call(this);
|
||||||
|
|||||||
@@ -1,10 +1,32 @@
|
|||||||
class @JSONEditingDescriptor extends XModule.Descriptor
|
// Once generated by CoffeeScript 1.9.3, but now lives as pure JS
|
||||||
constructor: (@element) ->
|
/* eslint-disable */
|
||||||
@edit_box = CodeMirror.fromTextArea($(".edit-box", @element)[0], {
|
(function() {
|
||||||
mode: { name: "javascript", json: true }
|
var extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
|
||||||
lineNumbers: true
|
hasProp = {}.hasOwnProperty;
|
||||||
lineWrapping: true
|
|
||||||
})
|
|
||||||
|
|
||||||
save: ->
|
this.JSONEditingDescriptor = (function(superClass) {
|
||||||
data: JSON.parse @edit_box.getValue()
|
extend(JSONEditingDescriptor, superClass);
|
||||||
|
|
||||||
|
function JSONEditingDescriptor(element) {
|
||||||
|
this.element = element;
|
||||||
|
this.edit_box = CodeMirror.fromTextArea($(".edit-box", this.element)[0], {
|
||||||
|
mode: {
|
||||||
|
name: "javascript",
|
||||||
|
json: true
|
||||||
|
},
|
||||||
|
lineNumbers: true,
|
||||||
|
lineWrapping: true
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
JSONEditingDescriptor.prototype.save = function() {
|
||||||
|
return {
|
||||||
|
data: JSON.parse(this.edit_box.getValue())
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
return JSONEditingDescriptor;
|
||||||
|
|
||||||
|
})(XModule.Descriptor);
|
||||||
|
|
||||||
|
}).call(this);
|
||||||
|
|||||||
@@ -1,5 +1,24 @@
|
|||||||
class @MetadataOnlyEditingDescriptor extends XModule.Descriptor
|
// Once generated by CoffeeScript 1.9.3, but now lives as pure JS
|
||||||
constructor: (@element) ->
|
/* eslint-disable */
|
||||||
|
(function() {
|
||||||
|
var extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
|
||||||
|
hasProp = {}.hasOwnProperty;
|
||||||
|
|
||||||
save: ->
|
this.MetadataOnlyEditingDescriptor = (function(superClass) {
|
||||||
data: null
|
extend(MetadataOnlyEditingDescriptor, superClass);
|
||||||
|
|
||||||
|
function MetadataOnlyEditingDescriptor(element) {
|
||||||
|
this.element = element;
|
||||||
|
}
|
||||||
|
|
||||||
|
MetadataOnlyEditingDescriptor.prototype.save = function() {
|
||||||
|
return {
|
||||||
|
data: null
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
return MetadataOnlyEditingDescriptor;
|
||||||
|
|
||||||
|
})(XModule.Descriptor);
|
||||||
|
|
||||||
|
}).call(this);
|
||||||
|
|||||||
@@ -1,10 +1,29 @@
|
|||||||
class @XMLEditingDescriptor extends XModule.Descriptor
|
// Once generated by CoffeeScript 1.9.3, but now lives as pure JS
|
||||||
constructor: (@element) ->
|
/* eslint-disable */
|
||||||
@edit_box = CodeMirror.fromTextArea($(".edit-box", @element)[0], {
|
(function() {
|
||||||
mode: "xml"
|
var extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
|
||||||
lineNumbers: true
|
hasProp = {}.hasOwnProperty;
|
||||||
lineWrapping: true
|
|
||||||
})
|
|
||||||
|
|
||||||
save: ->
|
this.XMLEditingDescriptor = (function(superClass) {
|
||||||
data: @edit_box.getValue()
|
extend(XMLEditingDescriptor, superClass);
|
||||||
|
|
||||||
|
function XMLEditingDescriptor(element) {
|
||||||
|
this.element = element;
|
||||||
|
this.edit_box = CodeMirror.fromTextArea($(".edit-box", this.element)[0], {
|
||||||
|
mode: "xml",
|
||||||
|
lineNumbers: true,
|
||||||
|
lineWrapping: true
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
XMLEditingDescriptor.prototype.save = function() {
|
||||||
|
return {
|
||||||
|
data: this.edit_box.getValue()
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
return XMLEditingDescriptor;
|
||||||
|
|
||||||
|
})(XModule.Descriptor);
|
||||||
|
|
||||||
|
}).call(this);
|
||||||
|
|||||||
@@ -1,2 +1,18 @@
|
|||||||
class @SequenceDescriptor extends XModule.Descriptor
|
// Once generated by CoffeeScript 1.9.3, but now lives as pure JS
|
||||||
|
/* eslint-disable */
|
||||||
|
(function() {
|
||||||
|
var extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
|
||||||
|
hasProp = {}.hasOwnProperty;
|
||||||
|
|
||||||
|
this.SequenceDescriptor = (function(superClass) {
|
||||||
|
extend(SequenceDescriptor, superClass);
|
||||||
|
|
||||||
|
function SequenceDescriptor() {
|
||||||
|
return SequenceDescriptor.__super__.constructor.apply(this, arguments);
|
||||||
|
}
|
||||||
|
|
||||||
|
return SequenceDescriptor;
|
||||||
|
|
||||||
|
})(XModule.Descriptor);
|
||||||
|
|
||||||
|
}).call(this);
|
||||||
|
|||||||
@@ -1,142 +1,190 @@
|
|||||||
class @TabsEditingDescriptor
|
// Once generated by CoffeeScript 1.9.3, but now lives as pure JS
|
||||||
@isInactiveClass : "is-inactive"
|
/* eslint-disable */
|
||||||
|
(function() {
|
||||||
|
var bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; };
|
||||||
|
|
||||||
constructor: (element) ->
|
this.TabsEditingDescriptor = (function() {
|
||||||
@element = element;
|
TabsEditingDescriptor.isInactiveClass = "is-inactive";
|
||||||
###
|
|
||||||
Not tested on syncing of multiple editors of same type in tabs
|
|
||||||
(Like many CodeMirrors).
|
|
||||||
###
|
|
||||||
|
|
||||||
@$tabs = $(".tab", @element)
|
function TabsEditingDescriptor(element) {
|
||||||
@$content = $(".component-tab", @element)
|
this.onSwitchEditor = bind(this.onSwitchEditor, this);
|
||||||
|
var currentTab;
|
||||||
|
this.element = element;
|
||||||
|
|
||||||
@element.find('.editor-tabs .tab').each (index, value) =>
|
/*
|
||||||
$(value).on('click', @onSwitchEditor)
|
Not tested on syncing of multiple editors of same type in tabs
|
||||||
|
(Like many CodeMirrors).
|
||||||
|
*/
|
||||||
|
this.$tabs = $(".tab", this.element);
|
||||||
|
this.$content = $(".component-tab", this.element);
|
||||||
|
this.element.find('.editor-tabs .tab').each((function(_this) {
|
||||||
|
return function(index, value) {
|
||||||
|
return $(value).on('click', _this.onSwitchEditor);
|
||||||
|
};
|
||||||
|
})(this));
|
||||||
|
|
||||||
# If default visible tab is not setted or if were marked as current
|
/*
|
||||||
# more than 1 tab just first tab will be shown
|
If default visible tab is not setted or if were marked as current
|
||||||
currentTab = @$tabs.filter('.current')
|
more than 1 tab just first tab will be shown
|
||||||
currentTab = @$tabs.first() if currentTab.length isnt 1
|
*/
|
||||||
@html_id = @$tabs.closest('.wrapper-comp-editor').data('html_id')
|
currentTab = this.$tabs.filter('.current');
|
||||||
currentTab.trigger("click", [true, @html_id])
|
if (currentTab.length !== 1) {
|
||||||
|
currentTab = this.$tabs.first();
|
||||||
|
}
|
||||||
|
this.html_id = this.$tabs.closest('.wrapper-comp-editor').data('html_id');
|
||||||
|
currentTab.trigger("click", [true, this.html_id]);
|
||||||
|
}
|
||||||
|
|
||||||
onSwitchEditor: (e, firstTime, html_id) =>
|
TabsEditingDescriptor.prototype.onSwitchEditor = function(e, firstTime, html_id) {
|
||||||
e.preventDefault()
|
var $currentTarget, content_id, isInactiveClass, onSwitchFunction, previousTab;
|
||||||
|
e.preventDefault();
|
||||||
|
isInactiveClass = TabsEditingDescriptor.isInactiveClass;
|
||||||
|
$currentTarget = $(e.currentTarget);
|
||||||
|
if (!$currentTarget.hasClass('current') || firstTime === true) {
|
||||||
|
previousTab = null;
|
||||||
|
this.$tabs.each(function(index, value) {
|
||||||
|
if ($(value).hasClass('current')) {
|
||||||
|
return previousTab = $(value).data('tab_name');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
isInactiveClass = TabsEditingDescriptor.isInactiveClass
|
/*
|
||||||
$currentTarget = $(e.currentTarget)
|
init and save data from previous tab
|
||||||
|
*/
|
||||||
|
TabsEditingDescriptor.Model.updateValue(this.html_id, previousTab);
|
||||||
|
|
||||||
if not $currentTarget.hasClass('current') or firstTime is true
|
/*
|
||||||
previousTab = null
|
Save data from editor in previous tab to editor in current tab here.
|
||||||
|
(to be implemented when there is a use case for this functionality)
|
||||||
|
*/
|
||||||
|
|
||||||
@$tabs.each( (index, value) ->
|
// call onswitch
|
||||||
if $(value).hasClass('current')
|
onSwitchFunction = TabsEditingDescriptor.Model.modules[this.html_id].tabSwitch[$currentTarget.data('tab_name')];
|
||||||
previousTab = $(value).data('tab_name')
|
if ($.isFunction(onSwitchFunction)) {
|
||||||
)
|
onSwitchFunction();
|
||||||
|
}
|
||||||
|
this.$tabs.removeClass('current');
|
||||||
|
$currentTarget.addClass('current');
|
||||||
|
|
||||||
# init and save data from previous tab
|
/*
|
||||||
TabsEditingDescriptor.Model.updateValue(@html_id, previousTab)
|
Tabs are implemeted like anchors. Therefore we can use hash to find
|
||||||
|
corresponding content
|
||||||
|
*/
|
||||||
|
content_id = $currentTarget.attr('href');
|
||||||
|
return this.$content.addClass(isInactiveClass).filter(content_id).removeClass(isInactiveClass);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
# Save data from editor in previous tab to editor in current tab here.
|
TabsEditingDescriptor.prototype.save = function() {
|
||||||
# (to be implemented when there is a use case for this functionality)
|
var current_tab;
|
||||||
|
this.element.off('click', '.editor-tabs .tab', this.onSwitchEditor);
|
||||||
|
current_tab = this.$tabs.filter('.current').data('tab_name');
|
||||||
|
return {
|
||||||
|
data: TabsEditingDescriptor.Model.getValue(this.html_id, current_tab)
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
# call onswitch
|
TabsEditingDescriptor.prototype.setMetadataEditor = function(metadataEditor) {
|
||||||
onSwitchFunction = TabsEditingDescriptor.Model.modules[@html_id].tabSwitch[$currentTarget.data('tab_name')]
|
return TabsEditingDescriptor.setMetadataEditor.apply(TabsEditingDescriptor, arguments);
|
||||||
onSwitchFunction() if $.isFunction(onSwitchFunction)
|
};
|
||||||
|
|
||||||
@$tabs.removeClass('current')
|
TabsEditingDescriptor.prototype.getStorage = function() {
|
||||||
$currentTarget.addClass('current')
|
return TabsEditingDescriptor.getStorage();
|
||||||
|
};
|
||||||
|
|
||||||
# Tabs are implemeted like anchors. Therefore we can use hash to find
|
TabsEditingDescriptor.prototype.addToStorage = function(id, data) {
|
||||||
# corresponding content
|
return TabsEditingDescriptor.addToStorage.apply(TabsEditingDescriptor, arguments);
|
||||||
content_id = $currentTarget.attr('href')
|
};
|
||||||
|
|
||||||
@$content
|
TabsEditingDescriptor.Model = {
|
||||||
.addClass(isInactiveClass)
|
addModelUpdate: function(id, tabName, modelUpdateFunction) {
|
||||||
.filter(content_id)
|
|
||||||
.removeClass(isInactiveClass)
|
|
||||||
|
|
||||||
save: ->
|
/*
|
||||||
@element.off('click', '.editor-tabs .tab', @onSwitchEditor)
|
Function that registers 'modelUpdate' functions of every tab.
|
||||||
current_tab = @$tabs.filter('.current').data('tab_name')
|
These functions are used to update value, which will be returned
|
||||||
data: TabsEditingDescriptor.Model.getValue(@html_id, current_tab)
|
by calling save on component.
|
||||||
|
*/
|
||||||
|
this.initialize(id);
|
||||||
|
return this.modules[id].modelUpdate[tabName] = modelUpdateFunction;
|
||||||
|
},
|
||||||
|
addOnSwitch: function(id, tabName, onSwitchFunction) {
|
||||||
|
|
||||||
setMetadataEditor : (metadataEditor) ->
|
/*
|
||||||
TabsEditingDescriptor.setMetadataEditor.apply(TabsEditingDescriptor, arguments)
|
Function that registers functions invoked when switching
|
||||||
|
to particular tab.
|
||||||
|
*/
|
||||||
|
this.initialize(id);
|
||||||
|
return this.modules[id].tabSwitch[tabName] = onSwitchFunction;
|
||||||
|
},
|
||||||
|
updateValue: function(id, tabName) {
|
||||||
|
|
||||||
getStorage : () ->
|
/*
|
||||||
TabsEditingDescriptor.getStorage()
|
Function that invokes when switching tabs.
|
||||||
|
It ensures that data from previous tab is stored.
|
||||||
|
If new tab need this data, it should retrieve it from
|
||||||
|
stored value.
|
||||||
|
*/
|
||||||
|
var modelUpdateFunction;
|
||||||
|
this.initialize(id);
|
||||||
|
modelUpdateFunction = this.modules[id]['modelUpdate'][tabName];
|
||||||
|
if ($.isFunction(modelUpdateFunction)) {
|
||||||
|
return this.modules[id]['value'] = modelUpdateFunction();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
getValue: function(id, tabName) {
|
||||||
|
|
||||||
addToStorage : (id, data) ->
|
/*
|
||||||
TabsEditingDescriptor.addToStorage.apply(TabsEditingDescriptor, arguments)
|
Retrieves stored data on component save.
|
||||||
|
1. When we switching tabs - previous tab data is always saved to @[id].value
|
||||||
|
2. If current tab have registered 'modelUpdate' method, it should be invoked 1st.
|
||||||
|
(If we have edited in 1st tab, then switched to 2nd, 2nd tab should
|
||||||
|
care about getting data from @[id].value in onSwitch.)
|
||||||
|
*/
|
||||||
|
if (!this.modules[id]) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
if ($.isFunction(this.modules[id]['modelUpdate'][tabName])) {
|
||||||
|
return this.modules[id]['modelUpdate'][tabName]();
|
||||||
|
} else {
|
||||||
|
if (typeof this.modules[id]['value'] === 'undefined') {
|
||||||
|
return null;
|
||||||
|
} else {
|
||||||
|
return this.modules[id]['value'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
@Model :
|
/*
|
||||||
addModelUpdate : (id, tabName, modelUpdateFunction) ->
|
html_id's of descriptors will be stored in modules variable as
|
||||||
###
|
containers for callbacks.
|
||||||
Function that registers 'modelUpdate' functions of every tab.
|
*/
|
||||||
These functions are used to update value, which will be returned
|
modules: {},
|
||||||
by calling save on component.
|
Storage: {},
|
||||||
###
|
initialize: function(id) {
|
||||||
@initialize(id)
|
|
||||||
@modules[id].modelUpdate[tabName] = modelUpdateFunction
|
|
||||||
|
|
||||||
addOnSwitch : (id, tabName, onSwitchFunction) ->
|
/*
|
||||||
###
|
Initialize objects per id. Id is html_id of descriptor.
|
||||||
Function that registers functions invoked when switching
|
*/
|
||||||
to particular tab.
|
this.modules[id] = this.modules[id] || {};
|
||||||
###
|
this.modules[id].tabSwitch = this.modules[id]['tabSwitch'] || {};
|
||||||
@initialize(id)
|
return this.modules[id].modelUpdate = this.modules[id]['modelUpdate'] || {};
|
||||||
@modules[id].tabSwitch[tabName] = onSwitchFunction
|
}
|
||||||
|
};
|
||||||
|
|
||||||
updateValue : (id, tabName) ->
|
TabsEditingDescriptor.setMetadataEditor = function(metadataEditor) {
|
||||||
###
|
return TabsEditingDescriptor.Model.Storage['MetadataEditor'] = metadataEditor;
|
||||||
Function that invokes when switching tabs.
|
};
|
||||||
It ensures that data from previous tab is stored.
|
|
||||||
If new tab need this data, it should retrieve it from
|
|
||||||
stored value.
|
|
||||||
###
|
|
||||||
@initialize(id)
|
|
||||||
modelUpdateFunction = @modules[id]['modelUpdate'][tabName]
|
|
||||||
@modules[id]['value'] = modelUpdateFunction() if $.isFunction(modelUpdateFunction)
|
|
||||||
|
|
||||||
getValue : (id, tabName) ->
|
TabsEditingDescriptor.addToStorage = function(id, data) {
|
||||||
###
|
return TabsEditingDescriptor.Model.Storage[id] = data;
|
||||||
Retrieves stored data on component save.
|
};
|
||||||
1. When we switching tabs - previous tab data is always saved to @[id].value
|
|
||||||
2. If current tab have registered 'modelUpdate' method, it should be invoked 1st.
|
|
||||||
(If we have edited in 1st tab, then switched to 2nd, 2nd tab should
|
|
||||||
care about getting data from @[id].value in onSwitch.)
|
|
||||||
###
|
|
||||||
if not @modules[id]
|
|
||||||
return null
|
|
||||||
if $.isFunction(@modules[id]['modelUpdate'][tabName])
|
|
||||||
return @modules[id]['modelUpdate'][tabName]()
|
|
||||||
else
|
|
||||||
if typeof @modules[id]['value'] is 'undefined'
|
|
||||||
return null
|
|
||||||
else
|
|
||||||
return @modules[id]['value']
|
|
||||||
|
|
||||||
# html_id's of descriptors will be stored in modules variable as
|
TabsEditingDescriptor.getStorage = function() {
|
||||||
# containers for callbacks.
|
return TabsEditingDescriptor.Model.Storage;
|
||||||
modules: {}
|
};
|
||||||
Storage: {}
|
|
||||||
|
|
||||||
initialize : (id) ->
|
return TabsEditingDescriptor;
|
||||||
###
|
|
||||||
Initialize objects per id. Id is html_id of descriptor.
|
|
||||||
###
|
|
||||||
@modules[id] = @modules[id] or {}
|
|
||||||
@modules[id].tabSwitch = @modules[id]['tabSwitch'] or {}
|
|
||||||
@modules[id].modelUpdate = @modules[id]['modelUpdate'] or {}
|
|
||||||
|
|
||||||
@setMetadataEditor : (metadataEditor) ->
|
})();
|
||||||
TabsEditingDescriptor.Model.Storage['MetadataEditor'] = metadataEditor
|
|
||||||
|
|
||||||
@addToStorage : (id, data) ->
|
|
||||||
TabsEditingDescriptor.Model.Storage[id] = data
|
|
||||||
|
|
||||||
@getStorage : () ->
|
|
||||||
TabsEditingDescriptor.Model.Storage
|
|
||||||
|
|
||||||
|
}).call(this);
|
||||||
|
|||||||
@@ -1,2 +1,18 @@
|
|||||||
class @VerticalDescriptor extends XModule.Descriptor
|
// Once generated by CoffeeScript 1.9.3, but now lives as pure JS
|
||||||
|
/* eslint-disable */
|
||||||
|
(function() {
|
||||||
|
var extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
|
||||||
|
hasProp = {}.hasOwnProperty;
|
||||||
|
|
||||||
|
this.VerticalDescriptor = (function(superClass) {
|
||||||
|
extend(VerticalDescriptor, superClass);
|
||||||
|
|
||||||
|
function VerticalDescriptor() {
|
||||||
|
return VerticalDescriptor.__super__.constructor.apply(this, arguments);
|
||||||
|
}
|
||||||
|
|
||||||
|
return VerticalDescriptor;
|
||||||
|
|
||||||
|
})(XModule.Descriptor);
|
||||||
|
|
||||||
|
}).call(this);
|
||||||
|
|||||||
@@ -409,7 +409,7 @@ class LibraryContentDescriptor(LibraryContentFields, MakoModuleDescriptor, XmlDe
|
|||||||
|
|
||||||
module_class = LibraryContentModule
|
module_class = LibraryContentModule
|
||||||
mako_template = 'widgets/metadata-edit.html'
|
mako_template = 'widgets/metadata-edit.html'
|
||||||
js = {'coffee': [resource_string(__name__, 'js/src/vertical/edit.coffee')]}
|
js = {'js': [resource_string(__name__, 'js/src/vertical/edit.js')]}
|
||||||
js_module_name = "VerticalDescriptor"
|
js_module_name = "VerticalDescriptor"
|
||||||
|
|
||||||
show_in_read_only_mode = True
|
show_in_read_only_mode = True
|
||||||
|
|||||||
@@ -642,7 +642,7 @@ class SequenceDescriptor(SequenceFields, ProctoringFields, MakoModuleDescriptor,
|
|||||||
show_in_read_only_mode = True
|
show_in_read_only_mode = True
|
||||||
|
|
||||||
js = {
|
js = {
|
||||||
'coffee': [resource_string(__name__, 'js/src/sequence/edit.coffee')],
|
'js': [resource_string(__name__, 'js/src/sequence/edit.js')],
|
||||||
}
|
}
|
||||||
js_module_name = "SequenceDescriptor"
|
js_module_name = "SequenceDescriptor"
|
||||||
|
|
||||||
|
|||||||
@@ -92,8 +92,7 @@ class AnnotatableFields(object):
|
|||||||
|
|
||||||
class TextAnnotationModule(AnnotatableFields, XModule):
|
class TextAnnotationModule(AnnotatableFields, XModule):
|
||||||
''' Text Annotation Module '''
|
''' Text Annotation Module '''
|
||||||
js = {'coffee': [],
|
js = {'js': []}
|
||||||
'js': []}
|
|
||||||
css = {'scss': [resource_string(__name__, 'css/annotatable/display.scss')]}
|
css = {'scss': [resource_string(__name__, 'css/annotatable/display.scss')]}
|
||||||
icon_class = 'textannotation'
|
icon_class = 'textannotation'
|
||||||
|
|
||||||
|
|||||||
@@ -85,11 +85,9 @@ class AnnotatableFields(object):
|
|||||||
class VideoAnnotationModule(AnnotatableFields, XModule):
|
class VideoAnnotationModule(AnnotatableFields, XModule):
|
||||||
'''Video Annotation Module'''
|
'''Video Annotation Module'''
|
||||||
js = {
|
js = {
|
||||||
'coffee': [
|
|
||||||
resource_string(__name__, 'js/src/html/display.coffee'),
|
|
||||||
resource_string(__name__, 'js/src/annotatable/display.coffee'),
|
|
||||||
],
|
|
||||||
'js': [
|
'js': [
|
||||||
|
resource_string(__name__, 'js/src/html/display.js'),
|
||||||
|
resource_string(__name__, 'js/src/annotatable/display.js'),
|
||||||
resource_string(__name__, 'js/src/javascript_loader.js'),
|
resource_string(__name__, 'js/src/javascript_loader.js'),
|
||||||
resource_string(__name__, 'js/src/collapsible.js'),
|
resource_string(__name__, 'js/src/collapsible.js'),
|
||||||
]
|
]
|
||||||
|
|||||||
1
common/static/coffee/src/.gitignore
vendored
1
common/static/coffee/src/.gitignore
vendored
@@ -1 +0,0 @@
|
|||||||
*.js
|
|
||||||
@@ -65,7 +65,6 @@ var commonFiles = {
|
|||||||
{pattern: 'common/js/vendor/**/*.js'},
|
{pattern: 'common/js/vendor/**/*.js'},
|
||||||
{pattern: 'edx-pattern-library/js/**/*.js'},
|
{pattern: 'edx-pattern-library/js/**/*.js'},
|
||||||
{pattern: 'edx-ui-toolkit/js/**/*.js'},
|
{pattern: 'edx-ui-toolkit/js/**/*.js'},
|
||||||
{pattern: 'xmodule_js/common_static/coffee/src/**/!(*spec).js'},
|
|
||||||
{pattern: 'xmodule_js/common_static/common/js/**/!(*spec).js'},
|
{pattern: 'xmodule_js/common_static/common/js/**/!(*spec).js'},
|
||||||
{pattern: 'xmodule_js/common_static/js/**/!(*spec).js'},
|
{pattern: 'xmodule_js/common_static/js/**/!(*spec).js'},
|
||||||
{pattern: 'xmodule_js/src/**/*.js'}
|
{pattern: 'xmodule_js/src/**/*.js'}
|
||||||
|
|||||||
@@ -26,7 +26,7 @@
|
|||||||
'jquery.fileupload': 'js/vendor/jQuery-File-Upload/js/jquery.fileupload',
|
'jquery.fileupload': 'js/vendor/jQuery-File-Upload/js/jquery.fileupload',
|
||||||
'jquery.iframe-transport': 'js/vendor/jQuery-File-Upload/js/jquery.iframe-transport',
|
'jquery.iframe-transport': 'js/vendor/jQuery-File-Upload/js/jquery.iframe-transport',
|
||||||
'jquery.inputnumber': 'js/vendor/html5-input-polyfills/number-polyfill',
|
'jquery.inputnumber': 'js/vendor/html5-input-polyfills/number-polyfill',
|
||||||
'jquery.immediateDescendents': 'coffee/src/jquery.immediateDescendents',
|
'jquery.immediateDescendents': 'js/src/jquery.immediateDescendents',
|
||||||
'jquery.simulate': 'js/vendor/jquery.simulate',
|
'jquery.simulate': 'js/vendor/jquery.simulate',
|
||||||
'jquery.url': 'js/vendor/url.min',
|
'jquery.url': 'js/vendor/url.min',
|
||||||
'sinon': 'common/js/vendor/sinon',
|
'sinon': 'common/js/vendor/sinon',
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
padding: 10px;
|
padding: 10px;
|
||||||
background-color: #fff;
|
background-color: #fff;
|
||||||
/* keep font-family in sync with CUSTOM_FONTS constant in Html editor XModule
|
/* keep font-family in sync with CUSTOM_FONTS constant in Html editor XModule
|
||||||
* (edx-platform/common/lib/xmodule/xmodule/js/src/html/edit.coffee)
|
* (edx-platform/common/lib/xmodule/xmodule/js/src/html/edit.js)
|
||||||
* and with acceptance tests in cms/djangoapps/contentstore/features/html-editor.feature
|
* and with acceptance tests in cms/djangoapps/contentstore/features/html-editor.feature
|
||||||
*/
|
*/
|
||||||
font-family: 'Open Sans', Verdana, Arial, Helvetica, sans-serif;
|
font-family: 'Open Sans', Verdana, Arial, Helvetica, sans-serif;
|
||||||
|
|||||||
@@ -1,16 +1,24 @@
|
|||||||
@AjaxPrefix =
|
// Once generated by CoffeeScript 1.9.3, but now lives as pure JS
|
||||||
addAjaxPrefix: (jQuery, prefix) ->
|
/* eslint-disable */
|
||||||
jQuery.postWithPrefix = (url, data, callback, type) ->
|
(function() {
|
||||||
$.post("#{prefix()}#{url}", data, callback, type)
|
this.AjaxPrefix = {
|
||||||
|
addAjaxPrefix: function(jQuery, prefix) {
|
||||||
jQuery.getWithPrefix = (url, data, callback, type) ->
|
jQuery.postWithPrefix = function(url, data, callback, type) {
|
||||||
$.get("#{prefix()}#{url}", data, callback, type)
|
return $.post("" + (prefix()) + url, data, callback, type);
|
||||||
|
};
|
||||||
jQuery.ajaxWithPrefix = (url, settings) ->
|
jQuery.getWithPrefix = function(url, data, callback, type) {
|
||||||
if settings?
|
return $.get("" + (prefix()) + url, data, callback, type);
|
||||||
$.ajax("#{prefix()}#{url}", settings)
|
};
|
||||||
else
|
return jQuery.ajaxWithPrefix = function(url, settings) {
|
||||||
settings = url
|
if (settings != null) {
|
||||||
settings.url = "#{prefix()}#{settings.url}"
|
return $.ajax("" + (prefix()) + url, settings);
|
||||||
$.ajax settings
|
} else {
|
||||||
|
settings = url;
|
||||||
|
settings.url = "" + (prefix()) + settings.url;
|
||||||
|
return $.ajax(settings);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
}).call(this);
|
||||||
|
|||||||
@@ -1,11 +1,23 @@
|
|||||||
# Find all the children of an element that match the selector, but only
|
// Once generated by CoffeeScript 1.9.3, but now lives as pure JS
|
||||||
# the first instance found down any path. For example, we'll find all
|
/* eslint-disable */
|
||||||
# the ".xblock" elements below us, but not the ones that are themselves
|
|
||||||
# contained somewhere inside ".xblock" elements.
|
/*
|
||||||
jQuery.fn.immediateDescendents = (selector) ->
|
Find all the children of an element that match the selector, but only
|
||||||
@children().map ->
|
the first instance found down any path. For example, we'll find all
|
||||||
elem = jQuery(this)
|
the ".xblock" elements below us, but not the ones that are themselves
|
||||||
if elem.is(selector)
|
contained somewhere inside ".xblock" elements.
|
||||||
this
|
*/
|
||||||
else
|
(function() {
|
||||||
elem.immediateDescendents(selector).get()
|
jQuery.fn.immediateDescendents = function(selector) {
|
||||||
|
return this.children().map(function() {
|
||||||
|
var elem;
|
||||||
|
elem = jQuery(this);
|
||||||
|
if (elem.is(selector)) {
|
||||||
|
return this;
|
||||||
|
} else {
|
||||||
|
return elem.immediateDescendents(selector).get();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
}).call(this);
|
||||||
|
|||||||
@@ -1,47 +1,76 @@
|
|||||||
class XProblemGenerator
|
// Once generated by CoffeeScript 1.9.3, but now lives as pure JS
|
||||||
|
/* eslint-disable */
|
||||||
constructor: (seed, @parameters={}) ->
|
(function() {
|
||||||
|
var XProblemDisplay, XProblemGenerator, XProblemGrader, root;
|
||||||
|
|
||||||
@random = new MersenneTwister(seed)
|
XProblemGenerator = (function() {
|
||||||
|
function XProblemGenerator(seed, parameters) {
|
||||||
|
this.parameters = parameters != null ? parameters : {};
|
||||||
|
this.random = new MersenneTwister(seed);
|
||||||
|
this.problemState = {};
|
||||||
|
}
|
||||||
|
|
||||||
@problemState = {}
|
XProblemGenerator.prototype.generate = function() {
|
||||||
|
return console.error("Abstract method called: XProblemGenerator.generate");
|
||||||
|
};
|
||||||
|
|
||||||
generate: () ->
|
return XProblemGenerator;
|
||||||
|
|
||||||
console.error("Abstract method called: XProblemGenerator.generate")
|
})();
|
||||||
|
|
||||||
class XProblemDisplay
|
XProblemDisplay = (function() {
|
||||||
|
function XProblemDisplay(state, submission, evaluation, container, submissionField, parameters) {
|
||||||
|
this.state = state;
|
||||||
|
this.submission = submission;
|
||||||
|
this.evaluation = evaluation;
|
||||||
|
this.container = container;
|
||||||
|
this.submissionField = submissionField;
|
||||||
|
this.parameters = parameters != null ? parameters : {};
|
||||||
|
}
|
||||||
|
|
||||||
constructor: (@state, @submission, @evaluation, @container, @submissionField, @parameters={}) ->
|
XProblemDisplay.prototype.render = function() {
|
||||||
|
return console.error("Abstract method called: XProblemDisplay.render");
|
||||||
|
};
|
||||||
|
|
||||||
render: () ->
|
XProblemDisplay.prototype.updateSubmission = function() {
|
||||||
|
return this.submissionField.val(JSON.stringify(this.getCurrentSubmission()));
|
||||||
|
};
|
||||||
|
|
||||||
console.error("Abstract method called: XProblemDisplay.render")
|
XProblemDisplay.prototype.getCurrentSubmission = function() {
|
||||||
|
return console.error("Abstract method called: XProblemDisplay.getCurrentSubmission");
|
||||||
|
};
|
||||||
|
|
||||||
updateSubmission: () ->
|
return XProblemDisplay;
|
||||||
|
|
||||||
@submissionField.val(JSON.stringify(@getCurrentSubmission()))
|
})();
|
||||||
|
|
||||||
getCurrentSubmission: () ->
|
XProblemGrader = (function() {
|
||||||
console.error("Abstract method called: XProblemDisplay.getCurrentSubmission")
|
function XProblemGrader(submission, problemState, parameters) {
|
||||||
|
this.submission = submission;
|
||||||
|
this.problemState = problemState;
|
||||||
|
this.parameters = parameters != null ? parameters : {};
|
||||||
|
this.solution = null;
|
||||||
|
this.evaluation = {};
|
||||||
|
}
|
||||||
|
|
||||||
class XProblemGrader
|
XProblemGrader.prototype.solve = function() {
|
||||||
|
return console.error("Abstract method called: XProblemGrader.solve");
|
||||||
|
};
|
||||||
|
|
||||||
constructor: (@submission, @problemState, @parameters={}) ->
|
XProblemGrader.prototype.grade = function() {
|
||||||
|
return console.error("Abstract method called: XProblemGrader.grade");
|
||||||
|
};
|
||||||
|
|
||||||
@solution = null
|
return XProblemGrader;
|
||||||
@evaluation = {}
|
|
||||||
|
|
||||||
solve: () ->
|
})();
|
||||||
|
|
||||||
console.error("Abstract method called: XProblemGrader.solve")
|
root = typeof exports !== "undefined" && exports !== null ? exports : this;
|
||||||
|
|
||||||
grade: () ->
|
root.XProblemGenerator = XProblemGenerator;
|
||||||
|
|
||||||
console.error("Abstract method called: XProblemGrader.grade")
|
root.XProblemDisplay = XProblemDisplay;
|
||||||
|
|
||||||
root = exports ? this
|
root.XProblemGrader = XProblemGrader;
|
||||||
|
|
||||||
root.XProblemGenerator = XProblemGenerator
|
}).call(this);
|
||||||
root.XProblemDisplay = XProblemDisplay
|
|
||||||
root.XProblemGrader = XProblemGrader
|
|
||||||
|
|||||||
@@ -16,11 +16,11 @@ var options = {
|
|||||||
|
|
||||||
// Avoid adding files to this list. Use RequireJS.
|
// Avoid adding files to this list. Use RequireJS.
|
||||||
libraryFilesToInclude: [
|
libraryFilesToInclude: [
|
||||||
{pattern: 'coffee/src/ajax_prefix.js', included: true},
|
{pattern: 'js/src/ajax_prefix.js', included: true},
|
||||||
{pattern: 'js/vendor/draggabilly.js', included: true},
|
{pattern: 'js/vendor/draggabilly.js', included: true},
|
||||||
{pattern: 'common/js/vendor/jquery.js', included: true},
|
{pattern: 'common/js/vendor/jquery.js', included: true},
|
||||||
{pattern: 'common/js/vendor/jquery-migrate.js', included: true},
|
{pattern: 'common/js/vendor/jquery-migrate.js', included: true},
|
||||||
{pattern: 'coffee/src/jquery.immediateDescendents.js', included: true},
|
{pattern: 'js/src/jquery.immediateDescendents.js', included: true},
|
||||||
{pattern: 'js/vendor/jquery.leanModal.js', included: true},
|
{pattern: 'js/vendor/jquery.leanModal.js', included: true},
|
||||||
{pattern: 'js/vendor/jquery.timeago.js', included: true},
|
{pattern: 'js/vendor/jquery.timeago.js', included: true},
|
||||||
{pattern: 'js/vendor/jquery.truncate.js', included: true},
|
{pattern: 'js/vendor/jquery.truncate.js', included: true},
|
||||||
@@ -49,7 +49,6 @@ var options = {
|
|||||||
// Make sure the patterns in sourceFiles and specFiles do not match the same file.
|
// Make sure the patterns in sourceFiles and specFiles do not match the same file.
|
||||||
// Otherwise Istanbul which is used for coverage tracking will cause tests to not run.
|
// Otherwise Istanbul which is used for coverage tracking will cause tests to not run.
|
||||||
sourceFiles: [
|
sourceFiles: [
|
||||||
{pattern: 'coffee/src/**/*.js', included: true},
|
|
||||||
{pattern: 'common/js/xblock/core.js', included: true},
|
{pattern: 'common/js/xblock/core.js', included: true},
|
||||||
{pattern: 'common/js/xblock/runtime.v1.js', included: true},
|
{pattern: 'common/js/xblock/runtime.v1.js', included: true},
|
||||||
{pattern: 'common/js/discussion/**/*.js', included: true},
|
{pattern: 'common/js/discussion/**/*.js', included: true},
|
||||||
@@ -58,7 +57,6 @@ var options = {
|
|||||||
],
|
],
|
||||||
|
|
||||||
specFiles: [
|
specFiles: [
|
||||||
{pattern: 'coffee/spec/**/*.js', included: true},
|
|
||||||
{pattern: 'common/js/spec/xblock/*.js', included: true},
|
{pattern: 'common/js/spec/xblock/*.js', included: true},
|
||||||
{pattern: 'common/js/spec/discussion/**/*spec.js', included: true},
|
{pattern: 'common/js/spec/discussion/**/*spec.js', included: true},
|
||||||
{pattern: 'js/**/*spec.js', included: true}
|
{pattern: 'js/**/*spec.js', included: true}
|
||||||
|
|||||||
@@ -16,7 +16,6 @@ var options = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
libraryFiles: [
|
libraryFiles: [
|
||||||
{pattern: 'coffee/src/**/*.js'},
|
|
||||||
{pattern: 'js/libs/**/*.js'},
|
{pattern: 'js/libs/**/*.js'},
|
||||||
{pattern: 'js/test/**/*.js'},
|
{pattern: 'js/test/**/*.js'},
|
||||||
{pattern: 'js/vendor/**/*.js'}
|
{pattern: 'js/vendor/**/*.js'}
|
||||||
|
|||||||
@@ -66,9 +66,8 @@ out when files are missing (added when we started dynamically scanning XBlocks
|
|||||||
for assets).
|
for assets).
|
||||||
|
|
||||||
The ``django-pipeline`` config is aware of CSS files for the purposes of
|
The ``django-pipeline`` config is aware of CSS files for the purposes of
|
||||||
concatenation, but it does *not* know about the source Sass files (or handful of
|
concatenation, but it does *not* know about the source Sass files.
|
||||||
remaining CoffeeScript files). Those are processed with paver tasks before
|
Those are processed with paver tasks before ``django-pipeline`` ever sees them.
|
||||||
``django-pipeline`` ever sees them.
|
|
||||||
|
|
||||||
We also have the following custom extensions to Django's builtin ``STATICFILES``
|
We also have the following custom extensions to Django's builtin ``STATICFILES``
|
||||||
mechanism:
|
mechanism:
|
||||||
@@ -168,8 +167,7 @@ also be responsible for the optimization/minification of JavaScript assets, but
|
|||||||
those optimized assets would only appear under the ``/webpack`` directory. Third
|
those optimized assets would only appear under the ``/webpack`` directory. Third
|
||||||
party assets that Webpack is not aware of may have hash suffixes applied to them
|
party assets that Webpack is not aware of may have hash suffixes applied to them
|
||||||
by the Django collectstatic layer, but will not otherwise be processed or
|
by the Django collectstatic layer, but will not otherwise be processed or
|
||||||
optimized in any way -- so no coffeescript/sass compilation, no uglifyjs
|
optimized in any way -- so no sass compilation, no uglifyjs minification, etc.
|
||||||
minification, etc.
|
|
||||||
|
|
||||||
The django-pipeline dependency should be removed altogether.
|
The django-pipeline dependency should be removed altogether.
|
||||||
|
|
||||||
|
|||||||
@@ -92,10 +92,10 @@ Test Locations
|
|||||||
|
|
||||||
- Javascript unit tests: Located in ``spec`` folders. For example,
|
- Javascript unit tests: Located in ``spec`` folders. For example,
|
||||||
``common/lib/xmodule/xmodule/js/spec`` and
|
``common/lib/xmodule/xmodule/js/spec`` and
|
||||||
``{cms,lms}/static/coffee/spec`` For consistency, you should use the
|
``{cms,lms}/static/js/spec`` For consistency, you should use the
|
||||||
same directory structure for implementation and test. For example,
|
same directory structure for implementation and test. For example,
|
||||||
the test for ``src/views/module.coffee`` should be written in
|
the test for ``src/views/module.js`` should be written in
|
||||||
``spec/views/module_spec.coffee``.
|
``spec/views/module_spec.js``.
|
||||||
|
|
||||||
- UI acceptance tests:
|
- UI acceptance tests:
|
||||||
|
|
||||||
@@ -151,8 +151,8 @@ For example, this command runs all the python test scripts::
|
|||||||
paver test_python
|
paver test_python
|
||||||
|
|
||||||
It also runs ``collectstatic``, which prepares the
|
It also runs ``collectstatic``, which prepares the
|
||||||
static files used by the site (for example, compiling CoffeeScript to
|
static files used by the site (for example, compiling Sass to
|
||||||
JavaScript).
|
CSS).
|
||||||
|
|
||||||
You can re-run all failed python tests by running this command (see note at end of
|
You can re-run all failed python tests by running this command (see note at end of
|
||||||
section)::
|
section)::
|
||||||
@@ -332,7 +332,6 @@ To run a specific set of JavaScript tests and print the results to the
|
|||||||
console, run these commands::
|
console, run these commands::
|
||||||
|
|
||||||
paver test_js_run -s lms
|
paver test_js_run -s lms
|
||||||
paver test_js_run -s lms-coffee
|
|
||||||
paver test_js_run -s cms
|
paver test_js_run -s cms
|
||||||
paver test_js_run -s cms-squire
|
paver test_js_run -s cms-squire
|
||||||
paver test_js_run -s xmodule
|
paver test_js_run -s xmodule
|
||||||
@@ -342,7 +341,6 @@ console, run these commands::
|
|||||||
To run JavaScript tests in a browser, run these commands::
|
To run JavaScript tests in a browser, run these commands::
|
||||||
|
|
||||||
paver test_js_dev -s lms
|
paver test_js_dev -s lms
|
||||||
paver test_js_dev -s lms-coffee
|
|
||||||
paver test_js_dev -s cms
|
paver test_js_dev -s cms
|
||||||
paver test_js_dev -s cms-squire
|
paver test_js_dev -s cms-squire
|
||||||
paver test_js_dev -s xmodule
|
paver test_js_dev -s xmodule
|
||||||
|
|||||||
@@ -1241,7 +1241,7 @@ def get_students_features(request, course_id, csv=False): # pylint: disable=red
|
|||||||
]
|
]
|
||||||
|
|
||||||
# Provide human-friendly and translatable names for these features. These names
|
# Provide human-friendly and translatable names for these features. These names
|
||||||
# will be displayed in the table generated in data_download.coffee. It is not (yet)
|
# will be displayed in the table generated in data_download.js. It is not (yet)
|
||||||
# used as the header row in the CSV, but could be in the future.
|
# used as the header row in the CSV, but could be in the future.
|
||||||
query_features_names = {
|
query_features_names = {
|
||||||
'id': _('User ID'),
|
'id': _('User ID'),
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ lms/djangoapps/notes:
|
|||||||
|
|
||||||
Also requires:
|
Also requires:
|
||||||
|
|
||||||
* lms/static/coffee/src/notes.coffee -- wrapper around annotator.js
|
* lms/static/js/notes.js -- wrapper around annotator.js
|
||||||
* lms/templates/notes.html -- used by views.py to display the notes
|
* lms/templates/notes.html -- used by views.py to display the notes
|
||||||
|
|
||||||
Interacts with:
|
Interacts with:
|
||||||
|
|||||||
@@ -448,7 +448,6 @@ system_node_path = os.environ.get("NODE_PATH", NODE_MODULES_ROOT)
|
|||||||
|
|
||||||
node_paths = [
|
node_paths = [
|
||||||
COMMON_ROOT / "static/js/vendor",
|
COMMON_ROOT / "static/js/vendor",
|
||||||
COMMON_ROOT / "static/coffee/src",
|
|
||||||
system_node_path,
|
system_node_path,
|
||||||
]
|
]
|
||||||
NODE_PATH = ':'.join(node_paths)
|
NODE_PATH = ':'.join(node_paths)
|
||||||
@@ -1163,10 +1162,6 @@ EDXNOTES_READ_TIMEOUT = 1.5 # time in seconds
|
|||||||
# if parental consent is never required.
|
# if parental consent is never required.
|
||||||
PARENTAL_CONSENT_AGE_LIMIT = 13
|
PARENTAL_CONSENT_AGE_LIMIT = 13
|
||||||
|
|
||||||
################################# Jasmine ##################################
|
|
||||||
JASMINE_TEST_DIRECTORY = PROJECT_ROOT + '/static/coffee'
|
|
||||||
|
|
||||||
|
|
||||||
######################### Branded Footer ###################################
|
######################### Branded Footer ###################################
|
||||||
# Constants for the footer used on the site and shared with other sites
|
# Constants for the footer used on the site and shared with other sites
|
||||||
# (such as marketing and the blog) via the branding API.
|
# (such as marketing and the blog) via the branding API.
|
||||||
@@ -1340,14 +1335,13 @@ PIPELINE_UGLIFYJS_BINARY = 'node_modules/.bin/uglifyjs'
|
|||||||
|
|
||||||
from openedx.core.lib.rooted_paths import rooted_glob
|
from openedx.core.lib.rooted_paths import rooted_glob
|
||||||
|
|
||||||
courseware_js = (
|
courseware_js = [
|
||||||
[
|
'js/ajax-error.js',
|
||||||
'coffee/src/' + pth + '.js'
|
'js/courseware.js',
|
||||||
for pth in ['courseware', 'histogram', 'navigation']
|
'js/histogram.js',
|
||||||
] +
|
'js/navigation.js',
|
||||||
['js/' + pth + '.js' for pth in ['ajax-error']] +
|
'js/modules/tab.js',
|
||||||
sorted(rooted_glob(PROJECT_ROOT / 'static', 'coffee/src/modules/**/*.js'))
|
]
|
||||||
)
|
|
||||||
|
|
||||||
proctoring_js = (
|
proctoring_js = (
|
||||||
[
|
[
|
||||||
@@ -1428,9 +1422,9 @@ dashboard_js = (
|
|||||||
)
|
)
|
||||||
discussion_js = (
|
discussion_js = (
|
||||||
rooted_glob(COMMON_ROOT / 'static', 'common/js/discussion/mathjax_include.js') +
|
rooted_glob(COMMON_ROOT / 'static', 'common/js/discussion/mathjax_include.js') +
|
||||||
rooted_glob(PROJECT_ROOT / 'static', 'coffee/src/customwmd.js') +
|
rooted_glob(PROJECT_ROOT / 'static', 'js/customwmd.js') +
|
||||||
rooted_glob(PROJECT_ROOT / 'static', 'coffee/src/mathjax_accessible.js') +
|
rooted_glob(PROJECT_ROOT / 'static', 'js/mathjax_accessible.js') +
|
||||||
rooted_glob(PROJECT_ROOT / 'static', 'coffee/src/mathjax_delay_renderer.js') +
|
rooted_glob(PROJECT_ROOT / 'static', 'js/mathjax_delay_renderer.js') +
|
||||||
sorted(rooted_glob(COMMON_ROOT / 'static', 'common/js/discussion/**/*.js'))
|
sorted(rooted_glob(COMMON_ROOT / 'static', 'common/js/discussion/**/*.js'))
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -1445,7 +1439,7 @@ discussion_vendor_js = [
|
|||||||
'js/split.js'
|
'js/split.js'
|
||||||
]
|
]
|
||||||
|
|
||||||
notes_js = sorted(rooted_glob(PROJECT_ROOT / 'static', 'coffee/src/notes/**/*.js'))
|
notes_js = ['js/notes.js']
|
||||||
instructor_dash_js = sorted(rooted_glob(PROJECT_ROOT / 'static', 'js/instructor_dashboard/**/*.js'))
|
instructor_dash_js = sorted(rooted_glob(PROJECT_ROOT / 'static', 'js/instructor_dashboard/**/*.js'))
|
||||||
|
|
||||||
verify_student_js = [
|
verify_student_js = [
|
||||||
@@ -1682,15 +1676,21 @@ PIPELINE_CSS = {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
common_js = [
|
||||||
separately_bundled_js = set(courseware_js + discussion_js + notes_js + instructor_dash_js)
|
'js/src/ajax_prefix.js',
|
||||||
common_js = sorted(set(rooted_glob(COMMON_ROOT / 'static', 'coffee/src/**/*.js')) - separately_bundled_js)
|
'js/src/jquery.immediateDescendents.js',
|
||||||
|
'js/src/xproblem.js',
|
||||||
|
]
|
||||||
xblock_runtime_js = [
|
xblock_runtime_js = [
|
||||||
'common/js/xblock/core.js',
|
'common/js/xblock/core.js',
|
||||||
'common/js/xblock/runtime.v1.js',
|
'common/js/xblock/runtime.v1.js',
|
||||||
'lms/js/xblock/lms.runtime.v1.js',
|
'lms/js/xblock/lms.runtime.v1.js',
|
||||||
]
|
]
|
||||||
lms_application_js = sorted(set(rooted_glob(PROJECT_ROOT / 'static', 'coffee/src/**/*.js')) - separately_bundled_js)
|
lms_application_js = [
|
||||||
|
'js/calculator.js',
|
||||||
|
'js/feedback_form.js',
|
||||||
|
'js/main.js',
|
||||||
|
]
|
||||||
|
|
||||||
PIPELINE_JS = {
|
PIPELINE_JS = {
|
||||||
'base_application': {
|
'base_application': {
|
||||||
@@ -1796,10 +1796,6 @@ STATICFILES_IGNORE_PATTERNS = (
|
|||||||
"sass/*/*.scss",
|
"sass/*/*.scss",
|
||||||
"sass/*/*/*.scss",
|
"sass/*/*/*.scss",
|
||||||
"sass/*/*/*/*.scss",
|
"sass/*/*/*/*.scss",
|
||||||
"coffee/*.coffee",
|
|
||||||
"coffee/*/*.coffee",
|
|
||||||
"coffee/*/*/*.coffee",
|
|
||||||
"coffee/*/*/*/*.coffee",
|
|
||||||
|
|
||||||
# Ignore tests
|
# Ignore tests
|
||||||
"spec",
|
"spec",
|
||||||
|
|||||||
@@ -1,44 +0,0 @@
|
|||||||
CoffeeScript
|
|
||||||
============
|
|
||||||
|
|
||||||
This folder contains the CoffeeScript file that will be compiled to the static
|
|
||||||
directory. By default, we're compile and merge all the files ending `.coffee`
|
|
||||||
into `static/js/application.js`.
|
|
||||||
|
|
||||||
Install the Compiler
|
|
||||||
--------------------
|
|
||||||
|
|
||||||
CoffeeScript compiler are written in JavaScript. You'll need to install Node and
|
|
||||||
npm (Node Package Manager) to be able to install the CoffeeScript compiler.
|
|
||||||
|
|
||||||
### Mac OS X
|
|
||||||
|
|
||||||
Install Node via Homebrew, then use npm:
|
|
||||||
|
|
||||||
$ brew install node
|
|
||||||
$ curl http://npmjs.org/install.sh | sh
|
|
||||||
$ npm install -g git://github.com/jashkenas/coffee-script.git
|
|
||||||
|
|
||||||
(Note that we're using the edge version of CoffeeScript for now, as there was
|
|
||||||
some issue with directory watching in 1.3.1.)
|
|
||||||
|
|
||||||
Try to run `coffee` and make sure you get a coffee prompt.
|
|
||||||
|
|
||||||
### Debian/Ubuntu
|
|
||||||
|
|
||||||
Conveniently, you can install Node via `apt-get`, then use npm:
|
|
||||||
|
|
||||||
$ sudo apt-get install nodejs npm &&
|
|
||||||
$ sudo npm install -g git://github.com/jashkenas/coffee-script.git
|
|
||||||
|
|
||||||
Compiling
|
|
||||||
---------
|
|
||||||
|
|
||||||
CoffeeScript is compiled when you update assets using the command:
|
|
||||||
|
|
||||||
$ paver update_assets
|
|
||||||
|
|
||||||
Testing
|
|
||||||
-------
|
|
||||||
|
|
||||||
We use Jasmine to unit-test the JavaScript files. See `docs/en_us/internal/testing.rst` for details.
|
|
||||||
1
lms/static/coffee/src/.gitignore
vendored
1
lms/static/coffee/src/.gitignore
vendored
@@ -1 +0,0 @@
|
|||||||
*.js
|
|
||||||
@@ -1,224 +1,274 @@
|
|||||||
# Keyboard Support
|
// Once generated by CoffeeScript 1.9.3, but now lives as pure JS
|
||||||
|
/* eslint-disable */
|
||||||
|
|
||||||
# If focus is on the hint button:
|
/*
|
||||||
# * Enter: Open or close hint popup. Select last focused hint item if opening
|
Keyboard Support
|
||||||
# * Space: Open or close hint popup. Select last focused hint item if opening
|
|
||||||
|
|
||||||
# If focus is on a hint item:
|
If focus is on the hint button:
|
||||||
# * Left arrow: Select previous hint item
|
* Enter: Open or close hint popup. Select last focused hint item if opening
|
||||||
# * Up arrow: Select previous hint item
|
* Space: Open or close hint popup. Select last focused hint item if opening
|
||||||
# * Right arrow: Select next hint item
|
|
||||||
# * Down arrow: Select next hint item
|
|
||||||
|
|
||||||
|
If focus is on a hint item:
|
||||||
|
* Left arrow: Select previous hint item
|
||||||
|
* Up arrow: Select previous hint item
|
||||||
|
* Right arrow: Select next hint item
|
||||||
|
* Down arrow: Select next hint item
|
||||||
|
*/
|
||||||
|
|
||||||
class @Calculator
|
(function() {
|
||||||
constructor: ->
|
this.Calculator = (function() {
|
||||||
@hintButton = $('#calculator_hint')
|
function Calculator() {
|
||||||
@calcInput = $('#calculator_input')
|
this.hintButton = $('#calculator_hint');
|
||||||
@hintPopup = $('.help')
|
this.calcInput = $('#calculator_input');
|
||||||
@hintsList = @hintPopup.find('.hint-item')
|
this.hintPopup = $('.help');
|
||||||
@selectHint($('#' + @hintPopup.attr('data-calculator-hint')));
|
this.hintsList = this.hintPopup.find('.hint-item');
|
||||||
|
this.selectHint($('#' + this.hintPopup.attr('data-calculator-hint')));
|
||||||
|
$('.calc').click(this.toggle);
|
||||||
|
$('form#calculator').submit(this.calculate).submit(function(e) {
|
||||||
|
return e.preventDefault();
|
||||||
|
});
|
||||||
|
this.hintButton.click($.proxy(this.handleClickOnHintButton, this));
|
||||||
|
this.hintPopup.click($.proxy(this.handleClickOnHintPopup, this));
|
||||||
|
this.hintPopup.keydown($.proxy(this.handleKeyDownOnHint, this));
|
||||||
|
$('#calculator_wrapper').keyup($.proxy(this.handleKeyUpOnHint, this));
|
||||||
|
this.handleClickOnDocument = $.proxy(this.handleClickOnDocument, this);
|
||||||
|
this.calcInput.focus($.proxy(this.inputClickHandler, this));
|
||||||
|
}
|
||||||
|
|
||||||
$('.calc').click @toggle
|
Calculator.prototype.KEY = {
|
||||||
$('form#calculator').submit(@calculate).submit (e) ->
|
TAB: 9,
|
||||||
e.preventDefault()
|
ENTER: 13,
|
||||||
|
ESC: 27,
|
||||||
|
SPACE: 32,
|
||||||
|
LEFT: 37,
|
||||||
|
UP: 38,
|
||||||
|
RIGHT: 39,
|
||||||
|
DOWN: 40
|
||||||
|
};
|
||||||
|
|
||||||
@hintButton
|
Calculator.prototype.toggle = function(event) {
|
||||||
.click(($.proxy(@handleClickOnHintButton, @)))
|
var $calc, $calcWrapper, icon, isExpanded, text;
|
||||||
|
event.preventDefault();
|
||||||
|
$calc = $('.calc');
|
||||||
|
$calcWrapper = $('#calculator_wrapper');
|
||||||
|
text = gettext('Open Calculator');
|
||||||
|
isExpanded = false;
|
||||||
|
icon = 'fa-calculator';
|
||||||
|
$('.calc-main').toggleClass('open');
|
||||||
|
if ($calc.hasClass('closed')) {
|
||||||
|
$calcWrapper.attr('aria-hidden', 'true');
|
||||||
|
} else {
|
||||||
|
text = gettext('Close Calculator');
|
||||||
|
icon = 'fa-close';
|
||||||
|
isExpanded = true;
|
||||||
|
$calcWrapper.attr('aria-hidden', 'false');
|
||||||
|
|
||||||
@hintPopup
|
/*
|
||||||
.click(($.proxy(@handleClickOnHintPopup, @)))
|
TODO: Investigate why doing this without the timeout causes it to jump
|
||||||
|
down to the bottom of the page. I suspect it's because it's putting the
|
||||||
@hintPopup
|
focus on the text field before it transitions onto the page.
|
||||||
.keydown($.proxy(@handleKeyDownOnHint, @))
|
*/
|
||||||
|
setTimeout((function() {
|
||||||
$('#calculator_wrapper')
|
return $calcWrapper.find('#calculator_input').focus();
|
||||||
.keyup($.proxy(@handleKeyUpOnHint, @))
|
}), 100);
|
||||||
|
}
|
||||||
@handleClickOnDocument = $.proxy(@handleClickOnDocument, @)
|
$calc.attr({
|
||||||
|
'title': text,
|
||||||
@calcInput
|
|
||||||
.focus(($.proxy(@inputClickHandler, @)))
|
|
||||||
|
|
||||||
KEY:
|
|
||||||
TAB : 9
|
|
||||||
ENTER : 13
|
|
||||||
ESC : 27
|
|
||||||
SPACE : 32
|
|
||||||
LEFT : 37
|
|
||||||
UP : 38
|
|
||||||
RIGHT : 39
|
|
||||||
DOWN : 40
|
|
||||||
|
|
||||||
toggle: (event) ->
|
|
||||||
event.preventDefault()
|
|
||||||
$calc = $('.calc')
|
|
||||||
$calcWrapper = $('#calculator_wrapper')
|
|
||||||
text = gettext('Open Calculator')
|
|
||||||
isExpanded = false
|
|
||||||
icon = 'fa-calculator'
|
|
||||||
|
|
||||||
$('.calc-main').toggleClass 'open'
|
|
||||||
if $calc.hasClass('closed')
|
|
||||||
$calcWrapper
|
|
||||||
.attr('aria-hidden', 'true')
|
|
||||||
else
|
|
||||||
text = gettext('Close Calculator')
|
|
||||||
icon = 'fa-close'
|
|
||||||
isExpanded = true
|
|
||||||
|
|
||||||
$calcWrapper
|
|
||||||
.attr('aria-hidden', 'false')
|
|
||||||
# TODO: Investigate why doing this without the timeout causes it to jump
|
|
||||||
# down to the bottom of the page. I suspect it's because it's putting the
|
|
||||||
# focus on the text field before it transitions onto the page.
|
|
||||||
setTimeout (-> $calcWrapper.find('#calculator_input').focus()), 100
|
|
||||||
|
|
||||||
$calc
|
|
||||||
.attr
|
|
||||||
'title': text
|
|
||||||
'aria-expanded': isExpanded
|
'aria-expanded': isExpanded
|
||||||
.find('.utility-control-label').text text
|
}).find('.utility-control-label').text(text);
|
||||||
|
$calc.find('.icon').removeClass('fa-calculator').removeClass('fa-close').addClass(icon);
|
||||||
$calc
|
return $calc.toggleClass('closed');
|
||||||
.find('.icon')
|
};
|
||||||
.removeClass('fa-calculator')
|
|
||||||
.removeClass('fa-close')
|
|
||||||
.addClass(icon)
|
|
||||||
|
|
||||||
$calc.toggleClass 'closed'
|
Calculator.prototype.inputClickHandler = function() {
|
||||||
|
return $('#calculator_output').removeClass('has-result');
|
||||||
inputClickHandler: ->
|
};
|
||||||
$('#calculator_output').removeClass('has-result')
|
|
||||||
|
|
||||||
showHint: ->
|
Calculator.prototype.showHint = function() {
|
||||||
@hintPopup
|
this.hintPopup.addClass('shown').attr('aria-hidden', false);
|
||||||
.addClass('shown')
|
$('#calculator_output').removeClass('has-result');
|
||||||
.attr('aria-hidden', false)
|
return $(document).on('click', this.handleClickOnDocument);
|
||||||
|
};
|
||||||
|
|
||||||
$('#calculator_output').removeClass('has-result')
|
Calculator.prototype.hideHint = function() {
|
||||||
|
this.hintPopup.removeClass('shown').attr('aria-hidden', true);
|
||||||
|
$('#calculator_output').removeClass('has-result');
|
||||||
|
return $(document).off('click', this.handleClickOnDocument);
|
||||||
|
};
|
||||||
|
|
||||||
$(document).on('click', @handleClickOnDocument)
|
Calculator.prototype.selectHint = function(element) {
|
||||||
|
if (!element || (element && element.length === 0)) {
|
||||||
|
element = this.hintsList.first();
|
||||||
|
}
|
||||||
|
this.activeHint = element;
|
||||||
|
this.activeHint.focus();
|
||||||
|
return this.hintPopup.attr('data-calculator-hint', element.attr('id'));
|
||||||
|
};
|
||||||
|
|
||||||
hideHint: ->
|
Calculator.prototype.prevHint = function() {
|
||||||
@hintPopup
|
|
||||||
.removeClass('shown')
|
|
||||||
.attr('aria-hidden', true)
|
|
||||||
|
|
||||||
$('#calculator_output').removeClass('has-result')
|
|
||||||
|
|
||||||
$(document).off('click', @handleClickOnDocument)
|
/*
|
||||||
|
the previous hint
|
||||||
|
*/
|
||||||
|
var prev;
|
||||||
|
prev = this.activeHint.prev();
|
||||||
|
|
||||||
selectHint: (element) ->
|
/*
|
||||||
if not element or (element and element.length == 0)
|
if this was the first item
|
||||||
element = @hintsList.first()
|
select the last one in the group.
|
||||||
|
*/
|
||||||
|
if (this.activeHint.index() === 0) {
|
||||||
|
prev = this.hintsList.last();
|
||||||
|
}
|
||||||
|
|
||||||
@activeHint = element;
|
/*
|
||||||
@activeHint.focus();
|
select the previous hint
|
||||||
@hintPopup.attr('data-calculator-hint', element.attr('id'));
|
*/
|
||||||
|
return this.selectHint(prev);
|
||||||
|
};
|
||||||
|
|
||||||
prevHint: () ->
|
Calculator.prototype.nextHint = function() {
|
||||||
prev = @activeHint.prev(); # the previous hint
|
|
||||||
# if this was the first item
|
|
||||||
# select the last one in the group.
|
|
||||||
if @activeHint.index() == 0
|
|
||||||
prev = @hintsList.last()
|
|
||||||
# select the previous hint
|
|
||||||
@selectHint(prev)
|
|
||||||
|
|
||||||
nextHint: () ->
|
/*
|
||||||
next = @activeHint.next(); # the next hint
|
the next hint
|
||||||
# if this was the last item,
|
*/
|
||||||
# select the first one in the group.
|
var next;
|
||||||
if @activeHint.index() == @hintsList.length - 1
|
next = this.activeHint.next();
|
||||||
next = @hintsList.first()
|
|
||||||
# give the next hint focus
|
|
||||||
@selectHint(next)
|
|
||||||
|
|
||||||
handleKeyDown: (e) ->
|
/*
|
||||||
if e.altKey
|
if this was the last item,
|
||||||
# do nothing
|
select the first one in the group.
|
||||||
return true
|
*/
|
||||||
|
if (this.activeHint.index() === this.hintsList.length - 1) {
|
||||||
|
next = this.hintsList.first();
|
||||||
|
}
|
||||||
|
|
||||||
if e.keyCode == @KEY.ENTER or e.keyCode == @KEY.SPACE
|
/*
|
||||||
if @hintPopup.hasClass 'shown'
|
give the next hint focus
|
||||||
@hideHint()
|
*/
|
||||||
else
|
return this.selectHint(next);
|
||||||
@showHint()
|
};
|
||||||
@activeHint.focus()
|
|
||||||
|
|
||||||
e.preventDefault()
|
Calculator.prototype.handleKeyDown = function(e) {
|
||||||
return false
|
if (e.altKey) {
|
||||||
|
|
||||||
# allow the event to propagate
|
/*
|
||||||
return true
|
do nothing
|
||||||
|
*/
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (e.keyCode === this.KEY.ENTER || e.keyCode === this.KEY.SPACE) {
|
||||||
|
if (this.hintPopup.hasClass('shown')) {
|
||||||
|
this.hideHint();
|
||||||
|
} else {
|
||||||
|
this.showHint();
|
||||||
|
this.activeHint.focus();
|
||||||
|
}
|
||||||
|
e.preventDefault();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
handleKeyDownOnHint: (e) ->
|
/*
|
||||||
if e.altKey
|
allow the event to propagate
|
||||||
# do nothing
|
*/
|
||||||
return true
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
switch e.keyCode
|
Calculator.prototype.handleKeyDownOnHint = function(e) {
|
||||||
|
if (e.altKey) {
|
||||||
|
|
||||||
when @KEY.ESC
|
/*
|
||||||
# hide popup with hints
|
do nothing
|
||||||
@hideHint()
|
*/
|
||||||
@hintButton.focus()
|
return true;
|
||||||
|
}
|
||||||
|
switch (e.keyCode) {
|
||||||
|
case this.KEY.ESC:
|
||||||
|
|
||||||
e.stopPropagation()
|
/*
|
||||||
return false
|
hide popup with hints
|
||||||
|
*/
|
||||||
|
this.hideHint();
|
||||||
|
this.hintButton.focus();
|
||||||
|
e.stopPropagation();
|
||||||
|
return false;
|
||||||
|
case this.KEY.LEFT:
|
||||||
|
case this.KEY.UP:
|
||||||
|
if (e.shiftKey) {
|
||||||
|
|
||||||
when @KEY.LEFT, @KEY.UP
|
/*
|
||||||
if e.shiftKey
|
do nothing
|
||||||
# do nothing
|
*/
|
||||||
return true
|
}
|
||||||
|
return true;
|
||||||
|
this.prevHint();
|
||||||
|
e.stopPropagation();
|
||||||
|
return false;
|
||||||
|
case this.KEY.RIGHT:
|
||||||
|
case this.KEY.DOWN:
|
||||||
|
if (e.shiftKey) {
|
||||||
|
|
||||||
@prevHint()
|
/*
|
||||||
|
do nothing
|
||||||
|
*/
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
this.nextHint();
|
||||||
|
e.stopPropagation();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
e.stopPropagation()
|
/*
|
||||||
return false
|
allow the event to propagate
|
||||||
|
*/
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
when @KEY.RIGHT, @KEY.DOWN
|
Calculator.prototype.handleKeyUpOnHint = function(e) {
|
||||||
if e.shiftKey
|
switch (e.keyCode) {
|
||||||
# do nothing
|
case this.KEY.TAB:
|
||||||
return true
|
|
||||||
|
|
||||||
@nextHint()
|
/*
|
||||||
|
move focus to hint links and hide hint once focus is out of hint pop up
|
||||||
|
*/
|
||||||
|
this.active_element = document.activeElement;
|
||||||
|
if (!$(this.active_element).parents().is(this.hintPopup)) {
|
||||||
|
return this.hideHint();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
e.stopPropagation()
|
Calculator.prototype.handleClickOnDocument = function(e) {
|
||||||
return false
|
return this.hideHint();
|
||||||
|
};
|
||||||
|
|
||||||
# allow the event to propagate
|
Calculator.prototype.handleClickOnHintButton = function(e) {
|
||||||
return true
|
e.preventDefault();
|
||||||
|
e.stopPropagation();
|
||||||
|
if (this.hintPopup.hasClass('shown')) {
|
||||||
|
this.hideHint();
|
||||||
|
return this.hintButton.attr('aria-expanded', false);
|
||||||
|
} else {
|
||||||
|
this.showHint();
|
||||||
|
this.hintButton.attr('aria-expanded', true);
|
||||||
|
return this.activeHint.focus();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
handleKeyUpOnHint: (e) ->
|
Calculator.prototype.handleClickOnHintPopup = function(e) {
|
||||||
switch e.keyCode
|
return e.stopPropagation();
|
||||||
when @KEY.TAB
|
};
|
||||||
# move focus to hint links and hide hint once focus is out of hint pop up
|
|
||||||
@active_element = document.activeElement
|
|
||||||
if not $(@active_element).parents().is(@hintPopup)
|
|
||||||
@hideHint()
|
|
||||||
|
|
||||||
handleClickOnDocument: (e) ->
|
Calculator.prototype.calculate = function() {
|
||||||
@hideHint()
|
return $.getWithPrefix('/calculate', {
|
||||||
|
equation: $('#calculator_input').val()
|
||||||
|
}, function(data) {
|
||||||
|
return $('#calculator_output').val(data.result).addClass('has-result').focus();
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
handleClickOnHintButton: (e) ->
|
return Calculator;
|
||||||
e.preventDefault()
|
|
||||||
e.stopPropagation()
|
|
||||||
if @hintPopup.hasClass 'shown'
|
|
||||||
@hideHint()
|
|
||||||
@hintButton.attr('aria-expanded', false)
|
|
||||||
else
|
|
||||||
@showHint()
|
|
||||||
@hintButton.attr('aria-expanded', true)
|
|
||||||
@activeHint.focus()
|
|
||||||
|
|
||||||
handleClickOnHintPopup: (e) ->
|
})();
|
||||||
e.stopPropagation()
|
|
||||||
|
|
||||||
calculate: ->
|
}).call(this);
|
||||||
$.getWithPrefix '/calculate', { equation: $('#calculator_input').val() }, (data) ->
|
|
||||||
$('#calculator_output')
|
|
||||||
.val(data.result)
|
|
||||||
.addClass('has-result')
|
|
||||||
.focus()
|
|
||||||
|
|||||||
@@ -1,21 +1,38 @@
|
|||||||
class @Courseware
|
// Once generated by CoffeeScript 1.9.3, but now lives as pure JS
|
||||||
@prefix: ''
|
/* eslint-disable */
|
||||||
|
(function() {
|
||||||
|
this.Courseware = (function() {
|
||||||
|
Courseware.prefix = '';
|
||||||
|
|
||||||
constructor: ->
|
function Courseware() {
|
||||||
Logger.bind()
|
Logger.bind();
|
||||||
@render()
|
this.render();
|
||||||
|
}
|
||||||
|
|
||||||
@start: ->
|
Courseware.start = function() {
|
||||||
new Courseware
|
return new Courseware;
|
||||||
|
};
|
||||||
|
|
||||||
render: ->
|
Courseware.prototype.render = function() {
|
||||||
XBlock.initializeBlocks($('.course-content'))
|
XBlock.initializeBlocks($('.course-content'));
|
||||||
$('.course-content .histogram').each ->
|
return $('.course-content .histogram').each(function() {
|
||||||
id = $(this).attr('id').replace(/histogram_/, '')
|
var error, histg, id;
|
||||||
try
|
id = $(this).attr('id').replace(/histogram_/, '');
|
||||||
histg = new Histogram id, $(this).data('histogram')
|
try {
|
||||||
catch error
|
histg = new Histogram(id, $(this).data('histogram'));
|
||||||
histg = error
|
} catch (_error) {
|
||||||
if console?
|
error = _error;
|
||||||
console.log(error)
|
histg = error;
|
||||||
return histg
|
if (typeof console !== "undefined" && console !== null) {
|
||||||
|
console.log(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return histg;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
return Courseware;
|
||||||
|
|
||||||
|
})();
|
||||||
|
|
||||||
|
}).call(this);
|
||||||
|
|||||||
@@ -1,181 +1,247 @@
|
|||||||
# Mostly adapted from math.stackexchange.com: http://cdn.sstatic.net/js/mathjax-editing-new.js
|
// Once generated by CoffeeScript 1.9.3, but now lives as pure JS
|
||||||
|
/* eslint-disable */
|
||||||
|
// TODO: Examine all of the xss-lint exceptions (https://openedx.atlassian.net/browse/PLAT-2084)
|
||||||
|
|
||||||
class MathJaxProcessor
|
/*
|
||||||
|
Mostly adapted from math.stackexchange.com: http://cdn.sstatic.net/js/mathjax-editing-new.js
|
||||||
|
*/
|
||||||
|
(function() {
|
||||||
|
var MathJaxProcessor;
|
||||||
|
|
||||||
MATHSPLIT = /// (
|
MathJaxProcessor = (function() {
|
||||||
\$\$? # normal inline or display delimiter
|
|
||||||
| \\(?:begin|end)\{[a-z]*\*?\} # \begin{} \end{} style
|
|
||||||
| \\[\\{}$]
|
|
||||||
| [{}]
|
|
||||||
| (?:\n\s*)+ # only treat as math when there's single new line
|
|
||||||
| @@\d+@@ # delimiter similar to the one used internally
|
|
||||||
) ///i
|
|
||||||
|
|
||||||
CODESPAN = ///
|
var CODESPAN, MATHSPLIT;
|
||||||
(^|[^\\]) # match beginning or any previous character other than escape delimiter ('/')
|
|
||||||
(`+) # code span starts
|
|
||||||
([^\n]*?[^`\n]) # code content
|
|
||||||
\2 # code span ends
|
|
||||||
(?!`)
|
|
||||||
///gm
|
|
||||||
|
|
||||||
constructor: (inlineMark, displayMark) ->
|
/*
|
||||||
@inlineMark = inlineMark || "$"
|
\$\$? # normal inline or display delimiter
|
||||||
@displayMark = displayMark || "$$"
|
| \\(?:begin|end)\{[a-z]*\*?\} # \begin{} \end{} style
|
||||||
@math = null
|
| \\[\\{}$]
|
||||||
@blocks = null
|
| [{}]
|
||||||
|
| (?:\n\s*)+ # only treat as math when there's single new line
|
||||||
|
| @@\d+@@ # delimiter similar to the one used internally
|
||||||
|
*/
|
||||||
|
MATHSPLIT = /(\$\$?|\\(?:begin|end)\{[a-z]*\*?\}|\\[\\{}$]|[{}]|(?:\n\s*)+|@@\d+@@)/i;
|
||||||
|
|
||||||
processMath: (start, last, preProcess) ->
|
|
||||||
block = @blocks.slice(start, last + 1).join("").replace(/&/g, "&")
|
|
||||||
.replace(/</g, "<")
|
|
||||||
.replace(/>/g, ">")
|
|
||||||
if MathJax.Hub.Browser.isMSIE
|
|
||||||
block = block.replace /(%[^\n]*)\n/g, "$1<br/>\n"
|
|
||||||
@blocks[i] = "" for i in [start+1..last]
|
|
||||||
@blocks[start] = "@@#{@math.length}@@"
|
|
||||||
block = preProcess(block) if preProcess
|
|
||||||
@math.push block
|
|
||||||
|
|
||||||
removeMath: (text) ->
|
/*
|
||||||
|
(^|[^\\]) # match beginning or any previous character other than escape delimiter ('/')
|
||||||
|
(`+) # code span starts
|
||||||
|
([^\n]*?[^`\n]) # code content
|
||||||
|
\2 # code span ends
|
||||||
|
(?!`)
|
||||||
|
*/
|
||||||
|
CODESPAN = /(^|[^\\])(`+)([^\n]*?[^`\n])\2(?!`)/gm;
|
||||||
|
|
||||||
text = text || ""
|
function MathJaxProcessor(inlineMark, displayMark) {
|
||||||
@math = []
|
this.inlineMark = inlineMark || "$";
|
||||||
start = end = last = null
|
this.displayMark = displayMark || "$$";
|
||||||
braces = 0
|
this.math = null;
|
||||||
|
this.blocks = null;
|
||||||
|
}
|
||||||
|
|
||||||
hasCodeSpans = /`/.test text
|
MathJaxProcessor.prototype.processMath = function(start, last, preProcess) {
|
||||||
if hasCodeSpans
|
var block, i, j, ref, ref1;
|
||||||
text = text.replace(/~/g, "~T").replace CODESPAN, ($0) -> # replace dollar sign in code span temporarily
|
block = this.blocks.slice(start, last + 1).join("").replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
||||||
$0.replace /\$/g, "~D"
|
if (MathJax.Hub.Browser.isMSIE) {
|
||||||
deTilde = (text) ->
|
block = block.replace(/(%[^\n]*)\n/g, "$1<br/>\n");
|
||||||
text.replace /~([TD])/g, ($0, $1) ->
|
}
|
||||||
{T: "~", D: "$"}[$1]
|
for (i = j = ref = start + 1, ref1 = last; ref <= ref1 ? j <= ref1 : j >= ref1; i = ref <= ref1 ? ++j : --j) {
|
||||||
else
|
this.blocks[i] = "";
|
||||||
deTilde = (text) -> text
|
}
|
||||||
|
this.blocks[start] = "@@" + this.math.length + "@@";
|
||||||
|
if (preProcess) {
|
||||||
|
block = preProcess(block);
|
||||||
|
}
|
||||||
|
return this.math.push(block);
|
||||||
|
};
|
||||||
|
|
||||||
@blocks = _split(text.replace(/\r\n?/g, "\n"), MATHSPLIT)
|
MathJaxProcessor.prototype.removeMath = function(text) {
|
||||||
|
var block, braces, current, deTilde, end, hasCodeSpans, j, last, ref, start;
|
||||||
|
text = text || "";
|
||||||
|
this.math = [];
|
||||||
|
start = end = last = null;
|
||||||
|
braces = 0;
|
||||||
|
hasCodeSpans = /`/.test(text);
|
||||||
|
if (hasCodeSpans) {
|
||||||
|
|
||||||
for current in [1...@blocks.length] by 2
|
/*
|
||||||
block = @blocks[current]
|
replace dollar sign in code span temporarily
|
||||||
if block.charAt(0) == "@"
|
*/
|
||||||
@blocks[current] = "@@#{@math.length}@@"
|
text = text.replace(/~/g, "~T").replace(CODESPAN, function($0) {
|
||||||
@math.push block
|
return $0.replace(/\$/g, "~D");
|
||||||
else if start
|
});
|
||||||
if block == end
|
deTilde = function(text) {
|
||||||
if braces
|
return text.replace(/~([TD])/g, function($0, $1) {
|
||||||
last = current
|
return {
|
||||||
else
|
T: "~",
|
||||||
@processMath(start, current, deTilde)
|
D: "$"
|
||||||
start = end = last = null
|
}[$1];
|
||||||
else if block.match /\n.*\n/
|
});
|
||||||
if last
|
};
|
||||||
current = last
|
} else {
|
||||||
@processMath(start, current, deTilde)
|
deTilde = function(text) {
|
||||||
start = end = last = null
|
return text;
|
||||||
braces = 0
|
};
|
||||||
else if block == "{"
|
}
|
||||||
++braces
|
this.blocks = _split(text.replace(/\r\n?/g, "\n"), MATHSPLIT);
|
||||||
else if block == "}" and braces
|
for (current = j = 1, ref = this.blocks.length; j < ref; current = j += 2) {
|
||||||
--braces
|
block = this.blocks[current];
|
||||||
else
|
if (block.charAt(0) === "@") {
|
||||||
if block == @inlineMark or block == @displayMark
|
this.blocks[current] = "@@" + this.math.length + "@@";
|
||||||
start = current
|
this.math.push(block);
|
||||||
end = block
|
} else if (start) {
|
||||||
braces = 0
|
if (block === end) {
|
||||||
else if block.substr(1, 5) == "begin"
|
if (braces) {
|
||||||
start = current
|
last = current;
|
||||||
end = "\\end" + block.substr(6)
|
} else {
|
||||||
braces = 0
|
this.processMath(start, current, deTilde);
|
||||||
|
start = end = last = null;
|
||||||
|
}
|
||||||
|
} else if (block.match(/\n.*\n/)) {
|
||||||
|
if (last) {
|
||||||
|
current = last;
|
||||||
|
this.processMath(start, current, deTilde);
|
||||||
|
}
|
||||||
|
start = end = last = null;
|
||||||
|
braces = 0;
|
||||||
|
} else if (block === "{") {
|
||||||
|
++braces;
|
||||||
|
} else if (block === "}" && braces) {
|
||||||
|
--braces;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (block === this.inlineMark || block === this.displayMark) {
|
||||||
|
start = current;
|
||||||
|
end = block;
|
||||||
|
braces = 0;
|
||||||
|
} else if (block.substr(1, 5) === "begin") {
|
||||||
|
start = current;
|
||||||
|
end = "\\end" + block.substr(6);
|
||||||
|
braces = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (last) {
|
||||||
|
this.processMath(start, last, deTilde);
|
||||||
|
start = end = last = null;
|
||||||
|
}
|
||||||
|
return deTilde(this.blocks.join(""));
|
||||||
|
};
|
||||||
|
|
||||||
if last
|
MathJaxProcessor.removeMathWrapper = function(_this) {
|
||||||
@processMath(start, last, deTilde)
|
return function(text) {
|
||||||
start = end = last = null
|
return _this.removeMath(text);
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
deTilde(@blocks.join(""))
|
MathJaxProcessor.prototype.replaceMath = function(text) {
|
||||||
|
text = text.replace(/@@(\d+)@@/g, (function(_this) {
|
||||||
|
return function($0, $1) {
|
||||||
|
return _this.math[$1];
|
||||||
|
};
|
||||||
|
})(this));
|
||||||
|
this.math = null;
|
||||||
|
return text;
|
||||||
|
};
|
||||||
|
|
||||||
@removeMathWrapper: (_this) ->
|
MathJaxProcessor.replaceMathWrapper = function(_this) {
|
||||||
(text) -> _this.removeMath(text)
|
return function(text) {
|
||||||
|
return _this.replaceMath(text);
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
replaceMath: (text) ->
|
return MathJaxProcessor;
|
||||||
text = text.replace /@@(\d+)@@/g, ($0, $1) => @math[$1]
|
|
||||||
@math = null
|
|
||||||
text
|
|
||||||
|
|
||||||
@replaceMathWrapper: (_this) ->
|
})();
|
||||||
(text) -> _this.replaceMath(text)
|
|
||||||
|
|
||||||
if Markdown?
|
if (typeof Markdown !== "undefined" && Markdown !== null) {
|
||||||
|
Markdown.getMathCompatibleConverter = function(postProcessor) {
|
||||||
|
var converter, processor;
|
||||||
|
postProcessor || (postProcessor = (function(text) {
|
||||||
|
return text;
|
||||||
|
}));
|
||||||
|
converter = Markdown.getSanitizingConverter();
|
||||||
|
if (typeof MathJax !== "undefined" && MathJax !== null) {
|
||||||
|
processor = new MathJaxProcessor();
|
||||||
|
converter.hooks.chain("preConversion", MathJaxProcessor.removeMathWrapper(processor));
|
||||||
|
converter.hooks.chain("postConversion", function(text) {
|
||||||
|
return postProcessor(MathJaxProcessor.replaceMathWrapper(processor)(text));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return converter;
|
||||||
|
};
|
||||||
|
Markdown.makeWmdEditor = function(elem, appended_id, imageUploadUrl, postProcessor) {
|
||||||
|
var $elem, $wmdPanel, $wmdPreviewContainer, _append, ajaxFileUpload, converter, delayRenderer, editor, imageUploadHandler, initialText, wmdInputId;
|
||||||
|
$elem = $(elem);
|
||||||
|
if (!$elem.length) {
|
||||||
|
console.log("warning: elem for makeWmdEditor doesn't exist");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!$elem.find(".wmd-panel").length) {
|
||||||
|
initialText = $elem.html();
|
||||||
|
$elem.empty();
|
||||||
|
_append = appended_id || "";
|
||||||
|
wmdInputId = "wmd-input" + _append;
|
||||||
|
$wmdPreviewContainer = $("<div>").addClass("wmd-preview-container").attr("role", "region").attr("aria-label", gettext("HTML preview of post")).append($("<div>").addClass("wmd-preview-label").text(gettext("Preview"))).append($("<div>").attr("id", "wmd-preview" + _append).addClass("wmd-panel wmd-preview"));
|
||||||
|
$wmdPanel = $("<div>").addClass("wmd-panel").append($("<div>").attr("id", "wmd-button-bar" + _append)).append($("<label>").addClass("sr").attr("for", wmdInputId).text(gettext("Your question or idea (required)"))).append($("<textarea>").addClass("wmd-input").attr("id", wmdInputId).html(initialText)).append($wmdPreviewContainer); // xss-lint: disable=javascript-jquery-html
|
||||||
|
$elem.append($wmdPanel);
|
||||||
|
}
|
||||||
|
converter = Markdown.getMathCompatibleConverter(postProcessor);
|
||||||
|
ajaxFileUpload = function(imageUploadUrl, input, startUploadHandler) {
|
||||||
|
$("#loading").ajaxStart(function() {
|
||||||
|
return $(this).show();
|
||||||
|
}).ajaxComplete(function() {
|
||||||
|
return $(this).hide();
|
||||||
|
});
|
||||||
|
$("#upload").ajaxStart(function() {
|
||||||
|
return $(this).hide();
|
||||||
|
}).ajaxComplete(function() {
|
||||||
|
return $(this).show();
|
||||||
|
});
|
||||||
|
return $.ajaxFileUpload({
|
||||||
|
url: imageUploadUrl,
|
||||||
|
secureuri: false,
|
||||||
|
fileElementId: 'file-upload',
|
||||||
|
dataType: 'json',
|
||||||
|
success: function(data, status) {
|
||||||
|
var error, fileURL;
|
||||||
|
fileURL = data['result']['file_url'];
|
||||||
|
error = data['result']['error'];
|
||||||
|
if (error !== '') {
|
||||||
|
alert(error);
|
||||||
|
if (startUploadHandler) {
|
||||||
|
$('#file-upload').unbind('change').change(startUploadHandler);
|
||||||
|
}
|
||||||
|
return console.log(error);
|
||||||
|
} else {
|
||||||
|
return $(input).attr('value', fileURL);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
error: function(data, status, e) {
|
||||||
|
alert(e);
|
||||||
|
if (startUploadHandler) {
|
||||||
|
return $('#file-upload').unbind('change').change(startUploadHandler);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
imageUploadHandler = function(elem, input) {
|
||||||
|
return ajaxFileUpload(imageUploadUrl, input, imageUploadHandler);
|
||||||
|
};
|
||||||
|
editor = new Markdown.Editor(converter,
|
||||||
|
appended_id, // idPostfix
|
||||||
|
null, // help handler
|
||||||
|
imageUploadHandler);
|
||||||
|
delayRenderer = new MathJaxDelayRenderer();
|
||||||
|
editor.hooks.chain("onPreviewPush", function(text, previewSet) {
|
||||||
|
return delayRenderer.render({
|
||||||
|
text: text,
|
||||||
|
previewSetter: previewSet
|
||||||
|
});
|
||||||
|
});
|
||||||
|
editor.run();
|
||||||
|
return editor;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
Markdown.getMathCompatibleConverter = (postProcessor) ->
|
}).call(this);
|
||||||
postProcessor ||= ((text) -> text)
|
|
||||||
converter = Markdown.getSanitizingConverter()
|
|
||||||
if MathJax?
|
|
||||||
processor = new MathJaxProcessor()
|
|
||||||
converter.hooks.chain "preConversion", MathJaxProcessor.removeMathWrapper(processor)
|
|
||||||
converter.hooks.chain "postConversion", (text) ->
|
|
||||||
postProcessor(MathJaxProcessor.replaceMathWrapper(processor)(text))
|
|
||||||
converter
|
|
||||||
|
|
||||||
Markdown.makeWmdEditor = (elem, appended_id, imageUploadUrl, postProcessor) ->
|
|
||||||
$elem = $(elem)
|
|
||||||
if not $elem.length
|
|
||||||
console.log "warning: elem for makeWmdEditor doesn't exist"
|
|
||||||
return
|
|
||||||
if not $elem.find(".wmd-panel").length
|
|
||||||
initialText = $elem.html()
|
|
||||||
$elem.empty()
|
|
||||||
_append = appended_id || ""
|
|
||||||
wmdInputId = "wmd-input#{_append}"
|
|
||||||
$wmdPreviewContainer = $("<div>").addClass("wmd-preview-container")
|
|
||||||
.attr("role", "region")
|
|
||||||
.attr("aria-label", gettext("HTML preview of post"))
|
|
||||||
.append($("<div>").addClass("wmd-preview-label").text(gettext("Preview")))
|
|
||||||
.append($("<div>").attr("id", "wmd-preview#{_append}").addClass("wmd-panel wmd-preview"))
|
|
||||||
$wmdPanel = $("<div>").addClass("wmd-panel")
|
|
||||||
.append($("<div>").attr("id", "wmd-button-bar#{_append}"))
|
|
||||||
.append($("<label>").addClass("sr").attr("for", wmdInputId).text(gettext("Your question or idea (required)")))
|
|
||||||
.append($("<textarea>").addClass("wmd-input").attr("id", wmdInputId).html(initialText))
|
|
||||||
.append($wmdPreviewContainer)
|
|
||||||
$elem.append($wmdPanel)
|
|
||||||
|
|
||||||
converter = Markdown.getMathCompatibleConverter(postProcessor)
|
|
||||||
|
|
||||||
ajaxFileUpload = (imageUploadUrl, input, startUploadHandler) ->
|
|
||||||
$("#loading").ajaxStart(-> $(this).show()).ajaxComplete(-> $(this).hide())
|
|
||||||
$("#upload").ajaxStart(-> $(this).hide()).ajaxComplete(-> $(this).show())
|
|
||||||
$.ajaxFileUpload
|
|
||||||
url: imageUploadUrl
|
|
||||||
secureuri: false
|
|
||||||
fileElementId: 'file-upload'
|
|
||||||
dataType: 'json'
|
|
||||||
success: (data, status) ->
|
|
||||||
fileURL = data['result']['file_url']
|
|
||||||
error = data['result']['error']
|
|
||||||
if error != ''
|
|
||||||
alert error
|
|
||||||
if startUploadHandler
|
|
||||||
$('#file-upload').unbind('change').change(startUploadHandler)
|
|
||||||
console.log error
|
|
||||||
else
|
|
||||||
$(input).attr('value', fileURL)
|
|
||||||
error: (data, status, e) ->
|
|
||||||
alert(e)
|
|
||||||
if startUploadHandler
|
|
||||||
$('#file-upload').unbind('change').change(startUploadHandler)
|
|
||||||
|
|
||||||
imageUploadHandler = (elem, input) ->
|
|
||||||
ajaxFileUpload(imageUploadUrl, input, imageUploadHandler)
|
|
||||||
|
|
||||||
editor = new Markdown.Editor(
|
|
||||||
converter,
|
|
||||||
appended_id, # idPostfix
|
|
||||||
null, # help handler
|
|
||||||
imageUploadHandler
|
|
||||||
)
|
|
||||||
delayRenderer = new MathJaxDelayRenderer()
|
|
||||||
editor.hooks.chain "onPreviewPush", (text, previewSet) ->
|
|
||||||
delayRenderer.render
|
|
||||||
text: text
|
|
||||||
previewSetter: previewSet
|
|
||||||
editor.run()
|
|
||||||
editor
|
|
||||||
|
|||||||
@@ -1,10 +1,23 @@
|
|||||||
class @FeedbackForm
|
// Once generated by CoffeeScript 1.9.3, but now lives as pure JS
|
||||||
constructor: ->
|
/* eslint-disable */
|
||||||
$('#feedback_button').click ->
|
(function() {
|
||||||
data =
|
this.FeedbackForm = (function() {
|
||||||
subject: $('#feedback_subject').val()
|
function FeedbackForm() {
|
||||||
message: $('#feedback_message').val()
|
$('#feedback_button').click(function() {
|
||||||
url: window.location.href
|
var data;
|
||||||
$.postWithPrefix '/send_feedback', data, ->
|
data = {
|
||||||
$('#feedback_div').html 'Feedback submitted. Thank you'
|
subject: $('#feedback_subject').val(),
|
||||||
,'json'
|
message: $('#feedback_message').val(),
|
||||||
|
url: window.location.href
|
||||||
|
};
|
||||||
|
return $.postWithPrefix('/send_feedback', data, function() {
|
||||||
|
return $('#feedback_div').html('Feedback submitted. Thank you'); // xss-lint: disable=javascript-jquery-html
|
||||||
|
}, 'json');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return FeedbackForm;
|
||||||
|
|
||||||
|
})();
|
||||||
|
|
||||||
|
}).call(this);
|
||||||
|
|||||||
@@ -1,36 +1,68 @@
|
|||||||
class @Histogram
|
// Once generated by CoffeeScript 1.9.3, but now lives as pure JS
|
||||||
constructor: (@id, @rawData) ->
|
/* eslint-disable */
|
||||||
@xTicks = []
|
(function() {
|
||||||
@yTicks = []
|
this.Histogram = (function() {
|
||||||
@data = []
|
function Histogram(id, rawData) {
|
||||||
@calculate()
|
this.id = id;
|
||||||
@render()
|
this.rawData = rawData;
|
||||||
|
this.xTicks = [];
|
||||||
|
this.yTicks = [];
|
||||||
|
this.data = [];
|
||||||
|
this.calculate();
|
||||||
|
this.render();
|
||||||
|
}
|
||||||
|
|
||||||
calculate: ->
|
Histogram.prototype.calculate = function() {
|
||||||
for [score, count] in @rawData
|
var count, i, len, log_count, ref, ref1, results, score;
|
||||||
continue if score == null
|
ref = this.rawData;
|
||||||
log_count = Math.log(count + 1)
|
results = [];
|
||||||
@data.push [score, log_count]
|
for (i = 0, len = ref.length; i < len; i++) {
|
||||||
@xTicks.push [score, score.toString()]
|
ref1 = ref[i], score = ref1[0], count = ref1[1];
|
||||||
@yTicks.push [log_count, count.toString()]
|
if (score === null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
log_count = Math.log(count + 1);
|
||||||
|
this.data.push([score, log_count]);
|
||||||
|
this.xTicks.push([score, score.toString()]);
|
||||||
|
results.push(this.yTicks.push([log_count, count.toString()]));
|
||||||
|
}
|
||||||
|
return results;
|
||||||
|
};
|
||||||
|
|
||||||
render: ->
|
Histogram.prototype.render = function() {
|
||||||
$.plot $("#histogram_#{@id}"), [
|
return $.plot($("#histogram_" + this.id), [
|
||||||
data: @data
|
{
|
||||||
bars:
|
data: this.data,
|
||||||
show: true
|
bars: {
|
||||||
align: 'center'
|
show: true,
|
||||||
lineWidth: 0
|
align: 'center',
|
||||||
fill: 1.0
|
lineWidth: 0,
|
||||||
color: "#b72121"
|
fill: 1.0
|
||||||
],
|
},
|
||||||
xaxis:
|
color: "#b72121"
|
||||||
min: -1
|
}
|
||||||
max: Math.max.apply Math, $.map(@xTicks, (data) -> data[0] + 1)
|
], {
|
||||||
ticks: @xTicks
|
xaxis: {
|
||||||
tickLength: 0
|
min: -1,
|
||||||
yaxis:
|
max: Math.max.apply(Math, $.map(this.xTicks, function(data) {
|
||||||
min: 0.0
|
return data[0] + 1;
|
||||||
max: Math.max.apply Math, $.map(@yTicks, (data) -> data[0] * 1.1)
|
})),
|
||||||
ticks: @yTicks
|
ticks: this.xTicks,
|
||||||
labelWidth: 50
|
tickLength: 0
|
||||||
|
},
|
||||||
|
yaxis: {
|
||||||
|
min: 0.0,
|
||||||
|
max: Math.max.apply(Math, $.map(this.yTicks, function(data) {
|
||||||
|
return data[0] * 1.1;
|
||||||
|
})),
|
||||||
|
ticks: this.yTicks,
|
||||||
|
labelWidth: 50
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
return Histogram;
|
||||||
|
|
||||||
|
})();
|
||||||
|
|
||||||
|
}).call(this);
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ The instructor dashboard is broken into sections.
|
|||||||
Only one section is visible at a time,
|
Only one section is visible at a time,
|
||||||
and is responsible for its own functionality.
|
and is responsible for its own functionality.
|
||||||
|
|
||||||
NOTE: plantTimeout (which is just setTimeout from util.coffee)
|
NOTE: plantTimeout (which is just setTimeout from util.js)
|
||||||
is used frequently in the instructor dashboard to isolate
|
is used frequently in the instructor dashboard to isolate
|
||||||
failures. If one piece of code under a plantTimeout fails
|
failures. If one piece of code under a plantTimeout fails
|
||||||
then it will not crash the rest of the dashboard.
|
then it will not crash the rest of the dashboard.
|
||||||
@@ -19,7 +19,7 @@ NOTE: Server endpoints in the dashboard are stored in
|
|||||||
The urls are rendered there by a template.
|
The urls are rendered there by a template.
|
||||||
|
|
||||||
NOTE: For an example of what a section object should look like
|
NOTE: For an example of what a section object should look like
|
||||||
see course_info.coffee
|
see course_info.js
|
||||||
|
|
||||||
imports from other modules
|
imports from other modules
|
||||||
wrap in (-> ... apply) to defer evaluation
|
wrap in (-> ... apply) to defer evaluation
|
||||||
|
|||||||
@@ -1,38 +1,64 @@
|
|||||||
AjaxPrefix.addAjaxPrefix(jQuery, -> $("meta[name='path_prefix']").attr('content'))
|
// Once generated by CoffeeScript 1.9.3, but now lives as pure JS
|
||||||
|
/* eslint-disable */
|
||||||
|
(function() {
|
||||||
|
AjaxPrefix.addAjaxPrefix(jQuery, function() {
|
||||||
|
return $("meta[name='path_prefix']").attr('content');
|
||||||
|
});
|
||||||
|
|
||||||
$ ->
|
$(function() {
|
||||||
$.ajaxSetup
|
$.ajaxSetup({
|
||||||
headers : { 'X-CSRFToken': $.cookie 'csrftoken' }
|
headers: {
|
||||||
dataType: 'json'
|
'X-CSRFToken': $.cookie('csrftoken')
|
||||||
|
},
|
||||||
|
dataType: 'json'
|
||||||
|
});
|
||||||
|
window.onTouchBasedDevice = function() {
|
||||||
|
return navigator.userAgent.match(/iPhone|iPod|iPad|Android/i);
|
||||||
|
};
|
||||||
|
if (onTouchBasedDevice()) {
|
||||||
|
$('body').addClass('touch-based-device');
|
||||||
|
}
|
||||||
|
|
||||||
window.onTouchBasedDevice = ->
|
/*
|
||||||
navigator.userAgent.match /iPhone|iPod|iPad|Android/i
|
$("a[rel*=leanModal]").leanModal()
|
||||||
|
*/
|
||||||
|
$('#csrfmiddlewaretoken').attr('value', $.cookie('csrftoken'));
|
||||||
|
new Calculator;
|
||||||
|
new FeedbackForm;
|
||||||
|
if ($('body').hasClass('courseware')) {
|
||||||
|
Courseware.start();
|
||||||
|
}
|
||||||
|
window.postJSON = function(url, data, callback) {
|
||||||
|
return $.postWithPrefix(url, data, callback);
|
||||||
|
};
|
||||||
|
$('#login').click(function() {
|
||||||
|
$('#login_form input[name="email"]').focus();
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
$('#signup').click(function() {
|
||||||
|
$('#signup-modal input[name="email"]').focus();
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
|
||||||
$('body').addClass 'touch-based-device' if onTouchBasedDevice()
|
/*
|
||||||
|
fix for ie
|
||||||
|
*/
|
||||||
|
if (!Array.prototype.indexOf) {
|
||||||
|
return Array.prototype.indexOf = function(obj, start) {
|
||||||
|
var ele, i, j, len, ref;
|
||||||
|
if (start == null) {
|
||||||
|
start = 0;
|
||||||
|
}
|
||||||
|
ref = this.slice(start);
|
||||||
|
for (i = j = 0, len = ref.length; j < len; i = ++j) {
|
||||||
|
ele = ref[i];
|
||||||
|
if (ele === obj) {
|
||||||
|
return i + start;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
# $("a[rel*=leanModal]").leanModal()
|
}).call(this);
|
||||||
$('#csrfmiddlewaretoken').attr 'value', $.cookie('csrftoken')
|
|
||||||
|
|
||||||
new Calculator
|
|
||||||
new FeedbackForm
|
|
||||||
if $('body').hasClass('courseware')
|
|
||||||
Courseware.start()
|
|
||||||
|
|
||||||
window.postJSON = (url, data, callback) ->
|
|
||||||
$.postWithPrefix url, data, callback
|
|
||||||
|
|
||||||
$('#login').click ->
|
|
||||||
$('#login_form input[name="email"]').focus()
|
|
||||||
false
|
|
||||||
|
|
||||||
$('#signup').click ->
|
|
||||||
$('#signup-modal input[name="email"]').focus()
|
|
||||||
false
|
|
||||||
|
|
||||||
# fix for ie
|
|
||||||
if !Array::indexOf
|
|
||||||
Array::indexOf = (obj, start = 0) ->
|
|
||||||
for ele, i in this[start..]
|
|
||||||
if ele is obj
|
|
||||||
return i + start
|
|
||||||
return -1
|
|
||||||
|
|||||||
@@ -1,21 +1,37 @@
|
|||||||
$ ->
|
// Once generated by CoffeeScript 1.9.3, but now lives as pure JS
|
||||||
if window.navigator.appName is "Microsoft Internet Explorer"
|
/* eslint-disable */
|
||||||
isMPInstalled = (boolean) ->
|
(function() {
|
||||||
# check if MathPlayer is installed
|
$(function() {
|
||||||
# (from http://www.dessci.com/en/products/mathplayer/check.htm)
|
var isMPInstalled;
|
||||||
try
|
if (window.navigator.appName === "Microsoft Internet Explorer") {
|
||||||
oMP = new ActiveXObject("MathPlayer.Factory.1")
|
isMPInstalled = function(boolean) {
|
||||||
true
|
var e, oMP;
|
||||||
catch e
|
/*
|
||||||
false
|
check if MathPlayer is installed
|
||||||
|
(from http://www.dessci.com/en/products/mathplayer/check.htm)
|
||||||
|
*/
|
||||||
|
try {
|
||||||
|
oMP = new ActiveXObject("MathPlayer.Factory.1");
|
||||||
|
return true;
|
||||||
|
} catch (_error) {
|
||||||
|
e = _error;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
# detect if there is mathjax on the page
|
/*
|
||||||
# if not, set 'aria-hidden' to 'true'
|
detect if there is mathjax on the page
|
||||||
if MathJax? and not isMPInstalled()
|
if not, set 'aria-hidden' to 'true'
|
||||||
$("#mathjax-accessibility-message").attr("aria-hidden", "false")
|
*/
|
||||||
|
if ((typeof MathJax !== "undefined" && MathJax !== null) && !isMPInstalled()) {
|
||||||
|
$("#mathjax-accessibility-message").attr("aria-hidden", "false");
|
||||||
|
}
|
||||||
|
if ((typeof MathJax !== "undefined" && MathJax !== null) && $("#mathplayer-browser-message").length > 0) {
|
||||||
|
return $("#mathplayer-browser-message").attr("aria-hidden", "false");
|
||||||
|
} else {
|
||||||
|
return $("#mathjax-accessibility-message").attr("aria-hidden", "true");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
if MathJax? and $("#mathplayer-browser-message").length > 0
|
}).call(this);
|
||||||
$("#mathplayer-browser-message").attr("aria-hidden", "false")
|
|
||||||
|
|
||||||
else
|
|
||||||
$("#mathjax-accessibility-message").attr("aria-hidden", "true")
|
|
||||||
|
|||||||
@@ -1,73 +1,109 @@
|
|||||||
getTime = ->
|
// Once generated by CoffeeScript 1.9.3, but now lives as pure JS
|
||||||
new Date().getTime()
|
/* eslint-disable */
|
||||||
|
// TODO: Examine all of the xss-lint exceptions (https://openedx.atlassian.net/browse/PLAT-2084)
|
||||||
|
(function() {
|
||||||
|
var getTime;
|
||||||
|
|
||||||
class @MathJaxDelayRenderer
|
getTime = function() {
|
||||||
|
return new Date().getTime();
|
||||||
|
};
|
||||||
|
|
||||||
maxDelay: 3000
|
this.MathJaxDelayRenderer = (function() {
|
||||||
mathjaxRunning: false
|
var bufferId, numBuffers;
|
||||||
elapsedTime: 0
|
|
||||||
mathjaxDelay: 0
|
|
||||||
mathjaxTimeout: undefined
|
|
||||||
bufferId = "mathjax_delay_buffer"
|
|
||||||
numBuffers = 0
|
|
||||||
|
|
||||||
constructor: (params) ->
|
MathJaxDelayRenderer.prototype.maxDelay = 3000;
|
||||||
params = params || {}
|
|
||||||
@maxDelay = params["maxDelay"] || @maxDelay
|
|
||||||
@bufferId = params["bufferId"] || (bufferId + numBuffers)
|
|
||||||
numBuffers += 1
|
|
||||||
@$buffer = $("<div>").attr("id", @bufferId).css("display", "none").appendTo($("body"))
|
|
||||||
|
|
||||||
# render: (params) ->
|
MathJaxDelayRenderer.prototype.mathjaxRunning = false;
|
||||||
# params:
|
|
||||||
# elem: jquery element to be rendered
|
|
||||||
# text: text to be rendered & put into the element;
|
|
||||||
# if blank, then just render the current text in the element
|
|
||||||
# preprocessor: pre-process the text before rendering using MathJax
|
|
||||||
# if text is blank, it will pre-process the html in the element
|
|
||||||
# previewSetter: if provided, will pass text back to it instead of
|
|
||||||
# directly setting the element
|
|
||||||
|
|
||||||
render: (params) ->
|
MathJaxDelayRenderer.prototype.elapsedTime = 0;
|
||||||
|
|
||||||
elem = params["element"]
|
MathJaxDelayRenderer.prototype.mathjaxDelay = 0;
|
||||||
previewSetter = params["previewSetter"]
|
|
||||||
text = params["text"]
|
|
||||||
if not text?
|
|
||||||
text = $(elem).html()
|
|
||||||
preprocessor = params["preprocessor"]
|
|
||||||
|
|
||||||
if params["delay"] == false
|
MathJaxDelayRenderer.prototype.mathjaxTimeout = void 0;
|
||||||
if preprocessor?
|
|
||||||
text = preprocessor(text)
|
bufferId = "mathjax_delay_buffer";
|
||||||
$(elem).html(text)
|
|
||||||
MathJax.Hub.Queue ["Typeset", MathJax.Hub, $(elem).attr("id")]
|
numBuffers = 0;
|
||||||
else
|
|
||||||
if @mathjaxTimeout
|
function MathJaxDelayRenderer(params) {
|
||||||
window.clearTimeout(@mathjaxTimeout)
|
params = params || {};
|
||||||
@mathjaxTimeout = undefined
|
this.maxDelay = params["maxDelay"] || this.maxDelay;
|
||||||
delay = Math.min @elapsedTime + @mathjaxDelay, @maxDelay
|
this.bufferId = params["bufferId"] || (bufferId + numBuffers);
|
||||||
|
numBuffers += 1;
|
||||||
renderer = =>
|
this.$buffer = $("<div>").attr("id", this.bufferId).css("display", "none").appendTo($("body")); // xss-lint: disable=javascript-jquery-insert-into-target
|
||||||
if @mathjaxRunning
|
}
|
||||||
return
|
|
||||||
prevTime = getTime()
|
|
||||||
if preprocessor?
|
/*
|
||||||
text = preprocessor(text)
|
render: (params) ->
|
||||||
@$buffer.html(text)
|
params:
|
||||||
curTime = getTime()
|
elem: jquery element to be rendered
|
||||||
@elapsedTime = curTime - prevTime
|
text: text to be rendered & put into the element;
|
||||||
if MathJax?
|
if blank, then just render the current text in the element
|
||||||
prevTime = getTime()
|
preprocessor: pre-process the text before rendering using MathJax
|
||||||
@mathjaxRunning = true
|
if text is blank, it will pre-process the html in the element
|
||||||
MathJax.Hub.Queue ["Typeset", MathJax.Hub, @$buffer.attr("id")], =>
|
previewSetter: if provided, will pass text back to it instead of
|
||||||
@mathjaxRunning = false
|
directly setting the element
|
||||||
curTime = getTime()
|
*/
|
||||||
@mathjaxDelay = curTime - prevTime
|
|
||||||
if previewSetter
|
MathJaxDelayRenderer.prototype.render = function(params) {
|
||||||
previewSetter($(@$buffer).html())
|
var delay, elem, preprocessor, previewSetter, renderer, text;
|
||||||
else
|
elem = params["element"];
|
||||||
$(elem).html($(@$buffer).html())
|
previewSetter = params["previewSetter"];
|
||||||
else
|
text = params["text"];
|
||||||
@mathjaxDelay = 0
|
if (text == null) {
|
||||||
@mathjaxTimeout = window.setTimeout(renderer, delay)
|
text = $(elem).html();
|
||||||
|
}
|
||||||
|
preprocessor = params["preprocessor"];
|
||||||
|
if (params["delay"] === false) {
|
||||||
|
if (preprocessor != null) {
|
||||||
|
text = preprocessor(text);
|
||||||
|
}
|
||||||
|
$(elem).html(text); // xss-lint: disable=javascript-jquery-html
|
||||||
|
return MathJax.Hub.Queue(["Typeset", MathJax.Hub, $(elem).attr("id")]);
|
||||||
|
} else {
|
||||||
|
if (this.mathjaxTimeout) {
|
||||||
|
window.clearTimeout(this.mathjaxTimeout);
|
||||||
|
this.mathjaxTimeout = void 0;
|
||||||
|
}
|
||||||
|
delay = Math.min(this.elapsedTime + this.mathjaxDelay, this.maxDelay);
|
||||||
|
renderer = (function(_this) {
|
||||||
|
return function() {
|
||||||
|
var curTime, prevTime;
|
||||||
|
if (_this.mathjaxRunning) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
prevTime = getTime();
|
||||||
|
if (preprocessor != null) {
|
||||||
|
text = preprocessor(text);
|
||||||
|
}
|
||||||
|
_this.$buffer.html(text); // xss-lint: disable=javascript-jquery-html
|
||||||
|
curTime = getTime();
|
||||||
|
_this.elapsedTime = curTime - prevTime;
|
||||||
|
if (typeof MathJax !== "undefined" && MathJax !== null) {
|
||||||
|
prevTime = getTime();
|
||||||
|
_this.mathjaxRunning = true;
|
||||||
|
return MathJax.Hub.Queue(["Typeset", MathJax.Hub, _this.$buffer.attr("id")], function() {
|
||||||
|
_this.mathjaxRunning = false;
|
||||||
|
curTime = getTime();
|
||||||
|
_this.mathjaxDelay = curTime - prevTime;
|
||||||
|
if (previewSetter) {
|
||||||
|
return previewSetter($(_this.$buffer).html());
|
||||||
|
} else {
|
||||||
|
return $(elem).html($(_this.$buffer).html()); // xss-lint: disable=javascript-jquery-html
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
return _this.mathjaxDelay = 0;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
})(this);
|
||||||
|
return this.mathjaxTimeout = window.setTimeout(renderer, delay);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return MathJaxDelayRenderer;
|
||||||
|
|
||||||
|
})();
|
||||||
|
|
||||||
|
}).call(this);
|
||||||
|
|||||||
@@ -1,23 +1,52 @@
|
|||||||
class @Tab
|
// Once generated by CoffeeScript 1.9.3, but now lives as pure JS
|
||||||
constructor: (@id, @items) ->
|
/* eslint-disable */
|
||||||
@el = $("#tab_#{id}")
|
// TODO: Examine all of the xss-lint exceptions (https://openedx.atlassian.net/browse/PLAT-2084)
|
||||||
@render()
|
(function() {
|
||||||
|
var bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; };
|
||||||
|
|
||||||
$: (selector) ->
|
this.Tab = (function() {
|
||||||
$(selector, @el)
|
function Tab(id1, items) {
|
||||||
|
this.id = id1;
|
||||||
|
this.items = items;
|
||||||
|
this.onShow = bind(this.onShow, this);
|
||||||
|
this.el = $("#tab_" + id);
|
||||||
|
this.render();
|
||||||
|
}
|
||||||
|
|
||||||
render: ->
|
Tab.prototype.$ = function(selector) {
|
||||||
$.each @items, (index, item) =>
|
return $(selector, this.el);
|
||||||
tab = $('<a>').attr(href: "##{@tabId(index)}").html(item.title)
|
};
|
||||||
@$('.navigation').append($('<li>').append(tab))
|
|
||||||
@el.append($('<section>').attr(id: @tabId(index)))
|
|
||||||
@el.tabs
|
|
||||||
show: @onShow
|
|
||||||
|
|
||||||
onShow: (element, ui) =>
|
Tab.prototype.render = function() {
|
||||||
@$('section.ui-tabs-hide').html('')
|
$.each(this.items, (function(_this) {
|
||||||
@$("##{@tabId(ui.index)}").html(@items[ui.index]['content'])
|
return function(index, item) {
|
||||||
@el.trigger 'contentChanged'
|
var tab;
|
||||||
|
tab = $('<a>').attr({
|
||||||
|
href: "#" + (_this.tabId(index))
|
||||||
|
}).html(item.title); // xss-lint: disable=javascript-jquery-html
|
||||||
|
_this.$('.navigation').append($('<li>').append(tab)); // xss-lint: disable=javascript-jquery-append
|
||||||
|
return _this.el.append($('<section>').attr({
|
||||||
|
id: _this.tabId(index)
|
||||||
|
}));
|
||||||
|
};
|
||||||
|
})(this));
|
||||||
|
return this.el.tabs({
|
||||||
|
show: this.onShow
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
tabId: (index) ->
|
Tab.prototype.onShow = function(element, ui) {
|
||||||
"tab-#{@id}-#{index}"
|
this.$('section.ui-tabs-hide').html('');
|
||||||
|
this.$("#" + (this.tabId(ui.index))).html(this.items[ui.index]['content']); // xss-lint: disable=javascript-jquery-html
|
||||||
|
return this.el.trigger('contentChanged');
|
||||||
|
};
|
||||||
|
|
||||||
|
Tab.prototype.tabId = function(index) {
|
||||||
|
return "tab-" + this.id + "-" + index;
|
||||||
|
};
|
||||||
|
|
||||||
|
return Tab;
|
||||||
|
|
||||||
|
})();
|
||||||
|
|
||||||
|
}).call(this);
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
// This file is intentionally blank as it was removed because it was not
|
// This file is intentionally blank as it was removed because it was no
|
||||||
// longer necessary, but the pipeline requires it for whatever reason.
|
// longer necessary, but the pipeline requires it for whatever reason.
|
||||||
// Until the pipeline issue is resolved this file is here. It shouldn't
|
// Until the pipeline issue is resolved this file is here. It shouldn't
|
||||||
// conflict with anything.
|
// conflict with anything.
|
||||||
var nothingtoseehere;
|
var nothingtoseehere;
|
||||||
@@ -1,97 +1,168 @@
|
|||||||
class StudentNotes
|
// Once generated by CoffeeScript 1.9.3, but now lives as pure JS
|
||||||
_debug: false
|
/* eslint-disable */
|
||||||
|
(function() {
|
||||||
|
var StudentNotes,
|
||||||
|
bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; };
|
||||||
|
|
||||||
targets: [] # holds elements with annotator() instances
|
StudentNotes = (function() {
|
||||||
|
StudentNotes.prototype._debug = false;
|
||||||
|
|
||||||
# Adds a listener for "notes" events that may bubble up from descendants.
|
|
||||||
constructor: ($, el) ->
|
|
||||||
console.log 'student notes init', arguments, this if @_debug
|
|
||||||
|
|
||||||
if not $(el).data('notes-instance')
|
/*
|
||||||
events = 'notes:init': @onInitNotes
|
holds elements with annotator() instances
|
||||||
$(el).delegate('*', events)
|
*/
|
||||||
$(el).data('notes-instance', @)
|
|
||||||
|
|
||||||
# Initializes annotations on a container element in response to an init event.
|
StudentNotes.prototype.targets = [];
|
||||||
onInitNotes: (event, uri=null, storage_url=null, token=null) =>
|
|
||||||
event.stopPropagation()
|
|
||||||
|
|
||||||
found = @targets.some (target) -> target is event.target
|
|
||||||
|
|
||||||
# Get uri
|
/*
|
||||||
unless uri.substring(0, 4) is "http"
|
Adds a listener for "notes" events that may bubble up from descendants.
|
||||||
uri_root = (window.location.href.split(/#|\?/).shift() or "")
|
*/
|
||||||
uri = uri_root + uri.substring(1)
|
|
||||||
parts = window.location.href.split("/")
|
|
||||||
courseid = parts[4] + "/" + parts[5] + "/" + parts[6]
|
|
||||||
|
|
||||||
# Get id and name user
|
function StudentNotes($, el) {
|
||||||
idUdiv = $(event.target).parent().find(".idU")[0]
|
this.onInitNotes = bind(this.onInitNotes, this);
|
||||||
idDUdiv = $(event.target).parent().find(".idDU")[0]
|
var events;
|
||||||
idUdiv = (if typeof idUdiv isnt "undefined" then idUdiv.innerHTML else "")
|
if (this._debug) {
|
||||||
idDUdiv = (if typeof idDUdiv isnt "undefined" then idDUdiv.innerHTML else "")
|
console.log('student notes init', arguments, this);
|
||||||
|
}
|
||||||
options =
|
if (!$(el).data('notes-instance')) {
|
||||||
optionsAnnotator:
|
events = {
|
||||||
permissions:
|
'notes:init': this.onInitNotes
|
||||||
user:
|
};
|
||||||
id: idUdiv
|
$(el).delegate('*', events);
|
||||||
name: idDUdiv
|
$(el).data('notes-instance', this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
userString: (user) ->
|
|
||||||
return user.name if user and user.name
|
|
||||||
user
|
|
||||||
|
|
||||||
userId: (user) ->
|
/*
|
||||||
return user.id if user and user.id
|
Initializes annotations on a container element in response to an init event.
|
||||||
user
|
*/
|
||||||
auth:
|
|
||||||
token: token
|
|
||||||
|
|
||||||
store:
|
StudentNotes.prototype.onInitNotes = function(event, uri, storage_url, token) {
|
||||||
prefix: storage_url
|
var courseid, found, idDUdiv, idUdiv, options, ova, parts, uri_root;
|
||||||
|
if (uri == null) {
|
||||||
|
uri = null;
|
||||||
|
}
|
||||||
|
if (storage_url == null) {
|
||||||
|
storage_url = null;
|
||||||
|
}
|
||||||
|
if (token == null) {
|
||||||
|
token = null;
|
||||||
|
}
|
||||||
|
event.stopPropagation();
|
||||||
|
found = this.targets.some(function(target) {
|
||||||
|
return target === event.target;
|
||||||
|
});
|
||||||
|
|
||||||
annotationData: uri:uri
|
/*
|
||||||
|
Get uri
|
||||||
|
*/
|
||||||
|
if (uri.substring(0, 4) !== "http") {
|
||||||
|
uri_root = window.location.href.split(/#|\?/).shift() || "";
|
||||||
|
uri = uri_root + uri.substring(1);
|
||||||
|
}
|
||||||
|
parts = window.location.href.split("/");
|
||||||
|
courseid = parts[4] + "/" + parts[5] + "/" + parts[6];
|
||||||
|
|
||||||
urls:
|
/*
|
||||||
create: '/create',
|
Get id and name user
|
||||||
read: '/read/:id',
|
*/
|
||||||
update: '/update/:id',
|
idUdiv = $(event.target).parent().find(".idU")[0];
|
||||||
destroy: '/delete/:id',
|
idDUdiv = $(event.target).parent().find(".idDU")[0];
|
||||||
search: '/search'
|
idUdiv = (typeof idUdiv !== "undefined" ? idUdiv.innerHTML : "");
|
||||||
|
idDUdiv = (typeof idDUdiv !== "undefined" ? idDUdiv.innerHTML : "");
|
||||||
|
options = {
|
||||||
|
optionsAnnotator: {
|
||||||
|
permissions: {
|
||||||
|
user: {
|
||||||
|
id: idUdiv,
|
||||||
|
name: idDUdiv
|
||||||
|
},
|
||||||
|
userString: function(user) {
|
||||||
|
if (user && user.name) {
|
||||||
|
return user.name;
|
||||||
|
}
|
||||||
|
return user;
|
||||||
|
},
|
||||||
|
userId: function(user) {
|
||||||
|
if (user && user.id) {
|
||||||
|
return user.id;
|
||||||
|
}
|
||||||
|
return user;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
auth: {
|
||||||
|
token: token
|
||||||
|
},
|
||||||
|
store: {
|
||||||
|
prefix: storage_url,
|
||||||
|
annotationData: {
|
||||||
|
uri: uri
|
||||||
|
},
|
||||||
|
urls: {
|
||||||
|
create: '/create',
|
||||||
|
read: '/read/:id',
|
||||||
|
update: '/update/:id',
|
||||||
|
destroy: '/delete/:id',
|
||||||
|
search: '/search'
|
||||||
|
},
|
||||||
|
loadFromSearch: {
|
||||||
|
limit: 10000,
|
||||||
|
uri: uri,
|
||||||
|
user: idUdiv
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
optionsVideoJS: {
|
||||||
|
techOrder: ["html5", "flash", "youtube"],
|
||||||
|
customControlsOnMobile: true
|
||||||
|
},
|
||||||
|
optionsOVA: {
|
||||||
|
posBigNew: 'none',
|
||||||
|
NumAnnotations: 20
|
||||||
|
},
|
||||||
|
optionsRichText: {
|
||||||
|
tinymce: {
|
||||||
|
selector: "li.annotator-item textarea",
|
||||||
|
plugins: "media image insertdatetime link code",
|
||||||
|
menubar: false,
|
||||||
|
toolbar_items_size: 'small',
|
||||||
|
extended_valid_elements: "iframe[src|frameborder|style|scrolling|class|width|height|name|align|id]",
|
||||||
|
toolbar: "insertfile undo redo | styleselect | bold italic | alignleft aligncenter alignright alignjustify | bullist numlist outdent indent | link image media rubric | code "
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
if (found) {
|
||||||
|
if (Annotator._instances.length !== 0) {
|
||||||
|
$(event.target).annotator("destroy");
|
||||||
|
}
|
||||||
|
return ova = new OpenVideoAnnotation.Annotator($(event.target), options);
|
||||||
|
} else {
|
||||||
|
if (event.target.id === "annotator-viewer") {
|
||||||
|
return ova = new OpenVideoAnnotation.Annotator($(event.target), options);
|
||||||
|
} else {
|
||||||
|
return this.targets.push(event.target);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
loadFromSearch:
|
return StudentNotes;
|
||||||
limit:10000
|
|
||||||
uri: uri
|
|
||||||
user:idUdiv
|
|
||||||
|
|
||||||
optionsVideoJS: techOrder: ["html5","flash","youtube"],customControlsOnMobile: true
|
|
||||||
optionsOVA:
|
|
||||||
posBigNew:'none'
|
|
||||||
NumAnnotations:20
|
|
||||||
optionsRichText:
|
|
||||||
tinymce:
|
|
||||||
selector: "li.annotator-item textarea"
|
|
||||||
plugins: "media image insertdatetime link code"
|
|
||||||
menubar: false
|
|
||||||
toolbar_items_size: 'small'
|
|
||||||
extended_valid_elements : "iframe[src|frameborder|style|scrolling|class|width|height|name|align|id]"
|
|
||||||
toolbar: "insertfile undo redo | styleselect | bold italic | alignleft aligncenter alignright alignjustify | bullist numlist outdent indent | link image media rubric | code "
|
|
||||||
|
|
||||||
if found
|
|
||||||
$(event.target).annotator "destroy" unless Annotator._instances.length is 0
|
|
||||||
ova = new OpenVideoAnnotation.Annotator($(event.target), options)
|
|
||||||
else
|
|
||||||
if event.target.id is "annotator-viewer"
|
|
||||||
ova = new OpenVideoAnnotation.Annotator($(event.target), options)
|
|
||||||
else
|
|
||||||
@targets.push(event.target)
|
|
||||||
|
|
||||||
# Enable notes by default on the document root.
|
})();
|
||||||
# To initialize annotations on a container element in the document:
|
|
||||||
#
|
|
||||||
# $('#myElement').trigger('notes:init');
|
|
||||||
#
|
|
||||||
# Comment this line to disable notes.
|
|
||||||
|
|
||||||
$(document).ready ($) -> new StudentNotes $, @
|
|
||||||
|
/*
|
||||||
|
Enable notes by default on the document root.
|
||||||
|
To initialize annotations on a container element in the document:
|
||||||
|
|
||||||
|
$('#myElement').trigger('notes:init');
|
||||||
|
|
||||||
|
Comment this line to disable notes.
|
||||||
|
*/
|
||||||
|
|
||||||
|
$(document).ready(function($) {
|
||||||
|
return new StudentNotes($, this);
|
||||||
|
});
|
||||||
|
|
||||||
|
}).call(this);
|
||||||
|
|||||||
@@ -26,7 +26,6 @@ var options = {
|
|||||||
// Make sure the patterns in sourceFiles and specFiles do not match the same file.
|
// Make sure the patterns in sourceFiles and specFiles do not match the same file.
|
||||||
// Otherwise Istanbul which is used for coverage tracking will cause tests to not run.
|
// Otherwise Istanbul which is used for coverage tracking will cause tests to not run.
|
||||||
sourceFiles: [
|
sourceFiles: [
|
||||||
{pattern: 'coffee/src/**/!(*spec).js'},
|
|
||||||
{pattern: 'course_bookmarks/**/!(*spec).js'},
|
{pattern: 'course_bookmarks/**/!(*spec).js'},
|
||||||
{pattern: 'course_search/**/!(*spec).js'},
|
{pattern: 'course_search/**/!(*spec).js'},
|
||||||
{pattern: 'discussion/js/**/!(*spec).js'},
|
{pattern: 'discussion/js/**/!(*spec).js'},
|
||||||
|
|||||||
@@ -1,71 +0,0 @@
|
|||||||
// Karma config for lms-coffee suite.
|
|
||||||
// Docs and troubleshooting tips in common/static/common/js/karma.common.conf.js
|
|
||||||
|
|
||||||
/* eslint-env node */
|
|
||||||
'use strict';
|
|
||||||
var path = require('path');
|
|
||||||
var configModule = require(path.join(__dirname, '../../common/static/common/js/karma.common.conf.js'));
|
|
||||||
|
|
||||||
var options = {
|
|
||||||
|
|
||||||
useRequireJs: false,
|
|
||||||
includeCommonFiles: true,
|
|
||||||
|
|
||||||
// Avoid adding files to this list. Use RequireJS.
|
|
||||||
libraryFilesToInclude: [
|
|
||||||
{pattern: 'common/js/vendor/require.js', included: true},
|
|
||||||
{pattern: 'js/RequireJS-namespace-undefine.js', included: true},
|
|
||||||
|
|
||||||
{pattern: 'common/js/vendor/jquery.js', included: true},
|
|
||||||
{pattern: 'common/js/vendor/jquery-migrate.js', included: true},
|
|
||||||
{pattern: 'xmodule_js/common_static/js/vendor/jquery.event.drag-2.2.js', included: true},
|
|
||||||
{pattern: 'xmodule_js/common_static/js/vendor/slick.core.js', included: true},
|
|
||||||
{pattern: 'xmodule_js/common_static/js/vendor/slick.grid.js', included: true},
|
|
||||||
|
|
||||||
{pattern: 'xmodule_js/common_static/coffee/src/ajax_prefix.js', included: true},
|
|
||||||
{pattern: 'common/js/vendor/jquery.js', included: true},
|
|
||||||
{pattern: 'common/js/vendor/jquery-migrate.js', included: true},
|
|
||||||
{pattern: 'common/js/vendor/underscore.js', included: true},
|
|
||||||
{pattern: 'common/js/xblock/*.js', included: true},
|
|
||||||
{pattern: 'xmodule_js/common_static/js/src/logger.js', included: true},
|
|
||||||
{pattern: 'xmodule_js/common_static/js/test/i18n.js', included: true},
|
|
||||||
{pattern: 'xmodule_js/common_static/js/vendor/CodeMirror/codemirror.js', included: true},
|
|
||||||
{pattern: 'xmodule_js/common_static/js/vendor/jquery.cookie.js', included: true},
|
|
||||||
{pattern: 'xmodule_js/common_static/js/vendor/flot/jquery.flot.js', included: true},
|
|
||||||
{pattern: 'xmodule_js/common_static/coffee/src/jquery.immediateDescendents.js', included: true},
|
|
||||||
{pattern: 'xmodule_js/common_static/js/vendor/jquery-ui.min.js', included: true},
|
|
||||||
{pattern: 'xmodule_js/common_static/js/vendor/URI.min.js', included: true},
|
|
||||||
{pattern: 'common/js/vendor/hls.js', included: true},
|
|
||||||
|
|
||||||
{pattern: 'xmodule_js/src/capa/*.js', included: true},
|
|
||||||
{pattern: 'xmodule_js/src/video/*.js', included: true},
|
|
||||||
{pattern: 'xmodule_js/src/xmodule.js', included: true},
|
|
||||||
|
|
||||||
{pattern: 'xmodule_js/common_static/js/vendor/jasmine-imagediff.js', included: true},
|
|
||||||
{pattern: 'common/js/spec_helpers/jasmine-extensions.js', included: true},
|
|
||||||
|
|
||||||
{pattern: 'lms/js/spec/main_requirejs_coffee.js', included: true}
|
|
||||||
],
|
|
||||||
|
|
||||||
libraryFiles: [
|
|
||||||
{pattern: 'xmodule_js/common_static/js/vendor/**/*.js'}
|
|
||||||
],
|
|
||||||
|
|
||||||
// Make sure the patterns in sourceFiles and specFiles do not match the same file.
|
|
||||||
// Otherwise Istanbul which is used for coverage tracking will cause tests to not run.
|
|
||||||
sourceFiles: [
|
|
||||||
{pattern: 'coffee/src/**/*.js', included: true}
|
|
||||||
],
|
|
||||||
|
|
||||||
specFiles: [
|
|
||||||
{pattern: 'coffee/spec/**/*.js', included: true}
|
|
||||||
],
|
|
||||||
|
|
||||||
fixtureFiles: [
|
|
||||||
{pattern: 'coffee/fixtures/**/*.*', included: true}
|
|
||||||
]
|
|
||||||
};
|
|
||||||
|
|
||||||
module.exports = function(config) {
|
|
||||||
configModule.configure(config, options);
|
|
||||||
};
|
|
||||||
@@ -69,7 +69,7 @@
|
|||||||
*/
|
*/
|
||||||
paths: {
|
paths: {
|
||||||
gettext: 'empty:',
|
gettext: 'empty:',
|
||||||
'coffee/src/ajax_prefix': 'empty:',
|
'js/src/ajax_prefix': 'empty:',
|
||||||
jquery: 'empty:',
|
jquery: 'empty:',
|
||||||
'jquery-migrate': 'empty:',
|
'jquery-migrate': 'empty:',
|
||||||
'jquery.cookie': 'empty:',
|
'jquery.cookie': 'empty:',
|
||||||
|
|||||||
@@ -31,7 +31,7 @@
|
|||||||
'jquery.fileupload': 'xmodule_js/common_static/js/vendor/jQuery-File-Upload/js/jquery.fileupload',
|
'jquery.fileupload': 'xmodule_js/common_static/js/vendor/jQuery-File-Upload/js/jquery.fileupload',
|
||||||
'jquery.iframe-transport': 'xmodule_js/common_static/js/vendor/jQuery-File-Upload/js/jquery.iframe-transport', // eslint-disable-line max-len
|
'jquery.iframe-transport': 'xmodule_js/common_static/js/vendor/jQuery-File-Upload/js/jquery.iframe-transport', // eslint-disable-line max-len
|
||||||
'jquery.inputnumber': 'xmodule_js/common_static/js/vendor/html5-input-polyfills/number-polyfill',
|
'jquery.inputnumber': 'xmodule_js/common_static/js/vendor/html5-input-polyfills/number-polyfill',
|
||||||
'jquery.immediateDescendents': 'xmodule_js/common_static/coffee/src/jquery.immediateDescendents',
|
'jquery.immediateDescendents': 'xmodule_js/common_static/js/src/jquery.immediateDescendents',
|
||||||
'jquery.simulate': 'xmodule_js/common_static/js/vendor/jquery.simulate',
|
'jquery.simulate': 'xmodule_js/common_static/js/vendor/jquery.simulate',
|
||||||
'jquery.timeago': 'xmodule_js/common_static/js/vendor/jquery.timeago',
|
'jquery.timeago': 'xmodule_js/common_static/js/vendor/jquery.timeago',
|
||||||
'jquery.url': 'xmodule_js/common_static/js/vendor/url.min',
|
'jquery.url': 'xmodule_js/common_static/js/vendor/url.min',
|
||||||
@@ -58,7 +58,7 @@
|
|||||||
'domReady': 'xmodule_js/common_static/js/vendor/domReady',
|
'domReady': 'xmodule_js/common_static/js/vendor/domReady',
|
||||||
mathjax: '//cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.1/MathJax.js?config=TeX-MML-AM_SVG&delayStartupUntil=configured', // eslint-disable-line max-len
|
mathjax: '//cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.1/MathJax.js?config=TeX-MML-AM_SVG&delayStartupUntil=configured', // eslint-disable-line max-len
|
||||||
'youtube': '//www.youtube.com/player_api?noext',
|
'youtube': '//www.youtube.com/player_api?noext',
|
||||||
'coffee/src/ajax_prefix': 'xmodule_js/common_static/coffee/src/ajax_prefix',
|
'js/src/ajax_prefix': 'xmodule_js/common_static/js/src/ajax_prefix',
|
||||||
'js/instructor_dashboard/student_admin': 'js/instructor_dashboard/student_admin',
|
'js/instructor_dashboard/student_admin': 'js/instructor_dashboard/student_admin',
|
||||||
'xmodule_js/common_static/js/test/add_ajax_prefix': 'xmodule_js/common_static/js/test/add_ajax_prefix',
|
'xmodule_js/common_static/js/test/add_ajax_prefix': 'xmodule_js/common_static/js/test/add_ajax_prefix',
|
||||||
'xblock/lms.runtime.v1': 'lms/js/xblock/lms.runtime.v1',
|
'xblock/lms.runtime.v1': 'lms/js/xblock/lms.runtime.v1',
|
||||||
@@ -71,8 +71,8 @@
|
|||||||
'Markdown.Editor': 'js/Markdown.Editor',
|
'Markdown.Editor': 'js/Markdown.Editor',
|
||||||
'Markdown.Sanitizer': 'js/Markdown.Sanitizer',
|
'Markdown.Sanitizer': 'js/Markdown.Sanitizer',
|
||||||
'_split': 'js/split',
|
'_split': 'js/split',
|
||||||
'mathjax_delay_renderer': 'coffee/src/mathjax_delay_renderer',
|
'mathjax_delay_renderer': 'js/mathjax_delay_renderer',
|
||||||
'MathJaxProcessor': 'coffee/src/customwmd',
|
'MathJaxProcessor': 'js/customwmd',
|
||||||
'picturefill': 'common/js/vendor/picturefill',
|
'picturefill': 'common/js/vendor/picturefill',
|
||||||
'bootstrap': 'common/js/vendor/bootstrap.bundle',
|
'bootstrap': 'common/js/vendor/bootstrap.bundle',
|
||||||
'draggabilly': 'xmodule_js/common_static/js/vendor/draggabilly',
|
'draggabilly': 'xmodule_js/common_static/js/vendor/draggabilly',
|
||||||
@@ -282,7 +282,7 @@
|
|||||||
},
|
},
|
||||||
'xmodule_js/common_static/js/test/add_ajax_prefix': {
|
'xmodule_js/common_static/js/test/add_ajax_prefix': {
|
||||||
exports: 'AjaxPrefix',
|
exports: 'AjaxPrefix',
|
||||||
deps: ['coffee/src/ajax_prefix']
|
deps: ['js/src/ajax_prefix']
|
||||||
},
|
},
|
||||||
'js/instructor_dashboard/util': {
|
'js/instructor_dashboard/util': {
|
||||||
exports: 'js/instructor_dashboard/util',
|
exports: 'js/instructor_dashboard/util',
|
||||||
|
|||||||
@@ -16,9 +16,9 @@ from openedx.core.djangolib.markup import HTML
|
|||||||
## add in a definition of 'xxx_url' in the right section_data for whatever page your
|
## add in a definition of 'xxx_url' in the right section_data for whatever page your
|
||||||
## feature is on.
|
## feature is on.
|
||||||
## 3. Add a url() entry in api_urls.py
|
## 3. Add a url() entry in api_urls.py
|
||||||
## 4. Over in lms/static/coffee/src/instructor_dashboard/ there there are .coffee files
|
## 4. Over in lms/static/js/instructor_dashboard/ there are .js files for each page.
|
||||||
## for each page which define the .js. Edit this to make your input do something
|
## Edit this to make your input do something when clicked. The .js files use the
|
||||||
## when clicked. The .coffee files use the name=xx to pick out inputs, not id=
|
## name=xx to pick out inputs, not id=
|
||||||
## 5. Implement your standard django/python in lms/djangoapps/instructor/views/api.py
|
## 5. Implement your standard django/python in lms/djangoapps/instructor/views/api.py
|
||||||
## 6. And tests go in lms/djangoapps/instructor/tests/
|
## 6. And tests go in lms/djangoapps/instructor/tests/
|
||||||
|
|
||||||
@@ -110,7 +110,7 @@ from openedx.core.djangolib.markup import HTML
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
## links which are tied to idash-sections below.
|
## links which are tied to idash-sections below.
|
||||||
## the links are activated and handled in instructor_dashboard.coffee
|
## the links are activated and handled in instructor_dashboard.js
|
||||||
## when the javascript loads, it clicks on the first section
|
## when the javascript loads, it clicks on the first section
|
||||||
<ul class="instructor-nav">
|
<ul class="instructor-nav">
|
||||||
% for section_data in sections:
|
% for section_data in sections:
|
||||||
|
|||||||
25
package-lock.json
generated
25
package-lock.json
generated
@@ -2091,31 +2091,6 @@
|
|||||||
"resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz",
|
||||||
"integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c="
|
"integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c="
|
||||||
},
|
},
|
||||||
"coffee-loader": {
|
|
||||||
"version": "0.7.3",
|
|
||||||
"resolved": "https://registry.npmjs.org/coffee-loader/-/coffee-loader-0.7.3.tgz",
|
|
||||||
"integrity": "sha1-+tvG79b8fsyIxbMEaiwpIGa8tUo=",
|
|
||||||
"requires": {
|
|
||||||
"loader-utils": "1.1.0"
|
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"loader-utils": {
|
|
||||||
"version": "1.1.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.1.0.tgz",
|
|
||||||
"integrity": "sha1-yYrvSIvM7aL/teLeZG1qdUQp9c0=",
|
|
||||||
"requires": {
|
|
||||||
"big.js": "3.2.0",
|
|
||||||
"emojis-list": "2.1.0",
|
|
||||||
"json5": "0.5.1"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"coffee-script": {
|
|
||||||
"version": "1.6.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/coffee-script/-/coffee-script-1.6.1.tgz",
|
|
||||||
"integrity": "sha1-NLVd7bCc7zbRseKQgwLgV/HiYGg="
|
|
||||||
},
|
|
||||||
"collapse-white-space": {
|
"collapse-white-space": {
|
||||||
"version": "1.0.3",
|
"version": "1.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/collapse-white-space/-/collapse-white-space-1.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/collapse-white-space/-/collapse-white-space-1.0.3.tgz",
|
||||||
|
|||||||
@@ -19,8 +19,6 @@
|
|||||||
"bootstrap": "4.0.0-beta.2",
|
"bootstrap": "4.0.0-beta.2",
|
||||||
"camelize": "1.0.0",
|
"camelize": "1.0.0",
|
||||||
"classnames": "2.2.5",
|
"classnames": "2.2.5",
|
||||||
"coffee-loader": "0.7.3",
|
|
||||||
"coffee-script": "1.6.1",
|
|
||||||
"css-loader": "0.28.8",
|
"css-loader": "0.28.8",
|
||||||
"edx-pattern-library": "0.18.1",
|
"edx-pattern-library": "0.18.1",
|
||||||
"edx-ui-toolkit": "1.5.2",
|
"edx-ui-toolkit": "1.5.2",
|
||||||
|
|||||||
@@ -28,7 +28,6 @@ from .utils.timer import timed
|
|||||||
# setup baseline paths
|
# setup baseline paths
|
||||||
|
|
||||||
ALL_SYSTEMS = ['lms', 'studio']
|
ALL_SYSTEMS = ['lms', 'studio']
|
||||||
COFFEE_DIRS = ['lms', 'cms', 'common']
|
|
||||||
|
|
||||||
LMS = 'lms'
|
LMS = 'lms'
|
||||||
CMS = 'cms'
|
CMS = 'cms'
|
||||||
@@ -301,32 +300,6 @@ def debounce(seconds=1):
|
|||||||
return decorator
|
return decorator
|
||||||
|
|
||||||
|
|
||||||
class CoffeeScriptWatcher(PatternMatchingEventHandler):
|
|
||||||
"""
|
|
||||||
Watches for coffeescript changes
|
|
||||||
"""
|
|
||||||
ignore_directories = True
|
|
||||||
patterns = ['*.coffee']
|
|
||||||
|
|
||||||
def register(self, observer):
|
|
||||||
"""
|
|
||||||
register files with observer
|
|
||||||
"""
|
|
||||||
dirnames = set()
|
|
||||||
for filename in sh(coffeescript_files(), capture=True).splitlines():
|
|
||||||
dirnames.add(path(filename).dirname())
|
|
||||||
for dirname in dirnames:
|
|
||||||
observer.schedule(self, dirname)
|
|
||||||
|
|
||||||
@debounce()
|
|
||||||
def on_any_event(self, event):
|
|
||||||
print('\tCHANGED:', event.src_path)
|
|
||||||
try:
|
|
||||||
compile_coffeescript(event.src_path)
|
|
||||||
except Exception: # pylint: disable=broad-except
|
|
||||||
traceback.print_exc()
|
|
||||||
|
|
||||||
|
|
||||||
class SassWatcher(PatternMatchingEventHandler):
|
class SassWatcher(PatternMatchingEventHandler):
|
||||||
"""
|
"""
|
||||||
Watches for sass file changes
|
Watches for sass file changes
|
||||||
@@ -403,28 +376,6 @@ class XModuleAssetsWatcher(PatternMatchingEventHandler):
|
|||||||
restart_django_servers()
|
restart_django_servers()
|
||||||
|
|
||||||
|
|
||||||
def coffeescript_files():
|
|
||||||
"""
|
|
||||||
return find command for paths containing coffee files
|
|
||||||
"""
|
|
||||||
dirs = " ".join(Env.REPO_ROOT / coffee_dir for coffee_dir in COFFEE_DIRS)
|
|
||||||
return cmd('find', dirs, '-type f', '-name \"*.coffee\"')
|
|
||||||
|
|
||||||
|
|
||||||
@task
|
|
||||||
@no_help
|
|
||||||
@timed
|
|
||||||
def compile_coffeescript(*files):
|
|
||||||
"""
|
|
||||||
Compile CoffeeScript to JavaScript.
|
|
||||||
"""
|
|
||||||
if not files:
|
|
||||||
files = ["`{}`".format(coffeescript_files())]
|
|
||||||
sh(cmd(
|
|
||||||
"node_modules/.bin/coffee", "--compile", *files
|
|
||||||
))
|
|
||||||
|
|
||||||
|
|
||||||
@task
|
@task
|
||||||
@no_help
|
@no_help
|
||||||
@cmdopts([
|
@cmdopts([
|
||||||
@@ -736,7 +687,6 @@ def collect_assets(systems, settings, **kwargs):
|
|||||||
|
|
||||||
# We compile these out, don't need the source files in staticfiles
|
# We compile these out, don't need the source files in staticfiles
|
||||||
"sass",
|
"sass",
|
||||||
"*.coffee",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
ignore_args = " ".join(
|
ignore_args = " ".join(
|
||||||
@@ -906,7 +856,6 @@ def watch_assets(options):
|
|||||||
sass_directories = get_watcher_dirs(theme_dirs, themes)
|
sass_directories = get_watcher_dirs(theme_dirs, themes)
|
||||||
observer = Observer(timeout=wait)
|
observer = Observer(timeout=wait)
|
||||||
|
|
||||||
CoffeeScriptWatcher().register(observer)
|
|
||||||
SassWatcher().register(observer, sass_directories)
|
SassWatcher().register(observer, sass_directories)
|
||||||
XModuleSassWatcher().register(observer, ['common/lib/xmodule/'])
|
XModuleSassWatcher().register(observer, ['common/lib/xmodule/'])
|
||||||
XModuleAssetsWatcher().register(observer)
|
XModuleAssetsWatcher().register(observer)
|
||||||
@@ -936,7 +885,7 @@ def watch_assets(options):
|
|||||||
@timed
|
@timed
|
||||||
def update_assets(args):
|
def update_assets(args):
|
||||||
"""
|
"""
|
||||||
Compile CoffeeScript and Sass, then collect static assets.
|
Compile Sass, then collect static assets.
|
||||||
"""
|
"""
|
||||||
parser = argparse.ArgumentParser(prog='paver update_assets')
|
parser = argparse.ArgumentParser(prog='paver update_assets')
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
@@ -980,7 +929,6 @@ def update_assets(args):
|
|||||||
|
|
||||||
process_xmodule_assets()
|
process_xmodule_assets()
|
||||||
process_npm_assets()
|
process_npm_assets()
|
||||||
compile_coffeescript()
|
|
||||||
|
|
||||||
# Build Webpack
|
# Build Webpack
|
||||||
call_task('pavelib.assets.webpack', options={'settings': args.settings})
|
call_task('pavelib.assets.webpack', options={'settings': args.settings})
|
||||||
|
|||||||
@@ -25,7 +25,6 @@ DEFAULT_SETTINGS = Env.DEVSTACK_SETTINGS
|
|||||||
@needs(
|
@needs(
|
||||||
"pavelib.prereqs.install_prereqs",
|
"pavelib.prereqs.install_prereqs",
|
||||||
"pavelib.i18n.i18n_validate_gettext",
|
"pavelib.i18n.i18n_validate_gettext",
|
||||||
"pavelib.assets.compile_coffeescript",
|
|
||||||
)
|
)
|
||||||
@cmdopts([
|
@cmdopts([
|
||||||
("verbose", "v", "Sets 'verbose' to True"),
|
("verbose", "v", "Sets 'verbose' to True"),
|
||||||
|
|||||||
@@ -18,10 +18,6 @@ class TestPaverJavaScriptTestTasks(PaverTestCase):
|
|||||||
|
|
||||||
EXPECTED_DELETE_JAVASCRIPT_REPORT_COMMAND = u'find {platform_root}/reports/javascript -type f -delete'
|
EXPECTED_DELETE_JAVASCRIPT_REPORT_COMMAND = u'find {platform_root}/reports/javascript -type f -delete'
|
||||||
EXPECTED_INSTALL_NPM_ASSETS_COMMAND = u'install npm_assets'
|
EXPECTED_INSTALL_NPM_ASSETS_COMMAND = u'install npm_assets'
|
||||||
EXPECTED_COFFEE_COMMAND = (
|
|
||||||
u'node_modules/.bin/coffee --compile `find {platform_root}/lms {platform_root}/cms '
|
|
||||||
u'{platform_root}/common -type f -name "*.coffee"`'
|
|
||||||
)
|
|
||||||
EXPECTED_KARMA_OPTIONS = (
|
EXPECTED_KARMA_OPTIONS = (
|
||||||
u"{config_file} "
|
u"{config_file} "
|
||||||
u"--single-run={single_run} "
|
u"--single-run={single_run} "
|
||||||
@@ -120,7 +116,6 @@ class TestPaverJavaScriptTestTasks(PaverTestCase):
|
|||||||
platform_root=self.platform_root
|
platform_root=self.platform_root
|
||||||
))
|
))
|
||||||
expected_messages.append(self.EXPECTED_INSTALL_NPM_ASSETS_COMMAND)
|
expected_messages.append(self.EXPECTED_INSTALL_NPM_ASSETS_COMMAND)
|
||||||
expected_messages.append(self.EXPECTED_COFFEE_COMMAND.format(platform_root=self.platform_root))
|
|
||||||
|
|
||||||
for suite in suites:
|
for suite in suites:
|
||||||
# Karma test command
|
# Karma test command
|
||||||
|
|||||||
@@ -6,10 +6,6 @@ from paver.easy import call_task
|
|||||||
from ..utils.envs import Env
|
from ..utils.envs import Env
|
||||||
from .utils import PaverTestCase
|
from .utils import PaverTestCase
|
||||||
|
|
||||||
EXPECTED_COFFEE_COMMAND = (
|
|
||||||
u"node_modules/.bin/coffee --compile `find {platform_root}/lms "
|
|
||||||
u"{platform_root}/cms {platform_root}/common -type f -name \"*.coffee\"`"
|
|
||||||
)
|
|
||||||
EXPECTED_SASS_COMMAND = (
|
EXPECTED_SASS_COMMAND = (
|
||||||
u"libsass {sass_directory}"
|
u"libsass {sass_directory}"
|
||||||
)
|
)
|
||||||
@@ -33,7 +29,7 @@ EXPECTED_COLLECT_STATIC_COMMAND = (
|
|||||||
u'python manage.py {system} --settings={asset_settings} collectstatic '
|
u'python manage.py {system} --settings={asset_settings} collectstatic '
|
||||||
u'--ignore "fixtures" --ignore "karma_*.js" --ignore "spec" '
|
u'--ignore "fixtures" --ignore "karma_*.js" --ignore "spec" '
|
||||||
u'--ignore "spec_helpers" --ignore "spec-helpers" --ignore "xmodule_js" '
|
u'--ignore "spec_helpers" --ignore "spec-helpers" --ignore "xmodule_js" '
|
||||||
u'--ignore "geoip" --ignore "sass" --ignore "*.coffee" '
|
u'--ignore "geoip" --ignore "sass" '
|
||||||
u'--noinput {log_string}'
|
u'--noinput {log_string}'
|
||||||
)
|
)
|
||||||
EXPECTED_CELERY_COMMAND = (
|
EXPECTED_CELERY_COMMAND = (
|
||||||
@@ -247,7 +243,6 @@ class TestPaverServerTasks(PaverTestCase):
|
|||||||
if not is_fast:
|
if not is_fast:
|
||||||
expected_messages.append(u"xmodule_assets common/static/xmodule")
|
expected_messages.append(u"xmodule_assets common/static/xmodule")
|
||||||
expected_messages.append(u"install npm_assets")
|
expected_messages.append(u"install npm_assets")
|
||||||
expected_messages.append(EXPECTED_COFFEE_COMMAND.format(platform_root=self.platform_root))
|
|
||||||
expected_messages.extend(
|
expected_messages.extend(
|
||||||
[c.format(settings=expected_asset_settings) for c in EXPECTED_PRINT_SETTINGS_COMMAND]
|
[c.format(settings=expected_asset_settings) for c in EXPECTED_PRINT_SETTINGS_COMMAND]
|
||||||
)
|
)
|
||||||
@@ -293,7 +288,6 @@ class TestPaverServerTasks(PaverTestCase):
|
|||||||
if not is_fast:
|
if not is_fast:
|
||||||
expected_messages.append(u"xmodule_assets common/static/xmodule")
|
expected_messages.append(u"xmodule_assets common/static/xmodule")
|
||||||
expected_messages.append(u"install npm_assets")
|
expected_messages.append(u"install npm_assets")
|
||||||
expected_messages.append(EXPECTED_COFFEE_COMMAND.format(platform_root=self.platform_root))
|
|
||||||
expected_messages.extend(
|
expected_messages.extend(
|
||||||
[c.format(settings=expected_asset_settings) for c in EXPECTED_PRINT_SETTINGS_COMMAND]
|
[c.format(settings=expected_asset_settings) for c in EXPECTED_PRINT_SETTINGS_COMMAND]
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -182,7 +182,6 @@ class Env(object):
|
|||||||
REPO_ROOT / 'cms/static/karma_cms.conf.js',
|
REPO_ROOT / 'cms/static/karma_cms.conf.js',
|
||||||
REPO_ROOT / 'cms/static/karma_cms_squire.conf.js',
|
REPO_ROOT / 'cms/static/karma_cms_squire.conf.js',
|
||||||
REPO_ROOT / 'lms/static/karma_lms.conf.js',
|
REPO_ROOT / 'lms/static/karma_lms.conf.js',
|
||||||
REPO_ROOT / 'lms/static/karma_lms_coffee.conf.js',
|
|
||||||
REPO_ROOT / 'common/lib/xmodule/xmodule/js/karma_xmodule.conf.js',
|
REPO_ROOT / 'common/lib/xmodule/xmodule/js/karma_xmodule.conf.js',
|
||||||
REPO_ROOT / 'common/static/karma_common.conf.js',
|
REPO_ROOT / 'common/static/karma_common.conf.js',
|
||||||
REPO_ROOT / 'common/static/karma_common_requirejs.conf.js',
|
REPO_ROOT / 'common/static/karma_common_requirejs.conf.js',
|
||||||
@@ -192,7 +191,6 @@ class Env(object):
|
|||||||
'cms',
|
'cms',
|
||||||
'cms-squire',
|
'cms-squire',
|
||||||
'lms',
|
'lms',
|
||||||
'lms-coffee',
|
|
||||||
'xmodule',
|
'xmodule',
|
||||||
'common',
|
'common',
|
||||||
'common-requirejs'
|
'common-requirejs'
|
||||||
|
|||||||
@@ -39,7 +39,6 @@ class JsTestSuite(TestSuite):
|
|||||||
test_utils.clean_dir(self.report_dir)
|
test_utils.clean_dir(self.report_dir)
|
||||||
|
|
||||||
assets.process_npm_assets()
|
assets.process_npm_assets()
|
||||||
assets.compile_coffeescript("`find lms cms common -type f -name \"*.coffee\"`")
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def _default_subsuites(self):
|
def _default_subsuites(self):
|
||||||
@@ -51,7 +50,7 @@ class JsTestSuite(TestSuite):
|
|||||||
|
|
||||||
class JsTestSubSuite(TestSuite):
|
class JsTestSubSuite(TestSuite):
|
||||||
"""
|
"""
|
||||||
Class for JS suites like cms, cms-squire, lms, lms-coffee, common,
|
Class for JS suites like cms, cms-squire, lms, common,
|
||||||
common-requirejs and xmodule
|
common-requirejs and xmodule
|
||||||
"""
|
"""
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user