| /********************************************* |
| * Manage the MathQuill instance's textarea |
| * (as owned by the Controller) |
| ********************************************/ |
| |
| Controller.open(function(_) { |
| Options.p.substituteTextarea = function() { |
| return $('<textarea autocapitalize=off autocomplete=off autocorrect=off ' + |
| 'spellcheck=false x-palm-disable-ste-all=true />')[0]; |
| }; |
| _.createTextarea = function() { |
| var textareaSpan = this.textareaSpan = $('<span class="mq-textarea"></span>'), |
| textarea = this.options.substituteTextarea(); |
| if (!textarea.nodeType) { |
| throw 'substituteTextarea() must return a DOM element, got ' + textarea; |
| } |
| textarea = this.textarea = $(textarea).appendTo(textareaSpan); |
| |
| var ctrlr = this; |
| ctrlr.cursor.selectionChanged = function() { ctrlr.selectionChanged(); }; |
| ctrlr.container.bind('copy', function() { ctrlr.setTextareaSelection(); }); |
| }; |
| _.selectionChanged = function() { |
| var ctrlr = this; |
| forceIERedraw(ctrlr.container[0]); |
| |
| // throttle calls to setTextareaSelection(), because setting textarea.value |
| // and/or calling textarea.select() can have anomalously bad performance: |
| // https://github.com/mathquill/mathquill/issues/43#issuecomment-1399080 |
| if (ctrlr.textareaSelectionTimeout === undefined) { |
| ctrlr.textareaSelectionTimeout = setTimeout(function() { |
| ctrlr.setTextareaSelection(); |
| }); |
| } |
| }; |
| _.setTextareaSelection = function() { |
| this.textareaSelectionTimeout = undefined; |
| var latex = ''; |
| if (this.cursor.selection) { |
| latex = this.cursor.selection.join('latex'); |
| if (this.options.statelessClipboard) { |
| // FIXME: like paste, only this works for math fields; should ask parent |
| latex = '$' + latex + '$'; |
| } |
| } |
| this.selectFn(latex); |
| }; |
| _.staticMathTextareaEvents = function() { |
| var ctrlr = this, root = ctrlr.root, cursor = ctrlr.cursor, |
| textarea = ctrlr.textarea, textareaSpan = ctrlr.textareaSpan; |
| |
| this.container.prepend('<span class="mq-selectable">$'+ctrlr.exportLatex()+'$</span>'); |
| ctrlr.blurred = true; |
| textarea.bind('cut paste', false) |
| .focus(function() { ctrlr.blurred = false; }).blur(function() { |
| if (cursor.selection) cursor.selection.clear(); |
| setTimeout(detach); //detaching during blur explodes in WebKit |
| }); |
| function detach() { |
| textareaSpan.detach(); |
| ctrlr.blurred = true; |
| } |
| |
| ctrlr.selectFn = function(text) { |
| textarea.val(text); |
| if (text) textarea.select(); |
| }; |
| }; |
| _.editablesTextareaEvents = function() { |
| var ctrlr = this, root = ctrlr.root, cursor = ctrlr.cursor, |
| textarea = ctrlr.textarea, textareaSpan = ctrlr.textareaSpan; |
| |
| var keyboardEventsShim = saneKeyboardEvents(textarea, this); |
| this.selectFn = function(text) { keyboardEventsShim.select(text); }; |
| |
| this.container.prepend(textareaSpan) |
| .on('cut', function(e) { |
| if (cursor.selection) { |
| setTimeout(function() { |
| ctrlr.notify('edit'); // deletes selection if present |
| cursor.parent.bubble('reflow'); |
| }); |
| } |
| }); |
| |
| this.focusBlurEvents(); |
| }; |
| _.typedText = function(ch) { |
| if (ch === '\n') return this.handle('enter'); |
| var cursor = this.notify().cursor; |
| cursor.parent.write(cursor, ch); |
| this.scrollHoriz(); |
| }; |
| _.paste = function(text) { |
| // TODO: document `statelessClipboard` config option in README, after |
| // making it work like it should, that is, in both text and math mode |
| // (currently only works in math fields, so worse than pointless, it |
| // only gets in the way by \text{}-ifying pasted stuff and $-ifying |
| // cut/copied LaTeX) |
| if (this.options.statelessClipboard) { |
| if (text.slice(0,1) === '$' && text.slice(-1) === '$') { |
| text = text.slice(1, -1); |
| } |
| else { |
| text = '\\text{'+text+'}'; |
| } |
| } |
| // FIXME: this always inserts math or a TextBlock, even in a RootTextBlock |
| this.writeLatex(text).cursor.show(); |
| }; |
| }); |