diff options
author | Paul Duncan <pabs@pablotron.org> | 2017-11-07 20:44:10 -0500 |
---|---|---|
committer | Paul Duncan <pabs@pablotron.org> | 2017-11-07 20:44:10 -0500 |
commit | 074c8ca2a16bc4849e8ecea5a123d4d9a2995898 (patch) | |
tree | ae2597166fb9da56ff34bf8abafc59548bc0cad5 /htdocs/js/mathy.js | |
download | mathy-074c8ca2a16bc4849e8ecea5a123d4d9a2995898.tar.bz2 mathy-074c8ca2a16bc4849e8ecea5a123d4d9a2995898.zip |
initial commit
Diffstat (limited to 'htdocs/js/mathy.js')
-rw-r--r-- | htdocs/js/mathy.js | 245 |
1 files changed, 245 insertions, 0 deletions
diff --git a/htdocs/js/mathy.js b/htdocs/js/mathy.js new file mode 100644 index 0000000..13794fc --- /dev/null +++ b/htdocs/js/mathy.js @@ -0,0 +1,245 @@ +jQuery(function($) { + "use strict"; + + var TEMPLATES = new LuigiTemplate.Cache({ + save: [ + "<li>", + "<a ", + "href='#' ", + "title='Load \"%{name|h}\".' ", + "data-name='%{name|h}' ", + "data-text='%{text|h}' ", + ">", + "%{name|h}", + "</a>", + "</li>", + ], + + none: [ + "<li class='disabled'>", + "<a ", + "href='#' ", + "title='No saved results.' ", + ">", + "No saved results...", + "</a>", + "</li>", + ], + }); + + var Preview = window.Preview = { + delay: 150, // delay after keystroke before updating + + preview: null, // filled in by Init below + buffer: null, // filled in by Init below + + timeout: null, // store setTimout id + mjRunning: false, // true when MathJax is processing + mjPending: false, // true when a typeset has been queued + oldText: null, // used to check if an update is needed + + // + // Get the preview and buffer DIV's + // + Init: function () { + this.preview = document.getElementById("MathPreview"); + this.buffer = document.getElementById("MathBuffer"); + }, + + // + // Switch the buffer and preview, and display the right one. + // (We use visibility:hidden rather than display:none since + // the results of running MathJax are more accurate that way.) + // + SwapBuffers: function () { + var buffer = this.preview, preview = this.buffer; + this.buffer = buffer; this.preview = preview; + buffer.style.visibility = "hidden"; buffer.style.position = "absolute"; + preview.style.position = ""; preview.style.visibility = ""; + }, + + // + // This gets called when a key is pressed in the textarea. + // We check if there is already a pending update and clear it if so. + // Then set up an update to occur after a small delay (so if more keys + // are pressed, the update won't occur until after there has been + // a pause in the typing). + // The callback function is set up below, after the Preview object is set up. + // + Update: function () { + if (this.timeout) {clearTimeout(this.timeout)} + this.timeout = setTimeout(this.callback, this.delay); + }, + + // + // Creates the preview and runs MathJax on it. + // If MathJax is already trying to render the code, return + // If the text hasn't changed, return + // Otherwise, indicate that MathJax is running, and start the + // typesetting. After it is done, call PreviewDone. + // + CreatePreview: function () { + var syntax = $('#menu-syntax .active a').data(); + + Preview.timeout = null; + if (this.mjPending) return; + var text = "\\[" + editor.getValue() + "\\]"; + if (text === this.oldtext) return; + if (this.mjRunning) { + this.mjPending = true; + MathJax.Hub.Queue(["CreatePreview",this]); + } else { + this.buffer.innerHTML = this.oldtext = text; + this.mjRunning = true; + MathJax.Hub.Queue( + ["Typeset",MathJax.Hub,this.buffer], + ["PreviewDone",this] + ); + } + }, + + // + // Indicate that MathJax is no longer running, + // and swap the buffers to show the results. + // + PreviewDone: function () { + this.mjRunning = this.mjPending = false; + this.SwapBuffers(); + } + }; + + // + // Cache a callback to the CreatePreview action + // + Preview.callback = MathJax.Callback(["CreatePreview",Preview]); + Preview.callback.autoReset = true; // make sure it can run more than once + + function add_text(el, text, pos) { + var val = el.value, + head = val.substring(0, el.selectionStart), + tail = val.substring(el.selectionEnd, val.length); + + // update value + el.value = head + text + tail; + + // get offset + if (pos === undefined) + pos = text.length; + + // update caret position + el.selectionStart = el.selectionEnd = head.length + pos; + } + + $('#input').keyup(function(ev) { + window.Preview.Update(); + }); + + var autosave_timeout = null, + editor = ace.edit('editor'); + editor.setShowPrintMargin(false); + editor.setTheme('ace/theme/monokai'); + editor.getSession().setMode('ace/mode/latex'); + editor.getSession().on('change', function(e) { + window.Preview.Update(); + if (autosave_timeout) { + clearTimeout(autosave_timeout); + autosave_timeout = null; + } + autosave_timeout = setTimeout(function() { + localStorage.setItem('mathy_last', editor.getValue()); + }, 1000); + }); + + (function() { + var last = localStorage.getItem('mathy_last'); + if (!last) + return; + editor.setValue(last); + })(); + + $('#add').click(function() { + var el = $('#input')[0]; + add_shit(el, 'shit'); + try { el.focus(); } catch (e) {} + return false; + }); + + $('#saves').on('click', 'a', function() { + if ($(this).parent().hasClass('disabled')) + return false; + + var text = $(this).data('text'); + $('body').trigger('click'); + + setTimeout(function() { + editor.setValue(text); + }, 10); + + return false; + }).parent().on('show.bs.dropdown', function() { + var saves = localStorage.getItem('mathy_saves'); + saves = saves ? JSON.parse(saves) : []; + + var html = ''; + if (saves.length > 0) { + html = $.map(saves, function(row) { + return TEMPLATES.run('save', row); + }).join(''); + } else { + html = TEMPLATES.run('none'); + } + + $('#saves').html(html); + }); + + $('#btn-save').click(function() { + // get name + var name = prompt('Enter name:', ''); + if (!name) + return false; + + // build sortable name + var sort = name + .replace(/\s+/g, ' ') + .replace(/^\s+|\s+$/g, '') + .toLowerCase(); + + // load saves + var saves = localStorage.getItem('mathy_saves'); + saves = saves ? JSON.parse(saves) : []; + + if ($.grep(saves, function(row) { + return row.save == sort; + }).length > 0) { + if (!confirm("Replace existing \"" + name + " \"?")) + return false; + } + + // append to results + saves.push({ + name: name, + sort: sort, + text: editor.getValue(), + }); + + // write saves + localStorage.setItem('mathy_saves', JSON.stringify(saves.sort(function(a, b) { + return b.sort < a.sort; + }))); + + return false; + }); + + $('#help').on('click', 'a', function() { + var text = $(this).data('text').replace(/^\s+|\s+$/g, ''); + $('body').trigger('click'); + + setTimeout(function() { + editor.setValue(text); + }, 10); + + return false; + }); + + Preview.Init(); +}); |