<!DOCTYPE html>
<html>

  <head>
    

    <script data-require="jquery@2.0.3" data-semver="2.0.3" src="http://code.jquery.com/jquery-2.0.3.min.js"></script>
    <link data-require="select2@3.4.5" data-semver="3.4.5" rel="stylesheet" href="//cdn.jsdelivr.net/select2/3.4.5/select2.css" />
    <script data-require="select2@3.4.5" data-semver="3.4.5" src="//cdn.jsdelivr.net/select2/3.4.5/select2.js"></script>
    <script data-require="angular.js@1.2.14" data-semver="1.2.14" src="http://code.angularjs.org/1.2.14/angular.js"></script>
  
    <link rel="stylesheet" href="style.css" />
    <script src="select2.js"></script>
    <script src="script.js"></script>
      
      
  </head>

  <body ng-app="app">
    <h1>Hello Plunker!</h1>
    <div ng-controller="myController">
    
      <select ui-select2 ng-blur="blur()" ng-focus="focus()" ng-model="selectedMovie" placeholder="Choose one of these movies" ng-options="movie as movie.name group by movie.category for movie in movies">
        <option></option>
      </select>
      <div>
        <a ng-click="selectFirst()" href="">Select First</a>
        <a ng-click="newOptions()" href="">Change Options</a>
      </div>
      <p>
        {{selectedMovie | json}}
      </p>
      
      <select ui-select2 ng-model="favoriteMovies" placeholder="Choose many movies" multiple ng-options="movie as movie.name group by movie.category for movie in movies">
        <option></option>
      </select>
      <div>
      
        <a ng-click="removeFirst()" href="">Remove First</a>
      </div>
      <p>
        {{favoriteMovies | json}}
        {{selectValue()}}
      </p>
      

      <script type="text/ng-template" id="/myTemplate.html">
           <span style="color:red;">{{ optionLabel($option) }}</span>
      </script>

      <select ui-select2 ng-model="selectedMovie" placeholder="Choose one of these movies" ng-options="movie as movie.name for movie in movies" option-template-url='/myTemplate.html'>
        <option></option>
      </select>
      <div>
        <a ng-click="selectFirst()" href="">Select First</a>
      </div>
      <p>
        {{selectedMovie | json}}
      </p>
      
      
      <h1> Search {{searchText}}</h1>
      
      <input ui-select2="{minimumInputLength: 1}" placeholder="alskdjfl kajsdl fkajsl dfkasd fasdf" ng-model="selectedNumber" query="getNumbers(query)" query-label="option.text"/>
        
      
      <div>
        Selected: {{selectedNumber | json}}
        <a ng-click="nextValue()" href="">nextValue</a>
        <a ng-click="toggle()" href="">Toggle</a>
  
  
      </div>
      
      <div>
        IsOPen : {{isOpen}}
      </div>   
      <input ui-select2 placeholder="movies from server" ng-model="selectedAjaxMovie" query="getMovies()" query-label="option.name" is-open='isOpen'/>
      
    </div>
  </body>

</html>
// Code goes here

var module = angular.module('app',['ui.select2']);

module.controller("myController", function($scope, $http){
  $scope.movies=[
    { 
      name: 'Dark Knight',
      category: 'Action'
    },
    { 
      name: 'Terminator',
      category: 'Action'
    },
    { 
      name: 'Love Actually',
      category: 'Romance'
    }
    ];
  $scope.blur = function(){
    console.log("BLURRED");
  }
  
  $scope.focus = function(){
    console.log("FOCUS");
  }
  
  $scope.favoriteMovies = [];
  
  $scope.removeFirst = function(){
    $scope.favoriteMovies.pop();
    console.log("Removed movie and now it is:",$scope.favoriteMovies);

  };
  
  $scope.optionLabel = function(option){
    var movie = $scope.movies[option.id];
    return movie.name + " YEAH! (" +movie.category+")";
  }
  
  
  function query(query){
    $timeout(function(){
      var options = [];
      element.find('option').each(function(option){
        options.push({ id: option.val(), text: option.text()});
        });
      query.callback(options);
      
    }, 0);
  }
  
  $scope.selectFirst = function(){
    $scope.selectedMovie = $scope.movies[0];
  }
  
  $scope.selectValue = function(){
    return $('select').eq(1).val();
  }
  
  var newMovies = [{name: 'Naked Gun', category: 'Comedy'}];
  
  $scope.newOptions = function(){
    var old = $scope.movies;
    $scope.movies=newMovies;
    newMovies = old;
  };
  
  
  
  
  $scope.getNumbers=function(query){
        var data = [];
        for (i = 1; i < 5; i++) {
            s = "";
            for (j = 0; j < i; j++) {s = s + query.term;}
            data.push({ id:i, name: "This is option "+ i, text: s +" Page "+query.page, even: s % 2 === 0});
        }
        
        return { results: data, more: true};
  }
  
  var counter = 0;
  $scope.nextValue = function(){
    counter++;
    $scope.selectedNumber = {name:'Initial Selection', text: 'Initial Sellection '+counter};  
  }
  
  $scope.getMovies = function(){
    return $http.get('movies.json').then(function(result){
      return {
        results: result.data
      };
    });
  }
  $scope.toggle = function(){
    $scope.isOpen = !$scope.isOpen;
  }
});


