Commit 03d976be by ichuang

Merge branch 'ps-dynamath' of github.com:MITx/mitx into dogfood-xmodule

parents 9d0dfd2f f9ad0bd9
...@@ -2,49 +2,32 @@ ...@@ -2,49 +2,32 @@
### version of textline.html which does dynammic math ### version of textline.html which does dynammic math
### ###
<section class="text-input-dynamath"> <section class="text-input-dynamath">
<table style="display:inline; vertical-align:middle;"><tr><td> <table style="display:inline; vertical-align:middle;">
<input type="text" name="input_${id}" id="input_${id}" value="${value}" <tr>
% if size: <td>
size="${size}" <input type="text" name="input_${id}" id="input_${id}" value="${value}" class="math" size="${size if size else ''}" />
% endif </td>
onkeyup="DoUpdateMath('${id}')" <td>
/> <span id="answer_${id}"></span>
</td><td>
<span id="answer_${id}"></span> % if state == 'unsubmitted':
<span class="unanswered" style="display:inline-block;" id="status_${id}"></span>
% if state == 'unsubmitted': % elif state == 'correct':
<span class="unanswered" style="display:inline-block;" id="status_${id}"></span> <span class="correct" id="status_${id}"></span>
% elif state == 'correct': % elif state == 'incorrect':
<span class="correct" id="status_${id}"></span> <span class="incorrect" id="status_${id}"></span>
% elif state == 'incorrect': % elif state == 'incomplete':
<span class="incorrect" id="status_${id}"></span> <span class="incorrect" id="status_${id}"></span>
% elif state == 'incomplete': % endif
<span class="incorrect" id="status_${id}"></span> </td>
% endif </tr>
<tr>
</td></tr><tr><td> <td>
<span id="display_${id}">`{::}`</span> <span id="display_${id}">`{::}`</span>
</td><td> </td>
<textarea style="display:none" id="input_${id}_dynamath" name="input_${id}_dynamath"> </textarea> <td>
</td></tr> <textarea style="display:none" id="input_${id}_dynamath" name="input_${id}_dynamath"> </textarea>
</table> </td>
## </tr>
## javascript for dynamic math: add this math element to the MathJax rendering queue </table>
## also adds to global jaxset js array
##
<script type="text/javascript">
MathJax.Hub.queue.Push(function () {
math = MathJax.Hub.getAllJax("display_${id}")[0];
if (math){
jaxset["${id}"] = math;
math.Text(document.getElementById("input_${id}").value);
// UpdateMathML(math,"${id}");
}
});
</script>
% if msg:
<br/>
<span class="debug">${msg|n}</span>
% endif
</section> </section>
...@@ -6,6 +6,10 @@ ...@@ -6,6 +6,10 @@
<section class="action"> <section class="action">
<input type="hidden" name="problem_id" value="1"> <input type="hidden" name="problem_id" value="1">
<input type="text" name="input_example_1" id="input_example_1" value="" class="math" />
<span id="display_example_1"></span>
<span id="input_example_1_dynamath"></span>
<input class="check" type="button" value="Check"> <input class="check" type="button" value="Check">
<input class="reset" type="button" value="Reset"> <input class="reset" type="button" value="Reset">
<input class="save" type="button" value="Save"> <input class="save" type="button" value="Save">
......
describe 'Problem', -> describe 'Problem', ->
beforeEach -> beforeEach ->
# Stub MathJax # Stub MathJax
window.MathJax = { Hub: { Queue: -> } } window.MathJax =
Hub: jasmine.createSpyObj('MathJax.Hub', ['getAllJax', 'Queue'])
Callback: jasmine.createSpyObj('MathJax.Callback', ['After'])
@stubbedJax = root: jasmine.createSpyObj('jax.root', ['toMathML'])
MathJax.Hub.getAllJax.andReturn [@stubbedJax]
window.update_schematics = -> window.update_schematics = ->
loadFixtures 'problem.html' loadFixtures 'problem.html'
...@@ -25,8 +29,8 @@ describe 'Problem', -> ...@@ -25,8 +29,8 @@ describe 'Problem', ->
describe 'bind', -> describe 'bind', ->
beforeEach -> beforeEach ->
spyOn MathJax.Hub, 'Queue'
spyOn window, 'update_schematics' spyOn window, 'update_schematics'
MathJax.Hub.getAllJax.andReturn [@stubbedJax]
@problem = new Problem 1, '/problem/url/' @problem = new Problem 1, '/problem/url/'
it 'set mathjax typeset', -> it 'set mathjax typeset', ->
...@@ -50,6 +54,12 @@ describe 'Problem', -> ...@@ -50,6 +54,12 @@ describe 'Problem', ->
it 'bind the save button', -> it 'bind the save button', ->
expect($('section.action input.save')).toHandleWith 'click', @problem.save expect($('section.action input.save')).toHandleWith 'click', @problem.save
it 'bind the math input', ->
expect($('input.math')).toHandleWith 'keyup', @problem.refreshMath
it 'display the math input', ->
expect(@stubbedJax.root.toMathML).toHaveBeenCalled()
describe 'render', -> describe 'render', ->
beforeEach -> beforeEach ->
@problem = new Problem 1, '/problem/url/' @problem = new Problem 1, '/problem/url/'
...@@ -223,6 +233,30 @@ describe 'Problem', -> ...@@ -223,6 +233,30 @@ describe 'Problem', ->
@problem.save() @problem.save()
expect(window.alert).toHaveBeenCalledWith 'Saved' expect(window.alert).toHaveBeenCalledWith 'Saved'
describe 'refreshMath', ->
beforeEach ->
@problem = new Problem 1, '/problem/url/'
@stubbedJax.root.toMathML.andReturn '<MathML>'
$('#input_example_1').val 'E=mc^2'
describe 'when there is no exception', ->
beforeEach ->
@problem.refreshMath target: $('#input_example_1').get(0)
it 'should convert and display the MathML object', ->
expect(MathJax.Hub.Queue).toHaveBeenCalledWith ['Text', @stubbedJax, 'E=mc^2']
it 'should display debug output in hidden div', ->
expect($('#input_example_1_dynamath')).toHaveValue '<MathML>'
describe 'when there is an exception', ->
beforeEach ->
@stubbedJax.root.toMathML.andThrow {restart: true}
@problem.refreshMath target: $('#input_example_1').get(0)
it 'should queue up the exception', ->
expect(MathJax.Callback.After).toHaveBeenCalledWith [@problem.refreshMath, @stubbedJax], true
describe 'refreshAnswers', -> describe 'refreshAnswers', ->
beforeEach -> beforeEach ->
@problem = new Problem 1, '/problem/url/' @problem = new Problem 1, '/problem/url/'
......
...@@ -15,6 +15,7 @@ class @Problem ...@@ -15,6 +15,7 @@ class @Problem
@$('section.action input.reset').click @reset @$('section.action input.reset').click @reset
@$('section.action input.show').click @show @$('section.action input.show').click @show
@$('section.action input.save').click @save @$('section.action input.save').click @save
@$('input.math').keyup(@refreshMath).each(@refreshMath)
render: (content) -> render: (content) ->
if content if content
...@@ -62,6 +63,20 @@ class @Problem ...@@ -62,6 +63,20 @@ class @Problem
if response.success if response.success
alert 'Saved' alert 'Saved'
refreshMath: (event, element) =>
element = event.target unless element
target = "display_#{element.id.replace(/^input_/, '')}"
jax = MathJax.Hub.getAllJax(target)[0]
MathJax.Hub.Queue ['Text', jax, $(element).val()]
try
output = jax.root.toMathML ''
$("##{element.id}_dynamath").val(output)
catch exception
throw exception unless exception.restart
MathJax.Callback.After [@refreshMath, jax], exception.restart
refreshAnswers: => refreshAnswers: =>
@$('input.schematic').each (index, element) -> @$('input.schematic').each (index, element) ->
element.schematic.update_value() element.schematic.update_value()
......
...@@ -5,82 +5,22 @@ ...@@ -5,82 +5,22 @@
## ##
## This enables ASCIIMathJAX, and is used by js_textbox ## This enables ASCIIMathJAX, and is used by js_textbox
<script type="text/x-mathjax-config"> <script type="text/x-mathjax-config">
MathJax.Hub.Config({
// (function () { tex2jax: {
var QUEUE = MathJax.Hub.queue; // shorthand for the queue inlineMath: [
var math = null; ["\\(","\\)"],
var jaxset = {}; // associative array of the element jaxs for the math output. ['[mathjaxinline]','[/mathjaxinline]']
var mmlset = {}; // associative array of mathml from each jax ],
displayMath: [
// constructs mathML of the specified jax element ["\\[","\\]"],
function toMathML(jax,callback) { ['[mathjax]','[/mathjax]']
var mml; ]
try {
mml = jax.root.toMathML("");
} catch(err) {
if (!err.restart) {throw err} // an actual error
return MathJax.Callback.After([toMathML,jax,callback],err.restart);
}
MathJax.Callback(callback)(mml);
}
// function to queue in MathJax to get put the MathML expression in in the right document element
function UpdateMathML(jax,id) {
toMathML(jax,function (mml) {
// document.getElementById(id+'_dynamath').value=math.originalText+ "\n\n=>\n\n"+ mml;
delem = document.getElementById("input_" + id + "_dynamath");
if (delem) { delem.value=mml; };
mmlset[id] = mml;
})
}
MathJax.Hub.Config({
tex2jax: {
inlineMath: [
["\\(","\\)"],
['[mathjaxinline]','[/mathjaxinline]']
],
displayMath: [
["\\[","\\]"],
['[mathjax]','[/mathjax]']
]
}
});
//
// The onchange event handler that typesets the
// math entered by the user
//
window.UpdateMath = function (Am,id) {
QUEUE.Push(["Text",jaxset[id],Am]);
QUEUE.Push(UpdateMathML(jaxset[id],id));
} }
});
</script>
// })(); <!-- This must appear after all mathjax-config blocks, so it is after the imports from the other templates.
It can't be run through static.url because MathJax uses crazy url introspection to do lazy loading of
function DoUpdateMath(inputId) { MathJax extension libraries -->
var str = document.getElementById("input_"+inputId).value; <script type="text/javascript" src="/static/js/mathjax-MathJax-c9db6ac/MathJax.js?config=TeX-MML-AM_HTMLorMML-full"></script>
// make sure the input field is in the jaxset
if ($.inArray(inputId,jaxset) == -1){
//alert('missing '+inputId);
if (document.getElementById("display_" + inputId)){
MathJax.Hub.queue.Push(function () {
math = MathJax.Hub.getAllJax("display_" + inputId)[0];
if (math){
jaxset[inputId] = math;
}
});
};
}
UpdateMath(str,inputId)
}
</script>
<!-- This must appear after all mathjax-config blocks, so it is after the imports from the other templates.
It can't be run through static.url because MathJax uses crazy url introspection to do lazy loading of
MathJax extension libraries -->
<script type="text/javascript" src="/static/js/mathjax-MathJax-c9db6ac/MathJax.js?config=TeX-MML-AM_HTMLorMML-full"></script>
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment