a zip code crypto-currency system good for red ONLY

select.js 19KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491
  1. var __extends = (this && this.__extends) || (function () {
  2. var extendStatics = Object.setPrototypeOf ||
  3. ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
  4. function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
  5. return function (d, b) {
  6. extendStatics(d, b);
  7. function __() { this.constructor = d; }
  8. d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
  9. };
  10. })();
  11. import { Component, ContentChildren, ElementRef, EventEmitter, HostListener, Input, Optional, Output, Renderer, ViewEncapsulation } from '@angular/core';
  12. import { NG_VALUE_ACCESSOR } from '@angular/forms';
  13. import { ActionSheet } from '../action-sheet/action-sheet';
  14. import { Alert } from '../alert/alert';
  15. import { Popover } from '../popover/popover';
  16. import { App } from '../app/app';
  17. import { Config } from '../../config/config';
  18. import { DeepLinker } from '../../navigation/deep-linker';
  19. import { Form } from '../../util/form';
  20. import { BaseInput } from '../../util/base-input';
  21. import { deepCopy, deepEqual, isCheckedProperty, isTrueProperty } from '../../util/util';
  22. import { Item } from '../item/item';
  23. import { Option } from '../option/option';
  24. import { SelectPopover } from './select-popover-component';
  25. /**
  26. * @name Select
  27. * @description
  28. * The `ion-select` component is similar to an HTML `<select>` element, however,
  29. * Ionic's select component makes it easier for users to sort through and select
  30. * the preferred option or options. When users tap the select component, a
  31. * dialog will appear with all of the options in a large, easy to select list
  32. * for users.
  33. *
  34. * The select component takes child `ion-option` components. If `ion-option` is not
  35. * given a `value` attribute then it will use its text as the value.
  36. *
  37. * If `ngModel` is bound to `ion-select`, the selected value will be based on the
  38. * bound value of the model. Otherwise, the `selected` attribute can be used on
  39. * `ion-option` components.
  40. *
  41. * ### Interfaces
  42. *
  43. * By default, the `ion-select` uses the {@link ../../alert/AlertController AlertController API}
  44. * to open up the overlay of options in an alert. The interface can be changed to use the
  45. * {@link ../../action-sheet/ActionSheetController ActionSheetController API} or
  46. * {@link ../../popover/PopoverController PopoverController API} by passing `action-sheet` or `popover`,
  47. * respectively, to the `interface` property. Read on to the other sections for the limitations
  48. * of the different interfaces.
  49. *
  50. * ### Single Value: Radio Buttons
  51. *
  52. * The standard `ion-select` component allows the user to select only one
  53. * option. When selecting only one option the alert interface presents users with
  54. * a radio button styled list of options. The action sheet interface can only be
  55. * used with a single value select. If the number of options exceed 6, it will
  56. * use the `alert` interface even if `action-sheet` is passed. The `ion-select`
  57. * component's value receives the value of the selected option's value.
  58. *
  59. * ```html
  60. * <ion-item>
  61. * <ion-label>Gender</ion-label>
  62. * <ion-select [(ngModel)]="gender">
  63. * <ion-option value="f">Female</ion-option>
  64. * <ion-option value="m">Male</ion-option>
  65. * </ion-select>
  66. * </ion-item>
  67. * ```
  68. *
  69. * ### Multiple Value: Checkboxes
  70. *
  71. * By adding the `multiple="true"` attribute to `ion-select`, users are able
  72. * to select multiple options. When multiple options can be selected, the alert
  73. * overlay presents users with a checkbox styled list of options. The
  74. * `ion-select multiple="true"` component's value receives an array of all the
  75. * selected option values. In the example below, because each option is not given
  76. * a `value`, then it'll use its text as the value instead.
  77. *
  78. * Note: the `action-sheet` and `popover` interfaces will not work with a multi-value select.
  79. *
  80. * ```html
  81. * <ion-item>
  82. * <ion-label>Toppings</ion-label>
  83. * <ion-select [(ngModel)]="toppings" multiple="true">
  84. * <ion-option>Bacon</ion-option>
  85. * <ion-option>Black Olives</ion-option>
  86. * <ion-option>Extra Cheese</ion-option>
  87. * <ion-option>Mushrooms</ion-option>
  88. * <ion-option>Pepperoni</ion-option>
  89. * <ion-option>Sausage</ion-option>
  90. * </ion-select>
  91. * </ion-item>
  92. * ```
  93. *
  94. * ### Select Buttons
  95. * By default, the two buttons read `Cancel` and `OK`. Each button's text
  96. * can be customized using the `cancelText` and `okText` attributes:
  97. *
  98. * ```html
  99. * <ion-select okText="Okay" cancelText="Dismiss">
  100. * ...
  101. * </ion-select>
  102. * ```
  103. *
  104. * The `action-sheet` and `popover` interfaces do not have an `OK` button, clicking
  105. * on any of the options will automatically close the overlay and select
  106. * that value.
  107. *
  108. * ### Select Options
  109. *
  110. * Since `ion-select` uses the `Alert`, `Action Sheet` and `Popover` interfaces, options can be
  111. * passed to these components through the `selectOptions` property. This can be used
  112. * to pass a custom title, subtitle, css class, and more. See the
  113. * {@link ../../alert/AlertController/#create AlertController API docs},
  114. * {@link ../../action-sheet/ActionSheetController/#create ActionSheetController API docs}, and
  115. * {@link ../../popover/PopoverController/#create PopoverController API docs}
  116. * for the properties that each interface accepts.
  117. *
  118. * For example, to change the `mode` of the overlay, pass it into `selectOptions`.
  119. *
  120. * ```html
  121. * <ion-select [selectOptions]="selectOptions">
  122. * ...
  123. * </ion-select>
  124. * ```
  125. *
  126. * ```ts
  127. * this.selectOptions = {
  128. * title: 'Pizza Toppings',
  129. * subTitle: 'Select your toppings',
  130. * mode: 'md'
  131. * };
  132. * ```
  133. *
  134. * ### Object Value References
  135. *
  136. * When using objects for select values, it is possible for the identities of these objects to
  137. * change if they are coming from a server or database, while the selected value's identity
  138. * remains the same. For example, this can occur when an existing record with the desired object value
  139. * is loaded into the select, but the newly retrieved select options now have different identities. This will
  140. * result in the select appearing to have no value at all, even though the original selection in still intact.
  141. *
  142. * Using the `compareWith` `Input` is the solution to this problem
  143. *
  144. * ```html
  145. * <ion-item>
  146. * <ion-label>Employee</ion-label>
  147. * <ion-select [(ngModel)]="employee" [compareWith]="compareFn">
  148. * <ion-option *ngFor="let employee of employees" [value]="employee">{{employee.name}}</ion-option>
  149. * </ion-select>
  150. * </ion-item>
  151. * ```
  152. *
  153. * ```ts
  154. * compareFn(e1: Employee, e2: Employee): boolean {
  155. * return e1 && e2 ? e1.id === e2.id : e1 === e2;
  156. * }
  157. * ```
  158. *
  159. * @demo /docs/demos/src/select/
  160. */
  161. var Select = (function (_super) {
  162. __extends(Select, _super);
  163. function Select(_app, form, config, elementRef, renderer, item, deepLinker) {
  164. var _this = _super.call(this, config, elementRef, renderer, 'select', [], form, item, null) || this;
  165. _this._app = _app;
  166. _this.config = config;
  167. _this.deepLinker = deepLinker;
  168. _this._multi = false;
  169. _this._texts = [];
  170. _this._text = '';
  171. _this._compareWith = isCheckedProperty;
  172. /**
  173. * @input {string} The text to display on the cancel button. Default: `Cancel`.
  174. */
  175. _this.cancelText = 'Cancel';
  176. /**
  177. * @input {string} The text to display on the ok button. Default: `OK`.
  178. */
  179. _this.okText = 'OK';
  180. /**
  181. * @input {any} Any additional options that the `alert` or `action-sheet` interface can take.
  182. * See the [AlertController API docs](../../alert/AlertController/#create) and the
  183. * [ActionSheetController API docs](../../action-sheet/ActionSheetController/#create) for the
  184. * create options for each interface.
  185. */
  186. _this.selectOptions = {};
  187. /**
  188. * @input {string} The interface the select should use: `action-sheet`, `popover` or `alert`. Default: `alert`.
  189. */
  190. _this.interface = '';
  191. /**
  192. * @input {string} The text to display instead of the selected option's value.
  193. */
  194. _this.selectedText = '';
  195. /**
  196. * @output {any} Emitted when the selection was cancelled.
  197. */
  198. _this.ionCancel = new EventEmitter();
  199. return _this;
  200. }
  201. Object.defineProperty(Select.prototype, "compareWith", {
  202. /**
  203. * @input {Function} The function that will be called to compare object values
  204. */
  205. set: function (fn) {
  206. if (typeof fn !== 'function') {
  207. throw new Error("compareWith must be a function, but received " + JSON.stringify(fn));
  208. }
  209. this._compareWith = fn;
  210. },
  211. enumerable: true,
  212. configurable: true
  213. });
  214. Select.prototype._click = function (ev) {
  215. ev.preventDefault();
  216. ev.stopPropagation();
  217. this.open(ev);
  218. };
  219. Select.prototype._keyup = function () {
  220. this.open();
  221. };
  222. /**
  223. * @hidden
  224. */
  225. Select.prototype.getValues = function () {
  226. var values = Array.isArray(this._value) ? this._value : [this._value];
  227. (void 0) /* assert */;
  228. return values;
  229. };
  230. /**
  231. * Open the select interface.
  232. */
  233. Select.prototype.open = function (ev) {
  234. var _this = this;
  235. if (this.isFocus() || this._disabled) {
  236. return;
  237. }
  238. (void 0) /* console.debug */;
  239. // the user may have assigned some options specifically for the alert
  240. var selectOptions = deepCopy(this.selectOptions);
  241. // make sure their buttons array is removed from the options
  242. // and we create a new array for the alert's two buttons
  243. selectOptions.buttons = [{
  244. text: this.cancelText,
  245. role: 'cancel',
  246. handler: function () {
  247. _this.ionCancel.emit(_this);
  248. }
  249. }];
  250. // if the selectOptions didn't provide a title then use the label's text
  251. if (!selectOptions.title && this._item) {
  252. selectOptions.title = this._item.getLabelText();
  253. }
  254. var options = this._options.toArray();
  255. if ((this.interface === 'action-sheet' || this.interface === 'popover') && this._multi) {
  256. console.warn('Interface cannot be "' + this.interface + '" with a multi-value select. Using the "alert" interface.');
  257. this.interface = 'alert';
  258. }
  259. if (this.interface === 'popover' && !ev) {
  260. console.warn('Interface cannot be "popover" without UIEvent.');
  261. this.interface = 'alert';
  262. }
  263. var overlay;
  264. if (this.interface === 'action-sheet') {
  265. selectOptions.buttons = selectOptions.buttons.concat(options.map(function (input) {
  266. return {
  267. role: (input.selected ? 'selected' : ''),
  268. text: input.text,
  269. handler: function () {
  270. _this.value = input.value;
  271. input.ionSelect.emit(input.value);
  272. }
  273. };
  274. }));
  275. var selectCssClass = 'select-action-sheet';
  276. // If the user passed a cssClass for the select, add it
  277. selectCssClass += selectOptions.cssClass ? ' ' + selectOptions.cssClass : '';
  278. selectOptions.cssClass = selectCssClass;
  279. overlay = new ActionSheet(this._app, selectOptions, this.config);
  280. }
  281. else if (this.interface === 'popover') {
  282. var popoverOptions = options.map(function (input) { return ({
  283. text: input.text,
  284. checked: input.selected,
  285. disabled: input.disabled,
  286. value: input.value,
  287. handler: function () {
  288. _this.value = input.value;
  289. input.ionSelect.emit(input.value);
  290. }
  291. }); });
  292. var popoverCssClass = 'select-popover';
  293. // If the user passed a cssClass for the select, add it
  294. popoverCssClass += selectOptions.cssClass ? ' ' + selectOptions.cssClass : '';
  295. overlay = new Popover(this._app, SelectPopover, {
  296. options: popoverOptions
  297. }, {
  298. cssClass: popoverCssClass
  299. }, this.config, this.deepLinker);
  300. // ev.target is readonly.
  301. // place popover regarding to ion-select instead of .button-inner
  302. Object.defineProperty(ev, 'target', { value: ev.currentTarget });
  303. selectOptions.ev = ev;
  304. }
  305. else {
  306. // default to use the alert interface
  307. this.interface = 'alert';
  308. // user cannot provide inputs from selectOptions
  309. // alert inputs must be created by ionic from ion-options
  310. selectOptions.inputs = this._options.map(function (input) {
  311. return {
  312. type: (_this._multi ? 'checkbox' : 'radio'),
  313. label: input.text,
  314. value: input.value,
  315. checked: input.selected,
  316. disabled: input.disabled,
  317. handler: function (selectedOption) {
  318. // Only emit the select event if it is being checked
  319. // For multi selects this won't emit when unchecking
  320. if (selectedOption.checked) {
  321. input.ionSelect.emit(input.value);
  322. }
  323. }
  324. };
  325. });
  326. var selectCssClass_1 = 'select-alert';
  327. // create the alert instance from our built up selectOptions
  328. overlay = new Alert(this._app, selectOptions, this.config);
  329. if (this._multi) {
  330. // use checkboxes
  331. selectCssClass_1 += ' multiple-select-alert';
  332. }
  333. else {
  334. // use radio buttons
  335. selectCssClass_1 += ' single-select-alert';
  336. }
  337. // If the user passed a cssClass for the select, add it
  338. selectCssClass_1 += selectOptions.cssClass ? ' ' + selectOptions.cssClass : '';
  339. overlay.setCssClass(selectCssClass_1);
  340. overlay.addButton({
  341. text: this.okText,
  342. handler: function (selectedValues) { return _this.value = selectedValues; }
  343. });
  344. }
  345. overlay.present(selectOptions);
  346. this._fireFocus();
  347. overlay.onDidDismiss(function () {
  348. _this._fireBlur();
  349. _this._overlay = undefined;
  350. });
  351. this._overlay = overlay;
  352. };
  353. /**
  354. * Close the select interface.
  355. */
  356. Select.prototype.close = function () {
  357. if (!this._overlay || !this.isFocus()) {
  358. return;
  359. }
  360. return this._overlay.dismiss();
  361. };
  362. Object.defineProperty(Select.prototype, "multiple", {
  363. /**
  364. * @input {boolean} If true, the element can accept multiple values.
  365. */
  366. get: function () {
  367. return this._multi;
  368. },
  369. set: function (val) {
  370. this._multi = isTrueProperty(val);
  371. },
  372. enumerable: true,
  373. configurable: true
  374. });
  375. Object.defineProperty(Select.prototype, "text", {
  376. /**
  377. * @hidden
  378. */
  379. get: function () {
  380. return (this._multi ? this._texts : this._texts.join());
  381. },
  382. enumerable: true,
  383. configurable: true
  384. });
  385. Object.defineProperty(Select.prototype, "options", {
  386. /**
  387. * @private
  388. */
  389. set: function (val) {
  390. this._options = val;
  391. var values = this.getValues();
  392. if (values.length === 0) {
  393. // there are no values set at this point
  394. // so check to see who should be selected
  395. // we use writeValue() because we don't want to update ngModel
  396. this.writeValue(val.filter(function (o) { return o.selected; }).map(function (o) { return o.value; }));
  397. }
  398. else {
  399. this._updateText();
  400. }
  401. },
  402. enumerable: true,
  403. configurable: true
  404. });
  405. Select.prototype._inputShouldChange = function (val) {
  406. return !deepEqual(this._value, val);
  407. };
  408. /**
  409. * TODO: REMOVE THIS
  410. * @hidden
  411. */
  412. Select.prototype._inputChangeEvent = function () {
  413. return this.value;
  414. };
  415. /**
  416. * @hidden
  417. */
  418. Select.prototype._updateText = function () {
  419. var _this = this;
  420. this._texts.length = 0;
  421. if (this._options) {
  422. this._options.forEach(function (option) {
  423. // check this option if the option's value is in the values array
  424. option.selected = _this.getValues().some(function (selectValue) {
  425. return _this._compareWith(selectValue, option.value);
  426. });
  427. if (option.selected) {
  428. _this._texts.push(option.text);
  429. }
  430. });
  431. }
  432. this._text = this._texts.join(', ');
  433. };
  434. /**
  435. * @hidden
  436. */
  437. Select.prototype._inputUpdated = function () {
  438. this._updateText();
  439. _super.prototype._inputUpdated.call(this);
  440. };
  441. Select.decorators = [
  442. { type: Component, args: [{
  443. selector: 'ion-select',
  444. template: '<div *ngIf="!_text" class="select-placeholder select-text">{{placeholder}}</div>' +
  445. '<div *ngIf="_text" class="select-text">{{selectedText || _text}}</div>' +
  446. '<div class="select-icon">' +
  447. '<div class="select-icon-inner"></div>' +
  448. '</div>' +
  449. '<button aria-haspopup="true" ' +
  450. 'type="button" ' +
  451. '[id]="id" ' +
  452. 'ion-button="item-cover" ' +
  453. '[attr.aria-labelledby]="_labelId" ' +
  454. '[attr.aria-disabled]="_disabled" ' +
  455. 'class="item-cover">' +
  456. '</button>',
  457. host: {
  458. '[class.select-disabled]': '_disabled'
  459. },
  460. providers: [{ provide: NG_VALUE_ACCESSOR, useExisting: Select, multi: true }],
  461. encapsulation: ViewEncapsulation.None,
  462. },] },
  463. ];
  464. /** @nocollapse */
  465. Select.ctorParameters = function () { return [
  466. { type: App, },
  467. { type: Form, },
  468. { type: Config, },
  469. { type: ElementRef, },
  470. { type: Renderer, },
  471. { type: Item, decorators: [{ type: Optional },] },
  472. { type: DeepLinker, },
  473. ]; };
  474. Select.propDecorators = {
  475. 'cancelText': [{ type: Input },],
  476. 'okText': [{ type: Input },],
  477. 'placeholder': [{ type: Input },],
  478. 'selectOptions': [{ type: Input },],
  479. 'interface': [{ type: Input },],
  480. 'selectedText': [{ type: Input },],
  481. 'compareWith': [{ type: Input },],
  482. 'ionCancel': [{ type: Output },],
  483. '_click': [{ type: HostListener, args: ['click', ['$event'],] },],
  484. '_keyup': [{ type: HostListener, args: ['keyup.space',] },],
  485. 'multiple': [{ type: Input },],
  486. 'options': [{ type: ContentChildren, args: [Option,] },],
  487. };
  488. return Select;
  489. }(BaseInput));
  490. export { Select };
  491. //# sourceMappingURL=select.js.map