find.js 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226
  1. /**
  2. * Explore plugin.
  3. */
  4. Draw.loadPlugin(function(ui)
  5. {
  6. var graph = ui.editor.graph;
  7. var lastSearch = null;
  8. var lastFound = null;
  9. var div = document.createElement('div');
  10. div.style.userSelect = 'none';
  11. div.style.overflow = 'hidden';
  12. div.style.padding = '10px';
  13. div.style.height = '100%';
  14. var searchInput = document.createElement('input');
  15. searchInput.setAttribute('placeholder', 'Find');
  16. searchInput.setAttribute('type', 'text');
  17. searchInput.style.marginTop = '4px';
  18. searchInput.style.width = '170px';
  19. searchInput.style.fontSize = '12px';
  20. searchInput.style.borderRadius = '4px';
  21. searchInput.style.padding = '6px';
  22. div.appendChild(searchInput);
  23. var tmp = document.createElement('div');
  24. function testMeta(re, cell)
  25. {
  26. if (typeof cell.value === 'object' && cell.value.attributes != null)
  27. {
  28. var attrs = cell.value.attributes;
  29. for (var i = 0; i < attrs.length; i++)
  30. {
  31. if (attrs[i].nodeName != 'label' && re.test(attrs[i].nodeValue.toLowerCase()))
  32. {
  33. return true;
  34. }
  35. }
  36. }
  37. return false;
  38. };
  39. function search()
  40. {
  41. var cells = graph.model.getDescendants(graph.model.getRoot());
  42. var search = searchInput.value.toLowerCase();
  43. var re = new RegExp(search);
  44. var firstMatch = null;
  45. if (lastSearch != search)
  46. {
  47. lastSearch = search;
  48. lastFound = null;
  49. }
  50. var active = lastFound == null;
  51. if (graph.isEnabled() && search.length > 0)
  52. {
  53. for (var i = 0; i < cells.length; i++)
  54. {
  55. var state = graph.view.getState(cells[i]);
  56. if (state != null && state.cell.value != null && (active || firstMatch == null) &&
  57. (graph.model.isVertex(state.cell) || graph.model.isEdge(state.cell)))
  58. {
  59. if (graph.isHtmlLabel(state.cell))
  60. {
  61. tmp.innerHTML = graph.getLabel(state.cell);
  62. label = mxUtils.extractTextWithWhitespace([tmp]);
  63. }
  64. else
  65. {
  66. label = graph.getLabel(state.cell);
  67. }
  68. label = mxUtils.trim(label.replace(/[\x00-\x1F\x7F-\x9F]|\s+/g, ' ')).toLowerCase();
  69. if (re.test(label) || testMeta(re, state.cell))
  70. {
  71. if (active)
  72. {
  73. firstMatch = state;
  74. break;
  75. }
  76. else if (firstMatch == null)
  77. {
  78. firstMatch = state;
  79. }
  80. }
  81. }
  82. active = active || state == lastFound;
  83. }
  84. }
  85. if (firstMatch != null)
  86. {
  87. lastFound = firstMatch;
  88. graph.setSelectionCell(lastFound.cell);
  89. graph.scrollCellToVisible(lastFound.cell);
  90. }
  91. else
  92. {
  93. graph.clearSelection();
  94. }
  95. return !graph.isEnabled() || search.length == 0 || firstMatch != null;
  96. };
  97. mxUtils.br(div);
  98. var resetBtn = mxUtils.button(mxResources.get('reset'), function()
  99. {
  100. searchInput.value = '';
  101. searchInput.style.backgroundColor = '';
  102. lastFound = null;
  103. lastSearch = null;
  104. searchInput.focus();
  105. });
  106. resetBtn.setAttribute('title', mxResources.get('reset'));
  107. resetBtn.style.marginTop = '8px';
  108. resetBtn.style.marginRight = '4px';
  109. resetBtn.style.backgroundColor = '#f5f5f5';
  110. resetBtn.style.backgroundImage = 'none';
  111. resetBtn.className = 'geBtn';
  112. div.appendChild(resetBtn);
  113. var btn = mxUtils.button('Find Again', function()
  114. {
  115. searchInput.style.backgroundColor = search() ? '' : '#ffcfcf';
  116. });
  117. btn.setAttribute('title', 'Find Again (Enter)');
  118. btn.style.marginTop = '8px';
  119. btn.style.backgroundColor = '#4d90fe';
  120. btn.style.backgroundImage = 'none';
  121. btn.className = 'geBtn gePrimaryBtn';
  122. div.appendChild(btn);
  123. mxEvent.addListener(searchInput, 'keyup', function(evt)
  124. {
  125. // Ctrl or Cmd keys
  126. if (evt.keyCode == 91 || evt.keyCode == 17)
  127. {
  128. // Workaround for lost focus on show
  129. mxEvent.consume(evt);
  130. }
  131. else if (evt.keyCode == 27)
  132. {
  133. findAction.funct();
  134. }
  135. else if (lastSearch != searchInput.value.toLowerCase() || evt.keyCode == 13)
  136. {
  137. searchInput.style.backgroundColor = search() ? '' : '#ffcfcf';
  138. }
  139. });
  140. var wnd = new mxWindow('Find', div, document.body.offsetWidth - 300, 110, 204, 116, true, true);
  141. wnd.destroyOnClose = false;
  142. wnd.setMaximizable(false);
  143. wnd.setResizable(false);
  144. wnd.setClosable(true);
  145. // Extends Extras menu
  146. mxResources.parse('find=Find');
  147. // Adds action
  148. ui.actions.addAction('find...', function()
  149. {
  150. wnd.setVisible(!wnd.isVisible());
  151. if (wnd.isVisible())
  152. {
  153. searchInput.focus();
  154. if (mxClient.IS_FF || document.documentMode >= 5 || mxClient.IS_QUIRKS)
  155. {
  156. searchInput.select();
  157. }
  158. else
  159. {
  160. document.execCommand('selectAll', false, null);
  161. }
  162. }
  163. else
  164. {
  165. graph.container.focus();
  166. }
  167. }, null, null, 'Ctrl+F');
  168. var findAction = ui.actions.get('find');
  169. findAction.setToggleAction(true);
  170. findAction.setSelectedCallback(function() { return wnd.isVisible(); });
  171. var menu = ui.menus.get('edit');
  172. var oldFunct = menu.funct;
  173. menu.funct = function(menu, parent)
  174. {
  175. oldFunct.apply(this, arguments);
  176. ui.menus.addMenuItems(menu, ['-', 'find'], parent);
  177. };
  178. ui.keyHandler.bindAction(70, true, 'find'); // Ctrl+F
  179. mxEvent.addListener(div, 'keydown', function(evt)
  180. {
  181. if (evt.keyCode == 70 && ui.keyHandler.isControlDown(evt) && !mxEvent.isShiftDown(evt))
  182. {
  183. findAction.funct();
  184. mxEvent.consume(evt);
  185. }
  186. });
  187. });