michael@0: // Open simple dialogs on top of an editor. Relies on dialog.css. michael@0: michael@0: (function(mod) { michael@0: if (typeof exports == "object" && typeof module == "object") // CommonJS michael@0: mod(require("../../lib/codemirror")); michael@0: else if (typeof define == "function" && define.amd) // AMD michael@0: define(["../../lib/codemirror"], mod); michael@0: else // Plain browser env michael@0: mod(CodeMirror); michael@0: })(function(CodeMirror) { michael@0: function dialogDiv(cm, template, bottom) { michael@0: var wrap = cm.getWrapperElement(); michael@0: var dialog; michael@0: dialog = wrap.appendChild(document.createElement("div")); michael@0: if (bottom) { michael@0: dialog.className = "CodeMirror-dialog CodeMirror-dialog-bottom"; michael@0: } else { michael@0: dialog.className = "CodeMirror-dialog CodeMirror-dialog-top"; michael@0: } michael@0: if (typeof template == "string") { michael@0: dialog.innerHTML = template; michael@0: } else { // Assuming it's a detached DOM element. michael@0: dialog.appendChild(template); michael@0: } michael@0: return dialog; michael@0: } michael@0: michael@0: function closeNotification(cm, newVal) { michael@0: if (cm.state.currentNotificationClose) michael@0: cm.state.currentNotificationClose(); michael@0: cm.state.currentNotificationClose = newVal; michael@0: } michael@0: michael@0: CodeMirror.defineExtension("openDialog", function(template, callback, options) { michael@0: closeNotification(this, null); michael@0: var dialog = dialogDiv(this, template, options && options.bottom); michael@0: var closed = false, me = this; michael@0: function close() { michael@0: if (closed) return; michael@0: closed = true; michael@0: dialog.parentNode.removeChild(dialog); michael@0: } michael@0: var inp = dialog.getElementsByTagName("input")[0], button; michael@0: if (inp) { michael@0: if (options && options.value) inp.value = options.value; michael@0: CodeMirror.on(inp, "keydown", function(e) { michael@0: if (options && options.onKeyDown && options.onKeyDown(e, inp.value, close)) { return; } michael@0: if (e.keyCode == 13 || e.keyCode == 27) { michael@0: inp.blur(); michael@0: CodeMirror.e_stop(e); michael@0: close(); michael@0: me.focus(); michael@0: if (e.keyCode == 13) callback(inp.value); michael@0: } michael@0: }); michael@0: if (options && options.onKeyUp) { michael@0: CodeMirror.on(inp, "keyup", function(e) {options.onKeyUp(e, inp.value, close);}); michael@0: } michael@0: if (options && options.value) inp.value = options.value; michael@0: inp.focus(); michael@0: CodeMirror.on(inp, "blur", close); michael@0: } else if (button = dialog.getElementsByTagName("button")[0]) { michael@0: CodeMirror.on(button, "click", function() { michael@0: close(); michael@0: me.focus(); michael@0: }); michael@0: button.focus(); michael@0: CodeMirror.on(button, "blur", close); michael@0: } michael@0: return close; michael@0: }); michael@0: michael@0: CodeMirror.defineExtension("openConfirm", function(template, callbacks, options) { michael@0: closeNotification(this, null); michael@0: var dialog = dialogDiv(this, template, options && options.bottom); michael@0: var buttons = dialog.getElementsByTagName("button"); michael@0: var closed = false, me = this, blurring = 1; michael@0: function close() { michael@0: if (closed) return; michael@0: closed = true; michael@0: dialog.parentNode.removeChild(dialog); michael@0: me.focus(); michael@0: } michael@0: buttons[0].focus(); michael@0: for (var i = 0; i < buttons.length; ++i) { michael@0: var b = buttons[i]; michael@0: (function(callback) { michael@0: CodeMirror.on(b, "click", function(e) { michael@0: CodeMirror.e_preventDefault(e); michael@0: close(); michael@0: if (callback) callback(me); michael@0: }); michael@0: })(callbacks[i]); michael@0: CodeMirror.on(b, "blur", function() { michael@0: --blurring; michael@0: setTimeout(function() { if (blurring <= 0) close(); }, 200); michael@0: }); michael@0: CodeMirror.on(b, "focus", function() { ++blurring; }); michael@0: } michael@0: }); michael@0: michael@0: /* michael@0: * openNotification michael@0: * Opens a notification, that can be closed with an optional timer michael@0: * (default 5000ms timer) and always closes on click. michael@0: * michael@0: * If a notification is opened while another is opened, it will close the michael@0: * currently opened one and open the new one immediately. michael@0: */ michael@0: CodeMirror.defineExtension("openNotification", function(template, options) { michael@0: closeNotification(this, close); michael@0: var dialog = dialogDiv(this, template, options && options.bottom); michael@0: var duration = options && (options.duration === undefined ? 5000 : options.duration); michael@0: var closed = false, doneTimer; michael@0: michael@0: function close() { michael@0: if (closed) return; michael@0: closed = true; michael@0: clearTimeout(doneTimer); michael@0: dialog.parentNode.removeChild(dialog); michael@0: } michael@0: michael@0: CodeMirror.on(dialog, 'click', function(e) { michael@0: CodeMirror.e_preventDefault(e); michael@0: close(); michael@0: }); michael@0: if (duration) michael@0: doneTimer = setTimeout(close, options.duration); michael@0: }); michael@0: });