<!DOCTYPE html> | |
<html> | |
<head> | |
<meta name="viewport" content="width=624"> | |
<title>MathQuill Test Page</title> | |
<link rel="stylesheet" type="text/css" href="support/home.css"> | |
<link rel="stylesheet" type="text/css" href="../build/mathquill.css"> | |
<script type="text/javascript" src="support/jquery-1.5.2.js"></script> | |
<style type="text/css"> | |
body { | |
font-size: .8em; | |
} | |
#body { | |
padding: 1.25em; | |
} | |
h1 { | |
font-size: 2.5em; | |
} | |
td { | |
width: 33%; | |
} | |
#static-latex-rendering-table td { | |
width: 50%; | |
} | |
#show-textareas-button { | |
float: right; | |
} | |
.show-textareas .mq-editable-field.mq-text-mode { | |
overflow: visible; | |
} | |
.show-textareas .mq-textarea textarea { | |
font-size: inherit; | |
clip: auto !important; | |
resize: auto !important; | |
height: auto !important; | |
width: auto !important; | |
top: -45px; | |
} | |
/* Non-white background test */ | |
.different-bgcolor.mq-editable-field, | |
.different-bgcolor.mq-editable-field .mq-matrixed { | |
background: black; | |
color: white; | |
} | |
.different-bgcolor.mq-editable-field .cursor { | |
border-color: white; | |
} | |
#overflow-test { | |
width: 100px; | |
} | |
</style> | |
</head> | |
<body> | |
<div id="body"> | |
<a href="http://github.com/laughinghan/mathquill"><img style="position: absolute; top: 0; right: 0; border: 0;" src="https://s3.amazonaws.com/github/ribbons/forkme_right_white_ffffff.png" alt="Fork me on GitHub!"></a> | |
<h1><a href="http://mathquill.github.com">MathQuill</a> Tests <small>local test page</small></h1> | |
<button id="show-textareas-button">Show Textareas</button> | |
<h3>MathQuill Editables</h3> | |
<p>In all editable fields, the selection should clear and ghost parens should solidify if you click outside, but not if you switch tabs/windows and switch back to this page. | |
<table id="editables"> | |
<tr><th colspan=3>Initial LaTeX | |
<tr> | |
<td><span class="mathquill-math-field">\frac{d}{dx}\sqrt{x}=\frac{1}{2\sqrt{x}}</span> | |
<td><span class="mathquill-text-field">lolwut $a^2 + b^2 = c^2$. Also, awesomesauce: $\int_0^1 \sin x dx.</span> | |
<td><span class="mathquill-static-math">\sqrt{\MathQuillMathField{x^2+y^2}}</span> | |
</table> | |
<p>Touch taps/clicks/mousedown to drag should work anywhere in the blue box: <div class="math-container" style="border: solid 1px lightblue; height: 5em; width: 15em; line-height: 5em; text-align: center; -webkit-tap-highlight-color: rgba(0,0,0,0)"><span class="mathquill-math-field">x_{very\ long\ thing}^2 + a_0 = 0</span></div> | |
<h3>Redrawing</h3> | |
<p> | |
<span id="reflowing-test">\sqrt{}</span> | |
should look the same as | |
<span class="mathquill-static-math"> | |
\sqrt{\pi\sqrt\sqrt\frac12} | |
</span> | |
</p> | |
<script type="text/javascript"> | |
$(function() { | |
var count = 0; | |
MQ.MathField($('#reflowing-test')[0], { | |
handlers: { edit: function() { count += 1; } }, // also test 'edit' hook | |
}).focus().moveToLeftEnd().keystroke('Right'); | |
var textarea = $('#reflowing-test textarea'); | |
// paste some stuff that needs resizing | |
textarea.trigger('paste'); | |
textarea.val('\\pi\\sqrt{\\sqrt{\\frac12}}'); | |
setTimeout(function() { if (count !== 1) throw 'reflow not called'; }); | |
}); | |
</script> | |
<h3>Behavior Options</h3> | |
<p><span id="custom-behavior">x_a^b + \frac{\sqrt[n]{x}}{\frac{1}{2}}</span></p> | |
<p>Space should behave like Tab, left and right should go through the upper block, sums should start with <code>n=</code>, exponents should require an base, any of <code>+-=<></code> should break out of an exponent, <code>pi</code>, <code>theta</code>, <code>sqrt</code>, and <code>sum</code> should all be auto-commands, but <code>only</code> should be the only auto-operator name (so <code>sin</code> etc. shouldn't automatically become non-italicized).</p> | |
<script> | |
$(function() { | |
MQ.MathField($('#custom-behavior')[0], { | |
spaceBehavesLikeTab: true, | |
leftRightIntoCmdGoes: 'up', | |
restrictMismatchedBrackets: true, | |
sumStartsWithNEquals: true, | |
supSubsRequireOperand: true, | |
charsThatBreakOutOfSupSub: '+-=<>', | |
autoSubscriptNumerals: true, | |
autoCommands: 'pi theta sqrt sum', | |
autoOperatorNames: 'only' | |
}); | |
}); | |
</script> | |
<h3>Up/Down seeking and caching</h3> | |
<p> | |
<span id="seek-test" class="mathquill-math-field"> | |
\frac{1}{\sqrt \sqrt \sqrt \sqrt \sqrt \sqrt x} | |
</span> | |
</p> | |
<p> | |
↑ If you hit down from next to the 1, you should end up inside one of the square roots. If you hit up from the right of the x and then hit down again, you should end up where you were. | |
</p> | |
<h3>Horizontal overflow</h3> | |
<p> | |
<span id="overflow-test"> | |
\frac{d}{dx}\sqrt{x}=\frac{d}{dx}x^{\frac{1}{2}}=\frac{1}{2}x^{-\frac{1}{2}}=\frac{1}{2\sqrt{x}} | |
</span> | |
(for comparison: <input value="\frac{d}{dx}\sqrt{x}=\frac{d}{dx}x^{\frac{1}{2}}=\frac{1}{2}x^{-\frac{1}{2}}=\frac{1}{2\sqrt{x}}"/>) | |
</p> | |
<script> | |
$(function() { | |
var overflowTest = $('#overflow-test'); | |
MQ.MathField(overflowTest[0]); | |
var width = overflowTest.outerWidth(true); | |
if (width !== 102) { | |
throw 'math field '+width+'px wide instead of 102px'; | |
} | |
}); | |
</script> | |
<h3>Selection Tests</h3> | |
<p id="selection-tests"><span class="mathquill-text-field different-bgcolor">lolwut $a^2 + b^2 = c^2$. $\sqrt{ \left( \frac{1}{2} \right) }$. Also, awesomesauce: $\int_0^1 \sin x dx.</span> | |
<p>Even in IE<9, the background color of the parens and square root radical should be the background color of the selection. | |
<h3>Dynamic mathquill-ification</h3> | |
<table id="dynamic-initial"> | |
<tr><th colspan=3>Initial LaTeX | |
<tr> | |
<td><span>\frac{d}{dx}\sqrt{x} = \frac{d}{dx}x^{\frac{1}{2}} = \frac{1}{2}x^{-\frac{1}{2}} = \frac{1}{2\sqrt{x}}</span> | |
<td><span>\frac{d}{dx}\sqrt{x} = \frac{d}{dx}x^{\frac{1}{2}} = \frac{1}{2}x^{-\frac{1}{2}} = \frac{1}{2\sqrt{x}}</span> | |
<td><span>\frac{d}{dx}\sqrt{x} = \frac{d}{dx}x^{\frac{1}{2}} = \frac{1}{2}x^{-\frac{1}{2}} = \frac{1}{2\sqrt{x}}</span> | |
<tr> | |
<td><span>\frac{ \text{apples} }{ \text{oranges} } = \text{NaN}</span> | |
<td><span>\frac{ \text{apples} }{ \text{oranges} } = \text{NaN}</span> | |
<td><span>\frac{ \text{apples} }{ \text{oranges} } = \text{NaN}</span> | |
</table> | |
<table id="dynamic-reflow"> | |
<tr><th colspan=3><code>MQ(...).reflow()</code> | |
<tr> | |
<td><span>\sqrt{ \left ( \frac{x^2 + y^2}{2} \right ) } + \binom{n}{k}</span> | |
<td><span>\sqrt{ \left ( \frac{x^2 + y^2}{2} \right ) } + \binom{n}{k}</span> | |
<td><span>\sqrt{ \left ( \frac{x^2 + y^2}{2} \right ) } + \binom{n}{k}</span> | |
</table> | |
<h3>Static LaTeX rendering (<code>.mathquill-static-math</code>) tests</h3> | |
<table id="static-latex-rendering-table"> | |
<tr><td><span class="mathquill-static-math">^{\frac{as}{ }df}</span><td><span>^{\frac{as}{ }df}</span> | |
<tr><td><span class="mathquill-static-math">e^{i\pi}+1=0</span><td><span>e^{i\pi}+1=0</span> | |
<tr><td><span class="mathquill-static-math">\sqrt[n]{1}</span><td><span>\sqrt[n]{1}</span> | |
<tr><td><span class="mathquill-static-math">\sin ^2x+\sin ^2\left(x\right)+\sin ^2(x)</span></td><td><span>\sin ^2x+\sin ^2\left(x\right)+\sin ^2(x)</span> | |
<tr><td><span class="mathquill-static-math">12a\sin b</span></td><td><span>12a\sin b</span> | |
<tr><td><span class="mathquill-static-math">1a^2 \sin b</span></td><td><span>1a^2 \sin b</span> | |
<tr><td><span class="mathquill-static-math">a + \sin b</span></td><td><span>a + \sin b</span> | |
<tr><td><span class="mathquill-static-math">a + b</span></td><td><span>a + b</span> | |
<tr><td><span class="mathquill-static-math">\sum\sin</span></td><td><span>\sum\sin</span> | |
<tr><td><span class="mathquill-static-math">\sum a</span></td><td><span>\sum a</span> | |
<tr><td><span class="mathquill-static-math">(\sin)</span></td><td><span>(\sin)</span> | |
<tr><td><span class="mathquill-static-math">\left(\sin\right)</span></td><td><span>\left(\sin\right)</span> | |
<tr><td><span class="mathquill-static-math">(x)\sin(x)</span></td><td><span>(x)\sin(x)</span> | |
<tr><td><span class="mathquill-static-math">\left(x\right)\sin\left(x\right)</span></td><td><span>\left(x\right)\sin\left(x\right)</span> | |
<tr><td><span class="mathquill-static-math">a \sin b</span></td><td><span>a \sin b</span> | |
<tr><td><span class="mathquill-static-math">-1 + +-2</span><td><span>-1 + +-2</span> | |
<tr><td><span class="mathquill-static-math">\left ( n+1 \right ) + \frac{1}{\frac{n}{k}} + \binom{n}{k}</span><td><span>\left ( n+1 \right ) + \frac{1}{\frac{n}{k}} + \binom{n}{k}</span> | |
<tr><td><span class="mathquill-static-math">x_{\frac{1}{\frac{2}{3}}}^{\frac{\frac{1}{2}}{3}}</span><td><span>x_{\frac{1}{\frac{2}{3}}}^{\frac{\frac{1}{2}}{3}}</span> | |
<tr><td><span class="mathquill-static-math" style="font-size:14.99px">\left(\frac{\frac{\frac{1}{2}}{\frac{3}{4}}}{\frac{\frac{5}{6}}{\frac{7}{8}}}\right)</span><td><span>\left(\frac{\frac{\frac{1}{2}}{\frac{3}{4}}}{\frac{\frac{5}{6}}{\frac{7}{8}}}\right)</span> | |
<tr><td><span class="mathquill-static-math" style="font-size:1.4375em">\left| a + \left| b \right| \right|</span><td><span>\left| a + \left| b \right| \right|</span> | |
<tr><td><span class="mathquill-static-math" style="font-size:1.4375em">\sqrt{x}+\sqrt{\frac{x}{\frac{ }{\frac{ }{ }}}}+\sqrt{\frac{x}{\frac{ }{\frac{ }{\frac{ }{\frac{ }{ }}}}}}</span><td><span>\sqrt{x}+\sqrt{\frac{x}{\frac{ }{\frac{ }{ }}}}+\sqrt{\frac{x}{\frac{ }{\frac{ }{\frac{ }{\frac{ }{ }}}}}}</span> | |
<tr><td><span class="mathquill-static-math">1+\sum_0^n+\sum_{i=0123}^n+\sum_0^{wordiness}</span><td><span>1+\sum_0^n+\sum_{i=0123}^n+\sum_0^{wordiness}</span>^M | |
<tr><td><span class="mathquill-static-math">x\ \ \ +\ \ \ y</span><td><span>x\ \ \ +\ \ \ y</span>^M | |
<tr><td><span class="mathquill-static-math">\sum _{n=0}^3\cos x</span><td><span>\sum _{n=0}^3\cos x</span>^M | |
<tr><td><span class="mathquill-static-math">\vec x + \tilde x + \vec A + \tilde A + \vec{abcd} + \tilde{abcd}</span><td><span>\vec x + \tilde x + \vec A + \tilde A + \vec{abcd} + \tilde{abcd}</span>^M | |
<tr><td><span class="mathquill-static-math">\int _{\phi =0}^{2\pi }\int _{\theta =0}^{\pi }\int _{r=0}^{\infty }f(r,\theta ,\phi )r^2\sin \theta drd\theta d\phi </span><td><span>\int _{\phi =0}^{2\pi }\int _{\theta =0}^{\pi }\int _{r=0}^{\infty }f(r,\theta ,\phi )r^2\sin \theta drd\theta d\phi </span> | |
<tr><td><span class="mathquill-static-math">\int_0^{\frac{\frac{1}{2}}{3}} \int_0^{\frac{1}{\frac{2}{3}}} \int_0^{\frac{1}{\frac{2}{\frac{3}{\frac{4}{5}}}}}</span><td><span>\int_0^{\frac{\frac{1}{2}}{3}} \int_0^{\frac{1}{\frac{2}{3}}} \int_0^{\frac{1}{\frac{2}{\frac{3}{\frac{4}{5}}}}}</span> | |
<tr><td colspan=2><span id="sixes"></span> | |
<script> | |
$(function() { | |
var i, | |
sixes = '', | |
start = 10, | |
end = 40; | |
for (i = start; i <= end; i++) { | |
sixes += '<span style="font-size: ' + i + 'px" class="mathquill-math-field">6<\/span>'; | |
} | |
$('#sixes').html(sixes); | |
$('#sixes .mathquill-math-field').each(function() { MQ.MathField(this); }); | |
}); | |
</script> | |
</table> | |
<p id="paren-alignment">Parentheses vertical alignment at font sizes ranging from 10px to 24px: <button>Click Me</button></p> | |
<script> | |
$('#paren-alignment button').click(function() { | |
var html = '<div>'; | |
for (var i = 10; i <= 24; i += 1) { | |
html += i+'px: <span class="mathquill-static-math" style="font-size:'+i+'px">\\left(\\left(\\left(\\left(\\left(\\left(\\left( \\right)\\right)\\right)\\right)\\right)\\right)\\right)+\\left(1\\right)+\\left(x\\right)+\\left(y\\right)+\\left(\\frac{1}{2}\\right)+\\left(\\frac{\\frac{1}{x}}{2}\\right)+\\left(\\frac{1}{\\frac{x}{2}}\\right)+\\left(\\frac{\\frac{\\frac{1}{2}}{\\frac{3}{4}}}{\\frac{\\frac{5}{6}}{\\frac{7}{8}}}\\right)</span><br>'; | |
} | |
html += '</div>'; | |
$(html).insertAfter('#paren-alignment').find('.mathquill-static-math').each(function() { | |
MQ.StaticMath(this); | |
}); | |
}); | |
</script> | |
<h3>Dynamic rendering performance</h3> | |
<p id="latex-render-perf">LaTeX: <textarea></textarea> <button>→</button> <span class="mathquill-math-field"></span></p> | |
<p id="html-render-perf">HTML: <textarea></textarea> <button>→</button> <span class="mq-math-mode"></span></p> | |
<p>There should be no space between here <span class="mathquill-static-math"> </span>and here, even in IE8</p> | |
<h3>Textcolor</h3> | |
<p>Colors should match their names: | |
<span class="mathquill-static-math"> | |
\textcolor{#0000FF}{blue} + \textcolor{red}{red} | |
= \textcolor { rgb(255, -10, 255) } {magenta} | |
</span> | |
</p> | |
<p>Nested <code>\textcolor</code>: the 2 should be red, the "a+" green, the 4 blue, and the "+b" green again. | |
<span class="mathquill-static-math"> | |
e^{\textcolor{#FF0000}{2}}\sin(x^\textcolor{#00FF00}{{a+\textcolor{blue}{4}+b}}) | |
</span> | |
</p> | |
<h3>Adding CSS class</h3> | |
<style type="text/css"> | |
.testclass { background-color: #5A8; border-radius: 5px; padding: 4px; font-weight:bold;color:gold;} | |
</style> | |
<p>Second term should be styled like <span class='testclass'>this</span>: | |
<span class="mathquill-static-math"> | |
x+\class{testclass}{y}+z | |
</span> | |
</p> | |
<h3>substituteTextarea</h3> | |
<p>In Safari on iOS, this should be focusable but not bring up the on-screen keyboard; to test, try focusing anything else and confirm this blurs: <span id="no-kbd-math"></span> (confirmed working on iOS 6.1.3)</p> | |
<h3>substituteKeyboardEvents</h3> | |
<p>Should be able to prevent cut, typing, and pasting in this field: <span id="disable-typing">1+2+3</span></p> | |
<p>Should wrap anything you type in '<>': <span id="wrap-typing">1+2+3</span></p> | |
</div> | |
<script type="text/javascript"> | |
window.onerror = function(err) { | |
console.log(err); // to show up in Selenium WebDriver logs | |
$('html').css('background', 'red'); | |
}; | |
</script> | |
<script type="text/javascript" src="../build/mathquill.js"></script> | |
<script type="text/javascript"> | |
MQ = MathQuill.getInterface(MathQuill.getInterface.MAX); | |
$('#show-textareas-button').click(function() { | |
$(document.body).toggleClass('show-textareas'); | |
}); | |
//on document ready, mathquill-ify all `<tag class="mathquill-*">latex</tag>` | |
//elements according to their CSS class. | |
$(function() { | |
$('.mathquill-static-math').each(function() { MQ.StaticMath(this); }); | |
$('.mathquill-math-field').each(function() { MQ.MathField(this); }); | |
$('.mathquill-text-field').each(function() { MQ.TextField(this); }); | |
}); | |
// test selecting from outside the mathquill editable | |
var $mq = $('.math-container .mathquill-math-field'); | |
$('.math-container').mousedown(function(e) { | |
if (e.target === $mq[0] || $.contains($mq[0], e.target)) return; | |
$mq.triggerHandler(e); | |
}) | |
// test API for "fast touch taps" #622 & #403 | |
.bind('touchstart', function() { | |
var moved = false; | |
$(this).bind('touchmove.tmp', function() { moved = true; }) | |
.bind('touchend.tmp', function(e) { | |
$(this).off('.tmp'); | |
MathQuill($mq[0]).ignoreNextMousedown(function() { | |
return Date.now() < e.timeStamp + 1000; | |
}); | |
if (moved) return; // note that this happens after .ignoreNextMousedown() | |
// because even if the touch gesture doesn't 'count' as a tap to us, | |
// we still want to suppress the legacy mouse events, else we'd react | |
// fast to some taps and slow to others, that'd be weird | |
var touch = e.originalEvent.changedTouches[0]; | |
MathQuill($mq[0]).clickAt(touch.clientX, touch.clientY, touch.target); | |
}); | |
}); | |
// Selection Tests | |
document.body.onload = function() { | |
setTimeout(function() { | |
$('#selection-tests .mathquill-text-field').each(function() { | |
var start = +new Date; | |
$('textarea', this).focus().trigger({type: 'keydown', ctrlKey: true, which: 65}); | |
console.log('Time taken to Select All (should be <50ms):',new Date - start); | |
}); | |
}); | |
}; | |
// Dynamic MathQuill-ification | |
// Initial LaTeX | |
$('#dynamic-initial tr').each(function() { | |
var math = $('span', this); | |
if (!math.length) return; | |
MQ.StaticMath(math[0]); | |
MQ.MathField(math[1]); | |
MQ.MathField(math[2]).revert(); | |
}); | |
// MQ(...).reflow() | |
$('#dynamic-reflow tr').each(function() { | |
var math = $('span', this), td; | |
if (!math.length) return; | |
td = math.eq(0).parent(); | |
math.eq(0).detach(); | |
MQ.StaticMath(math[0]); | |
math.eq(0).appendTo(td); | |
MQ(math[0]).reflow(); | |
td = math.eq(1).parent(); | |
math.eq(1).detach(); | |
MQ.MathField(math[1]); | |
math.eq(1).appendTo(td); | |
MQ(math[1]).reflow(); | |
td = math.eq(2).parent(); | |
math.eq(2).detach(); | |
MQ.MathField(math[2]).revert(); | |
math.eq(2).appendTo(td); | |
if (MQ(math[2])) throw 'should been have reverted'; | |
}); | |
// Dynamic rendering performance | |
function Avgs() { | |
return { | |
avgs: {}, | |
add: function(k, v) { | |
if (!this.avgs[k]) this.avgs[k] = { n: 0, avg: 0 }; | |
var avgObj = this.avgs[k]; | |
avgObj.avg = (avgObj.n*avgObj.avg + v) / (avgObj.n + 1); | |
avgObj.n += 1; | |
return avgObj.avg + 'ms (across ' + avgObj.n + ' trials)'; | |
} | |
}; | |
} | |
var performance = window.performance || Date; | |
window.rawLogs = []; | |
function timeAndLog(f) { | |
var currentLog = []; | |
$.fn.mathquill.setLogFn(function(msg) { | |
currentLog.push({ msg: msg, now: performance.now() }); | |
}); | |
var start = performance.now(); | |
f(); | |
var duration = performance.now() - start; | |
$.fn.mathquill.setLogFn($.noop); | |
var timeline = [], prev = 0; | |
for (var i = 0; i < currentLog.length; i += 1) { | |
var now = Math.round((currentLog[i].now - start)*1000); | |
timeline.push(now + ': [' + (now - prev) + 'µs] ' + currentLog[i].msg); | |
prev = now; | |
} | |
timeline = timeline.join('\n'); | |
rawLogs.push({ | |
start: start, | |
duration: duration, | |
log: currentLog, | |
timeline: timeline | |
}); | |
if (timeline.length) { | |
// for tablets without a console | |
if (location.hash === '#alert') alert(timeline); | |
else console.log(timeline); | |
} | |
return duration; | |
}; | |
(function() { | |
var textarea = $('#latex-render-perf textarea'); | |
var mathquill = $('#latex-render-perf .mathquill-math-field'); | |
var avgs = Avgs(); | |
$('#latex-render-perf button').click(function() { | |
var latex = textarea.val(); | |
var duration = timeAndLog(function() { | |
mathquill.mathquill('latex', latex); | |
}); | |
$('#html-render-perf').after('<p>'+duration+'ms rendering <code>'+latex+'</code>, for an average of '+avgs.add(latex, duration)+'</p>'); | |
$('#html-render-perf textarea').val(mathquill.mathquill('html')); | |
}); | |
}()); | |
(function() { | |
var textarea = $('#html-render-perf textarea'); | |
var span = $('#html-render-perf span'); | |
var avgs = Avgs(); | |
$('#html-render-perf button').click(function() { | |
var html = textarea.val(); | |
var duration = timeAndLog(function() { | |
span.html(html); | |
}); | |
$('<p>'+duration+'ms rendering <code></code>, for an average of '+avgs.add(html, duration)+'</p>').find('code').text(html).end() | |
.insertAfter('#html-render-perf'); | |
}); | |
}()); | |
MQ.MathField($('#no-kbd-math')[0], { | |
substituteTextarea: function() { | |
return $('<span tabindex=0 style="display:inline-block;width:1px;height:1px" />')[0]; | |
} | |
}); | |
MQ.MathField($('#disable-typing')[0], { | |
substituteKeyboardEvents: function(textarea, handlers) { | |
return MQ.saneKeyboardEvents(textarea, $.extend({}, handlers, { | |
cut: $.noop, | |
paste: $.noop, | |
keystroke: $.noop, | |
typedText: $.noop | |
})); | |
} | |
}); | |
MQ.MathField($('#wrap-typing')[0], { | |
substituteKeyboardEvents: function(textarea, handlers) { | |
return MQ.saneKeyboardEvents(textarea, $.extend({}, handlers, { | |
typedText: function (text) { | |
handlers.typedText('<'); | |
handlers.typedText(text); | |
handlers.typedText('>'); | |
} | |
})); | |
} | |
}); | |
</script> | |
</body> | |
</html> |