Skip to content

Commit

Permalink
remove mathjax form main xmodule requirement and add it on problem ad…
Browse files Browse the repository at this point in the history
…ding

TNL-823
  • Loading branch information
zubair-arbi committed Nov 25, 2014
1 parent 7b36645 commit ef3d181
Show file tree
Hide file tree
Showing 3 changed files with 173 additions and 166 deletions.
5 changes: 2 additions & 3 deletions common/djangoapps/pipeline_js/templates/xmodule.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,13 @@
## These files assume that several libraries are available and bound to
## variables in the global context, so we load those libraries with requirejs
## and attach them to the global context manually.
define(["jquery", "underscore", "mathjax", "codemirror", "tinymce",
define(["jquery", "underscore", "codemirror", "tinymce",
"jquery.tinymce", "jquery.qtip", "jquery.scrollTo", "jquery.flot",
"jquery.cookie",
"utility"],
function($, _, MathJax, CodeMirror, tinymce) {
function($, _, CodeMirror, tinymce) {
window.$ = $;
window._ = _;
window.MathJax = MathJax;
window.CodeMirror = CodeMirror;
window.RequireJS = {
'requirejs': requirejs,
Expand Down
329 changes: 166 additions & 163 deletions common/static/js/capa/src/formula_equation_preview.js
Original file line number Diff line number Diff line change
@@ -1,172 +1,175 @@
var formulaEquationPreview = {
minDelay: 300, // Minimum time between requests sent out.
errorDelay: 1500 // Wait time before showing error (prevent frustration).
};

/** Setup the FormulaEquationInputs and associated javascript code. */
formulaEquationPreview.enable = function () {

/**
* Accumulate all the variables and attach event handlers.
* This includes rate-limiting `sendRequest` and creating a closure for
* its callback.
*/
function setupInput() {
var $this = $(this); // cache the jQuery object

var $preview = $("#" + this.id + "_preview");
var inputData = {
// These are the mutable values

lastSent: 0,
isWaitingForRequest: false,
requestVisible: 0,
errorDelayTimeout: null,

// The following don't change

// Find the URL from the closest parent problems-wrapper.
url: $this.closest('.problems-wrapper').data('url'),
// Grab the input id from the input.
inputId: $this.data('input-id'),

// Store the DOM/MathJax elements in which visible output occurs.
$preview: $preview,
jax: null, // Fill this in later.
$img: $preview.find("img.loading"),

requestCallback: null // Fill it in in a bit.
};

// Give callback access to `inputData` (fill in first parameter).
inputData.requestCallback = _.partial(updatePage, inputData);

// Limit `sendRequest` and have it show the loading icon.
var throttledRequest = _.throttle(
sendRequest,
formulaEquationPreview.minDelay,
{leading: false}
);
// The following acts as a closure of `inputData`.
var initializeRequest = function () {
// Show the loading icon.
inputData.$img.css('visibility', 'visible');

// Say we are waiting for request.
inputData.isWaitingForRequest = true;
// First thing in `sendRequest`, say we aren't anymore.
throttledRequest(inputData, this.value);
};

$this.on("input", initializeRequest);
// Ask for initial preview.
initializeRequest.call(this);
}

/**
* Fire off a request for a preview of the current value.
* Also send along the time it was sent, and store that locally.
*/
function sendRequest(inputData, formula) {
// Save the time.
var now = Date.now();
inputData.lastSent = now;
// We're sending it.
inputData.isWaitingForRequest = false;

if (formula) {
// Send the request.
Problem.inputAjax(
inputData.url,
inputData.inputId,
'preview_formcalc',
{"formula" : formula, "request_start" : now},
inputData.requestCallback
require(['jquery', 'mathjax'], function() {
window.MathJax = MathJax;

var formulaEquationPreview = {
minDelay: 300, // Minimum time between requests sent out.
errorDelay: 1500 // Wait time before showing error (prevent frustration).
};

/** Setup the FormulaEquationInputs and associated javascript code. */
formulaEquationPreview.enable = function () {

/**
* Accumulate all the variables and attach event handlers.
* This includes rate-limiting `sendRequest` and creating a closure for
* its callback.
*/
function setupInput() {
var $this = $(this); // cache the jQuery object

var $preview = $("#" + this.id + "_preview");
var inputData = {
// These are the mutable values

lastSent: 0,
isWaitingForRequest: false,
requestVisible: 0,
errorDelayTimeout: null,

// The following don't change
// Find the URL from the closest parent problems-wrapper.
url: $this.closest('.problems-wrapper').data('url'),
// Grab the input id from the input.
inputId: $this.data('input-id'),

// Store the DOM/MathJax elements in which visible output occurs.
$preview: $preview,
jax: null, // Fill this in later.
$img: $preview.find("img.loading"),

requestCallback: null // Fill it in in a bit.
};

// Give callback access to `inputData` (fill in first parameter).
inputData.requestCallback = _.partial(updatePage, inputData);

// Limit `sendRequest` and have it show the loading icon.
var throttledRequest = _.throttle(
sendRequest,
formulaEquationPreview.minDelay,
{leading: false}
);
// ).fail(function () {
// // This is run when ajax call fails.
// // Have an error message and other stuff here?
// inputData.$img.css('visibility', 'hidden');
// });
}
else {
inputData.requestCallback({
preview: '',
request_start: now
});
}
}

/**
* Respond to the preview request if need be.
* Stop if it is outdated (i.e. a later request arrived back earlier)
* Otherwise:
* -Refresh the MathJax
* -Stop the loading icon if this is the most recent request
* -Save which request is visible
*/
function updatePage(inputData, response) {
var requestStart = response['request_start'];
if (requestStart == inputData.lastSent &&
!inputData.isWaitingForRequest) {
// Disable icon.
inputData.$img.css('visibility', 'hidden');
}

if (requestStart <= inputData.requestVisible) {
// This is an old request.
return;
}

// Save the value of the last response displayed.
inputData.requestVisible = requestStart;

// Prevent an old error message from showing.
if (inputData.errorWaitTimeout != null) {
window.clearTimeout(inputData.errorWaitTimeout);
// The following acts as a closure of `inputData`.
var initializeRequest = function () {
// Show the loading icon.
inputData.$img.css('visibility', 'visible');

// Say we are waiting for request.
inputData.isWaitingForRequest = true;
// First thing in `sendRequest`, say we aren't anymore.
throttledRequest(inputData, this.value);
};

$this.on("input", initializeRequest);
// Ask for initial preview.
initializeRequest.call(this);
}

function display(latex) {
MathJax.Hub.Startup.signal.Interest(function (message) {
if(message === "End") {
var previewElement = inputData.$preview[0];
MathJax.Hub.Queue(function () {
inputData.jax = MathJax.Hub.getAllJax(previewElement)[0];
});

MathJax.Hub.Queue(function () {
// Check if MathJax is loaded
if (inputData.jax) {
// Set the text as the latex code, and then update the MathJax.
MathJax.Hub.Queue(
['Text', inputData.jax, latex],
['Reprocess', inputData.jax]
);
} else if (latex) {
console.log("[FormulaEquationInput] Oops no mathjax for ", latex);
// Fall back to modifying the actual element.
var textNode = previewElement.childNodes[0];
textNode.data = "\\[" + latex + "\\]";
MathJax.Hub.Queue(["Typeset", MathJax.Hub, previewElement]);
}
});
}
});
/**
* Fire off a request for a preview of the current value.
* Also send along the time it was sent, and store that locally.
*/
function sendRequest(inputData, formula) {
// Save the time.
var now = Date.now();
inputData.lastSent = now;
// We're sending it.
inputData.isWaitingForRequest = false;

if (formula) {
// Send the request.
Problem.inputAjax(
inputData.url,
inputData.inputId,
'preview_formcalc',
{"formula" : formula, "request_start" : now},
inputData.requestCallback
);
// ).fail(function () {
// // This is run when ajax call fails.
// // Have an error message and other stuff here?
// inputData.$img.css('visibility', 'hidden');
// });
}
else {
inputData.requestCallback({
preview: '',
request_start: now
});
}
}

if (response.error) {
inputData.$img.css('visibility', 'visible');
inputData.errorWaitTimeout = window.setTimeout(function () {
display("\\text{" + response.error + "}");
/**
* Respond to the preview request if need be.
* Stop if it is outdated (i.e. a later request arrived back earlier)
* Otherwise:
* -Refresh the MathJax
* -Stop the loading icon if this is the most recent request
* -Save which request is visible
*/
function updatePage(inputData, response) {
var requestStart = response['request_start'];
if (requestStart == inputData.lastSent &&
!inputData.isWaitingForRequest) {
// Disable icon.
inputData.$img.css('visibility', 'hidden');
}, formulaEquationPreview.errorDelay);
} else {
display(response.preview);
}

if (requestStart <= inputData.requestVisible) {
// This is an old request.
return;
}

// Save the value of the last response displayed.
inputData.requestVisible = requestStart;

// Prevent an old error message from showing.
if (inputData.errorWaitTimeout != null) {
window.clearTimeout(inputData.errorWaitTimeout);
}

function display(latex) {
MathJax.Hub.Startup.signal.Interest(function (message) {
if(message === "End") {
var previewElement = inputData.$preview[0];
MathJax.Hub.Queue(function () {
inputData.jax = MathJax.Hub.getAllJax(previewElement)[0];
});

MathJax.Hub.Queue(function () {
// Check if MathJax is loaded
if (inputData.jax) {
// Set the text as the latex code, and then update the MathJax.
MathJax.Hub.Queue(
['Text', inputData.jax, latex],
['Reprocess', inputData.jax]
);
} else if (latex) {
console.log("[FormulaEquationInput] Oops no mathjax for ", latex);
// Fall back to modifying the actual element.
var textNode = previewElement.childNodes[0];
textNode.data = "\\[" + latex + "\\]";
MathJax.Hub.Queue(["Typeset", MathJax.Hub, previewElement]);
}
});
}
});
}

if (response.error) {
inputData.$img.css('visibility', 'visible');
inputData.errorWaitTimeout = window.setTimeout(function () {
display("\\text{" + response.error + "}");
inputData.$img.css('visibility', 'hidden');
}, formulaEquationPreview.errorDelay);
} else {
display(response.preview);
}
}
}

// Invoke the setup method.
$('.formulaequationinput input').each(setupInput);
};
// Invoke the setup method.
$('.formulaequationinput input').each(setupInput);
};

formulaEquationPreview.enable();
formulaEquationPreview.enable();
});
5 changes: 5 additions & 0 deletions lms/templates/problem.html
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
<%! from django.utils.translation import ugettext as _ %>

<%namespace name='static' file='static_content.html'/>
<script>
require(['jquery', 'mathjax'], function() {
});
</script>

<h2 class="problem-header">
${ problem['name'] }
</h2>
Expand Down

0 comments on commit ef3d181

Please sign in to comment.