index.js 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383
  1. import _extends from "@babel/runtime/helpers/esm/extends";
  2. // Utils
  3. import { createNamespace } from '../utils';
  4. import { preventDefault } from '../utils/dom/event';
  5. import { BORDER_UNSET_TOP_BOTTOM } from '../utils/constant';
  6. import { pickerProps, DEFAULT_ITEM_HEIGHT } from './shared';
  7. import { unitToPx } from '../utils/format/unit'; // Components
  8. import Loading from '../loading';
  9. import PickerColumn from './PickerColumn';
  10. var _createNamespace = createNamespace('picker'),
  11. createComponent = _createNamespace[0],
  12. bem = _createNamespace[1],
  13. t = _createNamespace[2];
  14. export default createComponent({
  15. props: _extends({}, pickerProps, {
  16. defaultIndex: {
  17. type: [Number, String],
  18. default: 0
  19. },
  20. columns: {
  21. type: Array,
  22. default: function _default() {
  23. return [];
  24. }
  25. },
  26. toolbarPosition: {
  27. type: String,
  28. default: 'top'
  29. },
  30. valueKey: {
  31. type: String,
  32. default: 'text'
  33. }
  34. }),
  35. data: function data() {
  36. return {
  37. children: [],
  38. formattedColumns: []
  39. };
  40. },
  41. computed: {
  42. itemPxHeight: function itemPxHeight() {
  43. return this.itemHeight ? unitToPx(this.itemHeight) : DEFAULT_ITEM_HEIGHT;
  44. },
  45. dataType: function dataType() {
  46. var columns = this.columns;
  47. var firstColumn = columns[0] || {};
  48. if (firstColumn.children) {
  49. return 'cascade';
  50. }
  51. if (firstColumn.values) {
  52. return 'object';
  53. }
  54. return 'text';
  55. }
  56. },
  57. watch: {
  58. columns: {
  59. handler: 'format',
  60. immediate: true
  61. }
  62. },
  63. methods: {
  64. format: function format() {
  65. var columns = this.columns,
  66. dataType = this.dataType;
  67. if (dataType === 'text') {
  68. this.formattedColumns = [{
  69. values: columns
  70. }];
  71. } else if (dataType === 'cascade') {
  72. this.formatCascade();
  73. } else {
  74. this.formattedColumns = columns;
  75. }
  76. },
  77. formatCascade: function formatCascade() {
  78. var formatted = [];
  79. var cursor = {
  80. children: this.columns
  81. };
  82. while (cursor && cursor.children) {
  83. var _cursor$defaultIndex;
  84. var _cursor = cursor,
  85. children = _cursor.children;
  86. var defaultIndex = (_cursor$defaultIndex = cursor.defaultIndex) != null ? _cursor$defaultIndex : +this.defaultIndex;
  87. while (children[defaultIndex] && children[defaultIndex].disabled) {
  88. if (defaultIndex < children.length - 1) {
  89. defaultIndex++;
  90. } else {
  91. defaultIndex = 0;
  92. break;
  93. }
  94. }
  95. formatted.push({
  96. values: cursor.children,
  97. className: cursor.className,
  98. defaultIndex: defaultIndex
  99. });
  100. cursor = children[defaultIndex];
  101. }
  102. this.formattedColumns = formatted;
  103. },
  104. emit: function emit(event) {
  105. var _this = this;
  106. if (this.dataType === 'text') {
  107. this.$emit(event, this.getColumnValue(0), this.getColumnIndex(0));
  108. } else {
  109. var values = this.getValues(); // compatible with old version of wrong parameters
  110. // should be removed in next major version
  111. // see: https://github.com/vant-ui/vant/issues/5905
  112. if (this.dataType === 'cascade') {
  113. values = values.map(function (item) {
  114. return item[_this.valueKey];
  115. });
  116. }
  117. this.$emit(event, values, this.getIndexes());
  118. }
  119. },
  120. onCascadeChange: function onCascadeChange(columnIndex) {
  121. var cursor = {
  122. children: this.columns
  123. };
  124. var indexes = this.getIndexes();
  125. for (var i = 0; i <= columnIndex; i++) {
  126. cursor = cursor.children[indexes[i]];
  127. }
  128. while (cursor && cursor.children) {
  129. columnIndex++;
  130. this.setColumnValues(columnIndex, cursor.children);
  131. cursor = cursor.children[cursor.defaultIndex || 0];
  132. }
  133. },
  134. onChange: function onChange(columnIndex) {
  135. var _this2 = this;
  136. if (this.dataType === 'cascade') {
  137. this.onCascadeChange(columnIndex);
  138. }
  139. if (this.dataType === 'text') {
  140. this.$emit('change', this, this.getColumnValue(0), this.getColumnIndex(0));
  141. } else {
  142. var values = this.getValues(); // compatible with old version of wrong parameters
  143. // should be removed in next major version
  144. // see: https://github.com/vant-ui/vant/issues/5905
  145. if (this.dataType === 'cascade') {
  146. values = values.map(function (item) {
  147. return item[_this2.valueKey];
  148. });
  149. }
  150. this.$emit('change', this, values, columnIndex);
  151. }
  152. },
  153. // get column instance by index
  154. getColumn: function getColumn(index) {
  155. return this.children[index];
  156. },
  157. // @exposed-api
  158. // get column value by index
  159. getColumnValue: function getColumnValue(index) {
  160. var column = this.getColumn(index);
  161. return column && column.getValue();
  162. },
  163. // @exposed-api
  164. // set column value by index
  165. setColumnValue: function setColumnValue(index, value) {
  166. var column = this.getColumn(index);
  167. if (column) {
  168. column.setValue(value);
  169. if (this.dataType === 'cascade') {
  170. this.onCascadeChange(index);
  171. }
  172. }
  173. },
  174. // @exposed-api
  175. // get column option index by column index
  176. getColumnIndex: function getColumnIndex(columnIndex) {
  177. return (this.getColumn(columnIndex) || {}).currentIndex;
  178. },
  179. // @exposed-api
  180. // set column option index by column index
  181. setColumnIndex: function setColumnIndex(columnIndex, optionIndex) {
  182. var column = this.getColumn(columnIndex);
  183. if (column) {
  184. column.setIndex(optionIndex);
  185. if (this.dataType === 'cascade') {
  186. this.onCascadeChange(columnIndex);
  187. }
  188. }
  189. },
  190. // @exposed-api
  191. // get options of column by index
  192. getColumnValues: function getColumnValues(index) {
  193. return (this.children[index] || {}).options;
  194. },
  195. // @exposed-api
  196. // set options of column by index
  197. setColumnValues: function setColumnValues(index, options) {
  198. var column = this.children[index];
  199. if (column) {
  200. column.setOptions(options);
  201. }
  202. },
  203. // @exposed-api
  204. // get values of all columns
  205. getValues: function getValues() {
  206. return this.children.map(function (child) {
  207. return child.getValue();
  208. });
  209. },
  210. // @exposed-api
  211. // set values of all columns
  212. setValues: function setValues(values) {
  213. var _this3 = this;
  214. values.forEach(function (value, index) {
  215. _this3.setColumnValue(index, value);
  216. });
  217. },
  218. // @exposed-api
  219. // get indexes of all columns
  220. getIndexes: function getIndexes() {
  221. return this.children.map(function (child) {
  222. return child.currentIndex;
  223. });
  224. },
  225. // @exposed-api
  226. // set indexes of all columns
  227. setIndexes: function setIndexes(indexes) {
  228. var _this4 = this;
  229. indexes.forEach(function (optionIndex, columnIndex) {
  230. _this4.setColumnIndex(columnIndex, optionIndex);
  231. });
  232. },
  233. // @exposed-api
  234. confirm: function confirm() {
  235. this.children.forEach(function (child) {
  236. return child.stopMomentum();
  237. });
  238. this.emit('confirm');
  239. },
  240. cancel: function cancel() {
  241. this.emit('cancel');
  242. },
  243. genTitle: function genTitle() {
  244. var h = this.$createElement;
  245. var titleSlot = this.slots('title');
  246. if (titleSlot) {
  247. return titleSlot;
  248. }
  249. if (this.title) {
  250. return h("div", {
  251. "class": ['van-ellipsis', bem('title')]
  252. }, [this.title]);
  253. }
  254. },
  255. genCancel: function genCancel() {
  256. var h = this.$createElement;
  257. return h("button", {
  258. "attrs": {
  259. "type": "button"
  260. },
  261. "class": bem('cancel'),
  262. "on": {
  263. "click": this.cancel
  264. }
  265. }, [this.slots('cancel') || this.cancelButtonText || t('cancel')]);
  266. },
  267. genConfirm: function genConfirm() {
  268. var h = this.$createElement;
  269. return h("button", {
  270. "attrs": {
  271. "type": "button"
  272. },
  273. "class": bem('confirm'),
  274. "on": {
  275. "click": this.confirm
  276. }
  277. }, [this.slots('confirm') || this.confirmButtonText || t('confirm')]);
  278. },
  279. genToolbar: function genToolbar() {
  280. var h = this.$createElement;
  281. if (this.showToolbar) {
  282. return h("div", {
  283. "class": bem('toolbar')
  284. }, [this.slots() || [this.genCancel(), this.genTitle(), this.genConfirm()]]);
  285. }
  286. },
  287. genColumns: function genColumns() {
  288. var h = this.$createElement;
  289. var itemPxHeight = this.itemPxHeight;
  290. var wrapHeight = itemPxHeight * this.visibleItemCount;
  291. var frameStyle = {
  292. height: itemPxHeight + "px"
  293. };
  294. var columnsStyle = {
  295. height: wrapHeight + "px"
  296. };
  297. var maskStyle = {
  298. backgroundSize: "100% " + (wrapHeight - itemPxHeight) / 2 + "px"
  299. };
  300. return h("div", {
  301. "class": bem('columns'),
  302. "style": columnsStyle,
  303. "on": {
  304. "touchmove": preventDefault
  305. }
  306. }, [this.genColumnItems(), h("div", {
  307. "class": bem('mask'),
  308. "style": maskStyle
  309. }), h("div", {
  310. "class": [BORDER_UNSET_TOP_BOTTOM, bem('frame')],
  311. "style": frameStyle
  312. })]);
  313. },
  314. genColumnItems: function genColumnItems() {
  315. var _this5 = this;
  316. var h = this.$createElement;
  317. return this.formattedColumns.map(function (item, columnIndex) {
  318. var _item$defaultIndex;
  319. return h(PickerColumn, {
  320. "attrs": {
  321. "readonly": _this5.readonly,
  322. "valueKey": _this5.valueKey,
  323. "allowHtml": _this5.allowHtml,
  324. "className": item.className,
  325. "itemHeight": _this5.itemPxHeight,
  326. "defaultIndex": (_item$defaultIndex = item.defaultIndex) != null ? _item$defaultIndex : +_this5.defaultIndex,
  327. "swipeDuration": _this5.swipeDuration,
  328. "visibleItemCount": _this5.visibleItemCount,
  329. "initialOptions": item.values
  330. },
  331. "scopedSlots": {
  332. option: _this5.$scopedSlots.option
  333. },
  334. "on": {
  335. "change": function change() {
  336. _this5.onChange(columnIndex);
  337. }
  338. }
  339. });
  340. });
  341. }
  342. },
  343. render: function render(h) {
  344. return h("div", {
  345. "class": bem()
  346. }, [this.toolbarPosition === 'top' ? this.genToolbar() : h(), this.loading ? h(Loading, {
  347. "class": bem('loading')
  348. }) : h(), this.slots('columns-top'), this.genColumns(), this.slots('columns-bottom'), this.toolbarPosition === 'bottom' ? this.genToolbar() : h()]);
  349. }
  350. });