js/find.js

  1. /**=====LICENSE STATEMENT START=====
  2. Translator++
  3. CAT (Computer-Assisted Translation) tools and framework to create quality
  4. translations and localizations efficiently.
  5. Copyright (C) 2018 Dreamsavior<dreamsavior@gmail.com>
  6. This program is free software: you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation, either version 3 of the License, or
  9. (at your option) any later version.
  10. This program is distributed in the hope that it will be useful,
  11. but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. GNU General Public License for more details.
  14. You should have received a copy of the GNU General Public License
  15. along with this program. If not, see <https://www.gnu.org/licenses/>.
  16. =====LICENSE STATEMENT END=====*/
  17. var nwPath = require("path"); // eslint-disable-line
  18. const Search = function() {
  19. try {
  20. this.config = JSON.parse(localStorage.getItem('search.config'));
  21. } catch (e) {
  22. // do nothing.
  23. }
  24. this.config = this.config || {};
  25. if (typeof this.config.alwaysOnTop == 'undefined') this.config.alwaysOnTop = true;
  26. this.config.blurOpacity = this.config.blurOpacity || 0.7
  27. };
  28. var search = new Search();
  29. search.setConfig = function(key, value) {
  30. this.config[key] = value;
  31. this.saveConfig();
  32. }
  33. search.getConfig = function(key) {
  34. return this.config[key];
  35. }
  36. search.saveConfig = function() {
  37. localStorage.setItem('search.config', JSON.stringify(this.config));
  38. }
  39. search.blurOpacity = search.getConfig('blurOpacity');
  40. var win = nw.Window.get();
  41. win.restore(); // restore if minimized
  42. win.show(); // show if hidden
  43. win.setResizable(true);
  44. win.height = 340;
  45. win.width = 640;
  46. if (win.y < 0) win.y = 0;
  47. if (win.x < 0) win.x = 0;
  48. //win.setResizable(false);
  49. console.log("current Y", win.y, win.y < 0);
  50. setTimeout(()=>{
  51. if (win.y < 0) win.y = 0;
  52. win.setMinimumSize(640, 340)
  53. console.log("current Y", win.y);
  54. try {
  55. var lastPos = window.localStorage.getItem("searchWindowPossition");
  56. if (!lastPos) return;
  57. lastPos = JSON.parse(lastPos);
  58. console.log("Setting window position", lastPos);
  59. win.x = lastPos.x;
  60. win.y = lastPos.y;
  61. } catch(e) {
  62. //do nothing
  63. }
  64. }, 200)
  65. win.setAlwaysOnTop(search.getConfig('alwaysOnTop'));
  66. win.setShowInTaskbar(false);
  67. win.setMinimumSize(530, 260);
  68. var sys = window.opener.sys;
  69. var trans = window.opener.trans;
  70. var ui = window.opener.ui;
  71. var UiTags = window.opener.UiTags;
  72. search.getSelectedResult = function() {
  73. var $activeTab = $(".ui-tabs-panel[aria-hidden=false]")
  74. var $selected = $activeTab.find(".findItemSelector:checked");
  75. var data = [];
  76. $selected.each(function() {
  77. var $this = $(this);
  78. var thisData = $this.data();
  79. thisData.file = $this.closest(".resultContext").data("id")
  80. data.push(thisData);
  81. })
  82. return data;
  83. }
  84. /**
  85. * Replaces \r\n\t with carriage return, new line or tab
  86. * @param {String} text
  87. * @returns {String} transpiled text
  88. */
  89. search.transpileText = function(text) {
  90. console.log("Transpiling text", text);
  91. text = text || "";
  92. text = text.replaceAll("\\r", "\r");
  93. text = text.replaceAll("\\n", "\n");
  94. text = text.replaceAll("\\t", "\t");
  95. console.log("After transpile:", text);
  96. return text;
  97. }
  98. search.initFileSelectorDragSelect = function() {
  99. var DragSelect = DragSelect||require("dragselect");
  100. const toggleCheck = function(elm) {
  101. //console.log($(elm));
  102. //console.log(this);
  103. var $elm = $(elm);
  104. // ignore selection if selecting less than 2 row
  105. var orig = this._initialCursorPos.x+","+this._initialCursorPos.y;
  106. var after = this._newCursorPos.x+","+this._newCursorPos.y;
  107. if (orig == after) return false;
  108. if ($elm.length <= 1) return false;
  109. $elm.each(function() {
  110. var $input = $(this).find("input");
  111. if ($input.prop("disabled")) return;
  112. if (search.shiftPressed) {
  113. $input.prop("checked", false);
  114. } else {
  115. $input.prop("checked", true);
  116. }
  117. $input.trigger("change");
  118. window.ds.clearSelection();
  119. })
  120. }
  121. const $fileSelectors = $(".fileSelector")
  122. for (let i=0; i<$fileSelectors.length; i++) {
  123. let thisSelector = $fileSelectors[i]
  124. window.ds = new DragSelect({
  125. selectables : document.querySelectorAll('.selectable'),
  126. autoScrollSpeed : 15,
  127. area : thisSelector,
  128. callback : toggleCheck
  129. });
  130. }
  131. if (search.fileSelectorIsInitialized) return;
  132. // tracking shift key
  133. window.onkeyup = function(e) {
  134. if (e.keyCode == 16) search.shiftPressed = false;
  135. //console.log("canceled");
  136. }
  137. window.onkeydown = function(e) {
  138. if (e.shiftKey) search.shiftPressed = true;
  139. //console.log("do");
  140. }
  141. search.fileSelectorIsInitialized = true;
  142. }
  143. search.getKeyboardStatus = function(keyboard) {
  144. if (keyboard == "shift") return search.shiftPressed;
  145. }
  146. search.checkGroup = function($selectFld, action) {
  147. var $allCheckbox = $selectFld.closest('.resultContext').find("ul .findItemSelector");
  148. var thisStatus = $selectFld.prop("checked");
  149. $allCheckbox.each(function() {
  150. $(this).prop("checked", thisStatus)
  151. })
  152. }
  153. search.checkAll = function($selectFld, action) {
  154. console.log($selectFld);
  155. var $allHeaderCheckbox = $selectFld.closest('.actionResult').find(".headerGroupCheckbox");
  156. var thisStatus = $selectFld.prop("checked");
  157. $allHeaderCheckbox.each(function() {
  158. $(this).prop("checked", thisStatus);
  159. $(this).trigger("input");
  160. })
  161. }
  162. search.getTags = function(file, row) {
  163. // results : array of tags;
  164. var result = [];
  165. try {
  166. result = trans.project.files[file].tags[row];
  167. } catch (err) {
  168. // do nothing
  169. }
  170. return result;
  171. }
  172. search.drawTags = function($resultLine, file, row, options) {
  173. options = options||{};
  174. options.force = options.force||false;
  175. try {
  176. var tags = search.getTags(file, row);
  177. if (options.force == false) {
  178. if (Array.isArray(tags) == false) return $resultLine;
  179. if (tags.length == 0) return $resultLine;
  180. }
  181. var $resultInfo = $resultLine.find(".resultInfo");
  182. $resultInfo.find(".tags").remove();
  183. var $tagContainer = $("<span class='tags'></span>");
  184. $resultInfo.append($tagContainer);
  185. if (Array.isArray(tags) == false) return $resultLine;
  186. for (var i=0; i<tags.length; i++) {
  187. let $thisIcon = $("<i class='tagIcon icon-circle "+tags[i]+"' title='"+tags[i]+"'></i>");
  188. $thisIcon.css("color", consts.tagColor[tags[i]]);
  189. $tagContainer.append($thisIcon);
  190. }
  191. } catch (err) {
  192. console.log("Error drawing tags", err);
  193. }
  194. return $resultLine;
  195. }
  196. search.appendTags = function(file, row, tags, $actionResult) {
  197. try {
  198. if (Array.isArray(tags) == false) tags = [tags];
  199. trans.appendTags(file, parseInt(row), tags);
  200. } catch (err) {
  201. console.warning("Failed to handle appendTags", err);
  202. }
  203. }
  204. search.appendTagsOnSelected = function(tags, $actionResult) {
  205. $actionResult = $actionResult||$(".ui-tabs-panel[aria-hidden=false] .actionResult");
  206. var startTime = performance.now();
  207. var $lines = $actionResult.find(".findItemSelector:checked");
  208. $lines.each(function() {
  209. var $this = $(this);
  210. var $resultItem = $this.closest(".resultItem");
  211. var $resultContext = $this.closest(".resultContext");
  212. search.appendTags($resultContext.data("id"), $resultItem.attr("data-row"), tags);
  213. search.drawTags($resultItem, $resultContext.data("id"), $resultItem.attr("data-row"));
  214. });
  215. var endTime = performance.now()
  216. console.log(`Append tags done! It took ${endTime - startTime} ms `);
  217. trans.grid.render();
  218. }
  219. search.setTags = function(file, row, tags, $actionResult) {
  220. try {
  221. if (Array.isArray(tags) == false) tags = [tags];
  222. trans.setTags(file, parseInt(row), tags);
  223. } catch (err) {
  224. console.warning("Failed to handle appendTags", err);
  225. }
  226. }
  227. search.setTagsOnSelected = function(tags, $actionResult) {
  228. $actionResult = $actionResult||$(".ui-tabs-panel[aria-hidden=false] .actionResult");
  229. var $lines = $actionResult.find(".findItemSelector:checked");
  230. $lines.each(function() {
  231. var $resultItem = $(this).closest(".resultItem");
  232. var $resultContext = $(this).closest(".resultContext");
  233. search.setTags($resultContext.data("id"), $resultItem.attr("data-row"), tags);
  234. search.drawTags($resultItem, $resultContext.data("id"), $resultItem.attr("data-row"));
  235. })
  236. trans.grid.render();
  237. }
  238. search.removeTags = function(file, row, tags, $actionResult) {
  239. try {
  240. if (Array.isArray(tags) == false) tags = [tags];
  241. trans.removeTags(file, parseInt(row), tags);
  242. } catch (err) {
  243. console.warning("Failed to handle appendTags", err);
  244. }
  245. }
  246. search.removeTagsOnSelected = function(tags, $actionResult) {
  247. $actionResult = $actionResult||$(".ui-tabs-panel[aria-hidden=false] .actionResult");
  248. var $lines = $actionResult.find(".findItemSelector:checked");
  249. $lines.each(function() {
  250. var $resultItem = $(this).closest(".resultItem");
  251. var $resultContext = $(this).closest(".resultContext");
  252. search.removeTags($resultContext.data("id"), $resultItem.attr("data-row"), tags);
  253. search.drawTags($resultItem, $resultContext.data("id"), $resultItem.attr("data-row"));
  254. });
  255. trans.grid.render();
  256. }
  257. search.clearTags = function(file, row, $actionResult) {
  258. try {
  259. trans.clearTags(file, parseInt(row));
  260. } catch (err) {
  261. console.warning("Failed to handle clearTags", err);
  262. }
  263. }
  264. search.clearTagsOnSelected = function($actionResult) {
  265. $actionResult = $actionResult||$(".ui-tabs-panel[aria-hidden=false] .actionResult");
  266. var $lines = $actionResult.find(".findItemSelector:checked");
  267. $lines.each(function() {
  268. var $resultItem = $(this).closest(".resultItem");
  269. var $resultContext = $(this).closest(".resultContext");
  270. search.clearTags($resultContext.data("id"), $resultItem.attr("data-row"));
  271. $resultItem.find(".tags").empty();
  272. })
  273. trans.grid.render();
  274. }
  275. search.openTagMenu = function() {
  276. var $popup = $("#find_tagMenu");
  277. if ($popup.length == 0) {
  278. $popup = $("<div id='find_tagMenu'></div>");
  279. $("#template").append($popup);
  280. var tags = new UiTags({
  281. options : $(`
  282. <h2 data-tran="">${t('Action')}</h2>
  283. <div class="actionSet">
  284. <label class="flex"><input type="radio" name="tagAction" class="appendTags" value="appendTags" /> <span data-tran="">${t('Append tags')}</span></label>
  285. <label class="flex"><input type="radio" name="tagAction" class="removeTags" value="removeTags" /> <span data-tran="">${t('Remove tags')}</span></label>
  286. <label class="flex"><input type="radio" name="tagAction" class="setTags" value="setTags" /> <span data-tran="">${t('Set tags')}</span></label>
  287. <label class="flex"><input type="radio" name="tagAction" class="actionNone" value="" /> <span data-tran="">${t('Do nothing')}</span></label>
  288. </div>
  289. `)
  290. });
  291. this._uiTags = tags;
  292. $popup.empty();
  293. $popup.append(tags.element);
  294. }
  295. $popup.dialog({
  296. title: t("Set tags"),
  297. autoOpen: false,
  298. modal:true,
  299. width:480,
  300. height:220,
  301. minWidth:480,
  302. minHeight:220,
  303. show: {
  304. effect: "fade",
  305. duration: 200
  306. },
  307. hide: {
  308. effect: "fade",
  309. duration: 200
  310. },
  311. buttons:[
  312. {
  313. text: t("Close"),
  314. icon: "ui-icon-close",
  315. click: function() {
  316. $(this).dialog( "close" );
  317. }
  318. },
  319. {
  320. text: t("Proceed"),
  321. click: async function() {
  322. var $this = $(this)
  323. var tags = search._uiTags.getValue();
  324. console.log(tags);
  325. if (tags === false) return false;
  326. $this.dialog( "close" );
  327. if (tags.filterTagMode == "appendTags") {
  328. search.appendTagsOnSelected(tags.filterTag);
  329. } else if (tags.filterTagMode == "removeTags") {
  330. search.removeTagsOnSelected(tags.filterTag);
  331. } else {
  332. search.setTagsOnSelected(tags.filterTag);
  333. }
  334. }
  335. }
  336. ]
  337. });
  338. $popup.dialog("open");
  339. }
  340. search.loadKeywords = function() {
  341. var $keywords = $("#keywords");
  342. if (!localStorage.getItem("search.keywords")) return;
  343. try {
  344. var keywords = JSON.parse(localStorage.getItem("search.keywords"))
  345. } catch (e) {
  346. // do nothing
  347. }
  348. for (var i=0; i<keywords.length; i++) {
  349. var $newOption = $("<option></option>");
  350. $newOption.attr("value", keywords[i]);
  351. $keywords.append($newOption);
  352. }
  353. }
  354. search.addKeyword = function(keyword) {
  355. var $keywords = $("#keywords");
  356. try {
  357. // remove existing keyword
  358. var $exsit = $keywords.find(`[value="${CSS.escape(keyword)}"]`);
  359. $exsit.remove();
  360. } catch (e) {
  361. console.warn(e)
  362. }
  363. var $newOption = $("<option></option>");
  364. $newOption.attr("value", keyword);
  365. $keywords.prepend($newOption);
  366. $keywords = $keywords.find("option");
  367. if ($keywords.length > 100) {
  368. $keywords.eq($keywords.length - 1).remove();
  369. }
  370. // save keyword
  371. var keywords = [];
  372. for (var i=0; i<$keywords.length; i++) {
  373. keywords.push($keywords.eq(i).attr("value"));
  374. }
  375. if (keywords.length>0) localStorage.setItem("search.keywords", JSON.stringify(keywords))
  376. }
  377. search.sendCommandFind = function(keyword) {
  378. keyword = keyword||$("#fieldFind").val();
  379. if (keyword.length < 1) return alert(t("Keyword too short!"));
  380. this.addKeyword(keyword);
  381. var caseSensitiveMode = $("#caseSensitive").prop("checked");
  382. var $notFoundMsg = $("<div class='blockBox infoBlock withIcon'>"+t("Found nothing!<br />Don't forget to set the Target search field.")+"</div>")
  383. var selectedFiles = "*";
  384. if ($("#selectAllFile").prop("checked") == false) {
  385. selectedFiles = [];
  386. $("#find .fileSelector .filename:checked").each(function() {
  387. selectedFiles.push($(this).attr("value"));
  388. });
  389. }
  390. // transpile
  391. if ($("#find .transpileCode").prop("checked")) {
  392. keyword = this.transpileText(keyword);
  393. }
  394. console.log("Selected file is :");
  395. console.log(selectedFiles);
  396. // array of value
  397. var searchLocations = $(".searchMode").val();
  398. var result = trans.search(keyword, {
  399. caseSensitive : caseSensitiveMode,
  400. files : selectedFiles,
  401. searchLocations : searchLocations,
  402. isRegexp : $("#findIsRegexp").prop("checked")
  403. });
  404. search.toggleFileList(false);
  405. $("#find .searchResult").empty();
  406. var $template = $("<div class='searchResultHeader column2'>\
  407. <div class='searchresultAction'>\
  408. <input type='checkbox' value='' class='headerCheckbox' /> \
  409. <span>Select all</span>\
  410. </div>\
  411. <div class='right searchResultData'>\
  412. <i class='icon-docs'></i> <span class='numFile'>"+result.count+"</span>\
  413. <i class='icon-hourglass-3'></i> "+result.executionTime+" ms\
  414. </div>\
  415. </div>");
  416. $template.find(".headerCheckbox").on("input", function(e) {
  417. search.checkAll.call(search, $(this));
  418. });
  419. $("#find .searchResult").append($template);
  420. if (typeof result.files == "undefined" || result.count == 0) $("#find .searchResult").append($notFoundMsg);
  421. for (var file in result.files) {
  422. //var $lineFile = $("<div class='resultContext' data-id="+file+"><h2><input type='checkbox' value='1' class='headerGroupCheckbox' /> <i class='icon-doc'></i>"+file+" <span class='contextCount'>"+result.files[file].length+"</span></h2><ul></ul></div>");
  423. var $lineFile = $("<div class='resultContext' ><h2><input type='checkbox' value='1' class='headerGroupCheckbox' /> <i class='icon-doc'></i>"+file+" <span class='contextCount'>"+result.files[file].length+"</span></h2><ul></ul></div>");
  424. $lineFile.data("id", file);
  425. $lineFile.find(".headerGroupCheckbox").on("input", function(e) {
  426. search.checkGroup.call(search, $(this));
  427. });
  428. for(var i in result.files[file]) {
  429. var currentLine = result.files[file][i];
  430. var refference = "";
  431. var foundStr = common.htmlEntities(currentLine.fullString);
  432. if (result.isRegexp) {
  433. var regExpKeyword = common.evalRegExpStr(keyword);
  434. if (regExpKeyword !== false) {
  435. foundStr = foundStr.replace(regExpKeyword,
  436. function(){
  437. return '<span class="highlight">'+arguments[0]+'</span>';
  438. });
  439. }
  440. } else {
  441. foundStr = foundStr.replaces(keyword, "<span class='highlight'>"+common.htmlEntities(keyword)+"</span>", !caseSensitiveMode);
  442. }
  443. //console.log(currentLine);
  444. try {
  445. var thisFileRef = trans.project.files[file].data[currentLine.row];
  446. if (currentLine.col == 0) {
  447. // this is key row, search translation for refference
  448. for (var n=thisFileRef.length; n>0; n--) {
  449. if (thisFileRef[n]) {
  450. refference = thisFileRef[n];
  451. break;
  452. }
  453. }
  454. } else {
  455. // this not a key row, search keyrow for refference
  456. refference = thisFileRef[0];
  457. }
  458. }
  459. catch (err) {
  460. // do nothing
  461. }
  462. refference = common.htmlEntities(refference);
  463. var lineTemplate = $("<li class='resultItem' title='click to go' data-row='"+currentLine.row+"' data-col='"+currentLine.col+"'>"+
  464. "<div class='texts'>"+
  465. "<h1>"+foundStr+"</h1>"+
  466. "<h1 class='refference' title='refference'>"+refference+"</h1>"+
  467. "</div>"+
  468. `<div class='resultInfo'><span class='findItemSelectorWrapper'><input type='checkbox' data-row='${currentLine.row}' data-col='${currentLine.col}' class='findItemSelector' value='' /></span><span class='rowLabel' title='row'>${currentLine.row}</span><span class='colLabel' title='column'>${currentLine.col}</span></div></li>`);
  469. lineTemplate.data("row", currentLine.row);
  470. lineTemplate.data("col", currentLine.col);
  471. lineTemplate.data("context", file);
  472. lineTemplate.on("click", function(e) {
  473. if ($(e.target).is("input[type=checkbox]")) {
  474. return;
  475. }
  476. trans.goTo($(this).data("row"), $(this).data("col"), $(this).data("context"));
  477. $(this).closest(".searchResult").find(".selected").removeClass("selected");
  478. $(this).addClass("selected");
  479. });
  480. lineTemplate.find(".findItemSelector").on("change", function() {
  481. search.find = search.find || {};
  482. if ($(this).prop("checked") == true) {
  483. search.find.$lastCheckedFile = $(this);
  484. } else {
  485. search.find.$lastCheckedFile = undefined;
  486. }
  487. });
  488. lineTemplate.find(".findItemSelector").on("mousedown", function(e) {
  489. search.find = search.find || {};
  490. if (!search.find.$lastCheckedFile) return false;
  491. if (e.shiftKey) {
  492. console.log("The SHIFT key was pressed!");
  493. var $checkBoxes = $(this).closest(".actionResult").find(".findItemSelector");
  494. var lastIndex = $checkBoxes.index(search.find.$lastCheckedFile);
  495. var thisIndex = $checkBoxes.index(this);
  496. var chckFrom;
  497. var chckTo;
  498. if (lastIndex < thisIndex) {
  499. chckFrom = lastIndex;
  500. chckTo = thisIndex;
  501. } else {
  502. chckFrom = thisIndex;
  503. chckTo = lastIndex;
  504. }
  505. console.log("check from index "+chckFrom+" to "+chckTo);
  506. for (var i=chckFrom; i<chckTo; i++) {
  507. $checkBoxes.eq(i).prop("checked", true).trigger("change");
  508. }
  509. }
  510. });
  511. search.drawTags(lineTemplate, file, currentLine.row);
  512. $lineFile.find("ul").append(lineTemplate);
  513. }
  514. $("#find .searchResult").append($lineFile);
  515. }
  516. console.log(result);
  517. }
  518. search.sendCommandReplace = function() {
  519. var keyword = $("#fieldReplaceFind").val();
  520. var replacer = $("#fieldReplaceReplace").val();
  521. if (keyword.length < 1) return alert("Keyword too short!");
  522. this.addKeyword(keyword);
  523. var $notFoundMsg = $("<div class='blockBox infoBlock withIcon'>"+t("Found nothing to replace!<br />Replace function doesn't replace anything on the key column.")+"</div>")
  524. var conf = confirm(t("Replace '")+keyword+t("' with '")+replacer+t("'?\r\nWe still haven't create undo function for this thing!\nAre you sure want to proceed?"));
  525. if (!conf) return false;
  526. var caseSensitiveMode = $("#caseSensitiveReplace").prop("checked");
  527. var selectedFiles = "*";
  528. if ($("#selectAllFileReplace").prop("checked") == false) {
  529. selectedFiles = [];
  530. $("#replace .fileSelector .filename:checked").each(function() {
  531. selectedFiles.push($(this).attr("value"));
  532. });
  533. }
  534. // transpile
  535. if ($("#replace .transpileCode").prop("checked")) {
  536. keyword = this.transpileText(keyword);
  537. replacer = this.transpileText(replacer);
  538. }
  539. console.log("Selected file is :");
  540. console.log(selectedFiles);
  541. var result = trans.replace(keyword, replacer, {
  542. caseSensitive : caseSensitiveMode,
  543. 'files' : selectedFiles,
  544. isRegexp : $("#replaceIsRegexp").prop("checked")
  545. });
  546. search.toggleFileList(false);
  547. $(".replaceResult").empty();
  548. if (typeof result.files == "undefined") $(".replaceResult").html($notFoundMsg);
  549. if (result.count == 0) $(".replaceResult").html($notFoundMsg);
  550. var $template = $("<div class='searchResultHeader column2'>\
  551. <div class='searchresultAction'>\
  552. <input type='checkbox' value='' class='headerCheckbox' /> \
  553. <span>Select all</span>\
  554. </div>\
  555. <div class='right searchResultData'>\
  556. <i class='icon-docs'></i> <span class='numFile'>"+result.count+"</span>\
  557. <i class='icon-hourglass-3'></i> "+result.executionTime+" ms\
  558. </div>\
  559. </div>");
  560. $template.find(".headerCheckbox").on("input", function(e) {
  561. search.checkAll.call(search, $(this));
  562. });
  563. $(".replaceResult").prepend($template);
  564. for (var file in result.files) {
  565. //var $lineFile = $("<div class='resultContext' data-id="+file+"><h2><input type='checkbox' value='1' class='headerGroupCheckbox' /><i class='icon-doc'></i>"+file+" <span class='contextCount'>"+result.files[file].length+"</span></h2><ul></ul></div>");
  566. var $lineFile = $("<div class='resultContext' ><h2><input type='checkbox' value='1' class='headerGroupCheckbox' /><i class='icon-doc'></i>"+file+" <span class='contextCount'>"+result.files[file].length+"</span></h2><ul></ul></div>");
  567. $lineFile.data("id", file);
  568. $lineFile.find(".headerGroupCheckbox").on("input", function(e) {
  569. search.checkGroup.call(search, $(this));
  570. });
  571. for(var i in result.files[file]) {
  572. var currentLine = result.files[file][i];
  573. var foundStr = common.htmlEntities(currentLine.originalString);
  574. if (result.isRegexp) {
  575. var regExpKeyword = common.evalRegExpStr(keyword);
  576. if (regExpKeyword !== false) {
  577. foundStr = foundStr.replace(regExpKeyword,
  578. function(){
  579. return '<span class="highlight2">'+arguments[0]+'</span>';
  580. });
  581. }
  582. } else {
  583. foundStr = foundStr.replaces(keyword, "<span class='highlight2'>"+keyword+"</span>", !caseSensitiveMode);
  584. }
  585. var replacedString = common.htmlEntities(currentLine.fullString).replaces(replacer, "<span class='highlight'>"+replacer+"</span>");
  586. //var foundStr = currentLine.fullString.replaces(keyword, "<span class='highlight'>"+keyword+"</span>", !caseSensitiveMode);
  587. var lineTemplate = $("<li class='resultItem' title='"+t("click to go")+"' data-row='"+currentLine.row+"' data-col='"+currentLine.col+"'>"+
  588. "<div class='texts'>"+
  589. "<h1 class='refference' title='refference'>"+foundStr+"</h1>"+
  590. "<span><i class='icon-right-big'> </i></span>"+
  591. "<h1>"+replacedString+"</h1>"+
  592. "</div>"+
  593. `<div class='resultInfo'><span class='findItemSelectorWrapper'><input type='checkbox' data-row='${currentLine.row}' data-col='${currentLine.col}' class='findItemSelector' value='' /></span><span class='rowLabel' title='row'>${currentLine.row}</span><span class='colLabel' title='column'>${currentLine.col}</span></div></li>`);
  594. lineTemplate.data("row", currentLine.row);
  595. lineTemplate.data("col", currentLine.col);
  596. lineTemplate.data("context", file);
  597. lineTemplate.on("click", function(e) {
  598. if ($(e.target).is("input[type=checkbox]")) {
  599. return;
  600. }
  601. trans.goTo($(this).data("row"), $(this).data("col"), $(this).data("context"));
  602. });
  603. lineTemplate.find(".findItemSelector").on("change", function() {
  604. search.repl = search.repl || {};
  605. if ($(this).prop("checked") == true) {
  606. search.repl.$lastCheckedFile = $(this);
  607. } else {
  608. search.repl.$lastCheckedFile = undefined;
  609. }
  610. });
  611. lineTemplate.find(".findItemSelector").on("mousedown", function(e) {
  612. search.repl = search.repl || {};
  613. if (!search.repl.$lastCheckedFile) return false;
  614. if (e.shiftKey) {
  615. console.log("The SHIFT key was pressed!");
  616. var $checkBoxes = $(this).closest(".actionResult").find(".findItemSelector");
  617. var lastIndex = $checkBoxes.index(search.repl.$lastCheckedFile);
  618. var thisIndex = $checkBoxes.index(this);
  619. var chckFrom;
  620. var chckTo;
  621. if (lastIndex < thisIndex) {
  622. chckFrom = lastIndex;
  623. chckTo = thisIndex;
  624. } else {
  625. chckFrom = thisIndex;
  626. chckTo = lastIndex;
  627. }
  628. console.log("check from index "+chckFrom+" to "+chckTo);
  629. for (let i=chckFrom; i<chckTo; i++) {
  630. $checkBoxes.eq(i).prop("checked", true).trigger("change");
  631. }
  632. }
  633. });
  634. search.drawTags(lineTemplate, file, currentLine.row);
  635. $lineFile.find("ul").append(lineTemplate);
  636. }
  637. $(".replaceResult").append($lineFile);
  638. }
  639. console.log(result);
  640. }
  641. search.sendCommandPut = function() {
  642. var conf = confirm(t("This will replace any translation found in target colum,\nAre you sure?"));
  643. if (!conf) return false;
  644. var keyword = $("#findPut .fldFind").val();
  645. if (keyword.length < 1) return alert(t("Keyword too short!"));
  646. var put = $("#findPut .fldPut").val();
  647. var caseSensitiveMode = $("#findPut .caseSensitive").prop("checked");
  648. var targetCol = parseInt($("#findPut .targetSelector select").val());
  649. targetCol = parseInt(targetCol);
  650. var selectedFiles = "*";
  651. if ($("#findPut .selectAllFile").prop("checked") == false) {
  652. selectedFiles = [];
  653. $("#findPut .fileSelector .filename:checked").each(function() {
  654. selectedFiles.push($(this).attr("value"));
  655. });
  656. }
  657. console.log("Selected file is :");
  658. console.log(selectedFiles);
  659. var result = trans.findPut(keyword, put, targetCol, {
  660. caseSensitive : caseSensitiveMode,
  661. files : selectedFiles,
  662. lineMatch : true
  663. });
  664. console.log("result is", result);
  665. search.toggleFileList(false);
  666. $("#findPut .searchResult").empty();
  667. if (typeof result.files == "undefined") $("#findPut .searchResult").html(t("Not found!"));
  668. if (result.count == 0) $("#findPut .searchResult").html(t("Not found!"));
  669. var $template = $("<div class='searchResultHeader column2'>\
  670. <div class='searchresultAction'>\
  671. <input type='checkbox' value='' class='headerCheckbox' /> \
  672. <span>Select all</span>\
  673. </div>\
  674. <div class='right searchResultData'>\
  675. <i class='icon-docs'></i> <span class='numFile'>"+result.count+"</span>\
  676. <i class='icon-hourglass-3'></i> "+result.executionTime+" ms\
  677. </div>\
  678. </div>");
  679. $template.find(".headerCheckbox").on("input", function(e) {
  680. search.checkAll.call(search, $(this));
  681. });
  682. $("#findPut .searchResult").prepend($template);
  683. for (var file in result.files) {
  684. //var $lineFile = $("<div class='resultContext' data-id="+file+"><h2><i class='icon-doc'></i>"+file+" <span class='contextCount'>"+result.files[file].length+"</span></h2><ul></ul></div>");
  685. var $lineFile = $("<div class='resultContext' ><h2><i class='icon-doc'></i>"+file+" <span class='contextCount'>"+result.files[file].length+"</span></h2><ul></ul></div>");
  686. $lineFile.data("id", file);
  687. for(var i in result.files[file]) {
  688. var currentLine = result.files[file][i];
  689. var foundStr = currentLine.fullString.replaces(keyword, "<span class='highlight'>"+keyword+"</span>", !caseSensitiveMode);
  690. var refference = "";
  691. //console.log(currentLine);
  692. try {
  693. var thisFileRef = trans.project.files[file].data[currentLine.row];
  694. refference = thisFileRef[targetCol];
  695. }
  696. catch (err) {
  697. // do nothing
  698. }
  699. var lineTemplate = $("<li class='resultItem' title='click to go' data-row='"+currentLine.row+"' data-col='"+currentLine.col+"'>"+
  700. "<div class='texts'>"+
  701. "<h1>"+foundStr+"</h1>"+
  702. "<h1 class='refference' title='refference'>"+refference+"</h1>"+
  703. "</div>"+
  704. `<div class='resultInfo'><span class='findItemSelectorWrapper'><input type='checkbox' data-row='${currentLine.row}' data-col='${currentLine.col}' class='findItemSelector' value='' /></span><span class='rowLabel' title='row'>${currentLine.row}</span><span class='colLabel' title='column'>${currentLine.col}</span></div></li>`);
  705. lineTemplate.data("row", currentLine.row);
  706. lineTemplate.data("col", currentLine.col);
  707. lineTemplate.data("context", file);
  708. lineTemplate.on("click", function(e) {
  709. if ($(e.target).is("input[type=checkbox]")) {
  710. return;
  711. }
  712. trans.goTo($(this).data("row"), $(this).data("col"), $(this).data("context"));
  713. });
  714. lineTemplate.find(".findItemSelector").on("change", function() {
  715. search.find = search.find || {};
  716. if ($(this).prop("checked") == true) {
  717. search.find.$lastCheckedFile = $(this);
  718. } else {
  719. search.find.$lastCheckedFile = undefined;
  720. }
  721. });
  722. lineTemplate.find(".findItemSelector").on("mousedown", function(e) {
  723. search.find = search.find || {};
  724. if (!search.find.$lastCheckedFile) return false;
  725. if (e.shiftKey) {
  726. console.log("The SHIFT key was pressed!");
  727. var $checkBoxes = $(this).closest(".actionResult").find(".findItemSelector");
  728. var lastIndex = $checkBoxes.index(search.find.$lastCheckedFile);
  729. var thisIndex = $checkBoxes.index(this);
  730. var chckFrom;
  731. var chckTo;
  732. if (lastIndex < thisIndex) {
  733. chckFrom = lastIndex;
  734. chckTo = thisIndex;
  735. } else {
  736. chckFrom = thisIndex;
  737. chckTo = lastIndex;
  738. }
  739. console.log("check from index "+chckFrom+" to "+chckTo);
  740. for (let i=chckFrom; i<chckTo; i++) {
  741. $checkBoxes.eq(i).prop("checked", true).trigger("change");
  742. }
  743. }
  744. });
  745. search.drawTags(lineTemplate, file, currentLine.row);
  746. $lineFile.find("ul").append(lineTemplate);
  747. }
  748. $("#findPut .searchResult").append($lineFile);
  749. }
  750. }
  751. search.drawFileSelector = function() {
  752. if (typeof trans.project == 'undefined') return false;
  753. var project = trans.project;
  754. for (var file in project.files) {
  755. var template = $("<label class='selectable'><input type='checkbox' class='filename' value='"+file+"' /><span>"+file+"</span></label>");
  756. template.attr("title", file)
  757. $(".fileSelector").append(template);
  758. }
  759. search.initFileSelectorDragSelect();
  760. }
  761. search.toggleFileList = function(stat) {
  762. if (typeof stat == 'undefined') {
  763. stat = !$(".toggleFileSelector").hasClass("opened");
  764. }
  765. if (!stat) {
  766. $(".fileSelector").addClass("hidden");
  767. $(".toggleFileSelector").removeClass("opened");
  768. } else {
  769. $(".fileSelector").removeClass("hidden");
  770. $(".toggleFileSelector").addClass("opened");
  771. }
  772. return stat;
  773. }
  774. // ======================================================================
  775. // context menu handler
  776. // ======================================================================
  777. search.selectAll = function($actionResult) {
  778. //select all by given actionResult
  779. $actionResult = $actionResult||$(".ui-tabs-panel[aria-hidden=false] .actionResult");
  780. var $headerCheckbox = $actionResult.find(".headerCheckbox");
  781. $headerCheckbox.prop("checked", true);
  782. $headerCheckbox.trigger("input");
  783. //search.checkAll($actionResult.find(".headerCheckbox"));
  784. }
  785. search.unSelectAll = function($actionResult) {
  786. //select all by given actionResult
  787. $actionResult = $actionResult||$(".ui-tabs-panel[aria-hidden=false] .actionResult");
  788. var $headerCheckbox = $actionResult.find(".headerCheckbox");
  789. $headerCheckbox.prop("checked", false);
  790. $headerCheckbox.trigger("input");
  791. //search.checkAll($actionResult.find(".headerCheckbox"));
  792. }
  793. search.clearTranslationOnSelected = function($actionResult) {
  794. $actionResult = $actionResult||$(".ui-tabs-panel[aria-hidden=false] .actionResult");
  795. var $lines = $actionResult.find(".findItemSelector:checked");
  796. $lines.each(function() {
  797. var $resultItem = $(this).closest(".resultItem");
  798. var $resultContext = $(this).closest(".resultContext");
  799. var fileId = $resultContext.data("id");
  800. var row = $resultItem.attr("data-row");
  801. try {
  802. var thisRow = trans.project.files[fileId].data[row];
  803. trans.project.files[fileId].data[row] = thisRow.fill("", 1);
  804. } catch (e) {
  805. //do nothing
  806. }
  807. //search.appendTags($resultContext.data("id"), $resultItem.attr("data-row"), tags);
  808. })
  809. trans.grid.render();
  810. }
  811. search.removeSelectedElement = function($actionResult) {
  812. $actionResult = $actionResult||$(".ui-tabs-panel[aria-hidden=false] .actionResult");
  813. var $files = $actionResult.find(".resultContext");
  814. $files.each(function() {
  815. var $thisFile = $(this);
  816. var $thisLines = $thisFile.find(".findItemSelector:checked");
  817. if ($thisLines.length < 1) return;
  818. $thisLines.each(function() {
  819. $(this).closest("li").remove();
  820. })
  821. if($thisFile.find("li.resultItem").length < 1) $thisFile.remove();
  822. })
  823. $actionResult.find(".numFile").text( $actionResult.find("li.resultItem").length)
  824. }
  825. search.deleteSelected = function($actionResult) {
  826. // should make the row, col & file id unique
  827. $actionResult = $actionResult||$(".ui-tabs-panel[aria-hidden=false] .actionResult");
  828. var $files = $actionResult.find(".resultContext");
  829. for (var i=0; i<$files.length; i++) {
  830. var $thisFile = $files.eq(i);
  831. var $thisLine = $thisFile.find(".findItemSelector:checked");
  832. if ($thisLine.length < 1) continue;
  833. var fileId = $thisFile.data("id");
  834. var rows = [];
  835. for (var x=0; x<$thisLine.length; x++) {
  836. rows.push($thisLine.eq(x).data("row"));
  837. }
  838. console.log(`trans.removeRow()`, fileId, rows);
  839. trans.removeRow(fileId, rows)
  840. }
  841. this.removeSelectedElement($actionResult);
  842. trans.grid.render();
  843. }
  844. search.openAutomationEditor = async function() {
  845. var options = {
  846. workspace : "foundCells",
  847. foundCells : search.getSelectedResult()
  848. }
  849. ui.openAutomationEditor("codeEditor_foundCells", options);
  850. }
  851. search.automationMenu = function() {
  852. console.log("Creating automation menu");
  853. var subMenu = new nw.Menu();
  854. const configPath = "codeEditor/foundCells"
  855. var menuConfig = sys.getConfig(configPath);
  856. if (!menuConfig) {
  857. sys.setConfig(configPath, {quickLaunch:[]});
  858. menuConfig = sys.getConfig(configPath);
  859. }
  860. menuConfig["quickLaunch"] = menuConfig["quickLaunch"] || [];
  861. for (var i=0; i<menuConfig["quickLaunch"].length; i++) {
  862. (()=>{
  863. var filePath = menuConfig["quickLaunch"][i];
  864. var filename = common.getFilename(filePath);
  865. subMenu.append(new nw.MenuItem({
  866. label: filename,
  867. type: "normal",
  868. click: function(){
  869. const searchResult = search.getSelectedResult();
  870. var conf = confirm(t("Are you sure want to execute the following script?")+"\n"+filename+"\n"+
  871. t("For ")+searchResult.length+t(" selected item(s)?")
  872. );
  873. if (!conf) return;
  874. trans.runCustomScript("foundCells", filePath, {
  875. foundCells: searchResult
  876. });
  877. }
  878. }));
  879. })()
  880. }
  881. return subMenu;
  882. }
  883. search.searchResultContextMenu = function() {
  884. console.log("trans.fileSelectorContextMenuInit");
  885. if (this.searchResultContextMenuIsInitialized) return false;
  886. this.menu = new nw.Menu();
  887. // Add some items with label
  888. this.menu.append(new nw.MenuItem({
  889. label: t(' Select all'),
  890. type: "normal",
  891. click: function() {
  892. search.selectAll();
  893. }
  894. }));
  895. this.menu.append(new nw.MenuItem({
  896. label: t(' Clear selection'),
  897. type: "normal",
  898. click: function() {
  899. search.unSelectAll();
  900. }
  901. }));
  902. this.menu.append(new nw.MenuItem({
  903. type: 'separator'
  904. }));
  905. var tagging = new nw.Menu();
  906. tagging.append(new nw.MenuItem({
  907. label: t(' Set Red tag'),
  908. type: "normal",
  909. icon: "www/img/red.png",
  910. click: function() {
  911. search.appendTagsOnSelected("red");
  912. }
  913. }));
  914. tagging.append(new nw.MenuItem({
  915. label: t(' Set Yellow tag'),
  916. type: "normal",
  917. icon: "www/img/yellow.png",
  918. click: function() {
  919. search.appendTagsOnSelected("yellow");
  920. }
  921. }));
  922. tagging.append(new nw.MenuItem({
  923. label: t(' Set Green tag'),
  924. type: "normal",
  925. icon: "www/img/green.png",
  926. click: function() {
  927. search.appendTagsOnSelected("green");
  928. }
  929. }));
  930. tagging.append(new nw.MenuItem({
  931. label: t(' Set Blue tag'),
  932. type: "normal",
  933. icon: "www/img/blue.png",
  934. click: function() {
  935. search.appendTagsOnSelected("blue");
  936. }
  937. }));
  938. tagging.append(new nw.MenuItem({
  939. label: t(' Set Gold tag'),
  940. type: "normal",
  941. icon: "www/img/gold.png",
  942. click: function() {
  943. search.appendTagsOnSelected("gold");
  944. }
  945. }));
  946. tagging.append(new nw.MenuItem({
  947. label: t(' More tags...'),
  948. type: "normal",
  949. click: function() {
  950. search.openTagMenu();
  951. }
  952. }));
  953. tagging.append(new nw.MenuItem({
  954. type: 'separator'
  955. }));
  956. tagging.append(new nw.MenuItem({
  957. label: t(' Clear tags'),
  958. type: "normal",
  959. click: function() {
  960. search.clearTagsOnSelected();
  961. }
  962. }));
  963. tagging.append(new nw.MenuItem({
  964. type: 'separator'
  965. }));
  966. tagging.append(new nw.MenuItem({
  967. label: t(' Create Automation'),
  968. type: "normal",
  969. click: function() {
  970. search.openAutomationEditor();
  971. }
  972. }));
  973. tagging.append(new nw.MenuItem({
  974. label: t(' Run Automation'),
  975. type: "normal",
  976. submenu: search.automationMenu()
  977. }));
  978. tagging.append(new nw.MenuItem({
  979. label: t(' Clear Automation'),
  980. type: "normal",
  981. click: function() {
  982. var conf = confirm(t("Are you sure want to clear all quick launch scripts?"));
  983. if (!conf) return;
  984. sys.setConfig("codeEditor/foundCells", {quickLaunch:[]});
  985. sys.saveConfig();
  986. }
  987. }));
  988. tagging.append(new nw.MenuItem({
  989. type: 'separator'
  990. }));
  991. tagging.append(new nw.MenuItem({
  992. label: t(' Clear translation'),
  993. type: "normal",
  994. icon: "www/img/brush_icon.png",
  995. click: function() {
  996. var conf = confirm(t("Do you want to clear translations of the selected items?"));
  997. if (!conf) return;
  998. search.clearTranslationOnSelected();
  999. }
  1000. }));
  1001. tagging.append(new nw.MenuItem({
  1002. label: t(' Delete rows'),
  1003. type: "normal",
  1004. icon: "www/img/trash_icon.png",
  1005. click: function() {
  1006. var conf = confirm(t("Do you want to remove selected rows?\nYou can not undo this action!"));
  1007. if (!conf) return;
  1008. search.deleteSelected();
  1009. }
  1010. }));
  1011. /*
  1012. var withSelection = new nw.Menu();
  1013. withSelection.append(new nw.MenuItem({
  1014. label: 'Tagging',
  1015. submenu: tagging
  1016. }))
  1017. */
  1018. this.menu.append(new nw.MenuItem({
  1019. label: t(' With selection ...'),
  1020. icon: "www/img/checkmark.png",
  1021. submenu: tagging
  1022. }));
  1023. var that = this;
  1024. $(document.body).on("contextmenu", ".actionResult", function(ev) {
  1025. ev.preventDefault();
  1026. // Popup the native context menu at place you click
  1027. //console.log(ev);
  1028. console.log(ev.originalEvent);
  1029. that.menu.popup(parseInt(ev.originalEvent.x), parseInt(ev.originalEvent.y));
  1030. return false;
  1031. })
  1032. /*
  1033. document.body.addEventListener('contextmenu', function(ev) {
  1034. // Prevent showing default context menu
  1035. //console.log(ev);
  1036. if ($(ev.target).is(".actionResult") == false) return false;
  1037. ev.preventDefault();
  1038. // Popup the native context menu at place you click
  1039. that.menu.popup(ev.x, ev.y);
  1040. return false;
  1041. }, false);
  1042. */
  1043. this.searchResultContextMenuIsInitialized = true;
  1044. }
  1045. search.optionsMenu = function(x, y) {
  1046. console.log("search.optionsMenu");
  1047. var uncheckBlurMenu = () => {
  1048. for (var id in this.menuOpacityItem) {
  1049. if (Boolean(this.menuOpacityItem[id]) == false) continue;
  1050. this.menuOpacityItem[id].checked = false;
  1051. }
  1052. }
  1053. this.menuOptions = new nw.Menu();
  1054. // Add some items with label
  1055. this.menuAlwaysOnTop = new nw.MenuItem({
  1056. label: t('Always on top'),
  1057. type: "checkbox",
  1058. checked: win.isAlwaysOnTop,
  1059. click: function(){
  1060. var currentState = win.isAlwaysOnTop;
  1061. win.setAlwaysOnTop(!currentState);
  1062. this.checked = !currentState;
  1063. search.setConfig('alwaysOnTop', !currentState);
  1064. }
  1065. })
  1066. this.menuOptions.append(this.menuAlwaysOnTop);
  1067. //this.menuOptions.append(new nw.MenuItem({ type: 'separator' }));
  1068. var opacity = new nw.Menu();
  1069. this.menuOpacityItem = {};
  1070. for (let i=10; i>0; i--) {
  1071. void function() {
  1072. var z = i;
  1073. var percent = z*10;
  1074. var current = search.blurOpacity*100;
  1075. var isChecked = false;
  1076. if (current == percent) isChecked = true;
  1077. var thisMenu = new nw.MenuItem({
  1078. label: percent+'%',
  1079. type: "checkbox",
  1080. checked: isChecked,
  1081. click: function(){
  1082. uncheckBlurMenu();
  1083. this.checked = true;
  1084. search.blurOpacity = z/10;
  1085. search.setConfig('blurOpacity', z/10);
  1086. }
  1087. });
  1088. search.menuOpacityItem[percent] = thisMenu;
  1089. opacity.append(thisMenu);
  1090. }()
  1091. }
  1092. opacity.append(new nw.MenuItem({ type: 'separator' }));
  1093. var isChecked = false;
  1094. if (search.blurOpacity == 0.6) isChecked = true;
  1095. this.menuOpacityItem['default'] = new nw.MenuItem({
  1096. label: t('Default'),
  1097. type: "checkbox",
  1098. checked: isChecked,
  1099. click: function(){
  1100. console.log(this, arguments)
  1101. uncheckBlurMenu();
  1102. this.checked = true;
  1103. search.blurOpacity = 0.6;
  1104. search.setConfig('blurOpacity', 0.6);
  1105. }
  1106. })
  1107. opacity.append(this.menuOpacityItem['default']);
  1108. /*
  1109. var withSelection = new nw.Menu();
  1110. withSelection.append(new nw.MenuItem({
  1111. label: 'Tagging',
  1112. submenu: tagging
  1113. }))
  1114. */
  1115. this.menuOptions.append(new nw.MenuItem({
  1116. label: t('Blur opacity'),
  1117. submenu: opacity
  1118. }));
  1119. var that = this;
  1120. if (this.optionsMenuIsInitialized) return false;
  1121. $(".application-menu-button").on("click", function(ev) {
  1122. ev.preventDefault();
  1123. // Popup the native context menu at place you click
  1124. var thisOffset = $(this).offset();
  1125. //that.menu.popup(ev.originalEvent.x, ev.originalEvent.y);
  1126. that.menuOptions.popup(parseInt(thisOffset.left) - 80, 32);
  1127. return false;
  1128. })
  1129. this.optionsMenuIsInitialized = true;
  1130. }
  1131. search.getBlurOpacity = function() {
  1132. return this.blurOpacity;
  1133. }
  1134. search.initialize = function() {
  1135. this.appMenu = new nw.Menu();
  1136. this.appMenu.append(new nw.MenuItem({
  1137. label: t('Close'),
  1138. type: "normal",
  1139. click: function() {
  1140. }
  1141. }));
  1142. var that = this;
  1143. $(document.body).on("contextmenu", ".findWrapper", function(ev) {
  1144. ev.preventDefault();
  1145. // Popup the native context menu at place you click
  1146. //console.log(ev);
  1147. that.appMenu.popup(parseInt(ev.originalEvent.x), parseInt(ev.originalEvent.y));
  1148. return false;
  1149. })
  1150. this.optionsMenu();
  1151. this.loadKeywords();
  1152. }
  1153. // =======================================================
  1154. // EVENTS
  1155. // =======================================================
  1156. $(document).ready(function() {
  1157. search.searchResultContextMenu();
  1158. $(document).on('keydown', function(e) {
  1159. var keyCode = e.keyCode || e.which;
  1160. switch (keyCode) {
  1161. case 13 : //Enter
  1162. if (e.altKey || e.shiftKey) break;
  1163. e.preventDefault();
  1164. console.log("Searching");
  1165. if ($("div[aria-hidden=false]").attr("id") == "find") {
  1166. search.sendCommandFind();
  1167. } else if ($("div[aria-hidden=false]").attr("id") == "replace"){
  1168. search.sendCommandReplace();
  1169. } else {
  1170. search.sendCommandPut();
  1171. }
  1172. //$(".button-about").trigger("click");
  1173. break;
  1174. }
  1175. });
  1176. // INITIALIZING TAB
  1177. var type = window.location.hash.substr(1);
  1178. var mode = 0;
  1179. if (type == "replace") mode = 1;
  1180. console.log("tab index : "+mode);
  1181. $("#tabs").tabs({
  1182. active: mode,
  1183. activate: function(e, thisUi) {
  1184. console.log(thisUi);
  1185. if (thisUi.newPanel.attr("id") == 'findPut') {
  1186. $("#findPut .targetSelector").empty();
  1187. ui.generateColSelector({
  1188. skipFirstCol:true
  1189. }).appendTo($("#findPut .targetSelector"));
  1190. }
  1191. }
  1192. });
  1193. if (mode == 0) {
  1194. $("#fieldFind").focus();
  1195. } else {
  1196. $("#fieldReplaceFind").focus();
  1197. }
  1198. $(".toggleFileSelector").on("click", function(e) {
  1199. var $thisTab = $(this).closest(".ui-tabs-panel");
  1200. $(this).toggleClass("opened");
  1201. if ($(this).hasClass("opened")) {
  1202. $thisTab.find(".fileSelector").removeClass("hidden");
  1203. } else {
  1204. $thisTab.find(".fileSelector").addClass("hidden");
  1205. }
  1206. });
  1207. $(".selectAllFile").on("change", function(e) {
  1208. var $thisTab = $(this).closest(".ui-tabs-panel");
  1209. if ($(this).prop("checked")) {
  1210. $thisTab.find(".fileSelector").addClass("hidden");
  1211. $thisTab.find(".toggleFileSelector").removeClass("opened");
  1212. $thisTab.find(".fileSelector .filename").each(function() {
  1213. //console.log($(this));
  1214. $(this).prop("disabled", true);
  1215. });
  1216. } else {
  1217. $thisTab.find(".fileSelector").removeClass("hidden");
  1218. $thisTab.find(".toggleFileSelector").addClass("opened");
  1219. $thisTab.find(".fileSelector .filename").each(function() {
  1220. $(this).prop("disabled", false);
  1221. });
  1222. }
  1223. });
  1224. $(".application-bar .application-close-button").on("click", function(e) {
  1225. win.close();
  1226. })
  1227. $("#replaceIsRegexp").on("change", function() {
  1228. let $this = $(this);
  1229. if ($this.prop("checked")) {
  1230. $("#fieldReplaceFind").attr("placeholder", t("Type regex with the modifier"))
  1231. $("#fieldReplaceReplace").attr("placeholder", t("Use $n to replace a group. e.g. $1"))
  1232. } else {
  1233. $("#fieldReplaceFind").attr("placeholder", t("Find"))
  1234. $("#fieldReplaceReplace").attr("placeholder", t("Replace"))
  1235. }
  1236. })
  1237. search.initialize();
  1238. search.drawFileSelector();
  1239. $(".selectAllFile").trigger("change");
  1240. }); // document ready
  1241. win.on('blur', function() {
  1242. $("body").css("opacity", search.getBlurOpacity())
  1243. })
  1244. win.on('focus', function() {
  1245. $("body").css("opacity", "1")
  1246. })
  1247. win.on('close', function() {
  1248. // Hide the window to give user the feeling of closing immediately
  1249. this.hide();
  1250. window.localStorage.setItem("searchWindowPossition", JSON.stringify({
  1251. x: Math.round(win.x),
  1252. y: Math.round(win.y)
  1253. }));
  1254. // unregister this window on parent window.
  1255. if (typeof ui.windows.search !== 'undefined') ui.windows.search = undefined;
  1256. // After closing the new window, close the main window.
  1257. this.close(true);
  1258. });