Shopping List v2.0
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

ListInput.svelte 2.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  1. <script>
  2. import { createEventDispatcher } from 'svelte';
  3. import { fade } from 'svelte/transition';
  4. export let words;
  5. let dispatch = createEventDispatcher();
  6. let inputEl;
  7. let hidden = true;
  8. let wordList = [];
  9. function updateWords() {
  10. wordList = [];
  11. for (let content in words) {
  12. if (content.includes(inputEl.value))
  13. wordList.push({ content, score: words[content] });
  14. }
  15. wordList.sort((a, b) => b.score - a.score);
  16. }
  17. function onBlur() {
  18. setTimeout(() => hidden = true, 50);
  19. }
  20. function onFocus() {
  21. updateWords();
  22. hidden = false;
  23. }
  24. function onSubmit(evt) {
  25. let val = inputEl.value.toLowerCase();
  26. if (!val)
  27. return;
  28. inputEl.value = "";
  29. dispatch("add", val);
  30. }
  31. function add(content) {
  32. inputEl.value = "";
  33. dispatch("add", content.toLowerCase());
  34. }
  35. function capitalize(str) {
  36. var first = str[0].toUpperCase();
  37. return first + str.substring(1);
  38. }
  39. </script>
  40. <style>
  41. .add {
  42. padding-top: 12px;
  43. }
  44. .add .content,
  45. .add .submit {
  46. box-sizing: content-box;
  47. -webkit-appearance: none;
  48. font-size: 16px;
  49. border: 1px solid #aaa;
  50. border-radius: 5px;
  51. background-color: #fff;
  52. height: 20px;
  53. padding: 6px;
  54. line-height: 0px;
  55. }
  56. .add .content {
  57. width: 78%;
  58. border-top-right-radius: 0px;
  59. border-bottom-right-radius: 0px;
  60. }
  61. .add .submit {
  62. width: 8%;
  63. background-color: #eee;
  64. border-top-left-radius: 0px;
  65. border-bottom-left-radius: 0px;
  66. }
  67. .add .submit:hover {
  68. background-color: #ddd;
  69. }
  70. .add .suggestions {
  71. z-index: 2;
  72. background: white;
  73. box-shadow: 0px 0px 10px 1px #ccc;
  74. position: absolute;
  75. width: 90%;
  76. margin: auto;
  77. left: 0px;
  78. right: 0px;
  79. margin-top: 15px;
  80. padding-top: 6px;
  81. padding-bottom: 6px;
  82. max-height: 70%;
  83. overflow-y: auto;
  84. overflow-x: hidden;
  85. }
  86. .add .suggestions .suggestion:last-child {
  87. border-bottom: none;
  88. }
  89. .add .suggestions .suggestion {
  90. padding: 12px;
  91. cursor: pointer;
  92. border-bottom: 1px solid #ccc;
  93. text-overflow: ellipsis;
  94. max-width: 100%;
  95. overflow: hidden;
  96. }
  97. </style>
  98. <form on:submit|preventDefault={onSubmit} class="add">
  99. <input
  100. class="content" name="content" autocomplete="off"
  101. on:focus={onFocus} on:blur={onBlur} on:keydown={() => window.setTimeout(updateWords, 10)} bind:this={inputEl}>
  102. <button class="submit" type="submit">+</button>
  103. {#if !hidden}
  104. <div transition:fade={{duration: 50}} class="suggestions">
  105. {#each wordList as word}
  106. <div class="suggestion" on:click={() => add(word.content)}>
  107. {capitalize(word.content)}
  108. </div>
  109. {/each}
  110. </div>
  111. {/if}
  112. </form>