Guest User

Untitled

a guest
Jan 23rd, 2019
101
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 6.14 KB | None | 0 0
  1. <template lang='pug'>
  2. div.input-select(:class="{ quiet: quiet }")
  3. div.dummy(v-show="loading")
  4. select(:multiple="multiple" size=1 ref="original")
  5. template(v-for="optionOrGroup in options")
  6. template(v-if="!!optionOrGroup.options")
  7. optgroup(:label="optionOrGroup.label")
  8. option(
  9. v-for="option in optionOrGroup.options"
  10. :value="String(option.value)"
  11. ) {{ option.label }}
  12. template(v-else)
  13. option(
  14. :value="String(optionOrGroup.value)"
  15. ) {{ optionOrGroup.label }}
  16. </template>
  17.  
  18. <script>
  19. import $ from "jquery"
  20.  
  21. export default {
  22. props: {
  23. value: {
  24. type: [Array, String, Number],
  25. default: null
  26. },
  27. options: {
  28. type: Array,
  29. default: () => []
  30. },
  31. placeholder: {
  32. type: String,
  33. default: ' '
  34. },
  35. multiple: {
  36. type: Boolean,
  37. default: false
  38. },
  39. search: {
  40. type: Boolean,
  41. default: false
  42. },
  43. selectAll: {
  44. type: Boolean,
  45. default: false
  46. },
  47. displayCount: {
  48. type: Number,
  49. default: 4
  50. },
  51. quiet: {
  52. type: Boolean,
  53. default: false
  54. },
  55. readonly: {
  56. type: Boolean,
  57. default: false
  58. }
  59. },
  60. data () {
  61. return {
  62. loading: true
  63. }
  64. },
  65. computed: {
  66. optionsFlatten() {
  67. if (!this.options[0].options) return this.options
  68. return Array.prototype.concat.apply([], this.options.map(optGroup => optGroup.options))
  69. }
  70. },
  71. watch: {
  72. value() {
  73. this.reload(this.value)
  74. },
  75. options() {
  76. this.$nextTick(() => {
  77. this.$refs.original.sumo.reload()
  78. this.reload(this.value)
  79. })
  80. }
  81. },
  82. mounted() {
  83. // init
  84. $(this.$refs.original).SumoSelect({
  85. search: this.search,
  86. selectAll: this.selectAll,
  87. locale: ['OK', 'Cancel', this.$t("select_all")],
  88. searchText: '',
  89. noMatch: '...',
  90. placeholder: this.placeholder || this.$t("select"),
  91. captionFormatAllSelected: this.$t("all_selected"),
  92. captionFormat: this.$t("many_selected"),
  93. csvDispCount: this.displayCount
  94. })
  95. // event handler
  96. $(this.$refs.original).on('sumo:closing', (e) => {
  97. const valRaw = $(e.target).val()
  98. let val
  99. if (this.multiple) {
  100. val = valRaw.map(v => this.optionsFlatten.find(opt => String(opt.value) === v).value)
  101. } else {
  102. val = this.optionsFlatten.find(opt => String(opt.value) === valRaw).value
  103. }
  104. this.$emit('input', val)
  105. if (!_.isEqual(val, this.value)) this.$emit('change', val)
  106. // set placeholder
  107. if (!this.multiple) {
  108. if ([null, ""].includes(val)) {
  109. $(this.$el).find(".CaptionCont > span").addClass("unselected")
  110. $(this.$el).find(".CaptionCont > span.unselected").text(this.placeholder)
  111. } else {
  112. $(this.$el).find(".CaptionCont > span").removeClass("unselected")
  113. }
  114. }
  115. })
  116. // set initial value
  117. this.reload(this.value)
  118. this.loading = false
  119. },
  120. beforeDestroy() {
  121. this.$refs.original.sumo.unload()
  122. },
  123. methods: {
  124. reload(val) {
  125. // set selected item
  126. this.optionsFlatten.forEach(opt => this.$refs.original.sumo.unSelectItem(String(opt.value)))
  127. if (this.multiple && val) {
  128. val.forEach(v => this.$refs.original.sumo.selectItem(String(v)))
  129. } else {
  130. this.$refs.original.sumo.selectItem(String(val))
  131. }
  132. // set placeholder
  133. if (!this.multiple) {
  134. if ([null, ""].includes(val)) {
  135. $(this.$el).find(".CaptionCont > span").addClass("unselected")
  136. $(this.$el).find(".CaptionCont > span.unselected").text(this.placeholder)
  137. } else {
  138. $(this.$el).find(".CaptionCont > span").removeClass("unselected")
  139. }
  140. }
  141.  
  142. // set icon
  143. $('.SumoSelect > .CaptionCont > label > i').addClass("fas fa-caret-down")
  144.  
  145. // set disabled
  146. if (this.readonly) this.$refs.original.sumo.disable()
  147. }
  148. }
  149. }
  150. </script>
  151.  
  152. <style lang='scss' scoped>
  153. @import "~/assets/stylesheets/variables.scss";
  154.  
  155. .input-select {
  156. width: 100%;
  157. display: flex;
  158. }
  159.  
  160. select {
  161. -webkit-appearance: none;
  162. -moz-appearance: none;
  163. appearance: none;
  164. display: none;
  165. }
  166.  
  167. .dummy {
  168. box-sizing: border-box;
  169. flex-grow: 1;
  170. border: 1px solid $border-base;
  171. color: $bg-base;
  172. height: calc(1em + 11px);
  173. }
  174. </style>
  175.  
  176. <style lang='scss'>
  177. @import "~/assets/stylesheets/variables.scss";
  178. @import "sumoselect/sumoselect.css";
  179.  
  180. .SumoSelect {
  181. flex-grow: 1;
  182. max-width: 100%;
  183. }
  184.  
  185. .SumoSelect .SelectBox {
  186. padding: 4px 2px;
  187. }
  188.  
  189. .SumoSelect.disabled {
  190. cursor: default;
  191. opacity: 1;
  192. }
  193.  
  194. .SumoSelect.disabled > .CaptionCont {
  195. background-color: $bg-disable;
  196. }
  197.  
  198. .SumoSelect.open > .optWrapper {
  199. top: initial;
  200. border-radius: 0;
  201. border: 1px solid $border-base;
  202. }
  203.  
  204. .SumoSelect.open .search-txt {
  205. border-radius: 0;
  206. padding: 4px 2px;
  207. }
  208. .SumoSelect > .CaptionCont {
  209. border-radius: 0;
  210. border: 1px solid $border-base;
  211. min-height: initial;
  212. box-sizing: border-box;
  213. width: 100%;
  214. }
  215. .SumoSelect > .CaptionCont > span {
  216. }
  217.  
  218. .quiet .SumoSelect > .CaptionCont {
  219. border-color: transparent;
  220. }
  221. .quiet .SumoSelect > .CaptionCont > span {
  222. padding-right: 0;
  223. }
  224.  
  225. .SumoSelect > .CaptionCont > span.unselected {
  226. color: $fg-quiet;
  227. }
  228. .SumoSelect > .CaptionCont > span.placeholder {
  229. font-style: initial;
  230. color: $fg-quiet;
  231. }
  232.  
  233. .SumoSelect > .CaptionCont > label > i {
  234. background-image: none;
  235. font-size: 1.45em;
  236. text-align: right;
  237. color: $fg-quiet;
  238. }
  239.  
  240. .quiet .SumoSelect > .CaptionCont > label > i {
  241. display: none;
  242. }
  243.  
  244.  
  245. .SumoSelect:focus > .CaptionCont, .SumoSelect:hover > .CaptionCont, .SumoSelect.open > .CaptionCont {
  246. box-shadow: 0 0 2px $border-focus;
  247. border-color: $border-focus;
  248. }
  249.  
  250. .SumoSelect > .optWrapper > .options {
  251. max-height: 50vh;
  252. }
  253.  
  254. .SumoSelect > .optWrapper.multiple > .options li.opt.selected span i, .SumoSelect .select-all.selected > span i, .SumoSelect .select-all.partial > span i {
  255. background-color: $bg-selection;
  256. }
  257. .SumoSelect .select-all {
  258. border-radius: 0;
  259. padding-top: 3px;
  260. > label {
  261. margin-top: 3px;
  262. display: inline-block;
  263. }
  264. }
  265. </style>
  266.  
  267. <i18n>
  268. ja:
  269. select: 選択
  270. select_all: 全選択/解除
  271. all_selected: 全て
  272. many_selected: "{0}件を選択中"
  273. filter: "..."
  274. </i18n>
Add Comment
Please, Sign In to add comment