<!DOCTYPE html>
<html ng-app="app">

<head>
  <meta charset="utf-8" />
  <meta name="viewport" content="initial-scale=1, maximum-scale=1, user-scalable=no, width=device-width" />
  <title>Fancy Select</title>
  <script src="//code.ionicframework.com/nightly/js/ionic.bundle.js"></script>
  <
  <script src="script.js"></script>
  <script src="modal.service.js"></script>
  <script src="fancy-select.directive.js"></script>
  <link href="//code.ionicframework.com/nightly/css/ionic.css" rel="stylesheet" />
  <link rel="stylesheet" href="style.css" />
</head>

<body ng-controller="MainController as main">
  <ion-header-bar class="bar-positive">
    <h1 class="title">Fancy Ionic Select</h1>
  </ion-header-bar>
  <ion-content>
    <ion-list>
      <div class="item item-divider">Select single item</div>
      <div class="item  item-select" fancy-select ng-model="single1" items="selectable" item-label="fname + ' ' +lname">
        {{single1.fname || 'Select item'}}
      </div>
      <div class="item item-divider"> Select select with group by</div>
      <div class="item item-select" fancy-select ng-model="single2" items="selectable" item-label="fname+ ' ' +lname" group-by="group">
        {{single2.fname || 'Select item'}}
      </div>
      <div class="item item-divider"> Select select with group by and group label</div>
      <div class="item item-select" fancy-select ng-model="single3" items="selectable" item-label="fname+ ' ' +lname" group-by="group" group-label="group+ ' persons'">
        {{single3.fname || 'Select item'}}
      </div>
      <div class="item item-divider">Multiple select</div>
      <div class="item item-select" fancy-select ng-model="multi1" multi-select="true" items="selectable" item-label="fname+ ' ' +lname">
        {{parseMulti(multi1) || 'Select Items'}}
      </div>
      <div class="item item-divider"> Multiple select with group by</div>
      <div class="item item-select" fancy-select ng-model="multi2" multi-select="true" items="selectable" item-label="fname+ ' ' +lname" group-by="group">
        {{parseMulti(multi2) || 'Select Items'}}
      </div>
      <div class="item item-divider"> Multiple select with group by and group label</div>
      <div class="item item-select" fancy-select ng-model="multi3" multi-select="true" items="selectable" item-label="fname+ ' ' +lname" group-by="group" group-label="group+ ' persons'">
        {{parseMulti(multi3) || 'Select Items'}}
      </div>
    </ion-list>
  </ion-content>
</body>

</html>
angular.module('app', ['ionic'])

.controller('MainController', function($scope) {
  $scope.selectable = [{"fname":"Ghaffar","lname":"Peterman","group":"Good"},{"fname":"Arturo","lname":"Sessa","group":"Good"},{"fname":"Bilal","lname":"Cox","group":"Best"},{"fname":"Serena","lname":"Bradley","group":"Best"},{"fname":"Mario","lname":"Delaura","group":"Best"},{"fname":"Bruce","lname":"Hackman","group":"Good"},{"fname":"Hope","lname":"Barowsky","group":"Best"},{"fname":"Lauris","lname":"Kaa","group":"Better"},{"fname":"Bola","lname":"Obara","group":"Best"},{"fname":"Jamie","lname":"Betts","group":"Good"},{"fname":"Bartley","lname":"Cole","group":"Best"},{"fname":"Wichaya","lname":"Mullins","group":"Good"},{"fname":"Rich","lname":"Seymour","group":"Better"},{"fname":"Denys","lname":"Gallant","group":"Good"},{"fname":"Maurice","lname":"Barrientos","group":"Best"},{"fname":"Jawdat","lname":"Ward","group":"Better"},{"fname":"Sherrie","lname":"Whalley","group":"Better"},{"fname":"Rob","lname":"Gould","group":"Better"},{"fname":"Saowalak","lname":"Hadley","group":"Good"},{"fname":"Marqueal","lname":"Wright","group":"Better"}];
  
  $scope.parseMulti = function(items){
    if(items){
      return items.map(function(item){ return item.fname + ' ' +item.lname; }).join(', ');
    }
  };

});
body {
  cursor: url('http://ionicframework.com/img/finger.png'), auto;
}

