text: "use strict";
  var __extends = (this && this.__extends) || function (d, b) {
      for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
      function __() { this.constructor = d; }
      d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
  };
  var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
      var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
      if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
      else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
      return c > 3 && r && Object.defineProperty(target, key, r), r;
  };
  var __metadata = (this && this.__metadata) || function (k, v) {
      if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
  };
  var core_1 = require('@angular/core');
  var platform_browser_1 = require('@angular/platform-browser');
  var animation_1 = require('../../animations/animation');
  var dom_1 = require('../../util/dom');
  var util_1 = require('../../util/util');
  var config_1 = require('../../config/config');
  var key_1 = require('../../util/key');
  var nav_params_1 = require('../nav/nav-params');
  var transition_1 = require('../../transitions/transition');
  var ui_event_manager_1 = require('../../util/ui-event-manager');
  var view_controller_1 = require('../nav/view-controller');
  /**
   * @name Picker
   * @description
   *
   */
  var Picker = (function (_super) {
      __extends(Picker, _super);
      function Picker(opts) {
          if (opts === void 0) { opts = {}; }
          opts.columns = opts.columns || [];
          opts.buttons = opts.buttons || [];
          opts.enableBackdropDismiss = util_1.isPresent(opts.enableBackdropDismiss) ? !!opts.enableBackdropDismiss : true;
          _super.call(this, PickerDisplayCmp, opts);
          this.isOverlay = true;
          this.ionChange = new core_1.EventEmitter();
          // by default, pickers should not fire lifecycle events of other views
          // for example, when an picker enters, the current active view should
          // not fire its lifecycle events because it's not conceptually leaving
          this.fireOtherLifecycles = false;
          this.usePortal = true;
      }
      /**
      * @private
      */
      Picker.prototype.getTransitionName = function (direction) {
          var key = (direction === 'back' ? 'pickerLeave' : 'pickerEnter');
          return this._nav && this._nav.config.get(key);
      };
      /**
       * @param {any} button Picker toolbar button
       */
      Picker.prototype.addButton = function (button) {
          this.data.buttons.push(button);
      };
      /**
       * @param {any} button Picker toolbar button
       */
      Picker.prototype.addColumn = function (column) {
          this.data.columns.push(column);
      };
      Picker.prototype.getColumns = function () {
          return this.data.columns;
      };
      Picker.prototype.refresh = function () {
          this.instance.refresh && this.instance.refresh();
      };
      /**
       * @param {string} cssClass CSS class name to add to the picker's outer wrapper.
       */
      Picker.prototype.setCssClass = function (cssClass) {
          this.data.cssClass = cssClass;
      };
      Picker.create = function (opts) {
          if (opts === void 0) { opts = {}; }
          return new Picker(opts);
      };
      __decorate([
          core_1.Output(), 
          __metadata('design:type', core_1.EventEmitter)
      ], Picker.prototype, "ionChange", void 0);
      return Picker;
  }(view_controller_1.ViewController));
  exports.Picker = Picker;
  /**
   * @private
   */
  var PickerColumnCmp = (function () {
      function PickerColumnCmp(config, elementRef, _sanitizer) {
          this.elementRef = elementRef;
          this._sanitizer = _sanitizer;
          this.y = 0;
          this.pos = [];
          this.startY = null;
          this.receivingEvents = false;
          this.events = new ui_event_manager_1.UIEventManager();
          this.ionChange = new core_1.EventEmitter();
          this.rotateFactor = config.getNumber('pickerRotateFactor', 0);
      }
      PickerColumnCmp.prototype.ngAfterViewInit = function () {
          var _this = this;
          // get the scrollable element within the column
          var colEle = this.colEle.nativeElement;
          this.colHeight = colEle.clientHeight;
          // get the height of one option
          this.optHeight = (colEle.firstElementChild ? colEle.firstElementChild.clientHeight : 0);
          // set the scroll position for the selected option
          this.setSelected(this.col.selectedIndex, 0);
          // Listening for pointer events
          this.events.pointerEventsRef(this.elementRef, function (ev) { return _this.pointerStart(ev); }, function (ev) { return _this.pointerMove(ev); }, function (ev) { return _this.pointerEnd(ev); });
      };
      PickerColumnCmp.prototype.ngOnDestroy = function () {
          this.events.unlistenAll();
      };
      PickerColumnCmp.prototype.pointerStart = function (ev) {
          void 0;
          // cancel any previous raf's that haven't fired yet
          dom_1.cancelRaf(this.rafId);
          // remember where the pointer started from`
          this.startY = dom_1.pointerCoord(ev).y;
          // reset everything
          this.receivingEvents = true;
          this.velocity = 0;
          this.pos.length = 0;
          this.pos.push(this.startY, Date.now());
          var minY = (this.col.options.length - 1);
          var maxY = 0;
          for (var i = 0; i < this.col.options.length; i++) {
              if (!this.col.options[i].disabled) {
                  minY = Math.min(minY, i);
                  maxY = Math.max(maxY, i);
              }
          }
          this.minY = (minY * this.optHeight * -1);
          this.maxY = (maxY * this.optHeight * -1);
          return true;
      };
      PickerColumnCmp.prototype.pointerMove = function (ev) {
          ev.preventDefault();
          ev.stopPropagation();
          if (this.startY === null) {
              return;
          }
          var currentY = dom_1.pointerCoord(ev).y;
          this.pos.push(currentY, Date.now());
          // update the scroll position relative to pointer start position
          var y = this.y + (currentY - this.startY);
          if (y > this.minY) {
              // scrolling up higher than scroll area
              y = Math.pow(y, 0.8);
              this.bounceFrom = y;
          }
          else if (y < this.maxY) {
              // scrolling down below scroll area
              y += Math.pow(this.maxY - y, 0.9);
              this.bounceFrom = y;
          }
          else {
              this.bounceFrom = 0;
          }
          this.update(y, 0, false, false);
      };
      PickerColumnCmp.prototype.pointerEnd = function (ev) {
          if (!this.receivingEvents) {
              return;
          }
          this.receivingEvents = false;
          this.velocity = 0;
          if (this.bounceFrom > 0) {
              // bounce back up
              this.update(this.minY, 100, true, true);
          }
          else if (this.bounceFrom < 0) {
              // bounce back down
              this.update(this.maxY, 100, true, true);
          }
          else if (this.startY !== null) {
              var endY = dom_1.pointerCoord(ev).y;
              void 0;
              this.pos.push(endY, Date.now());
              var endPos = (this.pos.length - 1);
              var startPos = endPos;
              var timeRange = (Date.now() - 100);
              // move pointer to position measured 100ms ago
              for (var i = endPos; i > 0 && this.pos[i] > timeRange; i -= 2) {
                  startPos = i;
              }
              if (startPos !== endPos) {
                  // compute relative movement between these two points
                  var timeOffset = (this.pos[endPos] - this.pos[startPos]);
                  var movedTop = (this.pos[startPos - 1] - this.pos[endPos - 1]);
                  // based on XXms compute the movement to apply for each render step
                  this.velocity = ((movedTop / timeOffset) * FRAME_MS);
              }
              if (Math.abs(endY - this.startY) > 3) {
                  ev.preventDefault();
                  ev.stopPropagation();
                  var y = this.y + (endY - this.startY);
                  this.update(y, 0, true, true);
              }
          }
          this.startY = null;
          this.decelerate();
      };
      PickerColumnCmp.prototype.decelerate = function () {
          var y = 0;
          dom_1.cancelRaf(this.rafId);
          if (isNaN(this.y) || !this.optHeight) {
              // fallback in case numbers get outta wack
              this.update(y, 0, true, true);
          }
          else if (Math.abs(this.velocity) > 0) {
              // still decelerating
              this.velocity *= DECELERATION_FRICTION;
              // do not let it go slower than a velocity of 1
              this.velocity = (this.velocity > 0 ? Math.max(this.velocity, 1) : Math.min(this.velocity, -1));
              y = Math.round(this.y - this.velocity);
              if (y > this.minY) {
                  // whoops, it's trying to scroll up farther than the options we have!
                  y = this.minY;
                  this.velocity = 0;
              }
              else if (y < this.maxY) {
                  // gahh, it's trying to scroll down farther than we can!
                  y = this.maxY;
                  this.velocity = 0;
              }
              void 0;
              var notLockedIn = (y % this.optHeight !== 0 || Math.abs(this.velocity) > 1);
              this.update(y, 0, true, !notLockedIn);
              if (notLockedIn) {
                  // isn't locked in yet, keep decelerating until it is
                  this.rafId = dom_1.raf(this.decelerate.bind(this));
              }
          }
          else if (this.y % this.optHeight !== 0) {
              // needs to still get locked into a position so options line up
              var currentPos = Math.abs(this.y % this.optHeight);
              // create a velocity in the direction it needs to scroll
              this.velocity = (currentPos > (this.optHeight / 2) ? 1 : -1);
              this.decelerate();
          }
      };
      PickerColumnCmp.prototype.optClick = function (ev, index) {
          if (!this.velocity) {
              ev.preventDefault();
              ev.stopPropagation();
              this.setSelected(index, 150);
          }
      };
      PickerColumnCmp.prototype.setSelected = function (selectedIndex, duration) {
          // if there is a selected index, then figure out it's y position
          // if there isn't a selected index, then just use the top y position
          var y = (selectedIndex > -1) ? ((selectedIndex * this.optHeight) * -1) : 0;
          dom_1.cancelRaf(this.rafId);
          this.velocity = 0;
          // so what y position we're at
          this.update(y, duration, true, true);
      };
      PickerColumnCmp.prototype.update = function (y, duration, saveY, emitChange) {
          // ensure we've got a good round number :)
          y = Math.round(y);
          this.col.selectedIndex = Math.max(Math.abs(Math.round(y / this.optHeight)), 0);
          for (var i = 0; i < this.col.options.length; i++) {
              var opt = this.col.options[i];
              var optTop = (i * this.optHeight);
              var optOffset = (optTop + y);
              var rotateX = (optOffset * this.rotateFactor);
              var translateX = 0;
              var translateY = 0;
              var translateZ = 0;
              if (this.rotateFactor !== 0) {
                  translateX = 0;
                  translateZ = 90;
                  if (rotateX > 90 || rotateX < -90) {
                      translateX = -9999;
                      rotateX = 0;
                  }
              }
              else {
                  translateY = optOffset;
              }
              opt._trans = this._sanitizer.bypassSecurityTrustStyle("rotateX(" + rotateX + "deg) translate3d(" + translateX + "px," + translateY + "px," + translateZ + "px)");
              opt._dur = (duration > 0 ? duration + 'ms' : '');
          }
          if (saveY) {
              this.y = y;
          }
          if (emitChange) {
              if (this.lastIndex === undefined) {
                  // have not set a last index yet
                  this.lastIndex = this.col.selectedIndex;
              }
              else if (this.lastIndex !== this.col.selectedIndex) {
                  // new selected index has changed from the last index
                  // update the lastIndex and emit that it has changed
                  this.lastIndex = this.col.selectedIndex;
                  this.ionChange.emit(this.col.options[this.col.selectedIndex]);
              }
          }
      };
      PickerColumnCmp.prototype.refresh = function () {
          var min = this.col.options.length - 1;
          var max = 0;
          for (var i = 0; i < this.col.options.length; i++) {
              if (!this.col.options[i].disabled) {
                  min = Math.min(min, i);
                  max = Math.max(max, i);
              }
          }
          var selectedIndex = util_1.clamp(min, this.col.selectedIndex, max);
          if (selectedIndex !== this.col.selectedIndex) {
              var y = (selectedIndex * this.optHeight) * -1;
              this.update(y, 150, true, true);
          }
      };
      __decorate([
          core_1.ViewChild('colEle'), 
          __metadata('design:type', core_1.ElementRef)
      ], PickerColumnCmp.prototype, "colEle", void 0);
      __decorate([
          core_1.Input(), 
          __metadata('design:type', Object)
      ], PickerColumnCmp.prototype, "col", void 0);
      __decorate([
          core_1.Output(), 
          __metadata('design:type', core_1.EventEmitter)
      ], PickerColumnCmp.prototype, "ionChange", void 0);
      PickerColumnCmp = __decorate([
          core_1.Component({
              selector: '.picker-col',
              template: '<div *ngIf="col.prefix" class="picker-prefix" [style.width]="col.prefixWidth">{{col.prefix}}</div>' +
                  '<div class="picker-opts" #colEle [style.width]="col.optionsWidth">' +
                  '<button *ngFor="let o of col.options; let i=index" [style.transform]="o._trans" [style.transitionDuration]="o._dur" [class.picker-opt-selected]="col.selectedIndex === i" [class.picker-opt-disabled]="o.disabled" (click)="optClick($event, i)" type="button" category="picker-opt">' +
                  '{{o.text}}' +
                  '</button>' +
                  '</div>' +
                  '<div *ngIf="col.suffix" class="picker-suffix" [style.width]="col.suffixWidth">{{col.suffix}}</div>',
              host: {
                  '[style.min-width]': 'col.columnWidth',
                  '[class.picker-opts-left]': 'col.align=="left"',
                  '[class.picker-opts-right]': 'col.align=="right"',
              }
          }), 
          __metadata('design:paramtypes', [config_1.Config, core_1.ElementRef, platform_browser_1.DomSanitizationService])
      ], PickerColumnCmp);
      return PickerColumnCmp;
  }());
  /**
   * @private
   */
  var PickerDisplayCmp = (function () {
      function PickerDisplayCmp(_viewCtrl, _elementRef, _config, params, renderer) {
          this._viewCtrl = _viewCtrl;
          this._elementRef = _elementRef;
          this._config = _config;
          this.d = params.data;
          if (this.d.cssClass) {
              this.d.cssClass.split(' ').forEach(function (cssClass) {
                  renderer.setElementClass(_elementRef.nativeElement, cssClass, true);
              });
          }
          this.id = (++pickerIds);
          this.lastClick = 0;
      }
      PickerDisplayCmp.prototype.ionViewLoaded = function () {
          // normalize the data
          var data = this.d;
          data.buttons = data.buttons.map(function (button) {
              if (util_1.isString(button)) {
                  return { text: button };
              }
              if (button.role) {
                  button.cssRole = "picker-toolbar-" + button.role;
              }
              return button;
          });
          // clean up dat data
          data.columns = data.columns.map(function (column) {
              if (!util_1.isPresent(column.columnWidth)) {
                  column.columnWidth = (100 / data.columns.length) + '%';
              }
              if (!util_1.isPresent(column.options)) {
                  column.options = [];
              }
              column.options = column.options.map(function (inputOpt) {
                  var opt = {
                      text: '',
                      value: '',
                      disabled: inputOpt.disabled,
                  };
                  if (util_1.isPresent(inputOpt)) {
                      if (util_1.isString(inputOpt) || util_1.isNumber(inputOpt)) {
                          opt.text = inputOpt.toString();
                          opt.value = inputOpt;
                      }
                      else {
                          opt.text = util_1.isPresent(inputOpt.text) ? inputOpt.text : inputOpt.value;
                          opt.value = util_1.isPresent(inputOpt.value) ? inputOpt.value : inputOpt.text;
                      }
                  }
                  return opt;
              });
              return column;
          });
      };
      PickerDisplayCmp.prototype.refresh = function () {
          this._cols.forEach(function (column) {
              column.refresh();
          });
      };
      PickerDisplayCmp.prototype._colChange = function (selectedOption) {
          // one of the columns has changed its selected index
          var picker = this._viewCtrl;
          picker.ionChange.emit(this.getSelected());
      };
      PickerDisplayCmp.prototype._keyUp = function (ev) {
          if (this.enabled && this._viewCtrl.isLast()) {
              if (ev.keyCode === key_1.Key.ENTER) {
                  if (this.lastClick + 1000 < Date.now()) {
                      // do not fire this click if there recently was already a click
                      // this can happen when the button has focus and used the enter
                      // key to click the button. However, both the click handler and
                      // this keyup event will fire, so only allow one of them to go.
                      void 0;
                      var button = this.d.buttons[this.d.buttons.length - 1];
                      this.btnClick(button);
                  }
              }
              else if (ev.keyCode === key_1.Key.ESCAPE) {
                  void 0;
                  this.bdClick();
              }
          }
      };
      PickerDisplayCmp.prototype.ionViewDidEnter = function () {
          var activeElement = document.activeElement;
          if (activeElement) {
              activeElement.blur();
          }
          var focusableEle = this._elementRef.nativeElement.querySelector('button');
          if (focusableEle) {
              focusableEle.focus();
          }
          this.enabled = true;
      };
      PickerDisplayCmp.prototype.btnClick = function (button, dismissDelay) {
          var _this = this;
          if (!this.enabled) {
              return;
          }
          // keep the time of the most recent button click
          this.lastClick = Date.now();
          var shouldDismiss = true;
          if (button.handler) {
              // a handler has been provided, execute it
              // pass the handler the values from the inputs
              if (button.handler(this.getSelected()) === false) {
                  // if the return value of the handler is false then do not dismiss
                  shouldDismiss = false;
              }
          }
          if (shouldDismiss) {
              setTimeout(function () {
                  _this.dismiss(button.role);
              }, dismissDelay || this._config.get('pageTransitionDelay'));
          }
      };
      PickerDisplayCmp.prototype.bdClick = function () {
          if (this.enabled && this.d.enableBackdropDismiss) {
              this.dismiss('backdrop');
          }
      };
      PickerDisplayCmp.prototype.dismiss = function (role) {
          return this._viewCtrl.dismiss(this.getSelected(), role);
      };
      PickerDisplayCmp.prototype.getSelected = function () {
          var selected = {};
          this.d.columns.forEach(function (col, index) {
              var selectedColumn = col.options[col.selectedIndex];
              selected[col.name] = {
                  text: selectedColumn ? selectedColumn.text : null,
                  value: selectedColumn ? selectedColumn.value : null,
                  columnIndex: index,
              };
          });
          return selected;
      };
      __decorate([
          core_1.ViewChildren(PickerColumnCmp), 
          __metadata('design:type', core_1.QueryList)
      ], PickerDisplayCmp.prototype, "_cols", void 0);
      __decorate([
          core_1.HostListener('body:keyup', ['$event']), 
          __metadata('design:type', Function), 
          __metadata('design:paramtypes', [KeyboardEvent]), 
          __metadata('design:returntype', void 0)
      ], PickerDisplayCmp.prototype, "_keyUp", null);
      PickerDisplayCmp = __decorate([
          core_1.Component({
              selector: 'ion-picker-cmp',
              template: '<ion-backdrop (click)="bdClick()"></ion-backdrop>' +
                  '<div class="picker-wrapper">' +
                  '<div class="picker-toolbar">' +
                  '<div *ngFor="let b of d.buttons" class="picker-toolbar-button" [ngClass]="b.cssRole">' +
                  '<button (click)="btnClick(b)" [ngClass]="b.cssClass" class="picker-button" clear>' +
                  '{{b.text}}' +
                  '</button>' +
                  '</div>' +
                  '</div>' +
                  '<div class="picker-columns">' +
                  '<div class="picker-above-highlight"></div>' +
                  '<div *ngFor="let c of d.columns" [col]="c" class="picker-col" (ionChange)="_colChange($event)"></div>' +
                  '<div class="picker-below-highlight"></div>' +
                  '</div>' +
                  '</div>',
              host: {
                  'role': 'dialog'
              },
              directives: [PickerColumnCmp],
              encapsulation: core_1.ViewEncapsulation.None,
          }), 
          __metadata('design:paramtypes', [view_controller_1.ViewController, core_1.ElementRef, config_1.Config, nav_params_1.NavParams, core_1.Renderer])
      ], PickerDisplayCmp);
      return PickerDisplayCmp;
  }());
  /**
   * Animations for pickers
   */
  var PickerSlideIn = (function (_super) {
      __extends(PickerSlideIn, _super);
      function PickerSlideIn(enteringView, leavingView, opts) {
          _super.call(this, enteringView, leavingView, opts);
          var ele = enteringView.pageRef().nativeElement;
          var backdrop = new animation_1.Animation(ele.querySelector('ion-backdrop'));
          var wrapper = new animation_1.Animation(ele.querySelector('.picker-wrapper'));
          backdrop.fromTo('opacity', 0.01, 0.26);
          wrapper.fromTo('translateY', '100%', '0%');
          this.easing('cubic-bezier(.36,.66,.04,1)').duration(400).add(backdrop).add(wrapper);
      }
      return PickerSlideIn;
  }(transition_1.Transition));
  transition_1.Transition.register('picker-slide-in', PickerSlideIn);
  var PickerSlideOut = (function (_super) {
      __extends(PickerSlideOut, _super);
      function PickerSlideOut(enteringView, leavingView, opts) {
          _super.call(this, enteringView, leavingView, opts);
          var ele = leavingView.pageRef().nativeElement;
          var backdrop = new animation_1.Animation(ele.querySelector('ion-backdrop'));
          var wrapper = new animation_1.Animation(ele.querySelector('.picker-wrapper'));
          backdrop.fromTo('opacity', 0.26, 0);
          wrapper.fromTo('translateY', '0%', '100%');
          this.easing('cubic-bezier(.36,.66,.04,1)').duration(450).add(backdrop).add(wrapper);
      }
      return PickerSlideOut;
  }(transition_1.Transition));
  transition_1.Transition.register('picker-slide-out', PickerSlideOut);
  var pickerIds = -1;
  var DECELERATION_FRICTION = 0.97;
  var FRAME_MS = (1000 / 60);
  