/* Styles go here */

(function() {
	"use strict";
	var module = angular.module('ui.select2', []);

	module.value('uiSelect2Config', {});

	module.directive('uiSelect2', [
		'uiSelect2Config', '$timeout', '$compile', '$parse', '$q', '$rootScope', '$templateCache',
		function(uiSelect2Config, $timeout, $compile, $parse, $q, $rootScope, $templateCache ) {
			var options = {};
			if(uiSelect2Config) {
				angular.extend(options, uiSelect2Config);
			}
			return {
				require: '?ngModel',
				link: function(scope, element, attrs, ngModel) {
				    element.removeClass('form-control');
				    if (isMobileBrowser()) {
				        fixFastClose();
                    }
					// instance-specific options
					var opts = setupOptions();
					setupAttributeAndClassSynchronization();
					setupCleanupOnDestroy();

					if(attrs.isOpen) {
						setupIsOpenBinding();
					}

					if(attrs.query) {
						setupQueryHandler();
					} else {
						scheduleResyncAfterEveryDigest();
					}

					element.select2(opts);
					return;


				    //Privates

				    //This fixes a bug on some android browsers where select closes immediately after opening
					function fixFastClose() {
					    var abstractSelect2 = window.Select2['class'].abstract.prototype;
                        if (abstractSelect2.fixed) {
                            return;
                        }
					    abstractSelect2.fixed = true;
					    var existingOpen = abstractSelect2.open;
					    var existingClose = abstractSelect2.close;
					    var lastOpened = new Date().getTime();

					    abstractSelect2.open = function() {
					        lastOpened = new Date().getTime();
					        return existingOpen.apply(this, arguments);
					    };

					    abstractSelect2.close = function() {
					        var currentTime = new Date().getTime();
					        var timeSinceOpen = currentTime - lastOpened;
					        if (timeSinceOpen > 1000) {
					            return existingClose.apply(this, arguments);
					        }
					        return undefined;
					    };
					}

					function setupOptions() {
						var opts = angular.extend({}, options, scope.$eval(attrs.uiSelect2));
						opts.shouldFocusInput = shouldFocusInput;
						setupFormatter(opts);
						return opts;
					}
					
					function getTemplateHtml(){
					  if(attrs.optionTemplate){
					      return scope.$eval(attrs.optionTemplate);  
					  }
					  if(attrs.optionTemplateUrl){
					    return $templateCache.get(attrs.optionTemplateUrl);
					  }
					  
					}
					
					function setupFormatter(opts){
					  if(!attrs.optionTemplate && !attrs.optionTemplateUrl){
					    return;
					  }
					  var templateHtml = getTemplateHtml();
					  var templateNode = angular.element("<div>"+templateHtml+"</div>");
					  var compiledTemplate = $compile(templateNode);
					  opts.formatResult = function(data){
					       var tempScope = scope.$new();
					       tempScope.$option = data;
					       var template = null;
					       compiledTemplate(tempScope, function(clone){
					         template = clone.children();
					         
					       });
					       scope.$digest();
					       return template;
					      
					  }
					  
					}

					function scheduleResyncAfterEveryDigest() {
						//After every digest make sure that select2's value is in sync
						var scheduledValue = false;
						scope.$watch(function() {
							//Only schedule once per digest cycle regardles of times watch is called;
							if(!scheduledValue) {
								scheduledValue = true;
								$timeout(function() {
									element.select2('val', element.val());
									scheduledValue = false;
								}, 0, false);
							}
						});
					}

					function shouldFocusInput(instance) {
						// Attempt to detect touch devices
						var supportsTouchEvents = (('ontouchstart' in window) || (navigator.msMaxTouchPoints > 0));

						// Only devices which support touch events should be special cased
						if(!supportsTouchEvents) {
							return true;
						}

						if(isMobileBrowser()) {
							return false;
						} // Don't focus (show virtual keyboard) on mobile devices

						// Never focus the input if search is disabled
						if(instance.opts.minimumResultsForSearch < 0) {
							return false;
						}

						return true;
                    }

					function isMobileBrowser() {
						/// <summary>
						/// Based on: http://detectmobilebrowsers.com/
						/// added the following: |ipad|playbook|silk|tablet pc
						/// </summary>
						var a = navigator.userAgent || navigator.vendor || window.opera;
						return /(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|tablet pc|hiptop|iemobile|ip(hone|od)|playbook|ipad|iris|kindle|silk|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino/i.test(a)
							|| /1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test(a.substr(0, 4));
					}


					function setupIsOpenBinding() {
						var isOpen = false;
						var isOpenExpression = $parse(attrs.isOpen);
						scope.$watch(isOpenExpression, function(value) {
							if(value && !isOpen) {
								$timeout(function() {
									isOpen = true;
									element.select2('open');
								}, 0, false);

							}
							if(!value && isOpen) {
								$timeout(function() {
									element.select2('close');
									isOpen = false;
									element.select2('close');
								}, 0, false);
							}
						});

						element.on('select2-open.select2', function() {
							scope.$apply(function() {
								isOpen = true;
								isOpenExpression.assign(scope, true);
							});
						});

						element.on('select2-close.select2', function() {
							scope.$apply(function() {
								isOpen = false;
								isOpenExpression.assign(scope, false);
							});
						});
					}


					function setupCleanupOnDestroy() {
						element.on("$destroy", function() {
							element.select2("destroy");
							element.off('.select2');
						});
					}


					function setupAttributeAndClassSynchronization() {
						attrs.$observe('disabled', function(value) {
							element.select2('enable', !value);
						});

						attrs.$observe('readonly', function(value) {
							element.select2('readonly', !!value);
						});

						// Update valid and dirty statuses
						if(ngModel) {
							ngModel.$parsers.push(function(value) {
								var div = element.select2("container");
								div
									.toggleClass('ng-invalid', !ngModel.$valid)
									.toggleClass('ng-valid', ngModel.$valid)
									.toggleClass('ng-invalid-required', !ngModel.$valid)
									.toggleClass('ng-valid-required', ngModel.$valid)
									.toggleClass('ng-dirty', ngModel.$dirty)
									.toggleClass('ng-pristine', ngModel.$pristine);
								return value;
							});
						}
					}


					function setupQueryHandler() {
						var queryResults = [];
						ngModel.$parsers.unshift(function(value) {
							var result = queryResults[value];
							return result;
						});

						ngModel.$formatters.push(function(value) {
							if(value) {
								var label = scope.$eval(attrs.queryLabel, {
									option: value
								});
								element.select2('data', {
									text: label
								});
							}
						});

						opts.query = function(query) {
							if(query.page === 1) {
								queryResults = [];
							}

							var queryOptions = {
								term: query.term,
								page: query.page,
								context: query.context
							};
							var resultPromiseOrObject = scope.$eval(attrs.query, {
								query: queryOptions
							});

							$q.when(resultPromiseOrObject).then(function(result) {
								var select2Results = [];
								var i = queryResults.length;

								angular.forEach(result.results, function(option) {
									var context = {
										option: option
									};
									var label = scope.$eval(attrs.queryLabel, context);
									select2Results.push({
										id: i,
										text: label
									});
									i++;
								});

								queryResults = queryResults.concat(result.results);
								query.callback({
									results: select2Results,
									more: result.more
								});
							});
						};
					}

				}
			};
		}
	]);
})();
 [{ 
      "name" : "Dark Knight",
      "category": "Action"
      },
    { 
      "name": "Terminator",
      "category": "Action"
    },
    { 
      "name": "Love Actually",
      "category": "Romance"
    }
]