mdict.html 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206
  1. <!DOCTYPE html>
  2. <html lang="en-us">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>mdict</title>
  6. <meta name="viewport" content="width=device-width, initial-scale=1">
  7. <link rel="stylesheet" type="text/css">
  8. <link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/gh/torappinfo/uweb/en/searchurl/mdict/selectize.default.css" media="screen">
  9. <style>
  10. #btnLookup {
  11. border: none;
  12. height: 36px;
  13. font-size: 12pt;
  14. font-weight: bold;
  15. vertical-align: top;
  16. border-radius: 3px;
  17. }
  18. #btnLookup:not([disabled]) {
  19. background: #1A4FDD;
  20. color: white;
  21. }
  22. #word + .selectize-control {
  23. display: inline-block;
  24. min-width: 18em;
  25. }
  26. </style>
  27. <script type="text/javascript" src="https://cdn.jsdelivr.net/npm/jquery@3.6.1/dist/jquery.min.js"></script>
  28. <script type="text/javascript" src="https://cdn.jsdelivr.net/gh/fengdh/mdict-js/selectize.min.js"></script>
  29. <script type="text/javascript" src="https://cdn.jsdelivr.net/gh/nodeca/pako/dist/pako_inflate.min.js"></script>
  30. <script type="text/javascript" src="https://cdn.jsdelivr.net/npm/bluebird@3.7.2/js/browser/bluebird.min.js"></script>
  31. <script type="text/javascript" src="https://cdn.jsdelivr.net/gh/torappinfo/uweb/en/searchurl/mdict/ripemd128.min.js"></script>
  32. <script type="text/javascript" src="https://cdn.jsdelivr.net/gh/torappinfo/uweb/en/searchurl/mdict/mdict-common.min.js"></script>
  33. <script type="text/javascript" src="https://cdn.jsdelivr.net/gh/torappinfo/uweb/en/searchurl/mdict/mdict-parser.min.js"></script>
  34. <script type="text/javascript" src="https://cdn.jsdelivr.net/gh/torappinfo/uweb/en/searchurl/mdict/mdict-renderer.min.js"></script>
  35. </head>
  36. <body>
  37. Choose a dictionary file (*.mdx + optional *.mdd): <input id="dictfile" type="file" multiple>
  38. <p>
  39. <input id="word" type="text" value="">
  40. <input id="btnLookup" type="button" value="look up" disabled="false">
  41. <div id="definition">
  42. </div>
  43. <script>
  44. //file:///...mdictstem?app=....html#word=
  45. var dictinput = document.getElementById('dictfile');
  46. var wordinput = document.getElementById('word');
  47. var btnLookup = document.getElementById('btnLookup');
  48. var definition = document.getElementById('definition');
  49. window.onhashchange = function() {
  50. let v = location.hash.substring(6);
  51. if(v.length>0){
  52. wordinput.value = v;
  53. //wordinput.dispatchEvent(new Event('change', {'bubbles': true}));
  54. btnLookup.click();
  55. }
  56. };
  57. {
  58. let v = decodeURIComponent(location.hash.substring(6));
  59. wordinput.value = v;
  60. }
  61. $(wordinput).selectize({maxItems: 1});
  62. function accept(e) {
  63. var fileList = $(e.target).prop('files');
  64. $(btnLookup).attr('disabled', true);
  65. if (fileList.length > 0) {
  66. $(btnLookup).addClass('stripes');
  67. $(wordinput).on('keyup', function(e) { e.which === 13
  68. && $(btnLookup).click(); });
  69. MParser(fileList).then(function(resources) {
  70. var mdict = MRenderer(resources);
  71. function doSearch(phrase, offset) {
  72. console.log(phrase + '');
  73. mdict.lookup(phrase, offset).then(function($content) {
  74. $(definition).empty().append($content.contents());
  75. console.log('--');
  76. });
  77. }
  78. $(btnLookup)
  79. .attr('disabled', false)
  80. .off('.#mdict')
  81. .on('click.#mdict', function() {
  82. doSearch($(wordinput).val());
  83. }).click();
  84. $(wordinput)[0].selectize.destroy();
  85. $(wordinput).selectize({
  86. plugins: ['restore_on_backspace'],
  87. maxItems: 1,
  88. maxOptions: 1 << 20,
  89. valueField: 'value',
  90. labelField: 'word',
  91. searchField: 'word',
  92. delimiter: '~~',
  93. loadThrottle: 10,
  94. create: function(v, callback) {
  95. return callback({word: v, value: v});
  96. },
  97. createOnBlur: true,
  98. closeAfterSelect: true,
  99. allowEmptyOption: true,
  100. score: function(search) {
  101. var score =
  102. this.getScoreFunction(search);
  103. return function(item) {
  104. return 1;
  105. };
  106. },
  107. load: function(query, callback) {
  108. var self = this;
  109. if (!query.length) {
  110. this.clearOptions();
  111. this.refreshOptions();
  112. return;
  113. };
  114. mdict.search({phrase: query, max: 5000}).then(function(list) {
  115. // console.log(list.join(', '));
  116. // TODO: filter candidate keyword starting with "_"
  117. list = list.map(function(v) {
  118. return {word: v, value: v.offset};
  119. });
  120. self.clearOptions();
  121. callback(list);
  122. });
  123. },
  124. onChange: function(value) {
  125. var item = this.options[value];
  126. if (item) {
  127. var value = item.word;
  128. doSearch(value, value.offset);
  129. $(wordinput).val(value);
  130. } else {
  131. $(definition).empty();
  132. }
  133. },
  134. });
  135. }).catch(err => alert(err)) ;
  136. } else {
  137. $(btnLookup).attr('disabled', false);
  138. }
  139. // jump to word with link started with "entry://"
  140. // TODO: have to ignore in-page jump
  141. $(definition).on('click', 'a', function(e) {
  142. var href = $(this).attr('href');
  143. if (href && href.substring(0, 8) === 'entry://') {
  144. var word = href.substring(8);
  145. // TODO: remove '#' to get jump target
  146. if (word.charAt(0) !== '#') {
  147. word = word.replace(/(^[/\\])|([/]$)/, '');
  148. $(wordinput).val(word);
  149. $(btnLookup).click();
  150. } else {
  151. var currentUrl = location.href;
  152. location.href = word; //Go to the target element.
  153. history.replaceState(null,null,currentUrl);
  154. }
  155. return false;
  156. }
  157. });
  158. }
  159. $(dictinput).on('change', accept);
  160. {
  161. let path = location.pathname;
  162. let iSlash = path.lastIndexOf('/');
  163. let filenames=path.substring(iSlash+1);
  164. {
  165. let iDot = filenames.indexOf('.');
  166. document.getElementsByTagName("link")[0].href =
  167. filenames.substring(0,iDot+1)+"css";
  168. }
  169. window.onload = function(){
  170. if(filenames.length>0){
  171. let clickurl = "i:5fdictinput.click():"+filenames;
  172. location.href=clickurl;
  173. var callbackTimer = setInterval(function() {
  174. let files = dictinput.files;
  175. if(files.length>0){
  176. if(!btnLookup.disabled){
  177. clearInterval(callbackTimer);
  178. return;
  179. }
  180. }else
  181. location.href=clickurl;
  182. dictinput.dispatchEvent(new Event('change', {'bubbles': true}));
  183. }, 100);
  184. }
  185. };
  186. }
  187. </script>
  188. </body>
  189. </html>