diff --git a/Apollo/api/application/models/Studentview_model.php b/Apollo/api/application/models/Studentview_model.php
index 5487cef7..9d031631 100755
--- a/Apollo/api/application/models/Studentview_model.php
+++ b/Apollo/api/application/models/Studentview_model.php
@@ -79,7 +79,7 @@ class Studentview_model extends CI_Model
* */
public function getStudentCourse($studentId=null){
- $this->db->select('SCU.EnrollmentID,CU.CourseID,CU.CourseName,US.UniversityID,US.UniversityName');
+ $this->db->select('SCU.EnrollmentID,CU.CourseID,CU.CourseName,US.UniversityID,US.UniversityName,US.UniversityShortName');
$this->db->from( STUDENTCOURSE . ' as SCU');
$this->db->join( COURSE . ' as CU', 'CU.CourseID = SCU.CourseID');
$this->db->join( UNIVERSITY . ' as US', 'US.UniversityID = SCU.UniversityID');
@@ -93,6 +93,7 @@ class Studentview_model extends CI_Model
$fetchData['CourseName']=$row->CourseName;
$fetchData['UniversityID']=$row->UniversityID;
$fetchData['UniversityName']=$row->UniversityName;
+ $fetchData['UniveShortName'] = $row->UniversityShortName;
// $fetchData['SessionName']=$row->SessionName;
$fetchData['EnrollmentID']=$row->EnrollmentID;
// get student fees details
@@ -170,11 +171,16 @@ class Studentview_model extends CI_Model
$storePaidDetails['BatchDate'] = $feeRow->BatchDate;
// for get paid bill details
- $this->db->select('ifnull(SUM((BillAmount)),0) as BillAmount,BillNO,BillDate,ModeOfPayment,ReceiptNo');
- $this->db->where('FeesId',$feeRow->FeesID);
- $this->db->order_by('ID',"ASC");
- $this->db->group_by('BillNO');
- $storePaidDetails['paidDetails']=$this->db->get(STUDENTS_FEES_PAID)->result();
+ // for get paid bill details
+ $this->db->select('ifnull(SUM((BillAmount)),0) as BillAmount,BillNO,BillDate,ModeOfPayment,ReceiptNo,BR.BranchName,BR.Address,BR.LogoPath,STF.Firstname as ReceivedBy');
+ $this->db->from(STUDENTS_FEES_PAID.' as SFP');
+ $this->db->join(BRANCH.' as BR','BR.BranchCode = SFP.UpdatedBy','left');
+ $this->db->join(LOGIN.' as LO','LO.ID = SFP.CreatedBy');
+ $this->db->join(STAFF.' as STF','STF.StaffID = LO.StaffID');
+ $this->db->where('SFP.FeesId',$feeRow->FeesID);
+ $this->db->order_by('SFP.ID',"ASC");
+ $this->db->group_by('SFP.BillNO');
+ $storePaidDetails['paidDetails']=$this->db->get()->result();
// for installment details
$this->load->model('Fees_status_model');
@@ -252,11 +258,15 @@ class Studentview_model extends CI_Model
$storePaidDetails['BatchDate'] = "";
// for get paid bill details
- $this->db->select('ifnull(SUM((BillAmount)),0) as BillAmount,BillNO,BillDate,ModeOfPayment,ReceiptNo');
- $this->db->where('FeesId',$feeRow->FeesID);
- $this->db->order_by('ID',"ASC");
- $this->db->group_by('BillNO');
- $storePaidDetails['paidDetails']=$this->db->get(STUDENTS_FEES_PAID)->result();
+ $this->db->select('ifnull(SUM((BillAmount)),0) as BillAmount,BillNO,BillDate,ModeOfPayment,ReceiptNo,BR.BranchName,BR.Address,BR.LogoPath,STF.Firstname as ReceivedBy');
+ $this->db->from(STUDENTS_FEES_PAID.' as SFP');
+ $this->db->join(BRANCH.' as BR','BR.BranchCode = SFP.UpdatedBy','left');
+ $this->db->join(LOGIN.' as LO','LO.ID = SFP.CreatedBy');
+ $this->db->join(STAFF.' as STF','STF.StaffID = LO.StaffID');
+ $this->db->where('SFP.FeesId',$feeRow->FeesID);
+ $this->db->order_by('SFP.ID',"ASC");
+ $this->db->group_by('SFP.BillNO');
+ $storePaidDetails['paidDetails']=$this->db->get()->result();
$storePaidDetails['InstallmentDetails']="";
$mergeResult[]=$storePaidDetails;
diff --git a/Apollo/assets/js/app.js b/Apollo/assets/js/app.js
index 1ba34fe9..95138825 100755
--- a/Apollo/assets/js/app.js
+++ b/Apollo/assets/js/app.js
@@ -19,5 +19,6 @@ angular.module("clip-two", [
'ipCookie',
'angularUtils.directives.dirPagination',
'htmlToPdfSave',
+ 'ui.select2',
]);
diff --git a/Apollo/assets/js/controllers/studentViewCtrl.js b/Apollo/assets/js/controllers/studentViewCtrl.js
index 2312792b..1701bcb9 100755
--- a/Apollo/assets/js/controllers/studentViewCtrl.js
+++ b/Apollo/assets/js/controllers/studentViewCtrl.js
@@ -27,12 +27,12 @@ app.controller('studentViewCtrl', ["$scope","$rootScope", "toaster", "$filter",
if (response.data.status == 200 && response.data.studentStatus== true) {
$rootScope.studentAllDetails = response.data;
- $scope.studentDetails = response.data.studentDetails;
+ $rootScope.studentDetails = response.data.studentDetails;
$scope.courseDetails = response.data.courseDetails;
} else {
- $scope.studentDetails = "";
+ $rootScope.studentDetails = "";
$scope.courseDetails = "";
$rootScope.studentAllDetails="";
@@ -73,7 +73,7 @@ app.controller('studentViewCtrl', ["$scope","$rootScope", "toaster", "$filter",
/*modal controller
* */
-app.controller('FeesModalDemoCtrl', ["$scope", "$modal", "$log", function ($scope, $modal, $log) {
+app.controller('FeesModalDemoCtrl', ["$scope", "$rootScope", "$modal", "$log", function ($scope, $rootScope, $modal, $log) {
//Tooltip for print button
$scope.dynamicTooltip = 'Click to View Bill Details';
@@ -82,10 +82,11 @@ app.controller('FeesModalDemoCtrl', ["$scope", "$modal", "$log", function ($scop
// $scope.items = ['item1', 'item2', 'item3'];
$scope.FeesName="" ;
- $scope.open = function (values,type) {
+ $rootScope.CUDetails="" ;
+ $scope.open = function (values,type,courseDetails) {
$scope.FeesName = values;
-
+ $rootScope.CUDetails=courseDetails ;
var modalInstance = $modal.open({
templateUrl: 'myModalContent.html',
controller: 'ModalInstanceCtrl',
@@ -109,6 +110,18 @@ app.controller('FeesModalDemoCtrl', ["$scope", "$modal", "$log", function ($scop
});
};
}]);
+app.directive('visible', function() {
+
+ return {
+ restrict: 'A',
+
+ link: function(scope, element, attributes) {
+ scope.$watch(attributes.visible, function(value){
+ element.css('visibility', value ? 'visible' : 'hidden');
+ });
+ }
+ };
+});
// Please note that $modalInstance represents a modal window (instance) dependency.
// It is not the same as the $modal service used above.
@@ -129,6 +142,47 @@ app.controller('ModalInstanceCtrl', ["$scope", "$modalInstance", "items","WordsS
$modalInstance.dismiss('cancel');
};
+ //show hide function for pdf design
+ $scope.billNo="";
+ $scope.sessionName="";
+ $scope.paymentType="";
+ $scope.billDate="";
+ $scope.amountInWords = "";
+ $scope.billAmount = "";
+ $scope.branchName = "";
+ $scope.ReceivedBy = "";
+ $scope.BranchAddr = "";
+ $scope.BranchAddr = "";
+ $scope.BranchLogo = "";
+ $scope.ShowHide = function (pdfValue) {
+ $scope.showButton = true;
+ $scope.billNo = pdfValue.BillNO;
+ $scope.paymentType=pdfValue.ModeOfPayment;
+ $scope.billDate=pdfValue.BillDate;
+ $scope.amountInWords = WordsService.convertNumberToWords(pdfValue.BillAmount);
+ $scope.billAmount = pdfValue.BillAmount;
+ $scope.branchName = pdfValue.BranchName;
+ $scope.ReceivedBy = pdfValue.ReceivedBy;
+ $scope.BranchAddr = pdfValue.Address;
+ $scope.BranchLogo = pdfValue.LogoPath;
+
+
+ }
+
+ $scope.mouseLeave = function(){
+ $scope.showButton = false;
+ $scope.billNo="";
+ $scope.sessionName="";
+ $scope.paymentType="";
+ $scope.billDate="";
+ $scope.amountInWords = "";
+ $scope.billAmount = "";
+ $scope.branchName = "";
+ $scope.ReceivedBy="";
+ $scope.BranchAddr = "";
+ $scope.BranchLogo = "";
+ }
+
}]);
app.filter('unique', function() {
diff --git a/Apollo/assets/views/status-update/answer_booklet_status.html b/Apollo/assets/views/status-update/answer_booklet_status.html
index c2fb96d2..b4c323fd 100755
--- a/Apollo/assets/views/status-update/answer_booklet_status.html
+++ b/Apollo/assets/views/status-update/answer_booklet_status.html
@@ -19,7 +19,7 @@
-
+
@@ -32,18 +32,18 @@
-
+
-
-
+
diff --git a/Apollo/assets/views/status-update/application_status.html b/Apollo/assets/views/status-update/application_status.html
index a664f900..b4a5a6f4 100755
--- a/Apollo/assets/views/status-update/application_status.html
+++ b/Apollo/assets/views/status-update/application_status.html
@@ -19,7 +19,7 @@
-
+
@@ -32,18 +32,18 @@
-
+
-
+
-
+
diff --git a/Apollo/assets/views/status-update/certification_status.html b/Apollo/assets/views/status-update/certification_status.html
index c98b1bf6..ff296fb4 100755
--- a/Apollo/assets/views/status-update/certification_status.html
+++ b/Apollo/assets/views/status-update/certification_status.html
@@ -37,7 +37,7 @@
Course
-
+
diff --git a/Apollo/assets/views/status-update/fees_status.html b/Apollo/assets/views/status-update/fees_status.html
index a16eb4fd..a7b19941 100755
--- a/Apollo/assets/views/status-update/fees_status.html
+++ b/Apollo/assets/views/status-update/fees_status.html
@@ -81,7 +81,7 @@
-
diff --git a/Apollo/assets/views/status-update/study_material_status.html b/Apollo/assets/views/status-update/study_material_status.html
index 9678de9a..0e7268bc 100755
--- a/Apollo/assets/views/status-update/study_material_status.html
+++ b/Apollo/assets/views/status-update/study_material_status.html
@@ -37,7 +37,7 @@
Course
-
+
diff --git a/Apollo/assets/views/student/studentView.html b/Apollo/assets/views/student/studentView.html
index fa8d7ec1..73a67bf4 100755
--- a/Apollo/assets/views/student/studentView.html
+++ b/Apollo/assets/views/student/studentView.html
@@ -19,8 +19,8 @@
.modal-content {
background: #ffffff;
box-shadow: none;
- width: 80%;
- margin-left: 30%;
+ width: 150%;
+ margin-left: -20%;
margin-top: 10%;
}
@@ -48,9 +48,9 @@
-
+
@@ -287,12 +287,12 @@
{{fees.PaidBillAmount}}
{{fees.BalanceAmount}} |
-
+ |
|
-
+ |
@@ -311,6 +311,7 @@
| Amount |
Due Date |
+
@@ -334,6 +335,7 @@
Bill Date |
Receipt NO |
Mode of Payment |
+ Print |
@@ -344,12 +346,83 @@
{{v.BillDate}} |
{{v.ReceiptNo}} |
{{v.ModeOfPayment}} |
+
+ |
+
+
+
+
+ | APOLLO |
+
+
+ ![]()
+
+
+ |
+ APOLLO DISTANCE EDUCATION COLLEGE
+
+ (A Group of SVE Trust)
+
+ {{BranchAddr}}
+ |
+
+
+ |
+
+
+ |
+
+
+ |
+ FEES ESTIMATE
+ |
+ DOM: {{billNo}} |
+
+
+ |
+ Date: {{billDate}} |
+
+
+ | Mr. /Mrs. /Miss: {{studentDetails.Firstname}} |
+ Enrl.No: {{CUDetails.EnrollmentID}} |
+
+
+ | S/o. /D/o. W/o. Mr. /Mrs: {{studentDetails.Fathername}} |
+ Mobile No: {{studentDetails.MobileNumber}} |
+
+
+ | Course: {{CUDetails.CourseName}} |
+ Sem/Year: {{items.FeesName}} |
+ Session: {{items.SessionName}} |
+ Session: {{items.SessionName}}/{{items.ToSessionName}} |
+ Univ: {{CUDetails.UniveShortName}} |
+
+
+ | Rupees In Words: {{amountInWords}} |
+
+
+ | RS.{{billAmount}} |
+
+ Cash / DD / Cheque: {{paymentType}}
+ Payable At/Base Branch: {{branchName}}
+ Received By: {{ReceivedBy}}
+ Date: {{billDate}} Place: {{branchName}}
+ |
+ For APOLLO DISTANCE EDUCATION COLLEGE |
+
+
+ | Note: Terms & Conditions will be applicable as per University norms Fees once paid will not be refunded at any reasons |
+
+
+
+
diff --git a/Apollo/assets/views/student/student_details.html b/Apollo/assets/views/student/student_details.html
index 68e861d1..d351cec7 100755
--- a/Apollo/assets/views/student/student_details.html
+++ b/Apollo/assets/views/student/student_details.html
@@ -96,7 +96,7 @@
Course
-
+
diff --git a/Apollo/assets/views/student/student_details_SuperAdmin.html b/Apollo/assets/views/student/student_details_SuperAdmin.html
index 265ebb3a..5a1543c0 100644
--- a/Apollo/assets/views/student/student_details_SuperAdmin.html
+++ b/Apollo/assets/views/student/student_details_SuperAdmin.html
@@ -137,7 +137,7 @@
Course
-
+
diff --git a/Apollo/bower_components/select2/dist/css/select2.css b/Apollo/bower_components/select2/dist/css/select2.css
index c69b7273..9218a6ca 100755
--- a/Apollo/bower_components/select2/dist/css/select2.css
+++ b/Apollo/bower_components/select2/dist/css/select2.css
@@ -8,7 +8,7 @@
box-sizing: border-box;
cursor: pointer;
display: block;
- height: 28px;
+ height: 34px;
user-select: none;
-webkit-user-select: none; }
.select2-container .select2-selection--single .select2-selection__rendered {
@@ -115,7 +115,7 @@
.select2-container--default .select2-selection--single {
background-color: #fff;
border: 1px solid #aaa;
- border-radius: 4px; }
+ border-radius: 0px; }
.select2-container--default .select2-selection--single .select2-selection__rendered {
color: #444;
line-height: 28px; }
diff --git a/Apollo/bower_components/ui-select2-master/.bowerrc b/Apollo/bower_components/ui-select2-master/.bowerrc
new file mode 100644
index 00000000..deceb62e
--- /dev/null
+++ b/Apollo/bower_components/ui-select2-master/.bowerrc
@@ -0,0 +1,3 @@
+{
+ "directory": "bower_components"
+}
\ No newline at end of file
diff --git a/Apollo/bower_components/ui-select2-master/.gitignore b/Apollo/bower_components/ui-select2-master/.gitignore
new file mode 100644
index 00000000..d8d73943
--- /dev/null
+++ b/Apollo/bower_components/ui-select2-master/.gitignore
@@ -0,0 +1,3 @@
+node_modules
+bower_components
+demo/bower_components
\ No newline at end of file
diff --git a/Apollo/bower_components/ui-select2-master/.jshintrc b/Apollo/bower_components/ui-select2-master/.jshintrc
new file mode 100644
index 00000000..1b83bfb4
--- /dev/null
+++ b/Apollo/bower_components/ui-select2-master/.jshintrc
@@ -0,0 +1,11 @@
+{
+ "curly": true,
+ "eqeqeq": true,
+ "immed": true,
+ "latedef": true,
+ "newcap": true,
+ "noarg": true,
+ "sub": true,
+ "boss": true,
+ "eqnull": true
+}
diff --git a/Apollo/bower_components/ui-select2-master/.travis.yml b/Apollo/bower_components/ui-select2-master/.travis.yml
new file mode 100644
index 00000000..ffa35634
--- /dev/null
+++ b/Apollo/bower_components/ui-select2-master/.travis.yml
@@ -0,0 +1,13 @@
+ language: node_js
+ node_js:
+ - "0.8"
+ - "0.10"
+
+ before_install:
+ - export DISPLAY=:99.0
+ - sh -e /etc/init.d/xvfb start
+ - npm install -g karma bower grunt-cli
+ - bower install
+ - npm install
+
+ script: "grunt"
diff --git a/Apollo/bower_components/ui-select2-master/CONTRIBUTING.md b/Apollo/bower_components/ui-select2-master/CONTRIBUTING.md
new file mode 100644
index 00000000..cb66f02b
--- /dev/null
+++ b/Apollo/bower_components/ui-select2-master/CONTRIBUTING.md
@@ -0,0 +1,8 @@
+CONTRIBUTING
+============
+
+* Open a [Pull Request (PR)](https://github.com/angular-ui/ui-select2/pull/new/master)
+* Make sure your PR is on a **new branch** you created off of the latest version of master
+* Do **not** open a PR from your master branch
+* Open a PR to start a discussion even if the code isn't finished (easier to collect feedback this way)
+* Make sure all previous tests pass and add new tests for added behaviors
diff --git a/Apollo/bower_components/ui-select2-master/Gruntfile.js b/Apollo/bower_components/ui-select2-master/Gruntfile.js
new file mode 100644
index 00000000..f2148422
--- /dev/null
+++ b/Apollo/bower_components/ui-select2-master/Gruntfile.js
@@ -0,0 +1,59 @@
+module.exports = function (grunt) {
+ 'use strict';
+
+ var initConfig;
+
+ // Loading external tasks
+ require('load-grunt-tasks')(grunt);
+
+ // Project configuration.
+ initConfig = {
+ bower: 'bower_components',
+ pkg: grunt.file.readJSON('package.json'),
+ watch: {
+ test: {
+ // Lint & run unit tests in Karma
+ // Just running `$ grunt watch` will only lint your code; to run tests
+ // on watch, use `$ grunt watch:karma` to start a Karma server first
+ files: ['src/select2.js', 'test/select2Spec.js'],
+ tasks: ['jshint', 'karma:unit:run']
+ }
+ },
+ karma: {
+ options: {
+ configFile: 'test/karma.conf.js',
+ browsers: ['Firefox', 'PhantomJS']
+ },
+ unit: {
+ singleRun: true
+ },
+ watch: {
+ autoWatch: true
+ },
+ server: {
+ background: true
+ }
+ },
+ jshint: {
+ all:[
+ 'gruntFile.js',
+ 'src/**/*.js',
+ 'test/**/*Spec.js'
+ ],
+ options: {
+ jshintrc: '.jshintrc'
+ }
+ },
+ changelog: {
+ options: {
+ dest: 'CHANGELOG.md'
+ }
+ }
+ };
+
+ // Register tasks
+ grunt.registerTask('default', ['jshint', 'karma:unit']);
+ grunt.registerTask('watch', ['jshint', 'karma:watch']);
+
+ grunt.initConfig(initConfig);
+};
diff --git a/Apollo/bower_components/ui-select2-master/LICENSE b/Apollo/bower_components/ui-select2-master/LICENSE
new file mode 100644
index 00000000..dfc5e0ca
--- /dev/null
+++ b/Apollo/bower_components/ui-select2-master/LICENSE
@@ -0,0 +1,21 @@
+The MIT License
+
+Copyright (c) 2012 the AngularUI Team, http://angular-ui.github.com
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
diff --git a/Apollo/bower_components/ui-select2-master/README.md b/Apollo/bower_components/ui-select2-master/README.md
new file mode 100644
index 00000000..7b32cb75
--- /dev/null
+++ b/Apollo/bower_components/ui-select2-master/README.md
@@ -0,0 +1,183 @@
+ui-select2 (deprecated) [](https://travis-ci.org/angular-ui/ui-select2)
+========================
+
+# Annoucement
+
+
+This **directive is now obsolete**. A new initiative, more active, and 100% angular is available at https://github.com/angular-ui/ui-select.
+
+As development slowed down on ui-select2, it is getting unlikely that bugs will be fixed. So the new alternative should be used as soon as possible.
+
+# Description
+
+This directive allows you to enhance your select elements with behaviour from the [select2](http://ivaynberg.github.io/select2/) library.
+
+# Requirements
+
+- [AngularJS](http://angularjs.org/)
+- [JQuery](http://jquery.com/)
+- [Select2](http://ivaynberg.github.io/select2/)
+
+## Setup
+
+1. Install **Karma**, **Grunt** and **Bower**
+ `$ npm install -g karma grunt-cli bower`
+2. Install development dependencies
+ `$ npm install`
+3. Install components
+ `$ bower install`
+4. ???
+5. Profit!
+
+## Testing
+
+We use [Grunt](http://gruntjs.com/) to check for JavaScript syntax errors and execute all unit tests. To run Grunt, simply execute:
+
+`$ grunt`
+
+This will lint and test the code, then exit. To have Grunt stay open and automatically lint and test your files whenever you make a code change, use:
+
+`$ grunt karma:server watch`
+
+This will start a Karma server in the background and run unit tests in Firefox and PhantomJS whenever the source code or spec file is saved.
+
+# Usage
+
+We use [bower](https://github.com/bower/bower) for dependency management. Install AngularUI Select2 into your project by running the command
+
+`$ bower install angular-ui-select2`
+
+If you use a `bower.json` file in your project, you can have Bower save ui-select2 as a dependency by passing the `--save` or `--save-dev` flag with the above command.
+
+This will copy the ui-select2 files into your `bower_components` folder, along with its dependencies. Load the script files in your application:
+```html
+
+
+
+
+
+```
+
+(Note that `jquery` must be loaded before `angular` so that it doesn't use `jqLite` internally)
+
+
+Add the select2 module as a dependency to your application module:
+
+```javascript
+var myAppModule = angular.module('MyApp', ['ui.select2']);
+```
+
+Apply the directive to your form elements:
+
+```html
+
+
+
+
+
+
+```
+
+## Options
+
+All the select2 options can be passed through the directive. You can read more about the supported list of options and what they do on the [Select2 Documentation Page](http://ivaynberg.github.com/select2/)
+
+```javascript
+myAppModule.controller('MyController', function($scope) {
+ $scope.select2Options = {
+ allowClear:true
+ };
+});
+```
+
+```html
+
+
+
+
+
+```
+
+Some times it may make sense to specify the options in the template file.
+
+```html
+
+
+
+
+
+```
+
+To define global defaults, you can configure the `uiSelect2Config` injectable:
+
+```javascript
+myAppModule.run(['uiSelect2Config', function(uiSelect2Config) {
+ uiSelect2Config.placeholder = "Placeholder text";
+}]);
+```
+
+## Working with ng-model
+
+The ui-select2 directive plays nicely with ng-model and validation directives such as ng-required.
+
+If you add the ng-model directive to same the element as ui-select2 then the picked option is automatically synchronized with the model value.
+
+## Working with dynamic options
+`ui-select2` is incompatible with ``. For the best results use `` tag at the top of the `` and either set a `data-placeholder` on the select element or pass a `placeholder` option to Select2.
+```html
+
+
+ First
+ Second
+ Third
+
+```
+
+## ng-required directive
+
+If you apply the required directive to element then the form element is invalid until an option is selected.
+
+Note: Remember that the ng-required directive must be explicitly set, i.e. to "true". This is especially true on divs:
+
+```html
+
+
+ First
+ Second
+ Third
+
+```
+
+## Using simple tagging mode
+
+When AngularJS View-Model tags are stored as a list of strings, setting
+the ui-select2 specific option `simple_tags` will allow to keep the model
+as a list of strings, and not convert it into a list of Select2 tag objects.
+
+```html
+
+```
+
+```javascript
+myAppModule.controller('MyController', function($scope) {
+ $scope.list_of_string = ['tag1', 'tag2']
+ $scope.select2Options = {
+ 'multiple': true,
+ 'simple_tags': true,
+ 'tags': ['tag1', 'tag2', 'tag3', 'tag4'] // Can be empty list.
+ };
+});
+```
diff --git a/Apollo/bower_components/ui-select2-master/bower.json b/Apollo/bower_components/ui-select2-master/bower.json
new file mode 100644
index 00000000..2cf5041e
--- /dev/null
+++ b/Apollo/bower_components/ui-select2-master/bower.json
@@ -0,0 +1,20 @@
+{
+ "author": "AngularUI",
+ "name": "angular-ui-select2",
+ "version": "0.0.5",
+ "homepage": "http://angular-ui.github.com",
+ "keywords": [
+ "angular",
+ "angularui",
+ "select2"
+ ],
+ "main": "./src/select2.js",
+ "dependencies": {
+ "angular": ">=1.2.0",
+ "select2": "~3.4",
+ "jquery": ">=1.6.4"
+ },
+ "devDependencies": {
+ "angular-mocks": ">=1.0.2"
+ }
+}
diff --git a/Apollo/bower_components/ui-select2-master/demo/app.js b/Apollo/bower_components/ui-select2-master/demo/app.js
new file mode 100644
index 00000000..7530204c
--- /dev/null
+++ b/Apollo/bower_components/ui-select2-master/demo/app.js
@@ -0,0 +1,114 @@
+
+var app = angular.module('angular-ui-select2-demo', ['ui.select2']);
+
+app.controller('MainCtrl', function ($scope, $element) {
+
+ var states = [
+ { text: 'Alaskan/Hawaiian Time Zone', children: [
+ { id: 'AK', text: 'Alaska' },
+ { id: 'HI', text: 'Hawaii' }
+ ]},
+ { text: 'Pacific Time Zone', children: [
+ { id: 'CA', text: 'California' },
+ { id: 'NV', text: 'Nevada' },
+ { id: 'OR', text: 'Oregon' },
+ { id: 'WA', text: 'Washington' }
+ ]},
+ { text: 'Mountain Time Zone', children: [
+ { id: 'AZ', text: 'Arizona' },
+ { id: 'CO', text: 'Colorado' },
+ { id: 'ID', text: 'Idaho' },
+ { id: 'MT', text: 'Montana' },
+ { id: 'NE', text: 'Nebraska' },
+ { id: 'NM', text: 'New Mexico' },
+ { id: 'ND', text: 'North Dakota' },
+ { id: 'UT', text: 'Utah' },
+ { id: 'WY', text: 'Wyoming' }
+ ]},
+ { text: 'Central Time Zone', children: [
+ { id: 'AL', text: 'Alabama' },
+ { id: 'AR', text: 'Arkansas' },
+ { id: 'IL', text: 'Illinois' },
+ { id: 'IA', text: 'Iowa' },
+ { id: 'KS', text: 'Kansas' },
+ { id: 'KY', text: 'Kentucky' },
+ { id: 'LA', text: 'Louisiana' },
+ { id: 'MN', text: 'Minnesota' },
+ { id: 'MS', text: 'Mississippi' },
+ { id: 'MO', text: 'Missouri' },
+ { id: 'OK', text: 'Oklahoma' },
+ { id: 'SD', text: 'South Dakota' },
+ { id: 'TX', text: 'Texas' },
+ { id: 'TN', text: 'Tennessee' },
+ { id: 'WI', text: 'Wisconsin' }
+ ]},
+ { text: 'Eastern Time Zone', children: [
+ { id: 'CT', text: 'Connecticut' },
+ { id: 'DE', text: 'Delaware' },
+ { id: 'FL', text: 'Florida' },
+ { id: 'GA', text: 'Georgia' },
+ { id: 'IN', text: 'Indiana' },
+ { id: 'ME', text: 'Maine' },
+ { id: 'MD', text: 'Maryland' },
+ { id: 'MA', text: 'Massachusetts' },
+ { id: 'MI', text: 'Michigan' },
+ { id: 'NH', text: 'New Hampshire' },
+ { id: 'NJ', text: 'New Jersey' },
+ { id: 'NY', text: 'New York' },
+ { id: 'NC', text: 'North Carolina' },
+ { id: 'OH', text: 'Ohio' },
+ { id: 'PA', text: 'Pennsylvania' },
+ { id: 'RI', text: 'Rhode Island' },
+ { id: 'SC', text: 'South Carolina' },
+ { id: 'VT', text: 'Vermont' },
+ { id: 'VA', text: 'Virginia' },
+ { id: 'WV', text: 'West Virginia' }
+ ]}
+ ];
+
+ function findState(id) {
+ for (var i=0; i=1.2.0",
+ "select2": "~3.4",
+ "jquery": ">=1.6.4",
+ "bootstrap": "~3.0.3",
+ "angular-ui-select2": "~0.0.5"
+ }
+}
diff --git a/Apollo/bower_components/ui-select2-master/demo/index.html b/Apollo/bower_components/ui-select2-master/demo/index.html
new file mode 100644
index 00000000..c7145a92
--- /dev/null
+++ b/Apollo/bower_components/ui-select2-master/demo/index.html
@@ -0,0 +1,225 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ The Basics
+
+
+
+
+
+
+
+
+
+
+
+
+
Value
+
{{ basicsValue }}
+
+
+
+
+
+ Multi-Value
+
+
+
+
+
+
+
Value
+
{{ multiValue }}
+
+
+
+
+
+
+
+
+
Config
+
{
+ multiple: true,
+ query: function (query) {
+ query.callback({ results: states });
+ },
+ initSelection: function(element, callback) {
+ var val = $(element).select2('val'),
+ results = [];
+ for (var i=0; i<val.length; i++) {
+ results.push(findState(val[i]));
+ }
+ callback(results);
+ }
+ }
+
Value
+
{{ multi2Value }}
+
+
+
+
+
+ Placeholders
+
+
+
+
+
+
+
Value
+
{{ placeholdersValue }}
+
+
+
+
+
+
+
+
+
Config
+
{{ placeholders }}
+
Value
+
{{ placeholdersMultiValue }}
+
+
+
+
+
+ Array Data
+
+
+
+
+
+
+
Config
+
{{ array }}
+
Value
+
{{ arrayValue }}
+
+
+
+
+
+
+
+
+
Config
+
{
+ query: function (query) {
+ query.callback({ results: states });
+ },
+ initSelection: function(element, callback) {
+ var val = $(element).select2('val');
+ return callback(findState(val));
+ }
+ }
+
Value
+
{{ arrayAsyncValue }}
+
+
+
+
+
+
+
diff --git a/Apollo/bower_components/ui-select2-master/docs/index.html b/Apollo/bower_components/ui-select2-master/docs/index.html
new file mode 100644
index 00000000..ff373e78
--- /dev/null
+++ b/Apollo/bower_components/ui-select2-master/docs/index.html
@@ -0,0 +1,47 @@
+
+
+
+
+
Demo
+
+
+
+
Value is: {{select2multiple}} (choose second)
+
+ First
+ Second
+ Third
+
+
+
+
+
Options
+
You can pass an object to Select2 as the expression: ui-select2="{allowClear:true}" that will be passed directly to $.fn.select2(). You can read more about the supported list of options and what they do on the Select2 Documentation Page. AngularUI will leverage properties passed to Select2 for any complex behavior, there are no parameters necessary for that are specific to AngularUI.
+
+
+ ui-select2 is incompatible with <select ng-options>. For the best results use <option ng-repeat> instead
+ In order to properly support the Select2 placeholder, create an empty <option> tag at the top of the <select> and either set a data-placeholder on the select element or pass a placeholder option to Select2.
+
+ How?
+
+<p>Value is: {{select2}} <a ng-click="select2='two'">(choose second)</a></p>
+<select ui-select2 ng-model="select2">
+<option value="">Pick a number</option>
+<option value="one">First</option>
+<option value="two">Second</option>
+<option value="three">Third</option>
+</select>
+
+Or try playing around with this sandbox demo to see how AJAX works
+
\ No newline at end of file
diff --git a/Apollo/bower_components/ui-select2-master/docs/styles.css b/Apollo/bower_components/ui-select2-master/docs/styles.css
new file mode 100644
index 00000000..08611a47
--- /dev/null
+++ b/Apollo/bower_components/ui-select2-master/docs/styles.css
@@ -0,0 +1,4 @@
+
+#directives-select2 select {
+ width: 200px;
+}
\ No newline at end of file
diff --git a/Apollo/bower_components/ui-select2-master/package.json b/Apollo/bower_components/ui-select2-master/package.json
new file mode 100644
index 00000000..9b831360
--- /dev/null
+++ b/Apollo/bower_components/ui-select2-master/package.json
@@ -0,0 +1,30 @@
+{
+ "author": "https://github.com/angular-ui/ui-select2/graphs/contributors",
+ "name": "angular-ui-select2",
+ "keywords": [
+ "angular",
+ "angularui",
+ "select2"
+ ],
+ "description": "AngularUI - The companion suite for AngularJS",
+ "version": "0.0.5",
+ "homepage": "http://angular-ui.github.com",
+ "repository": {
+ "type": "git",
+ "url": "git://github.com/angular-ui/ui-select2.git"
+ },
+ "engines": {
+ "node": ">= 0.8.4"
+ },
+ "dependencies": {},
+ "devDependencies": {
+ "async": "0.1.x",
+ "grunt": "~0.4.1",
+ "grunt-contrib-jshint": "~0.6.4",
+ "grunt-contrib-watch": "~0.5.3",
+ "grunt-karma": "~0.6.2",
+ "karma": "~0.10.2",
+ "grunt-conventional-changelog": "~1.0.0",
+ "load-grunt-tasks": "~0.2.0"
+ }
+}
diff --git a/Apollo/bower_components/ui-select2-master/src/select2.js b/Apollo/bower_components/ui-select2-master/src/select2.js
new file mode 100644
index 00000000..c3b99ae9
--- /dev/null
+++ b/Apollo/bower_components/ui-select2-master/src/select2.js
@@ -0,0 +1,238 @@
+/**
+ * Enhanced Select2 Dropmenus
+ *
+ * @AJAX Mode - When in this mode, your value will be an object (or array of objects) of the data used by Select2
+ * This change is so that you do not have to do an additional query yourself on top of Select2's own query
+ * @params [options] {object} The configuration options passed to $.fn.select2(). Refer to the documentation
+ */
+angular.module('ui.select2', []).value('uiSelect2Config', {}).directive('uiSelect2', ['uiSelect2Config', '$timeout', function (uiSelect2Config, $timeout) {
+ var options = {};
+ if (uiSelect2Config) {
+ angular.extend(options, uiSelect2Config);
+ }
+ return {
+ require: 'ngModel',
+ priority: 1,
+ compile: function (tElm, tAttrs) {
+ var watch,
+ repeatOption,
+ repeatAttr,
+ isSelect = tElm.is('select'),
+ isMultiple = angular.isDefined(tAttrs.multiple);
+
+ // Enable watching of the options dataset if in use
+ if (tElm.is('select')) {
+ repeatOption = tElm.find( 'optgroup[ng-repeat], optgroup[data-ng-repeat], option[ng-repeat], option[data-ng-repeat]');
+
+ if (repeatOption.length) {
+ repeatAttr = repeatOption.attr('ng-repeat') || repeatOption.attr('data-ng-repeat');
+ watch = jQuery.trim(repeatAttr.split('|')[0]).split(' ').pop();
+ }
+ }
+
+ return function (scope, elm, attrs, controller) {
+ // instance-specific options
+ var opts = angular.extend({}, options, scope.$eval(attrs.uiSelect2));
+
+ /*
+ Convert from Select2 view-model to Angular view-model.
+ */
+ var convertToAngularModel = function(select2_data) {
+ var model;
+ if (opts.simple_tags) {
+ model = [];
+ angular.forEach(select2_data, function(value, index) {
+ model.push(value.id);
+ });
+ } else {
+ model = select2_data;
+ }
+ return model;
+ };
+
+ /*
+ Convert from Angular view-model to Select2 view-model.
+ */
+ var convertToSelect2Model = function(angular_data) {
+ var model = [];
+ if (!angular_data) {
+ return model;
+ }
+
+ if (opts.simple_tags) {
+ model = [];
+ angular.forEach(
+ angular_data,
+ function(value, index) {
+ model.push({'id': value, 'text': value});
+ });
+ } else {
+ model = angular_data;
+ }
+ return model;
+ };
+
+ if (isSelect) {
+ // Use instead
+ delete opts.multiple;
+ delete opts.initSelection;
+ } else if (isMultiple) {
+ opts.multiple = true;
+ }
+
+ if (controller) {
+ // Watch the model for programmatic changes
+ scope.$watch(tAttrs.ngModel, function(current, old) {
+ if (!current) {
+ return;
+ }
+ if (current === old) {
+ return;
+ }
+ controller.$render();
+ }, true);
+ controller.$render = function () {
+ if (isSelect) {
+ elm.select2('val', controller.$viewValue);
+ } else {
+ if (opts.multiple) {
+ controller.$isEmpty = function (value) {
+ return !value || value.length === 0;
+ };
+ var viewValue = controller.$viewValue;
+ if (angular.isString(viewValue)) {
+ viewValue = viewValue.split(',');
+ }
+ elm.select2(
+ 'data', convertToSelect2Model(viewValue));
+ if (opts.sortable) {
+ elm.select2("container").find("ul.select2-choices").sortable({
+ containment: 'parent',
+ start: function () {
+ elm.select2("onSortStart");
+ },
+ update: function () {
+ elm.select2("onSortEnd");
+ elm.trigger('change');
+ }
+ });
+ }
+ } else {
+ if (angular.isObject(controller.$viewValue)) {
+ elm.select2('data', controller.$viewValue);
+ } else if (!controller.$viewValue) {
+ elm.select2('data', null);
+ } else {
+ elm.select2('val', controller.$viewValue);
+ }
+ }
+ }
+ };
+
+ // Watch the options dataset for changes
+ if (watch) {
+ scope.$watch(watch, function (newVal, oldVal, scope) {
+ if (angular.equals(newVal, oldVal)) {
+ return;
+ }
+ // Delayed so that the options have time to be rendered
+ $timeout(function () {
+ elm.select2('val', controller.$viewValue);
+ // Refresh angular to remove the superfluous option
+ controller.$render();
+ if(newVal && !oldVal && controller.$setPristine) {
+ controller.$setPristine(true);
+ }
+ });
+ });
+ }
+
+ // Update valid and dirty statuses
+ controller.$parsers.push(function (value) {
+ var div = elm.prev();
+ div
+ .toggleClass('ng-invalid', !controller.$valid)
+ .toggleClass('ng-valid', controller.$valid)
+ .toggleClass('ng-invalid-required', !controller.$valid)
+ .toggleClass('ng-valid-required', controller.$valid)
+ .toggleClass('ng-dirty', controller.$dirty)
+ .toggleClass('ng-pristine', controller.$pristine);
+ return value;
+ });
+
+ if (!isSelect) {
+ // Set the view and model value and update the angular template manually for the ajax/multiple select2.
+ elm.bind("change", function (e) {
+ e.stopImmediatePropagation();
+
+ if (scope.$$phase || scope.$root.$$phase) {
+ return;
+ }
+ scope.$apply(function () {
+ controller.$setViewValue(
+ convertToAngularModel(elm.select2('data')));
+ });
+ });
+
+ if (opts.initSelection) {
+ var initSelection = opts.initSelection;
+ opts.initSelection = function (element, callback) {
+ initSelection(element, function (value) {
+ var isPristine = controller.$pristine;
+ controller.$setViewValue(convertToAngularModel(value));
+ callback(value);
+ if (isPristine) {
+ controller.$setPristine();
+ }
+ elm.prev().toggleClass('ng-pristine', controller.$pristine);
+ });
+ };
+ }
+ }
+ }
+
+ elm.bind("$destroy", function() {
+ elm.select2("destroy");
+ });
+
+ attrs.$observe('disabled', function (value) {
+ elm.select2('enable', !value);
+ });
+
+ attrs.$observe('readonly', function (value) {
+ elm.select2('readonly', !!value);
+ });
+
+ if (attrs.ngMultiple) {
+ scope.$watch(attrs.ngMultiple, function(newVal) {
+ attrs.$set('multiple', !!newVal);
+ elm.select2(opts);
+ });
+ }
+
+ // Initialize the plugin late so that the injected DOM does not disrupt the template compiler
+ $timeout(function () {
+ elm.select2(opts);
+
+ // Set initial value - I'm not sure about this but it seems to need to be there
+ elm.select2('data', controller.$modelValue);
+ // important!
+ controller.$render();
+
+ // Not sure if I should just check for !isSelect OR if I should check for 'tags' key
+ if (!opts.initSelection && !isSelect) {
+ var isPristine = controller.$pristine;
+ controller.$pristine = false;
+ controller.$setViewValue(
+ convertToAngularModel(elm.select2('data'))
+ );
+ if (isPristine) {
+ controller.$setPristine();
+ }
+ elm.prev().toggleClass('ng-pristine', controller.$pristine);
+ }
+ });
+ };
+ }
+ };
+}]);
diff --git a/Apollo/bower_components/ui-select2-master/test/karma.conf.js b/Apollo/bower_components/ui-select2-master/test/karma.conf.js
new file mode 100644
index 00000000..d5f21b3e
--- /dev/null
+++ b/Apollo/bower_components/ui-select2-master/test/karma.conf.js
@@ -0,0 +1,80 @@
+// Karma configuration
+// Generated on Tue Sep 17 2013 06:59:46 GMT-0400 (EDT)
+
+module.exports = function(config) {
+ config.set({
+
+ // base path, that will be used to resolve files and exclude
+ basePath: '..',
+
+
+ // frameworks to use
+ frameworks: ['jasmine'],
+
+
+ // list of files / patterns to load in the browser
+ files: [
+ // Dependencies
+ 'bower_components/jquery/dist/jquery.js',
+ 'bower_components/angular/angular.js',
+ 'bower_components/angular-mocks/angular-mocks.js',
+ 'bower_components/select2/select2.js',
+
+ // Source Code
+ 'src/select2.js',
+
+ // Test Specs
+ 'test/*Spec.js'
+ ],
+
+
+ // list of files to exclude
+ exclude: [
+
+ ],
+
+
+ // test results reporter to use
+ // possible values: 'dots', 'progress', 'junit', 'growl', 'coverage'
+ reporters: ['progress'],
+
+
+ // web server port
+ port: 9876,
+
+
+ // enable / disable colors in the output (reporters and logs)
+ colors: true,
+
+
+ // level of logging
+ // possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
+ logLevel: config.LOG_INFO,
+
+
+ // enable / disable watching file and executing tests whenever any file changes
+ autoWatch: false,
+
+
+ // Start these browsers, currently available:
+ // - Chrome
+ // - ChromeCanary
+ // - Firefox
+ // - Opera
+ // - Safari (only Mac)
+ // - PhantomJS
+ // - IE (only Windows)
+ browsers: ['Chrome', 'Firefox'],
+
+
+ // If browser does not capture in given timeout [ms], kill it
+ captureTimeout: 60000,
+
+
+ // Continuous Integration mode
+ // if true, it capture browsers, run tests and exit
+ singleRun: false
+
+
+ });
+};
diff --git a/Apollo/bower_components/ui-select2-master/test/select2Spec.js b/Apollo/bower_components/ui-select2-master/test/select2Spec.js
new file mode 100644
index 00000000..8c5c27dd
--- /dev/null
+++ b/Apollo/bower_components/ui-select2-master/test/select2Spec.js
@@ -0,0 +1,411 @@
+// a helper directive for injecting formatters and parsers
+angular.module('ui.select2').directive('injectTransformers', [ function () {
+ return {
+ restrict: 'A',
+ require: 'ngModel',
+ priority: -1,
+ link: function (scope, element, attr, ngModel) {
+ var local = scope.$eval(attr.injectTransformers);
+
+ if (!angular.isObject(local) || !angular.isFunction(local.fromModel) || !angular.isFunction(local.fromElement)) {
+ throw "The injectTransformers directive must be bound to an object with two functions (`fromModel` and `fromElement`)";
+ }
+
+ ngModel.$parsers.push(local.fromElement);
+ ngModel.$formatters.push(local.fromModel);
+ }
+ };
+}]);
+
+/*global describe, beforeEach, module, inject, it, spyOn, expect, $ */
+describe('uiSelect2', function () {
+ 'use strict';
+
+ var scope, $compile, options, $timeout;
+ beforeEach(module('ui.select2'));
+ beforeEach(inject(function (_$rootScope_, _$compile_, _$window_, _$timeout_) {
+ scope = _$rootScope_.$new();
+ $compile = _$compile_;
+ $timeout = _$timeout_;
+ scope.options = {
+ query: function (query) {
+ var data = {
+ results: [{ id: 1, text: 'first' }]
+ };
+ query.callback(data);
+ }
+ };
+
+ scope.transformers = {
+ fromModel: function (modelValue) {
+ if (!modelValue) {
+ return modelValue;
+ }
+
+ if (angular.isArray(modelValue)) {
+ return modelValue.map(function (val) {
+ val.text += " - I've been formatted";
+ return val;
+ });
+ }
+
+ if (angular.isObject(modelValue)) {
+ modelValue.text += " - I've been formatted";
+ return modelValue;
+ }
+
+ return modelValue + " - I've been formatted";
+ },
+ fromElement: function (elementValue) {
+ var suffix = " - I've been formatted";
+
+ if (!elementValue) {
+ return elementValue;
+ }
+
+ if (angular.isArray(elementValue)) {
+ return elementValue.map(function (val) {
+ val.text += val.text.slice(0, val.text.indexOf(" - I've been formatted"));
+ return val;
+ });
+ }
+
+ if (angular.isObject(elementValue)) {
+ elementValue.text = elementValue.text.slice(0, elementValue.text.indexOf(suffix));
+ return elementValue;
+ }
+
+ if (elementValue) {
+ return elementValue.slice(0, elementValue.indexOf(suffix));
+ }
+
+ return undefined;
+ }
+ };
+ }));
+
+ /**
+ * Compile a template synchronously
+ * @param {String} template The string to compile
+ * @return {Object} A reference to the compiled template
+ */
+ function compile(template) {
+ var element = $compile(template)(scope);
+ scope.$apply();
+ $timeout.flush();
+ return element;
+ }
+
+ describe('with a element', function () {
+ describe('compiling this directive', function () {
+ it('should throw an error if we have no model defined', function () {
+ expect(function(){
+ compile('');
+ }).toThrow();
+ });
+ it('should create proper DOM structure', function () {
+ var element = compile('');
+ expect(element.siblings().is('div.select2-container')).toBe(true);
+ });
+ it('should not modify the model if there is no initial value', function(){
+ //TODO
+ });
+ });
+ describe('when model is changed programmatically', function(){
+ describe('for single select', function(){
+ it('should set select2 to the value', function(){
+ scope.foo = 'First';
+ var element = compile('FirstSecond');
+ expect(element.select2('val')).toBe('First');
+ scope.$apply('foo = "Second"');
+ expect(element.select2('val')).toBe('Second');
+ });
+ it('should handle falsey values', function(){
+ scope.foo = 'First';
+ var element = compile('FirstSecond');
+ expect(element.select2('val')).toBe('First');
+ scope.$apply('foo = false');
+ expect(element.select2('val')).toBe(null);
+ scope.$apply('foo = "Second"');
+ scope.$apply('foo = null');
+ expect(element.select2('val')).toBe(null);
+ scope.$apply('foo = "Second"');
+ scope.$apply('foo = undefined');
+ expect(element.select2('val')).toBe(null);
+ });
+ });
+ describe('for multiple select', function(){
+ it('should set select2 to multiple value', function(){
+ scope.foo = ['First'];
+ var element = compile('FirstSecondThird');
+ expect(element.select2('val')).toEqual(['First']);
+ scope.$apply('foo = ["Second"]');
+ expect(element.select2('val')).toEqual(['Second']);
+ scope.$apply('foo = ["Second","Third"]');
+ expect(element.select2('val')).toEqual(['Second','Third']);
+ });
+ it('should handle falsey values', function(){
+ scope.foo = ['First'];
+ var element = compile('FirstSecondThird');
+ expect(element.val()).toEqual(['First']);
+ scope.$apply('foo = ["Second"]');
+ scope.$apply('foo = false');
+ expect(element.select2('val')).toEqual([]);
+ scope.$apply('foo = ["Second"]');
+ scope.$apply('foo = null');
+ expect(element.select2('val')).toEqual([]);
+ scope.$apply('foo = ["Second"]');
+ scope.$apply('foo = undefined');
+ expect(element.select2('val')).toEqual([]);
+ });
+ });
+ });
+ it('should observe the disabled attribute', function () {
+ var element = compile('');
+ expect(element.siblings().hasClass('select2-container-disabled')).toBe(false);
+ scope.$apply('disabled = true');
+ expect(element.siblings().hasClass('select2-container-disabled')).toBe(true);
+ scope.$apply('disabled = false');
+ expect(element.siblings().hasClass('select2-container-disabled')).toBe(false);
+ });
+ it('should observe the multiple attribute', function () {
+ var element = $compile('')(scope);
+
+ expect(element.siblings().hasClass('select2-container-multi')).toBe(false);
+ scope.$apply('multiple = true');
+ expect(element.siblings().hasClass('select2-container-multi')).toBe(true);
+ scope.$apply('multiple = false');
+ expect(element.siblings().hasClass('select2-container-multi')).toBe(false);
+ });
+ it('should observe an option with ng-repeat for changes', function(){
+ scope.items = ['first', 'second', 'third'];
+ scope.foo = 'fourth';
+ var element = compile('{{item}}');
+ expect(element.select2('val')).toBe(null);
+ scope.$apply('foo="fourth";items=["fourth"]');
+ $timeout.flush();
+ expect(element.select2('val')).toBe('fourth');
+ });
+ });
+ describe('with an element', function () {
+ describe('compiling this directive', function () {
+ it('should throw an error if we have no model defined', function () {
+ expect(function() {
+ compile('');
+ }).toThrow();
+ });
+ it('should create proper DOM structure', function () {
+ var element = compile('');
+ expect(element.siblings().is('div.select2-container')).toBe(true);
+ });
+ it('should not modify the model if there is no initial value', function(){
+ //TODO
+ });
+ });
+ describe('when model is changed programmatically', function(){
+ describe('for single-select', function(){
+ it('should call select2(data, ...) for objects', function(){
+ var element = compile('');
+ spyOn($.fn, 'select2');
+ scope.$apply('foo={ id: 1, text: "first" }');
+ expect(element.select2).toHaveBeenCalledWith('data', { id: 1, text: "first" });
+ });
+ it('should call select2(val, ...) for strings', function(){
+ var element = compile('');
+ spyOn($.fn, 'select2');
+ scope.$apply('foo="first"');
+ expect(element.select2).toHaveBeenCalledWith('val', 'first');
+ });
+ });
+ describe('for multi-select', function(){
+ it('should call select2(data, ...) for arrays', function(){
+ var element = compile('');
+ spyOn($.fn, 'select2');
+ scope.$apply('foo=[{ id: 1, text: "first" },{ id: 2, text: "second" }]');
+ expect(element.select2).toHaveBeenCalledWith('data', [{ id: 1, text: "first" },{ id: 2, text: "second" }]);
+ });
+ it('should call select2(data, []) for falsey values', function(){
+ var element = compile('');
+ spyOn($.fn, 'select2');
+ scope.$apply('foo=[]');
+ expect(element.select2).toHaveBeenCalledWith('data', []);
+ });
+ xit('should call select2(val, ...) for strings', function(){
+ var element = compile('');
+ spyOn($.fn, 'select2');
+ scope.$apply('foo="first,second"');
+ expect(element.select2).toHaveBeenCalledWith('val', 'first,second');
+ });
+ });
+ });
+ describe('consumers of ngModel should correctly use $viewValue', function() {
+ it('should use any formatters if present (select - single select)', function(){
+ scope.foo = 'First';
+ var element = compile('First - I\'ve been formattedSecond - I\'ve been formatted');
+ expect(element.select2('val')).toBe('First - I\'ve been formatted');
+ scope.$apply('foo = "Second"');
+ expect(element.select2('val')).toBe('Second - I\'ve been formatted');
+ });
+
+ // isMultiple && falsey
+ it('should use any formatters if present (input multi select - falsey value)', function() {
+ // need special function to hit this case
+ // old code checked modelValue... can't just pass undefined to model value because view value will be the same
+ scope.transformers.fromModel = function(modelValue) {
+ if (modelValue === "magic") {
+ return undefined;
+ }
+
+ return modelValue;
+ };
+
+ var element = compile('');
+ spyOn($.fn, 'select2');
+ scope.$apply('foo="magic"');
+ expect(element.select2).toHaveBeenCalledWith('data', []);
+ });
+ // isMultiple && isArray
+ it('should use any formatters if present (input multi select)', function() {
+ var element = compile('');
+ spyOn($.fn, 'select2');
+ scope.$apply('foo=[{ id: 1, text: "first" },{ id: 2, text: "second" }]');
+ expect(element.select2).toHaveBeenCalledWith('data', [{ id: 1, text: "first - I've been formatted" },{ id: 2, text: "second - I've been formatted" }]);
+ });
+ // isMultiple...
+ xit('should use any formatters if present (input multi select - non array)', function() {
+ var element = compile('');
+ spyOn($.fn, 'select2');
+ scope.$apply('foo={ id: 1, text: "first" }');
+ expect(element.select2).toHaveBeenCalledWith('val', { id: 1, text: "first - I've been formatted" });
+ });
+
+ // !isMultiple
+ it('should use any formatters if present (input - single select - object)', function() {
+ var element = compile('');
+ spyOn($.fn, 'select2');
+ scope.$apply('foo={ id: 1, text: "first" }');
+ expect(element.select2).toHaveBeenCalledWith('data', { id: 1, text: "first - I've been formatted" });
+ });
+ it('should use any formatters if present (input - single select - non object)', function() {
+ var element = compile('');
+ spyOn($.fn, 'select2');
+ scope.$apply('foo="first"');
+ expect(element.select2).toHaveBeenCalledWith('val', "first - I've been formatted");
+ });
+
+ it('should not set the default value using scope.$eval', function() {
+ // testing directive instantiation - change order of test
+ spyOn($.fn, 'select2');
+ spyOn($.fn, 'val');
+ scope.$apply('foo=[{ id: 1, text: "first" },{ id: 2, text: "second" }]');
+
+ var element = compile('');
+ expect(element.val).not.toHaveBeenCalledWith([{ id: 1, text: "first" },{ id: 2, text: "second" }]);
+ });
+ it('should expect a default value to be set with a call to the render method', function() {
+ // this should monitor the events after init, when the timeout callback executes
+ var opts = angular.copy(scope.options);
+ opts.multiple = true;
+
+ scope.$apply('foo=[{ id: 1, text: "first" },{ id: 2, text: "second" }]');
+
+ spyOn($.fn, 'select2');
+ var element = compile('');
+
+ // select 2 init
+ expect(element.select2).toHaveBeenCalledWith(opts);
+
+ // callback setting
+ expect(element.select2).toHaveBeenCalledWith('data', [{ id: 1, text: "first - I've been formatted" },{ id: 2, text: "second - I've been formatted" }]);
+
+ // retieve data
+ expect(element.select2).toHaveBeenCalledWith('data');
+ });
+
+ });
+ it('should set the model when the user selects an item', function(){
+ var element = compile('');
+ // TODO: programmactically select an option
+ // expect(scope.foo).toBe(/* selected val */) ;
+ });
+
+ it('updated the view when model changes with complex object', function(){
+ scope.foo = [{'id': '0', 'text': '0'}];
+ scope.options['multiple'] = true;
+ var element = compile('');
+ scope.$digest();
+
+ scope.foo.push({'id': '1', 'text': '1'});
+ scope.$digest();
+
+ expect(element.select2('data')).toEqual(
+ [{'id': '0', 'text': '0'}, {'id': '1', 'text': '1'}]);
+ });
+
+
+ describe('simple_tags', function() {
+
+ beforeEach(function() {
+ scope.options['multiple'] = true;
+ scope.options['simple_tags'] = true;
+ scope.options['tags'] = [];
+ });
+
+ it('Initialize the select2 view based on list of strings.', function() {
+ scope.foo = ['tag1', 'tag2'];
+
+ var element = compile('');
+ scope.$digest();
+
+ expect(element.select2('data')).toEqual([
+ {'id': 'tag1', 'text': 'tag1'},
+ {'id': 'tag2', 'text': 'tag2'}
+ ]);
+ });
+
+ it(
+ 'When list is empty select2 view model is also initialized as empty',
+ function() {
+ scope.foo = [];
+
+ var element = compile('');
+ scope.$digest();
+
+ expect(element.select2('data')).toEqual([]);
+ });
+
+ it(
+ 'Updating the model with a string will update the select2 view model.',
+ function() {
+ scope.foo = [];
+ var element = compile('');
+ scope.$digest();
+
+ scope.foo.push('tag1');
+ scope.$digest();
+
+ expect(element.select2('data')).toEqual([
+ {'id': 'tag1', 'text': 'tag1'}
+ ]);
+ });
+
+ it(
+ 'Updating the select2 model will update AngularJS model with a string.',
+ function() {
+ scope.foo = [];
+ var element = compile('');
+ scope.$digest();
+
+ element.select2('data', [
+ {'id':'tag1', 'text': 'tag1'},
+ {'id':'tag2', 'text': 'tag2'}
+ ]);
+ element.trigger('change');
+
+ expect(scope.foo).toEqual(['tag1', 'tag2']);
+ });
+
+ });
+
+ });
+});
\ No newline at end of file
diff --git a/Apollo/index.html b/Apollo/index.html
index e6a74cba..d1e01780 100755
--- a/Apollo/index.html
+++ b/Apollo/index.html
@@ -25,6 +25,8 @@
+
+
@@ -65,6 +67,9 @@
+
+
+