dialog.js (5174B)
1 // CodeMirror, copyright (c) by Marijn Haverbeke and others 2 // Distributed under an MIT license: http://codemirror.net/LICENSE 3 4 // Open simple dialogs on top of an editor. Relies on dialog.css. 5 6 (function(mod) { 7 if (typeof exports == "object" && typeof module == "object") // CommonJS 8 mod(require("../../lib/codemirror")); 9 else if (typeof define == "function" && define.amd) // AMD 10 define(["../../lib/codemirror"], mod); 11 else // Plain browser env 12 mod(CodeMirror); 13 })(function(CodeMirror) { 14 function dialogDiv(cm, template, bottom) { 15 var wrap = cm.getWrapperElement(); 16 var dialog; 17 dialog = wrap.appendChild(document.createElement("div")); 18 if (bottom) 19 dialog.className = "CodeMirror-dialog CodeMirror-dialog-bottom"; 20 else 21 dialog.className = "CodeMirror-dialog CodeMirror-dialog-top"; 22 23 if (typeof template == "string") { 24 dialog.innerHTML = template; 25 } else { // Assuming it's a detached DOM element. 26 dialog.appendChild(template); 27 } 28 CodeMirror.addClass(wrap, 'dialog-opened'); 29 return dialog; 30 } 31 32 function closeNotification(cm, newVal) { 33 if (cm.state.currentNotificationClose) 34 cm.state.currentNotificationClose(); 35 cm.state.currentNotificationClose = newVal; 36 } 37 38 CodeMirror.defineExtension("openDialog", function(template, callback, options) { 39 if (!options) options = {}; 40 41 closeNotification(this, null); 42 43 var dialog = dialogDiv(this, template, options.bottom); 44 var closed = false, me = this; 45 function close(newVal) { 46 if (typeof newVal == 'string') { 47 inp.value = newVal; 48 } else { 49 if (closed) return; 50 closed = true; 51 CodeMirror.rmClass(dialog.parentNode, 'dialog-opened'); 52 dialog.parentNode.removeChild(dialog); 53 me.focus(); 54 55 if (options.onClose) options.onClose(dialog); 56 } 57 } 58 59 var inp = dialog.getElementsByTagName("input")[0], button; 60 if (inp) { 61 inp.focus(); 62 63 if (options.value) { 64 inp.value = options.value; 65 if (options.selectValueOnOpen !== false) { 66 inp.select(); 67 } 68 } 69 70 if (options.onInput) 71 CodeMirror.on(inp, "input", function(e) { options.onInput(e, inp.value, close);}); 72 if (options.onKeyUp) 73 CodeMirror.on(inp, "keyup", function(e) {options.onKeyUp(e, inp.value, close);}); 74 75 CodeMirror.on(inp, "keydown", function(e) { 76 if (options && options.onKeyDown && options.onKeyDown(e, inp.value, close)) { return; } 77 if (e.keyCode == 27 || (options.closeOnEnter !== false && e.keyCode == 13)) { 78 inp.blur(); 79 CodeMirror.e_stop(e); 80 close(); 81 } 82 if (e.keyCode == 13) callback(inp.value, e); 83 }); 84 85 if (options.closeOnBlur !== false) CodeMirror.on(inp, "blur", close); 86 } else if (button = dialog.getElementsByTagName("button")[0]) { 87 CodeMirror.on(button, "click", function() { 88 close(); 89 me.focus(); 90 }); 91 92 if (options.closeOnBlur !== false) CodeMirror.on(button, "blur", close); 93 94 button.focus(); 95 } 96 return close; 97 }); 98 99 CodeMirror.defineExtension("openConfirm", function(template, callbacks, options) { 100 closeNotification(this, null); 101 var dialog = dialogDiv(this, template, options && options.bottom); 102 var buttons = dialog.getElementsByTagName("button"); 103 var closed = false, me = this, blurring = 1; 104 function close() { 105 if (closed) return; 106 closed = true; 107 CodeMirror.rmClass(dialog.parentNode, 'dialog-opened'); 108 dialog.parentNode.removeChild(dialog); 109 me.focus(); 110 } 111 buttons[0].focus(); 112 for (var i = 0; i < buttons.length; ++i) { 113 var b = buttons[i]; 114 (function(callback) { 115 CodeMirror.on(b, "click", function(e) { 116 CodeMirror.e_preventDefault(e); 117 close(); 118 if (callback) callback(me); 119 }); 120 })(callbacks[i]); 121 CodeMirror.on(b, "blur", function() { 122 --blurring; 123 setTimeout(function() { if (blurring <= 0) close(); }, 200); 124 }); 125 CodeMirror.on(b, "focus", function() { ++blurring; }); 126 } 127 }); 128 129 /* 130 * openNotification 131 * Opens a notification, that can be closed with an optional timer 132 * (default 5000ms timer) and always closes on click. 133 * 134 * If a notification is opened while another is opened, it will close the 135 * currently opened one and open the new one immediately. 136 */ 137 CodeMirror.defineExtension("openNotification", function(template, options) { 138 closeNotification(this, close); 139 var dialog = dialogDiv(this, template, options && options.bottom); 140 var closed = false, doneTimer; 141 var duration = options && typeof options.duration !== "undefined" ? options.duration : 5000; 142 143 function close() { 144 if (closed) return; 145 closed = true; 146 clearTimeout(doneTimer); 147 CodeMirror.rmClass(dialog.parentNode, 'dialog-opened'); 148 dialog.parentNode.removeChild(dialog); 149 } 150 151 CodeMirror.on(dialog, 'click', function(e) { 152 CodeMirror.e_preventDefault(e); 153 close(); 154 }); 155 156 if (duration) 157 doneTimer = setTimeout(close, duration); 158 159 return close; 160 }); 161 });