[ Index ] |
PHP Cross Reference of Joomla 4.2.2 documentation |
[Summary view] [Print] [Text view]
1 // CodeMirror, copyright (c) by Marijn Haverbeke and others 2 // Distributed under an MIT license: https://codemirror.net/5/LICENSE 3 4 // Define search commands. Depends on dialog.js or another 5 // implementation of the openDialog method. 6 7 // Replace works a little oddly -- it will do the replace on the next 8 // Ctrl-G (or whatever is bound to findNext) press. You prevent a 9 // replace by making sure the match is no longer selected when hitting 10 // Ctrl-G. 11 12 (function(mod) { 13 if (typeof exports == "object" && typeof module == "object") // CommonJS 14 mod(require("../../lib/codemirror"), require("./searchcursor"), require("../dialog/dialog")); 15 else if (typeof define == "function" && define.amd) // AMD 16 define(["../../lib/codemirror", "./searchcursor", "../dialog/dialog"], mod); 17 else // Plain browser env 18 mod(CodeMirror); 19 })(function(CodeMirror) { 20 "use strict"; 21 22 // default search panel location 23 CodeMirror.defineOption("search", {bottom: false}); 24 25 function searchOverlay(query, caseInsensitive) { 26 if (typeof query == "string") 27 query = new RegExp(query.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&"), caseInsensitive ? "gi" : "g"); 28 else if (!query.global) 29 query = new RegExp(query.source, query.ignoreCase ? "gi" : "g"); 30 31 return {token: function(stream) { 32 query.lastIndex = stream.pos; 33 var match = query.exec(stream.string); 34 if (match && match.index == stream.pos) { 35 stream.pos += match[0].length || 1; 36 return "searching"; 37 } else if (match) { 38 stream.pos = match.index; 39 } else { 40 stream.skipToEnd(); 41 } 42 }}; 43 } 44 45 function SearchState() { 46 this.posFrom = this.posTo = this.lastQuery = this.query = null; 47 this.overlay = null; 48 } 49 50 function getSearchState(cm) { 51 return cm.state.search || (cm.state.search = new SearchState()); 52 } 53 54 function queryCaseInsensitive(query) { 55 return typeof query == "string" && query == query.toLowerCase(); 56 } 57 58 function getSearchCursor(cm, query, pos) { 59 // Heuristic: if the query string is all lowercase, do a case insensitive search. 60 return cm.getSearchCursor(query, pos, {caseFold: queryCaseInsensitive(query), multiline: true}); 61 } 62 63 function persistentDialog(cm, text, deflt, onEnter, onKeyDown) { 64 cm.openDialog(text, onEnter, { 65 value: deflt, 66 selectValueOnOpen: true, 67 closeOnEnter: false, 68 onClose: function() { clearSearch(cm); }, 69 onKeyDown: onKeyDown, 70 bottom: cm.options.search.bottom 71 }); 72 } 73 74 function dialog(cm, text, shortText, deflt, f) { 75 if (cm.openDialog) cm.openDialog(text, f, {value: deflt, selectValueOnOpen: true, bottom: cm.options.search.bottom}); 76 else f(prompt(shortText, deflt)); 77 } 78 79 function confirmDialog(cm, text, shortText, fs) { 80 if (cm.openConfirm) cm.openConfirm(text, fs); 81 else if (confirm(shortText)) fs[0](); 82 } 83 84 function parseString(string) { 85 return string.replace(/\\([nrt\\])/g, function(match, ch) { 86 if (ch == "n") return "\n" 87 if (ch == "r") return "\r" 88 if (ch == "t") return "\t" 89 if (ch == "\\") return "\\" 90 return match 91 }) 92 } 93 94 function parseQuery(query) { 95 var isRE = query.match(/^\/(.*)\/([a-z]*)$/); 96 if (isRE) { 97 try { query = new RegExp(isRE[1], isRE[2].indexOf("i") == -1 ? "" : "i"); } 98 catch(e) {} // Not a regular expression after all, do a string search 99 } else { 100 query = parseString(query) 101 } 102 if (typeof query == "string" ? query == "" : query.test("")) 103 query = /x^/; 104 return query; 105 } 106 107 function startSearch(cm, state, query) { 108 state.queryText = query; 109 state.query = parseQuery(query); 110 cm.removeOverlay(state.overlay, queryCaseInsensitive(state.query)); 111 state.overlay = searchOverlay(state.query, queryCaseInsensitive(state.query)); 112 cm.addOverlay(state.overlay); 113 if (cm.showMatchesOnScrollbar) { 114 if (state.annotate) { state.annotate.clear(); state.annotate = null; } 115 state.annotate = cm.showMatchesOnScrollbar(state.query, queryCaseInsensitive(state.query)); 116 } 117 } 118 119 function doSearch(cm, rev, persistent, immediate) { 120 var state = getSearchState(cm); 121 if (state.query) return findNext(cm, rev); 122 var q = cm.getSelection() || state.lastQuery; 123 if (q instanceof RegExp && q.source == "x^") q = null 124 if (persistent && cm.openDialog) { 125 var hiding = null 126 var searchNext = function(query, event) { 127 CodeMirror.e_stop(event); 128 if (!query) return; 129 if (query != state.queryText) { 130 startSearch(cm, state, query); 131 state.posFrom = state.posTo = cm.getCursor(); 132 } 133 if (hiding) hiding.style.opacity = 1 134 findNext(cm, event.shiftKey, function(_, to) { 135 var dialog 136 if (to.line < 3 && document.querySelector && 137 (dialog = cm.display.wrapper.querySelector(".CodeMirror-dialog")) && 138 dialog.getBoundingClientRect().bottom - 4 > cm.cursorCoords(to, "window").top) 139 (hiding = dialog).style.opacity = .4 140 }) 141 }; 142 persistentDialog(cm, getQueryDialog(cm), q, searchNext, function(event, query) { 143 var keyName = CodeMirror.keyName(event) 144 var extra = cm.getOption('extraKeys'), cmd = (extra && extra[keyName]) || CodeMirror.keyMap[cm.getOption("keyMap")][keyName] 145 if (cmd == "findNext" || cmd == "findPrev" || 146 cmd == "findPersistentNext" || cmd == "findPersistentPrev") { 147 CodeMirror.e_stop(event); 148 startSearch(cm, getSearchState(cm), query); 149 cm.execCommand(cmd); 150 } else if (cmd == "find" || cmd == "findPersistent") { 151 CodeMirror.e_stop(event); 152 searchNext(query, event); 153 } 154 }); 155 if (immediate && q) { 156 startSearch(cm, state, q); 157 findNext(cm, rev); 158 } 159 } else { 160 dialog(cm, getQueryDialog(cm), "Search for:", q, function(query) { 161 if (query && !state.query) cm.operation(function() { 162 startSearch(cm, state, query); 163 state.posFrom = state.posTo = cm.getCursor(); 164 findNext(cm, rev); 165 }); 166 }); 167 } 168 } 169 170 function findNext(cm, rev, callback) {cm.operation(function() { 171 var state = getSearchState(cm); 172 var cursor = getSearchCursor(cm, state.query, rev ? state.posFrom : state.posTo); 173 if (!cursor.find(rev)) { 174 cursor = getSearchCursor(cm, state.query, rev ? CodeMirror.Pos(cm.lastLine()) : CodeMirror.Pos(cm.firstLine(), 0)); 175 if (!cursor.find(rev)) return; 176 } 177 cm.setSelection(cursor.from(), cursor.to()); 178 cm.scrollIntoView({from: cursor.from(), to: cursor.to()}, 20); 179 state.posFrom = cursor.from(); state.posTo = cursor.to(); 180 if (callback) callback(cursor.from(), cursor.to()) 181 });} 182 183 function clearSearch(cm) {cm.operation(function() { 184 var state = getSearchState(cm); 185 state.lastQuery = state.query; 186 if (!state.query) return; 187 state.query = state.queryText = null; 188 cm.removeOverlay(state.overlay); 189 if (state.annotate) { state.annotate.clear(); state.annotate = null; } 190 });} 191 192 function el(tag, attrs) { 193 var element = tag ? document.createElement(tag) : document.createDocumentFragment(); 194 for (var key in attrs) { 195 element[key] = attrs[key]; 196 } 197 for (var i = 2; i < arguments.length; i++) { 198 var child = arguments[i] 199 element.appendChild(typeof child == "string" ? document.createTextNode(child) : child); 200 } 201 return element; 202 } 203 204 function getQueryDialog(cm) { 205 var label = el("label", {className: "CodeMirror-search-label"}, 206 cm.phrase("Search:"), 207 el("input", {type: "text", "style": "width: 10em", className: "CodeMirror-search-field", 208 id: "CodeMirror-search-field"})); 209 label.setAttribute("for","CodeMirror-search-field"); 210 return el("", null, label, " ", 211 el("span", {style: "color: #666", className: "CodeMirror-search-hint"}, 212 cm.phrase("(Use /re/ syntax for regexp search)"))); 213 } 214 function getReplaceQueryDialog(cm) { 215 return el("", null, " ", 216 el("input", {type: "text", "style": "width: 10em", className: "CodeMirror-search-field"}), " ", 217 el("span", {style: "color: #666", className: "CodeMirror-search-hint"}, 218 cm.phrase("(Use /re/ syntax for regexp search)"))); 219 } 220 function getReplacementQueryDialog(cm) { 221 return el("", null, 222 el("span", {className: "CodeMirror-search-label"}, cm.phrase("With:")), " ", 223 el("input", {type: "text", "style": "width: 10em", className: "CodeMirror-search-field"})); 224 } 225 function getDoReplaceConfirm(cm) { 226 return el("", null, 227 el("span", {className: "CodeMirror-search-label"}, cm.phrase("Replace?")), " ", 228 el("button", {}, cm.phrase("Yes")), " ", 229 el("button", {}, cm.phrase("No")), " ", 230 el("button", {}, cm.phrase("All")), " ", 231 el("button", {}, cm.phrase("Stop"))); 232 } 233 234 function replaceAll(cm, query, text) { 235 cm.operation(function() { 236 for (var cursor = getSearchCursor(cm, query); cursor.findNext();) { 237 if (typeof query != "string") { 238 var match = cm.getRange(cursor.from(), cursor.to()).match(query); 239 cursor.replace(text.replace(/\$(\d)/g, function(_, i) {return match[i];})); 240 } else cursor.replace(text); 241 } 242 }); 243 } 244 245 function replace(cm, all) { 246 if (cm.getOption("readOnly")) return; 247 var query = cm.getSelection() || getSearchState(cm).lastQuery; 248 var dialogText = all ? cm.phrase("Replace all:") : cm.phrase("Replace:") 249 var fragment = el("", null, 250 el("span", {className: "CodeMirror-search-label"}, dialogText), 251 getReplaceQueryDialog(cm)) 252 dialog(cm, fragment, dialogText, query, function(query) { 253 if (!query) return; 254 query = parseQuery(query); 255 dialog(cm, getReplacementQueryDialog(cm), cm.phrase("Replace with:"), "", function(text) { 256 text = parseString(text) 257 if (all) { 258 replaceAll(cm, query, text) 259 } else { 260 clearSearch(cm); 261 var cursor = getSearchCursor(cm, query, cm.getCursor("from")); 262 var advance = function() { 263 var start = cursor.from(), match; 264 if (!(match = cursor.findNext())) { 265 cursor = getSearchCursor(cm, query); 266 if (!(match = cursor.findNext()) || 267 (start && cursor.from().line == start.line && cursor.from().ch == start.ch)) return; 268 } 269 cm.setSelection(cursor.from(), cursor.to()); 270 cm.scrollIntoView({from: cursor.from(), to: cursor.to()}); 271 confirmDialog(cm, getDoReplaceConfirm(cm), cm.phrase("Replace?"), 272 [function() {doReplace(match);}, advance, 273 function() {replaceAll(cm, query, text)}]); 274 }; 275 var doReplace = function(match) { 276 cursor.replace(typeof query == "string" ? text : 277 text.replace(/\$(\d)/g, function(_, i) {return match[i];})); 278 advance(); 279 }; 280 advance(); 281 } 282 }); 283 }); 284 } 285 286 CodeMirror.commands.find = function(cm) {clearSearch(cm); doSearch(cm);}; 287 CodeMirror.commands.findPersistent = function(cm) {clearSearch(cm); doSearch(cm, false, true);}; 288 CodeMirror.commands.findPersistentNext = function(cm) {doSearch(cm, false, true, true);}; 289 CodeMirror.commands.findPersistentPrev = function(cm) {doSearch(cm, true, true, true);}; 290 CodeMirror.commands.findNext = doSearch; 291 CodeMirror.commands.findPrev = function(cm) {doSearch(cm, true);}; 292 CodeMirror.commands.clearSearch = clearSearch; 293 CodeMirror.commands.replace = replace; 294 CodeMirror.commands.replaceAll = function(cm) {replace(cm, true);}; 295 });
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Wed Sep 7 05:41:13 2022 | Chilli.vc Blog - For Webmaster,Blog-Writer,System Admin and Domainer |