.slide-in-right {
  -webkit-transform: translateX(100%);
  -moz-transform: translateX(100%);
  -ms-transform: translateX(100%);
  -o-transform: translateX(100%);
  transform: translateX(100%);
}

    @media (min-width: 680px){
		.slide-in-right.ng-leave-active {
		    bottom: 20%;
		}
	}

.slide-in-right.ng-enter,
.slide-in-right > .ng-enter {
  -webkit-transition: all cubic-bezier(0.1, 0.7, 0.1, 1) 400ms;
  -moz-transition: all cubic-bezier(0.1, 0.7, 0.1, 1) 400ms;
  -o-transition: all cubic-bezier(0.1, 0.7, 0.1, 1) 400ms;
  transition: all cubic-bezier(0.1, 0.7, 0.1, 1) 400ms;
}

.slide-in-right.ng-enter-active,
.slide-in-right > .ng-enter-active {
  -webkit-transform: translateX(0);
  -moz-transform: translateX(0);
  -ms-transform: translateX(0);
  -o-transform: translateX(0);
  transform: translateX(0);
}

.slide-in-right.ng-leave,
.slide-in-right > .ng-leave {
  -webkit-transition: all ease-in-out 250ms;
  -moz-transition: all ease-in-out 250ms;
  -o-transition: all ease-in-out 250ms;
  transition: all ease-in-out 250ms;
}

.fancy-select.item-select:after{
			margin-top: -5px;
		    width: 0;
		    height: 0;
		    border-left: 5px solid;
		    border-top-color: white;
		    border-bottom-color: white;
		    border-top: 5px solid rgba(0, 0, 0, 0);
		    border-bottom: 5px solid rgba(0, 0, 0, 0);
		    color: #999;
		}
		
.fancy-select-modal .list{
		margin: 0;
}

