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
|
||||
|
||||
|
||||
# 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
|
||||
cms/static/xmodule_js
|
||||
lms/static/xmodule_js
|
||||
@@ -36,27 +29,40 @@ lms/static/xmodule_js
|
||||
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/capa/display_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.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
|
||||
|
||||
@@ -810,10 +810,7 @@ PIPELINE_JS = {
|
||||
},
|
||||
}
|
||||
|
||||
PIPELINE_COMPILERS = (
|
||||
'pipeline.compilers.coffee.CoffeeScriptCompiler',
|
||||
)
|
||||
|
||||
PIPELINE_COMPILERS = ()
|
||||
PIPELINE_CSS_COMPRESSOR = None
|
||||
PIPELINE_JS_COMPRESSOR = None
|
||||
|
||||
@@ -829,10 +826,6 @@ STATICFILES_IGNORE_PATTERNS = (
|
||||
"sass/*/*.scss",
|
||||
"sass/*/*/*.scss",
|
||||
"sass/*/*/*/*.scss",
|
||||
"coffee/*.coffee",
|
||||
"coffee/*/*.coffee",
|
||||
"coffee/*/*/*.coffee",
|
||||
"coffee/*/*/*/*.coffee",
|
||||
|
||||
# Ignore tests
|
||||
"spec",
|
||||
|
||||
@@ -104,7 +104,7 @@
|
||||
'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.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',
|
||||
'date': 'js/vendor/date',
|
||||
moment: 'common/js/vendor/moment-with-locales',
|
||||
@@ -304,11 +304,11 @@
|
||||
deps: ['xblock/core']
|
||||
},
|
||||
'cms/js/main': {
|
||||
deps: ['coffee/src/ajax_prefix']
|
||||
deps: ['js/src/ajax_prefix']
|
||||
},
|
||||
'js/src/logger': {
|
||||
exports: 'Logger',
|
||||
deps: ['coffee/src/ajax_prefix']
|
||||
deps: ['js/src/ajax_prefix']
|
||||
},
|
||||
|
||||
// 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.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.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',
|
||||
'datepair': 'xmodule_js/common_static/js/vendor/timepicker/datepair',
|
||||
'date': 'xmodule_js/common_static/js/vendor/date',
|
||||
@@ -72,7 +72,7 @@
|
||||
'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
|
||||
'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'
|
||||
},
|
||||
shim: {
|
||||
@@ -218,9 +218,9 @@
|
||||
deps: ['jquery']
|
||||
},
|
||||
'cms/js/main': {
|
||||
deps: ['coffee/src/ajax_prefix']
|
||||
deps: ['js/src/ajax_prefix']
|
||||
},
|
||||
'coffee/src/ajax_prefix': {
|
||||
'js/src/ajax_prefix': {
|
||||
deps: ['jquery']
|
||||
}
|
||||
}
|
||||
@@ -231,17 +231,17 @@
|
||||
testFiles = [
|
||||
'cms/js/spec/main_spec',
|
||||
'cms/js/spec/xblock/cms.runtime.v1_spec',
|
||||
'coffee/spec/models/course_spec',
|
||||
'coffee/spec/models/metadata_spec',
|
||||
'coffee/spec/models/section_spec',
|
||||
'coffee/spec/models/settings_course_grader_spec',
|
||||
'coffee/spec/models/settings_grading_spec',
|
||||
'coffee/spec/models/textbook_spec',
|
||||
'coffee/spec/models/upload_spec',
|
||||
'coffee/spec/views/course_info_spec',
|
||||
'coffee/spec/views/metadata_edit_spec',
|
||||
'coffee/spec/views/textbook_spec',
|
||||
'coffee/spec/views/upload_spec',
|
||||
'js/spec/models/course_spec',
|
||||
'js/spec/models/metadata_spec',
|
||||
'js/spec/models/section_spec',
|
||||
'js/spec/models/settings_course_grader_spec',
|
||||
'js/spec/models/settings_grading_spec',
|
||||
'js/spec/models/textbook_spec',
|
||||
'js/spec/models/upload_spec',
|
||||
'js/spec/views/course_info_spec',
|
||||
'js/spec/views/metadata_edit_spec',
|
||||
'js/spec/views/textbook_spec',
|
||||
'js/spec/views/upload_spec',
|
||||
'js/spec/video/transcripts/utils_spec',
|
||||
'js/spec/video/transcripts/editor_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.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.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',
|
||||
'date': 'xmodule_js/common_static/js/vendor/date',
|
||||
'text': 'xmodule_js/common_static/js/vendor/requirejs/text',
|
||||
@@ -49,7 +49,7 @@
|
||||
'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
|
||||
'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: {
|
||||
'gettext': {
|
||||
@@ -174,9 +174,9 @@
|
||||
deps: ['xblock/core']
|
||||
},
|
||||
'cms/js/main': {
|
||||
deps: ['coffee/src/ajax_prefix']
|
||||
deps: ['js/src/ajax_prefix']
|
||||
},
|
||||
'coffee/src/ajax_prefix': {
|
||||
'js/src/ajax_prefix': {
|
||||
deps: ['jquery']
|
||||
}
|
||||
}
|
||||
@@ -185,7 +185,7 @@
|
||||
jasmine.getFixtures().fixturesPath = '/base/templates';
|
||||
|
||||
testFiles = [
|
||||
'coffee/spec/views/assets_spec',
|
||||
'js/spec/views/assets_squire_spec',
|
||||
'js/spec/video/translations_editor_spec',
|
||||
'js/spec/video/file_uploader_editor_spec',
|
||||
'js/spec/models/group_configuration_spec'
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
define(['backbone'], function(Backbone) {
|
||||
/**
|
||||
* 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({
|
||||
defaults: {
|
||||
|
||||
@@ -22,13 +22,11 @@ var options = {
|
||||
// Otherwise Istanbul which is used for coverage tracking will cause tests to not run.
|
||||
sourceFiles: [
|
||||
{pattern: 'cms/**/!(*spec|djangojs).js'},
|
||||
{pattern: 'coffee/src/**/!(*spec).js'},
|
||||
{pattern: 'js/**/!(*spec|djangojs).js'}
|
||||
],
|
||||
|
||||
specFiles: [
|
||||
{pattern: 'cms/**/*spec.js'},
|
||||
{pattern: 'coffee/spec/**/*spec.js'},
|
||||
{pattern: 'js/certificates/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.
|
||||
// Otherwise Istanbul which is used for coverage tracking will cause tests to not run.
|
||||
sourceFiles: [
|
||||
{pattern: 'coffee/src/**/!(*spec).js'},
|
||||
{pattern: 'cms/js/**/!(*spec|djangojs).js'},
|
||||
{pattern: 'js/**/!(*spec|djangojs).js'}
|
||||
],
|
||||
|
||||
specFiles: [
|
||||
{pattern: 'coffee/spec/**/*spec.js'},
|
||||
{pattern: 'js/spec/**/*spec.js'}
|
||||
],
|
||||
|
||||
fixtureFiles: [
|
||||
{pattern: 'coffee/fixtures/**/*.*'},
|
||||
{pattern: 'templates/**/*.*'}
|
||||
],
|
||||
|
||||
|
||||
@@ -64,6 +64,7 @@
|
||||
email: m-mat @ math.sci.hiroshima-u.ac.jp (remove space)
|
||||
*/
|
||||
|
||||
/* eslint-disable */
|
||||
var MersenneTwister = function(seed) {
|
||||
if (seed == undefined) {
|
||||
seed = new Date().getTime();
|
||||
|
||||
@@ -47,11 +47,9 @@ class AnnotatableFields(object):
|
||||
|
||||
class AnnotatableModule(AnnotatableFields, XModule):
|
||||
js = {
|
||||
'coffee': [
|
||||
resource_string(__name__, 'js/src/html/display.coffee'),
|
||||
resource_string(__name__, 'js/src/annotatable/display.coffee'),
|
||||
],
|
||||
'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/collapsible.js'),
|
||||
]
|
||||
|
||||
@@ -116,10 +116,8 @@ class ConditionalModule(ConditionalFields, XModule, StudioEditableModule):
|
||||
"""
|
||||
|
||||
js = {
|
||||
'coffee': [
|
||||
resource_string(__name__, 'js/src/conditional/display.coffee'),
|
||||
],
|
||||
'js': [
|
||||
resource_string(__name__, 'js/src/conditional/display.js'),
|
||||
resource_string(__name__, 'js/src/javascript_loader.js'),
|
||||
resource_string(__name__, 'js/src/collapsible.js'),
|
||||
]
|
||||
|
||||
@@ -58,8 +58,8 @@ class TabsEditingDescriptor(EditingFields, MakoModuleDescriptor):
|
||||
"""
|
||||
mako_template = "widgets/tabs-aggregator.html"
|
||||
css = {'scss': [resource_string(__name__, 'css/tabs/tabs.scss')]}
|
||||
js = {'coffee': [resource_string(
|
||||
__name__, 'js/src/tabs/tabs-aggregator.coffee')]}
|
||||
js = {'js': [resource_string(
|
||||
__name__, 'js/src/tabs/tabs-aggregator.js')]}
|
||||
js_module_name = "TabsEditingDescriptor"
|
||||
tabs = []
|
||||
|
||||
@@ -93,7 +93,7 @@ class XMLEditingDescriptor(EditingDescriptor):
|
||||
|
||||
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"
|
||||
|
||||
|
||||
@@ -103,7 +103,7 @@ class MetadataOnlyEditingDescriptor(EditingDescriptor):
|
||||
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"
|
||||
|
||||
mako_template = "widgets/metadata-only-edit.html"
|
||||
@@ -117,5 +117,5 @@ class JSONEditingDescriptor(EditingDescriptor):
|
||||
|
||||
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"
|
||||
|
||||
@@ -107,10 +107,8 @@ class HtmlModuleMixin(HtmlBlock, XModule):
|
||||
Attributes and methods used by HtmlModules internally.
|
||||
"""
|
||||
js = {
|
||||
'coffee': [
|
||||
resource_string(__name__, 'js/src/html/display.coffee'),
|
||||
],
|
||||
'js': [
|
||||
resource_string(__name__, 'js/src/html/display.js'),
|
||||
resource_string(__name__, 'js/src/javascript_loader.js'),
|
||||
resource_string(__name__, 'js/src/collapsible.js'),
|
||||
resource_string(__name__, 'js/src/html/imageModal.js'),
|
||||
@@ -139,7 +137,7 @@ class HtmlDescriptor(HtmlBlock, XmlDescriptor, EditingDescriptor): # pylint: di
|
||||
template_dir_name = "html"
|
||||
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"
|
||||
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):
|
||||
'''Image Annotation Module'''
|
||||
js = {
|
||||
'coffee': [
|
||||
resource_string(__name__, 'js/src/html/display.coffee'),
|
||||
resource_string(__name__, 'js/src/annotatable/display.coffee'),
|
||||
],
|
||||
'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/collapsible.js'),
|
||||
]
|
||||
|
||||
@@ -18,7 +18,7 @@ var options = {
|
||||
// Avoid adding files to this list. Use RequireJS.
|
||||
libraryFilesToInclude: [
|
||||
// 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/backbone.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, '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:
|
||||
// 'External request attempted for blah, which is not defined.'
|
||||
// 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() {
|
||||
// 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() {
|
||||
const data = MarkdownEditingDescriptor.markdownToXml(`\
|
||||
>>á 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
|
||||
_debug: false
|
||||
// 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)
|
||||
(function() {
|
||||
var bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; };
|
||||
|
||||
# selectors for the annotatable xmodule
|
||||
wrapperSelector: '.annotatable-wrapper'
|
||||
toggleAnnotationsSelector: '.annotatable-toggle-annotations'
|
||||
toggleInstructionsSelector: '.annotatable-toggle-instructions'
|
||||
instructionsSelector: '.annotatable-instructions'
|
||||
sectionSelector: '.annotatable-section'
|
||||
spanSelector: '.annotatable-span'
|
||||
replySelector: '.annotatable-reply'
|
||||
this.Annotatable = (function() {
|
||||
Annotatable.prototype._debug = false;
|
||||
|
||||
# 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
|
||||
@el = el
|
||||
@$el = $(el)
|
||||
@init()
|
||||
/*
|
||||
selectors for the annotatable xmodule
|
||||
*/
|
||||
|
||||
$: (selector) ->
|
||||
$(selector, @el)
|
||||
Annotatable.prototype.wrapperSelector = '.annotatable-wrapper';
|
||||
|
||||
init: () ->
|
||||
@initEvents()
|
||||
@initTips()
|
||||
Annotatable.prototype.toggleAnnotationsSelector = '.annotatable-toggle-annotations';
|
||||
|
||||
initEvents: () ->
|
||||
# Initialize toggle handlers for the instructions and annotations sections
|
||||
[@annotationsHidden, @instructionsHidden] = [false, false]
|
||||
@$(@toggleAnnotationsSelector).bind 'click', @onClickToggleAnnotations
|
||||
@$(@toggleInstructionsSelector).bind 'click', @onClickToggleInstructions
|
||||
Annotatable.prototype.toggleInstructionsSelector = '.annotatable-toggle-instructions';
|
||||
|
||||
# Initialize handler for 'reply to annotation' events that scroll to
|
||||
# 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
|
||||
Annotatable.prototype.instructionsSelector = '.annotatable-instructions';
|
||||
|
||||
# Initialize handler for 'return to annotation' events triggered from problems.
|
||||
# 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
|
||||
Annotatable.prototype.sectionSelector = '.annotatable-section';
|
||||
|
||||
initTips: () ->
|
||||
# tooltips are used to display annotations for highlighted text spans
|
||||
@$(@spanSelector).each (index, el) =>
|
||||
$(el).qtip(@getSpanTipOptions el)
|
||||
Annotatable.prototype.spanSelector = '.annotatable-span';
|
||||
|
||||
getSpanTipOptions: (el) ->
|
||||
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
|
||||
Annotatable.prototype.replySelector = '.annotatable-reply';
|
||||
|
||||
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) =>
|
||||
event.preventDefault() if @annotationsHidden
|
||||
Annotatable.prototype.problemInputSelector = 'div.problem .annotation-input';
|
||||
|
||||
onMoveTip: (event, api, position) =>
|
||||
###
|
||||
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:
|
||||
Annotatable.prototype.problemReturnSelector = 'div.problem .annotation-return';
|
||||
|
||||
(( TOOLTIP ))
|
||||
\/
|
||||
text text text ... text text text ...... <span span span>
|
||||
<span span span>
|
||||
function Annotatable(el) {
|
||||
this.onMoveTip = bind(this.onMoveTip, this);
|
||||
this.onShowTip = bind(this.onShowTip, this);
|
||||
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
|
||||
we should re-position the tooltip to appear above the span.
|
||||
###
|
||||
Annotatable.prototype.$ = function(selector) {
|
||||
return $(selector, this.el);
|
||||
};
|
||||
|
||||
tip = api.elements.tooltip
|
||||
adjust_y = api.options.position?.adjust?.y || 0
|
||||
container = api.options.position?.container || $('body')
|
||||
target = api.elements.target
|
||||
Annotatable.prototype.init = function() {
|
||||
this.initEvents();
|
||||
return this.initTips();
|
||||
};
|
||||
|
||||
rects = $(target).get(0).getClientRects()
|
||||
is_non_overlapping = (rects?.length == 2 and rects[0].left > rects[1].right)
|
||||
Annotatable.prototype.initEvents = function() {
|
||||
|
||||
if is_non_overlapping
|
||||
# we want to choose the largest of the two non-overlapping spans and display
|
||||
# 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])
|
||||
else
|
||||
# always compute the new position because Firefox doesn't
|
||||
# properly vertically position the tooltip
|
||||
focus_rect = rects[0]
|
||||
/*
|
||||
Initialize toggle handlers for the instructions and annotations sections
|
||||
*/
|
||||
var ref;
|
||||
ref = [false, false], this.annotationsHidden = ref[0], this.instructionsHidden = ref[1];
|
||||
this.$(this.toggleAnnotationsSelector).bind('click', this.onClickToggleAnnotations);
|
||||
this.$(this.toggleInstructionsSelector).bind('click', this.onClickToggleInstructions);
|
||||
|
||||
rect_center = focus_rect.left + (focus_rect.width / 2)
|
||||
rect_top = focus_rect.top
|
||||
tip_width = $(tip).width()
|
||||
tip_height = $(tip).height()
|
||||
/*
|
||||
Initialize handler for 'reply to annotation' events that scroll to
|
||||
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.
|
||||
*/
|
||||
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()
|
||||
offset_left = -container_offset.left
|
||||
offset_top = $(document).scrollTop() - container_offset.top
|
||||
/*
|
||||
Initialize handler for 'return to annotation' events triggered from problems.
|
||||
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.
|
||||
*/
|
||||
return $(document).on('click', this.problemReturnSelector, this.onClickReturn);
|
||||
};
|
||||
|
||||
tip_left = offset_left + rect_center - (tip_width / 2)
|
||||
tip_top = offset_top + rect_top - tip_height + adjust_y
|
||||
Annotatable.prototype.initTips = function() {
|
||||
|
||||
# make sure the new tip position doesn't clip the edges of the screen
|
||||
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
|
||||
/*
|
||||
tooltips are used to display annotations for highlighted text spans
|
||||
*/
|
||||
return this.$(this.spanSelector).each((function(_this) {
|
||||
return function(index, el) {
|
||||
return $(el).qtip(_this.getSpanTipOptions(el));
|
||||
};
|
||||
})(this));
|
||||
};
|
||||
|
||||
# final step: update the position object (used by qtip2 to show the tip after the move event)
|
||||
$.extend position, 'left': tip_left, 'top': tip_top
|
||||
Annotatable.prototype.getSpanTipOptions = function(el) {
|
||||
return {
|
||||
content: {
|
||||
title: {
|
||||
text: this.makeTipTitle(el)
|
||||
},
|
||||
text: this.makeTipContent(el)
|
||||
},
|
||||
position: {
|
||||
|
||||
getSpanForProblemReturn: (el) ->
|
||||
problem_id = $(@problemReturnSelector).index(el)
|
||||
@$(@spanSelector).filter("[data-problem-id='#{problem_id}']")
|
||||
/*
|
||||
of tooltip
|
||||
*/
|
||||
my: 'bottom center',
|
||||
|
||||
getProblem: (el) ->
|
||||
problem_id = @getProblemId(el)
|
||||
$(@problemInputSelector).eq(problem_id)
|
||||
/*
|
||||
of target
|
||||
*/
|
||||
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)
|
||||
@toggleAnnotationButtonText hide
|
||||
@toggleSpans hide
|
||||
@toggleTips hide
|
||||
/*
|
||||
don't hide the tooltip if it is moused over
|
||||
*/
|
||||
fixed: true
|
||||
},
|
||||
style: {
|
||||
classes: 'ui-tooltip-annotatable'
|
||||
},
|
||||
events: {
|
||||
show: this.onShowTip,
|
||||
move: this.onMoveTip
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
toggleTips: (hide) ->
|
||||
visible = @findVisibleTips()
|
||||
@hideTips visible
|
||||
Annotatable.prototype.onClickToggleAnnotations = function(e) {
|
||||
return this.toggleAnnotations();
|
||||
};
|
||||
|
||||
toggleAnnotationButtonText: (hide) ->
|
||||
if hide
|
||||
buttonText = gettext('Show Annotations')
|
||||
else
|
||||
buttonText = gettext('Hide Annotations')
|
||||
@$(@toggleAnnotationsSelector).text(buttonText)
|
||||
Annotatable.prototype.onClickToggleInstructions = function(e) {
|
||||
return this.toggleInstructions();
|
||||
};
|
||||
|
||||
toggleInstructions: () ->
|
||||
hide = (@instructionsHidden = not @instructionsHidden)
|
||||
@toggleInstructionsButton hide
|
||||
@toggleInstructionsText hide
|
||||
Annotatable.prototype.onClickReply = function(e) {
|
||||
return this.replyTo(e.currentTarget);
|
||||
};
|
||||
|
||||
toggleInstructionsButton: (hide) ->
|
||||
if hide
|
||||
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])
|
||||
Annotatable.prototype.onClickReturn = function(e) {
|
||||
return this.returnFrom(e.currentTarget);
|
||||
};
|
||||
|
||||
toggleInstructionsText: (hide) ->
|
||||
slideMethod = (if hide then 'slideUp' else 'slideDown')
|
||||
@$(@instructionsSelector)[slideMethod]()
|
||||
Annotatable.prototype.onShowTip = function(event, api) {
|
||||
if (this.annotationsHidden) {
|
||||
return event.preventDefault();
|
||||
}
|
||||
};
|
||||
|
||||
toggleSpans: (hide) ->
|
||||
@$(@spanSelector).toggleClass 'hide', hide, 250
|
||||
Annotatable.prototype.onMoveTip = function(event, api, position) {
|
||||
|
||||
replyTo: (buttonEl) ->
|
||||
offset = -20
|
||||
el = @getProblem buttonEl
|
||||
if el.length > 0
|
||||
@scrollTo(el, @afterScrollToProblem, offset)
|
||||
else
|
||||
console.log('problem not found. event: ', e) if @_debug
|
||||
/*
|
||||
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 ))
|
||||
\/
|
||||
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
|
||||
el = @getSpanForProblemReturn buttonEl
|
||||
if el.length > 0
|
||||
@scrollTo(el, @afterScrollToSpan, offset)
|
||||
else
|
||||
console.log('span not found. event:', e) if @_debug
|
||||
/*
|
||||
we want to choose the largest of the two non-overlapping spans and display
|
||||
the tooltip above the center of it (see api.options.position settings)
|
||||
*/
|
||||
focus_rect = (rects[0].width > rects[1].width ? rects[0] : rects[1]);
|
||||
} else {
|
||||
|
||||
scrollTo: (el, after, offset = -20) ->
|
||||
$('html,body').scrollTo(el, {
|
||||
duration: 500
|
||||
onAfter: @_once => after?.call this, el
|
||||
offset: offset
|
||||
}) if $(el).length > 0
|
||||
/*
|
||||
always compute the new position because Firefox doesn't
|
||||
properly vertically position the tooltip
|
||||
*/
|
||||
focus_rect = rects[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', ->
|
||||
span_el.removeClass 'selected', 400, 'swing'
|
||||
/*
|
||||
make sure the new tip position doesn't clip the edges of the screen
|
||||
*/
|
||||
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) =>
|
||||
text = $(el).data('comment-body')
|
||||
comment = @createComment(text)
|
||||
problem_id = @getProblemId(el)
|
||||
reply = @createReplyLink(problem_id)
|
||||
$(comment).add(reply)
|
||||
/*
|
||||
final step: update the position object (used by qtip2 to show the tip after the move event)
|
||||
*/
|
||||
return $.extend(position, {
|
||||
'left': tip_left,
|
||||
'top': tip_top
|
||||
});
|
||||
};
|
||||
|
||||
makeTipTitle: (el) ->
|
||||
(api) =>
|
||||
title = $(el).data('comment-title')
|
||||
(if title then title else gettext('Commentary'))
|
||||
Annotatable.prototype.getSpanForProblemReturn = function(el) {
|
||||
var problem_id;
|
||||
problem_id = $(this.problemReturnSelector).index(el);
|
||||
return this.$(this.spanSelector).filter("[data-problem-id='" + problem_id + "']");
|
||||
};
|
||||
|
||||
createComment: (text) ->
|
||||
$("<div class=\"annotatable-comment\">#{text}</div>")
|
||||
Annotatable.prototype.getProblem = function(el) {
|
||||
var problem_id;
|
||||
problem_id = this.getProblemId(el);
|
||||
return $(this.problemInputSelector).eq(problem_id);
|
||||
};
|
||||
|
||||
createReplyLink: (problem_id) ->
|
||||
linktxt = gettext('Reply to Annotation')
|
||||
$("<a class=\"annotatable-reply\" href=\"javascript:void(0);\" data-problem-id=\"#{problem_id}\">#{linktxt}</a>")
|
||||
Annotatable.prototype.getProblemId = function(el) {
|
||||
return $(el).data('problem-id');
|
||||
};
|
||||
|
||||
findVisibleTips: () ->
|
||||
visible = []
|
||||
@$(@spanSelector).each (index, el) ->
|
||||
api = $(el).qtip('api')
|
||||
tip = $(api?.elements.tooltip)
|
||||
if tip.is(':visible')
|
||||
visible.push el
|
||||
visible
|
||||
Annotatable.prototype.toggleAnnotations = function() {
|
||||
var hide;
|
||||
hide = (this.annotationsHidden = !this.annotationsHidden);
|
||||
this.toggleAnnotationButtonText(hide);
|
||||
this.toggleSpans(hide);
|
||||
return this.toggleTips(hide);
|
||||
};
|
||||
|
||||
hideTips: (elements) ->
|
||||
$(elements).qtip('hide')
|
||||
Annotatable.prototype.toggleTips = function(hide) {
|
||||
var visible;
|
||||
visible = this.findVisibleTips();
|
||||
return this.hideTips(visible);
|
||||
};
|
||||
|
||||
_once: (fn) ->
|
||||
done = false
|
||||
return =>
|
||||
fn.call this unless done
|
||||
done = true
|
||||
Annotatable.prototype.toggleAnnotationButtonText = function(hide) {
|
||||
var buttonText;
|
||||
if (hide) {
|
||||
buttonText = gettext('Show Annotations');
|
||||
} 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
|
||||
|
||||
@@ -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) ->
|
||||
@el = $(element).find('.conditional-wrapper')
|
||||
Conditional.prototype.render = function(element) {
|
||||
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
|
||||
dependencies = @el.data('depends')
|
||||
if (typeof dependencies is 'string') and (dependencies.length > 0) and (dependencies.indexOf(callerElId) is -1)
|
||||
return
|
||||
return Conditional;
|
||||
|
||||
@url = @el.data('url')
|
||||
if @url
|
||||
@render(element)
|
||||
})();
|
||||
|
||||
render: (element) ->
|
||||
$.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)
|
||||
}).call(this);
|
||||
|
||||
@@ -1,4 +1,21 @@
|
||||
class @InlineDiscussion extends XModule.Descriptor
|
||||
constructor: (element) ->
|
||||
@el = $(element).find('.discussion-module')
|
||||
@view = new DiscussionInlineView(el: @el)
|
||||
// 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.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) ->
|
||||
@el = $(@element)
|
||||
JavascriptLoader.executeModuleScripts(@el)
|
||||
Collapsible.setCollapsibles(@el)
|
||||
if MathJax?
|
||||
MathJax.Hub.Queue ["Typeset", MathJax.Hub, @el[0]]
|
||||
if setupFullScreenModal?
|
||||
setupFullScreenModal()
|
||||
HTMLModule.prototype.$ = function(selector) {
|
||||
return $(selector, this.el);
|
||||
};
|
||||
|
||||
$: (selector) ->
|
||||
$(selector, @el)
|
||||
return HTMLModule;
|
||||
|
||||
})();
|
||||
|
||||
}).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
|
||||
CUSTOM_FONTS = "Default='Open Sans', Verdana, Arial, Helvetica, sans-serif;"
|
||||
this.HTMLEditingDescriptor = (function() {
|
||||
|
||||
# list of standard tinyMCE fonts: http://www.tinymce.com/wiki.php/Configuration:font_formats
|
||||
STANDARD_FONTS = "Andale Mono=andale mono,times;"+
|
||||
"Arial=arial,helvetica,sans-serif;"+
|
||||
"Arial Black=arial black,avant garde;"+
|
||||
"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"
|
||||
/*
|
||||
custom fonts are prepended to font selection dropdown
|
||||
*/
|
||||
var CUSTOM_FONTS, STANDARD_FONTS, _getFonts;
|
||||
|
||||
_getFonts = () ->
|
||||
CUSTOM_FONTS + STANDARD_FONTS
|
||||
CUSTOM_FONTS = "Default='Open Sans', Verdana, Arial, Helvetica, sans-serif;";
|
||||
|
||||
constructor: (element) ->
|
||||
@element = element
|
||||
@base_asset_url = @element.find("#editor-tab").data('base-asset-url')
|
||||
@editor_choice = @element.find("#editor-tab").data('editor')
|
||||
@new_image_modal = window.STUDIO_FRONTEND_IN_CONTEXT_IMAGE_SELECTION
|
||||
if @base_asset_url == undefined
|
||||
@base_asset_url = null
|
||||
/*
|
||||
list of standard tinyMCE fonts: http://www.tinymce.com/wiki.php/Configuration:font_formats
|
||||
*/
|
||||
STANDARD_FONTS = "Andale Mono=andale mono,times;" +
|
||||
"Arial=arial,helvetica,sans-serif;" +
|
||||
"Arial Black=arial black,avant garde;" +
|
||||
"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.
|
||||
@advanced_editor = CodeMirror.fromTextArea($(".edit-box", @element)[0], {
|
||||
mode: "text/html"
|
||||
lineNumbers: true
|
||||
_getFonts = function() {
|
||||
return CUSTOM_FONTS + STANDARD_FONTS;
|
||||
};
|
||||
|
||||
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
|
||||
})
|
||||
});
|
||||
if (this.editor_choice === 'visual') {
|
||||
this.$advancedEditorWrapper = $(this.advanced_editor.getWrapperElement());
|
||||
this.$advancedEditorWrapper.addClass('is-inactive');
|
||||
|
||||
if @editor_choice == 'visual'
|
||||
@$advancedEditorWrapper = $(@advanced_editor.getWrapperElement())
|
||||
@$advancedEditorWrapper.addClass('is-inactive')
|
||||
# Create an array of all content CSS links to use in and pass to Tiny MCE.
|
||||
# We create this dynamically in order to support hashed files from our Django pipeline.
|
||||
# CSS files that are to be used by Tiny MCE should contain the string "tinymce" so
|
||||
# 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 = []
|
||||
$("link[rel=stylesheet][href*='tinymce']").filter("[href*='content']").each ->
|
||||
tiny_mce_css_links.push $(this).attr("href")
|
||||
return
|
||||
/*
|
||||
Create an array of all content CSS links to use in and pass to Tiny MCE.
|
||||
We create this dynamically in order to support hashed files from our Django pipeline.
|
||||
CSS files that are to be used by Tiny MCE should contain the string "tinymce" so
|
||||
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 = [];
|
||||
$("link[rel=stylesheet][href*='tinymce']").filter("[href*='content']").each(function() {
|
||||
tiny_mce_css_links.push($(this).attr("href"));
|
||||
});
|
||||
|
||||
# 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.
|
||||
tinyMCE.baseURL = "#{baseUrl}/js/vendor/tinymce/js/tinymce"
|
||||
# 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.suffix = ".min"
|
||||
@tiny_mce_textarea = $(".tiny-mce", @element).tinymce({
|
||||
script_url : "#{baseUrl}/js/vendor/tinymce/js/tinymce/tinymce.full.min.js",
|
||||
font_formats : _getFonts(),
|
||||
theme : "modern",
|
||||
skin: 'studio-tmce4',
|
||||
schema: "html5",
|
||||
# Necessary to preserve relative URLs to our images.
|
||||
convert_urls : false,
|
||||
# Sniff UI direction from `.wrapper-view` in studio or `.window-wrap` in LMS
|
||||
directionality: $(".wrapper-view, .window-wrap").prop('dir'),
|
||||
content_css : tiny_mce_css_links.join(", "),
|
||||
formats : {
|
||||
# tinyMCE does block level for code by default
|
||||
code: {inline: 'code'}
|
||||
},
|
||||
# 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 " +
|
||||
"#{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", {
|
||||
/*
|
||||
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.
|
||||
*/
|
||||
tinyMCE.baseURL = baseUrl + "/js/vendor/tinymce/js/tinymce";
|
||||
|
||||
/*
|
||||
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.suffix = ".min";
|
||||
this.tiny_mce_textarea = $(".tiny-mce", this.element).tinymce({
|
||||
script_url: baseUrl + "/js/vendor/tinymce/js/tinymce/tinymce.full.min.js",
|
||||
font_formats: _getFonts(),
|
||||
theme: "modern",
|
||||
skin: 'studio-tmce4',
|
||||
schema: "html5",
|
||||
|
||||
/*
|
||||
Necessary to preserve relative URLs to our images.
|
||||
*/
|
||||
convert_urls: false,
|
||||
|
||||
/*
|
||||
Sniff UI direction from `.wrapper-view` in studio or `.window-wrap` in LMS
|
||||
*/
|
||||
directionality: $(".wrapper-view, .window-wrap").prop('dir'),
|
||||
content_css: tiny_mce_css_links.join(", "),
|
||||
formats: {
|
||||
// tinyMCE does block level for code by default
|
||||
code: {
|
||||
inline: 'code'
|
||||
}
|
||||
},
|
||||
|
||||
/*
|
||||
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"),
|
||||
preformatted: gettext("Preformatted"),
|
||||
heading3: gettext("Heading 3"),
|
||||
@@ -94,961 +143,1246 @@ class @HTMLEditingDescriptor
|
||||
heading5: gettext("Heading 5"),
|
||||
heading6: gettext("Heading 6")
|
||||
}, true),
|
||||
width: '100%',
|
||||
height: '400px',
|
||||
menubar: false,
|
||||
statusbar: false,
|
||||
width: '100%',
|
||||
height: '400px',
|
||||
menubar: 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: "*[*]",
|
||||
extended_valid_elements: "*[*]",
|
||||
invalid_elements: "",
|
||||
/*
|
||||
Allow any elements to be used, e.g. link, script, math
|
||||
*/
|
||||
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.
|
||||
# The tinyMCE callback passes in the editor as a parameter.
|
||||
init_instance_callback: @initInstanceCallback,
|
||||
/*
|
||||
Cannot get access to tinyMCE Editor instance (for focusing) until after it is rendered.
|
||||
The tinyMCE callback passes in the editor as a parameter.
|
||||
*/
|
||||
init_instance_callback: this.initInstanceCallback,
|
||||
browser_spellcheck: true
|
||||
});
|
||||
tinymce.addI18n('en', {
|
||||
|
||||
browser_spellcheck: true
|
||||
})
|
||||
tinymce.addI18n('en', {
|
||||
###
|
||||
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."),
|
||||
})
|
||||
/*
|
||||
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"),
|
||||
|
||||
setupTinyMCE: (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 : () ->
|
||||
ed.formatter.toggle('code')
|
||||
})
|
||||
/*
|
||||
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
||||
*/
|
||||
"Advanced": gettext("Advanced"),
|
||||
|
||||
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 : @openImageModal
|
||||
})
|
||||
/*
|
||||
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"),
|
||||
|
||||
@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.
|
||||
ed.on('SaveImage', @saveImage)
|
||||
ed.on('EditImage', @editImage)
|
||||
ed.on('SaveLink', @saveLink)
|
||||
ed.on('EditLink', @editLink)
|
||||
ed.on('ShowCodeEditor', @showCodeEditor)
|
||||
ed.on('SaveCodeEditor', @saveCodeEditor)
|
||||
/*
|
||||
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"),
|
||||
|
||||
@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.
|
||||
if data['src']
|
||||
data['src'] = rewriteStaticLinks(data['src'], @base_asset_url, '/static/')
|
||||
/*
|
||||
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"),
|
||||
|
||||
saveImage: (data) =>
|
||||
# Called when the image plugin is saved. Input arg is the JSON version of the image data.
|
||||
if data['src']
|
||||
data['src'] = rewriteStaticLinks(data['src'], '/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
|
||||
*/
|
||||
"Anchor": gettext("Anchor"),
|
||||
|
||||
openImageModal: () =>
|
||||
img = $(@visualEditor.selection.getNode())
|
||||
imgAttrs =
|
||||
baseAssetUrl: @base_asset_url
|
||||
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}))
|
||||
/*
|
||||
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
||||
*/
|
||||
"Anchors": gettext("Anchors"),
|
||||
|
||||
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
|
||||
if data['src']
|
||||
data['src'] = rewriteStaticLinks(data['src'], '/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
|
||||
*/
|
||||
"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
|
||||
@saveImageFromModal(event.detail)
|
||||
/*
|
||||
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
||||
*/
|
||||
"Blocks": gettext("Blocks"),
|
||||
|
||||
editLink: (data) =>
|
||||
# Called when the link plugin will be shown. Input arg is the JSON version of the link data.
|
||||
if data['href']
|
||||
data['href'] = rewriteStaticLinks(data['href'], @base_asset_url, '/static/')
|
||||
/*
|
||||
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
||||
*/
|
||||
"Body": gettext("Body"),
|
||||
|
||||
saveLink: (data) =>
|
||||
# Called when the link plugin is saved. Input arg is the JSON version of the link data.
|
||||
if data['href']
|
||||
data['href'] = rewriteStaticLinks(data['href'], '/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
|
||||
*/
|
||||
"Bold": gettext("Bold"),
|
||||
|
||||
showCodeEditor: (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.
|
||||
content = rewriteStaticLinks(source.content, @base_asset_url, '/static/')
|
||||
source.content = content
|
||||
/*
|
||||
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"),
|
||||
|
||||
saveCodeEditor: (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.
|
||||
content = rewriteStaticLinks(source.content, '/static/', @base_asset_url)
|
||||
source.content = content
|
||||
/*
|
||||
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
||||
*/
|
||||
"Border": gettext("Border"),
|
||||
|
||||
initInstanceCallback: (visualEditor) =>
|
||||
visualEditor.setContent(rewriteStaticLinks(visualEditor.getContent({no_events: 1}), '/static/', @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.
|
||||
@starting_content = visualEditor.getContent({format:"raw", no_events: 1})
|
||||
visualEditor.focus()
|
||||
/*
|
||||
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
||||
*/
|
||||
"Bottom": gettext("Bottom"),
|
||||
|
||||
getVisualEditor: () ->
|
||||
###
|
||||
Returns the instance of TinyMCE.
|
||||
/*
|
||||
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"),
|
||||
|
||||
Pulled out as a helper method for unit test.
|
||||
###
|
||||
return @visualEditor
|
||||
/*
|
||||
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
||||
*/
|
||||
"Cancel": gettext("Cancel"),
|
||||
|
||||
save: ->
|
||||
text = undefined
|
||||
if @editor_choice == 'visual'
|
||||
visualEditor = @getVisualEditor()
|
||||
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/')
|
||||
/*
|
||||
Translators: this is a message from the raw HTML editor displayed in the browser when a user needs to edit HTML
|
||||
*/
|
||||
"Caption": gettext("Caption"),
|
||||
|
||||
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
|
||||
constructor: (@element) ->
|
||||
@edit_box = CodeMirror.fromTextArea($(".edit-box", @element)[0], {
|
||||
mode: { name: "javascript", json: true }
|
||||
lineNumbers: true
|
||||
lineWrapping: true
|
||||
})
|
||||
// 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;
|
||||
|
||||
save: ->
|
||||
data: JSON.parse @edit_box.getValue()
|
||||
this.JSONEditingDescriptor = (function(superClass) {
|
||||
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
|
||||
constructor: (@element) ->
|
||||
// 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;
|
||||
|
||||
save: ->
|
||||
data: null
|
||||
this.MetadataOnlyEditingDescriptor = (function(superClass) {
|
||||
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
|
||||
constructor: (@element) ->
|
||||
@edit_box = CodeMirror.fromTextArea($(".edit-box", @element)[0], {
|
||||
mode: "xml"
|
||||
lineNumbers: true
|
||||
lineWrapping: true
|
||||
})
|
||||
// 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;
|
||||
|
||||
save: ->
|
||||
data: @edit_box.getValue()
|
||||
this.XMLEditingDescriptor = (function(superClass) {
|
||||
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
|
||||
@isInactiveClass : "is-inactive"
|
||||
// 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); }; };
|
||||
|
||||
constructor: (element) ->
|
||||
@element = element;
|
||||
###
|
||||
Not tested on syncing of multiple editors of same type in tabs
|
||||
(Like many CodeMirrors).
|
||||
###
|
||||
this.TabsEditingDescriptor = (function() {
|
||||
TabsEditingDescriptor.isInactiveClass = "is-inactive";
|
||||
|
||||
@$tabs = $(".tab", @element)
|
||||
@$content = $(".component-tab", @element)
|
||||
function TabsEditingDescriptor(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
|
||||
currentTab = @$tabs.filter('.current')
|
||||
currentTab = @$tabs.first() if currentTab.length isnt 1
|
||||
@html_id = @$tabs.closest('.wrapper-comp-editor').data('html_id')
|
||||
currentTab.trigger("click", [true, @html_id])
|
||||
/*
|
||||
If default visible tab is not setted or if were marked as current
|
||||
more than 1 tab just first tab will be shown
|
||||
*/
|
||||
currentTab = this.$tabs.filter('.current');
|
||||
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) =>
|
||||
e.preventDefault()
|
||||
TabsEditingDescriptor.prototype.onSwitchEditor = function(e, firstTime, html_id) {
|
||||
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) ->
|
||||
if $(value).hasClass('current')
|
||||
previousTab = $(value).data('tab_name')
|
||||
)
|
||||
// call onswitch
|
||||
onSwitchFunction = TabsEditingDescriptor.Model.modules[this.html_id].tabSwitch[$currentTarget.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.
|
||||
# (to be implemented when there is a use case for this functionality)
|
||||
TabsEditingDescriptor.prototype.save = function() {
|
||||
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
|
||||
onSwitchFunction = TabsEditingDescriptor.Model.modules[@html_id].tabSwitch[$currentTarget.data('tab_name')]
|
||||
onSwitchFunction() if $.isFunction(onSwitchFunction)
|
||||
TabsEditingDescriptor.prototype.setMetadataEditor = function(metadataEditor) {
|
||||
return TabsEditingDescriptor.setMetadataEditor.apply(TabsEditingDescriptor, arguments);
|
||||
};
|
||||
|
||||
@$tabs.removeClass('current')
|
||||
$currentTarget.addClass('current')
|
||||
TabsEditingDescriptor.prototype.getStorage = function() {
|
||||
return TabsEditingDescriptor.getStorage();
|
||||
};
|
||||
|
||||
# Tabs are implemeted like anchors. Therefore we can use hash to find
|
||||
# corresponding content
|
||||
content_id = $currentTarget.attr('href')
|
||||
TabsEditingDescriptor.prototype.addToStorage = function(id, data) {
|
||||
return TabsEditingDescriptor.addToStorage.apply(TabsEditingDescriptor, arguments);
|
||||
};
|
||||
|
||||
@$content
|
||||
.addClass(isInactiveClass)
|
||||
.filter(content_id)
|
||||
.removeClass(isInactiveClass)
|
||||
TabsEditingDescriptor.Model = {
|
||||
addModelUpdate: function(id, tabName, modelUpdateFunction) {
|
||||
|
||||
save: ->
|
||||
@element.off('click', '.editor-tabs .tab', @onSwitchEditor)
|
||||
current_tab = @$tabs.filter('.current').data('tab_name')
|
||||
data: TabsEditingDescriptor.Model.getValue(@html_id, current_tab)
|
||||
/*
|
||||
Function that registers 'modelUpdate' functions of every tab.
|
||||
These functions are used to update value, which will be returned
|
||||
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) ->
|
||||
###
|
||||
Function that registers 'modelUpdate' functions of every tab.
|
||||
These functions are used to update value, which will be returned
|
||||
by calling save on component.
|
||||
###
|
||||
@initialize(id)
|
||||
@modules[id].modelUpdate[tabName] = modelUpdateFunction
|
||||
/*
|
||||
html_id's of descriptors will be stored in modules variable as
|
||||
containers for callbacks.
|
||||
*/
|
||||
modules: {},
|
||||
Storage: {},
|
||||
initialize: function(id) {
|
||||
|
||||
addOnSwitch : (id, tabName, onSwitchFunction) ->
|
||||
###
|
||||
Function that registers functions invoked when switching
|
||||
to particular tab.
|
||||
###
|
||||
@initialize(id)
|
||||
@modules[id].tabSwitch[tabName] = onSwitchFunction
|
||||
/*
|
||||
Initialize objects per id. Id is html_id of descriptor.
|
||||
*/
|
||||
this.modules[id] = this.modules[id] || {};
|
||||
this.modules[id].tabSwitch = this.modules[id]['tabSwitch'] || {};
|
||||
return this.modules[id].modelUpdate = this.modules[id]['modelUpdate'] || {};
|
||||
}
|
||||
};
|
||||
|
||||
updateValue : (id, tabName) ->
|
||||
###
|
||||
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)
|
||||
TabsEditingDescriptor.setMetadataEditor = function(metadataEditor) {
|
||||
return TabsEditingDescriptor.Model.Storage['MetadataEditor'] = metadataEditor;
|
||||
};
|
||||
|
||||
getValue : (id, tabName) ->
|
||||
###
|
||||
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']
|
||||
TabsEditingDescriptor.addToStorage = function(id, data) {
|
||||
return TabsEditingDescriptor.Model.Storage[id] = data;
|
||||
};
|
||||
|
||||
# html_id's of descriptors will be stored in modules variable as
|
||||
# containers for callbacks.
|
||||
modules: {}
|
||||
Storage: {}
|
||||
TabsEditingDescriptor.getStorage = function() {
|
||||
return TabsEditingDescriptor.Model.Storage;
|
||||
};
|
||||
|
||||
initialize : (id) ->
|
||||
###
|
||||
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 {}
|
||||
return TabsEditingDescriptor;
|
||||
|
||||
@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
|
||||
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"
|
||||
|
||||
show_in_read_only_mode = True
|
||||
|
||||
@@ -642,7 +642,7 @@ class SequenceDescriptor(SequenceFields, ProctoringFields, MakoModuleDescriptor,
|
||||
show_in_read_only_mode = True
|
||||
|
||||
js = {
|
||||
'coffee': [resource_string(__name__, 'js/src/sequence/edit.coffee')],
|
||||
'js': [resource_string(__name__, 'js/src/sequence/edit.js')],
|
||||
}
|
||||
js_module_name = "SequenceDescriptor"
|
||||
|
||||
|
||||
@@ -92,8 +92,7 @@ class AnnotatableFields(object):
|
||||
|
||||
class TextAnnotationModule(AnnotatableFields, XModule):
|
||||
''' Text Annotation Module '''
|
||||
js = {'coffee': [],
|
||||
'js': []}
|
||||
js = {'js': []}
|
||||
css = {'scss': [resource_string(__name__, 'css/annotatable/display.scss')]}
|
||||
icon_class = 'textannotation'
|
||||
|
||||
|
||||
@@ -85,11 +85,9 @@ class AnnotatableFields(object):
|
||||
class VideoAnnotationModule(AnnotatableFields, XModule):
|
||||
'''Video Annotation Module'''
|
||||
js = {
|
||||
'coffee': [
|
||||
resource_string(__name__, 'js/src/html/display.coffee'),
|
||||
resource_string(__name__, 'js/src/annotatable/display.coffee'),
|
||||
],
|
||||
'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/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: 'edx-pattern-library/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/js/**/!(*spec).js'},
|
||||
{pattern: 'xmodule_js/src/**/*.js'}
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
'jquery.fileupload': 'js/vendor/jQuery-File-Upload/js/jquery.fileupload',
|
||||
'jquery.iframe-transport': 'js/vendor/jQuery-File-Upload/js/jquery.iframe-transport',
|
||||
'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.url': 'js/vendor/url.min',
|
||||
'sinon': 'common/js/vendor/sinon',
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
padding: 10px;
|
||||
background-color: #fff;
|
||||
/* 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
|
||||
*/
|
||||
font-family: 'Open Sans', Verdana, Arial, Helvetica, sans-serif;
|
||||
|
||||
@@ -1,16 +1,24 @@
|
||||
@AjaxPrefix =
|
||||
addAjaxPrefix: (jQuery, prefix) ->
|
||||
jQuery.postWithPrefix = (url, data, callback, type) ->
|
||||
$.post("#{prefix()}#{url}", data, callback, type)
|
||||
|
||||
jQuery.getWithPrefix = (url, data, callback, type) ->
|
||||
$.get("#{prefix()}#{url}", data, callback, type)
|
||||
|
||||
jQuery.ajaxWithPrefix = (url, settings) ->
|
||||
if settings?
|
||||
$.ajax("#{prefix()}#{url}", settings)
|
||||
else
|
||||
settings = url
|
||||
settings.url = "#{prefix()}#{settings.url}"
|
||||
$.ajax settings
|
||||
// Once generated by CoffeeScript 1.9.3, but now lives as pure JS
|
||||
/* eslint-disable */
|
||||
(function() {
|
||||
this.AjaxPrefix = {
|
||||
addAjaxPrefix: function(jQuery, prefix) {
|
||||
jQuery.postWithPrefix = function(url, data, callback, type) {
|
||||
return $.post("" + (prefix()) + url, data, callback, type);
|
||||
};
|
||||
jQuery.getWithPrefix = function(url, data, callback, type) {
|
||||
return $.get("" + (prefix()) + url, data, callback, type);
|
||||
};
|
||||
return jQuery.ajaxWithPrefix = function(url, settings) {
|
||||
if (settings != null) {
|
||||
return $.ajax("" + (prefix()) + url, 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
|
||||
# the first instance found down any path. For example, we'll find all
|
||||
# the ".xblock" elements below us, but not the ones that are themselves
|
||||
# contained somewhere inside ".xblock" elements.
|
||||
jQuery.fn.immediateDescendents = (selector) ->
|
||||
@children().map ->
|
||||
elem = jQuery(this)
|
||||
if elem.is(selector)
|
||||
this
|
||||
else
|
||||
elem.immediateDescendents(selector).get()
|
||||
// Once generated by CoffeeScript 1.9.3, but now lives as pure JS
|
||||
/* eslint-disable */
|
||||
|
||||
/*
|
||||
Find all the children of an element that match the selector, but only
|
||||
the first instance found down any path. For example, we'll find all
|
||||
the ".xblock" elements below us, but not the ones that are themselves
|
||||
contained somewhere inside ".xblock" elements.
|
||||
*/
|
||||
(function() {
|
||||
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
|
||||
|
||||
constructor: (seed, @parameters={}) ->
|
||||
// Once generated by CoffeeScript 1.9.3, but now lives as pure JS
|
||||
/* eslint-disable */
|
||||
(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: () ->
|
||||
console.error("Abstract method called: XProblemDisplay.getCurrentSubmission")
|
||||
XProblemGrader = (function() {
|
||||
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
|
||||
@evaluation = {}
|
||||
return XProblemGrader;
|
||||
|
||||
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
|
||||
root.XProblemDisplay = XProblemDisplay
|
||||
root.XProblemGrader = XProblemGrader
|
||||
}).call(this);
|
||||
|
||||
@@ -16,11 +16,11 @@ var options = {
|
||||
|
||||
// Avoid adding files to this list. Use RequireJS.
|
||||
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: 'common/js/vendor/jquery.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.timeago.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.
|
||||
// Otherwise Istanbul which is used for coverage tracking will cause tests to not run.
|
||||
sourceFiles: [
|
||||
{pattern: 'coffee/src/**/*.js', included: true},
|
||||
{pattern: 'common/js/xblock/core.js', included: true},
|
||||
{pattern: 'common/js/xblock/runtime.v1.js', included: true},
|
||||
{pattern: 'common/js/discussion/**/*.js', included: true},
|
||||
@@ -58,7 +57,6 @@ var options = {
|
||||
],
|
||||
|
||||
specFiles: [
|
||||
{pattern: 'coffee/spec/**/*.js', included: true},
|
||||
{pattern: 'common/js/spec/xblock/*.js', included: true},
|
||||
{pattern: 'common/js/spec/discussion/**/*spec.js', included: true},
|
||||
{pattern: 'js/**/*spec.js', included: true}
|
||||
|
||||
@@ -16,7 +16,6 @@ var options = {
|
||||
},
|
||||
|
||||
libraryFiles: [
|
||||
{pattern: 'coffee/src/**/*.js'},
|
||||
{pattern: 'js/libs/**/*.js'},
|
||||
{pattern: 'js/test/**/*.js'},
|
||||
{pattern: 'js/vendor/**/*.js'}
|
||||
|
||||
@@ -66,9 +66,8 @@ out when files are missing (added when we started dynamically scanning XBlocks
|
||||
for assets).
|
||||
|
||||
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
|
||||
remaining CoffeeScript files). Those are processed with paver tasks before
|
||||
``django-pipeline`` ever sees them.
|
||||
concatenation, but it does *not* know about the source Sass files.
|
||||
Those are processed with paver tasks before ``django-pipeline`` ever sees them.
|
||||
|
||||
We also have the following custom extensions to Django's builtin ``STATICFILES``
|
||||
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
|
||||
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
|
||||
optimized in any way -- so no coffeescript/sass compilation, no uglifyjs
|
||||
minification, etc.
|
||||
optimized in any way -- so no sass compilation, no uglifyjs minification, etc.
|
||||
|
||||
The django-pipeline dependency should be removed altogether.
|
||||
|
||||
|
||||
@@ -92,10 +92,10 @@ Test Locations
|
||||
|
||||
- Javascript unit tests: Located in ``spec`` folders. For example,
|
||||
``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,
|
||||
the test for ``src/views/module.coffee`` should be written in
|
||||
``spec/views/module_spec.coffee``.
|
||||
the test for ``src/views/module.js`` should be written in
|
||||
``spec/views/module_spec.js``.
|
||||
|
||||
- UI acceptance tests:
|
||||
|
||||
@@ -151,8 +151,8 @@ For example, this command runs all the python test scripts::
|
||||
paver test_python
|
||||
|
||||
It also runs ``collectstatic``, which prepares the
|
||||
static files used by the site (for example, compiling CoffeeScript to
|
||||
JavaScript).
|
||||
static files used by the site (for example, compiling Sass to
|
||||
CSS).
|
||||
|
||||
You can re-run all failed python tests by running this command (see note at end of
|
||||
section)::
|
||||
@@ -332,7 +332,6 @@ To run a specific set of JavaScript tests and print the results to the
|
||||
console, run these commands::
|
||||
|
||||
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-squire
|
||||
paver test_js_run -s xmodule
|
||||
@@ -342,7 +341,6 @@ console, 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-coffee
|
||||
paver test_js_dev -s cms
|
||||
paver test_js_dev -s cms-squire
|
||||
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
|
||||
# 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.
|
||||
query_features_names = {
|
||||
'id': _('User ID'),
|
||||
|
||||
@@ -48,7 +48,7 @@ lms/djangoapps/notes:
|
||||
|
||||
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
|
||||
|
||||
Interacts with:
|
||||
|
||||
@@ -448,7 +448,6 @@ system_node_path = os.environ.get("NODE_PATH", NODE_MODULES_ROOT)
|
||||
|
||||
node_paths = [
|
||||
COMMON_ROOT / "static/js/vendor",
|
||||
COMMON_ROOT / "static/coffee/src",
|
||||
system_node_path,
|
||||
]
|
||||
NODE_PATH = ':'.join(node_paths)
|
||||
@@ -1163,10 +1162,6 @@ EDXNOTES_READ_TIMEOUT = 1.5 # time in seconds
|
||||
# if parental consent is never required.
|
||||
PARENTAL_CONSENT_AGE_LIMIT = 13
|
||||
|
||||
################################# Jasmine ##################################
|
||||
JASMINE_TEST_DIRECTORY = PROJECT_ROOT + '/static/coffee'
|
||||
|
||||
|
||||
######################### Branded Footer ###################################
|
||||
# Constants for the footer used on the site and shared with other sites
|
||||
# (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
|
||||
|
||||
courseware_js = (
|
||||
[
|
||||
'coffee/src/' + pth + '.js'
|
||||
for pth in ['courseware', 'histogram', 'navigation']
|
||||
] +
|
||||
['js/' + pth + '.js' for pth in ['ajax-error']] +
|
||||
sorted(rooted_glob(PROJECT_ROOT / 'static', 'coffee/src/modules/**/*.js'))
|
||||
)
|
||||
courseware_js = [
|
||||
'js/ajax-error.js',
|
||||
'js/courseware.js',
|
||||
'js/histogram.js',
|
||||
'js/navigation.js',
|
||||
'js/modules/tab.js',
|
||||
]
|
||||
|
||||
proctoring_js = (
|
||||
[
|
||||
@@ -1428,9 +1422,9 @@ dashboard_js = (
|
||||
)
|
||||
discussion_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', 'coffee/src/mathjax_accessible.js') +
|
||||
rooted_glob(PROJECT_ROOT / 'static', 'coffee/src/mathjax_delay_renderer.js') +
|
||||
rooted_glob(PROJECT_ROOT / 'static', 'js/customwmd.js') +
|
||||
rooted_glob(PROJECT_ROOT / 'static', 'js/mathjax_accessible.js') +
|
||||
rooted_glob(PROJECT_ROOT / 'static', 'js/mathjax_delay_renderer.js') +
|
||||
sorted(rooted_glob(COMMON_ROOT / 'static', 'common/js/discussion/**/*.js'))
|
||||
)
|
||||
|
||||
@@ -1445,7 +1439,7 @@ discussion_vendor_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'))
|
||||
|
||||
verify_student_js = [
|
||||
@@ -1682,15 +1676,21 @@ PIPELINE_CSS = {
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
separately_bundled_js = set(courseware_js + discussion_js + notes_js + instructor_dash_js)
|
||||
common_js = sorted(set(rooted_glob(COMMON_ROOT / 'static', 'coffee/src/**/*.js')) - separately_bundled_js)
|
||||
common_js = [
|
||||
'js/src/ajax_prefix.js',
|
||||
'js/src/jquery.immediateDescendents.js',
|
||||
'js/src/xproblem.js',
|
||||
]
|
||||
xblock_runtime_js = [
|
||||
'common/js/xblock/core.js',
|
||||
'common/js/xblock/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 = {
|
||||
'base_application': {
|
||||
@@ -1796,10 +1796,6 @@ STATICFILES_IGNORE_PATTERNS = (
|
||||
"sass/*/*.scss",
|
||||
"sass/*/*/*.scss",
|
||||
"sass/*/*/*/*.scss",
|
||||
"coffee/*.coffee",
|
||||
"coffee/*/*.coffee",
|
||||
"coffee/*/*/*.coffee",
|
||||
"coffee/*/*/*/*.coffee",
|
||||
|
||||
# Ignore tests
|
||||
"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
|
||||
# * Space: Open or close hint popup. Select last focused hint item if opening
|
||||
/*
|
||||
Keyboard Support
|
||||
|
||||
# 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
|
||||
If focus is on the hint button:
|
||||
* Enter: Open or close hint popup. Select last focused hint item if opening
|
||||
* Space: Open or close hint popup. Select last focused hint item if opening
|
||||
|
||||
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
|
||||
constructor: ->
|
||||
@hintButton = $('#calculator_hint')
|
||||
@calcInput = $('#calculator_input')
|
||||
@hintPopup = $('.help')
|
||||
@hintsList = @hintPopup.find('.hint-item')
|
||||
@selectHint($('#' + @hintPopup.attr('data-calculator-hint')));
|
||||
(function() {
|
||||
this.Calculator = (function() {
|
||||
function Calculator() {
|
||||
this.hintButton = $('#calculator_hint');
|
||||
this.calcInput = $('#calculator_input');
|
||||
this.hintPopup = $('.help');
|
||||
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
|
||||
$('form#calculator').submit(@calculate).submit (e) ->
|
||||
e.preventDefault()
|
||||
Calculator.prototype.KEY = {
|
||||
TAB: 9,
|
||||
ENTER: 13,
|
||||
ESC: 27,
|
||||
SPACE: 32,
|
||||
LEFT: 37,
|
||||
UP: 38,
|
||||
RIGHT: 39,
|
||||
DOWN: 40
|
||||
};
|
||||
|
||||
@hintButton
|
||||
.click(($.proxy(@handleClickOnHintButton, @)))
|
||||
Calculator.prototype.toggle = function(event) {
|
||||
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, @)))
|
||||
|
||||
@hintPopup
|
||||
.keydown($.proxy(@handleKeyDownOnHint, @))
|
||||
|
||||
$('#calculator_wrapper')
|
||||
.keyup($.proxy(@handleKeyUpOnHint, @))
|
||||
|
||||
@handleClickOnDocument = $.proxy(@handleClickOnDocument, @)
|
||||
|
||||
@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
|
||||
/*
|
||||
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((function() {
|
||||
return $calcWrapper.find('#calculator_input').focus();
|
||||
}), 100);
|
||||
}
|
||||
$calc.attr({
|
||||
'title': text,
|
||||
'aria-expanded': isExpanded
|
||||
.find('.utility-control-label').text text
|
||||
|
||||
$calc
|
||||
.find('.icon')
|
||||
.removeClass('fa-calculator')
|
||||
.removeClass('fa-close')
|
||||
.addClass(icon)
|
||||
}).find('.utility-control-label').text(text);
|
||||
$calc.find('.icon').removeClass('fa-calculator').removeClass('fa-close').addClass(icon);
|
||||
return $calc.toggleClass('closed');
|
||||
};
|
||||
|
||||
$calc.toggleClass 'closed'
|
||||
|
||||
inputClickHandler: ->
|
||||
$('#calculator_output').removeClass('has-result')
|
||||
Calculator.prototype.inputClickHandler = function() {
|
||||
return $('#calculator_output').removeClass('has-result');
|
||||
};
|
||||
|
||||
showHint: ->
|
||||
@hintPopup
|
||||
.addClass('shown')
|
||||
.attr('aria-hidden', false)
|
||||
Calculator.prototype.showHint = function() {
|
||||
this.hintPopup.addClass('shown').attr('aria-hidden', false);
|
||||
$('#calculator_output').removeClass('has-result');
|
||||
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: ->
|
||||
@hintPopup
|
||||
.removeClass('shown')
|
||||
.attr('aria-hidden', true)
|
||||
|
||||
$('#calculator_output').removeClass('has-result')
|
||||
Calculator.prototype.prevHint = function() {
|
||||
|
||||
$(document).off('click', @handleClickOnDocument)
|
||||
/*
|
||||
the previous hint
|
||||
*/
|
||||
var prev;
|
||||
prev = this.activeHint.prev();
|
||||
|
||||
selectHint: (element) ->
|
||||
if not element or (element and element.length == 0)
|
||||
element = @hintsList.first()
|
||||
/*
|
||||
if this was the first item
|
||||
select the last one in the group.
|
||||
*/
|
||||
if (this.activeHint.index() === 0) {
|
||||
prev = this.hintsList.last();
|
||||
}
|
||||
|
||||
@activeHint = element;
|
||||
@activeHint.focus();
|
||||
@hintPopup.attr('data-calculator-hint', element.attr('id'));
|
||||
/*
|
||||
select the previous hint
|
||||
*/
|
||||
return this.selectHint(prev);
|
||||
};
|
||||
|
||||
prevHint: () ->
|
||||
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)
|
||||
Calculator.prototype.nextHint = function() {
|
||||
|
||||
nextHint: () ->
|
||||
next = @activeHint.next(); # the next hint
|
||||
# if this was the last item,
|
||||
# select the first one in the group.
|
||||
if @activeHint.index() == @hintsList.length - 1
|
||||
next = @hintsList.first()
|
||||
# give the next hint focus
|
||||
@selectHint(next)
|
||||
/*
|
||||
the next hint
|
||||
*/
|
||||
var next;
|
||||
next = this.activeHint.next();
|
||||
|
||||
handleKeyDown: (e) ->
|
||||
if e.altKey
|
||||
# do nothing
|
||||
return true
|
||||
/*
|
||||
if this was the last item,
|
||||
select the first one in the group.
|
||||
*/
|
||||
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'
|
||||
@hideHint()
|
||||
else
|
||||
@showHint()
|
||||
@activeHint.focus()
|
||||
/*
|
||||
give the next hint focus
|
||||
*/
|
||||
return this.selectHint(next);
|
||||
};
|
||||
|
||||
e.preventDefault()
|
||||
return false
|
||||
Calculator.prototype.handleKeyDown = function(e) {
|
||||
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
|
||||
# do nothing
|
||||
return true
|
||||
/*
|
||||
allow the event to propagate
|
||||
*/
|
||||
return true;
|
||||
};
|
||||
|
||||
switch e.keyCode
|
||||
Calculator.prototype.handleKeyDownOnHint = function(e) {
|
||||
if (e.altKey) {
|
||||
|
||||
when @KEY.ESC
|
||||
# hide popup with hints
|
||||
@hideHint()
|
||||
@hintButton.focus()
|
||||
/*
|
||||
do nothing
|
||||
*/
|
||||
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
|
||||
return true
|
||||
/*
|
||||
do nothing
|
||||
*/
|
||||
}
|
||||
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
|
||||
if e.shiftKey
|
||||
# do nothing
|
||||
return true
|
||||
Calculator.prototype.handleKeyUpOnHint = function(e) {
|
||||
switch (e.keyCode) {
|
||||
case this.KEY.TAB:
|
||||
|
||||
@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()
|
||||
return false
|
||||
Calculator.prototype.handleClickOnDocument = function(e) {
|
||||
return this.hideHint();
|
||||
};
|
||||
|
||||
# allow the event to propagate
|
||||
return true
|
||||
Calculator.prototype.handleClickOnHintButton = function(e) {
|
||||
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) ->
|
||||
switch e.keyCode
|
||||
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()
|
||||
Calculator.prototype.handleClickOnHintPopup = function(e) {
|
||||
return e.stopPropagation();
|
||||
};
|
||||
|
||||
handleClickOnDocument: (e) ->
|
||||
@hideHint()
|
||||
Calculator.prototype.calculate = function() {
|
||||
return $.getWithPrefix('/calculate', {
|
||||
equation: $('#calculator_input').val()
|
||||
}, function(data) {
|
||||
return $('#calculator_output').val(data.result).addClass('has-result').focus();
|
||||
});
|
||||
};
|
||||
|
||||
handleClickOnHintButton: (e) ->
|
||||
e.preventDefault()
|
||||
e.stopPropagation()
|
||||
if @hintPopup.hasClass 'shown'
|
||||
@hideHint()
|
||||
@hintButton.attr('aria-expanded', false)
|
||||
else
|
||||
@showHint()
|
||||
@hintButton.attr('aria-expanded', true)
|
||||
@activeHint.focus()
|
||||
return Calculator;
|
||||
|
||||
handleClickOnHintPopup: (e) ->
|
||||
e.stopPropagation()
|
||||
})();
|
||||
|
||||
calculate: ->
|
||||
$.getWithPrefix '/calculate', { equation: $('#calculator_input').val() }, (data) ->
|
||||
$('#calculator_output')
|
||||
.val(data.result)
|
||||
.addClass('has-result')
|
||||
.focus()
|
||||
}).call(this);
|
||||
|
||||
@@ -1,21 +1,38 @@
|
||||
class @Courseware
|
||||
@prefix: ''
|
||||
// Once generated by CoffeeScript 1.9.3, but now lives as pure JS
|
||||
/* eslint-disable */
|
||||
(function() {
|
||||
this.Courseware = (function() {
|
||||
Courseware.prefix = '';
|
||||
|
||||
constructor: ->
|
||||
Logger.bind()
|
||||
@render()
|
||||
function Courseware() {
|
||||
Logger.bind();
|
||||
this.render();
|
||||
}
|
||||
|
||||
@start: ->
|
||||
new Courseware
|
||||
Courseware.start = function() {
|
||||
return new Courseware;
|
||||
};
|
||||
|
||||
render: ->
|
||||
XBlock.initializeBlocks($('.course-content'))
|
||||
$('.course-content .histogram').each ->
|
||||
id = $(this).attr('id').replace(/histogram_/, '')
|
||||
try
|
||||
histg = new Histogram id, $(this).data('histogram')
|
||||
catch error
|
||||
histg = error
|
||||
if console?
|
||||
console.log(error)
|
||||
return histg
|
||||
Courseware.prototype.render = function() {
|
||||
XBlock.initializeBlocks($('.course-content'));
|
||||
return $('.course-content .histogram').each(function() {
|
||||
var error, histg, id;
|
||||
id = $(this).attr('id').replace(/histogram_/, '');
|
||||
try {
|
||||
histg = new Histogram(id, $(this).data('histogram'));
|
||||
} catch (_error) {
|
||||
error = _error;
|
||||
histg = error;
|
||||
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 = /// (
|
||||
\$\$? # 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
|
||||
MathJaxProcessor = (function() {
|
||||
|
||||
CODESPAN = ///
|
||||
(^|[^\\]) # match beginning or any previous character other than escape delimiter ('/')
|
||||
(`+) # code span starts
|
||||
([^\n]*?[^`\n]) # code content
|
||||
\2 # code span ends
|
||||
(?!`)
|
||||
///gm
|
||||
var CODESPAN, MATHSPLIT;
|
||||
|
||||
constructor: (inlineMark, displayMark) ->
|
||||
@inlineMark = inlineMark || "$"
|
||||
@displayMark = displayMark || "$$"
|
||||
@math = null
|
||||
@blocks = null
|
||||
/*
|
||||
\$\$? # 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
|
||||
*/
|
||||
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 || ""
|
||||
@math = []
|
||||
start = end = last = null
|
||||
braces = 0
|
||||
function MathJaxProcessor(inlineMark, displayMark) {
|
||||
this.inlineMark = inlineMark || "$";
|
||||
this.displayMark = displayMark || "$$";
|
||||
this.math = null;
|
||||
this.blocks = null;
|
||||
}
|
||||
|
||||
hasCodeSpans = /`/.test text
|
||||
if hasCodeSpans
|
||||
text = text.replace(/~/g, "~T").replace CODESPAN, ($0) -> # replace dollar sign in code span temporarily
|
||||
$0.replace /\$/g, "~D"
|
||||
deTilde = (text) ->
|
||||
text.replace /~([TD])/g, ($0, $1) ->
|
||||
{T: "~", D: "$"}[$1]
|
||||
else
|
||||
deTilde = (text) -> text
|
||||
MathJaxProcessor.prototype.processMath = function(start, last, preProcess) {
|
||||
var block, i, j, ref, ref1;
|
||||
block = this.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");
|
||||
}
|
||||
for (i = j = ref = start + 1, ref1 = last; ref <= ref1 ? j <= ref1 : j >= ref1; i = ref <= ref1 ? ++j : --j) {
|
||||
this.blocks[i] = "";
|
||||
}
|
||||
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]
|
||||
if block.charAt(0) == "@"
|
||||
@blocks[current] = "@@#{@math.length}@@"
|
||||
@math.push block
|
||||
else if start
|
||||
if block == end
|
||||
if braces
|
||||
last = current
|
||||
else
|
||||
@processMath(start, current, deTilde)
|
||||
start = end = last = null
|
||||
else if block.match /\n.*\n/
|
||||
if last
|
||||
current = last
|
||||
@processMath(start, current, deTilde)
|
||||
start = end = last = null
|
||||
braces = 0
|
||||
else if block == "{"
|
||||
++braces
|
||||
else if block == "}" and braces
|
||||
--braces
|
||||
else
|
||||
if block == @inlineMark or block == @displayMark
|
||||
start = current
|
||||
end = block
|
||||
braces = 0
|
||||
else if block.substr(1, 5) == "begin"
|
||||
start = current
|
||||
end = "\\end" + block.substr(6)
|
||||
braces = 0
|
||||
/*
|
||||
replace dollar sign in code span temporarily
|
||||
*/
|
||||
text = text.replace(/~/g, "~T").replace(CODESPAN, function($0) {
|
||||
return $0.replace(/\$/g, "~D");
|
||||
});
|
||||
deTilde = function(text) {
|
||||
return text.replace(/~([TD])/g, function($0, $1) {
|
||||
return {
|
||||
T: "~",
|
||||
D: "$"
|
||||
}[$1];
|
||||
});
|
||||
};
|
||||
} else {
|
||||
deTilde = function(text) {
|
||||
return text;
|
||||
};
|
||||
}
|
||||
this.blocks = _split(text.replace(/\r\n?/g, "\n"), MATHSPLIT);
|
||||
for (current = j = 1, ref = this.blocks.length; j < ref; current = j += 2) {
|
||||
block = this.blocks[current];
|
||||
if (block.charAt(0) === "@") {
|
||||
this.blocks[current] = "@@" + this.math.length + "@@";
|
||||
this.math.push(block);
|
||||
} else if (start) {
|
||||
if (block === end) {
|
||||
if (braces) {
|
||||
last = current;
|
||||
} else {
|
||||
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
|
||||
@processMath(start, last, deTilde)
|
||||
start = end = last = null
|
||||
MathJaxProcessor.removeMathWrapper = function(_this) {
|
||||
return function(text) {
|
||||
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) ->
|
||||
(text) -> _this.removeMath(text)
|
||||
MathJaxProcessor.replaceMathWrapper = function(_this) {
|
||||
return function(text) {
|
||||
return _this.replaceMath(text);
|
||||
};
|
||||
};
|
||||
|
||||
replaceMath: (text) ->
|
||||
text = text.replace /@@(\d+)@@/g, ($0, $1) => @math[$1]
|
||||
@math = null
|
||||
text
|
||||
return MathJaxProcessor;
|
||||
|
||||
@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) ->
|
||||
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
|
||||
}).call(this);
|
||||
|
||||
@@ -1,10 +1,23 @@
|
||||
class @FeedbackForm
|
||||
constructor: ->
|
||||
$('#feedback_button').click ->
|
||||
data =
|
||||
subject: $('#feedback_subject').val()
|
||||
message: $('#feedback_message').val()
|
||||
url: window.location.href
|
||||
$.postWithPrefix '/send_feedback', data, ->
|
||||
$('#feedback_div').html 'Feedback submitted. Thank you'
|
||||
,'json'
|
||||
// Once generated by CoffeeScript 1.9.3, but now lives as pure JS
|
||||
/* eslint-disable */
|
||||
(function() {
|
||||
this.FeedbackForm = (function() {
|
||||
function FeedbackForm() {
|
||||
$('#feedback_button').click(function() {
|
||||
var data;
|
||||
data = {
|
||||
subject: $('#feedback_subject').val(),
|
||||
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
|
||||
constructor: (@id, @rawData) ->
|
||||
@xTicks = []
|
||||
@yTicks = []
|
||||
@data = []
|
||||
@calculate()
|
||||
@render()
|
||||
// Once generated by CoffeeScript 1.9.3, but now lives as pure JS
|
||||
/* eslint-disable */
|
||||
(function() {
|
||||
this.Histogram = (function() {
|
||||
function Histogram(id, rawData) {
|
||||
this.id = id;
|
||||
this.rawData = rawData;
|
||||
this.xTicks = [];
|
||||
this.yTicks = [];
|
||||
this.data = [];
|
||||
this.calculate();
|
||||
this.render();
|
||||
}
|
||||
|
||||
calculate: ->
|
||||
for [score, count] in @rawData
|
||||
continue if score == null
|
||||
log_count = Math.log(count + 1)
|
||||
@data.push [score, log_count]
|
||||
@xTicks.push [score, score.toString()]
|
||||
@yTicks.push [log_count, count.toString()]
|
||||
Histogram.prototype.calculate = function() {
|
||||
var count, i, len, log_count, ref, ref1, results, score;
|
||||
ref = this.rawData;
|
||||
results = [];
|
||||
for (i = 0, len = ref.length; i < len; i++) {
|
||||
ref1 = ref[i], score = ref1[0], count = ref1[1];
|
||||
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: ->
|
||||
$.plot $("#histogram_#{@id}"), [
|
||||
data: @data
|
||||
bars:
|
||||
show: true
|
||||
align: 'center'
|
||||
lineWidth: 0
|
||||
fill: 1.0
|
||||
color: "#b72121"
|
||||
],
|
||||
xaxis:
|
||||
min: -1
|
||||
max: Math.max.apply Math, $.map(@xTicks, (data) -> data[0] + 1)
|
||||
ticks: @xTicks
|
||||
tickLength: 0
|
||||
yaxis:
|
||||
min: 0.0
|
||||
max: Math.max.apply Math, $.map(@yTicks, (data) -> data[0] * 1.1)
|
||||
ticks: @yTicks
|
||||
labelWidth: 50
|
||||
Histogram.prototype.render = function() {
|
||||
return $.plot($("#histogram_" + this.id), [
|
||||
{
|
||||
data: this.data,
|
||||
bars: {
|
||||
show: true,
|
||||
align: 'center',
|
||||
lineWidth: 0,
|
||||
fill: 1.0
|
||||
},
|
||||
color: "#b72121"
|
||||
}
|
||||
], {
|
||||
xaxis: {
|
||||
min: -1,
|
||||
max: Math.max.apply(Math, $.map(this.xTicks, function(data) {
|
||||
return data[0] + 1;
|
||||
})),
|
||||
ticks: this.xTicks,
|
||||
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,
|
||||
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
|
||||
failures. If one piece of code under a plantTimeout fails
|
||||
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.
|
||||
|
||||
NOTE: For an example of what a section object should look like
|
||||
see course_info.coffee
|
||||
see course_info.js
|
||||
|
||||
imports from other modules
|
||||
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');
|
||||
});
|
||||
|
||||
$ ->
|
||||
$.ajaxSetup
|
||||
headers : { 'X-CSRFToken': $.cookie 'csrftoken' }
|
||||
dataType: 'json'
|
||||
$(function() {
|
||||
$.ajaxSetup({
|
||||
headers: {
|
||||
'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()
|
||||
$('#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
|
||||
}).call(this);
|
||||
|
||||
@@ -1,21 +1,37 @@
|
||||
$ ->
|
||||
if window.navigator.appName is "Microsoft Internet Explorer"
|
||||
isMPInstalled = (boolean) ->
|
||||
# check if MathPlayer is installed
|
||||
# (from http://www.dessci.com/en/products/mathplayer/check.htm)
|
||||
try
|
||||
oMP = new ActiveXObject("MathPlayer.Factory.1")
|
||||
true
|
||||
catch e
|
||||
false
|
||||
// Once generated by CoffeeScript 1.9.3, but now lives as pure JS
|
||||
/* eslint-disable */
|
||||
(function() {
|
||||
$(function() {
|
||||
var isMPInstalled;
|
||||
if (window.navigator.appName === "Microsoft Internet Explorer") {
|
||||
isMPInstalled = function(boolean) {
|
||||
var e, oMP;
|
||||
/*
|
||||
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'
|
||||
if MathJax? and not isMPInstalled()
|
||||
$("#mathjax-accessibility-message").attr("aria-hidden", "false")
|
||||
/*
|
||||
detect if there is mathjax on the page
|
||||
if not, set 'aria-hidden' to 'true'
|
||||
*/
|
||||
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
|
||||
$("#mathplayer-browser-message").attr("aria-hidden", "false")
|
||||
|
||||
else
|
||||
$("#mathjax-accessibility-message").attr("aria-hidden", "true")
|
||||
}).call(this);
|
||||
|
||||
@@ -1,73 +1,109 @@
|
||||
getTime = ->
|
||||
new Date().getTime()
|
||||
// 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)
|
||||
(function() {
|
||||
var getTime;
|
||||
|
||||
class @MathJaxDelayRenderer
|
||||
getTime = function() {
|
||||
return new Date().getTime();
|
||||
};
|
||||
|
||||
maxDelay: 3000
|
||||
mathjaxRunning: false
|
||||
elapsedTime: 0
|
||||
mathjaxDelay: 0
|
||||
mathjaxTimeout: undefined
|
||||
bufferId = "mathjax_delay_buffer"
|
||||
numBuffers = 0
|
||||
this.MathJaxDelayRenderer = (function() {
|
||||
var bufferId, numBuffers;
|
||||
|
||||
constructor: (params) ->
|
||||
params = params || {}
|
||||
@maxDelay = params["maxDelay"] || @maxDelay
|
||||
@bufferId = params["bufferId"] || (bufferId + numBuffers)
|
||||
numBuffers += 1
|
||||
@$buffer = $("<div>").attr("id", @bufferId).css("display", "none").appendTo($("body"))
|
||||
MathJaxDelayRenderer.prototype.maxDelay = 3000;
|
||||
|
||||
# render: (params) ->
|
||||
# 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
|
||||
MathJaxDelayRenderer.prototype.mathjaxRunning = false;
|
||||
|
||||
render: (params) ->
|
||||
MathJaxDelayRenderer.prototype.elapsedTime = 0;
|
||||
|
||||
elem = params["element"]
|
||||
previewSetter = params["previewSetter"]
|
||||
text = params["text"]
|
||||
if not text?
|
||||
text = $(elem).html()
|
||||
preprocessor = params["preprocessor"]
|
||||
MathJaxDelayRenderer.prototype.mathjaxDelay = 0;
|
||||
|
||||
if params["delay"] == false
|
||||
if preprocessor?
|
||||
text = preprocessor(text)
|
||||
$(elem).html(text)
|
||||
MathJax.Hub.Queue ["Typeset", MathJax.Hub, $(elem).attr("id")]
|
||||
else
|
||||
if @mathjaxTimeout
|
||||
window.clearTimeout(@mathjaxTimeout)
|
||||
@mathjaxTimeout = undefined
|
||||
delay = Math.min @elapsedTime + @mathjaxDelay, @maxDelay
|
||||
|
||||
renderer = =>
|
||||
if @mathjaxRunning
|
||||
return
|
||||
prevTime = getTime()
|
||||
if preprocessor?
|
||||
text = preprocessor(text)
|
||||
@$buffer.html(text)
|
||||
curTime = getTime()
|
||||
@elapsedTime = curTime - prevTime
|
||||
if MathJax?
|
||||
prevTime = getTime()
|
||||
@mathjaxRunning = true
|
||||
MathJax.Hub.Queue ["Typeset", MathJax.Hub, @$buffer.attr("id")], =>
|
||||
@mathjaxRunning = false
|
||||
curTime = getTime()
|
||||
@mathjaxDelay = curTime - prevTime
|
||||
if previewSetter
|
||||
previewSetter($(@$buffer).html())
|
||||
else
|
||||
$(elem).html($(@$buffer).html())
|
||||
else
|
||||
@mathjaxDelay = 0
|
||||
@mathjaxTimeout = window.setTimeout(renderer, delay)
|
||||
MathJaxDelayRenderer.prototype.mathjaxTimeout = void 0;
|
||||
|
||||
bufferId = "mathjax_delay_buffer";
|
||||
|
||||
numBuffers = 0;
|
||||
|
||||
function MathJaxDelayRenderer(params) {
|
||||
params = params || {};
|
||||
this.maxDelay = params["maxDelay"] || this.maxDelay;
|
||||
this.bufferId = params["bufferId"] || (bufferId + numBuffers);
|
||||
numBuffers += 1;
|
||||
this.$buffer = $("<div>").attr("id", this.bufferId).css("display", "none").appendTo($("body")); // xss-lint: disable=javascript-jquery-insert-into-target
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
render: (params) ->
|
||||
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
|
||||
*/
|
||||
|
||||
MathJaxDelayRenderer.prototype.render = function(params) {
|
||||
var delay, elem, preprocessor, previewSetter, renderer, text;
|
||||
elem = params["element"];
|
||||
previewSetter = params["previewSetter"];
|
||||
text = params["text"];
|
||||
if (text == null) {
|
||||
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
|
||||
constructor: (@id, @items) ->
|
||||
@el = $("#tab_#{id}")
|
||||
@render()
|
||||
// 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)
|
||||
(function() {
|
||||
var bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; };
|
||||
|
||||
$: (selector) ->
|
||||
$(selector, @el)
|
||||
this.Tab = (function() {
|
||||
function Tab(id1, items) {
|
||||
this.id = id1;
|
||||
this.items = items;
|
||||
this.onShow = bind(this.onShow, this);
|
||||
this.el = $("#tab_" + id);
|
||||
this.render();
|
||||
}
|
||||
|
||||
render: ->
|
||||
$.each @items, (index, item) =>
|
||||
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
|
||||
Tab.prototype.$ = function(selector) {
|
||||
return $(selector, this.el);
|
||||
};
|
||||
|
||||
onShow: (element, ui) =>
|
||||
@$('section.ui-tabs-hide').html('')
|
||||
@$("##{@tabId(ui.index)}").html(@items[ui.index]['content'])
|
||||
@el.trigger 'contentChanged'
|
||||
Tab.prototype.render = function() {
|
||||
$.each(this.items, (function(_this) {
|
||||
return function(index, item) {
|
||||
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-#{@id}-#{index}"
|
||||
Tab.prototype.onShow = function(element, ui) {
|
||||
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.
|
||||
// Until the pipeline issue is resolved this file is here. It shouldn't
|
||||
// conflict with anything.
|
||||
var nothingtoseehere;
|
||||
var nothingtoseehere;
|
||||
@@ -1,97 +1,168 @@
|
||||
class StudentNotes
|
||||
_debug: false
|
||||
// Once generated by CoffeeScript 1.9.3, but now lives as pure JS
|
||||
/* 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
|
||||
$(el).delegate('*', events)
|
||||
$(el).data('notes-instance', @)
|
||||
/*
|
||||
holds elements with annotator() instances
|
||||
*/
|
||||
|
||||
# Initializes annotations on a container element in response to an init event.
|
||||
onInitNotes: (event, uri=null, storage_url=null, token=null) =>
|
||||
event.stopPropagation()
|
||||
StudentNotes.prototype.targets = [];
|
||||
|
||||
found = @targets.some (target) -> target is event.target
|
||||
|
||||
# Get uri
|
||||
unless uri.substring(0, 4) is "http"
|
||||
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]
|
||||
/*
|
||||
Adds a listener for "notes" events that may bubble up from descendants.
|
||||
*/
|
||||
|
||||
# Get id and name user
|
||||
idUdiv = $(event.target).parent().find(".idU")[0]
|
||||
idDUdiv = $(event.target).parent().find(".idDU")[0]
|
||||
idUdiv = (if typeof idUdiv isnt "undefined" then idUdiv.innerHTML else "")
|
||||
idDUdiv = (if typeof idDUdiv isnt "undefined" then idDUdiv.innerHTML else "")
|
||||
|
||||
options =
|
||||
optionsAnnotator:
|
||||
permissions:
|
||||
user:
|
||||
id: idUdiv
|
||||
name: idDUdiv
|
||||
function StudentNotes($, el) {
|
||||
this.onInitNotes = bind(this.onInitNotes, this);
|
||||
var events;
|
||||
if (this._debug) {
|
||||
console.log('student notes init', arguments, this);
|
||||
}
|
||||
if (!$(el).data('notes-instance')) {
|
||||
events = {
|
||||
'notes:init': this.onInitNotes
|
||||
};
|
||||
$(el).delegate('*', events);
|
||||
$(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
|
||||
user
|
||||
auth:
|
||||
token: token
|
||||
/*
|
||||
Initializes annotations on a container element in response to an init event.
|
||||
*/
|
||||
|
||||
store:
|
||||
prefix: storage_url
|
||||
StudentNotes.prototype.onInitNotes = function(event, uri, storage_url, token) {
|
||||
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',
|
||||
read: '/read/:id',
|
||||
update: '/update/:id',
|
||||
destroy: '/delete/:id',
|
||||
search: '/search'
|
||||
/*
|
||||
Get id and name user
|
||||
*/
|
||||
idUdiv = $(event.target).parent().find(".idU")[0];
|
||||
idDUdiv = $(event.target).parent().find(".idDU")[0];
|
||||
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:
|
||||
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)
|
||||
return 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 ($) -> 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.
|
||||
// Otherwise Istanbul which is used for coverage tracking will cause tests to not run.
|
||||
sourceFiles: [
|
||||
{pattern: 'coffee/src/**/!(*spec).js'},
|
||||
{pattern: 'course_bookmarks/**/!(*spec).js'},
|
||||
{pattern: 'course_search/**/!(*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: {
|
||||
gettext: 'empty:',
|
||||
'coffee/src/ajax_prefix': 'empty:',
|
||||
'js/src/ajax_prefix': 'empty:',
|
||||
jquery: 'empty:',
|
||||
'jquery-migrate': 'empty:',
|
||||
'jquery.cookie': 'empty:',
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
'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.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.timeago': 'xmodule_js/common_static/js/vendor/jquery.timeago',
|
||||
'jquery.url': 'xmodule_js/common_static/js/vendor/url.min',
|
||||
@@ -58,7 +58,7 @@
|
||||
'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
|
||||
'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',
|
||||
'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',
|
||||
@@ -71,8 +71,8 @@
|
||||
'Markdown.Editor': 'js/Markdown.Editor',
|
||||
'Markdown.Sanitizer': 'js/Markdown.Sanitizer',
|
||||
'_split': 'js/split',
|
||||
'mathjax_delay_renderer': 'coffee/src/mathjax_delay_renderer',
|
||||
'MathJaxProcessor': 'coffee/src/customwmd',
|
||||
'mathjax_delay_renderer': 'js/mathjax_delay_renderer',
|
||||
'MathJaxProcessor': 'js/customwmd',
|
||||
'picturefill': 'common/js/vendor/picturefill',
|
||||
'bootstrap': 'common/js/vendor/bootstrap.bundle',
|
||||
'draggabilly': 'xmodule_js/common_static/js/vendor/draggabilly',
|
||||
@@ -282,7 +282,7 @@
|
||||
},
|
||||
'xmodule_js/common_static/js/test/add_ajax_prefix': {
|
||||
exports: 'AjaxPrefix',
|
||||
deps: ['coffee/src/ajax_prefix']
|
||||
deps: ['js/src/ajax_prefix']
|
||||
},
|
||||
'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
|
||||
## feature is on.
|
||||
## 3. Add a url() entry in api_urls.py
|
||||
## 4. Over in lms/static/coffee/src/instructor_dashboard/ there there are .coffee files
|
||||
## for each page which define the .js. Edit this to make your input do something
|
||||
## when clicked. The .coffee files use the name=xx to pick out inputs, not id=
|
||||
## 4. Over in lms/static/js/instructor_dashboard/ there are .js files for each page.
|
||||
## Edit this to make your input do something when clicked. The .js files use the
|
||||
## name=xx to pick out inputs, not id=
|
||||
## 5. Implement your standard django/python in lms/djangoapps/instructor/views/api.py
|
||||
## 6. And tests go in lms/djangoapps/instructor/tests/
|
||||
|
||||
@@ -110,7 +110,7 @@ from openedx.core.djangolib.markup import HTML
|
||||
</div>
|
||||
|
||||
## 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
|
||||
<ul class="instructor-nav">
|
||||
% 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",
|
||||
"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": {
|
||||
"version": "1.0.3",
|
||||
"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",
|
||||
"camelize": "1.0.0",
|
||||
"classnames": "2.2.5",
|
||||
"coffee-loader": "0.7.3",
|
||||
"coffee-script": "1.6.1",
|
||||
"css-loader": "0.28.8",
|
||||
"edx-pattern-library": "0.18.1",
|
||||
"edx-ui-toolkit": "1.5.2",
|
||||
|
||||
@@ -28,7 +28,6 @@ from .utils.timer import timed
|
||||
# setup baseline paths
|
||||
|
||||
ALL_SYSTEMS = ['lms', 'studio']
|
||||
COFFEE_DIRS = ['lms', 'cms', 'common']
|
||||
|
||||
LMS = 'lms'
|
||||
CMS = 'cms'
|
||||
@@ -301,32 +300,6 @@ def debounce(seconds=1):
|
||||
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):
|
||||
"""
|
||||
Watches for sass file changes
|
||||
@@ -403,28 +376,6 @@ class XModuleAssetsWatcher(PatternMatchingEventHandler):
|
||||
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
|
||||
@no_help
|
||||
@cmdopts([
|
||||
@@ -736,7 +687,6 @@ def collect_assets(systems, settings, **kwargs):
|
||||
|
||||
# We compile these out, don't need the source files in staticfiles
|
||||
"sass",
|
||||
"*.coffee",
|
||||
]
|
||||
|
||||
ignore_args = " ".join(
|
||||
@@ -906,7 +856,6 @@ def watch_assets(options):
|
||||
sass_directories = get_watcher_dirs(theme_dirs, themes)
|
||||
observer = Observer(timeout=wait)
|
||||
|
||||
CoffeeScriptWatcher().register(observer)
|
||||
SassWatcher().register(observer, sass_directories)
|
||||
XModuleSassWatcher().register(observer, ['common/lib/xmodule/'])
|
||||
XModuleAssetsWatcher().register(observer)
|
||||
@@ -936,7 +885,7 @@ def watch_assets(options):
|
||||
@timed
|
||||
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.add_argument(
|
||||
@@ -980,7 +929,6 @@ def update_assets(args):
|
||||
|
||||
process_xmodule_assets()
|
||||
process_npm_assets()
|
||||
compile_coffeescript()
|
||||
|
||||
# Build Webpack
|
||||
call_task('pavelib.assets.webpack', options={'settings': args.settings})
|
||||
|
||||
@@ -25,7 +25,6 @@ DEFAULT_SETTINGS = Env.DEVSTACK_SETTINGS
|
||||
@needs(
|
||||
"pavelib.prereqs.install_prereqs",
|
||||
"pavelib.i18n.i18n_validate_gettext",
|
||||
"pavelib.assets.compile_coffeescript",
|
||||
)
|
||||
@cmdopts([
|
||||
("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_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 = (
|
||||
u"{config_file} "
|
||||
u"--single-run={single_run} "
|
||||
@@ -120,7 +116,6 @@ class TestPaverJavaScriptTestTasks(PaverTestCase):
|
||||
platform_root=self.platform_root
|
||||
))
|
||||
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:
|
||||
# Karma test command
|
||||
|
||||
@@ -6,10 +6,6 @@ from paver.easy import call_task
|
||||
from ..utils.envs import Env
|
||||
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 = (
|
||||
u"libsass {sass_directory}"
|
||||
)
|
||||
@@ -33,7 +29,7 @@ EXPECTED_COLLECT_STATIC_COMMAND = (
|
||||
u'python manage.py {system} --settings={asset_settings} collectstatic '
|
||||
u'--ignore "fixtures" --ignore "karma_*.js" --ignore "spec" '
|
||||
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}'
|
||||
)
|
||||
EXPECTED_CELERY_COMMAND = (
|
||||
@@ -247,7 +243,6 @@ class TestPaverServerTasks(PaverTestCase):
|
||||
if not is_fast:
|
||||
expected_messages.append(u"xmodule_assets common/static/xmodule")
|
||||
expected_messages.append(u"install npm_assets")
|
||||
expected_messages.append(EXPECTED_COFFEE_COMMAND.format(platform_root=self.platform_root))
|
||||
expected_messages.extend(
|
||||
[c.format(settings=expected_asset_settings) for c in EXPECTED_PRINT_SETTINGS_COMMAND]
|
||||
)
|
||||
@@ -293,7 +288,6 @@ class TestPaverServerTasks(PaverTestCase):
|
||||
if not is_fast:
|
||||
expected_messages.append(u"xmodule_assets common/static/xmodule")
|
||||
expected_messages.append(u"install npm_assets")
|
||||
expected_messages.append(EXPECTED_COFFEE_COMMAND.format(platform_root=self.platform_root))
|
||||
expected_messages.extend(
|
||||
[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_squire.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/static/karma_common.conf.js',
|
||||
REPO_ROOT / 'common/static/karma_common_requirejs.conf.js',
|
||||
@@ -192,7 +191,6 @@ class Env(object):
|
||||
'cms',
|
||||
'cms-squire',
|
||||
'lms',
|
||||
'lms-coffee',
|
||||
'xmodule',
|
||||
'common',
|
||||
'common-requirejs'
|
||||
|
||||
@@ -39,7 +39,6 @@ class JsTestSuite(TestSuite):
|
||||
test_utils.clean_dir(self.report_dir)
|
||||
|
||||
assets.process_npm_assets()
|
||||
assets.compile_coffeescript("`find lms cms common -type f -name \"*.coffee\"`")
|
||||
|
||||
@property
|
||||
def _default_subsuites(self):
|
||||
@@ -51,7 +50,7 @@ class JsTestSuite(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
|
||||
"""
|
||||
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