.fancy-select-modal .list  + .list .item:first-child{
		margin-top: -2px;
}


    function fancySelectDirective($rootScope, $parse, $timeout, genericModalService) {
		return {
			restrict: 'EA',
			require: 'ngModel',
			scope: {
				'items': '='
			},

			link: function(scope, element, attrs, ngModelCtrl) {
				element.addClass('fancy-select');

				// Validate directive attributes.
                if (!attrs.items) {
                    throw(new Error('items requires list over which to iterate.'));
                }
                if (!attrs.itemLabel ) {
                    throw(new Error('fancySelect requires a itemLabel expression.'));
                }

				var multiSelect 		= scope.$eval(attrs.multiSelect) || false,
					closeOnSelection 	= scope.$eval(attrs.closeOnSelection) || multiSelect ? false : true,
					headerText 			= attrs.headerText || (multiSelect ? 'Select items' : 'Select item'),
					templateUrl 		= attrs.itemsTemplateUrl || 'template/fancy-select/fancy-select.html',
					groupBy				= attrs.groupBy || '',
					groupLabelParser 	= attrs.groupLabel ? $parse(attrs.groupLabel) : false,
					itemLabelParser 	= $parse(attrs.itemLabel),
					modalScope;

				function select(){
					var viewValue;
					if(multiSelect){
						viewValue = modalScope.selection.selectable.filter(function (item){return item.selected;});
					}else{
						viewValue = modalScope.selection.selected;
					}
					ngModelCtrl.$setViewValue(viewValue);
					ngModelCtrl.$render();
				}
				
				function showItems(){
					modalScope = $rootScope.$new();
					modalScope.multiSelect = multiSelect;
					modalScope.headerText = headerText;
					modalScope.itemLabel = itemLabelParser;
					modalScope.closeOnSelection = closeOnSelection;
					modalScope.group = groupBy;
					modalScope.groupLabel = groupLabelParser;
					modalScope.select = select;
					modalScope.selection = {
						selectable: scope.items,
						selected: scope.selected
					};

					if(multiSelect && typeof modalScope.selection.selected !== 'undefined' && Array.isArray(modalScope.selection.selected)){
						modalScope.selection.selectable.forEach(function (item){
							delete item.selected;
						});
						modalScope.selection.selected.forEach(function (item){
							var itemIndex = modalScope.selection.selectable.indexOf(item);
							if(itemIndex >= 0){
								modalScope.selection.selectable[itemIndex].selected = true;
							}
						});
					}

					if(closeOnSelection){
						var watchable = multiSelect ? 'selection.selectable' : 'selection.selected';
						modalScope.$watch(watchable, function (nv, ov){
							if(nv !== ov){
								select();
								$timeout(modalScope.closeModal, 0);
							}
						}, true);
					}

					genericModalService.show(templateUrl, modalScope, 'slide-in-right');
				}

				ngModelCtrl.$render = function() {
					scope.selected = ngModelCtrl.$viewValue;
				};

				element.on('click', showItems);
			}
		};
    }

    function fancySelectTemplate ($templateCache) {
		$templateCache.put('template/fancy-select/fancy-select.html', 
			'<ion-modal-view class="fancy-select-modal">' +
			'	<ion-header-bar align-title="center" class="bar-positive">' +
			'		<button class="button button-clear button-icon ion-arrow-left-c" ng-click="closeModal()"></button>' +
			'		<h1 class="title">{{headerText}}</h1>' +
			'		<button class="button button-clear button-icon ion-checkmark-round" ng-if="!closeOnSelection" ng-click="select(); closeModal();"></button>' +
			'	</ion-header-bar>' +
			'	<ion-content>' +
			'		<div ng-if="group">' +
			'			<div class="list" ng-if="multiSelect" ng-repeat="(key, value) in selection.selectable | groupBy : group">' +
        	'				<ion-item ng-if="groupLabel" class="item-divider">{{groupLabel(value[0])}}</ion-item>' +
			'				<ion-checkbox ng-repeat="item in value" ng-model="item.selected">{{itemLabel(item)}}</ion-checkbox>' +
        	'			</div>' +
			'			<div class="list" ng-if="!multiSelect" ng-repeat="(key, value) in selection.selectable | groupBy : group">' +
        	'				<ion-item ng-if="groupLabel" class="item-divider">{{groupLabel(value[0])}}</ion-item>' +
			'				<ion-radio ng-repeat="item in value" ng-model="selection.selected" ng-value="item" name="fancy-select">{{itemLabel(item)}}</ion-radio>' +
        	'			</div>' +
        	'		</div>' +
			'		<div ng-if="!group">' +
			'			<div class="list">' +
			'				<ion-checkbox ng-if="multiSelect" ng-repeat="item in selection.selectable" ng-model="item.selected">{{itemLabel(item)}}</ion-checkbox>' +
			'				<ion-radio ng-if="!multiSelect" ng-repeat="item in selection.selectable" ng-model="selection.selected" ng-value="item" name="fancy-select">{{itemLabel(item)}}</ion-radio>' +
        	'			</div>' +
        	'		</div>' +
			'	</ion-content>' +
			'</ion-modal-view>'
		);
	}

    angular.module('app')

    .run(fancySelectTemplate)

    .directive('fancySelect', fancySelectDirective);
	function ModalService($rootScope, $q, $ionicModal){

		function show(templateUrl, scope, animation){
			var deferred = $q.defer();
			var modalScope = typeof scope !== 'undefined' ? scope : $rootScope.$new();

			$ionicModal.fromTemplateUrl(templateUrl, {
	        	scope: modalScope,
	        	animation: animation || 'slide-in-up'
		    }).then(function(modal) {
		        modalScope.modal = modal;

		        modalScope.openModal = function(){
		        	modalScope.modal.show();
		        };

		        modalScope.closeModal = function(){
        			modalScope.modal.hide();
		        };

		        modalScope.$on('modal.hidden', function (thisModal){
		        	thisModal.currentScope.$destroy();
		        	thisModal.currentScope.modal.remove();
		        });
		        
		        modalScope.modal.show();

		        deferred.resolve(modalScope);
		    });

		    return deferred.promise;
		}

		return {
			show: show
		};
	}

	angular.module('app')

	.factory('genericModalService', ModalService);