From bc4f6c99d83d65b92e157dbbb662762f946962d5 Mon Sep 17 00:00:00 2001 From: thangngoc89 Date: Tue, 30 Dec 2014 22:46:05 +0700 Subject: [PATCH 01/19] Require package and add RESTful API route --- app/routes.php | 13 +++++++++++++ composer.json | 6 ++++-- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/app/routes.php b/app/routes.php index 8cd8f79a7..fa41762bb 100755 --- a/app/routes.php +++ b/app/routes.php @@ -30,6 +30,19 @@ Route::pattern('role', '[0-9]+'); Route::pattern('token', '[0-9a-z]+'); +/* + ** ----------------------------------------- + * RESTful API route + * ------------------------------------------ + */ + +Route::group(array('prefix' => 'api/v2'), function() +{ + Route::resource('users', 'UserV2Controller'); + Route::resource('roles', 'RolesV2Controller'); + Route::resource('permissions', 'PermissionV2Controller'); +}); + /** ------------------------------------------ * Admin Routes * ------------------------------------------ diff --git a/composer.json b/composer.json index 85cbc8d79..7bc1d4dd8 100755 --- a/composer.json +++ b/composer.json @@ -13,14 +13,16 @@ "laravel/framework": "~4.2", "zizaco/confide": "~4.0", "zizaco/entrust": "1.2.*", - "bllim/datatables": "~1.3" + "bllim/datatables": "~1.3", + "marcelgwerder/laravel-api-handler": "0.4.*" }, "require-dev": { "way/generators": "~2.6", "phpunit/phpunit": "~4.0", "mockery/mockery": "~0.9", "summerstreet/woodling": "~0.1.6", - "barryvdh/laravel-ide-helper": "~1.11" + "barryvdh/laravel-ide-helper": "~1.11", + "barryvdh/laravel-debugbar": "~1.8@dev" }, "autoload": { "classmap": [ From cfa64dc8ec7e0654407f2a54b215844922470170 Mon Sep 17 00:00:00 2001 From: thangngoc89 Date: Tue, 30 Dec 2014 22:48:36 +0700 Subject: [PATCH 02/19] CSRF token checking for ajax request --- app/filters.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/filters.php b/app/filters.php index 0aa293cf8..53dc318fe 100755 --- a/app/filters.php +++ b/app/filters.php @@ -93,7 +93,7 @@ Route::filter('csrf', function() { - if (Session::getToken() !== Input::get('csrf_token') && Session::getToken() !== Input::get('_token')) + if (Session::getToken() !== Input::get('csrf_token') && Session::getToken() !== Input::get('_token' ) && Session::getToken() !== Request::header('x-csrf-token')) { throw new Illuminate\Session\TokenMismatchException; } From 44b30ae8fd2c9844f13264c8ef753aed9940a3e2 Mon Sep 17 00:00:00 2001 From: thangngoc89 Date: Tue, 30 Dec 2014 22:50:23 +0700 Subject: [PATCH 03/19] Add one-to-many relationship to models --- app/models/AssignedRoles.php | 3 +++ app/models/Permission.php | 3 +++ app/models/Role.php | 6 ++++++ 3 files changed, 12 insertions(+) diff --git a/app/models/AssignedRoles.php b/app/models/AssignedRoles.php index 060d6d9d0..34c80b8a9 100644 --- a/app/models/AssignedRoles.php +++ b/app/models/AssignedRoles.php @@ -5,5 +5,8 @@ class AssignedRoles extends Eloquent { public static $rules = array(); + public function role() { + return $this->belongsTo('Role'); + } } \ No newline at end of file diff --git a/app/models/Permission.php b/app/models/Permission.php index cfdeb81ee..0fff14db1 100644 --- a/app/models/Permission.php +++ b/app/models/Permission.php @@ -4,6 +4,9 @@ class Permission extends EntrustPermission { + public function role(){ + return $this->belongsTo('Role'); + } public function preparePermissionsForDisplay($permissions) { // Get all the available permissions diff --git a/app/models/Role.php b/app/models/Role.php index 6f435fa40..9f28e74e1 100644 --- a/app/models/Role.php +++ b/app/models/Role.php @@ -20,4 +20,10 @@ public function validateRoles( array $roles ) } return $roleValidation; } + public function assigned_role() { + return $this->hasMany('AssignedRoles'); + } + public function permission() { + return $this->hasMany('Permission'); + } } \ No newline at end of file From e1686067c43101af9d0d5e0a5cc82907477b1e7b Mon Sep 17 00:00:00 2001 From: thangngoc89 Date: Tue, 30 Dec 2014 22:54:26 +0700 Subject: [PATCH 04/19] Copy User/Permission/Role API Controller from project --- app/controllers/api/APIController.php | 57 +++++++ .../api/PermissionV2Controller.php | 113 ++++++++++++++ app/controllers/api/RolesV2Controller.php | 144 ++++++++++++++++++ app/controllers/api/UserV2Controller.php | 103 +++++++++++++ 4 files changed, 417 insertions(+) create mode 100644 app/controllers/api/APIController.php create mode 100644 app/controllers/api/PermissionV2Controller.php create mode 100644 app/controllers/api/RolesV2Controller.php create mode 100644 app/controllers/api/UserV2Controller.php diff --git a/app/controllers/api/APIController.php b/app/controllers/api/APIController.php new file mode 100644 index 000000000..1a2c42572 --- /dev/null +++ b/app/controllers/api/APIController.php @@ -0,0 +1,57 @@ + 10, + '_offset' => 0, + ]; + // If have _sort is a valid column + if (in_array(Input::get('_sort'), $columns)) + { + // Default sortDir is ASC + $sortDir = (!empty(Input::get('_sortDir'))) ? Input::get('_sortDir') : 'ASC'; + // ASC --> null DESC --> - + $sort = ($sortDir === 'ASC' ) ? '' : '-'; + $sort .= Input::get('_sort'); + $params ['_sort'] = $sort; + } + if (!empty(Input::get('page')) && !empty(Input::get('per_page'))) + { + $params['_limit'] = Input::get('per_page'); + $params['_offset'] = (Input::get('page') - 1)*Input::get('per_page'); + } + if (!empty(Input::get('q')) && Input::get('q') != '{}') + { + $query = json_decode(Input::get('q')); + $params['_q'] = $query->query; + } + + foreach ($columns as $column) + { + // Use strlen == 0 instead of !empty to prevent boolean filter broken + if (strlen(Input::get($column)) != 0) + { + $params[$column] = Input::get($column); + } + } + $params ['_config'] = 'meta-filter-count'; + return $params; + } + public function makeResponse($response,$statusCode, $builder){ + return Response::json($response,$statusCode)->header('X-Total-Count', $builder->getHeaders()['Meta-Filter-Count']); + } +} \ No newline at end of file diff --git a/app/controllers/api/PermissionV2Controller.php b/app/controllers/api/PermissionV2Controller.php new file mode 100644 index 000000000..239ab8857 --- /dev/null +++ b/app/controllers/api/PermissionV2Controller.php @@ -0,0 +1,113 @@ +permission = $permission; + } + public function index() + { + + try{ + $statusCode = 200; + // dd($this->passParams('tests')); + $builder = ApiHandler::parseMultiple($this->permission, array(''), $this->passParams('permissions')); + $objects = $builder->getResult(); + + $response = []; + foreach($objects as $object){ + $response[] = $this->responseMap($object); + } + return $this->makeResponse($response,$statusCode, $builder); + }catch (Exception $e){ + $statusCode = 500; + $message = $e->getMessage(); + return Response::json($message, $statusCode); + } + } + + /** + * Store a newly created resource in storage. + * + * @return Response + */ + public function store() + { + // + } + + /** + * Display the specified resource. + * + * @param int $id + * @return Response + */ + public function show($id) + { + try{ + $statusCode = 200; + $test = $this->permission->find($id); + + $response = $this->responseMap($test); + + return Response::json($response, $statusCode); + }catch (Exception $e){ + $statusCode = 500; + return Response::json($e->getMessage(), $statusCode); + } + } + + + /** + * Show the form for editing the specified resource. + * + * @param int $id + * @return Response + */ + public function edit($id) + { + dd(Input::all()); + } + + /** + * Update the specified resource in storage. + * + * @method PUT + * @param int $id + * @return Response + */ + public function update($id) + { + return Response::json(Input::all()); + } + + /** + * Remove the specified resource from storage. + * + * @param int $id + * @return Response + */ + public function destroy($id) + { + $test = $this->permission->findOrFail($id); + $test->delete(); + return 'Deleted'; + } + + private function responseMap($object) + { + return [ + 'id' => $object->id, + 'name' => $object->name, + 'display_name' => $object->display_name, + ]; + } +} diff --git a/app/controllers/api/RolesV2Controller.php b/app/controllers/api/RolesV2Controller.php new file mode 100644 index 000000000..7c61eea13 --- /dev/null +++ b/app/controllers/api/RolesV2Controller.php @@ -0,0 +1,144 @@ +user = $user; + $this->role = $role; + $this->permission = $permission; + } + + public function index() + { + try{ + $statusCode = 200; + // dd($this->passParams('roles')); + $builder = ApiHandler::parseMultiple($this->role->with('perms'), array(), $this->passParams('roles')); + $roles = $builder->getResult(); + + $response = []; + foreach($roles as $role){ + $response[] = $this->responseMap($role); + } + return $this->makeResponse($response,$statusCode, $builder); + }catch (Exception $e){ + $statusCode = 500; + $message = $e->getMessage(); + return Response::json($message, $statusCode); + } + } + + public function show($id) + { + try{ + $statusCode = 200; + $role = $this->role->find($id); + + $response = $this->responseMap($role, true); + + return Response::json($response, $statusCode); + }catch (Exception $e){ + $statusCode = 500; + return Response::json($e->getMessage(), $statusCode); + } + } + + /** + * Store a newly created resource in storage. + * + * @return Response + */ + public function store() + { + $rules = array( + 'name' => 'required|min:3', + 'permissions' => 'required', + ); + + $validator = Validator::make(Input::all(), $rules); + if ($validator->passes()) + { + $inputs = Input::except('csrf_token'); + $this->role->name = $inputs['name']; + $this->role->save(); + $this->role->perms()->sync($inputs['permissions']); + + // Was the role created? + if ($this->role->id) + { + return $this->show($this->role->id); + } else { + $statusCode = 500; + $message = 'Something happen from our server'; + } + } else { + $statusCode = 400; + $messages = $validator->messages(); + } + return Response::json($messages, $statusCode); + } + public function update($id) + { + $role = $this->role->findOrFail($id); + $rules = array( + 'name' => 'required|min:3', + 'permissions' => 'required', + ); + + $validator = Validator::make(Input::all(), $rules); + if ($validator->passes()) + { + $inputs = Input::except('csrf_token'); + $role->name = $inputs['name']; + $role->save(); + $role->perms()->sync($inputs['permissions']); + + return $this->show($role->id); + } else { + $statusCode = 400; + $messages = $validator->messages(); + } + return Response::json($messages, $statusCode); + } + + public function destroy($id) + { + try + { + $role = $this->role->findOrFail($id); + if ($role->assigned_role()->count() > 0) + throw new Exception ('This Role was assigned to user(s). CAN NOT delete'); + else + $role->delete(); + + } catch (Exception $e){ + $statusCode = 400; + $error = $e->getMessage(); + return Response::json($error, $statusCode); + } + } + + private function responseMap($object, $show = false) + { + /* + * Prevent multi pivot table query on listView (which is useless) + */ + $return = [ + 'id' => $object->id, + 'name' => $object->name, + 'count' => $object->assigned_role()->count(), + 'created_at' => $object->created_at, + ]; + if ($show) + { + $return['permissions'] = $object->perms()->get()->modelKeys(); + } + return $return; + } +} diff --git a/app/controllers/api/UserV2Controller.php b/app/controllers/api/UserV2Controller.php new file mode 100644 index 000000000..5c0d44a9f --- /dev/null +++ b/app/controllers/api/UserV2Controller.php @@ -0,0 +1,103 @@ +user = $user; + } + public function index() + { + try{ + $statusCode = 200; + $builder = ApiHandler::parseMultiple($this->user->with('history'), array('name,username'), $this->passParams('users')); + $users = $builder->getResult(); + $response = []; + foreach($users as $user){ + $response[] = $this->responseMap($user); + } + + return $this->makeResponse($response,$statusCode, $builder); + }catch (Exception $e){ + $statusCode = 500; + $message = $e->getMessage(); + return Response::json($message, $statusCode); + } + } + + /** + * Store a newly created resource in storage. + * + * @return Response + */ + public function store() + { + // + } + + + /** + * Display the specified resource. + * + * @param int $id + * @return Response + */ + public function show($id) + { + try{ + $statusCode = 200; + $user = User::find($id); + + $response = $this->responseMap($user); + + return Response::json($response,$statusCode); + + }catch (Exception $e){ + $statusCode = 500; + return Response::json($e->getMessage(), $statusCode); + } + } + + + /** + * Update the specified resource in storage. + * + * @param int $id + * @return Response + */ + public function update($id) + { + // + } + + + /** + * Remove the specified resource from storage. + * + * @param int $id + * @return Response + */ + public function destroy($id) + { + $user = $this->user->findOrFail($id); + $user->delete(); + return 'Deleted'; + } + + private function responseMap($object) + { + return [ + 'id' => $object->id, + 'email' => $object->email, + 'username' => $object->username, + ]; + } + +} From 5b3e789ae26564fcecd997fbb01e65b734636e49 Mon Sep 17 00:00:00 2001 From: thangngoc89 Date: Tue, 30 Dec 2014 22:56:23 +0700 Subject: [PATCH 05/19] Install API handler --- app/config/app.php | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/app/config/app.php b/app/config/app.php index 77a02eccd..aa6b1d58e 100755 --- a/app/config/app.php +++ b/app/config/app.php @@ -114,6 +114,9 @@ 'Zizaco\Entrust\EntrustServiceProvider', // Entrust Provider for roles 'Bllim\Datatables\DatatablesServiceProvider', // Datatables + /* Laravel ng-admin Required */ + 'Marcelgwerder\ApiHandler\ApiHandlerServiceProvider', + /* Uncomment for use in development */ // 'Way\Generators\GeneratorsServiceProvider', // Generators // 'Barryvdh\LaravelIdeHelper\IdeHelperServiceProvider', // IDE Helpers @@ -191,7 +194,8 @@ 'String' => 'Andrew13\Helpers\String', // String 'Carbon' => 'Carbon\Carbon', // Carbon 'Datatables' => 'Bllim\Datatables\Datatables', // DataTables - + /* ng-admin Require */ + 'ApiHandler' => 'Marcelgwerder\ApiHandler\Facades\ApiHandler', ), 'available_language' => array('en', 'pt', 'es'), From 33ff72cda606f261c02139412e7134925611d8c5 Mon Sep 17 00:00:00 2001 From: thangngoc89 Date: Tue, 30 Dec 2014 23:00:56 +0700 Subject: [PATCH 06/19] Add my local machine name --- bootstrap/start.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bootstrap/start.php b/bootstrap/start.php index 23341a6c8..5f6c6f079 100755 --- a/bootstrap/start.php +++ b/bootstrap/start.php @@ -26,7 +26,7 @@ $env = $app->detectEnvironment(array( - 'local' => array('VirtualMint','homestead','*.local'), // Change this to your local machine hostname. + 'local' => array('VirtualMint','homestead','*.local','khoapc'), // Change this to your local machine hostname. 'staging' => array('your-staging-machine-name'), 'production' => array('your-production-machine-name'), From 7dd721321df480fadad4947996b307d941e2f745 Mon Sep 17 00:00:00 2001 From: thangngoc89 Date: Tue, 30 Dec 2014 23:06:45 +0700 Subject: [PATCH 07/19] Add Debugger Bar --- .../barryvdh/laravel-debugbar/config.php | 157 ++++++++++++++++++ app/controllers/api/APIController.php | 3 +- app/storage/debugbar/.gitignore | 2 + 3 files changed, 161 insertions(+), 1 deletion(-) create mode 100644 app/config/packages/barryvdh/laravel-debugbar/config.php create mode 100644 app/storage/debugbar/.gitignore diff --git a/app/config/packages/barryvdh/laravel-debugbar/config.php b/app/config/packages/barryvdh/laravel-debugbar/config.php new file mode 100644 index 000000000..b924afcc4 --- /dev/null +++ b/app/config/packages/barryvdh/laravel-debugbar/config.php @@ -0,0 +1,157 @@ + Config::get('app.debug'), + + /* + |-------------------------------------------------------------------------- + | Storage settings + |-------------------------------------------------------------------------- + | + | DebugBar stores data for session/ajax requests. + | You can disable this, so the debugbar stores data in headers/session, + | but this can cause problems with large data collectors. + | By default, file storage (in the storage folder) is used. Redis and PDO + | can also be used. For PDO, run the package migrations first. + | + */ + 'storage' => array( + 'enabled' => true, + 'driver' => 'file', // redis, file, pdo + 'path' => storage_path() . '/debugbar', // For file driver + 'connection' => null, // Leave null for default connection (Redis/PDO) + ), + + /* + |-------------------------------------------------------------------------- + | Vendors + |-------------------------------------------------------------------------- + | + | Vendor files are included by default, but can be set to false. + | This can also be set to 'js' or 'css', to only include javascript or css vendor files. + | Vendor files are for css: font-awesome (including fonts) and highlight.js (css files) + | and for js: jquery and and highlight.js + | So if you want syntax highlighting, set it to true. + | jQuery is set to not conflict with existing jQuery scripts. + | + */ + + 'include_vendors' => true, + + /* + |-------------------------------------------------------------------------- + | Capture Ajax Requests + |-------------------------------------------------------------------------- + | + | The Debugbar can capture Ajax requests and display them. If you don't want this (ie. because of errors), + | you can use this option to disable sending the data through the headers. + | + */ + + 'capture_ajax' => true, + + /* + |-------------------------------------------------------------------------- + | Capture Console Commands + |-------------------------------------------------------------------------- + | + | The Debugbar can listen to Artisan commands. You can view them with the browse button in the Debugbar. + | + */ + + 'capture_console' => false, + + /* + |-------------------------------------------------------------------------- + | DataCollectors + |-------------------------------------------------------------------------- + | + | Enable/disable DataCollectors + | + */ + + 'collectors' => array( + 'phpinfo' => true, // Php version + 'messages' => true, // Messages + 'time' => true, // Time Datalogger + 'memory' => true, // Memory usage + 'exceptions' => true, // Exception displayer + 'log' => true, // Logs from Monolog (merged in messages if enabled) + 'db' => true, // Show database (PDO) queries and bindings + 'views' => true, // Views with their data + 'route' => true, // Current route information + 'laravel' => false, // Laravel version and environment + 'events' => false, // All events fired + 'default_request' => false, // Regular or special Symfony request logger + 'symfony_request' => true, // Only one can be enabled.. + 'mail' => true, // Catch mail messages + 'logs' => false, // Add the latest log messages + 'files' => false, // Show the included files + 'config' => false, // Display config settings + 'auth' => false, // Display Laravel authentication status + 'session' => false, // Display session data in a separate tab + ), + + /* + |-------------------------------------------------------------------------- + | Extra options + |-------------------------------------------------------------------------- + | + | Configure some DataCollectors + | + */ + + 'options' => array( + 'auth' => array( + 'show_name' => false, // Also show the users name/email in the debugbar + ), + 'db' => array( + 'with_params' => true, // Render SQL with the parameters substituted + 'timeline' => false, // Add the queries to the timeline + 'backtrace' => false, // EXPERIMENTAL: Use a backtrace to find the origin of the query in your files. + 'explain' => array( // EXPERIMENTAL: Show EXPLAIN output on queries + 'enabled' => false, + 'types' => array('SELECT'), // array('SELECT', 'INSERT', 'UPDATE', 'DELETE'); for MySQL 5.6.3+ + ), + 'hints' => true, // Show hints for common mistakes + ), + 'mail' => array( + 'full_log' => false + ), + 'views' => array( + 'data' => false, //Note: Can slow down the application, because the data can be quite large.. + ), + 'route' => array( + 'label' => true // show complete route on bar + ), + 'logs' => array( + 'file' => null + ), + ), + + /* + |-------------------------------------------------------------------------- + | Inject Debugbar in Response + |-------------------------------------------------------------------------- + | + | Usually, the debugbar is added just before , by listening to the + | Response after the App is done. If you disable this, you have to add them + | in your template yourself. See http://phpdebugbar.com/docs/rendering.html + | + */ + + 'inject' => true, + +); diff --git a/app/controllers/api/APIController.php b/app/controllers/api/APIController.php index 1a2c42572..835c0a94f 100644 --- a/app/controllers/api/APIController.php +++ b/app/controllers/api/APIController.php @@ -5,7 +5,7 @@ class APIController extends BaseController { /** * Initializer. * - * @return \AdminController + * @return \APIController */ public function __construct() { @@ -48,6 +48,7 @@ public function passParams($table_name){ $params[$column] = Input::get($column); } } + // Return number of total rows in query (for pagination) $params ['_config'] = 'meta-filter-count'; return $params; } diff --git a/app/storage/debugbar/.gitignore b/app/storage/debugbar/.gitignore new file mode 100644 index 000000000..c96a04f00 --- /dev/null +++ b/app/storage/debugbar/.gitignore @@ -0,0 +1,2 @@ +* +!.gitignore \ No newline at end of file From 0389b640a158bd850b3e83b81279c8fcb7ff6343 Mon Sep 17 00:00:00 2001 From: thangngoc89 Date: Tue, 30 Dec 2014 23:16:55 +0700 Subject: [PATCH 08/19] Create main ng-admin panel route + view --- app/controllers/AdminController.php | 3 +++ app/routes.php | 2 ++ app/views/admin/ngadmin.blade.php | 16 ++++++++++++++++ 3 files changed, 21 insertions(+) create mode 100644 app/views/admin/ngadmin.blade.php diff --git a/app/controllers/AdminController.php b/app/controllers/AdminController.php index 719f1a18c..d5e30577f 100644 --- a/app/controllers/AdminController.php +++ b/app/controllers/AdminController.php @@ -11,5 +11,8 @@ public function __construct() { parent::__construct(); } + public function ngadmin(){ + return View::make('admin.ngadmin'); + } } \ No newline at end of file diff --git a/app/routes.php b/app/routes.php index fa41762bb..0ae62b7e2 100755 --- a/app/routes.php +++ b/app/routes.php @@ -47,6 +47,8 @@ * Admin Routes * ------------------------------------------ */ +Route::get('admincp', array('before' => 'auth', 'uses' => 'AdminController@ngadmin')); + Route::group(array('prefix' => 'admin', 'before' => 'auth'), function() { diff --git a/app/views/admin/ngadmin.blade.php b/app/views/admin/ngadmin.blade.php new file mode 100644 index 000000000..1e398511d --- /dev/null +++ b/app/views/admin/ngadmin.blade.php @@ -0,0 +1,16 @@ + + + + + ng-admmin Admin CP for Laravel 4 Bootstrap Starter Site + + + + + + + + +
+ + From 588bf803b9c43d6973a54cfab9c847164d8f69ad Mon Sep 17 00:00:00 2001 From: thangngoc89 Date: Tue, 30 Dec 2014 23:29:28 +0700 Subject: [PATCH 09/19] Add frontend assets --- app/views/admin/ngadmin.blade.php | 8 +- public/assets/ngadmin/app.js | 289 ++++++++++++++++++ public/assets/ngadmin/style.css | 49 +++ public/assets/ngadmin/vendor/angular.min.js | 250 +++++++++++++++ public/assets/ngadmin/vendor/ng-admin.min.css | 8 + public/assets/ngadmin/vendor/ng-admin.min.js | 13 + public/assets/ngadmin/vendor/ng-admin.min.map | 1 + 7 files changed, 615 insertions(+), 3 deletions(-) create mode 100644 public/assets/ngadmin/app.js create mode 100644 public/assets/ngadmin/style.css create mode 100644 public/assets/ngadmin/vendor/angular.min.js create mode 100644 public/assets/ngadmin/vendor/ng-admin.min.css create mode 100644 public/assets/ngadmin/vendor/ng-admin.min.js create mode 100644 public/assets/ngadmin/vendor/ng-admin.min.map diff --git a/app/views/admin/ngadmin.blade.php b/app/views/admin/ngadmin.blade.php index 1e398511d..937111a8a 100644 --- a/app/views/admin/ngadmin.blade.php +++ b/app/views/admin/ngadmin.blade.php @@ -4,10 +4,12 @@ ng-admmin Admin CP for Laravel 4 Bootstrap Starter Site - - + + - + + + diff --git a/public/assets/ngadmin/app.js b/public/assets/ngadmin/app.js new file mode 100644 index 000000000..bb32684d6 --- /dev/null +++ b/public/assets/ngadmin/app.js @@ -0,0 +1,289 @@ +/*global angular*/ +(function () { + "use strict"; + + var app = angular.module('myApp', ['ng-admin']); + + app.controller('main', function ($scope, $rootScope, $location) { + $rootScope.$on('$stateChangeSuccess', function () { + $scope.displayBanner = $location.$$path === '/dashboard'; + }); + }); + + app.directive('testEditLink', function () { + return { + restrict: 'E', + template: '' + + ' Sửa' + }; + }); + app.directive('testShowLink', function () { + return { + restrict: 'E', + template: '' + + ' Xem' + }; + }); + app.directive('color', function () { + return { + restrict: 'E', + template: '' + + '#{{entry.values.color}}' + }; + }); + app.directive('createdAt', function () { + return { + restrict: 'E', + template: '{{entry.values.created_at.date}}' + }; + }); + + /* Pass csrf token to X-CSRF-TOKEN header on every request */ + app.config(['$httpProvider',function($httpProvider){ + $httpProvider.defaults.headers.common['X-CSRF-TOKEN'] = document.getElementsByTagName('csrf')[0].getAttribute("content") + }]); + + app.config(function (NgAdminConfigurationProvider, Application, Entity, Field, Reference, ReferencedList, ReferenceMany) { + function truncate(value) { + if (!value) { + return ''; + } + return value.length > 40 ? value.substr(0, 40) + '...' : value; + } + function transformParams (params) { + params._sort = 'name'; + return params; + } + function dateParser(value){ + console.log(value.date); + return value.date; + } + var app = new Application('ng-admmin Admin CP') // application main title + .baseApiUrl('../api/v2/') + .transformParams(function(params) { + // Default parameters to override: page, per_page, q, _sort, _sortDir. + if (typeof params._sort === 'undefined') { + params._sort = 'id'; + } + return params; + }); + + var test = new Entity('tests'); + var user = new Entity('users'); + var category = new Entity('category'); + var role = new Entity('roles'); + var permission = new Entity('permissions'); + + app + .addEntity(test) + .addEntity(user) + .addEntity(category) + .addEntity(role) + .addEntity(permission); + + /* + * Menu View + */ + test.menuView().icon(' ').title('Đề Thi'); + user.menuView().icon(' ').title('Thành viên'); + category.menuView().icon(' '); + + role.dashboardView().disable(); + role.listView() + .title('All roles') + .addField(new Field('id')) + .addField(new Field('name').isDetailLink(true)) + .addField(new Field('count').label('# of Users')) + .addField(new Field().type('template').label('Created Date') + .template('') + ) + .listActions(['edit', 'delete']); + role.creationView() + .addField(new Field('name').validation({required: true, minlength: 3}) ) + .addField(new ReferenceMany('permissions') + .targetEntity(permission) + .targetField(new Field('display_name')) + ) + role.editionView() + .addField(new Field('name').validation({required: true, minlength: 3}) ) + .addField(new ReferenceMany('permissions') + .targetEntity(permission) + .targetField(new Field('display_name')) + ) + + + test.editionView().disable(); + test.dashboardView() + .title('Recent tests') + .addField(new Field('id').label('ID')) + .addField(new Field('questions')) + .addField(new Field('name').map(truncate)) + .order(1) + .limit(10); + + test.listView() + .title('All tests') + .addField(new Field('id').label('ID')) + .addField(new Field('name').isDetailLink(true)) + .addField(new Field('questions')) + .addField(new Reference('user_id').label('Posted by') + .targetEntity(user) + .targetField(new Field('username')) + + ) + .addField(new Reference('category_id').label('Subject') + .targetEntity(category) + .targetField(new Field('name')) + ) + .addQuickFilter('File PDF', function () { + return { + is_file: 1 + }; + }) + .addQuickFilter('Not approved', function () { + return { + is_approve: 0 + }; + }) + .addField(new Field() + .type('template') + .label('Frontend') + .template('') + ) + .listActions(['show', 'edit', 'delete']); + + test.showView() + .title('Details of "{{ entry.values.name }}"') + .addField(new Field('id')) + .addField(new Field('name')) + .addField(new Reference('user_id').label('User') + .targetEntity(user) + .targetField(new Field('username')) + ) + .addField(new Reference('category_id').label('Subject') + .targetEntity(category) + .targetField(new Field('name')) + ) + .addField(new Field('content').type('wysiwyg')) + .addField(new Field('is_file').type('boolean').label('File PDF')) + .addField(new Field('questions')) + .addField(new Field('description').label('Desc')) + .addField(new Field() + .type('template') + .label('Frontend') + .template(function () { + return '' + + ''; + }) + ); + test.editionView() + .title('Edit test "{{ entry.values.user }}"') + .actions(['list', 'show', 'delete']) + .addField(new Field('id')) + .addField(new Field('name')) + .addField(new Field('description').type('wysiwyg')) + .addField(new Field('is_approve').type('boolean')); + + user.filterView() + .addField( new Field('query').label('Search').attributes({placeholder: 'Name / Username'}) ); + + user.dashboardView() + .title('New User') + .order(3) + .limit(10) + .addField(new Field('id').label('ID')) + .addField(new Field('username')) + .addField(new Field('name')); + + user.listView() + .infinitePagination(true) + .title('All users') + .addField(new Field('id').label('ID')) + .addField(new Field('name').label('Tên')) + .addField(new Field('email')) + .addField(new Field('history').label('Số lần làm bài')) + .filterQuery(function(searchQuery) { + return { q: searchQuery }; + }) + .listActions(['show', 'edit', 'delete']); + + user.showView() // a showView displays one entry in full page - allows to display more data than in a a list + .title('User Info {{ entry.values.username }}') + .addField(new Field('id')) + .addField(new Field('name')) + .addField(new Field('username')) + .addField(new Field('email')) + .addField(new Field('avatar')) + .addField(new Field('history').label('Số lần làm bài')); + + user.editionView() + .title('Edit user "{{ entry.values.user }}"') + .actions(['list', 'show', 'delete']) + .addField(new Field('id')) + .addField(new Field('name')) + .addField(new Field('username')) + .addField(new Field('email')); + + category.dashboardView() + .title('All subjects') + .limit(10) + .addField(new Field('name')) + .addField(new Field() + .type('template') + .label('Color') + .template('') + ); + + category.listView() + .title('All subjects') + .addField(new Field('id').label('ID')) + .addField(new Field('name')) + .addField(new Field() + .type('template') + .label('Color') + .template('') + ) + .addField(new Field('slug').label('Slug')) + .listActions(['show', 'edit', 'delete']); + + category.showView() + .addField(new Field('id')) + .addField(new Field('name').label('Tên')) + .addField(new Field('description').label('Mô tả')) + .addField(new Field('color').label('Màu')) + .addField(new Field('slug').label('Slug')) + .addField(new Field() + .type('template') + .label('Màu') + .template(function () { + return ''; + }) + ) + .addField(new ReferencedList('tests') + .label('Đề thi') + .targetEntity(test) + .targetReferenceField('category_id') + .targetFields([ + new Field('id').label('ID'), + new Field('name').label('Đề thi').isDetailLink(true) + ]) + ) + category.creationView() + .addField(new Field('name').validation({required: true, minlength: 5}) ) + .addField(new Field('description').validation({required: true, minlength: 10}) ) + .addField(new Field('color').label('Color (hex)').validation({required: true, minlength: 6, maxlength: 6}) ) + .addField(new Field('slug').label('Custom Slug').validation({minlength: 8}) ) + + category.editionView() + .title('Edit subject info "{{ entry.values.name }}"') + .addField(new Field('name')) + .addField(new Field('description')) + .addField(new Field('color')) + .addField(new Field('slug') + .label('Slug') + .editable(false) + ) + + NgAdminConfigurationProvider.configure(app); + }); +}()); diff --git a/public/assets/ngadmin/style.css b/public/assets/ngadmin/style.css new file mode 100644 index 000000000..b83b40213 --- /dev/null +++ b/public/assets/ngadmin/style.css @@ -0,0 +1,49 @@ +/* + * Custom theme for ng-admin + * by thangngoc89 + * Website: http://khoanguyen.me + */ +#wrapper { + width: 100%; + background: #30426A; +} + +.nav>li>a { + color: #b2bfdc; + background: #30426A; + +} + +.nav>li>a:hover { + color: #fff; + border-left: 3px solid #e99d1a; + background: #2d3e63; +} + +.sidebar ul li a.active { + color: #fff; + border-left: 3px solid #60e928; + background: #2d3e63; +} +.sidebar ul li { + border-bottom: 0px; +} +.navbar-default, .navbar-brand{ + background-color: #2D3E63; + border: 0px; + +} +.navbar-default .navbar-brand { + color: #fff; + font-size: 16pt; +} +.navbar-default .navbar-brand:visited { + color: #fff; +} +.table{ + margin-bottom: 0; +} +.dashboard-content .panel-default { + overflow: auto; + height: 21em; +} diff --git a/public/assets/ngadmin/vendor/angular.min.js b/public/assets/ngadmin/vendor/angular.min.js new file mode 100644 index 000000000..06d5d7647 --- /dev/null +++ b/public/assets/ngadmin/vendor/angular.min.js @@ -0,0 +1,250 @@ +/* + AngularJS v1.3.8 + (c) 2010-2014 Google, Inc. http://angularjs.org + License: MIT +*/ +(function(M,Y,t){'use strict';function T(b){return function(){var a=arguments[0],c;c="["+(b?b+":":"")+a+"] http://errors.angularjs.org/1.3.8/"+(b?b+"/":"")+a;for(a=1;a").append(b).html();try{return b[0].nodeType===pb?Q(c):c.match(/^(<[^>]+>)/)[1].replace(/^<([\w\-]+)/,function(a,b){return"<"+Q(b)})}catch(d){return Q(c)}}function pc(b){try{return decodeURIComponent(b)}catch(a){}}function qc(b){var a={},c,d;s((b||"").split("&"),function(b){b&& +(c=b.replace(/\+/g,"%20").split("="),d=pc(c[0]),y(d)&&(b=y(c[1])?pc(c[1]):!0,rc.call(a,d)?x(a[d])?a[d].push(b):a[d]=[a[d],b]:a[d]=b))});return a}function Nb(b){var a=[];s(b,function(b,d){x(b)?s(b,function(b){a.push(Fa(d,!0)+(!0===b?"":"="+Fa(b,!0)))}):a.push(Fa(d,!0)+(!0===b?"":"="+Fa(b,!0)))});return a.length?a.join("&"):""}function qb(b){return Fa(b,!0).replace(/%26/gi,"&").replace(/%3D/gi,"=").replace(/%2B/gi,"+")}function Fa(b,a){return encodeURIComponent(b).replace(/%40/gi,"@").replace(/%3A/gi, +":").replace(/%24/g,"$").replace(/%2C/gi,",").replace(/%3B/gi,";").replace(/%20/g,a?"%20":"+")}function Id(b,a){var c,d,e=rb.length;b=B(b);for(d=0;d/,">"));}a=a||[];a.unshift(["$provide",function(a){a.value("$rootElement",b)}]);c.debugInfoEnabled&&a.push(["$compileProvider",function(a){a.debugInfoEnabled(!0)}]);a.unshift("ng");d=Ob(a,c.strictDi);d.invoke(["$rootScope","$rootElement","$compile","$injector",function(a,b,c,d){a.$apply(function(){b.data("$injector",d);c(b)(a)})}]);return d}, +e=/^NG_ENABLE_DEBUG_INFO!/,f=/^NG_DEFER_BOOTSTRAP!/;M&&e.test(M.name)&&(c.debugInfoEnabled=!0,M.name=M.name.replace(e,""));if(M&&!f.test(M.name))return d();M.name=M.name.replace(f,"");ga.resumeBootstrap=function(b){s(b,function(b){a.push(b)});d()}}function Kd(){M.name="NG_ENABLE_DEBUG_INFO!"+M.name;M.location.reload()}function Ld(b){b=ga.element(b).injector();if(!b)throw Ka("test");return b.get("$$testability")}function tc(b,a){a=a||"_";return b.replace(Md,function(b,d){return(d?a:"")+b.toLowerCase()})} +function Nd(){var b;uc||((ra=M.jQuery)&&ra.fn.on?(B=ra,z(ra.fn,{scope:La.scope,isolateScope:La.isolateScope,controller:La.controller,injector:La.injector,inheritedData:La.inheritedData}),b=ra.cleanData,ra.cleanData=function(a){var c;if(Pb)Pb=!1;else for(var d=0,e;null!=(e=a[d]);d++)(c=ra._data(e,"events"))&&c.$destroy&&ra(e).triggerHandler("$destroy");b(a)}):B=R,ga.element=B,uc=!0)}function Qb(b,a,c){if(!b)throw Ka("areq",a||"?",c||"required");return b}function sb(b,a,c){c&&x(b)&&(b=b[b.length-1]); +Qb(G(b),a,"not a function, got "+(b&&"object"===typeof b?b.constructor.name||"Object":typeof b));return b}function Ma(b,a){if("hasOwnProperty"===b)throw Ka("badname",a);}function vc(b,a,c){if(!a)return b;a=a.split(".");for(var d,e=b,f=a.length,g=0;g")+d[2];for(d=d[0];d--;)c=c.lastChild;f=Ya(f,c.childNodes);c=e.firstChild;c.textContent=""}else f.push(a.createTextNode(b));e.textContent="";e.innerHTML="";s(f,function(a){e.appendChild(a)});return e}function R(b){if(b instanceof +R)return b;var a;F(b)&&(b=U(b),a=!0);if(!(this instanceof R)){if(a&&"<"!=b.charAt(0))throw Sb("nosel");return new R(b)}if(a){a=Y;var c;b=(c=gf.exec(b))?[a.createElement(c[1])]:(c=Fc(b,a))?c.childNodes:[]}Gc(this,b)}function Tb(b){return b.cloneNode(!0)}function wb(b,a){a||xb(b);if(b.querySelectorAll)for(var c=b.querySelectorAll("*"),d=0,e=c.length;d 4096 bytes)!"));else{if(p.cookie!==y)for(y=p.cookie,d=y.split("; "),ea={},f=0;fk&&this.remove(q.key), +b},get:function(a){if(k").parent()[0])});var f=S(a,b,a,c,d,e);E.$$addScopeClass(a);var g=null;return function(b,c,d){Qb(b,"scope");d=d||{};var e=d.parentBoundTranscludeFn,h=d.transcludeControllers;d=d.futureParentElement;e&&e.$$boundTransclude&&(e=e.$$boundTransclude);g||(g=(d=d&&d[0])?"foreignobject"!==ua(d)&&d.toString().match(/SVG/)?"svg":"html":"html");d="html"!==g?B(Wb(g,B("
").append(a).html())): +c?La.clone.call(a):a;if(h)for(var l in h)d.data("$"+l+"Controller",h[l].instance);E.$$addScopeInfo(d,b);c&&c(d,b);f&&f(b,d,d,e);return d}}function S(a,b,c,d,e,f){function g(a,c,d,e){var f,l,k,q,p,n,w;if(r)for(w=Array(c.length),q=0;qK.priority)break;if(N=K.scope)K.templateUrl||(H(N)?(Oa("new/isolated scope",S||P,K,aa),S=K):Oa("new/isolated scope",S,K,aa)),P=P||K;z=K.name;!K.templateUrl&&K.controller&&(N=K.controller,J=J||{},Oa("'"+z+"' controller",J[z], +K,aa),J[z]=K);if(N=K.transclude)ca=!0,K.$$tlb||(Oa("transclusion",ea,K,aa),ea=K),"element"==N?(C=!0,A=K.priority,N=aa,aa=e.$$element=B(Y.createComment(" "+z+": "+e[z]+" ")),d=aa[0],V(g,Za.call(N,0),d),Aa=E(N,f,A,l&&l.name,{nonTlbTranscludeDirective:ea})):(N=B(Tb(d)).contents(),aa.empty(),Aa=E(N,f));if(K.template)if(D=!0,Oa("template",ka,K,aa),ka=K,N=G(K.template)?K.template(aa,e):K.template,N=Sc(N),K.replace){l=K;N=Rb.test(N)?Tc(Wb(K.templateNamespace,U(N))):[];d=N[0];if(1!=N.length||d.nodeType!== +na)throw ja("tplrt",z,"");V(g,aa,d);R={$attr:{}};N=W(d,[],R);var ba=a.splice(M+1,a.length-(M+1));S&&y(N);a=a.concat(N).concat(ba);Qc(e,R);R=a.length}else aa.html(N);if(K.templateUrl)D=!0,Oa("template",ka,K,aa),ka=K,K.replace&&(l=K),v=T(a.splice(M,a.length-M),aa,e,g,ca&&Aa,k,p,{controllerDirectives:J,newIsolateScopeDirective:S,templateDirective:ka,nonTlbTranscludeDirective:ea}),R=a.length;else if(K.compile)try{Q=K.compile(aa,e,Aa),G(Q)?w(null,Q,Pa,fb):Q&&w(Q.pre,Q.post,Pa,fb)}catch(qf){c(qf,va(aa))}K.terminal&& +(v.terminal=!0,A=Math.max(A,K.priority))}v.scope=P&&!0===P.scope;v.transcludeOnThisElement=ca;v.elementTranscludeOnThisElement=C;v.templateOnThisElement=D;v.transclude=Aa;r.hasElementTranscludeDirective=C;return v}function y(a){for(var b=0,c=a.length;bq.priority)&&-1!= +q.restrict.indexOf(f)){if(l){var w={$$start:l,$$end:k};q=z(Object.create(q),w)}b.push(q);h=q}}catch(O){c(O)}}return h}function D(b){if(d.hasOwnProperty(b))for(var c=a.get(b+"Directive"),e=0,f=c.length;e"+b+"";return c.childNodes[0].childNodes;default:return b}}function R(a,b){if("srcdoc"==b)return L.HTML;var c=ua(a);if("xlinkHref"==b||"form"==c&&"action"==b||"img"!=c&&("src"==b||"ngSrc"==b))return L.RESOURCE_URL}function Pa(a,c,d,e,f){var h=R(a,e);f=g[e]||f;var k=b(d,!0,h,f);if(k){if("multiple"===e&&"select"===ua(a))throw ja("selmulti", +va(a));c.push({priority:100,compile:function(){return{pre:function(a,c,g){c=g.$$observers||(g.$$observers={});if(l.test(e))throw ja("nodomevents");var p=g[e];p!==d&&(k=p&&b(p,!0,h,f),d=p);k&&(g[e]=k(a),(c[e]||(c[e]=[])).$$inter=!0,(g.$$observers&&g.$$observers[e].$$scope||a).$watch(k,function(a,b){"class"===e&&a!=b?g.$updateClass(a,b):g.$set(e,a)}))}}}})}}function V(a,b,c){var d=b[0],e=b.length,f=d.parentNode,g,h;if(a)for(g=0,h=a.length;g=a)return b;for(;a--;)8===b[a].nodeType&&rf.call(b,a,1);return b}function Fe(){var b={},a=!1,c=/^(\S+)(\s+as\s+(\w+))?$/;this.register=function(a,c){Ma(a,"controller");H(a)?z(b,a):b[a]=c};this.allowGlobals=function(){a=!0};this.$get=["$injector","$window",function(d,e){function f(a,b,c,d){if(!a||!H(a.$scope))throw T("$controller")("noscp",d,b);a.$scope[b]=c}return function(g,h,l,k){var m,p,q;l=!0===l;k&&F(k)&&(q=k);F(g)&& +(k=g.match(c),p=k[1],q=q||k[3],g=b.hasOwnProperty(p)?b[p]:vc(h.$scope,p,!0)||(a?vc(e,p,!0):t),sb(g,p,!0));if(l)return l=(x(g)?g[g.length-1]:g).prototype,m=Object.create(l),q&&f(h,q,m,p||g.name),z(function(){d.invoke(g,m,h,p);return m},{instance:m,identifier:q});m=d.instantiate(g,h,p);q&&f(h,q,m,p||g.name);return m}}]}function Ge(){this.$get=["$window",function(b){return B(b.document)}]}function He(){this.$get=["$log",function(b){return function(a,c){b.error.apply(b,arguments)}}]}function Yb(b,a){if(F(b)){var c= +b.replace(sf,"").trim();if(c){var d=a("Content-Type");(d=d&&0===d.indexOf(Vc))||(d=(d=c.match(tf))&&uf[d[0]].test(c));d&&(b=oc(c))}}return b}function Wc(b){var a=ha(),c,d,e;if(!b)return a;s(b.split("\n"),function(b){e=b.indexOf(":");c=Q(U(b.substr(0,e)));d=U(b.substr(e+1));c&&(a[c]=a[c]?a[c]+", "+d:d)});return a}function Xc(b){var a=H(b)?b:t;return function(c){a||(a=Wc(b));return c?(c=a[Q(c)],void 0===c&&(c=null),c):a}}function Yc(b,a,c,d){if(G(d))return d(b,a,c);s(d,function(d){b=d(b,a,c)});return b} +function Ke(){var b=this.defaults={transformResponse:[Yb],transformRequest:[function(a){return H(a)&&"[object File]"!==Da.call(a)&&"[object Blob]"!==Da.call(a)&&"[object FormData]"!==Da.call(a)?$a(a):a}],headers:{common:{Accept:"application/json, text/plain, */*"},post:qa(Zb),put:qa(Zb),patch:qa(Zb)},xsrfCookieName:"XSRF-TOKEN",xsrfHeaderName:"X-XSRF-TOKEN"},a=!1;this.useApplyAsync=function(b){return y(b)?(a=!!b,this):a};var c=this.interceptors=[];this.$get=["$httpBackend","$browser","$cacheFactory", +"$rootScope","$q","$injector",function(d,e,f,g,h,l){function k(a){function c(a){var b=z({},a);b.data=a.data?Yc(a.data,a.headers,a.status,e.transformResponse):a.data;a=a.status;return 200<=a&&300>a?b:h.reject(b)}function d(a){var b,c={};s(a,function(a,d){G(a)?(b=a(),null!=b&&(c[d]=b)):c[d]=a});return c}if(!ga.isObject(a))throw T("$http")("badreq",a);var e=z({method:"get",transformRequest:b.transformRequest,transformResponse:b.transformResponse},a);e.headers=function(a){var c=b.headers,e=z({},a.headers), +f,g,c=z({},c.common,c[Q(a.method)]);a:for(f in c){a=Q(f);for(g in e)if(Q(g)===a)continue a;e[f]=c[f]}return d(e)}(a);e.method=ub(e.method);var f=[function(a){var d=a.headers,e=Yc(a.data,Xc(d),t,a.transformRequest);D(e)&&s(d,function(a,b){"content-type"===Q(b)&&delete d[b]});D(a.withCredentials)&&!D(b.withCredentials)&&(a.withCredentials=b.withCredentials);return m(a,e).then(c,c)},t],g=h.when(e);for(s(u,function(a){(a.request||a.requestError)&&f.unshift(a.request,a.requestError);(a.response||a.responseError)&& +f.push(a.response,a.responseError)});f.length;){a=f.shift();var l=f.shift(),g=g.then(a,l)}g.success=function(a){g.then(function(b){a(b.data,b.status,b.headers,e)});return g};g.error=function(a){g.then(null,function(b){a(b.data,b.status,b.headers,e)});return g};return g}function m(c,f){function l(b,c,d,e){function f(){m(c,b,d,e)}P&&(200<=b&&300>b?P.put(X,[b,c,Wc(d),e]):P.remove(X));a?g.$applyAsync(f):(f(),g.$$phase||g.$apply())}function m(a,b,d,e){b=Math.max(b,0);(200<=b&&300>b?J.resolve:J.reject)({data:a, +status:b,headers:Xc(d),config:c,statusText:e})}function w(a){m(a.data,a.status,qa(a.headers()),a.statusText)}function u(){var a=k.pendingRequests.indexOf(c);-1!==a&&k.pendingRequests.splice(a,1)}var J=h.defer(),A=J.promise,P,E,s=c.headers,X=p(c.url,c.params);k.pendingRequests.push(c);A.then(u,u);!c.cache&&!b.cache||!1===c.cache||"GET"!==c.method&&"JSONP"!==c.method||(P=H(c.cache)?c.cache:H(b.cache)?b.cache:q);P&&(E=P.get(X),y(E)?E&&G(E.then)?E.then(w,w):x(E)?m(E[1],E[0],qa(E[2]),E[3]):m(E,200,{}, +"OK"):P.put(X,A));D(E)&&((E=Zc(c.url)?e.cookies()[c.xsrfCookieName||b.xsrfCookieName]:t)&&(s[c.xsrfHeaderName||b.xsrfHeaderName]=E),d(c.method,X,f,l,s,c.timeout,c.withCredentials,c.responseType));return A}function p(a,b){if(!b)return a;var c=[];Ed(b,function(a,b){null===a||D(a)||(x(a)||(a=[a]),s(a,function(a){H(a)&&(a=pa(a)?a.toISOString():$a(a));c.push(Fa(b)+"="+Fa(a))}))});0=l&&(r.resolve(q),p(O.$$intervalId),delete f[O.$$intervalId]);u||b.$apply()},h);f[O.$$intervalId]=r;return O}var f={};e.cancel=function(b){return b&&b.$$intervalId in f?(f[b.$$intervalId].reject("canceled"),a.clearInterval(b.$$intervalId),delete f[b.$$intervalId],!0):!1};return e}]}function Rd(){this.$get=function(){return{id:"en-us",NUMBER_FORMATS:{DECIMAL_SEP:".",GROUP_SEP:",",PATTERNS:[{minInt:1,minFrac:0,maxFrac:3,posPre:"",posSuf:"",negPre:"-",negSuf:"",gSize:3,lgSize:3},{minInt:1,minFrac:2, +maxFrac:2,posPre:"\u00a4",posSuf:"",negPre:"(\u00a4",negSuf:")",gSize:3,lgSize:3}],CURRENCY_SYM:"$"},DATETIME_FORMATS:{MONTH:"January February March April May June July August September October November December".split(" "),SHORTMONTH:"Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec".split(" "),DAY:"Sunday Monday Tuesday Wednesday Thursday Friday Saturday".split(" "),SHORTDAY:"Sun Mon Tue Wed Thu Fri Sat".split(" "),AMPMS:["AM","PM"],medium:"MMM d, y h:mm:ss a","short":"M/d/yy h:mm a",fullDate:"EEEE, MMMM d, y", +longDate:"MMMM d, y",mediumDate:"MMM d, y",shortDate:"M/d/yy",mediumTime:"h:mm:ss a",shortTime:"h:mm a"},pluralCat:function(b){return 1===b?"one":"other"}}}}function ac(b){b=b.split("/");for(var a=b.length;a--;)b[a]=qb(b[a]);return b.join("/")}function $c(b,a){var c=Ba(b);a.$$protocol=c.protocol;a.$$host=c.hostname;a.$$port=ba(c.port)||xf[c.protocol]||null}function ad(b,a){var c="/"!==b.charAt(0);c&&(b="/"+b);var d=Ba(b);a.$$path=decodeURIComponent(c&&"/"===d.pathname.charAt(0)?d.pathname.substring(1): +d.pathname);a.$$search=qc(d.search);a.$$hash=decodeURIComponent(d.hash);a.$$path&&"/"!=a.$$path.charAt(0)&&(a.$$path="/"+a.$$path)}function za(b,a){if(0===a.indexOf(b))return a.substr(b.length)}function Ha(b){var a=b.indexOf("#");return-1==a?b:b.substr(0,a)}function bd(b){return b.replace(/(#.+)|#$/,"$1")}function bc(b){return b.substr(0,Ha(b).lastIndexOf("/")+1)}function cc(b,a){this.$$html5=!0;a=a||"";var c=bc(b);$c(b,this);this.$$parse=function(a){var b=za(c,a);if(!F(b))throw Fb("ipthprfx",a,c); +ad(b,this);this.$$path||(this.$$path="/");this.$$compose()};this.$$compose=function(){var a=Nb(this.$$search),b=this.$$hash?"#"+qb(this.$$hash):"";this.$$url=ac(this.$$path)+(a?"?"+a:"")+b;this.$$absUrl=c+this.$$url.substr(1)};this.$$parseLinkUrl=function(d,e){if(e&&"#"===e[0])return this.hash(e.slice(1)),!0;var f,g;(f=za(b,d))!==t?(g=f,g=(f=za(a,f))!==t?c+(za("/",f)||f):b+g):(f=za(c,d))!==t?g=c+f:c==d+"/"&&(g=c);g&&this.$$parse(g);return!!g}}function dc(b,a){var c=bc(b);$c(b,this);this.$$parse=function(d){d= +za(b,d)||za(c,d);var e;"#"===d.charAt(0)?(e=za(a,d),D(e)&&(e=d)):e=this.$$html5?d:"";ad(e,this);d=this.$$path;var f=/^\/[A-Z]:(\/.*)/;0===e.indexOf(b)&&(e=e.replace(b,""));f.exec(e)||(d=(e=f.exec(d))?e[1]:d);this.$$path=d;this.$$compose()};this.$$compose=function(){var c=Nb(this.$$search),e=this.$$hash?"#"+qb(this.$$hash):"";this.$$url=ac(this.$$path)+(c?"?"+c:"")+e;this.$$absUrl=b+(this.$$url?a+this.$$url:"")};this.$$parseLinkUrl=function(a,c){return Ha(b)==Ha(a)?(this.$$parse(a),!0):!1}}function cd(b, +a){this.$$html5=!0;dc.apply(this,arguments);var c=bc(b);this.$$parseLinkUrl=function(d,e){if(e&&"#"===e[0])return this.hash(e.slice(1)),!0;var f,g;b==Ha(d)?f=d:(g=za(c,d))?f=b+a+g:c===d+"/"&&(f=c);f&&this.$$parse(f);return!!f};this.$$compose=function(){var c=Nb(this.$$search),e=this.$$hash?"#"+qb(this.$$hash):"";this.$$url=ac(this.$$path)+(c?"?"+c:"")+e;this.$$absUrl=b+a+this.$$url}}function Gb(b){return function(){return this[b]}}function dd(b,a){return function(c){if(D(c))return this[b];this[b]= +a(c);this.$$compose();return this}}function Me(){var b="",a={enabled:!1,requireBase:!0,rewriteLinks:!0};this.hashPrefix=function(a){return y(a)?(b=a,this):b};this.html5Mode=function(b){return Wa(b)?(a.enabled=b,this):H(b)?(Wa(b.enabled)&&(a.enabled=b.enabled),Wa(b.requireBase)&&(a.requireBase=b.requireBase),Wa(b.rewriteLinks)&&(a.rewriteLinks=b.rewriteLinks),this):a};this.$get=["$rootScope","$browser","$sniffer","$rootElement","$window",function(c,d,e,f,g){function h(a,b,c){var e=k.url(),f=k.$$state; +try{d.url(a,b,c),k.$$state=d.state()}catch(g){throw k.url(e),k.$$state=f,g;}}function l(a,b){c.$broadcast("$locationChangeSuccess",k.absUrl(),a,k.$$state,b)}var k,m;m=d.baseHref();var p=d.url(),q;if(a.enabled){if(!m&&a.requireBase)throw Fb("nobase");q=p.substring(0,p.indexOf("/",p.indexOf("//")+2))+(m||"/");m=e.history?cc:cd}else q=Ha(p),m=dc;k=new m(q,"#"+b);k.$$parseLinkUrl(p,p);k.$$state=d.state();var u=/^\s*(javascript|mailto):/i;f.on("click",function(b){if(a.rewriteLinks&&!b.ctrlKey&&!b.metaKey&& +2!=b.which){for(var e=B(b.target);"a"!==ua(e[0]);)if(e[0]===f[0]||!(e=e.parent())[0])return;var h=e.prop("href"),l=e.attr("href")||e.attr("xlink:href");H(h)&&"[object SVGAnimatedString]"===h.toString()&&(h=Ba(h.animVal).href);u.test(h)||!h||e.attr("target")||b.isDefaultPrevented()||!k.$$parseLinkUrl(h,l)||(b.preventDefault(),k.absUrl()!=d.url()&&(c.$apply(),g.angular["ff-684208-preventDefault"]=!0))}});k.absUrl()!=p&&d.url(k.absUrl(),!0);var r=!0;d.onUrlChange(function(a,b){c.$evalAsync(function(){var d= +k.absUrl(),e=k.$$state,f;k.$$parse(a);k.$$state=b;f=c.$broadcast("$locationChangeStart",a,d,b,e).defaultPrevented;k.absUrl()===a&&(f?(k.$$parse(d),k.$$state=e,h(d,!1,e)):(r=!1,l(d,e)))});c.$$phase||c.$digest()});c.$watch(function(){var a=bd(d.url()),b=bd(k.absUrl()),f=d.state(),g=k.$$replace,q=a!==b||k.$$html5&&e.history&&f!==k.$$state;if(r||q)r=!1,c.$evalAsync(function(){var b=k.absUrl(),d=c.$broadcast("$locationChangeStart",b,a,k.$$state,f).defaultPrevented;k.absUrl()===b&&(d?(k.$$parse(a),k.$$state= +f):(q&&h(b,g,f===k.$$state?null:k.$$state),l(a,f)))});k.$$replace=!1});return k}]}function Ne(){var b=!0,a=this;this.debugEnabled=function(a){return y(a)?(b=a,this):b};this.$get=["$window",function(c){function d(a){a instanceof Error&&(a.stack?a=a.message&&-1===a.stack.indexOf(a.message)?"Error: "+a.message+"\n"+a.stack:a.stack:a.sourceURL&&(a=a.message+"\n"+a.sourceURL+":"+a.line));return a}function e(a){var b=c.console||{},e=b[a]||b.log||C;a=!1;try{a=!!e.apply}catch(l){}return a?function(){var a= +[];s(arguments,function(b){a.push(d(b))});return e.apply(b,a)}:function(a,b){e(a,null==b?"":b)}}return{log:e("log"),info:e("info"),warn:e("warn"),error:e("error"),debug:function(){var c=e("debug");return function(){b&&c.apply(a,arguments)}}()}}]}function sa(b,a){if("__defineGetter__"===b||"__defineSetter__"===b||"__lookupGetter__"===b||"__lookupSetter__"===b||"__proto__"===b)throw la("isecfld",a);return b}function ta(b,a){if(b){if(b.constructor===b)throw la("isecfn",a);if(b.window===b)throw la("isecwindow", +a);if(b.children&&(b.nodeName||b.prop&&b.attr&&b.find))throw la("isecdom",a);if(b===Object)throw la("isecobj",a);}return b}function ec(b){return b.constant}function gb(b,a,c,d){ta(b,d);a=a.split(".");for(var e,f=0;1h?ed(g[0],g[1],g[2],g[3],g[4], +c,d):function(a,b){var e=0,f;do f=ed(g[e++],g[e++],g[e++],g[e++],g[e++],c,d)(a,b),b=t,a=f;while(e=this.promise.$$state.status&& +d&&d.length&&b(function(){for(var b,e,f=0,g=d.length;fa)for(b in k++,f)e.hasOwnProperty(b)||(u--,delete f[b])}else f!==e&&(f=e,k++);return k}}c.$stateful=!0;var d=this,e,f,h,l=1s&&(y=4-s,W[y]||(W[y]=[]),W[y].push({msg:G(e.exp)? +"fn: "+(e.exp.name||e.exp.toString()):e.exp,newVal:g,oldVal:l}));else if(e===c){v=!1;break a}}catch(D){f(D)}if(!(m=t.$$childHead||t!==this&&t.$$nextSibling))for(;t!==this&&!(m=t.$$nextSibling);)t=t.$parent}while(t=m);if((v||O.length)&&!s--)throw r.$$phase=null,a("infdig",b,W);}while(v||O.length);for(r.$$phase=null;n.length;)try{n.shift()()}catch(ca){f(ca)}},$destroy:function(){if(!this.$$destroyed){var a=this.$parent;this.$broadcast("$destroy");this.$$destroyed=!0;if(this!==r){for(var b in this.$$listenerCount)m(this, +this.$$listenerCount[b],b);a.$$childHead==this&&(a.$$childHead=this.$$nextSibling);a.$$childTail==this&&(a.$$childTail=this.$$prevSibling);this.$$prevSibling&&(this.$$prevSibling.$$nextSibling=this.$$nextSibling);this.$$nextSibling&&(this.$$nextSibling.$$prevSibling=this.$$prevSibling);this.$destroy=this.$digest=this.$apply=this.$evalAsync=this.$applyAsync=C;this.$on=this.$watch=this.$watchGroup=function(){return C};this.$$listeners={};this.$parent=this.$$nextSibling=this.$$prevSibling=this.$$childHead= +this.$$childTail=this.$root=this.$$watchers=null}}},$eval:function(a,b){return g(a)(this,b)},$evalAsync:function(a,b){r.$$phase||O.length||h.defer(function(){O.length&&r.$digest()});O.push({scope:this,expression:a,locals:b})},$$postDigest:function(a){n.push(a)},$apply:function(a){try{return k("$apply"),this.$eval(a)}catch(b){f(b)}finally{r.$$phase=null;try{r.$digest()}catch(c){throw f(c),c;}}},$applyAsync:function(a){function b(){c.$eval(a)}var c=this;a&&v.push(b);u()},$on:function(a,b){var c=this.$$listeners[a]; +c||(this.$$listeners[a]=c=[]);c.push(b);var d=this;do d.$$listenerCount[a]||(d.$$listenerCount[a]=0),d.$$listenerCount[a]++;while(d=d.$parent);var e=this;return function(){var d=c.indexOf(b);-1!==d&&(c[d]=null,m(e,1,a))}},$emit:function(a,b){var c=[],d,e=this,g=!1,h={name:a,targetScope:e,stopPropagation:function(){g=!0},preventDefault:function(){h.defaultPrevented=!0},defaultPrevented:!1},l=Ya([h],arguments,1),k,p;do{d=e.$$listeners[a]||c;h.currentScope=e;k=0;for(p=d.length;kRa)throw Ca("iequirks");var d=qa(ma);d.isEnabled=function(){return b};d.trustAs= +c.trustAs;d.getTrusted=c.getTrusted;d.valueOf=c.valueOf;b||(d.trustAs=d.getTrusted=function(a,b){return b},d.valueOf=oa);d.parseAs=function(b,c){var e=a(c);return e.literal&&e.constant?e:a(c,function(a){return d.getTrusted(b,a)})};var e=d.parseAs,f=d.getTrusted,g=d.trustAs;s(ma,function(a,b){var c=Q(b);d[cb("parse_as_"+c)]=function(b){return e(a,b)};d[cb("get_trusted_"+c)]=function(b){return f(a,b)};d[cb("trust_as_"+c)]=function(b){return g(a,b)}});return d}]}function Ue(){this.$get=["$window","$document", +function(b,a){var c={},d=ba((/android (\d+)/.exec(Q((b.navigator||{}).userAgent))||[])[1]),e=/Boxee/i.test((b.navigator||{}).userAgent),f=a[0]||{},g,h=/^(Moz|webkit|ms)(?=[A-Z])/,l=f.body&&f.body.style,k=!1,m=!1;if(l){for(var p in l)if(k=h.exec(p)){g=k[0];g=g.substr(0,1).toUpperCase()+g.substr(1);break}g||(g="WebkitOpacity"in l&&"webkit");k=!!("transition"in l||g+"Transition"in l);m=!!("animation"in l||g+"Animation"in l);!d||k&&m||(k=F(f.body.style.webkitTransition),m=F(f.body.style.webkitAnimation))}return{history:!(!b.history|| +!b.history.pushState||4>d||e),hasEvent:function(a){if("input"===a&&11>=Ra)return!1;if(D(c[a])){var b=f.createElement("div");c[a]="on"+a in b}return c[a]},csp:ab(),vendorPrefix:g,transitions:k,animations:m,android:d}}]}function We(){this.$get=["$templateCache","$http","$q",function(b,a,c){function d(e,f){d.totalPendingRequests++;var g=a.defaults&&a.defaults.transformResponse;x(g)?g=g.filter(function(a){return a!==Yb}):g===Yb&&(g=null);return a.get(e,{cache:b,transformResponse:g}).then(function(a){d.totalPendingRequests--; +return a.data},function(a){d.totalPendingRequests--;if(!f)throw ja("tpload",e);return c.reject(a)})}d.totalPendingRequests=0;return d}]}function Xe(){this.$get=["$rootScope","$browser","$location",function(b,a,c){return{findBindings:function(a,b,c){a=a.getElementsByClassName("ng-binding");var g=[];s(a,function(a){var d=ga.element(a).data("$binding");d&&s(d,function(d){c?(new RegExp("(^|\\s)"+gd(b)+"(\\s|\\||$)")).test(d)&&g.push(a):-1!=d.indexOf(b)&&g.push(a)})});return g},findModels:function(a,b, +c){for(var g=["ng-","data-ng-","ng\\:"],h=0;hb;b=Math.abs(b);var g=b+"",h="",l=[],k=!1;if(-1!==g.indexOf("e")){var m=g.match(/([\d\.]+)e(-?)(\d+)/);m&&"-"==m[2]&&m[3]>e+1?b=0:(h=g,k=!0)}if(k)0b&&(h=b.toFixed(e),b=parseFloat(h));else{g= +(g.split(od)[1]||"").length;D(e)&&(e=Math.min(Math.max(a.minFrac,g),a.maxFrac));b=+(Math.round(+(b.toString()+"e"+e)).toString()+"e"+-e);var g=(""+b).split(od),k=g[0],g=g[1]||"",p=0,q=a.lgSize,u=a.gSize;if(k.length>=q+u)for(p=k.length-q,m=0;mb&&(d="-",b=-b);for(b=""+b;b.length-c)e+=c;0===e&&-12==c&&(e=12);return Hb(e,a,d)}}function Ib(b,a){return function(c,d){var e=c["get"+b](),f=ub(a?"SHORT"+b:b);return d[f][e]}}function pd(b){var a=(new Date(b,0,1)).getDay();return new Date(b,0,(4>=a?5:12)-a)}function qd(b){return function(a){var c=pd(a.getFullYear());a=+new Date(a.getFullYear(),a.getMonth(), +a.getDate()+(4-a.getDay()))-+c;a=1+Math.round(a/6048E5);return Hb(a,b)}}function kd(b){function a(a){var b;if(b=a.match(c)){a=new Date(0);var f=0,g=0,h=b[8]?a.setUTCFullYear:a.setFullYear,l=b[8]?a.setUTCHours:a.setHours;b[9]&&(f=ba(b[9]+b[10]),g=ba(b[9]+b[11]));h.call(a,ba(b[1]),ba(b[2])-1,ba(b[3]));f=ba(b[4]||0)-f;g=ba(b[5]||0)-g;h=ba(b[6]||0);b=Math.round(1E3*parseFloat("0."+(b[7]||0)));l.call(a,f,g,h,b)}return a}var c=/^(\d{4})-?(\d\d)-?(\d\d)(?:T(\d\d)(?::?(\d\d)(?::?(\d\d)(?:\.(\d+))?)?)?(Z|([+-])(\d\d):?(\d\d))?)?$/; +return function(c,e,f){var g="",h=[],l,k;e=e||"mediumDate";e=b.DATETIME_FORMATS[e]||e;F(c)&&(c=Kf.test(c)?ba(c):a(c));V(c)&&(c=new Date(c));if(!pa(c))return c;for(;e;)(k=Lf.exec(e))?(h=Ya(h,k,1),e=h.pop()):(h.push(e),e=null);f&&"UTC"===f&&(c=new Date(c.getTime()),c.setMinutes(c.getMinutes()+c.getTimezoneOffset()));s(h,function(a){l=Mf[a];g+=l?l(c,b.DATETIME_FORMATS):a.replace(/(^'|'$)/g,"").replace(/''/g,"'")});return g}}function Ff(){return function(b,a){D(a)&&(a=2);return $a(b,a)}}function Gf(){return function(b, +a){V(b)&&(b=b.toString());if(!x(b)&&!F(b))return b;a=Infinity===Math.abs(Number(a))?Number(a):ba(a);if(F(b))return a?0<=a?b.slice(0,a):b.slice(a,b.length):"";var c,d;a>b.length?a=b.length:a<-b.length&&(a=-b.length);if(0b||37<=b&&40>=b||m(a,this,this.value)});if(e.hasEvent("paste"))a.on("paste cut",m)}a.on("change",l);d.$render=function(){a.val(d.$isEmpty(d.$viewValue)?"":d.$viewValue)}}function Lb(b,a){return function(c,d){var e,f;if(pa(c))return c;if(F(c)){'"'==c.charAt(0)&&'"'==c.charAt(c.length-1)&&(c=c.substring(1, +c.length-1));if(Nf.test(c))return new Date(c);b.lastIndex=0;if(e=b.exec(c))return e.shift(),f=d?{yyyy:d.getFullYear(),MM:d.getMonth()+1,dd:d.getDate(),HH:d.getHours(),mm:d.getMinutes(),ss:d.getSeconds(),sss:d.getMilliseconds()/1E3}:{yyyy:1970,MM:1,dd:1,HH:0,mm:0,ss:0,sss:0},s(e,function(b,c){c=s};g.$observe("min",function(a){s=q(a);h.$validate()})}if(y(g.max)||g.ngMax){var n;h.$validators.max=function(a){return!p(a)||D(n)||c(a)<=n};g.$observe("max",function(a){n=q(a);h.$validate()})}}}function td(b,a,c,d){(d.$$hasNativeValidators=H(a[0].validity))&&d.$parsers.push(function(b){var c=a.prop("validity")||{};return c.badInput&&!c.typeMismatch?t:b})}function ud(b,a,c,d,e){if(y(d)){b=b(d);if(!b.constant)throw T("ngModel")("constexpr",c,d);return b(a)}return e} +function sd(b){function a(a,b){b&&!f[a]?(k.addClass(e,a),f[a]=!0):!b&&f[a]&&(k.removeClass(e,a),f[a]=!1)}function c(b,c){b=b?"-"+tc(b,"-"):"";a(kb+b,!0===c);a(vd+b,!1===c)}var d=b.ctrl,e=b.$element,f={},g=b.set,h=b.unset,l=b.parentForm,k=b.$animate;f[vd]=!(f[kb]=e.hasClass(kb));d.$setValidity=function(b,e,f){e===t?(d.$pending||(d.$pending={}),g(d.$pending,b,f)):(d.$pending&&h(d.$pending,b,f),wd(d.$pending)&&(d.$pending=t));Wa(e)?e?(h(d.$error,b,f),g(d.$$success,b,f)):(g(d.$error,b,f),h(d.$$success, +b,f)):(h(d.$error,b,f),h(d.$$success,b,f));d.$pending?(a(xd,!0),d.$valid=d.$invalid=t,c("",null)):(a(xd,!1),d.$valid=wd(d.$error),d.$invalid=!d.$valid,c("",d.$valid));e=d.$pending&&d.$pending[b]?t:d.$error[b]?!1:d.$$success[b]?!0:null;c(b,e);l.$setValidity(b,e,d)}}function wd(b){if(b)for(var a in b)return!1;return!0}function ic(b,a){b="ngClass"+b;return["$animate",function(c){function d(a,b){var c=[],d=0;a:for(;d(?:<\/\1>|)$/,Rb=/<|&#?\w+;/,ef=/<([\w:]+)/,ff=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,ia={option:[1,'"],thead:[1,"","
"],col:[2,"","
"],tr:[2,"","
"],td:[3,"","
"],_default:[0,"",""]};ia.optgroup=ia.option;ia.tbody=ia.tfoot=ia.colgroup=ia.caption=ia.thead;ia.th=ia.td;var La=R.prototype={ready:function(b){function a(){c||(c=!0,b())}var c=!1;"complete"===Y.readyState?setTimeout(a):(this.on("DOMContentLoaded",a),R(M).on("load",a))},toString:function(){var b=[];s(this,function(a){b.push(""+ +a)});return"["+b.join(", ")+"]"},eq:function(b){return 0<=b?B(this[b]):B(this[this.length+b])},length:0,push:Pf,sort:[].sort,splice:[].splice},Eb={};s("multiple selected checked disabled readOnly required open".split(" "),function(b){Eb[Q(b)]=b});var Mc={};s("input select option textarea button form details".split(" "),function(b){Mc[b]=!0});var Nc={ngMinlength:"minlength",ngMaxlength:"maxlength",ngMin:"min",ngMax:"max",ngPattern:"pattern"};s({data:Ub,removeData:xb},function(b,a){R[a]=b});s({data:Ub, +inheritedData:Db,scope:function(b){return B.data(b,"$scope")||Db(b.parentNode||b,["$isolateScope","$scope"])},isolateScope:function(b){return B.data(b,"$isolateScope")||B.data(b,"$isolateScopeNoTemplate")},controller:Ic,injector:function(b){return Db(b,"$injector")},removeAttr:function(b,a){b.removeAttribute(a)},hasClass:Ab,css:function(b,a,c){a=cb(a);if(y(c))b.style[a]=c;else return b.style[a]},attr:function(b,a,c){var d=Q(a);if(Eb[d])if(y(c))c?(b[a]=!0,b.setAttribute(a,d)):(b[a]=!1,b.removeAttribute(d)); +else return b[a]||(b.attributes.getNamedItem(a)||C).specified?d:t;else if(y(c))b.setAttribute(a,c);else if(b.getAttribute)return b=b.getAttribute(a,2),null===b?t:b},prop:function(b,a,c){if(y(c))b[a]=c;else return b[a]},text:function(){function b(a,b){if(D(b)){var d=a.nodeType;return d===na||d===pb?a.textContent:""}a.textContent=b}b.$dv="";return b}(),val:function(b,a){if(D(a)){if(b.multiple&&"select"===ua(b)){var c=[];s(b.options,function(a){a.selected&&c.push(a.value||a.text)});return 0===c.length? +null:c}return b.value}b.value=a},html:function(b,a){if(D(a))return b.innerHTML;wb(b,!0);b.innerHTML=a},empty:Jc},function(b,a){R.prototype[a]=function(a,d){var e,f,g=this.length;if(b!==Jc&&(2==b.length&&b!==Ab&&b!==Ic?a:d)===t){if(H(a)){for(e=0;e":function(a,c,d,e){return d(a,c)>e(a,c)},"<=":function(a, +c,d,e){return d(a,c)<=e(a,c)},">=":function(a,c,d,e){return d(a,c)>=e(a,c)},"&&":function(a,c,d,e){return d(a,c)&&e(a,c)},"||":function(a,c,d,e){return d(a,c)||e(a,c)},"!":function(a,c,d){return!d(a,c)},"=":!0,"|":!0}),Xf={n:"\n",f:"\f",r:"\r",t:"\t",v:"\v","'":"'",'"':'"'},gc=function(a){this.options=a};gc.prototype={constructor:gc,lex:function(a){this.text=a;this.index=0;for(this.tokens=[];this.index=a&&"string"===typeof a},isWhitespace:function(a){return" "===a||"\r"===a||"\t"===a||"\n"===a||"\v"===a||"\u00a0"===a},isIdent:function(a){return"a"<=a&&"z">=a||"A"<=a&&"Z">=a||"_"===a||"$"===a},isExpOperator:function(a){return"-"===a||"+"===a||this.isNumber(a)},throwError:function(a,c,d){d=d||this.index;c=y(c)?"s "+c+"-"+this.index+" ["+this.text.substring(c, +d)+"]":" "+d;throw la("lexerr",a,c,this.text);},readNumber:function(){for(var a="",c=this.index;this.indexa){a=this.tokens[a];var g=a.text;if(g===c||g===d||g===e||g===f||!(c||d||e||f))return a}return!1},expect:function(a,c,d,e){return(a=this.peek(a,c,d,e))?(this.tokens.shift(),a):!1},consume:function(a){if(0===this.tokens.length)throw la("ueoe",this.text);var c=this.expect(a);c||this.throwError("is unexpected, expecting ["+a+"]",this.peek());return c},unaryFn:function(a,c){var d=mb[a];return z(function(a,f){return d(a,f,c)},{constant:c.constant,inputs:[c]})},binaryFn:function(a, +c,d,e){var f=mb[c];return z(function(c,e){return f(c,e,a,d)},{constant:a.constant&&d.constant,inputs:!e&&[a,d]})},identifier:function(){for(var a=this.consume().text;this.peek(".")&&this.peekAhead(1).identifier&&!this.peekAhead(2,"(");)a+=this.consume().text+this.consume().text;return zf(a,this.options,this.text)},constant:function(){var a=this.consume().value;return z(function(){return a},{constant:!0,literal:!0})},statements:function(){for(var a=[];;)if(0","<=",">=");)a=this.binaryFn(a,c.text,this.additive());return a},additive:function(){for(var a=this.multiplicative(),c;c=this.expect("+","-");)a=this.binaryFn(a,c.text,this.multiplicative());return a},multiplicative:function(){for(var a=this.unary(),c;c=this.expect("*","/","%");)a=this.binaryFn(a,c.text,this.unary());return a},unary:function(){var a;return this.expect("+")?this.primary():(a=this.expect("-"))?this.binaryFn(hb.ZERO, +a.text,this.unary()):(a=this.expect("!"))?this.unaryFn(a.text,this.unary()):this.primary()},fieldAccess:function(a){var c=this.identifier();return z(function(d,e,f){d=f||a(d,e);return null==d?t:c(d)},{assign:function(d,e,f){(f=a(d,f))||a.assign(d,f={});return c.assign(f,e)}})},objectIndex:function(a){var c=this.text,d=this.expression();this.consume("]");return z(function(e,f){var g=a(e,f),h=d(e,f);sa(h,c);return g?ta(g[h],c):t},{assign:function(e,f,g){var h=sa(d(e,g),c);(g=ta(a(e,g),c))||a.assign(e, +g={});return g[h]=f}})},functionCall:function(a,c){var d=[];if(")"!==this.peekToken().text){do d.push(this.expression());while(this.expect(","))}this.consume(")");var e=this.text,f=d.length?[]:null;return function(g,h){var l=c?c(g,h):y(c)?t:g,k=a(g,h,l)||C;if(f)for(var m=d.length;m--;)f[m]=ta(d[m](g,h),e);ta(l,e);if(k){if(k.constructor===k)throw la("isecfn",e);if(k===Uf||k===Vf||k===Wf)throw la("isecff",e);}l=k.apply?k.apply(l,f):k(f[0],f[1],f[2],f[3],f[4]);return ta(l,e)}},arrayDeclaration:function(){var a= +[];if("]"!==this.peekToken().text){do{if(this.peek("]"))break;a.push(this.expression())}while(this.expect(","))}this.consume("]");return z(function(c,d){for(var e=[],f=0,g=a.length;fa.getHours()?c.AMPMS[0]:c.AMPMS[1]},Z:function(a){a=-1*a.getTimezoneOffset();return a=(0<=a?"+":"")+(Hb(Math[0=h};d.$observe("min",function(a){y(a)&&!V(a)&&(a=parseFloat(a,10));h=V(a)&&!isNaN(a)?a:t;e.$validate()})}if(d.max||d.ngMax){var l;e.$validators.max=function(a){return e.$isEmpty(a)|| +D(l)||a<=l};d.$observe("max",function(a){y(a)&&!V(a)&&(a=parseFloat(a,10));l=V(a)&&!isNaN(a)?a:t;e.$validate()})}},url:function(a,c,d,e,f,g){ib(a,c,d,e,f,g);hc(e);e.$$parserName="url";e.$validators.url=function(a,c){var d=a||c;return e.$isEmpty(d)||Yf.test(d)}},email:function(a,c,d,e,f,g){ib(a,c,d,e,f,g);hc(e);e.$$parserName="email";e.$validators.email=function(a,c){var d=a||c;return e.$isEmpty(d)||Zf.test(d)}},radio:function(a,c,d,e){D(d.name)&&c.attr("name",++nb);c.on("click",function(a){c[0].checked&& +e.$setViewValue(d.value,a&&a.type)});e.$render=function(){c[0].checked=d.value==e.$viewValue};d.$observe("value",e.$render)},checkbox:function(a,c,d,e,f,g,h,l){var k=ud(l,a,"ngTrueValue",d.ngTrueValue,!0),m=ud(l,a,"ngFalseValue",d.ngFalseValue,!1);c.on("click",function(a){e.$setViewValue(c[0].checked,a&&a.type)});e.$render=function(){c[0].checked=e.$viewValue};e.$isEmpty=function(a){return!1===a};e.$formatters.push(function(a){return fa(a,k)});e.$parsers.push(function(a){return a?k:m})},hidden:C, +button:C,submit:C,reset:C,file:C},xc=["$browser","$sniffer","$filter","$parse",function(a,c,d,e){return{restrict:"E",require:["?ngModel"],link:{pre:function(f,g,h,l){l[0]&&(Dd[Q(h.type)]||Dd.text)(f,g,h,l[0],c,a,d,e)}}}}],kb="ng-valid",vd="ng-invalid",Sa="ng-pristine",Kb="ng-dirty",xd="ng-pending",bg=["$scope","$exceptionHandler","$attrs","$element","$parse","$animate","$timeout","$rootScope","$q","$interpolate",function(a,c,d,e,f,g,h,l,k,m){this.$modelValue=this.$viewValue=Number.NaN;this.$$rawModelValue= +t;this.$validators={};this.$asyncValidators={};this.$parsers=[];this.$formatters=[];this.$viewChangeListeners=[];this.$untouched=!0;this.$touched=!1;this.$pristine=!0;this.$dirty=!1;this.$valid=!0;this.$invalid=!1;this.$error={};this.$$success={};this.$pending=t;this.$name=m(d.name||"",!1)(a);var p=f(d.ngModel),q=p.assign,u=p,r=q,O=null,n=this;this.$$setOptions=function(a){if((n.$options=a)&&a.getterSetter){var c=f(d.ngModel+"()"),g=f(d.ngModel+"($$$p)");u=function(a){var d=p(a);G(d)&&(d=c(a));return d}; +r=function(a,c){G(p(a))?g(a,{$$$p:n.$modelValue}):q(a,n.$modelValue)}}else if(!p.assign)throw Mb("nonassign",d.ngModel,va(e));};this.$render=C;this.$isEmpty=function(a){return D(a)||""===a||null===a||a!==a};var v=e.inheritedData("$formController")||Jb,w=0;sd({ctrl:this,$element:e,set:function(a,c){a[c]=!0},unset:function(a,c){delete a[c]},parentForm:v,$animate:g});this.$setPristine=function(){n.$dirty=!1;n.$pristine=!0;g.removeClass(e,Kb);g.addClass(e,Sa)};this.$setDirty=function(){n.$dirty=!0;n.$pristine= +!1;g.removeClass(e,Sa);g.addClass(e,Kb);v.$setDirty()};this.$setUntouched=function(){n.$touched=!1;n.$untouched=!0;g.setClass(e,"ng-untouched","ng-touched")};this.$setTouched=function(){n.$touched=!0;n.$untouched=!1;g.setClass(e,"ng-touched","ng-untouched")};this.$rollbackViewValue=function(){h.cancel(O);n.$viewValue=n.$$lastCommittedViewValue;n.$render()};this.$validate=function(){if(!V(n.$modelValue)||!isNaN(n.$modelValue)){var a=n.$$rawModelValue,c=n.$valid,d=n.$modelValue,e=n.$options&&n.$options.allowInvalid; +n.$$runValidators(n.$error[n.$$parserName||"parse"]?!1:t,a,n.$$lastCommittedViewValue,function(f){e||c===f||(n.$modelValue=f?a:t,n.$modelValue!==d&&n.$$writeModelToScope())})}};this.$$runValidators=function(a,c,d,e){function f(){var a=!0;s(n.$validators,function(e,f){var g=e(c,d);a=a&&g;h(f,g)});return a?!0:(s(n.$asyncValidators,function(a,c){h(c,null)}),!1)}function g(){var a=[],e=!0;s(n.$asyncValidators,function(f,g){var l=f(c,d);if(!l||!G(l.then))throw Mb("$asyncValidators",l);h(g,t);a.push(l.then(function(){h(g, +!0)},function(a){e=!1;h(g,!1)}))});a.length?k.all(a).then(function(){l(e)},C):l(!0)}function h(a,c){m===w&&n.$setValidity(a,c)}function l(a){m===w&&e(a)}w++;var m=w;(function(a){var c=n.$$parserName||"parse";if(a===t)h(c,null);else if(h(c,a),!a)return s(n.$validators,function(a,c){h(c,null)}),s(n.$asyncValidators,function(a,c){h(c,null)}),!1;return!0})(a)?f()?g():l(!1):l(!1)};this.$commitViewValue=function(){var a=n.$viewValue;h.cancel(O);if(n.$$lastCommittedViewValue!==a||""===a&&n.$$hasNativeValidators)n.$$lastCommittedViewValue= +a,n.$pristine&&this.$setDirty(),this.$$parseAndValidate()};this.$$parseAndValidate=function(){var c=n.$$lastCommittedViewValue,d=D(c)?t:!0;if(d)for(var e=0;ef||e.$isEmpty(a)||c.length<=f}}}}},Ac=function(){return{restrict:"A",require:"?ngModel",link:function(a,c,d,e){if(e){var f=0;d.$observe("minlength", +function(a){f=ba(a)||0;e.$validate()});e.$validators.minlength=function(a,c){return e.$isEmpty(c)||c.length>=f}}}}},we=function(){return{restrict:"A",priority:100,require:"ngModel",link:function(a,c,d,e){var f=c.attr(d.$attr.ngList)||", ",g="false"!==d.ngTrim,h=g?U(f):f;e.$parsers.push(function(a){if(!D(a)){var c=[];a&&s(a.split(h),function(a){a&&c.push(g?U(a):a)});return c}});e.$formatters.push(function(a){return x(a)?a.join(f):t});e.$isEmpty=function(a){return!a||!a.length}}}},cg=/^(true|false|\d+)$/, +ye=function(){return{restrict:"A",priority:100,compile:function(a,c){return cg.test(c.ngValue)?function(a,c,f){f.$set("value",a.$eval(f.ngValue))}:function(a,c,f){a.$watch(f.ngValue,function(a){f.$set("value",a)})}}}},ze=function(){return{restrict:"A",controller:["$scope","$attrs",function(a,c){var d=this;this.$options=a.$eval(c.ngModelOptions);this.$options.updateOn!==t?(this.$options.updateOnDefault=!1,this.$options.updateOn=U(this.$options.updateOn.replace(ag,function(){d.$options.updateOnDefault= +!0;return" "}))):this.$options.updateOnDefault=!0}]}},Zd=["$compile",function(a){return{restrict:"AC",compile:function(c){a.$$addBindingClass(c);return function(c,e,f){a.$$addBindingInfo(e,f.ngBind);e=e[0];c.$watch(f.ngBind,function(a){e.textContent=a===t?"":a})}}}}],ae=["$interpolate","$compile",function(a,c){return{compile:function(d){c.$$addBindingClass(d);return function(d,f,g){d=a(f.attr(g.$attr.ngBindTemplate));c.$$addBindingInfo(f,d.expressions);f=f[0];g.$observe("ngBindTemplate",function(a){f.textContent= +a===t?"":a})}}}}],$d=["$sce","$parse","$compile",function(a,c,d){return{restrict:"A",compile:function(e,f){var g=c(f.ngBindHtml),h=c(f.ngBindHtml,function(a){return(a||"").toString()});d.$$addBindingClass(e);return function(c,e,f){d.$$addBindingInfo(e,f.ngBindHtml);c.$watch(h,function(){e.html(a.getTrustedHtml(g(c))||"")})}}}}],be=ic("",!0),de=ic("Odd",0),ce=ic("Even",1),ee=Ja({compile:function(a,c){c.$set("ngCloak",t);a.removeClass("ng-cloak")}}),fe=[function(){return{restrict:"A",scope:!0,controller:"@", +priority:500}}],Cc={},dg={blur:!0,focus:!0};s("click dblclick mousedown mouseup mouseover mouseout mousemove mouseenter mouseleave keydown keyup keypress submit focus blur copy cut paste".split(" "),function(a){var c=ya("ng-"+a);Cc[c]=["$parse","$rootScope",function(d,e){return{restrict:"A",compile:function(f,g){var h=d(g[c],null,!0);return function(c,d){d.on(a,function(d){var f=function(){h(c,{$event:d})};dg[a]&&e.$$phase?c.$evalAsync(f):c.$apply(f)})}}}}]});var ie=["$animate",function(a){return{multiElement:!0, +transclude:"element",priority:600,terminal:!0,restrict:"A",$$tlb:!0,link:function(c,d,e,f,g){var h,l,k;c.$watch(e.ngIf,function(c){c?l||g(function(c,f){l=f;c[c.length++]=Y.createComment(" end ngIf: "+e.ngIf+" ");h={clone:c};a.enter(c,d.parent(),d)}):(k&&(k.remove(),k=null),l&&(l.$destroy(),l=null),h&&(k=tb(h.clone),a.leave(k).then(function(){k=null}),h=null))})}}}],je=["$templateRequest","$anchorScroll","$animate","$sce",function(a,c,d,e){return{restrict:"ECA",priority:400,terminal:!0,transclude:"element", +controller:ga.noop,compile:function(f,g){var h=g.ngInclude||g.src,l=g.onload||"",k=g.autoscroll;return function(f,g,q,s,r){var t=0,n,v,w,L=function(){v&&(v.remove(),v=null);n&&(n.$destroy(),n=null);w&&(d.leave(w).then(function(){v=null}),v=w,w=null)};f.$watch(e.parseAsResourceUrl(h),function(e){var h=function(){!y(k)||k&&!f.$eval(k)||c()},q=++t;e?(a(e,!0).then(function(a){if(q===t){var c=f.$new();s.template=a;a=r(c,function(a){L();d.enter(a,null,g).then(h)});n=c;w=a;n.$emit("$includeContentLoaded", +e);f.$eval(l)}},function(){q===t&&(L(),f.$emit("$includeContentError",e))}),f.$emit("$includeContentRequested",e)):(L(),s.template=null)})}}}}],Ae=["$compile",function(a){return{restrict:"ECA",priority:-400,require:"ngInclude",link:function(c,d,e,f){/SVG/.test(d[0].toString())?(d.empty(),a(Fc(f.template,Y).childNodes)(c,function(a){d.append(a)},{futureParentElement:d})):(d.html(f.template),a(d.contents())(c))}}}],ke=Ja({priority:450,compile:function(){return{pre:function(a,c,d){a.$eval(d.ngInit)}}}}), +le=Ja({terminal:!0,priority:1E3}),me=["$locale","$interpolate",function(a,c){var d=/{}/g,e=/^when(Minus)?(.+)$/;return{restrict:"EA",link:function(f,g,h){function l(a){g.text(a||"")}var k=h.count,m=h.$attr.when&&g.attr(h.$attr.when),p=h.offset||0,q=f.$eval(m)||{},u={},m=c.startSymbol(),r=c.endSymbol(),t=m+k+"-"+p+r,n=ga.noop,v;s(h,function(a,c){var d=e.exec(c);d&&(d=(d[1]?"-":"")+Q(d[2]),q[d]=g.attr(h.$attr[c]))});s(q,function(a,e){u[e]=c(a.replace(d,t))});f.$watch(k,function(c){c=parseFloat(c);var d= +isNaN(c);d||c in q||(c=a.pluralCat(c-p));c===v||d&&isNaN(v)||(n(),n=f.$watch(u[c],l),v=c)})}}}],ne=["$parse","$animate",function(a,c){var d=T("ngRepeat"),e=function(a,c,d,e,k,m,p){a[d]=e;k&&(a[k]=m);a.$index=c;a.$first=0===c;a.$last=c===p-1;a.$middle=!(a.$first||a.$last);a.$odd=!(a.$even=0===(c&1))};return{restrict:"A",multiElement:!0,transclude:"element",priority:1E3,terminal:!0,$$tlb:!0,compile:function(f,g){var h=g.ngRepeat,l=Y.createComment(" end ngRepeat: "+h+" "),k=h.match(/^\s*([\s\S]+?)\s+in\s+([\s\S]+?)(?:\s+as\s+([\s\S]+?))?(?:\s+track\s+by\s+([\s\S]+?))?\s*$/); +if(!k)throw d("iexp",h);var m=k[1],p=k[2],q=k[3],u=k[4],k=m.match(/^(?:(\s*[\$\w]+)|\(\s*([\$\w]+)\s*,\s*([\$\w]+)\s*\))$/);if(!k)throw d("iidexp",m);var r=k[3]||k[1],y=k[2];if(q&&(!/^[$a-zA-Z_][$a-zA-Z0-9_]*$/.test(q)||/^(null|undefined|this|\$index|\$first|\$middle|\$last|\$even|\$odd|\$parent)$/.test(q)))throw d("badident",q);var n,v,w,D,z={$id:Na};u?n=a(u):(w=function(a,c){return Na(c)},D=function(a){return a});return function(a,f,g,k,m){n&&(v=function(c,d,e){y&&(z[y]=c);z[r]=d;z.$index=e;return n(a, +z)});var u=ha();a.$watchCollection(p,function(g){var k,p,n=f[0],E,z=ha(),C,S,N,G,J,x,H;q&&(a[q]=g);if(Ta(g))J=g,p=v||w;else{p=v||D;J=[];for(H in g)g.hasOwnProperty(H)&&"$"!=H.charAt(0)&&J.push(H);J.sort()}C=J.length;H=Array(C);for(k=0;kF;)d=r.pop(),m(N,d.label,!1),d.element.remove()}for(;R.length>x;){l=R.pop(); +for(F=1;Fa&&q.removeOption(c)})}var n;if(!(n=r.match(d)))throw eg("iexp",r,va(f));var C=c(n[2]||n[1]),A=n[4]||n[6],D=/ as /.test(n[0])&&n[1],B=D?c(D):null,H=n[5],J=c(n[3]||""),F=c(n[2]?n[1]:A),P=c(n[7]),M=n[8]?c(n[8]):null,Q={},R=[[{element:f,label:""}]],T={};z&&(a(z)(e),z.removeClass("ng-scope"),z.remove());f.empty();f.on("change",function(){e.$apply(function(){var a=P(e)||[],c;if(u)c=[],s(f.val(),function(d){d= +M?Q[d]:d;c.push("?"===d?t:""===d?null:h(B?B:F,d,a[d]))});else{var d=M?Q[f.val()]:f.val();c="?"===d?t:""===d?null:h(B?B:F,d,a[d])}g.$setViewValue(c);p()})});g.$render=p;e.$watchCollection(P,l);e.$watchCollection(function(){var a=P(e),c;if(a&&x(a)){c=Array(a.length);for(var d=0,f=a.length;d@charset "UTF-8";[ng\\:cloak],[ng-cloak],[data-ng-cloak],[x-ng-cloak],.ng-cloak,.x-ng-cloak,.ng-hide:not(.ng-hide-animate){display:none !important;}ng\\:form{display:block;}'); +//# sourceMappingURL=angular.min.js.map diff --git a/public/assets/ngadmin/vendor/ng-admin.min.css b/public/assets/ngadmin/vendor/ng-admin.min.css new file mode 100644 index 000000000..a3c894db2 --- /dev/null +++ b/public/assets/ngadmin/vendor/ng-admin.min.css @@ -0,0 +1,8 @@ +/*! normalize.css v3.0.2 | MIT License | git.io/normalize */html{font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}body{margin:0}article,aside,details,figcaption,figure,footer,header,hgroup,main,menu,nav,section,summary{display:block}audio,canvas,progress,video{display:inline-block;vertical-align:baseline}audio:not([controls]){display:none;height:0}[hidden],template{display:none}a{background-color:transparent}a:active,a:hover{outline:0}b,strong{font-weight:700}dfn{font-style:italic}h1{margin:.67em 0}mark{background:#ff0;color:#000}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sup{top:-.5em}sub{bottom:-.25em}img{border:0}svg:not(:root){overflow:hidden}hr{-moz-box-sizing:content-box;box-sizing:content-box;height:0}pre{overflow:auto}code,kbd,pre,samp{font-size:1em}button,input,optgroup,select,textarea{color:inherit;font:inherit;margin:0}button{overflow:visible}button,select{text-transform:none}button,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}button[disabled],html input[disabled]{cursor:default}button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}input[type=checkbox],input[type=radio]{box-sizing:border-box;padding:0}input[type=number]::-webkit-inner-spin-button,input[type=number]::-webkit-outer-spin-button{height:auto}input[type=search]::-webkit-search-cancel-button,input[type=search]::-webkit-search-decoration{-webkit-appearance:none}textarea{overflow:auto}optgroup{font-weight:700}table{border-collapse:collapse;border-spacing:0}td,th{padding:0}/*! Source: https://github.com/h5bp/html5-boilerplate/blob/master/src/css/main.css */@media print{*,:after,:before{background:0 0!important;color:#000!important;box-shadow:none!important;text-shadow:none!important}a,a:visited{text-decoration:underline}a[href]:after{content:" (" attr(href) ")"}abbr[title]:after{content:" (" attr(title) ")"}a[href^="#"]:after,a[href^="javascript:"]:after{content:""}blockquote,pre{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}img,tr{page-break-inside:avoid}img{max-width:100%!important}h2,h3,p{orphans:3;widows:3}h2,h3{page-break-after:avoid}select{background:#fff!important}.navbar{display:none}.btn>.caret,.dropup>.btn>.caret{border-top-color:#000!important}.label{border:1px solid #000}.table{border-collapse:collapse!important}.table td,.table th{background-color:#fff!important}.table-bordered td,.table-bordered th{border:1px solid #ddd!important}}@font-face{font-family:'Glyphicons Halflings';src:url(../../bootstrap-sass-official/assets/fonts/bootstrap/glyphicons-halflings-regular.eot);src:url(../../bootstrap-sass-official/assets/fonts/bootstrap/glyphicons-halflings-regular.eot?#iefix) format("embedded-opentype"),url(../../bootstrap-sass-official/assets/fonts/bootstrap/glyphicons-halflings-regular.woff) format("woff"),url(../../bootstrap-sass-official/assets/fonts/bootstrap/glyphicons-halflings-regular.ttf) format("truetype"),url(../../bootstrap-sass-official/assets/fonts/bootstrap/glyphicons-halflings-regular.svg#glyphicons_halflingsregular) format("svg")}.glyphicon{position:relative;top:1px;display:inline-block;font-family:'Glyphicons Halflings';font-style:normal;font-weight:400;line-height:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.glyphicon-asterisk:before{content:"\2a"}.glyphicon-plus:before{content:"\2b"}.glyphicon-eur:before,.glyphicon-euro:before{content:"\20ac"}.glyphicon-minus:before{content:"\2212"}.glyphicon-cloud:before{content:"\2601"}.glyphicon-envelope:before{content:"\2709"}.glyphicon-pencil:before{content:"\270f"}.glyphicon-glass:before{content:"\e001"}.glyphicon-music:before{content:"\e002"}.glyphicon-search:before{content:"\e003"}.glyphicon-heart:before{content:"\e005"}.glyphicon-star:before{content:"\e006"}.glyphicon-star-empty:before{content:"\e007"}.glyphicon-user:before{content:"\e008"}.glyphicon-film:before{content:"\e009"}.glyphicon-th-large:before{content:"\e010"}.glyphicon-th:before{content:"\e011"}.glyphicon-th-list:before{content:"\e012"}.glyphicon-ok:before{content:"\e013"}.glyphicon-remove:before{content:"\e014"}.glyphicon-zoom-in:before{content:"\e015"}.glyphicon-zoom-out:before{content:"\e016"}.glyphicon-off:before{content:"\e017"}.glyphicon-signal:before{content:"\e018"}.glyphicon-cog:before{content:"\e019"}.glyphicon-trash:before{content:"\e020"}.glyphicon-home:before{content:"\e021"}.glyphicon-file:before{content:"\e022"}.glyphicon-time:before{content:"\e023"}.glyphicon-road:before{content:"\e024"}.glyphicon-download-alt:before{content:"\e025"}.glyphicon-download:before{content:"\e026"}.glyphicon-upload:before{content:"\e027"}.glyphicon-inbox:before{content:"\e028"}.glyphicon-play-circle:before{content:"\e029"}.glyphicon-repeat:before{content:"\e030"}.glyphicon-refresh:before{content:"\e031"}.glyphicon-list-alt:before{content:"\e032"}.glyphicon-lock:before{content:"\e033"}.glyphicon-flag:before{content:"\e034"}.glyphicon-headphones:before{content:"\e035"}.glyphicon-volume-off:before{content:"\e036"}.glyphicon-volume-down:before{content:"\e037"}.glyphicon-volume-up:before{content:"\e038"}.glyphicon-qrcode:before{content:"\e039"}.glyphicon-barcode:before{content:"\e040"}.glyphicon-tag:before{content:"\e041"}.glyphicon-tags:before{content:"\e042"}.glyphicon-book:before{content:"\e043"}.glyphicon-bookmark:before{content:"\e044"}.glyphicon-print:before{content:"\e045"}.glyphicon-camera:before{content:"\e046"}.glyphicon-font:before{content:"\e047"}.glyphicon-bold:before{content:"\e048"}.glyphicon-italic:before{content:"\e049"}.glyphicon-text-height:before{content:"\e050"}.glyphicon-text-width:before{content:"\e051"}.glyphicon-align-left:before{content:"\e052"}.glyphicon-align-center:before{content:"\e053"}.glyphicon-align-right:before{content:"\e054"}.glyphicon-align-justify:before{content:"\e055"}.glyphicon-list:before{content:"\e056"}.glyphicon-indent-left:before{content:"\e057"}.glyphicon-indent-right:before{content:"\e058"}.glyphicon-facetime-video:before{content:"\e059"}.glyphicon-picture:before{content:"\e060"}.glyphicon-map-marker:before{content:"\e062"}.glyphicon-adjust:before{content:"\e063"}.glyphicon-tint:before{content:"\e064"}.glyphicon-edit:before{content:"\e065"}.glyphicon-share:before{content:"\e066"}.glyphicon-check:before{content:"\e067"}.glyphicon-move:before{content:"\e068"}.glyphicon-step-backward:before{content:"\e069"}.glyphicon-fast-backward:before{content:"\e070"}.glyphicon-backward:before{content:"\e071"}.glyphicon-play:before{content:"\e072"}.glyphicon-pause:before{content:"\e073"}.glyphicon-stop:before{content:"\e074"}.glyphicon-forward:before{content:"\e075"}.glyphicon-fast-forward:before{content:"\e076"}.glyphicon-step-forward:before{content:"\e077"}.glyphicon-eject:before{content:"\e078"}.glyphicon-chevron-left:before{content:"\e079"}.glyphicon-chevron-right:before{content:"\e080"}.glyphicon-plus-sign:before{content:"\e081"}.glyphicon-minus-sign:before{content:"\e082"}.glyphicon-remove-sign:before{content:"\e083"}.glyphicon-ok-sign:before{content:"\e084"}.glyphicon-question-sign:before{content:"\e085"}.glyphicon-info-sign:before{content:"\e086"}.glyphicon-screenshot:before{content:"\e087"}.glyphicon-remove-circle:before{content:"\e088"}.glyphicon-ok-circle:before{content:"\e089"}.glyphicon-ban-circle:before{content:"\e090"}.glyphicon-arrow-left:before{content:"\e091"}.glyphicon-arrow-right:before{content:"\e092"}.glyphicon-arrow-up:before{content:"\e093"}.glyphicon-arrow-down:before{content:"\e094"}.glyphicon-share-alt:before{content:"\e095"}.glyphicon-resize-full:before{content:"\e096"}.glyphicon-resize-small:before{content:"\e097"}.glyphicon-exclamation-sign:before{content:"\e101"}.glyphicon-gift:before{content:"\e102"}.glyphicon-leaf:before{content:"\e103"}.glyphicon-fire:before{content:"\e104"}.glyphicon-eye-open:before{content:"\e105"}.glyphicon-eye-close:before{content:"\e106"}.glyphicon-warning-sign:before{content:"\e107"}.glyphicon-plane:before{content:"\e108"}.glyphicon-calendar:before{content:"\e109"}.glyphicon-random:before{content:"\e110"}.glyphicon-comment:before{content:"\e111"}.glyphicon-magnet:before{content:"\e112"}.glyphicon-chevron-up:before{content:"\e113"}.glyphicon-chevron-down:before{content:"\e114"}.glyphicon-retweet:before{content:"\e115"}.glyphicon-shopping-cart:before{content:"\e116"}.glyphicon-folder-close:before{content:"\e117"}.glyphicon-folder-open:before{content:"\e118"}.glyphicon-resize-vertical:before{content:"\e119"}.glyphicon-resize-horizontal:before{content:"\e120"}.glyphicon-hdd:before{content:"\e121"}.glyphicon-bullhorn:before{content:"\e122"}.glyphicon-bell:before{content:"\e123"}.glyphicon-certificate:before{content:"\e124"}.glyphicon-thumbs-up:before{content:"\e125"}.glyphicon-thumbs-down:before{content:"\e126"}.glyphicon-hand-right:before{content:"\e127"}.glyphicon-hand-left:before{content:"\e128"}.glyphicon-hand-up:before{content:"\e129"}.glyphicon-hand-down:before{content:"\e130"}.glyphicon-circle-arrow-right:before{content:"\e131"}.glyphicon-circle-arrow-left:before{content:"\e132"}.glyphicon-circle-arrow-up:before{content:"\e133"}.glyphicon-circle-arrow-down:before{content:"\e134"}.glyphicon-globe:before{content:"\e135"}.glyphicon-wrench:before{content:"\e136"}.glyphicon-tasks:before{content:"\e137"}.glyphicon-filter:before{content:"\e138"}.glyphicon-briefcase:before{content:"\e139"}.glyphicon-fullscreen:before{content:"\e140"}.glyphicon-dashboard:before{content:"\e141"}.glyphicon-paperclip:before{content:"\e142"}.glyphicon-heart-empty:before{content:"\e143"}.glyphicon-link:before{content:"\e144"}.glyphicon-phone:before{content:"\e145"}.glyphicon-pushpin:before{content:"\e146"}.glyphicon-usd:before{content:"\e148"}.glyphicon-gbp:before{content:"\e149"}.glyphicon-sort:before{content:"\e150"}.glyphicon-sort-by-alphabet:before{content:"\e151"}.glyphicon-sort-by-alphabet-alt:before{content:"\e152"}.glyphicon-sort-by-order:before{content:"\e153"}.glyphicon-sort-by-order-alt:before{content:"\e154"}.glyphicon-sort-by-attributes:before{content:"\e155"}.glyphicon-sort-by-attributes-alt:before{content:"\e156"}.glyphicon-unchecked:before{content:"\e157"}.glyphicon-expand:before{content:"\e158"}.glyphicon-collapse-down:before{content:"\e159"}.glyphicon-collapse-up:before{content:"\e160"}.glyphicon-log-in:before{content:"\e161"}.glyphicon-flash:before{content:"\e162"}.glyphicon-log-out:before{content:"\e163"}.glyphicon-new-window:before{content:"\e164"}.glyphicon-record:before{content:"\e165"}.glyphicon-save:before{content:"\e166"}.glyphicon-open:before{content:"\e167"}.glyphicon-saved:before{content:"\e168"}.glyphicon-import:before{content:"\e169"}.glyphicon-export:before{content:"\e170"}.glyphicon-send:before{content:"\e171"}.glyphicon-floppy-disk:before{content:"\e172"}.glyphicon-floppy-saved:before{content:"\e173"}.glyphicon-floppy-remove:before{content:"\e174"}.glyphicon-floppy-save:before{content:"\e175"}.glyphicon-floppy-open:before{content:"\e176"}.glyphicon-credit-card:before{content:"\e177"}.glyphicon-transfer:before{content:"\e178"}.glyphicon-cutlery:before{content:"\e179"}.glyphicon-header:before{content:"\e180"}.glyphicon-compressed:before{content:"\e181"}.glyphicon-earphone:before{content:"\e182"}.glyphicon-phone-alt:before{content:"\e183"}.glyphicon-tower:before{content:"\e184"}.glyphicon-stats:before{content:"\e185"}.glyphicon-sd-video:before{content:"\e186"}.glyphicon-hd-video:before{content:"\e187"}.glyphicon-subtitles:before{content:"\e188"}.glyphicon-sound-stereo:before{content:"\e189"}.glyphicon-sound-dolby:before{content:"\e190"}.glyphicon-sound-5-1:before{content:"\e191"}.glyphicon-sound-6-1:before{content:"\e192"}.glyphicon-sound-7-1:before{content:"\e193"}.glyphicon-copyright-mark:before{content:"\e194"}.glyphicon-registration-mark:before{content:"\e195"}.glyphicon-cloud-download:before{content:"\e197"}.glyphicon-cloud-upload:before{content:"\e198"}.glyphicon-tree-conifer:before{content:"\e199"}.glyphicon-tree-deciduous:before{content:"\e200"}*,:after,:before{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}html{font-size:10px;-webkit-tap-highlight-color:transparent}body{font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:14px;line-height:1.42857;color:#333}button,input,select,textarea{font-family:inherit;font-size:inherit;line-height:inherit}a{color:#337ab7;text-decoration:none}a:focus,a:hover{color:#23527c;text-decoration:underline}a:focus{outline:dotted thin;outline:-webkit-focus-ring-color auto 5px;outline-offset:-2px}figure{margin:0}img{vertical-align:middle}.img-responsive{display:block;max-width:100%;height:auto}.img-rounded{border-radius:6px}.img-thumbnail{padding:4px;line-height:1.42857;background-color:#fff;border:1px solid #ddd;border-radius:4px;-webkit-transition:all .2s ease-in-out;-o-transition:all .2s ease-in-out;transition:all .2s ease-in-out;display:inline-block;max-width:100%;height:auto}.img-circle{border-radius:50%}hr{margin-top:20px;margin-bottom:20px;border:0;border-top:1px solid #eee}.sr-only{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0,0,0,0);border:0}.sr-only-focusable:active,.sr-only-focusable:focus{position:static;width:auto;height:auto;margin:0;overflow:visible;clip:auto}.h1,.h2,.h3,.h4,.h5,.h6,h1,h2,h3,h4,h5,h6{font-family:inherit;font-weight:500;line-height:1.1;color:inherit}.h1 .small,.h1 small,.h2 .small,.h2 small,.h3 .small,.h3 small,.h4 .small,.h4 small,.h5 .small,.h5 small,.h6 .small,.h6 small,h1 .small,h1 small,h2 .small,h2 small,h3 .small,h3 small,h4 .small,h4 small,h5 .small,h5 small,h6 .small,h6 small{font-weight:400;line-height:1;color:#777}.h1,.h2,.h3,h1,h2,h3{margin-top:20px;margin-bottom:10px}.h1 .small,.h1 small,.h2 .small,.h2 small,.h3 .small,.h3 small,h1 .small,h1 small,h2 .small,h2 small,h3 .small,h3 small{font-size:65%}.h4,.h5,.h6,h4,h5,h6{margin-top:10px;margin-bottom:10px}.h4 .small,.h4 small,.h5 .small,.h5 small,.h6 .small,.h6 small,h4 .small,h4 small,h5 .small,h5 small,h6 .small,h6 small{font-size:75%}.h1,h1{font-size:36px}.h2,h2{font-size:30px}.h3,h3{font-size:24px}.h4,h4{font-size:18px}.h5,h5{font-size:14px}.h6,h6{font-size:12px}p{margin:0 0 10px}.lead{margin-bottom:20px;font-size:16px;font-weight:300;line-height:1.4}@media (min-width:768px){.lead{font-size:21px}}.small,small{font-size:85%}.mark,mark{background-color:#fcf8e3;padding:.2em}.text-left{text-align:left}.text-right{text-align:right}.text-center{text-align:center}.text-justify{text-align:justify}.text-nowrap{white-space:nowrap}.text-lowercase{text-transform:lowercase}.text-uppercase{text-transform:uppercase}.text-capitalize{text-transform:capitalize}.text-muted{color:#777}.text-primary{color:#337ab7}a.text-primary:hover{color:#286090}.text-success{color:#3c763d}a.text-success:hover{color:#2b542c}.text-info{color:#31708f}a.text-info:hover{color:#245269}.text-warning{color:#8a6d3b}a.text-warning:hover{color:#66512c}.text-danger{color:#a94442}a.text-danger:hover{color:#843534}.bg-primary{color:#fff;background-color:#337ab7}a.bg-primary:hover{background-color:#286090}.bg-success{background-color:#dff0d8}a.bg-success:hover{background-color:#c1e2b3}.bg-info{background-color:#d9edf7}a.bg-info:hover{background-color:#afd9ee}.bg-warning{background-color:#fcf8e3}a.bg-warning:hover{background-color:#f7ecb5}.bg-danger{background-color:#f2dede}a.bg-danger:hover{background-color:#e4b9b9}.page-header{padding-bottom:9px;border-bottom:1px solid #eee}ol,ul{margin-top:0;margin-bottom:10px}ol ol,ol ul,ul ol,ul ul{margin-bottom:0}.list-unstyled{padding-left:0;list-style:none}.list-inline{padding-left:0;list-style:none;margin-left:-5px}.list-inline>li{display:inline-block;padding-left:5px;padding-right:5px}dl{margin-top:0;margin-bottom:20px}dd,dt{line-height:1.42857}dt{font-weight:700}dd{margin-left:0}.dl-horizontal dd:after,.dl-horizontal dd:before{content:" ";display:table}.dl-horizontal dd:after{clear:both}@media (min-width:768px){.dl-horizontal dt{float:left;width:160px;clear:left;text-align:right;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.dl-horizontal dd{margin-left:180px}}abbr[data-original-title],abbr[title]{cursor:help;border-bottom:1px dotted #777}.initialism{font-size:90%;text-transform:uppercase}blockquote{padding:10px 20px;margin:0 0 20px;font-size:17.5px;border-left:5px solid #eee}blockquote ol:last-child,blockquote p:last-child,blockquote ul:last-child{margin-bottom:0}blockquote .small,blockquote footer,blockquote small{display:block;font-size:80%;line-height:1.42857;color:#777}blockquote .small:before,blockquote footer:before,blockquote small:before{content:'\2014 \00A0'}.blockquote-reverse,blockquote.pull-right{padding-right:15px;padding-left:0;border-right:5px solid #eee;border-left:0;text-align:right}.blockquote-reverse .small:before,.blockquote-reverse footer:before,.blockquote-reverse small:before,blockquote.pull-right .small:before,blockquote.pull-right footer:before,blockquote.pull-right small:before{content:''}.blockquote-reverse .small:after,.blockquote-reverse footer:after,.blockquote-reverse small:after,blockquote.pull-right .small:after,blockquote.pull-right footer:after,blockquote.pull-right small:after{content:'\00A0 \2014'}address{margin-bottom:20px;font-style:normal;line-height:1.42857}code,kbd,pre,samp{font-family:Menlo,Monaco,Consolas,"Courier New",monospace}code{padding:2px 4px;font-size:90%;color:#c7254e;background-color:#f9f2f4;border-radius:4px}kbd{padding:2px 4px;font-size:90%;color:#fff;background-color:#333;border-radius:3px;box-shadow:inset 0 -1px 0 rgba(0,0,0,.25)}kbd kbd{padding:0;font-size:100%;font-weight:700;box-shadow:none}pre{display:block;padding:9.5px;margin:0 0 10px;font-size:13px;line-height:1.42857;word-break:break-all;word-wrap:break-word;color:#333;background-color:#f5f5f5;border:1px solid #ccc;border-radius:4px}pre code{padding:0;font-size:inherit;color:inherit;white-space:pre-wrap;background-color:transparent;border-radius:0}.pre-scrollable{max-height:340px;overflow-y:scroll}.container{margin-right:auto;margin-left:auto;padding-left:15px;padding-right:15px}.container:after,.container:before{content:" ";display:table}.container:after{clear:both}@media (min-width:768px){.container{width:750px}}@media (min-width:992px){.container{width:970px}}@media (min-width:1200px){.container{width:1170px}}.container-fluid{margin-right:auto;margin-left:auto;padding-left:15px;padding-right:15px}.container-fluid:after,.container-fluid:before{content:" ";display:table}.container-fluid:after{clear:both}.row{margin-left:-15px;margin-right:-15px}.row:after,.row:before{content:" ";display:table}.row:after{clear:both}.col-lg-1,.col-lg-10,.col-lg-11,.col-lg-12,.col-lg-2,.col-lg-3,.col-lg-4,.col-lg-5,.col-lg-6,.col-lg-7,.col-lg-8,.col-lg-9,.col-md-1,.col-md-10,.col-md-11,.col-md-12,.col-md-2,.col-md-3,.col-md-4,.col-md-5,.col-md-6,.col-md-7,.col-md-8,.col-md-9,.col-sm-1,.col-sm-10,.col-sm-11,.col-sm-12,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9,.col-xs-1,.col-xs-10,.col-xs-11,.col-xs-12,.col-xs-2,.col-xs-3,.col-xs-4,.col-xs-5,.col-xs-6,.col-xs-7,.col-xs-8,.col-xs-9{position:relative;min-height:1px;padding-left:15px;padding-right:15px}.col-xs-1,.col-xs-10,.col-xs-11,.col-xs-12,.col-xs-2,.col-xs-3,.col-xs-4,.col-xs-5,.col-xs-6,.col-xs-7,.col-xs-8,.col-xs-9{float:left}.col-xs-1{width:8.33333%}.col-xs-2{width:16.66667%}.col-xs-3{width:25%}.col-xs-4{width:33.33333%}.col-xs-5{width:41.66667%}.col-xs-6{width:50%}.col-xs-7{width:58.33333%}.col-xs-8{width:66.66667%}.col-xs-9{width:75%}.col-xs-10{width:83.33333%}.col-xs-11{width:91.66667%}.col-xs-12{width:100%}.col-xs-pull-0{right:auto}.col-xs-pull-1{right:8.33333%}.col-xs-pull-2{right:16.66667%}.col-xs-pull-3{right:25%}.col-xs-pull-4{right:33.33333%}.col-xs-pull-5{right:41.66667%}.col-xs-pull-6{right:50%}.col-xs-pull-7{right:58.33333%}.col-xs-pull-8{right:66.66667%}.col-xs-pull-9{right:75%}.col-xs-pull-10{right:83.33333%}.col-xs-pull-11{right:91.66667%}.col-xs-pull-12{right:100%}.col-xs-push-0{left:auto}.col-xs-push-1{left:8.33333%}.col-xs-push-2{left:16.66667%}.col-xs-push-3{left:25%}.col-xs-push-4{left:33.33333%}.col-xs-push-5{left:41.66667%}.col-xs-push-6{left:50%}.col-xs-push-7{left:58.33333%}.col-xs-push-8{left:66.66667%}.col-xs-push-9{left:75%}.col-xs-push-10{left:83.33333%}.col-xs-push-11{left:91.66667%}.col-xs-push-12{left:100%}.col-xs-offset-0{margin-left:0}.col-xs-offset-1{margin-left:8.33333%}.col-xs-offset-2{margin-left:16.66667%}.col-xs-offset-3{margin-left:25%}.col-xs-offset-4{margin-left:33.33333%}.col-xs-offset-5{margin-left:41.66667%}.col-xs-offset-6{margin-left:50%}.col-xs-offset-7{margin-left:58.33333%}.col-xs-offset-8{margin-left:66.66667%}.col-xs-offset-9{margin-left:75%}.col-xs-offset-10{margin-left:83.33333%}.col-xs-offset-11{margin-left:91.66667%}.col-xs-offset-12{margin-left:100%}@media (min-width:768px){.col-sm-1,.col-sm-10,.col-sm-11,.col-sm-12,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9{float:left}.col-sm-1{width:8.33333%}.col-sm-2{width:16.66667%}.col-sm-3{width:25%}.col-sm-4{width:33.33333%}.col-sm-5{width:41.66667%}.col-sm-6{width:50%}.col-sm-7{width:58.33333%}.col-sm-8{width:66.66667%}.col-sm-9{width:75%}.col-sm-10{width:83.33333%}.col-sm-11{width:91.66667%}.col-sm-12{width:100%}.col-sm-pull-0{right:auto}.col-sm-pull-1{right:8.33333%}.col-sm-pull-2{right:16.66667%}.col-sm-pull-3{right:25%}.col-sm-pull-4{right:33.33333%}.col-sm-pull-5{right:41.66667%}.col-sm-pull-6{right:50%}.col-sm-pull-7{right:58.33333%}.col-sm-pull-8{right:66.66667%}.col-sm-pull-9{right:75%}.col-sm-pull-10{right:83.33333%}.col-sm-pull-11{right:91.66667%}.col-sm-pull-12{right:100%}.col-sm-push-0{left:auto}.col-sm-push-1{left:8.33333%}.col-sm-push-2{left:16.66667%}.col-sm-push-3{left:25%}.col-sm-push-4{left:33.33333%}.col-sm-push-5{left:41.66667%}.col-sm-push-6{left:50%}.col-sm-push-7{left:58.33333%}.col-sm-push-8{left:66.66667%}.col-sm-push-9{left:75%}.col-sm-push-10{left:83.33333%}.col-sm-push-11{left:91.66667%}.col-sm-push-12{left:100%}.col-sm-offset-0{margin-left:0}.col-sm-offset-1{margin-left:8.33333%}.col-sm-offset-2{margin-left:16.66667%}.col-sm-offset-3{margin-left:25%}.col-sm-offset-4{margin-left:33.33333%}.col-sm-offset-5{margin-left:41.66667%}.col-sm-offset-6{margin-left:50%}.col-sm-offset-7{margin-left:58.33333%}.col-sm-offset-8{margin-left:66.66667%}.col-sm-offset-9{margin-left:75%}.col-sm-offset-10{margin-left:83.33333%}.col-sm-offset-11{margin-left:91.66667%}.col-sm-offset-12{margin-left:100%}}@media (min-width:992px){.col-md-1,.col-md-10,.col-md-11,.col-md-12,.col-md-2,.col-md-3,.col-md-4,.col-md-5,.col-md-6,.col-md-7,.col-md-8,.col-md-9{float:left}.col-md-1{width:8.33333%}.col-md-2{width:16.66667%}.col-md-3{width:25%}.col-md-4{width:33.33333%}.col-md-5{width:41.66667%}.col-md-6{width:50%}.col-md-7{width:58.33333%}.col-md-8{width:66.66667%}.col-md-9{width:75%}.col-md-10{width:83.33333%}.col-md-11{width:91.66667%}.col-md-12{width:100%}.col-md-pull-0{right:auto}.col-md-pull-1{right:8.33333%}.col-md-pull-2{right:16.66667%}.col-md-pull-3{right:25%}.col-md-pull-4{right:33.33333%}.col-md-pull-5{right:41.66667%}.col-md-pull-6{right:50%}.col-md-pull-7{right:58.33333%}.col-md-pull-8{right:66.66667%}.col-md-pull-9{right:75%}.col-md-pull-10{right:83.33333%}.col-md-pull-11{right:91.66667%}.col-md-pull-12{right:100%}.col-md-push-0{left:auto}.col-md-push-1{left:8.33333%}.col-md-push-2{left:16.66667%}.col-md-push-3{left:25%}.col-md-push-4{left:33.33333%}.col-md-push-5{left:41.66667%}.col-md-push-6{left:50%}.col-md-push-7{left:58.33333%}.col-md-push-8{left:66.66667%}.col-md-push-9{left:75%}.col-md-push-10{left:83.33333%}.col-md-push-11{left:91.66667%}.col-md-push-12{left:100%}.col-md-offset-0{margin-left:0}.col-md-offset-1{margin-left:8.33333%}.col-md-offset-2{margin-left:16.66667%}.col-md-offset-3{margin-left:25%}.col-md-offset-4{margin-left:33.33333%}.col-md-offset-5{margin-left:41.66667%}.col-md-offset-6{margin-left:50%}.col-md-offset-7{margin-left:58.33333%}.col-md-offset-8{margin-left:66.66667%}.col-md-offset-9{margin-left:75%}.col-md-offset-10{margin-left:83.33333%}.col-md-offset-11{margin-left:91.66667%}.col-md-offset-12{margin-left:100%}}@media (min-width:1200px){.col-lg-1,.col-lg-10,.col-lg-11,.col-lg-12,.col-lg-2,.col-lg-3,.col-lg-4,.col-lg-5,.col-lg-6,.col-lg-7,.col-lg-8,.col-lg-9{float:left}.col-lg-1{width:8.33333%}.col-lg-2{width:16.66667%}.col-lg-3{width:25%}.col-lg-4{width:33.33333%}.col-lg-5{width:41.66667%}.col-lg-6{width:50%}.col-lg-7{width:58.33333%}.col-lg-8{width:66.66667%}.col-lg-9{width:75%}.col-lg-10{width:83.33333%}.col-lg-11{width:91.66667%}.col-lg-12{width:100%}.col-lg-pull-0{right:auto}.col-lg-pull-1{right:8.33333%}.col-lg-pull-2{right:16.66667%}.col-lg-pull-3{right:25%}.col-lg-pull-4{right:33.33333%}.col-lg-pull-5{right:41.66667%}.col-lg-pull-6{right:50%}.col-lg-pull-7{right:58.33333%}.col-lg-pull-8{right:66.66667%}.col-lg-pull-9{right:75%}.col-lg-pull-10{right:83.33333%}.col-lg-pull-11{right:91.66667%}.col-lg-pull-12{right:100%}.col-lg-push-0{left:auto}.col-lg-push-1{left:8.33333%}.col-lg-push-2{left:16.66667%}.col-lg-push-3{left:25%}.col-lg-push-4{left:33.33333%}.col-lg-push-5{left:41.66667%}.col-lg-push-6{left:50%}.col-lg-push-7{left:58.33333%}.col-lg-push-8{left:66.66667%}.col-lg-push-9{left:75%}.col-lg-push-10{left:83.33333%}.col-lg-push-11{left:91.66667%}.col-lg-push-12{left:100%}.col-lg-offset-0{margin-left:0}.col-lg-offset-1{margin-left:8.33333%}.col-lg-offset-2{margin-left:16.66667%}.col-lg-offset-3{margin-left:25%}.col-lg-offset-4{margin-left:33.33333%}.col-lg-offset-5{margin-left:41.66667%}.col-lg-offset-6{margin-left:50%}.col-lg-offset-7{margin-left:58.33333%}.col-lg-offset-8{margin-left:66.66667%}.col-lg-offset-9{margin-left:75%}.col-lg-offset-10{margin-left:83.33333%}.col-lg-offset-11{margin-left:91.66667%}.col-lg-offset-12{margin-left:100%}}table{background-color:transparent}caption{padding-top:8px;padding-bottom:8px;color:#777;text-align:left}th{text-align:left}.table{width:100%;max-width:100%;margin-bottom:20px}.table>tbody>tr>td,.table>tbody>tr>th,.table>tfoot>tr>td,.table>tfoot>tr>th,.table>thead>tr>td,.table>thead>tr>th{padding:8px;line-height:1.42857;vertical-align:top;border-top:1px solid #ddd}.table>thead>tr>th{vertical-align:bottom;border-bottom:2px solid #ddd}.table>caption+thead>tr:first-child>td,.table>caption+thead>tr:first-child>th,.table>colgroup+thead>tr:first-child>td,.table>colgroup+thead>tr:first-child>th,.table>thead:first-child>tr:first-child>td,.table>thead:first-child>tr:first-child>th{border-top:0}.table>tbody+tbody{border-top:2px solid #ddd}.table .table{background-color:#fff}.table-condensed>tbody>tr>td,.table-condensed>tbody>tr>th,.table-condensed>tfoot>tr>td,.table-condensed>tfoot>tr>th,.table-condensed>thead>tr>td,.table-condensed>thead>tr>th{padding:5px}.table-bordered,.table-bordered>tbody>tr>td,.table-bordered>tbody>tr>th,.table-bordered>tfoot>tr>td,.table-bordered>tfoot>tr>th,.table-bordered>thead>tr>td,.table-bordered>thead>tr>th{border:1px solid #ddd}.table-bordered>thead>tr>td,.table-bordered>thead>tr>th{border-bottom-width:2px}.table-striped>tbody>tr:nth-child(odd){background-color:#f9f9f9}.table-hover>tbody>tr:hover{background-color:#f5f5f5}table col[class*=col-]{position:static;float:none;display:table-column}table td[class*=col-],table th[class*=col-]{position:static;float:none;display:table-cell}.table>tbody>tr.active>td,.table>tbody>tr.active>th,.table>tbody>tr>td.active,.table>tbody>tr>th.active,.table>tfoot>tr.active>td,.table>tfoot>tr.active>th,.table>tfoot>tr>td.active,.table>tfoot>tr>th.active,.table>thead>tr.active>td,.table>thead>tr.active>th,.table>thead>tr>td.active,.table>thead>tr>th.active{background-color:#f5f5f5}.table-hover>tbody>tr.active:hover>td,.table-hover>tbody>tr.active:hover>th,.table-hover>tbody>tr:hover>.active,.table-hover>tbody>tr>td.active:hover,.table-hover>tbody>tr>th.active:hover{background-color:#e8e8e8}.table>tbody>tr.success>td,.table>tbody>tr.success>th,.table>tbody>tr>td.success,.table>tbody>tr>th.success,.table>tfoot>tr.success>td,.table>tfoot>tr.success>th,.table>tfoot>tr>td.success,.table>tfoot>tr>th.success,.table>thead>tr.success>td,.table>thead>tr.success>th,.table>thead>tr>td.success,.table>thead>tr>th.success{background-color:#dff0d8}.table-hover>tbody>tr.success:hover>td,.table-hover>tbody>tr.success:hover>th,.table-hover>tbody>tr:hover>.success,.table-hover>tbody>tr>td.success:hover,.table-hover>tbody>tr>th.success:hover{background-color:#d0e9c6}.table>tbody>tr.info>td,.table>tbody>tr.info>th,.table>tbody>tr>td.info,.table>tbody>tr>th.info,.table>tfoot>tr.info>td,.table>tfoot>tr.info>th,.table>tfoot>tr>td.info,.table>tfoot>tr>th.info,.table>thead>tr.info>td,.table>thead>tr.info>th,.table>thead>tr>td.info,.table>thead>tr>th.info{background-color:#d9edf7}.table-hover>tbody>tr.info:hover>td,.table-hover>tbody>tr.info:hover>th,.table-hover>tbody>tr:hover>.info,.table-hover>tbody>tr>td.info:hover,.table-hover>tbody>tr>th.info:hover{background-color:#c4e3f3}.table>tbody>tr.warning>td,.table>tbody>tr.warning>th,.table>tbody>tr>td.warning,.table>tbody>tr>th.warning,.table>tfoot>tr.warning>td,.table>tfoot>tr.warning>th,.table>tfoot>tr>td.warning,.table>tfoot>tr>th.warning,.table>thead>tr.warning>td,.table>thead>tr.warning>th,.table>thead>tr>td.warning,.table>thead>tr>th.warning{background-color:#fcf8e3}.table-hover>tbody>tr.warning:hover>td,.table-hover>tbody>tr.warning:hover>th,.table-hover>tbody>tr:hover>.warning,.table-hover>tbody>tr>td.warning:hover,.table-hover>tbody>tr>th.warning:hover{background-color:#faf2cc}.table>tbody>tr.danger>td,.table>tbody>tr.danger>th,.table>tbody>tr>td.danger,.table>tbody>tr>th.danger,.table>tfoot>tr.danger>td,.table>tfoot>tr.danger>th,.table>tfoot>tr>td.danger,.table>tfoot>tr>th.danger,.table>thead>tr.danger>td,.table>thead>tr.danger>th,.table>thead>tr>td.danger,.table>thead>tr>th.danger{background-color:#f2dede}.table-hover>tbody>tr.danger:hover>td,.table-hover>tbody>tr.danger:hover>th,.table-hover>tbody>tr:hover>.danger,.table-hover>tbody>tr>td.danger:hover,.table-hover>tbody>tr>th.danger:hover{background-color:#ebcccc}.table-responsive{overflow-x:auto;min-height:.01%}@media screen and (max-width:767px){.table-responsive{width:100%;margin-bottom:15px;overflow-y:hidden;-ms-overflow-style:-ms-autohiding-scrollbar;border:1px solid #ddd}.table-responsive>.table{margin-bottom:0}.table-responsive>.table>tbody>tr>td,.table-responsive>.table>tbody>tr>th,.table-responsive>.table>tfoot>tr>td,.table-responsive>.table>tfoot>tr>th,.table-responsive>.table>thead>tr>td,.table-responsive>.table>thead>tr>th{white-space:nowrap}.table-responsive>.table-bordered{border:0}.table-responsive>.table-bordered>tbody>tr>td:first-child,.table-responsive>.table-bordered>tbody>tr>th:first-child,.table-responsive>.table-bordered>tfoot>tr>td:first-child,.table-responsive>.table-bordered>tfoot>tr>th:first-child,.table-responsive>.table-bordered>thead>tr>td:first-child,.table-responsive>.table-bordered>thead>tr>th:first-child{border-left:0}.table-responsive>.table-bordered>tbody>tr>td:last-child,.table-responsive>.table-bordered>tbody>tr>th:last-child,.table-responsive>.table-bordered>tfoot>tr>td:last-child,.table-responsive>.table-bordered>tfoot>tr>th:last-child,.table-responsive>.table-bordered>thead>tr>td:last-child,.table-responsive>.table-bordered>thead>tr>th:last-child{border-right:0}.table-responsive>.table-bordered>tbody>tr:last-child>td,.table-responsive>.table-bordered>tbody>tr:last-child>th,.table-responsive>.table-bordered>tfoot>tr:last-child>td,.table-responsive>.table-bordered>tfoot>tr:last-child>th{border-bottom:0}}fieldset{padding:0;margin:0;border:0;min-width:0}legend{display:block;width:100%;padding:0;margin-bottom:20px;font-size:21px;line-height:inherit;color:#333;border:0;border-bottom:1px solid #e5e5e5}label{display:inline-block;max-width:100%;margin-bottom:5px;font-weight:700}input[type=search]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}input[type=checkbox],input[type=radio]{margin:4px 0 0;line-height:normal}input[type=file]{display:block}input[type=range]{display:block;width:100%}select[multiple],select[size]{height:auto}input[type=checkbox]:focus,input[type=file]:focus,input[type=radio]:focus{outline:dotted thin;outline:-webkit-focus-ring-color auto 5px;outline-offset:-2px}output{display:block;padding-top:7px;font-size:14px;line-height:1.42857;color:#555}.form-control{display:block;width:100%;height:34px;padding:6px 12px;font-size:14px;line-height:1.42857;color:#555;background-color:#fff;background-image:none;border:1px solid #ccc;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075);-webkit-transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s;-o-transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s;transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s}.form-control:focus{border-color:#66afe9;outline:0;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,.6);box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,.6)}.form-control::-moz-placeholder{color:#999;opacity:1}.form-control:-ms-input-placeholder{color:#999}.form-control::-webkit-input-placeholder{color:#999}.form-control[disabled],.form-control[readonly],fieldset[disabled] .form-control{cursor:not-allowed;background-color:#eee;opacity:1}textarea.form-control{height:auto}input[type=search]{-webkit-appearance:none}@media screen and (-webkit-min-device-pixel-ratio:0){input[type=date],input[type=datetime-local],input[type=month],input[type=time]{line-height:34px}.input-group-sm>.input-group-btn>input[type=date].btn,.input-group-sm>.input-group-btn>input[type=datetime-local].btn,.input-group-sm>.input-group-btn>input[type=month].btn,.input-group-sm>.input-group-btn>input[type=time].btn,.input-group-sm>input[type=date].form-control,.input-group-sm>input[type=date].input-group-addon,.input-group-sm>input[type=datetime-local].form-control,.input-group-sm>input[type=datetime-local].input-group-addon,.input-group-sm>input[type=month].form-control,.input-group-sm>input[type=month].input-group-addon,.input-group-sm>input[type=time].form-control,.input-group-sm>input[type=time].input-group-addon,input[type=date].input-sm,input[type=datetime-local].input-sm,input[type=month].input-sm,input[type=time].input-sm{line-height:30px}.input-group-lg>.input-group-btn>input[type=date].btn,.input-group-lg>.input-group-btn>input[type=datetime-local].btn,.input-group-lg>.input-group-btn>input[type=month].btn,.input-group-lg>.input-group-btn>input[type=time].btn,.input-group-lg>input[type=date].form-control,.input-group-lg>input[type=date].input-group-addon,.input-group-lg>input[type=datetime-local].form-control,.input-group-lg>input[type=datetime-local].input-group-addon,.input-group-lg>input[type=month].form-control,.input-group-lg>input[type=month].input-group-addon,.input-group-lg>input[type=time].form-control,.input-group-lg>input[type=time].input-group-addon,input[type=date].input-lg,input[type=datetime-local].input-lg,input[type=month].input-lg,input[type=time].input-lg{line-height:46px}}.form-group{margin-bottom:15px}.checkbox,.radio{position:relative;display:block;margin-top:10px;margin-bottom:10px}.checkbox label,.radio label{min-height:20px;padding-left:20px;margin-bottom:0;font-weight:400;cursor:pointer}.checkbox input[type=checkbox],.checkbox-inline input[type=checkbox],.radio input[type=radio],.radio-inline input[type=radio]{position:absolute;margin-left:-20px}.checkbox+.checkbox,.radio+.radio{margin-top:-5px}.checkbox-inline,.radio-inline{display:inline-block;padding-left:20px;margin-bottom:0;vertical-align:middle;font-weight:400;cursor:pointer}.checkbox-inline+.checkbox-inline,.radio-inline+.radio-inline{margin-top:0;margin-left:10px}.checkbox-inline.disabled,.checkbox.disabled label,.radio-inline.disabled,.radio.disabled label,fieldset[disabled] .checkbox label,fieldset[disabled] .checkbox-inline,fieldset[disabled] .radio label,fieldset[disabled] .radio-inline,fieldset[disabled] input[type=checkbox],fieldset[disabled] input[type=radio],input[type=checkbox].disabled,input[type=checkbox][disabled],input[type=radio].disabled,input[type=radio][disabled]{cursor:not-allowed}.form-control-static{padding-top:7px;padding-bottom:7px;margin-bottom:0}.form-control-static.input-lg,.form-control-static.input-sm,.input-group-lg>.form-control-static.form-control,.input-group-lg>.form-control-static.input-group-addon,.input-group-lg>.input-group-btn>.form-control-static.btn,.input-group-sm>.form-control-static.form-control,.input-group-sm>.form-control-static.input-group-addon,.input-group-sm>.input-group-btn>.form-control-static.btn{padding-left:0;padding-right:0}.form-group-sm .form-control,.input-group-sm>.form-control,.input-group-sm>.input-group-addon,.input-group-sm>.input-group-btn>.btn,.input-sm{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}.form-group-sm .form-control,.input-group-sm>.input-group-btn>select.btn,.input-group-sm>select.form-control,.input-group-sm>select.input-group-addon,select.input-sm{height:30px;line-height:30px}.form-group-sm .form-control,.input-group-sm>.input-group-btn>select[multiple].btn,.input-group-sm>.input-group-btn>textarea.btn,.input-group-sm>select[multiple].form-control,.input-group-sm>select[multiple].input-group-addon,.input-group-sm>textarea.form-control,.input-group-sm>textarea.input-group-addon,select[multiple].input-sm,textarea.input-sm{height:auto}.form-group-lg .form-control,.input-group-lg>.form-control,.input-group-lg>.input-group-addon,.input-group-lg>.input-group-btn>.btn,.input-lg{height:46px;padding:10px 16px;font-size:18px;line-height:1.33;border-radius:6px}.form-group-lg .form-control,.input-group-lg>.input-group-btn>select.btn,.input-group-lg>select.form-control,.input-group-lg>select.input-group-addon,select.input-lg{height:46px;line-height:46px}.form-group-lg .form-control,.input-group-lg>.input-group-btn>select[multiple].btn,.input-group-lg>.input-group-btn>textarea.btn,.input-group-lg>select[multiple].form-control,.input-group-lg>select[multiple].input-group-addon,.input-group-lg>textarea.form-control,.input-group-lg>textarea.input-group-addon,select[multiple].input-lg,textarea.input-lg{height:auto}.has-feedback{position:relative}.has-feedback .form-control{padding-right:42.5px}.form-control-feedback{position:absolute;top:0;right:0;z-index:2;display:block;width:34px;height:34px;line-height:34px;text-align:center;pointer-events:none}.input-group-lg>.form-control+.form-control-feedback,.input-group-lg>.input-group-addon+.form-control-feedback,.input-group-lg>.input-group-btn>.btn+.form-control-feedback,.input-lg+.form-control-feedback{width:46px;height:46px;line-height:46px}.input-group-sm>.form-control+.form-control-feedback,.input-group-sm>.input-group-addon+.form-control-feedback,.input-group-sm>.input-group-btn>.btn+.form-control-feedback,.input-sm+.form-control-feedback{width:30px;height:30px;line-height:30px}.has-success .checkbox,.has-success .checkbox-inline,.has-success .control-label,.has-success .help-block,.has-success .radio,.has-success .radio-inline,.has-success.checkbox label,.has-success.checkbox-inline label,.has-success.radio label,.has-success.radio-inline label{color:#3c763d}.has-success .form-control{border-color:#3c763d;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.has-success .form-control:focus{border-color:#2b542c;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #67b168;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #67b168}.has-success .input-group-addon{color:#3c763d;border-color:#3c763d;background-color:#dff0d8}.has-success .form-control-feedback{color:#3c763d}.has-warning .checkbox,.has-warning .checkbox-inline,.has-warning .control-label,.has-warning .help-block,.has-warning .radio,.has-warning .radio-inline,.has-warning.checkbox label,.has-warning.checkbox-inline label,.has-warning.radio label,.has-warning.radio-inline label{color:#8a6d3b}.has-warning .form-control{border-color:#8a6d3b;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.has-warning .form-control:focus{border-color:#66512c;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #c0a16b;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #c0a16b}.has-warning .input-group-addon{color:#8a6d3b;border-color:#8a6d3b;background-color:#fcf8e3}.has-warning .form-control-feedback{color:#8a6d3b}.has-error .checkbox,.has-error .checkbox-inline,.has-error .control-label,.has-error .help-block,.has-error .radio,.has-error .radio-inline,.has-error.checkbox label,.has-error.checkbox-inline label,.has-error.radio label,.has-error.radio-inline label{color:#a94442}.has-error .form-control{border-color:#a94442;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.has-error .form-control:focus{border-color:#843534;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #ce8483;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #ce8483}.has-error .input-group-addon{color:#a94442;border-color:#a94442;background-color:#f2dede}.has-error .form-control-feedback{color:#a94442}.has-feedback label~.form-control-feedback{top:25px}.has-feedback label.sr-only~.form-control-feedback{top:0}.help-block{display:block;margin-top:5px;margin-bottom:10px;color:#737373}@media (min-width:768px){.form-inline .form-group{display:inline-block;margin-bottom:0;vertical-align:middle}.form-inline .form-control{display:inline-block;width:auto;vertical-align:middle}.form-inline .form-control-static{display:inline-block}.form-inline .input-group{display:inline-table;vertical-align:middle}.form-inline .input-group .form-control,.form-inline .input-group .input-group-addon,.form-inline .input-group .input-group-btn{width:auto}.form-inline .input-group>.form-control{width:100%}.form-inline .control-label{margin-bottom:0;vertical-align:middle}.form-inline .checkbox,.form-inline .radio{display:inline-block;margin-top:0;margin-bottom:0;vertical-align:middle}.form-inline .checkbox label,.form-inline .radio label{padding-left:0}.form-inline .checkbox input[type=checkbox],.form-inline .radio input[type=radio]{position:relative;margin-left:0}.form-inline .has-feedback .form-control-feedback{top:0}}.form-horizontal .checkbox,.form-horizontal .checkbox-inline,.form-horizontal .radio,.form-horizontal .radio-inline{margin-top:0;margin-bottom:0;padding-top:7px}.form-horizontal .checkbox,.form-horizontal .radio{min-height:27px}.form-horizontal .form-group{margin-left:-15px;margin-right:-15px}.form-horizontal .form-group:after,.form-horizontal .form-group:before{content:" ";display:table}.form-horizontal .form-group:after{clear:both}@media (min-width:768px){.form-horizontal .control-label{text-align:right;margin-bottom:0;padding-top:7px}}.form-horizontal .has-feedback .form-control-feedback{right:15px}@media (min-width:768px){.form-horizontal .form-group-lg .control-label{padding-top:14.3px}}@media (min-width:768px){.form-horizontal .form-group-sm .control-label{padding-top:6px}}.btn{display:inline-block;margin-bottom:0;font-weight:400;text-align:center;vertical-align:middle;touch-action:manipulation;cursor:pointer;background-image:none;border:1px solid transparent;white-space:nowrap;padding:6px 12px;font-size:14px;line-height:1.42857;border-radius:4px;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.btn.active.focus,.btn.active:focus,.btn.focus,.btn:active.focus,.btn:active:focus,.btn:focus{outline:dotted thin;outline:-webkit-focus-ring-color auto 5px;outline-offset:-2px}.btn.focus,.btn:focus,.btn:hover{color:#333;text-decoration:none}.btn.active,.btn:active{outline:0;background-image:none;-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125);box-shadow:inset 0 3px 5px rgba(0,0,0,.125)}.btn.disabled,.btn[disabled],fieldset[disabled] .btn{cursor:not-allowed;pointer-events:none;opacity:.65;filter:alpha(opacity=65);-webkit-box-shadow:none;box-shadow:none}.btn-default{color:#333;background-color:#fff;border-color:#ccc}.btn-default.active,.btn-default.focus,.btn-default:active,.btn-default:focus,.btn-default:hover,.open>.btn-default.dropdown-toggle{color:#333;background-color:#e6e6e6;border-color:#adadad}.btn-default.active,.btn-default:active,.open>.btn-default.dropdown-toggle{background-image:none}.btn-default.disabled,.btn-default.disabled.active,.btn-default.disabled.focus,.btn-default.disabled:active,.btn-default.disabled:focus,.btn-default.disabled:hover,.btn-default[disabled],.btn-default[disabled].active,.btn-default[disabled].focus,.btn-default[disabled]:active,.btn-default[disabled]:focus,.btn-default[disabled]:hover,fieldset[disabled] .btn-default,fieldset[disabled] .btn-default.active,fieldset[disabled] .btn-default.focus,fieldset[disabled] .btn-default:active,fieldset[disabled] .btn-default:focus,fieldset[disabled] .btn-default:hover{background-color:#fff;border-color:#ccc}.btn-default .badge{color:#fff;background-color:#333}.btn-primary{color:#fff;background-color:#337ab7;border-color:#2e6da4}.btn-primary.active,.btn-primary.focus,.btn-primary:active,.btn-primary:focus,.btn-primary:hover,.open>.btn-primary.dropdown-toggle{color:#fff;background-color:#286090;border-color:#204d74}.btn-primary.active,.btn-primary:active,.open>.btn-primary.dropdown-toggle{background-image:none}.btn-primary.disabled,.btn-primary.disabled.active,.btn-primary.disabled.focus,.btn-primary.disabled:active,.btn-primary.disabled:focus,.btn-primary.disabled:hover,.btn-primary[disabled],.btn-primary[disabled].active,.btn-primary[disabled].focus,.btn-primary[disabled]:active,.btn-primary[disabled]:focus,.btn-primary[disabled]:hover,fieldset[disabled] .btn-primary,fieldset[disabled] .btn-primary.active,fieldset[disabled] .btn-primary.focus,fieldset[disabled] .btn-primary:active,fieldset[disabled] .btn-primary:focus,fieldset[disabled] .btn-primary:hover{background-color:#337ab7;border-color:#2e6da4}.btn-primary .badge{color:#337ab7;background-color:#fff}.btn-success{color:#fff;background-color:#5cb85c;border-color:#4cae4c}.btn-success.active,.btn-success.focus,.btn-success:active,.btn-success:focus,.btn-success:hover,.open>.btn-success.dropdown-toggle{color:#fff;background-color:#449d44;border-color:#398439}.btn-success.active,.btn-success:active,.open>.btn-success.dropdown-toggle{background-image:none}.btn-success.disabled,.btn-success.disabled.active,.btn-success.disabled.focus,.btn-success.disabled:active,.btn-success.disabled:focus,.btn-success.disabled:hover,.btn-success[disabled],.btn-success[disabled].active,.btn-success[disabled].focus,.btn-success[disabled]:active,.btn-success[disabled]:focus,.btn-success[disabled]:hover,fieldset[disabled] .btn-success,fieldset[disabled] .btn-success.active,fieldset[disabled] .btn-success.focus,fieldset[disabled] .btn-success:active,fieldset[disabled] .btn-success:focus,fieldset[disabled] .btn-success:hover{background-color:#5cb85c;border-color:#4cae4c}.btn-success .badge{color:#5cb85c;background-color:#fff}.btn-info{color:#fff;background-color:#5bc0de;border-color:#46b8da}.btn-info.active,.btn-info.focus,.btn-info:active,.btn-info:focus,.btn-info:hover,.open>.btn-info.dropdown-toggle{color:#fff;background-color:#31b0d5;border-color:#269abc}.btn-info.active,.btn-info:active,.open>.btn-info.dropdown-toggle{background-image:none}.btn-info.disabled,.btn-info.disabled.active,.btn-info.disabled.focus,.btn-info.disabled:active,.btn-info.disabled:focus,.btn-info.disabled:hover,.btn-info[disabled],.btn-info[disabled].active,.btn-info[disabled].focus,.btn-info[disabled]:active,.btn-info[disabled]:focus,.btn-info[disabled]:hover,fieldset[disabled] .btn-info,fieldset[disabled] .btn-info.active,fieldset[disabled] .btn-info.focus,fieldset[disabled] .btn-info:active,fieldset[disabled] .btn-info:focus,fieldset[disabled] .btn-info:hover{background-color:#5bc0de;border-color:#46b8da}.btn-info .badge{color:#5bc0de;background-color:#fff}.btn-warning{color:#fff;background-color:#f0ad4e;border-color:#eea236}.btn-warning.active,.btn-warning.focus,.btn-warning:active,.btn-warning:focus,.btn-warning:hover,.open>.btn-warning.dropdown-toggle{color:#fff;background-color:#ec971f;border-color:#d58512}.btn-warning.active,.btn-warning:active,.open>.btn-warning.dropdown-toggle{background-image:none}.btn-warning.disabled,.btn-warning.disabled.active,.btn-warning.disabled.focus,.btn-warning.disabled:active,.btn-warning.disabled:focus,.btn-warning.disabled:hover,.btn-warning[disabled],.btn-warning[disabled].active,.btn-warning[disabled].focus,.btn-warning[disabled]:active,.btn-warning[disabled]:focus,.btn-warning[disabled]:hover,fieldset[disabled] .btn-warning,fieldset[disabled] .btn-warning.active,fieldset[disabled] .btn-warning.focus,fieldset[disabled] .btn-warning:active,fieldset[disabled] .btn-warning:focus,fieldset[disabled] .btn-warning:hover{background-color:#f0ad4e;border-color:#eea236}.btn-warning .badge{color:#f0ad4e;background-color:#fff}.btn-danger{color:#fff;background-color:#d9534f;border-color:#d43f3a}.btn-danger.active,.btn-danger.focus,.btn-danger:active,.btn-danger:focus,.btn-danger:hover,.open>.btn-danger.dropdown-toggle{color:#fff;background-color:#c9302c;border-color:#ac2925}.btn-danger.active,.btn-danger:active,.open>.btn-danger.dropdown-toggle{background-image:none}.btn-danger.disabled,.btn-danger.disabled.active,.btn-danger.disabled.focus,.btn-danger.disabled:active,.btn-danger.disabled:focus,.btn-danger.disabled:hover,.btn-danger[disabled],.btn-danger[disabled].active,.btn-danger[disabled].focus,.btn-danger[disabled]:active,.btn-danger[disabled]:focus,.btn-danger[disabled]:hover,fieldset[disabled] .btn-danger,fieldset[disabled] .btn-danger.active,fieldset[disabled] .btn-danger.focus,fieldset[disabled] .btn-danger:active,fieldset[disabled] .btn-danger:focus,fieldset[disabled] .btn-danger:hover{background-color:#d9534f;border-color:#d43f3a}.btn-danger .badge{color:#d9534f;background-color:#fff}.btn-link{color:#337ab7;font-weight:400;border-radius:0}.btn-link,.btn-link.active,.btn-link:active,.btn-link[disabled],fieldset[disabled] .btn-link{background-color:transparent;-webkit-box-shadow:none;box-shadow:none}.btn-link,.btn-link:active,.btn-link:focus,.btn-link:hover{border-color:transparent}.btn-link:focus,.btn-link:hover{color:#23527c;text-decoration:underline;background-color:transparent}.btn-link[disabled]:focus,.btn-link[disabled]:hover,fieldset[disabled] .btn-link:focus,fieldset[disabled] .btn-link:hover{color:#777;text-decoration:none}.btn-group-lg>.btn,.btn-lg{padding:10px 16px;font-size:18px;line-height:1.33;border-radius:6px}.btn-group-sm>.btn,.btn-sm{padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}.btn-group-xs>.btn,.btn-xs{padding:1px 5px;font-size:12px;line-height:1.5;border-radius:3px}.btn-block{display:block;width:100%}.btn-block+.btn-block{margin-top:5px}input[type=button].btn-block,input[type=reset].btn-block,input[type=submit].btn-block{width:100%}.fade{opacity:0;-webkit-transition:opacity .15s linear;-o-transition:opacity .15s linear;transition:opacity .15s linear}.fade.in{opacity:1}.collapse{display:none;visibility:hidden}.collapse.in{display:block;visibility:visible}tr.collapse.in{display:table-row}tbody.collapse.in{display:table-row-group}.collapsing{position:relative;height:0;overflow:hidden;-webkit-transition-property:height,visibility;transition-property:height,visibility;-webkit-transition-duration:.35s;transition-duration:.35s;-webkit-transition-timing-function:ease;transition-timing-function:ease}.caret{display:inline-block;width:0;height:0;margin-left:2px;vertical-align:middle;border-top:4px solid;border-right:4px solid transparent;border-left:4px solid transparent}.dropdown{position:relative}.dropdown-toggle:focus{outline:0}.dropdown-menu{position:absolute;top:100%;left:0;z-index:1000;display:none;float:left;min-width:160px;padding:5px 0;margin:2px 0 0;list-style:none;font-size:14px;text-align:left;background-color:#fff;border:1px solid #ccc;border:1px solid rgba(0,0,0,.15);border-radius:4px;-webkit-box-shadow:0 6px 12px rgba(0,0,0,.175);box-shadow:0 6px 12px rgba(0,0,0,.175);background-clip:padding-box}.dropdown-menu.pull-right{right:0;left:auto}.dropdown-menu .divider{height:1px;margin:9px 0;overflow:hidden;background-color:#e5e5e5}.dropdown-menu>li>a{display:block;padding:3px 20px;clear:both;font-weight:400;line-height:1.42857;color:#333;white-space:nowrap}.dropdown-menu>li>a:focus,.dropdown-menu>li>a:hover{text-decoration:none;color:#262626;background-color:#f5f5f5}.dropdown-menu>.active>a,.dropdown-menu>.active>a:focus,.dropdown-menu>.active>a:hover{color:#fff;text-decoration:none;outline:0;background-color:#337ab7}.dropdown-menu>.disabled>a,.dropdown-menu>.disabled>a:focus,.dropdown-menu>.disabled>a:hover{color:#777}.dropdown-menu>.disabled>a:focus,.dropdown-menu>.disabled>a:hover{text-decoration:none;background-color:transparent;background-image:none;filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);cursor:not-allowed}.open>.dropdown-menu{display:block}.open>a{outline:0}.dropdown-menu-right{left:auto;right:0}.dropdown-menu-left{left:0;right:auto}.dropdown-header{display:block;padding:3px 20px;font-size:12px;line-height:1.42857;color:#777;white-space:nowrap}.dropdown-backdrop{position:fixed;left:0;right:0;bottom:0;top:0;z-index:990}.pull-right>.dropdown-menu{right:0;left:auto}.dropup .caret,.navbar-fixed-bottom .dropdown .caret{border-top:0;border-bottom:4px solid;content:""}.dropup .dropdown-menu,.navbar-fixed-bottom .dropdown .dropdown-menu{top:auto;bottom:100%;margin-bottom:1px}@media (min-width:768px){.navbar-right .dropdown-menu{right:0;left:auto}.navbar-right .dropdown-menu-left{left:0;right:auto}}.btn-group,.btn-group-vertical{position:relative;display:inline-block;vertical-align:middle}.btn-group-vertical>.btn,.btn-group>.btn{position:relative;float:left}.btn-group-vertical>.btn.active,.btn-group-vertical>.btn:active,.btn-group-vertical>.btn:focus,.btn-group-vertical>.btn:hover,.btn-group>.btn.active,.btn-group>.btn:active,.btn-group>.btn:focus,.btn-group>.btn:hover{z-index:2}.btn-group .btn+.btn,.btn-group .btn+.btn-group,.btn-group .btn-group+.btn,.btn-group .btn-group+.btn-group{margin-left:-1px}.btn-toolbar{margin-left:-5px}.btn-toolbar:after,.btn-toolbar:before{content:" ";display:table}.btn-toolbar:after{clear:both}.btn-toolbar .btn-group,.btn-toolbar .input-group{float:left}.btn-toolbar>.btn,.btn-toolbar>.btn-group,.btn-toolbar>.input-group{margin-left:5px}.btn-group>.btn:not(:first-child):not(:last-child):not(.dropdown-toggle){border-radius:0}.btn-group>.btn:first-child{margin-left:0}.btn-group>.btn:first-child:not(:last-child):not(.dropdown-toggle){border-bottom-right-radius:0;border-top-right-radius:0}.btn-group>.btn:last-child:not(:first-child),.btn-group>.dropdown-toggle:not(:first-child){border-bottom-left-radius:0;border-top-left-radius:0}.btn-group>.btn-group{float:left}.btn-group>.btn-group:not(:first-child):not(:last-child)>.btn{border-radius:0}.btn-group>.btn-group:first-child>.btn:last-child,.btn-group>.btn-group:first-child>.dropdown-toggle{border-bottom-right-radius:0;border-top-right-radius:0}.btn-group>.btn-group:last-child>.btn:first-child{border-bottom-left-radius:0;border-top-left-radius:0}.btn-group .dropdown-toggle:active,.btn-group.open .dropdown-toggle{outline:0}.btn-group>.btn+.dropdown-toggle{padding-left:8px;padding-right:8px}.btn-group-lg.btn-group>.btn+.dropdown-toggle,.btn-group>.btn-lg+.dropdown-toggle{padding-left:12px;padding-right:12px}.btn-group.open .dropdown-toggle{-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125);box-shadow:inset 0 3px 5px rgba(0,0,0,.125)}.btn-group.open .dropdown-toggle.btn-link{-webkit-box-shadow:none;box-shadow:none}.btn .caret{margin-left:0}.btn-group-lg>.btn .caret,.btn-lg .caret{border-width:5px 5px 0}.dropup .btn-group-lg>.btn .caret,.dropup .btn-lg .caret{border-width:0 5px 5px}.btn-group-vertical>.btn,.btn-group-vertical>.btn-group,.btn-group-vertical>.btn-group>.btn{display:block;float:none;width:100%;max-width:100%}.btn-group-vertical>.btn-group:after,.btn-group-vertical>.btn-group:before{content:" ";display:table}.btn-group-vertical>.btn-group:after{clear:both}.btn-group-vertical>.btn-group>.btn{float:none}.btn-group-vertical>.btn+.btn,.btn-group-vertical>.btn+.btn-group,.btn-group-vertical>.btn-group+.btn,.btn-group-vertical>.btn-group+.btn-group{margin-top:-1px;margin-left:0}.btn-group-vertical>.btn:not(:first-child):not(:last-child){border-radius:0}.btn-group-vertical>.btn:first-child:not(:last-child){border-top-right-radius:4px;border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn:last-child:not(:first-child){border-bottom-left-radius:4px;border-top-right-radius:0;border-top-left-radius:0}.btn-group-vertical>.btn-group:not(:first-child):not(:last-child)>.btn{border-radius:0}.btn-group-vertical>.btn-group:first-child:not(:last-child)>.btn:last-child,.btn-group-vertical>.btn-group:first-child:not(:last-child)>.dropdown-toggle{border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn-group:last-child:not(:first-child)>.btn:first-child{border-top-right-radius:0;border-top-left-radius:0}.btn-group-justified{display:table;width:100%;table-layout:fixed;border-collapse:separate}.btn-group-justified>.btn,.btn-group-justified>.btn-group{float:none;display:table-cell;width:1%}.btn-group-justified>.btn-group .btn{width:100%}.btn-group-justified>.btn-group .dropdown-menu{left:auto}[data-toggle=buttons]>.btn input[type=checkbox],[data-toggle=buttons]>.btn input[type=radio],[data-toggle=buttons]>.btn-group>.btn input[type=checkbox],[data-toggle=buttons]>.btn-group>.btn input[type=radio]{position:absolute;clip:rect(0,0,0,0);pointer-events:none}.input-group{position:relative;display:table;border-collapse:separate}.input-group[class*=col-]{float:none;padding-left:0;padding-right:0}.input-group .form-control{position:relative;z-index:2;float:left;width:100%;margin-bottom:0}.input-group .form-control,.input-group-addon,.input-group-btn{display:table-cell}.input-group .form-control:not(:first-child):not(:last-child),.input-group-addon:not(:first-child):not(:last-child),.input-group-btn:not(:first-child):not(:last-child){border-radius:0}.input-group-addon,.input-group-btn{width:1%;white-space:nowrap;vertical-align:middle}.input-group-addon{padding:6px 12px;font-size:14px;font-weight:400;line-height:1;color:#555;text-align:center;background-color:#eee;border:1px solid #ccc;border-radius:4px}.input-group-addon.input-sm,.input-group-sm>.input-group-addon,.input-group-sm>.input-group-btn>.input-group-addon.btn{padding:5px 10px;font-size:12px;border-radius:3px}.input-group-addon.input-lg,.input-group-lg>.input-group-addon,.input-group-lg>.input-group-btn>.input-group-addon.btn{padding:10px 16px;font-size:18px;border-radius:6px}.input-group-addon input[type=checkbox],.input-group-addon input[type=radio]{margin-top:0}.input-group .form-control:first-child,.input-group-addon:first-child,.input-group-btn:first-child>.btn,.input-group-btn:first-child>.btn-group>.btn,.input-group-btn:first-child>.dropdown-toggle,.input-group-btn:last-child>.btn-group:not(:last-child)>.btn,.input-group-btn:last-child>.btn:not(:last-child):not(.dropdown-toggle){border-bottom-right-radius:0;border-top-right-radius:0}.input-group-addon:first-child{border-right:0}.input-group .form-control:last-child,.input-group-addon:last-child,.input-group-btn:first-child>.btn-group:not(:first-child)>.btn,.input-group-btn:first-child>.btn:not(:first-child),.input-group-btn:last-child>.btn,.input-group-btn:last-child>.btn-group>.btn,.input-group-btn:last-child>.dropdown-toggle{border-bottom-left-radius:0;border-top-left-radius:0}.input-group-addon:last-child{border-left:0}.input-group-btn{position:relative;font-size:0;white-space:nowrap}.input-group-btn>.btn{position:relative}.input-group-btn>.btn+.btn{margin-left:-1px}.input-group-btn>.btn:active,.input-group-btn>.btn:focus,.input-group-btn>.btn:hover{z-index:2}.input-group-btn:first-child>.btn,.input-group-btn:first-child>.btn-group{margin-right:-1px}.input-group-btn:last-child>.btn,.input-group-btn:last-child>.btn-group{margin-left:-1px}.nav{margin-bottom:0;padding-left:0;list-style:none}.nav:after,.nav:before{content:" ";display:table}.nav:after{clear:both}.nav>li{position:relative;display:block}.nav>li>a{position:relative;display:block;padding:10px 15px}.nav>li>a:focus,.nav>li>a:hover{text-decoration:none;background-color:#eee}.nav>li.disabled>a{color:#777}.nav>li.disabled>a:focus,.nav>li.disabled>a:hover{color:#777;text-decoration:none;background-color:transparent;cursor:not-allowed}.nav .open>a,.nav .open>a:focus,.nav .open>a:hover{background-color:#eee;border-color:#337ab7}.nav .nav-divider{height:1px;margin:9px 0;overflow:hidden;background-color:#e5e5e5}.nav>li>a>img{max-width:none}.nav-tabs{border-bottom:1px solid #ddd}.nav-tabs>li{float:left;margin-bottom:-1px}.nav-tabs>li>a{margin-right:2px;line-height:1.42857;border:1px solid transparent;border-radius:4px 4px 0 0}.nav-tabs>li>a:hover{border-color:#eee #eee #ddd}.nav-tabs>li.active>a,.nav-tabs>li.active>a:focus,.nav-tabs>li.active>a:hover{color:#555;background-color:#fff;border:1px solid #ddd;border-bottom-color:transparent;cursor:default}.nav-pills>li{float:left}.nav-pills>li>a{border-radius:4px}.nav-pills>li+li{margin-left:2px}.nav-pills>li.active>a,.nav-pills>li.active>a:focus,.nav-pills>li.active>a:hover{color:#fff;background-color:#337ab7}.nav-stacked>li{float:none}.nav-stacked>li+li{margin-top:2px;margin-left:0}.nav-justified,.nav-tabs.nav-justified{width:100%}.nav-justified>li,.nav-tabs.nav-justified>li{float:none}.nav-justified>li>a,.nav-tabs.nav-justified>li>a{text-align:center;margin-bottom:5px}.nav-justified>.dropdown .dropdown-menu{top:auto;left:auto}@media (min-width:768px){.nav-justified>li,.nav-tabs.nav-justified>li{display:table-cell;width:1%}.nav-justified>li>a,.nav-tabs.nav-justified>li>a{margin-bottom:0}}.nav-tabs-justified,.nav-tabs.nav-justified{border-bottom:0}.nav-tabs-justified>li>a,.nav-tabs.nav-justified>li>a{margin-right:0;border-radius:4px}.nav-tabs-justified>.active>a,.nav-tabs-justified>.active>a:focus,.nav-tabs-justified>.active>a:hover,.nav-tabs.nav-justified>.active>a,.nav-tabs.nav-justified>.active>a:focus,.nav-tabs.nav-justified>.active>a:hover{border:1px solid #ddd}@media (min-width:768px){.nav-tabs-justified>li>a,.nav-tabs.nav-justified>li>a{border-bottom:1px solid #ddd;border-radius:4px 4px 0 0}.nav-tabs-justified>.active>a,.nav-tabs-justified>.active>a:focus,.nav-tabs-justified>.active>a:hover,.nav-tabs.nav-justified>.active>a,.nav-tabs.nav-justified>.active>a:focus,.nav-tabs.nav-justified>.active>a:hover{border-bottom-color:#fff}}.tab-content>.tab-pane{display:none;visibility:hidden}.tab-content>.active{display:block;visibility:visible}.nav-tabs .dropdown-menu{margin-top:-1px;border-top-right-radius:0;border-top-left-radius:0}.navbar{position:relative;min-height:50px;margin-bottom:20px;border:1px solid transparent}.navbar:after,.navbar:before{content:" ";display:table}.navbar:after{clear:both}@media (min-width:768px){.navbar{border-radius:4px}}.navbar-header:after,.navbar-header:before{content:" ";display:table}.navbar-header:after{clear:both}@media (min-width:768px){.navbar-header{float:left}}.navbar-collapse{overflow-x:visible;padding-right:15px;padding-left:15px;border-top:1px solid transparent;box-shadow:inset 0 1px 0 rgba(255,255,255,.1);-webkit-overflow-scrolling:touch}.navbar-collapse:after,.navbar-collapse:before{content:" ";display:table}.navbar-collapse:after{clear:both}.navbar-collapse.in{overflow-y:auto}@media (min-width:768px){.navbar-collapse{width:auto;border-top:0;box-shadow:none}.navbar-collapse.collapse{display:block!important;visibility:visible!important;height:auto!important;padding-bottom:0;overflow:visible!important}.navbar-collapse.in{overflow-y:visible}.navbar-fixed-bottom .navbar-collapse,.navbar-fixed-top .navbar-collapse,.navbar-static-top .navbar-collapse{padding-left:0;padding-right:0}}.navbar-fixed-bottom .navbar-collapse,.navbar-fixed-top .navbar-collapse{max-height:340px}@media (max-device-width:480px) and (orientation:landscape){.navbar-fixed-bottom .navbar-collapse,.navbar-fixed-top .navbar-collapse{max-height:200px}}.container-fluid>.navbar-collapse,.container-fluid>.navbar-header,.container>.navbar-collapse,.container>.navbar-header{margin-right:-15px;margin-left:-15px}@media (min-width:768px){.container-fluid>.navbar-collapse,.container-fluid>.navbar-header,.container>.navbar-collapse,.container>.navbar-header{margin-right:0;margin-left:0}}.navbar-static-top{z-index:1000;border-width:0 0 1px}@media (min-width:768px){.navbar-static-top{border-radius:0}}.navbar-fixed-bottom,.navbar-fixed-top{position:fixed;right:0;left:0;z-index:1030}@media (min-width:768px){.navbar-fixed-bottom,.navbar-fixed-top{border-radius:0}}.navbar-fixed-top{top:0;border-width:0 0 1px}.navbar-fixed-bottom{bottom:0;margin-bottom:0;border-width:1px 0 0}.navbar-brand{float:left;padding:15px;font-size:18px;line-height:20px;height:50px}.navbar-brand:focus,.navbar-brand:hover{text-decoration:none}.navbar-brand>img{display:block}@media (min-width:768px){.navbar>.container .navbar-brand,.navbar>.container-fluid .navbar-brand{margin-left:-15px}}.navbar-toggle{position:relative;float:right;margin-right:15px;padding:9px 10px;margin-top:8px;margin-bottom:8px;background-color:transparent;background-image:none;border:1px solid transparent;border-radius:4px}.navbar-toggle:focus{outline:0}.navbar-toggle .icon-bar{display:block;width:22px;height:2px;border-radius:1px}.navbar-toggle .icon-bar+.icon-bar{margin-top:4px}@media (min-width:768px){.navbar-toggle{display:none}}.navbar-nav{margin:7.5px -15px}.navbar-nav>li>a{padding-top:10px;padding-bottom:10px;line-height:20px}@media (max-width:767px){.navbar-nav .open .dropdown-menu{position:static;float:none;width:auto;margin-top:0;background-color:transparent;border:0;box-shadow:none}.navbar-nav .open .dropdown-menu .dropdown-header,.navbar-nav .open .dropdown-menu>li>a{padding:5px 15px 5px 25px}.navbar-nav .open .dropdown-menu>li>a{line-height:20px}.navbar-nav .open .dropdown-menu>li>a:focus,.navbar-nav .open .dropdown-menu>li>a:hover{background-image:none}}@media (min-width:768px){.navbar-nav{float:left;margin:0}.navbar-nav>li{float:left}.navbar-nav>li>a{padding-top:15px;padding-bottom:15px}}.navbar-form{margin:8px -15px;padding:10px 15px;border-top:1px solid transparent;border-bottom:1px solid transparent;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.1),0 1px 0 rgba(255,255,255,.1);box-shadow:inset 0 1px 0 rgba(255,255,255,.1),0 1px 0 rgba(255,255,255,.1)}@media (min-width:768px){.navbar-form .form-group{display:inline-block;margin-bottom:0;vertical-align:middle}.navbar-form .form-control{display:inline-block;width:auto;vertical-align:middle}.navbar-form .form-control-static{display:inline-block}.navbar-form .input-group{display:inline-table;vertical-align:middle}.navbar-form .input-group .form-control,.navbar-form .input-group .input-group-addon,.navbar-form .input-group .input-group-btn{width:auto}.navbar-form .input-group>.form-control{width:100%}.navbar-form .control-label{margin-bottom:0;vertical-align:middle}.navbar-form .checkbox,.navbar-form .radio{display:inline-block;margin-top:0;margin-bottom:0;vertical-align:middle}.navbar-form .checkbox label,.navbar-form .radio label{padding-left:0}.navbar-form .checkbox input[type=checkbox],.navbar-form .radio input[type=radio]{position:relative;margin-left:0}.navbar-form .has-feedback .form-control-feedback{top:0}}@media (max-width:767px){.navbar-form .form-group{margin-bottom:5px}.navbar-form .form-group:last-child{margin-bottom:0}}@media (min-width:768px){.navbar-form{width:auto;border:0;margin-left:0;margin-right:0;padding-top:0;padding-bottom:0;-webkit-box-shadow:none;box-shadow:none}}.navbar-nav>li>.dropdown-menu{margin-top:0;border-top-right-radius:0;border-top-left-radius:0}.navbar-fixed-bottom .navbar-nav>li>.dropdown-menu{border-radius:4px 4px 0 0}.navbar-btn{margin-top:8px;margin-bottom:8px}.btn-group-sm>.navbar-btn.btn,.navbar-btn.btn-sm{margin-top:10px;margin-bottom:10px}.btn-group-xs>.navbar-btn.btn,.navbar-btn.btn-xs{margin-top:14px;margin-bottom:14px}.navbar-text{margin-top:15px;margin-bottom:15px}@media (min-width:768px){.navbar-text{float:left;margin-left:15px;margin-right:15px}}@media (min-width:768px){.navbar-left{float:left!important}.navbar-right{float:right!important;margin-right:-15px}.navbar-right~.navbar-right{margin-right:0}}.navbar-default{background-color:#f8f8f8;border-color:#e7e7e7}.navbar-default .navbar-brand{color:#777}.navbar-default .navbar-brand:focus,.navbar-default .navbar-brand:hover{color:#5e5e5e;background-color:transparent}.navbar-default .navbar-nav>li>a,.navbar-default .navbar-text{color:#777}.navbar-default .navbar-nav>li>a:focus,.navbar-default .navbar-nav>li>a:hover{color:#333;background-color:transparent}.navbar-default .navbar-nav>.active>a,.navbar-default .navbar-nav>.active>a:focus,.navbar-default .navbar-nav>.active>a:hover{color:#555;background-color:#e7e7e7}.navbar-default .navbar-nav>.disabled>a,.navbar-default .navbar-nav>.disabled>a:focus,.navbar-default .navbar-nav>.disabled>a:hover{color:#ccc;background-color:transparent}.navbar-default .navbar-toggle{border-color:#ddd}.navbar-default .navbar-toggle:focus,.navbar-default .navbar-toggle:hover{background-color:#ddd}.navbar-default .navbar-toggle .icon-bar{background-color:#888}.navbar-default .navbar-collapse,.navbar-default .navbar-form{border-color:#e7e7e7}.navbar-default .navbar-nav>.open>a,.navbar-default .navbar-nav>.open>a:focus,.navbar-default .navbar-nav>.open>a:hover{background-color:#e7e7e7;color:#555}@media (max-width:767px){.navbar-default .navbar-nav .open .dropdown-menu>li>a{color:#777}.navbar-default .navbar-nav .open .dropdown-menu>li>a:focus,.navbar-default .navbar-nav .open .dropdown-menu>li>a:hover{color:#333;background-color:transparent}.navbar-default .navbar-nav .open .dropdown-menu>.active>a,.navbar-default .navbar-nav .open .dropdown-menu>.active>a:focus,.navbar-default .navbar-nav .open .dropdown-menu>.active>a:hover{color:#555;background-color:#e7e7e7}.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a,.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a:focus,.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a:hover{color:#ccc;background-color:transparent}}.navbar-default .navbar-link{color:#777}.navbar-default .navbar-link:hover{color:#333}.navbar-default .btn-link{color:#777}.navbar-default .btn-link:focus,.navbar-default .btn-link:hover{color:#333}.navbar-default .btn-link[disabled]:focus,.navbar-default .btn-link[disabled]:hover,fieldset[disabled] .navbar-default .btn-link:focus,fieldset[disabled] .navbar-default .btn-link:hover{color:#ccc}.navbar-inverse{background-color:#222;border-color:#090909}.navbar-inverse .navbar-brand{color:#9d9d9d}.navbar-inverse .navbar-brand:focus,.navbar-inverse .navbar-brand:hover{color:#fff;background-color:transparent}.navbar-inverse .navbar-nav>li>a,.navbar-inverse .navbar-text{color:#9d9d9d}.navbar-inverse .navbar-nav>li>a:focus,.navbar-inverse .navbar-nav>li>a:hover{color:#fff;background-color:transparent}.navbar-inverse .navbar-nav>.active>a,.navbar-inverse .navbar-nav>.active>a:focus,.navbar-inverse .navbar-nav>.active>a:hover{color:#fff;background-color:#090909}.navbar-inverse .navbar-nav>.disabled>a,.navbar-inverse .navbar-nav>.disabled>a:focus,.navbar-inverse .navbar-nav>.disabled>a:hover{color:#444;background-color:transparent}.navbar-inverse .navbar-toggle{border-color:#333}.navbar-inverse .navbar-toggle:focus,.navbar-inverse .navbar-toggle:hover{background-color:#333}.navbar-inverse .navbar-toggle .icon-bar{background-color:#fff}.navbar-inverse .navbar-collapse,.navbar-inverse .navbar-form{border-color:#101010}.navbar-inverse .navbar-nav>.open>a,.navbar-inverse .navbar-nav>.open>a:focus,.navbar-inverse .navbar-nav>.open>a:hover{background-color:#090909;color:#fff}@media (max-width:767px){.navbar-inverse .navbar-nav .open .dropdown-menu>.dropdown-header{border-color:#090909}.navbar-inverse .navbar-nav .open .dropdown-menu .divider{background-color:#090909}.navbar-inverse .navbar-nav .open .dropdown-menu>li>a{color:#9d9d9d}.navbar-inverse .navbar-nav .open .dropdown-menu>li>a:focus,.navbar-inverse .navbar-nav .open .dropdown-menu>li>a:hover{color:#fff;background-color:transparent}.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a,.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a:focus,.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a:hover{color:#fff;background-color:#090909}.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a,.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a:focus,.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a:hover{color:#444;background-color:transparent}}.navbar-inverse .navbar-link{color:#9d9d9d}.navbar-inverse .navbar-link:hover{color:#fff}.navbar-inverse .btn-link{color:#9d9d9d}.navbar-inverse .btn-link:focus,.navbar-inverse .btn-link:hover{color:#fff}.navbar-inverse .btn-link[disabled]:focus,.navbar-inverse .btn-link[disabled]:hover,fieldset[disabled] .navbar-inverse .btn-link:focus,fieldset[disabled] .navbar-inverse .btn-link:hover{color:#444}.breadcrumb{padding:8px 15px;margin-bottom:20px;list-style:none;background-color:#f5f5f5;border-radius:4px}.breadcrumb>li{display:inline-block}.breadcrumb>li+li:before{content:"/ ";padding:0 5px;color:#ccc}.breadcrumb>.active{color:#777}.pagination{display:inline-block;padding-left:0;margin:20px 0;border-radius:4px}.pagination>li{display:inline}.pagination>li>a,.pagination>li>span{position:relative;float:left;padding:6px 12px;line-height:1.42857;text-decoration:none;color:#337ab7;background-color:#fff;border:1px solid #ddd;margin-left:-1px}.pagination>li:first-child>a,.pagination>li:first-child>span{margin-left:0;border-bottom-left-radius:4px;border-top-left-radius:4px}.pagination>li:last-child>a,.pagination>li:last-child>span{border-bottom-right-radius:4px;border-top-right-radius:4px}.pagination>li>a:focus,.pagination>li>a:hover,.pagination>li>span:focus,.pagination>li>span:hover{color:#23527c;background-color:#eee;border-color:#ddd}.pagination>.active>a,.pagination>.active>a:focus,.pagination>.active>a:hover,.pagination>.active>span,.pagination>.active>span:focus,.pagination>.active>span:hover{z-index:2;color:#fff;background-color:#337ab7;border-color:#337ab7;cursor:default}.pagination>.disabled>a,.pagination>.disabled>a:focus,.pagination>.disabled>a:hover,.pagination>.disabled>span,.pagination>.disabled>span:focus,.pagination>.disabled>span:hover{color:#777;background-color:#fff;border-color:#ddd;cursor:not-allowed}.pagination-lg>li>a,.pagination-lg>li>span{padding:10px 16px;font-size:18px}.pagination-lg>li:first-child>a,.pagination-lg>li:first-child>span{border-bottom-left-radius:6px;border-top-left-radius:6px}.pagination-lg>li:last-child>a,.pagination-lg>li:last-child>span{border-bottom-right-radius:6px;border-top-right-radius:6px}.pagination-sm>li>a,.pagination-sm>li>span{padding:5px 10px;font-size:12px}.pagination-sm>li:first-child>a,.pagination-sm>li:first-child>span{border-bottom-left-radius:3px;border-top-left-radius:3px}.pagination-sm>li:last-child>a,.pagination-sm>li:last-child>span{border-bottom-right-radius:3px;border-top-right-radius:3px}.pager{padding-left:0;margin:20px 0;list-style:none;text-align:center}.pager:after,.pager:before{content:" ";display:table}.pager:after{clear:both}.pager li{display:inline}.pager li>a,.pager li>span{display:inline-block;padding:5px 14px;background-color:#fff;border:1px solid #ddd;border-radius:15px}.pager li>a:focus,.pager li>a:hover{text-decoration:none;background-color:#eee}.pager .next>a,.pager .next>span{float:right}.pager .previous>a,.pager .previous>span{float:left}.pager .disabled>a,.pager .disabled>a:focus,.pager .disabled>a:hover,.pager .disabled>span{color:#777;background-color:#fff;cursor:not-allowed}.label{display:inline;padding:.2em .6em .3em;font-size:75%;font-weight:700;line-height:1;color:#fff;text-align:center;white-space:nowrap;vertical-align:baseline;border-radius:.25em}.label:empty{display:none}.btn .label{position:relative;top:-1px}a.label:focus,a.label:hover{color:#fff;text-decoration:none;cursor:pointer}.label-default{background-color:#777}.label-default[href]:focus,.label-default[href]:hover{background-color:#5e5e5e}.label-primary{background-color:#337ab7}.label-primary[href]:focus,.label-primary[href]:hover{background-color:#286090}.label-success{background-color:#5cb85c}.label-success[href]:focus,.label-success[href]:hover{background-color:#449d44}.label-info{background-color:#5bc0de}.label-info[href]:focus,.label-info[href]:hover{background-color:#31b0d5}.label-warning{background-color:#f0ad4e}.label-warning[href]:focus,.label-warning[href]:hover{background-color:#ec971f}.label-danger{background-color:#d9534f}.label-danger[href]:focus,.label-danger[href]:hover{background-color:#c9302c}.badge{display:inline-block;min-width:10px;padding:3px 7px;font-size:12px;font-weight:700;color:#fff;line-height:1;vertical-align:baseline;white-space:nowrap;text-align:center;background-color:#777;border-radius:10px}.badge:empty{display:none}.btn .badge{position:relative;top:-1px}.btn-group-xs>.btn .badge,.btn-xs .badge{top:0;padding:1px 5px}.list-group-item.active>.badge,.nav-pills>.active>a>.badge{color:#337ab7;background-color:#fff}.list-group-item>.badge{float:right}.list-group-item>.badge+.badge{margin-right:5px}.nav-pills>li>a>.badge{margin-left:3px}a.badge:focus,a.badge:hover{color:#fff;text-decoration:none;cursor:pointer}.jumbotron{padding:30px 15px;margin-bottom:30px;color:inherit;background-color:#eee}.jumbotron .h1,.jumbotron h1{color:inherit}.jumbotron p{margin-bottom:15px;font-size:21px;font-weight:200}.jumbotron>hr{border-top-color:#d5d5d5}.container .jumbotron,.container-fluid .jumbotron{border-radius:6px}.jumbotron .container{max-width:100%}@media screen and (min-width:768px){.jumbotron{padding:48px 0}.container .jumbotron,.container-fluid .jumbotron{padding-left:60px;padding-right:60px}.jumbotron .h1,.jumbotron h1{font-size:63px}}.thumbnail{display:block;padding:4px;margin-bottom:20px;line-height:1.42857;background-color:#fff;border:1px solid #ddd;border-radius:4px;-webkit-transition:border .2s ease-in-out;-o-transition:border .2s ease-in-out;transition:border .2s ease-in-out}.thumbnail a>img,.thumbnail>img{display:block;max-width:100%;height:auto;margin-left:auto;margin-right:auto}.thumbnail .caption{padding:9px;color:#333}a.thumbnail.active,a.thumbnail:focus,a.thumbnail:hover{border-color:#337ab7}.alert{padding:15px;margin-bottom:20px;border:1px solid transparent;border-radius:4px}.alert h4{margin-top:0;color:inherit}.alert .alert-link{font-weight:700}.alert>p,.alert>ul{margin-bottom:0}.alert>p+p{margin-top:5px}.alert-dismissable,.alert-dismissible{padding-right:35px}.alert-dismissable .close,.alert-dismissible .close{position:relative;top:-2px;right:-21px;color:inherit}.alert-success{background-color:#dff0d8;border-color:#d6e9c6;color:#3c763d}.alert-success hr{border-top-color:#c9e2b3}.alert-success .alert-link{color:#2b542c}.alert-info{background-color:#d9edf7;border-color:#bce8f1;color:#31708f}.alert-info hr{border-top-color:#a6e1ec}.alert-info .alert-link{color:#245269}.alert-warning{background-color:#fcf8e3;border-color:#faebcc;color:#8a6d3b}.alert-warning hr{border-top-color:#f7e1b5}.alert-warning .alert-link{color:#66512c}.alert-danger{background-color:#f2dede;border-color:#ebccd1;color:#a94442}.alert-danger hr{border-top-color:#e4b9c0}.alert-danger .alert-link{color:#843534}@-webkit-keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}@keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}.progress{overflow:hidden;height:20px;margin-bottom:20px;background-color:#f5f5f5;border-radius:4px;-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,.1);box-shadow:inset 0 1px 2px rgba(0,0,0,.1)}.progress-bar{float:left;width:0;height:100%;font-size:12px;line-height:20px;color:#fff;text-align:center;background-color:#337ab7;-webkit-box-shadow:inset 0 -1px 0 rgba(0,0,0,.15);box-shadow:inset 0 -1px 0 rgba(0,0,0,.15);-webkit-transition:width .6s ease;-o-transition:width .6s ease;transition:width .6s ease}.progress-bar-striped,.progress-striped .progress-bar{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-size:40px 40px}.progress-bar.active,.progress.active .progress-bar{-webkit-animation:progress-bar-stripes 2s linear infinite;-o-animation:progress-bar-stripes 2s linear infinite;animation:progress-bar-stripes 2s linear infinite}.progress-bar-success{background-color:#5cb85c}.progress-striped .progress-bar-success{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.progress-bar-info{background-color:#5bc0de}.progress-striped .progress-bar-info{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.progress-bar-warning{background-color:#f0ad4e}.progress-striped .progress-bar-warning{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.progress-bar-danger{background-color:#d9534f}.progress-striped .progress-bar-danger{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.media{margin-top:15px}.media:first-child{margin-top:0}.media-right,.media>.pull-right{padding-left:10px}.media-left,.media>.pull-left{padding-right:10px}.media-body,.media-left,.media-right{display:table-cell;vertical-align:top}.media-middle{vertical-align:middle}.media-bottom{vertical-align:bottom}.media-heading{margin-top:0;margin-bottom:5px}.media-list{padding-left:0;list-style:none}.list-group{margin-bottom:20px;padding-left:0}.list-group-item{position:relative;display:block;padding:10px 15px;margin-bottom:-1px;background-color:#fff;border:1px solid #ddd}.list-group-item:first-child{border-top-right-radius:4px;border-top-left-radius:4px}.list-group-item:last-child{margin-bottom:0;border-bottom-right-radius:4px;border-bottom-left-radius:4px}a.list-group-item{color:#555}a.list-group-item .list-group-item-heading{color:#333}a.list-group-item:focus,a.list-group-item:hover{text-decoration:none;color:#555;background-color:#f5f5f5}.list-group-item.disabled,.list-group-item.disabled:focus,.list-group-item.disabled:hover{background-color:#eee;color:#777;cursor:not-allowed}.list-group-item.disabled .list-group-item-heading,.list-group-item.disabled:focus .list-group-item-heading,.list-group-item.disabled:hover .list-group-item-heading{color:inherit}.list-group-item.disabled .list-group-item-text,.list-group-item.disabled:focus .list-group-item-text,.list-group-item.disabled:hover .list-group-item-text{color:#777}.list-group-item.active,.list-group-item.active:focus,.list-group-item.active:hover{z-index:2;color:#fff;background-color:#337ab7;border-color:#337ab7}.list-group-item.active .list-group-item-heading,.list-group-item.active .list-group-item-heading>.small,.list-group-item.active .list-group-item-heading>small,.list-group-item.active:focus .list-group-item-heading,.list-group-item.active:focus .list-group-item-heading>.small,.list-group-item.active:focus .list-group-item-heading>small,.list-group-item.active:hover .list-group-item-heading,.list-group-item.active:hover .list-group-item-heading>.small,.list-group-item.active:hover .list-group-item-heading>small{color:inherit}.list-group-item.active .list-group-item-text,.list-group-item.active:focus .list-group-item-text,.list-group-item.active:hover .list-group-item-text{color:#c7ddef}.list-group-item-success{color:#3c763d;background-color:#dff0d8}a.list-group-item-success{color:#3c763d}a.list-group-item-success .list-group-item-heading{color:inherit}a.list-group-item-success:focus,a.list-group-item-success:hover{color:#3c763d;background-color:#d0e9c6}a.list-group-item-success.active,a.list-group-item-success.active:focus,a.list-group-item-success.active:hover{color:#fff;background-color:#3c763d;border-color:#3c763d}.list-group-item-info{color:#31708f;background-color:#d9edf7}a.list-group-item-info{color:#31708f}a.list-group-item-info .list-group-item-heading{color:inherit}a.list-group-item-info:focus,a.list-group-item-info:hover{color:#31708f;background-color:#c4e3f3}a.list-group-item-info.active,a.list-group-item-info.active:focus,a.list-group-item-info.active:hover{color:#fff;background-color:#31708f;border-color:#31708f}.list-group-item-warning{color:#8a6d3b;background-color:#fcf8e3}a.list-group-item-warning{color:#8a6d3b}a.list-group-item-warning .list-group-item-heading{color:inherit}a.list-group-item-warning:focus,a.list-group-item-warning:hover{color:#8a6d3b;background-color:#faf2cc}a.list-group-item-warning.active,a.list-group-item-warning.active:focus,a.list-group-item-warning.active:hover{color:#fff;background-color:#8a6d3b;border-color:#8a6d3b}.list-group-item-danger{color:#a94442;background-color:#f2dede}a.list-group-item-danger{color:#a94442}a.list-group-item-danger .list-group-item-heading{color:inherit}a.list-group-item-danger:focus,a.list-group-item-danger:hover{color:#a94442;background-color:#ebcccc}a.list-group-item-danger.active,a.list-group-item-danger.active:focus,a.list-group-item-danger.active:hover{color:#fff;background-color:#a94442;border-color:#a94442}.list-group-item-heading{margin-top:0;margin-bottom:5px}.list-group-item-text{margin-bottom:0;line-height:1.3}.panel{margin-bottom:20px;background-color:#fff;border:1px solid transparent;border-radius:4px;-webkit-box-shadow:0 1px 1px rgba(0,0,0,.05);box-shadow:0 1px 1px rgba(0,0,0,.05)}.panel-body{padding:15px}.panel-body:after,.panel-body:before{content:" ";display:table}.panel-body:after{clear:both}.panel-heading{padding:10px 15px;border-bottom:1px solid transparent;border-top-right-radius:3px;border-top-left-radius:3px}.panel-heading>.dropdown .dropdown-toggle{color:inherit}.panel-title{margin-top:0;margin-bottom:0;font-size:16px;color:inherit}.panel-title>a{color:inherit}.panel-footer{padding:10px 15px;background-color:#f5f5f5;border-top:1px solid #ddd;border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.list-group,.panel>.panel-collapse>.list-group{margin-bottom:0}.panel>.list-group .list-group-item,.panel>.panel-collapse>.list-group .list-group-item{border-width:1px 0;border-radius:0}.panel>.list-group:first-child .list-group-item:first-child,.panel>.panel-collapse>.list-group:first-child .list-group-item:first-child{border-top:0;border-top-right-radius:3px;border-top-left-radius:3px}.panel>.list-group:last-child .list-group-item:last-child,.panel>.panel-collapse>.list-group:last-child .list-group-item:last-child{border-bottom:0;border-bottom-right-radius:3px;border-bottom-left-radius:3px}.list-group+.panel-footer,.panel-heading+.list-group .list-group-item:first-child{border-top-width:0}.panel>.panel-collapse>.table,.panel>.table,.panel>.table-responsive>.table{margin-bottom:0}.panel>.panel-collapse>.table caption,.panel>.table caption,.panel>.table-responsive>.table caption{padding-left:15px;padding-right:15px}.panel>.table-responsive:first-child>.table:first-child,.panel>.table:first-child{border-top-right-radius:3px;border-top-left-radius:3px}.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child,.panel>.table:first-child>thead:first-child>tr:first-child{border-top-left-radius:3px;border-top-right-radius:3px}.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child td:first-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child th:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child td:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child th:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child td:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child th:first-child,.panel>.table:first-child>thead:first-child>tr:first-child td:first-child,.panel>.table:first-child>thead:first-child>tr:first-child th:first-child{border-top-left-radius:3px}.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child td:last-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child th:last-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child td:last-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child th:last-child,.panel>.table:first-child>tbody:first-child>tr:first-child td:last-child,.panel>.table:first-child>tbody:first-child>tr:first-child th:last-child,.panel>.table:first-child>thead:first-child>tr:first-child td:last-child,.panel>.table:first-child>thead:first-child>tr:first-child th:last-child{border-top-right-radius:3px}.panel>.table-responsive:last-child>.table:last-child,.panel>.table:last-child{border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child,.panel>.table:last-child>tbody:last-child>tr:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child{border-bottom-left-radius:3px;border-bottom-right-radius:3px}.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child td:first-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child th:first-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child td:first-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child th:first-child,.panel>.table:last-child>tbody:last-child>tr:last-child td:first-child,.panel>.table:last-child>tbody:last-child>tr:last-child th:first-child,.panel>.table:last-child>tfoot:last-child>tr:last-child td:first-child,.panel>.table:last-child>tfoot:last-child>tr:last-child th:first-child{border-bottom-left-radius:3px}.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child td:last-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child th:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child td:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child th:last-child,.panel>.table:last-child>tbody:last-child>tr:last-child td:last-child,.panel>.table:last-child>tbody:last-child>tr:last-child th:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child td:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child th:last-child{border-bottom-right-radius:3px}.panel>.panel-body+.table,.panel>.panel-body+.table-responsive,.panel>.table+.panel-body,.panel>.table-responsive+.panel-body{border-top:1px solid #ddd}.panel>.table>tbody:first-child>tr:first-child td,.panel>.table>tbody:first-child>tr:first-child th{border-top:0}.panel>.table-bordered,.panel>.table-responsive>.table-bordered{border:0}.panel>.table-bordered>tbody>tr>td:first-child,.panel>.table-bordered>tbody>tr>th:first-child,.panel>.table-bordered>tfoot>tr>td:first-child,.panel>.table-bordered>tfoot>tr>th:first-child,.panel>.table-bordered>thead>tr>td:first-child,.panel>.table-bordered>thead>tr>th:first-child,.panel>.table-responsive>.table-bordered>tbody>tr>td:first-child,.panel>.table-responsive>.table-bordered>tbody>tr>th:first-child,.panel>.table-responsive>.table-bordered>tfoot>tr>td:first-child,.panel>.table-responsive>.table-bordered>tfoot>tr>th:first-child,.panel>.table-responsive>.table-bordered>thead>tr>td:first-child,.panel>.table-responsive>.table-bordered>thead>tr>th:first-child{border-left:0}.panel>.table-bordered>tbody>tr>td:last-child,.panel>.table-bordered>tbody>tr>th:last-child,.panel>.table-bordered>tfoot>tr>td:last-child,.panel>.table-bordered>tfoot>tr>th:last-child,.panel>.table-bordered>thead>tr>td:last-child,.panel>.table-bordered>thead>tr>th:last-child,.panel>.table-responsive>.table-bordered>tbody>tr>td:last-child,.panel>.table-responsive>.table-bordered>tbody>tr>th:last-child,.panel>.table-responsive>.table-bordered>tfoot>tr>td:last-child,.panel>.table-responsive>.table-bordered>tfoot>tr>th:last-child,.panel>.table-responsive>.table-bordered>thead>tr>td:last-child,.panel>.table-responsive>.table-bordered>thead>tr>th:last-child{border-right:0}.panel>.table-bordered>tbody>tr:first-child>td,.panel>.table-bordered>tbody>tr:first-child>th,.panel>.table-bordered>tbody>tr:last-child>td,.panel>.table-bordered>tbody>tr:last-child>th,.panel>.table-bordered>tfoot>tr:last-child>td,.panel>.table-bordered>tfoot>tr:last-child>th,.panel>.table-bordered>thead>tr:first-child>td,.panel>.table-bordered>thead>tr:first-child>th,.panel>.table-responsive>.table-bordered>tbody>tr:first-child>td,.panel>.table-responsive>.table-bordered>tbody>tr:first-child>th,.panel>.table-responsive>.table-bordered>tbody>tr:last-child>td,.panel>.table-responsive>.table-bordered>tbody>tr:last-child>th,.panel>.table-responsive>.table-bordered>tfoot>tr:last-child>td,.panel>.table-responsive>.table-bordered>tfoot>tr:last-child>th,.panel>.table-responsive>.table-bordered>thead>tr:first-child>td,.panel>.table-responsive>.table-bordered>thead>tr:first-child>th{border-bottom:0}.panel>.table-responsive{border:0;margin-bottom:0}.panel-group{margin-bottom:20px}.panel-group .panel{margin-bottom:0;border-radius:4px}.panel-group .panel+.panel{margin-top:5px}.panel-group .panel-heading{border-bottom:0}.panel-group .panel-heading+.panel-collapse>.list-group,.panel-group .panel-heading+.panel-collapse>.panel-body{border-top:1px solid #ddd}.panel-group .panel-footer{border-top:0}.panel-group .panel-footer+.panel-collapse .panel-body{border-bottom:1px solid #ddd}.panel-default{border-color:#ddd}.panel-default>.panel-heading{color:#333;background-color:#f5f5f5;border-color:#ddd}.panel-default>.panel-heading+.panel-collapse>.panel-body{border-top-color:#ddd}.panel-default>.panel-heading .badge{color:#f5f5f5;background-color:#333}.panel-default>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#ddd}.panel-primary{border-color:#337ab7}.panel-primary>.panel-heading{color:#fff;background-color:#337ab7;border-color:#337ab7}.panel-primary>.panel-heading+.panel-collapse>.panel-body{border-top-color:#337ab7}.panel-primary>.panel-heading .badge{color:#337ab7;background-color:#fff}.panel-primary>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#337ab7}.panel-success{border-color:#d6e9c6}.panel-success>.panel-heading{color:#3c763d;background-color:#dff0d8;border-color:#d6e9c6}.panel-success>.panel-heading+.panel-collapse>.panel-body{border-top-color:#d6e9c6}.panel-success>.panel-heading .badge{color:#dff0d8;background-color:#3c763d}.panel-success>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#d6e9c6}.panel-info{border-color:#bce8f1}.panel-info>.panel-heading{color:#31708f;background-color:#d9edf7;border-color:#bce8f1}.panel-info>.panel-heading+.panel-collapse>.panel-body{border-top-color:#bce8f1}.panel-info>.panel-heading .badge{color:#d9edf7;background-color:#31708f}.panel-info>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#bce8f1}.panel-warning{border-color:#faebcc}.panel-warning>.panel-heading{color:#8a6d3b;background-color:#fcf8e3;border-color:#faebcc}.panel-warning>.panel-heading+.panel-collapse>.panel-body{border-top-color:#faebcc}.panel-warning>.panel-heading .badge{color:#fcf8e3;background-color:#8a6d3b}.panel-warning>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#faebcc}.panel-danger{border-color:#ebccd1}.panel-danger>.panel-heading{color:#a94442;background-color:#f2dede;border-color:#ebccd1}.panel-danger>.panel-heading+.panel-collapse>.panel-body{border-top-color:#ebccd1}.panel-danger>.panel-heading .badge{color:#f2dede;background-color:#a94442}.panel-danger>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#ebccd1}.embed-responsive{position:relative;display:block;height:0;padding:0;overflow:hidden}.embed-responsive .embed-responsive-item,.embed-responsive embed,.embed-responsive iframe,.embed-responsive object,.embed-responsive video{position:absolute;top:0;left:0;bottom:0;height:100%;width:100%;border:0}.embed-responsive.embed-responsive-16by9{padding-bottom:56.25%}.embed-responsive.embed-responsive-4by3{padding-bottom:75%}.well{min-height:20px;padding:19px;margin-bottom:20px;background-color:#f5f5f5;border:1px solid #e3e3e3;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.05);box-shadow:inset 0 1px 1px rgba(0,0,0,.05)}.well blockquote{border-color:#ddd;border-color:rgba(0,0,0,.15)}.well-lg{padding:24px;border-radius:6px}.well-sm{padding:9px;border-radius:3px}.close{float:right;font-size:21px;font-weight:700;line-height:1;color:#000;text-shadow:0 1px 0 #fff;opacity:.2;filter:alpha(opacity=20)}.close:focus,.close:hover{color:#000;text-decoration:none;cursor:pointer;opacity:.5;filter:alpha(opacity=50)}button.close{padding:0;cursor:pointer;background:0 0;border:0;-webkit-appearance:none}.modal-open{overflow:hidden}.modal{display:none;overflow:hidden;position:fixed;top:0;right:0;bottom:0;left:0;z-index:1040;-webkit-overflow-scrolling:touch;outline:0}.modal.fade .modal-dialog{-webkit-transform:translate(0,-25%);-ms-transform:translate(0,-25%);-o-transform:translate(0,-25%);transform:translate(0,-25%);-webkit-transition:-webkit-transform .3s ease-out;-moz-transition:-moz-transform .3s ease-out;-o-transition:-o-transform .3s ease-out;transition:transform .3s ease-out}.modal.in .modal-dialog{-webkit-transform:translate(0,0);-ms-transform:translate(0,0);-o-transform:translate(0,0);transform:translate(0,0)}.modal-open .modal{overflow-x:hidden;overflow-y:auto}.modal-dialog{position:relative;width:auto;margin:10px}.modal-content{position:relative;background-color:#fff;border:1px solid #999;border:1px solid rgba(0,0,0,.2);border-radius:6px;-webkit-box-shadow:0 3px 9px rgba(0,0,0,.5);box-shadow:0 3px 9px rgba(0,0,0,.5);background-clip:padding-box;outline:0}.modal-backdrop{position:absolute;top:0;right:0;left:0;background-color:#000}.modal-backdrop.fade{opacity:0;filter:alpha(opacity=0)}.modal-backdrop.in{opacity:.5;filter:alpha(opacity=50)}.modal-header{padding:15px;border-bottom:1px solid #e5e5e5;min-height:16.43px}.modal-header .close{margin-top:-2px}.modal-title{margin:0;line-height:1.42857}.modal-body{position:relative;padding:15px}.modal-footer{padding:15px;text-align:right;border-top:1px solid #e5e5e5}.modal-footer:after,.modal-footer:before{content:" ";display:table}.modal-footer:after{clear:both}.modal-footer .btn+.btn{margin-left:5px;margin-bottom:0}.modal-footer .btn-group .btn+.btn{margin-left:-1px}.modal-footer .btn-block+.btn-block{margin-left:0}.modal-scrollbar-measure{position:absolute;top:-9999px;width:50px;height:50px;overflow:scroll}@media (min-width:768px){.modal-dialog{width:600px;margin:30px auto}.modal-content{-webkit-box-shadow:0 5px 15px rgba(0,0,0,.5);box-shadow:0 5px 15px rgba(0,0,0,.5)}.modal-sm{width:300px}}@media (min-width:992px){.modal-lg{width:900px}}.tooltip{position:absolute;z-index:1070;display:block;visibility:visible;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:12px;font-weight:400;line-height:1.4;opacity:0;filter:alpha(opacity=0)}.tooltip.in{opacity:.9;filter:alpha(opacity=90)}.tooltip.top{margin-top:-3px;padding:5px 0}.tooltip.right{margin-left:3px;padding:0 5px}.tooltip.bottom{margin-top:3px;padding:5px 0}.tooltip.left{margin-left:-3px;padding:0 5px}.tooltip-inner{max-width:200px;padding:3px 8px;color:#fff;text-align:center;text-decoration:none;background-color:#000;border-radius:4px}.tooltip-arrow{position:absolute;width:0;height:0;border-color:transparent;border-style:solid}.tooltip.top .tooltip-arrow{bottom:0;left:50%;margin-left:-5px;border-width:5px 5px 0;border-top-color:#000}.tooltip.top-left .tooltip-arrow{bottom:0;right:5px;margin-bottom:-5px;border-width:5px 5px 0;border-top-color:#000}.tooltip.top-right .tooltip-arrow{bottom:0;left:5px;margin-bottom:-5px;border-width:5px 5px 0;border-top-color:#000}.tooltip.right .tooltip-arrow{top:50%;left:0;margin-top:-5px;border-width:5px 5px 5px 0;border-right-color:#000}.tooltip.left .tooltip-arrow{top:50%;right:0;margin-top:-5px;border-width:5px 0 5px 5px;border-left-color:#000}.tooltip.bottom .tooltip-arrow{top:0;left:50%;margin-left:-5px;border-width:0 5px 5px;border-bottom-color:#000}.tooltip.bottom-left .tooltip-arrow{top:0;right:5px;margin-top:-5px;border-width:0 5px 5px;border-bottom-color:#000}.tooltip.bottom-right .tooltip-arrow{top:0;left:5px;margin-top:-5px;border-width:0 5px 5px;border-bottom-color:#000}.popover{position:absolute;top:0;left:0;z-index:1060;display:none;max-width:276px;padding:1px;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:14px;font-weight:400;line-height:1.42857;text-align:left;background-color:#fff;background-clip:padding-box;border:1px solid #ccc;border:1px solid rgba(0,0,0,.2);border-radius:6px;-webkit-box-shadow:0 5px 10px rgba(0,0,0,.2);box-shadow:0 5px 10px rgba(0,0,0,.2);white-space:normal}.popover.top{margin-top:-10px}.popover.right{margin-left:10px}.popover.bottom{margin-top:10px}.popover.left{margin-left:-10px}.popover-title{margin:0;padding:8px 14px;font-size:14px;background-color:#f7f7f7;border-bottom:1px solid #ebebeb;border-radius:5px 5px 0 0}.popover-content{padding:9px 14px}.popover>.arrow,.popover>.arrow:after{position:absolute;display:block;width:0;height:0;border-color:transparent;border-style:solid}.popover>.arrow{border-width:11px}.popover>.arrow:after{border-width:10px;content:""}.popover.top>.arrow{left:50%;margin-left:-11px;border-bottom-width:0;border-top-color:#999;border-top-color:rgba(0,0,0,.25);bottom:-11px}.popover.top>.arrow:after{content:" ";bottom:1px;margin-left:-10px;border-bottom-width:0;border-top-color:#fff}.popover.right>.arrow{top:50%;left:-11px;margin-top:-11px;border-left-width:0;border-right-color:#999;border-right-color:rgba(0,0,0,.25)}.popover.right>.arrow:after{content:" ";left:1px;bottom:-10px;border-left-width:0;border-right-color:#fff}.popover.bottom>.arrow{left:50%;margin-left:-11px;border-top-width:0;border-bottom-color:#999;border-bottom-color:rgba(0,0,0,.25);top:-11px}.popover.bottom>.arrow:after{content:" ";top:1px;margin-left:-10px;border-top-width:0;border-bottom-color:#fff}.popover.left>.arrow{top:50%;right:-11px;margin-top:-11px;border-right-width:0;border-left-color:#999;border-left-color:rgba(0,0,0,.25)}.popover.left>.arrow:after{content:" ";right:1px;border-right-width:0;border-left-color:#fff;bottom:-10px}.carousel{position:relative}.carousel-inner{position:relative;overflow:hidden;width:100%}.carousel-inner>.item{display:none;position:relative;-webkit-transition:.6s ease-in-out left;-o-transition:.6s ease-in-out left;transition:.6s ease-in-out left}.carousel-inner>.item>a>img,.carousel-inner>.item>img{display:block;max-width:100%;height:auto;line-height:1}@media all and (transform-3d),(-webkit-transform-3d){.carousel-inner>.item{transition:transform .6s ease-in-out;backface-visibility:hidden;perspective:1000}.carousel-inner>.item.active.right,.carousel-inner>.item.next{transform:translate3d(100%,0,0);left:0}.carousel-inner>.item.active.left,.carousel-inner>.item.prev{transform:translate3d(-100%,0,0);left:0}.carousel-inner>.item.active,.carousel-inner>.item.next.left,.carousel-inner>.item.prev.right{transform:translate3d(0,0,0);left:0}}.carousel-inner>.active,.carousel-inner>.next,.carousel-inner>.prev{display:block}.carousel-inner>.active{left:0}.carousel-inner>.next,.carousel-inner>.prev{position:absolute;top:0;width:100%}.carousel-inner>.next{left:100%}.carousel-inner>.prev{left:-100%}.carousel-inner>.next.left,.carousel-inner>.prev.right{left:0}.carousel-inner>.active.left{left:-100%}.carousel-inner>.active.right{left:100%}.carousel-control{position:absolute;top:0;left:0;bottom:0;width:15%;opacity:.5;filter:alpha(opacity=50);font-size:20px;color:#fff;text-align:center;text-shadow:0 1px 2px rgba(0,0,0,.6)}.carousel-control.left{background-image:-webkit-linear-gradient(left,rgba(0,0,0,.5) 0,rgba(0,0,0,.0001) 100%);background-image:-o-linear-gradient(left,rgba(0,0,0,.5) 0,rgba(0,0,0,.0001) 100%);background-image:linear-gradient(to right,rgba(0,0,0,.5) 0,rgba(0,0,0,.0001) 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#80000000', endColorstr='#00000000', GradientType=1)}.carousel-control.right{left:auto;right:0;background-image:-webkit-linear-gradient(left,rgba(0,0,0,.0001) 0,rgba(0,0,0,.5) 100%);background-image:-o-linear-gradient(left,rgba(0,0,0,.0001) 0,rgba(0,0,0,.5) 100%);background-image:linear-gradient(to right,rgba(0,0,0,.0001) 0,rgba(0,0,0,.5) 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#00000000', endColorstr='#80000000', GradientType=1)}.carousel-control:focus,.carousel-control:hover{outline:0;color:#fff;text-decoration:none;opacity:.9;filter:alpha(opacity=90)}.carousel-control .glyphicon-chevron-left,.carousel-control .glyphicon-chevron-right,.carousel-control .icon-next,.carousel-control .icon-prev{position:absolute;top:50%;z-index:5;display:inline-block}.carousel-control .glyphicon-chevron-left,.carousel-control .icon-prev{left:50%;margin-left:-10px}.carousel-control .glyphicon-chevron-right,.carousel-control .icon-next{right:50%;margin-right:-10px}.carousel-control .icon-next,.carousel-control .icon-prev{width:20px;height:20px;margin-top:-10px;font-family:serif}.carousel-control .icon-prev:before{content:'\2039'}.carousel-control .icon-next:before{content:'\203a'}.carousel-indicators{position:absolute;bottom:10px;left:50%;z-index:15;width:60%;margin-left:-30%;padding-left:0;list-style:none;text-align:center}.carousel-indicators li{display:inline-block;width:10px;height:10px;margin:1px;text-indent:-999px;border:1px solid #fff;border-radius:10px;cursor:pointer;background-color:transparent}.carousel-indicators .active{margin:0;width:12px;height:12px;background-color:#fff}.carousel-caption{position:absolute;left:15%;right:15%;bottom:20px;z-index:10;padding-top:20px;padding-bottom:20px;color:#fff;text-align:center;text-shadow:0 1px 2px rgba(0,0,0,.6)}.carousel-caption .btn{text-shadow:none}@media screen and (min-width:768px){.carousel-control .glyphicon-chevron-left,.carousel-control .glyphicon-chevron-right,.carousel-control .icon-next,.carousel-control .icon-prev{width:30px;height:30px;margin-top:-15px;font-size:30px}.carousel-control .glyphicon-chevron-left,.carousel-control .icon-prev{margin-left:-15px}.carousel-control .glyphicon-chevron-right,.carousel-control .icon-next{margin-right:-15px}.carousel-caption{left:20%;right:20%;padding-bottom:30px}.carousel-indicators{bottom:20px}}.clearfix:after,.clearfix:before{content:" ";display:table}.clearfix:after{clear:both}.center-block{display:block;margin-left:auto;margin-right:auto}.pull-right{float:right!important}.pull-left{float:left!important}.hide{display:none!important}.show{display:block!important}.invisible{visibility:hidden}.text-hide{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}.hidden{display:none!important;visibility:hidden!important}.affix{position:fixed}@-ms-viewport{width:device-width}.visible-lg,.visible-lg-block,.visible-lg-inline,.visible-lg-inline-block,.visible-md,.visible-md-block,.visible-md-inline,.visible-md-inline-block,.visible-print,.visible-print-block,.visible-print-inline,.visible-print-inline-block,.visible-sm,.visible-sm-block,.visible-sm-inline,.visible-sm-inline-block,.visible-xs,.visible-xs-block,.visible-xs-inline,.visible-xs-inline-block{display:none!important}@media (max-width:767px){.visible-xs{display:block!important}table.visible-xs{display:table}tr.visible-xs{display:table-row!important}td.visible-xs,th.visible-xs{display:table-cell!important}}@media (max-width:767px){.visible-xs-block{display:block!important}}@media (max-width:767px){.visible-xs-inline{display:inline!important}}@media (max-width:767px){.visible-xs-inline-block{display:inline-block!important}}@media (min-width:768px) and (max-width:991px){.visible-sm{display:block!important}table.visible-sm{display:table}tr.visible-sm{display:table-row!important}td.visible-sm,th.visible-sm{display:table-cell!important}}@media (min-width:768px) and (max-width:991px){.visible-sm-block{display:block!important}}@media (min-width:768px) and (max-width:991px){.visible-sm-inline{display:inline!important}}@media (min-width:768px) and (max-width:991px){.visible-sm-inline-block{display:inline-block!important}}@media (min-width:992px) and (max-width:1199px){.visible-md{display:block!important}table.visible-md{display:table}tr.visible-md{display:table-row!important}td.visible-md,th.visible-md{display:table-cell!important}}@media (min-width:992px) and (max-width:1199px){.visible-md-block{display:block!important}}@media (min-width:992px) and (max-width:1199px){.visible-md-inline{display:inline!important}}@media (min-width:992px) and (max-width:1199px){.visible-md-inline-block{display:inline-block!important}}@media (min-width:1200px){.visible-lg{display:block!important}table.visible-lg{display:table}tr.visible-lg{display:table-row!important}td.visible-lg,th.visible-lg{display:table-cell!important}}@media (min-width:1200px){.visible-lg-block{display:block!important}}@media (min-width:1200px){.visible-lg-inline{display:inline!important}}@media (min-width:1200px){.visible-lg-inline-block{display:inline-block!important}}@media (max-width:767px){.hidden-xs{display:none!important}}@media (min-width:768px) and (max-width:991px){.hidden-sm{display:none!important}}@media (min-width:992px) and (max-width:1199px){.hidden-md{display:none!important}}@media (min-width:1200px){.hidden-lg{display:none!important}}@media print{.visible-print{display:block!important}table.visible-print{display:table}tr.visible-print{display:table-row!important}td.visible-print,th.visible-print{display:table-cell!important}}@media print{.visible-print-block{display:block!important}}@media print{.visible-print-inline{display:inline!important}}@media print{.visible-print-inline-block{display:inline-block!important}}@media print{.hidden-print{display:none!important}}/*! + * Start Bootstrap - SB Admin 2 Bootstrap Admin Theme (http://startbootstrap.com) + * Code licensed under the Apache License v2.0. + * For details, see http://www.apache.org/licenses/LICENSE-2.0. + */body{background-color:#f8f8f8}#wrapper{width:100%}#page-wrapper{padding:0 15px;min-height:568px;background-color:#fff}@media (min-width:768px){#page-wrapper{position:inherit;margin:0 0 0 250px;padding:0 30px;border-left:1px solid #e7e7e7}}.navbar-top-links{margin-right:0}.navbar-top-links li{display:inline-block}.navbar-top-links li:last-child{margin-right:15px}.navbar-top-links li a{padding:15px;min-height:50px}.navbar-top-links .dropdown-menu li{display:block}.navbar-top-links .dropdown-menu li:last-child{margin-right:0}.navbar-top-links .dropdown-menu li a{padding:3px 20px;min-height:0}.navbar-top-links .dropdown-menu li a div{white-space:normal}.navbar-top-links .dropdown-alerts,.navbar-top-links .dropdown-messages,.navbar-top-links .dropdown-tasks{width:310px;min-width:0}.navbar-top-links .dropdown-messages{margin-left:5px}.navbar-top-links .dropdown-tasks{margin-left:-59px}.navbar-top-links .dropdown-alerts{margin-left:-123px}.navbar-top-links .dropdown-user{right:0;left:auto}.sidebar .sidebar-nav.navbar-collapse{padding-right:0;padding-left:0}.sidebar .sidebar-search{padding:15px}.sidebar ul li{border-bottom:1px solid #e7e7e7}.sidebar ul li a.active{background-color:#eee}.sidebar .arrow{float:right}.sidebar .fa.arrow:before{content:"\f104"}.sidebar .active>a>.fa.arrow:before{content:"\f107"}.sidebar .nav-second-level li,.sidebar .nav-third-level li{border-bottom:0!important}.sidebar .nav-second-level li a{padding-left:37px}.sidebar .nav-third-level li a{padding-left:52px}@media (min-width:768px){.sidebar{z-index:1;position:absolute;width:250px;margin-top:51px}.navbar-top-links .dropdown-alerts,.navbar-top-links .dropdown-messages,.navbar-top-links .dropdown-tasks{margin-left:auto}}.btn-outline{color:inherit;background-color:transparent;transition:all .5s}.btn-primary.btn-outline{color:#428bca}.btn-success.btn-outline{color:#5cb85c}.btn-info.btn-outline{color:#5bc0de}.btn-warning.btn-outline{color:#f0ad4e}.btn-danger.btn-outline{color:#d9534f}.btn-danger.btn-outline:hover,.btn-info.btn-outline:hover,.btn-primary.btn-outline:hover,.btn-success.btn-outline:hover,.btn-warning.btn-outline:hover{color:#fff}.chat{margin:0;padding:0;list-style:none}.chat li{margin-bottom:10px;padding-bottom:5px;border-bottom:1px dotted #999}.chat li.left .chat-body{margin-left:60px}.chat li.right .chat-body{margin-right:60px}.chat li .chat-body p{margin:0}.chat .glyphicon,.panel .slidedown .glyphicon{margin-right:5px}.chat-panel .panel-body{height:350px;overflow-y:scroll}.login-panel{margin-top:25%}.flot-chart{display:block;height:400px}.flot-chart-content{width:100%;height:100%}table.dataTable thead .sorting,table.dataTable thead .sorting_asc,table.dataTable thead .sorting_asc_disabled,table.dataTable thead .sorting_desc,table.dataTable thead .sorting_desc_disabled{background:0 0}table.dataTable thead .sorting_asc:after{content:"\f0de";float:right;font-family:fontawesome}table.dataTable thead .sorting_desc:after{content:"\f0dd";float:right;font-family:fontawesome}table.dataTable thead .sorting:after{content:"\f0dc";float:right;font-family:fontawesome;color:rgba(50,50,50,.5)}.btn-circle{width:30px;height:30px;padding:6px 0;border-radius:15px;text-align:center;font-size:12px;line-height:1.428571429}.btn-circle.btn-lg,.btn-group-lg>.btn-circle.btn{width:50px;height:50px;padding:10px 16px;border-radius:25px;font-size:18px;line-height:1.33}.btn-circle.btn-xl{width:70px;height:70px;padding:10px 16px;border-radius:35px;font-size:24px;line-height:1.33}.show-grid [class^=col-]{padding-top:10px;padding-bottom:10px;border:1px solid #ddd;background-color:#eee!important}.show-grid{margin:15px 0}.huge{font-size:40px}.panel-green{border-color:#5cb85c}.panel-green .panel-heading{border-color:#5cb85c;color:#fff;background-color:#5cb85c}.panel-green a{color:#5cb85c}.panel-green a:hover{color:#3d8b3d}.panel-red{border-color:#d9534f}.panel-red .panel-heading{border-color:#d9534f;color:#fff;background-color:#d9534f}.panel-red a{color:#d9534f}.panel-red a:hover{color:#b52b27}.panel-yellow{border-color:#f0ad4e}.panel-yellow .panel-heading{border-color:#f0ad4e;color:#fff;background-color:#f0ad4e}.panel-yellow a{color:#f0ad4e}.panel-yellow a:hover{color:#df8a13}/*! + * Font Awesome 4.2.0 by @davegandy - http://fontawesome.io - @fontawesome + * License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License) + */@font-face{font-family:FontAwesome;src:url(../assets/fonts/fontawesome-webfont.eot?v=4.2.0);src:url(../assets/fonts/fontawesome-webfont.eot?#iefix&v=4.2.0) format("embedded-opentype"),url(../assets/fonts/fontawesome-webfont.woff?v=4.2.0) format("woff"),url(../assets/fonts/fontawesome-webfont.ttf?v=4.2.0) format("truetype"),url(../assets/fonts/fontawesome-webfont.svg?v=4.2.0#fontawesomeregular) format("svg");font-weight:400;font-style:normal}.fa{display:inline-block;font:normal normal normal 14px/1 FontAwesome;font-size:inherit;text-rendering:auto;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.fa-lg{font-size:1.33333em;line-height:.75em;vertical-align:-15%}.fa-2x{font-size:2em}.fa-3x{font-size:3em}.fa-4x{font-size:4em}.fa-5x{font-size:5em}.fa-fw{width:1.28571em;text-align:center}.fa-ul{padding-left:0;margin-left:2.14286em;list-style-type:none}.fa-ul>li{position:relative}.fa-li{position:absolute;left:-2.14286em;width:2.14286em;top:.14286em;text-align:center}.fa-li.fa-lg{left:-1.85714em}.fa-border{padding:.2em .25em .15em;border:.08em solid #eee;border-radius:.1em}.fa.pull-left{margin-right:.3em}.fa.pull-right{margin-left:.3em}.fa-spin{-webkit-animation:fa-spin 2s infinite linear;animation:fa-spin 2s infinite linear}@-webkit-keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}@keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}.fa-rotate-90{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=1);-webkit-transform:rotate(90deg);-ms-transform:rotate(90deg);transform:rotate(90deg)}.fa-rotate-180{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=2);-webkit-transform:rotate(180deg);-ms-transform:rotate(180deg);transform:rotate(180deg)}.fa-rotate-270{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=3);-webkit-transform:rotate(270deg);-ms-transform:rotate(270deg);transform:rotate(270deg)}.fa-flip-horizontal{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=0);-webkit-transform:scale(-1,1);-ms-transform:scale(-1,1);transform:scale(-1,1)}.fa-flip-vertical{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=2);-webkit-transform:scale(1,-1);-ms-transform:scale(1,-1);transform:scale(1,-1)}:root .fa-flip-horizontal,:root .fa-flip-vertical,:root .fa-rotate-180,:root .fa-rotate-270,:root .fa-rotate-90{filter:none}.fa-stack{position:relative;display:inline-block;width:2em;height:2em;line-height:2em;vertical-align:middle}.fa-stack-1x,.fa-stack-2x{position:absolute;left:0;width:100%;text-align:center}.fa-stack-1x{line-height:inherit}.fa-stack-2x{font-size:2em}.fa-inverse{color:#fff}.fa-glass:before{content:""}.fa-music:before{content:""}.fa-search:before{content:""}.fa-envelope-o:before{content:""}.fa-heart:before{content:""}.fa-star:before{content:""}.fa-star-o:before{content:""}.fa-user:before{content:""}.fa-film:before{content:""}.fa-th-large:before{content:""}.fa-th:before{content:""}.fa-th-list:before{content:""}.fa-check:before{content:""}.fa-close:before,.fa-remove:before,.fa-times:before{content:""}.fa-search-plus:before{content:""}.fa-search-minus:before{content:""}.fa-power-off:before{content:""}.fa-signal:before{content:""}.fa-cog:before,.fa-gear:before{content:""}.fa-trash-o:before{content:""}.fa-home:before{content:""}.fa-file-o:before{content:""}.fa-clock-o:before{content:""}.fa-road:before{content:""}.fa-download:before{content:""}.fa-arrow-circle-o-down:before{content:""}.fa-arrow-circle-o-up:before{content:""}.fa-inbox:before{content:""}.fa-play-circle-o:before{content:""}.fa-repeat:before,.fa-rotate-right:before{content:""}.fa-refresh:before{content:""}.fa-list-alt:before{content:""}.fa-lock:before{content:""}.fa-flag:before{content:""}.fa-headphones:before{content:""}.fa-volume-off:before{content:""}.fa-volume-down:before{content:""}.fa-volume-up:before{content:""}.fa-qrcode:before{content:""}.fa-barcode:before{content:""}.fa-tag:before{content:""}.fa-tags:before{content:""}.fa-book:before{content:""}.fa-bookmark:before{content:""}.fa-print:before{content:""}.fa-camera:before{content:""}.fa-font:before{content:""}.fa-bold:before{content:""}.fa-italic:before{content:""}.fa-text-height:before{content:""}.fa-text-width:before{content:""}.fa-align-left:before{content:""}.fa-align-center:before{content:""}.fa-align-right:before{content:""}.fa-align-justify:before{content:""}.fa-list:before{content:""}.fa-dedent:before,.fa-outdent:before{content:""}.fa-indent:before{content:""}.fa-video-camera:before{content:""}.fa-image:before,.fa-photo:before,.fa-picture-o:before{content:""}.fa-pencil:before{content:""}.fa-map-marker:before{content:""}.fa-adjust:before{content:""}.fa-tint:before{content:""}.fa-edit:before,.fa-pencil-square-o:before{content:""}.fa-share-square-o:before{content:""}.fa-check-square-o:before{content:""}.fa-arrows:before{content:""}.fa-step-backward:before{content:""}.fa-fast-backward:before{content:""}.fa-backward:before{content:""}.fa-play:before{content:""}.fa-pause:before{content:""}.fa-stop:before{content:""}.fa-forward:before{content:""}.fa-fast-forward:before{content:""}.fa-step-forward:before{content:""}.fa-eject:before{content:""}.fa-chevron-left:before{content:""}.fa-chevron-right:before{content:""}.fa-plus-circle:before{content:""}.fa-minus-circle:before{content:""}.fa-times-circle:before{content:""}.fa-check-circle:before{content:""}.fa-question-circle:before{content:""}.fa-info-circle:before{content:""}.fa-crosshairs:before{content:""}.fa-times-circle-o:before{content:""}.fa-check-circle-o:before{content:""}.fa-ban:before{content:""}.fa-arrow-left:before{content:""}.fa-arrow-right:before{content:""}.fa-arrow-up:before{content:""}.fa-arrow-down:before{content:""}.fa-mail-forward:before,.fa-share:before{content:""}.fa-expand:before{content:""}.fa-compress:before{content:""}.fa-plus:before{content:""}.fa-minus:before{content:""}.fa-asterisk:before{content:""}.fa-exclamation-circle:before{content:""}.fa-gift:before{content:""}.fa-leaf:before{content:""}.fa-fire:before{content:""}.fa-eye:before{content:""}.fa-eye-slash:before{content:""}.fa-exclamation-triangle:before,.fa-warning:before{content:""}.fa-plane:before{content:""}.fa-calendar:before{content:""}.fa-random:before{content:""}.fa-comment:before{content:""}.fa-magnet:before{content:""}.fa-chevron-up:before{content:""}.fa-chevron-down:before{content:""}.fa-retweet:before{content:""}.fa-shopping-cart:before{content:""}.fa-folder:before{content:""}.fa-folder-open:before{content:""}.fa-arrows-v:before{content:""}.fa-arrows-h:before{content:""}.fa-bar-chart-o:before,.fa-bar-chart:before{content:""}.fa-twitter-square:before{content:""}.fa-facebook-square:before{content:""}.fa-camera-retro:before{content:""}.fa-key:before{content:""}.fa-cogs:before,.fa-gears:before{content:""}.fa-comments:before{content:""}.fa-thumbs-o-up:before{content:""}.fa-thumbs-o-down:before{content:""}.fa-star-half:before{content:""}.fa-heart-o:before{content:""}.fa-sign-out:before{content:""}.fa-linkedin-square:before{content:""}.fa-thumb-tack:before{content:""}.fa-external-link:before{content:""}.fa-sign-in:before{content:""}.fa-trophy:before{content:""}.fa-github-square:before{content:""}.fa-upload:before{content:""}.fa-lemon-o:before{content:""}.fa-phone:before{content:""}.fa-square-o:before{content:""}.fa-bookmark-o:before{content:""}.fa-phone-square:before{content:""}.fa-twitter:before{content:""}.fa-facebook:before{content:""}.fa-github:before{content:""}.fa-unlock:before{content:""}.fa-credit-card:before{content:""}.fa-rss:before{content:""}.fa-hdd-o:before{content:""}.fa-bullhorn:before{content:""}.fa-bell:before{content:""}.fa-certificate:before{content:""}.fa-hand-o-right:before{content:""}.fa-hand-o-left:before{content:""}.fa-hand-o-up:before{content:""}.fa-hand-o-down:before{content:""}.fa-arrow-circle-left:before{content:""}.fa-arrow-circle-right:before{content:""}.fa-arrow-circle-up:before{content:""}.fa-arrow-circle-down:before{content:""}.fa-globe:before{content:""}.fa-wrench:before{content:""}.fa-tasks:before{content:""}.fa-filter:before{content:""}.fa-briefcase:before{content:""}.fa-arrows-alt:before{content:""}.fa-group:before,.fa-users:before{content:""}.fa-chain:before,.fa-link:before{content:""}.fa-cloud:before{content:""}.fa-flask:before{content:""}.fa-cut:before,.fa-scissors:before{content:""}.fa-copy:before,.fa-files-o:before{content:""}.fa-paperclip:before{content:""}.fa-floppy-o:before,.fa-save:before{content:""}.fa-square:before{content:""}.fa-bars:before,.fa-navicon:before,.fa-reorder:before{content:""}.fa-list-ul:before{content:""}.fa-list-ol:before{content:""}.fa-strikethrough:before{content:""}.fa-underline:before{content:""}.fa-table:before{content:""}.fa-magic:before{content:""}.fa-truck:before{content:""}.fa-pinterest:before{content:""}.fa-pinterest-square:before{content:""}.fa-google-plus-square:before{content:""}.fa-google-plus:before{content:""}.fa-money:before{content:""}.fa-caret-down:before{content:""}.fa-caret-up:before{content:""}.fa-caret-left:before{content:""}.fa-caret-right:before{content:""}.fa-columns:before{content:""}.fa-sort:before,.fa-unsorted:before{content:""}.fa-sort-desc:before,.fa-sort-down:before{content:""}.fa-sort-asc:before,.fa-sort-up:before{content:""}.fa-envelope:before{content:""}.fa-linkedin:before{content:""}.fa-rotate-left:before,.fa-undo:before{content:""}.fa-gavel:before,.fa-legal:before{content:""}.fa-dashboard:before,.fa-tachometer:before{content:""}.fa-comment-o:before{content:""}.fa-comments-o:before{content:""}.fa-bolt:before,.fa-flash:before{content:""}.fa-sitemap:before{content:""}.fa-umbrella:before{content:""}.fa-clipboard:before,.fa-paste:before{content:""}.fa-lightbulb-o:before{content:""}.fa-exchange:before{content:""}.fa-cloud-download:before{content:""}.fa-cloud-upload:before{content:""}.fa-user-md:before{content:""}.fa-stethoscope:before{content:""}.fa-suitcase:before{content:""}.fa-bell-o:before{content:""}.fa-coffee:before{content:""}.fa-cutlery:before{content:""}.fa-file-text-o:before{content:""}.fa-building-o:before{content:""}.fa-hospital-o:before{content:""}.fa-ambulance:before{content:""}.fa-medkit:before{content:""}.fa-fighter-jet:before{content:""}.fa-beer:before{content:""}.fa-h-square:before{content:""}.fa-plus-square:before{content:""}.fa-angle-double-left:before{content:""}.fa-angle-double-right:before{content:""}.fa-angle-double-up:before{content:""}.fa-angle-double-down:before{content:""}.fa-angle-left:before{content:""}.fa-angle-right:before{content:""}.fa-angle-up:before{content:""}.fa-angle-down:before{content:""}.fa-desktop:before{content:""}.fa-laptop:before{content:""}.fa-tablet:before{content:""}.fa-mobile-phone:before,.fa-mobile:before{content:""}.fa-circle-o:before{content:""}.fa-quote-left:before{content:""}.fa-quote-right:before{content:""}.fa-spinner:before{content:""}.fa-circle:before{content:""}.fa-mail-reply:before,.fa-reply:before{content:""}.fa-github-alt:before{content:""}.fa-folder-o:before{content:""}.fa-folder-open-o:before{content:""}.fa-smile-o:before{content:""}.fa-frown-o:before{content:""}.fa-meh-o:before{content:""}.fa-gamepad:before{content:""}.fa-keyboard-o:before{content:""}.fa-flag-o:before{content:""}.fa-flag-checkered:before{content:""}.fa-terminal:before{content:""}.fa-code:before{content:""}.fa-mail-reply-all:before,.fa-reply-all:before{content:""}.fa-star-half-empty:before,.fa-star-half-full:before,.fa-star-half-o:before{content:""}.fa-location-arrow:before{content:""}.fa-crop:before{content:""}.fa-code-fork:before{content:""}.fa-chain-broken:before,.fa-unlink:before{content:""}.fa-question:before{content:""}.fa-info:before{content:""}.fa-exclamation:before{content:""}.fa-superscript:before{content:""}.fa-subscript:before{content:""}.fa-eraser:before{content:""}.fa-puzzle-piece:before{content:""}.fa-microphone:before{content:""}.fa-microphone-slash:before{content:""}.fa-shield:before{content:""}.fa-calendar-o:before{content:""}.fa-fire-extinguisher:before{content:""}.fa-rocket:before{content:""}.fa-maxcdn:before{content:""}.fa-chevron-circle-left:before{content:""}.fa-chevron-circle-right:before{content:""}.fa-chevron-circle-up:before{content:""}.fa-chevron-circle-down:before{content:""}.fa-html5:before{content:""}.fa-css3:before{content:""}.fa-anchor:before{content:""}.fa-unlock-alt:before{content:""}.fa-bullseye:before{content:""}.fa-ellipsis-h:before{content:""}.fa-ellipsis-v:before{content:""}.fa-rss-square:before{content:""}.fa-play-circle:before{content:""}.fa-ticket:before{content:""}.fa-minus-square:before{content:""}.fa-minus-square-o:before{content:""}.fa-level-up:before{content:""}.fa-level-down:before{content:""}.fa-check-square:before{content:""}.fa-pencil-square:before{content:""}.fa-external-link-square:before{content:""}.fa-share-square:before{content:""}.fa-compass:before{content:""}.fa-caret-square-o-down:before,.fa-toggle-down:before{content:""}.fa-caret-square-o-up:before,.fa-toggle-up:before{content:""}.fa-caret-square-o-right:before,.fa-toggle-right:before{content:""}.fa-eur:before,.fa-euro:before{content:""}.fa-gbp:before{content:""}.fa-dollar:before,.fa-usd:before{content:""}.fa-inr:before,.fa-rupee:before{content:""}.fa-cny:before,.fa-jpy:before,.fa-rmb:before,.fa-yen:before{content:""}.fa-rouble:before,.fa-rub:before,.fa-ruble:before{content:""}.fa-krw:before,.fa-won:before{content:""}.fa-bitcoin:before,.fa-btc:before{content:""}.fa-file:before{content:""}.fa-file-text:before{content:""}.fa-sort-alpha-asc:before{content:""}.fa-sort-alpha-desc:before{content:""}.fa-sort-amount-asc:before{content:""}.fa-sort-amount-desc:before{content:""}.fa-sort-numeric-asc:before{content:""}.fa-sort-numeric-desc:before{content:""}.fa-thumbs-up:before{content:""}.fa-thumbs-down:before{content:""}.fa-youtube-square:before{content:""}.fa-youtube:before{content:""}.fa-xing:before{content:""}.fa-xing-square:before{content:""}.fa-youtube-play:before{content:""}.fa-dropbox:before{content:""}.fa-stack-overflow:before{content:""}.fa-instagram:before{content:""}.fa-flickr:before{content:""}.fa-adn:before{content:""}.fa-bitbucket:before{content:""}.fa-bitbucket-square:before{content:""}.fa-tumblr:before{content:""}.fa-tumblr-square:before{content:""}.fa-long-arrow-down:before{content:""}.fa-long-arrow-up:before{content:""}.fa-long-arrow-left:before{content:""}.fa-long-arrow-right:before{content:""}.fa-apple:before{content:""}.fa-windows:before{content:""}.fa-android:before{content:""}.fa-linux:before{content:""}.fa-dribbble:before{content:""}.fa-skype:before{content:""}.fa-foursquare:before{content:""}.fa-trello:before{content:""}.fa-female:before{content:""}.fa-male:before{content:""}.fa-gittip:before{content:""}.fa-sun-o:before{content:""}.fa-moon-o:before{content:""}.fa-archive:before{content:""}.fa-bug:before{content:""}.fa-vk:before{content:""}.fa-weibo:before{content:""}.fa-renren:before{content:""}.fa-pagelines:before{content:""}.fa-stack-exchange:before{content:""}.fa-arrow-circle-o-right:before{content:""}.fa-arrow-circle-o-left:before{content:""}.fa-caret-square-o-left:before,.fa-toggle-left:before{content:""}.fa-dot-circle-o:before{content:""}.fa-wheelchair:before{content:""}.fa-vimeo-square:before{content:""}.fa-try:before,.fa-turkish-lira:before{content:""}.fa-plus-square-o:before{content:""}.fa-space-shuttle:before{content:""}.fa-slack:before{content:""}.fa-envelope-square:before{content:""}.fa-wordpress:before{content:""}.fa-openid:before{content:""}.fa-bank:before,.fa-institution:before,.fa-university:before{content:""}.fa-graduation-cap:before,.fa-mortar-board:before{content:""}.fa-yahoo:before{content:""}.fa-google:before{content:""}.fa-reddit:before{content:""}.fa-reddit-square:before{content:""}.fa-stumbleupon-circle:before{content:""}.fa-stumbleupon:before{content:""}.fa-delicious:before{content:""}.fa-digg:before{content:""}.fa-pied-piper:before{content:""}.fa-pied-piper-alt:before{content:""}.fa-drupal:before{content:""}.fa-joomla:before{content:""}.fa-language:before{content:""}.fa-fax:before{content:""}.fa-building:before{content:""}.fa-child:before{content:""}.fa-paw:before{content:""}.fa-spoon:before{content:""}.fa-cube:before{content:""}.fa-cubes:before{content:""}.fa-behance:before{content:""}.fa-behance-square:before{content:""}.fa-steam:before{content:""}.fa-steam-square:before{content:""}.fa-recycle:before{content:""}.fa-automobile:before,.fa-car:before{content:""}.fa-cab:before,.fa-taxi:before{content:""}.fa-tree:before{content:""}.fa-spotify:before{content:""}.fa-deviantart:before{content:""}.fa-soundcloud:before{content:""}.fa-database:before{content:""}.fa-file-pdf-o:before{content:""}.fa-file-word-o:before{content:""}.fa-file-excel-o:before{content:""}.fa-file-powerpoint-o:before{content:""}.fa-file-image-o:before,.fa-file-photo-o:before,.fa-file-picture-o:before{content:""}.fa-file-archive-o:before,.fa-file-zip-o:before{content:""}.fa-file-audio-o:before,.fa-file-sound-o:before{content:""}.fa-file-movie-o:before,.fa-file-video-o:before{content:""}.fa-file-code-o:before{content:""}.fa-vine:before{content:""}.fa-codepen:before{content:""}.fa-jsfiddle:before{content:""}.fa-life-bouy:before,.fa-life-buoy:before,.fa-life-ring:before,.fa-life-saver:before,.fa-support:before{content:""}.fa-circle-o-notch:before{content:""}.fa-ra:before,.fa-rebel:before{content:""}.fa-empire:before,.fa-ge:before{content:""}.fa-git-square:before{content:""}.fa-git:before{content:""}.fa-hacker-news:before{content:""}.fa-tencent-weibo:before{content:""}.fa-qq:before{content:""}.fa-wechat:before,.fa-weixin:before{content:""}.fa-paper-plane:before,.fa-send:before{content:""}.fa-paper-plane-o:before,.fa-send-o:before{content:""}.fa-history:before{content:""}.fa-circle-thin:before{content:""}.fa-header:before{content:""}.fa-paragraph:before{content:""}.fa-sliders:before{content:""}.fa-share-alt:before{content:""}.fa-share-alt-square:before{content:""}.fa-bomb:before{content:""}.fa-futbol-o:before,.fa-soccer-ball-o:before{content:""}.fa-tty:before{content:""}.fa-binoculars:before{content:""}.fa-plug:before{content:""}.fa-slideshare:before{content:""}.fa-twitch:before{content:""}.fa-yelp:before{content:""}.fa-newspaper-o:before{content:""}.fa-wifi:before{content:""}.fa-calculator:before{content:""}.fa-paypal:before{content:""}.fa-google-wallet:before{content:""}.fa-cc-visa:before{content:""}.fa-cc-mastercard:before{content:""}.fa-cc-discover:before{content:""}.fa-cc-amex:before{content:""}.fa-cc-paypal:before{content:""}.fa-cc-stripe:before{content:""}.fa-bell-slash:before{content:""}.fa-bell-slash-o:before{content:""}.fa-trash:before{content:""}.fa-copyright:before{content:""}.fa-at:before{content:""}.fa-eyedropper:before{content:""}.fa-paint-brush:before{content:""}.fa-birthday-cake:before{content:""}.fa-area-chart:before{content:""}.fa-pie-chart:before{content:""}.fa-line-chart:before{content:""}.fa-lastfm:before{content:""}.fa-lastfm-square:before{content:""}.fa-toggle-off:before{content:""}.fa-toggle-on:before{content:""}.fa-bicycle:before{content:""}.fa-bus:before{content:""}.fa-ioxhost:before{content:""}.fa-angellist:before{content:""}.fa-cc:before{content:""}.fa-ils:before,.fa-shekel:before,.fa-sheqel:before{content:""}.fa-meanpath:before{content:""}#nprogress div.spinner{width:18px;margin-left:-9px;left:50%}.nav a{cursor:pointer}.navbar-static-top{margin-bottom:0}menu{margin:0;padding:0}.dashboard-content .panel-default{margin-bottom:20px!important;padding:0;margin:0 1%;overflow:scroll}.dashboard-content .panel-default .panel-heading{color:#333;background-color:#f5f5f5;border-color:#ddd}.dashboard-content .panel-default table{width:100%}.dashboard-content .panel-default table thead{font-weight:700}.dashboard-content .panel-default table tr{height:40px}.dashboard-content .grid{border:none}.quick-filters{clear:both}.quick-filters li>span{padding:10px 15px;display:block}.page-header{margin:10px 0 15px}.page-header .lead{margin-bottom:0}ma-view-actions{margin:25px 0 15px;float:right}.list-header .filters{margin:0;float:left}.list-header .filters form{padding-left:0}.list-header ma-quick-filter{float:left}.list-header form{padding-left:0}.list-header .filters .filter{float:left;margin-right:5px}.list-header .filters .filter .input-group-btn{width:auto}.list-header .filters .datepicker .form-control{border-top-left-radius:0;border-bottom-left-radius:0}.list-header .filters .datepicker .btn-default{height:34px}.list-header .filters .form-control{width:auto}.grid{background-color:#fff}.grid a{cursor:pointer}.grid .label-default{margin-right:5px;font-weight:400;font-size:12px;padding-top:4px;text-decoration:none}.grid td a.multiple:hover{text-decoration:none}.grid thead tr .glyphicon{font-size:13px;color:#aaa}div.bottom-loader{margin-top:40px;position:inherit;width:auto;height:auto}div.bottom-loader:after{position:relative;display:inherit;margin:0 auto}div.bottom-loader:before{display:none}.grid-detail .total{float:left;display:inline-block;margin:25px 10px 0 0}.grid-detail .pagination{float:right}.form-horizontal textarea{height:150px}.form-horizontal input[type=checkbox],.form-horizontal input[type=radio]{max-width:16px;box-shadow:none;cursor:pointer;margin:0}.form-horizontal .border-around{margin-top:2px;background-color:#FFF;background-image:none;border:1px solid #CCC;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075);-webkit-transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s;-o-transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s;transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s;width:100%}.form-horizontal a{cursor:pointer}.form-horizontal .ta-toolbar button{font-size:12px;padding:5px 8px}.form-horizontal .ta-toolbar button.active{z-index:1}.form-horizontal#show-view .label-default{margin-right:5px;font-weight:400;font-size:12px;padding-top:4px}.form-horizontal#show-view .control-label{padding-top:0}#nprogress{pointer-events:none}#nprogress .bar{background:#29d;position:fixed;z-index:1031;top:0;left:0;width:100%;height:2px}#nprogress .peg{display:block;position:absolute;right:0;width:100px;height:100%;box-shadow:0 0 10px #29d,0 0 5px #29d;opacity:1;-webkit-transform:rotate(3deg) translate(0px,-4px);-ms-transform:rotate(3deg) translate(0px,-4px);transform:rotate(3deg) translate(0px,-4px)}#nprogress .spinner{display:block;position:fixed;z-index:1031;top:15px;right:15px}#nprogress .spinner-icon{width:18px;height:18px;box-sizing:border-box;border:2px solid transparent;border-top-color:#29d;border-left-color:#29d;border-radius:50%;-webkit-animation:nprogress-spinner 400ms linear infinite;animation:nprogress-spinner 400ms linear infinite}.nprogress-custom-parent{overflow:hidden;position:relative}.nprogress-custom-parent #nprogress .bar,.nprogress-custom-parent #nprogress .spinner{position:absolute}@-webkit-keyframes nprogress-spinner{0%{-webkit-transform:rotate(0deg)}100%{-webkit-transform:rotate(360deg)}}@keyframes nprogress-spinner{0%{transform:rotate(0deg)}100%{transform:rotate(360deg)}}body,html{min-height:100%}.humane,.humane-flatty{position:fixed;-moz-transition:all .4s ease-in-out;-webkit-transition:all .4s ease-in-out;-ms-transition:all .4s ease-in-out;-o-transition:all .4s ease-in-out;transition:all .4s ease-in-out;z-index:100000;filter:alpha(Opacity=100);font-family:Helvetica Neue,Helvetica,san-serif;font-size:16px;top:0;left:30%;opacity:0;width:40%;color:#444;padding:10px;text-align:center;background-color:#fff;-webkit-border-bottom-right-radius:3px;-webkit-border-bottom-left-radius:3px;-moz-border-radius-bottomright:3px;-moz-border-radius-bottomleft:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px;-webkit-box-shadow:0 1px 2px rgba(0,0,0,.5);box-shadow:0 1px 2px rgba(0,0,0,.5);-moz-transform:translateY(-100px);-webkit-transform:translateY(-100px);-ms-transform:translateY(-100px);-o-transform:translateY(-100px);transform:translateY(-100px)}.humane p,.humane ul,.humane-flatty p,.humane-flatty ul{margin:0;padding:0}.humane ul,.humane-flatty ul{list-style:none}.humane-flatty.humane-flatty-info,.humane.humane-flatty-info{background-color:#3498db;color:#FFF}.humane-flatty.humane-flatty-success,.humane.humane-flatty-success{background-color:#18bc9c;color:#FFF}.humane-flatty.humane-flatty-error,.humane.humane-flatty-error{background-color:#e74c3c;color:#FFF}.humane-animate,.humane-flatty.humane-flatty-animate{opacity:1;-moz-transform:translateY(0);-webkit-transform:translateY(0);-ms-transform:translateY(0);-o-transform:translateY(0);transform:translateY(0)}.humane-animate:hover,.humane-flatty.humane-flatty-animate:hover{opacity:.7}.humane-flatty.humane-flatty-js-animate,.humane-js-animate{opacity:1;-moz-transform:translateY(0);-webkit-transform:translateY(0);-ms-transform:translateY(0);-o-transform:translateY(0);transform:translateY(0)}.humane-flatty.humane-flatty-js-animate:hover,.humane-js-animate:hover{opacity:.7;filter:alpha(Opacity=70)} \ No newline at end of file diff --git a/public/assets/ngadmin/vendor/ng-admin.min.js b/public/assets/ngadmin/vendor/ng-admin.min.js new file mode 100644 index 000000000..32de245d2 --- /dev/null +++ b/public/assets/ngadmin/vendor/ng-admin.min.js @@ -0,0 +1,13 @@ +!function(a,b){"function"==typeof define&&define.amd?define(b):"object"==typeof exports?module.exports=b():a.ngAdmin=b()}(this,function(){var a,b,c;!function(d){function e(a,b){return u.call(a,b)}function f(a,b){var c,d,e,f,g,h,i,j,k,l,m,n=b&&b.split("/"),o=s.map,p=o&&o["*"]||{};if(a&&"."===a.charAt(0))if(b){for(n=n.slice(0,n.length-1),a=a.split("/"),g=a.length-1,s.nodeIdCompat&&w.test(a[g])&&(a[g]=a[g].replace(w,"")),a=n.concat(a),k=0;k0&&(a.splice(k-1,2),k-=2)}a=a.join("/")}else 0===a.indexOf("./")&&(a=a.substring(2));if((n||p)&&o){for(c=a.split("/"),k=c.length;k>0;k-=1){if(d=c.slice(0,k).join("/"),n)for(l=n.length;l>0;l-=1)if(e=o[n.slice(0,l).join("/")],e&&(e=e[d])){f=e,h=k;break}if(f)break;!i&&p&&p[d]&&(i=p[d],j=k)}!f&&i&&(f=i,h=j),f&&(c.splice(0,h,f),a=c.join("/"))}return a}function g(a,b){return function(){var c=v.call(arguments,0);return"string"!=typeof c[0]&&1===c.length&&c.push(null),n.apply(d,c.concat([a,b]))}}function h(a){return function(b){return f(b,a)}}function i(a){return function(b){q[a]=b}}function j(a){if(e(r,a)){var b=r[a];delete r[a],t[a]=!0,m.apply(d,b)}if(!e(q,a)&&!e(t,a))throw new Error("No "+a);return q[a]}function k(a){var b,c=a?a.indexOf("!"):-1;return c>-1&&(b=a.substring(0,c),a=a.substring(c+1,a.length)),[b,a]}function l(a){return function(){return s&&s.config&&s.config[a]||{}}}var m,n,o,p,q={},r={},s={},t={},u=Object.prototype.hasOwnProperty,v=[].slice,w=/\.js$/;o=function(a,b){var c,d=k(a),e=d[0];return a=d[1],e&&(e=f(e,b),c=j(e)),e?a=c&&c.normalize?c.normalize(a,h(b)):f(a,b):(a=f(a,b),d=k(a),e=d[0],a=d[1],e&&(c=j(e))),{f:e?e+"!"+a:a,n:a,pr:e,p:c}},p={require:function(a){return g(a)},exports:function(a){var b=q[a];return"undefined"!=typeof b?b:q[a]={}},module:function(a){return{id:a,uri:"",exports:q[a],config:l(a)}}},m=function(a,b,c,f){var h,k,l,m,n,s,u=[],v=typeof c;if(f=f||a,"undefined"===v||"function"===v){for(b=!b.length&&c.length?["require","exports","module"]:b,n=0;n>>0,d=Number(arguments[2])||0;for(d=0>d?Math.ceil(d):Math.floor(d),0>d&&(d+=c);c>d;d++)if(d in a&&a[d]===b)return d;return-1}function i(a,b,c,d){var e,i=f(c,d),j={},k=[];for(var l in i)if(i[l].params&&(e=g(i[l].params),e.length))for(var m in e)h(k,e[m])>=0||(k.push(e[m]),j[e[m]]=a[e[m]]);return M({},j,b)}function j(a,b,c){if(!c){c=[];for(var d in a)c.push(d)}for(var e=0;e "));if(s[c]=d,I(a))q.push(c,[function(){return b.get(a)}],j);else{var e=b.annotate(a);L(e,function(a){a!==c&&i.hasOwnProperty(a)&&n(i[a],a)}),q.push(c,a,e)}r.pop(),s[c]=f}}function o(a){return J(a)&&a.then&&a.$$promises}if(!J(i))throw new Error("'invocables' must be an object");var p=g(i||{}),q=[],r=[],s={};return L(i,n),i=r=s=null,function(d,f,g){function h(){--u||(v||e(t,f.$$values),r.$$values=t,r.$$promises=r.$$promises||!0,delete r.$$inheritedValues,n.resolve(t))}function i(a){r.$$failure=a,n.reject(a)}function j(c,e,f){function j(a){l.reject(a),i(a)}function k(){if(!G(r.$$failure))try{l.resolve(b.invoke(e,g,t)),l.promise.then(function(a){t[c]=a,h()},j)}catch(a){j(a)}}var l=a.defer(),m=0;L(f,function(a){s.hasOwnProperty(a)&&!d.hasOwnProperty(a)&&(m++,s[a].then(function(b){t[a]=b,--m||k()},j))}),m||k(),s[c]=l.promise}if(o(d)&&g===c&&(g=f,f=d,d=null),d){if(!J(d))throw new Error("'locals' must be an object")}else d=k;if(f){if(!o(f))throw new Error("'parent' must be a promise returned by $resolve.resolve()")}else f=m;var n=a.defer(),r=n.promise,s=r.$$promises={},t=M({},d),u=1+q.length/3,v=!1;if(G(f.$$failure))return i(f.$$failure),r;f.$$inheritedValues&&e(t,l(f.$$inheritedValues,p)),M(s,f.$$promises),f.$$values?(v=e(t,l(f.$$values,p)),r.$$inheritedValues=l(f.$$values,p),h()):(f.$$inheritedValues&&(r.$$inheritedValues=l(f.$$inheritedValues,p)),f.then(h,i));for(var w=0,x=q.length;x>w;w+=3)d.hasOwnProperty(q[w])?h():j(q[w],q[w+1],q[w+2]);return r}},this.resolve=function(a,b,c,d){return this.study(a)(b,c,d)}}function p(a,b,c){this.fromConfig=function(a,b,c){return G(a.template)?this.fromString(a.template,b):G(a.templateUrl)?this.fromUrl(a.templateUrl,b):G(a.templateProvider)?this.fromProvider(a.templateProvider,b,c):null},this.fromString=function(a,b){return H(a)?a(b):a},this.fromUrl=function(c,d){return H(c)&&(c=c(d)),null==c?null:a.get(c,{cache:b,headers:{Accept:"text/html"}}).then(function(a){return a.data})},this.fromProvider=function(a,b,d){return c.invoke(a,null,d||{params:b})}}function q(a,b,e){function f(b,c,d,e){if(q.push(b),o[b])return o[b];if(!/^\w+(-+\w+)*(?:\[\])?$/.test(b))throw new Error("Invalid parameter name '"+b+"' in pattern '"+a+"'");if(p[b])throw new Error("Duplicate parameter name '"+b+"' in pattern '"+a+"'");return p[b]=new O.Param(b,c,d,e),p[b]}function g(a,b,c){var d=["",""],e=a.replace(/[\\\[\]\^$*+?.()|{}]/g,"\\$&");if(!b)return e;switch(c){case!1:d=["(",")"];break;case!0:d=["?(",")?"];break;default:d=["("+c+"|",")?"]}return e+d[0]+b+d[1]}function h(c,e){var f,g,h,i,j;return f=c[2]||c[3],j=b.params[f],h=a.substring(m,c.index),g=e?c[4]:c[4]||("*"==c[1]?".*":null),i=O.type(g||"string")||d(O.type("string"),{pattern:new RegExp(g)}),{id:f,regexp:g,segment:h,type:i,cfg:j}}b=M({params:{}},J(b)?b:{});var i,j=/([:*])([\w\[\]]+)|\{([\w\[\]]+)(?:\:((?:[^{}\\]+|\\.|\{(?:[^{}\\]+|\\.)*\})+))?\}/g,k=/([:]?)([\w\[\]-]+)|\{([\w\[\]-]+)(?:\:((?:[^{}\\]+|\\.|\{(?:[^{}\\]+|\\.)*\})+))?\}/g,l="^",m=0,n=this.segments=[],o=e?e.params:{},p=this.params=e?e.params.$$new():new O.ParamSet,q=[];this.source=a;for(var r,s,t;(i=j.exec(a))&&(r=h(i,!1),!(r.segment.indexOf("?")>=0));)s=f(r.id,r.type,r.cfg,"path"),l+=g(r.segment,s.type.pattern.source,s.squash),n.push(r.segment),m=j.lastIndex;t=a.substring(m);var u=t.indexOf("?");if(u>=0){var v=this.sourceSearch=t.substring(u);if(t=t.substring(0,u),this.sourcePath=a.substring(0,m+u),v.length>0)for(m=0;i=k.exec(v);)r=h(i,!0),s=f(r.id,r.type,r.cfg,"search"),m=j.lastIndex}else this.sourcePath=a,this.sourceSearch="";l+=g(t)+(b.strict===!1?"/?":"")+"$",n.push(t),this.regexp=new RegExp(l,b.caseInsensitive?"i":c),this.prefix=n[0],this.$$paramNames=q}function r(a){M(this,a)}function s(){function a(a){return null!=a?a.toString().replace(/\//g,"%2F"):a}function e(a){return null!=a?a.toString().replace(/%2F/g,"/"):a}function f(a){return this.pattern.test(a)}function i(){return{strict:t,caseInsensitive:p}}function j(a){return H(a)||K(a)&&H(a[a.length-1])}function k(){for(;x.length;){var a=x.shift();if(a.pattern)throw new Error("You cannot override a type's .pattern at runtime.");b.extend(v[a.name],o.invoke(a.def))}}function l(a){M(this,a||{})}O=this;var o,p=!1,t=!0,u=!1,v={},w=!0,x=[],y={string:{encode:a,decode:e,is:f,pattern:/[^/]*/},"int":{encode:a,decode:function(a){return parseInt(a,10)},is:function(a){return G(a)&&this.decode(a.toString())===a},pattern:/\d+/},bool:{encode:function(a){return a?1:0},decode:function(a){return 0!==parseInt(a,10)},is:function(a){return a===!0||a===!1},pattern:/0|1/},date:{encode:function(a){return this.is(a)?[a.getFullYear(),("0"+(a.getMonth()+1)).slice(-2),("0"+a.getDate()).slice(-2)].join("-"):c},decode:function(a){if(this.is(a))return a;var b=this.capture.exec(a);return b?new Date(b[1],b[2]-1,b[3]):c},is:function(a){return a instanceof Date&&!isNaN(a.valueOf())},equals:function(a,b){return this.is(a)&&this.is(b)&&a.toISOString()===b.toISOString()},pattern:/[0-9]{4}-(?:0[1-9]|1[0-2])-(?:0[1-9]|[1-2][0-9]|3[0-1])/,capture:/([0-9]{4})-(0[1-9]|1[0-2])-(0[1-9]|[1-2][0-9]|3[0-1])/},json:{encode:b.toJson,decode:b.fromJson,is:b.isObject,equals:b.equals,pattern:/[^/]*/},any:{encode:b.identity,decode:b.identity,is:b.identity,equals:b.equals,pattern:/.*/}};s.$$getDefaultValue=function(a){if(!j(a.value))return a.value;if(!o)throw new Error("Injectable functions cannot be called at configuration time");return o.invoke(a.value)},this.caseInsensitive=function(a){return G(a)&&(p=a),p},this.strictMode=function(a){return G(a)&&(t=a),t},this.defaultSquashPolicy=function(a){if(!G(a))return u;if(a!==!0&&a!==!1&&!I(a))throw new Error("Invalid squash policy: "+a+". Valid policies: false, true, arbitrary-string");return u=a,a},this.compile=function(a,b){return new q(a,M(i(),b))},this.isMatcher=function(a){if(!J(a))return!1;var b=!0;return L(q.prototype,function(c,d){H(c)&&(b=b&&G(a[d])&&H(a[d]))}),b},this.type=function(a,b,c){if(!G(b))return v[a];if(v.hasOwnProperty(a))throw new Error("A type named '"+a+"' has already been defined.");return v[a]=new r(M({name:a},b)),c&&(x.push({name:a,def:c}),w||k()),this},L(y,function(a,b){v[b]=new r(M({name:b},a))}),v=d(v,{}),this.$get=["$injector",function(a){return o=a,w=!1,k(),L(y,function(a,b){v[b]||(v[b]=new r(a))}),this}],this.Param=function(a,b,d,e){function f(a){var b=J(a)?g(a):[],c=-1===h(b,"value")&&-1===h(b,"type")&&-1===h(b,"squash")&&-1===h(b,"array");return c&&(a={value:a}),a.$$fn=j(a.value)?a.value:function(){return a.value},a}function i(b,c,d){if(b.type&&c)throw new Error("Param '"+a+"' has two type configurations.");return c?c:b.type?b.type instanceof r?b.type:new r(b.type):"config"===d?v.any:v.string}function k(){var b={array:"search"===e?"auto":!1},c=a.match(/\[\]$/)?{array:!0}:{};return M(b,c,d).array}function l(a,b){var c=a.squash;if(!b||c===!1)return!1;if(!G(c)||null==c)return u;if(c===!0||I(c))return c;throw new Error("Invalid squash policy: '"+c+"'. Valid policies: false, true, or arbitrary string")}function p(a,b,d,e){var f,g,i=[{from:"",to:d||b?c:""},{from:null,to:d||b?c:""}];return f=K(a.replace)?a.replace:[],I(e)&&f.push({from:e,to:c}),g=n(f,function(a){return a.from}),m(i,function(a){return-1===h(g,a.from)}).concat(f)}function q(){if(!o)throw new Error("Injectable functions cannot be called at configuration time");return o.invoke(d.$$fn)}function s(a){function b(a){return function(b){return b.from===a}}function c(a){var c=n(m(w.replace,b(a)),function(a){return a.to});return c.length?c[0]:a}return a=c(a),G(a)?w.type.decode(a):q()}function t(){return"{Param:"+a+" "+b+" squash: '"+z+"' optional: "+y+"}"}var w=this;d=f(d),b=i(d,b,e);var x=k();b=x?b.$asArray(x,"search"===e):b,"string"!==b.name||x||"path"!==e||d.value!==c||(d.value="");var y=d.value!==c,z=l(d,y),A=p(d,x,y,z);M(this,{id:a,type:b,location:e,array:x,squash:z,replace:A,isOptional:y,value:s,dynamic:c,config:d,toString:t})},l.prototype={$$new:function(){return d(this,M(new l,{$$parent:this}))},$$keys:function(){for(var a=[],b=[],c=this,d=g(l.prototype);c;)b.push(c),c=c.$$parent;return b.reverse(),L(b,function(b){L(g(b),function(b){-1===h(a,b)&&-1===h(d,b)&&a.push(b)})}),a},$$values:function(a){var b={},c=this;return L(c.$$keys(),function(d){b[d]=c[d].value(a&&a[d])}),b},$$equals:function(a,b){var c=!0,d=this;return L(d.$$keys(),function(e){var f=a&&a[e],g=b&&b[e];d[e].type.equals(f,g)||(c=!1)}),c},$$validates:function(a){var b,c,d,e=!0,f=this;return L(this.$$keys(),function(g){d=f[g],c=a[g],b=!c&&d.isOptional,e=e&&(b||!!d.type.is(c))}),e},$$parent:c},this.ParamSet=l}function t(a,d){function e(a){var b=/^\^((?:\\[^a-zA-Z0-9]|[^\\\[\]\^$*+?.()|{}]+)*)/.exec(a.source);return null!=b?b[1].replace(/\\(.)/g,"$1"):""}function f(a,b){return a.replace(/\$(\$|\d{1,2})/,function(a,c){return b["$"===c?0:Number(c)]})}function g(a,b,c){if(!c)return!1;var d=a.invoke(b,b,{$match:c});return G(d)?d:!0}function h(d,e,f,g){function h(a,b,c){return"/"===p?a:b?p.slice(0,-1)+a:c?p.slice(1)+a:a}function m(a){function b(a){var b=a(f,d);return b?(I(b)&&d.replace().url(b),!0):!1}if(!a||!a.defaultPrevented){var e=o&&d.url()===o;if(o=c,e)return!0;var g,h=j.length;for(g=0;h>g;g++)if(b(j[g]))return;k&&b(k)}}function n(){return i=i||e.$on("$locationChangeSuccess",m)}var o,p=g.baseHref(),q=d.url();return l||n(),{sync:function(){m()},listen:function(){return n()},update:function(a){return a?void(q=d.url()):void(d.url()!==q&&(d.url(q),d.replace()))},push:function(a,b,e){d.url(a.format(b||{})),o=e&&e.$$avoidResync?d.url():c,e&&e.replace&&d.replace()},href:function(c,e,f){if(!c.validates(e))return null;var g=a.html5Mode();b.isObject(g)&&(g=g.enabled);var i=c.format(e);if(f=f||{},g||null===i||(i="#"+a.hashPrefix()+i),i=h(i,g,f.absolute),!f.absolute||!i)return i;var j=!g&&i?"/":"",k=d.port();return k=80===k||443===k?"":":"+k,[d.protocol(),"://",d.host(),k,j,i].join("")}}}var i,j=[],k=null,l=!1;this.rule=function(a){if(!H(a))throw new Error("'rule' must be a function");return j.push(a),this},this.otherwise=function(a){if(I(a)){var b=a;a=function(){return b}}else if(!H(a))throw new Error("'rule' must be a function");return k=a,this},this.when=function(a,b){var c,h=I(b);if(I(a)&&(a=d.compile(a)),!h&&!H(b)&&!K(b))throw new Error("invalid 'handler' in when()");var i={matcher:function(a,b){return h&&(c=d.compile(b),b=["$match",function(a){return c.format(a)}]),M(function(c,d){return g(c,b,a.exec(d.path(),d.search()))},{prefix:I(a.prefix)?a.prefix:""})},regex:function(a,b){if(a.global||a.sticky)throw new Error("when() RegExp must not be global or sticky");return h&&(c=b,b=["$match",function(a){return f(c,a)}]),M(function(c,d){return g(c,b,a.exec(d.path()))},{prefix:e(a)})}},j={matcher:d.isMatcher(a),regex:a instanceof RegExp};for(var k in j)if(j[k])return this.rule(i[k](a,b));throw new Error("invalid 'what' in when()")},this.deferIntercept=function(a){a===c&&(a=!0),l=a},this.$get=h,h.$inject=["$location","$rootScope","$injector","$browser"]}function u(a,e){function f(a){return 0===a.indexOf(".")||0===a.indexOf("^")}function l(a,b){if(!a)return c;var d=I(a),e=d?a:a.name,g=f(e);if(g){if(!b)throw new Error("No reference point given for path '"+e+"'");b=l(b);for(var h=e.split("."),i=0,j=h.length,k=b;j>i;i++)if(""!==h[i]||0!==i){if("^"!==h[i])break;if(!k.parent)throw new Error("Path '"+e+"' not valid for state '"+b.name+"'");k=k.parent}else k=b;h=h.slice(i).join("."),e=k.name+(k.name&&h?".":"")+h}var m=y[e];return!m||!d&&(d||m!==a&&m.self!==a)?c:m}function m(a,b){z[a]||(z[a]=[]),z[a].push(b)}function o(a){for(var b=z[a]||[];b.length;)p(b.shift())}function p(b){b=d(b,{self:b,resolve:b.resolve||{},toString:function(){return this.name}});var c=b.name;if(!I(c)||c.indexOf("@")>=0)throw new Error("State must have a valid name");if(y.hasOwnProperty(c))throw new Error("State '"+c+"'' is already defined");var e=-1!==c.indexOf(".")?c.substring(0,c.lastIndexOf(".")):I(b.parent)?b.parent:J(b.parent)&&I(b.parent.name)?b.parent.name:"";if(e&&!y[e])return m(e,b.self);for(var f in B)H(B[f])&&(b[f]=B[f](b,B.$delegates[f]));return y[c]=b,!b[A]&&b.url&&a.when(b.url,["$match","$stateParams",function(a,c){x.$current.navigable==b&&j(a,c)||x.transitionTo(b,a,{inherit:!0,location:!1})}]),o(c),b}function q(a){return a.indexOf("*")>-1}function r(a){var b=a.split("."),c=x.$current.name.split(".");if("**"===b[0]&&(c=c.slice(h(c,b[1])),c.unshift("**")),"**"===b[b.length-1]&&(c.splice(h(c,b[b.length-2])+1,Number.MAX_VALUE),c.push("**")),b.length!=c.length)return!1;for(var d=0,e=b.length;e>d;d++)"*"===b[d]&&(c[d]="*");return c.join("")===b.join("")}function s(a,b){return I(a)&&!G(b)?B[a]:H(b)&&I(a)?(B[a]&&!B.$delegates[a]&&(B.$delegates[a]=B[a]),B[a]=b,this):this}function t(a,b){return J(a)?b=a:b.name=a,p(b),this}function u(a,e,f,h,m,o,p){function s(b,c,d,f){var g=a.$broadcast("$stateNotFound",b,c,d);if(g.defaultPrevented)return p.update(),B;if(!g.retry)return null;if(f.$retry)return p.update(),C;var h=x.transition=e.when(g.retry);return h.then(function(){return h!==x.transition?u:(b.options.$retry=!0,x.transitionTo(b.to,b.toParams,b.options))},function(){return B}),p.update(),h}function t(a,c,d,g,i,j){var l=d?c:k(a.params.$$keys(),c),n={$stateParams:l};i.resolve=m.resolve(a.resolve,n,i.resolve,a);var o=[i.resolve.then(function(a){i.globals=a})];return g&&o.push(g),L(a.views,function(c,d){var e=c.resolve&&c.resolve!==a.resolve?c.resolve:{};e.$template=[function(){return f.load(d,{view:c,locals:n,params:l,notify:j.notify})||""}],o.push(m.resolve(e,n,i.resolve,a).then(function(f){if(H(c.controllerProvider)||K(c.controllerProvider)){var g=b.extend({},e,n);f.$$controller=h.invoke(c.controllerProvider,null,g)}else f.$$controller=c.controller;f.$$state=a,f.$$controllerAs=c.controllerAs,i[d]=f}))}),e.all(o).then(function(){return i})}var u=e.reject(new Error("transition superseded")),z=e.reject(new Error("transition prevented")),B=e.reject(new Error("transition aborted")),C=e.reject(new Error("transition failed"));return w.locals={resolve:null,globals:{$stateParams:{}}},x={params:{},current:w.self,$current:w,transition:null},x.reload=function(){return x.transitionTo(x.current,o,{reload:!0,inherit:!1,notify:!0})},x.go=function(a,b,c){return x.transitionTo(a,b,M({inherit:!0,relative:x.$current},c))},x.transitionTo=function(b,c,f){c=c||{},f=M({location:!0,inherit:!1,relative:null,notify:!0,reload:!1,$retry:!1},f||{});var g,j=x.$current,m=x.params,n=j.path,q=l(b,f.relative);if(!G(q)){var r={to:b,toParams:c,options:f},y=s(r,j.self,m,f);if(y)return y;if(b=r.to,c=r.toParams,f=r.options,q=l(b,f.relative),!G(q)){if(!f.relative)throw new Error("No such state '"+b+"'");throw new Error("Could not resolve '"+b+"' from state '"+f.relative+"'")}}if(q[A])throw new Error("Cannot transition to abstract state '"+b+"'");if(f.inherit&&(c=i(o,c||{},x.$current,q)),!q.params.$$validates(c))return C;c=q.params.$$values(c),b=q;var B=b.path,D=0,E=B[D],F=w.locals,H=[];if(!f.reload)for(;E&&E===n[D]&&E.ownParams.$$equals(c,m);)F=H[D]=E.locals,D++,E=B[D];if(v(b,j,F,f))return b.self.reloadOnSearch!==!1&&p.update(),x.transition=null,e.when(x.current);if(c=k(b.params.$$keys(),c||{}),f.notify&&a.$broadcast("$stateChangeStart",b.self,c,j.self,m).defaultPrevented)return p.update(),z;for(var I=e.when(F),J=D;J=D;d--)g=n[d],g.self.onExit&&h.invoke(g.self.onExit,g.self,g.locals.globals),g.locals=null;for(d=D;d=0?e:e+"@"+(f?f.state.name:"")}function A(a,b){var c,d=a.match(/^\s*({[^}]*})\s*$/);if(d&&(a=b+"("+d[1]+")"),c=a.replace(/\n/g," ").match(/^([^(]+?)\s*(\((.*)\))?$/),!c||4!==c.length)throw new Error("Invalid state ref '"+a+"'");return{state:c[1],paramExpr:c[3]||null}}function B(a){var b=a.parent().inheritedData("$uiView");return b&&b.state&&b.state.name?b.state:void 0}function C(a,c){var d=["location","inherit","reload"];return{restrict:"A",require:["?^uiSrefActive","?^uiSrefActiveEq"],link:function(e,f,g,h){var i=A(g.uiSref,a.current.name),j=null,k=B(f)||a.$current,l=null,m="A"===f.prop("tagName"),n="FORM"===f[0].nodeName,o=n?"action":"href",p=!0,q={relative:k,inherit:!0},r=e.$eval(g.uiSrefOpts)||{};b.forEach(d,function(a){a in r&&(q[a]=r[a])});var s=function(c){if(c&&(j=b.copy(c)),p){l=a.href(i.state,j,q);var d=h[1]||h[0];return d&&d.$$setStateInfo(i.state,j),null===l?(p=!1,!1):void g.$set(o,l)}};i.paramExpr&&(e.$watch(i.paramExpr,function(a){a!==j&&s(a)},!0),j=b.copy(e.$eval(i.paramExpr))),s(),n||f.bind("click",function(b){var d=b.which||b.button;if(!(d>1||b.ctrlKey||b.metaKey||b.shiftKey||f.attr("target"))){var e=c(function(){a.go(i.state,j,q)});b.preventDefault();var g=m&&!l?1:0;b.preventDefault=function(){g--<=0&&c.cancel(e)}}})}}}function D(a,b,c){return{restrict:"A",controller:["$scope","$element","$attrs",function(b,d,e){function f(){g()?d.addClass(j):d.removeClass(j)}function g(){return"undefined"!=typeof e.uiSrefActiveEq?h&&a.is(h.name,i):h&&a.includes(h.name,i)}var h,i,j;j=c(e.uiSrefActiveEq||e.uiSrefActive||"",!1)(b),this.$$setStateInfo=function(b,c){h=a.get(b,B(d)),i=c,f()},b.$on("$stateChangeSuccess",f)}]}}function E(a){var b=function(b){return a.is(b)};return b.$stateful=!0,b}function F(a){var b=function(b){return a.includes(b)};return b.$stateful=!0,b}var G=b.isDefined,H=b.isFunction,I=b.isString,J=b.isObject,K=b.isArray,L=b.forEach,M=b.extend,N=b.copy;b.module("ui.router.util",["ng"]),b.module("ui.router.router",["ui.router.util"]),b.module("ui.router.state",["ui.router.router","ui.router.util"]),b.module("ui.router",["ui.router.state"]),b.module("ui.router.compat",["ui.router"]),o.$inject=["$q","$injector"],b.module("ui.router.util").service("$resolve",o),p.$inject=["$http","$templateCache","$injector"],b.module("ui.router.util").service("$templateFactory",p);var O;q.prototype.concat=function(a,b){var c={caseInsensitive:O.caseInsensitive(),strict:O.strictMode(),squash:O.defaultSquashPolicy()};return new q(this.sourcePath+a+this.sourceSearch,M(c,b),this)},q.prototype.toString=function(){return this.source},q.prototype.exec=function(a,b){function c(a){function b(a){return a.split("").reverse().join("")}function c(a){return a.replace(/\\-/,"-")}var d=b(a).split(/-(?!\\)/),e=n(d,b);return n(e,c).reverse()}var d=this.regexp.exec(a);if(!d)return null;b=b||{};var e,f,g,h=this.parameters(),i=h.length,j=this.segments.length-1,k={};if(j!==d.length-1)throw new Error("Unbalanced capture group in route '"+this.source+"'");for(e=0;j>e;e++){g=h[e];var l=this.params[g],m=d[e+1];for(f=0;fe;e++)g=h[e],k[g]=this.params[g].value(b[g]);return k},q.prototype.parameters=function(a){return G(a)?this.params[a]||null:this.$$paramNames},q.prototype.validates=function(a){return this.params.$$validates(a)},q.prototype.format=function(a){function b(a){return encodeURIComponent(a).replace(/-/g,function(a){return"%5C%"+a.charCodeAt(0).toString(16).toUpperCase()})}a=a||{};var c=this.segments,d=this.parameters(),e=this.params;if(!this.validates(a))return null;var f,g=!1,h=c.length-1,i=d.length,j=c[0];for(f=0;i>f;f++){var k=h>f,l=d[f],m=e[l],o=m.value(a[l]),p=m.isOptional&&m.type.equals(m.value(),o),q=p?m.squash:!1,r=m.type.encode(o);if(k){var s=c[f+1];if(q===!1)null!=r&&(j+=K(r)?n(r,b).join("-"):encodeURIComponent(r)),j+=s;else if(q===!0){var t=j.match(/\/$/)?/\/?(.*)/:/(.*)/;j+=s.match(t)[1]}else I(q)&&(j+=q+s)}else{if(null==r||p&&q!==!1)continue;K(r)||(r=[r]),r=n(r,encodeURIComponent).join("&"+l+"="),j+=(g?"&":"?")+(l+"="+r),g=!0}}return j},r.prototype.is=function(){return!0},r.prototype.encode=function(a){return a},r.prototype.decode=function(a){return a},r.prototype.equals=function(a,b){return a==b},r.prototype.$subPattern=function(){var a=this.pattern.toString();return a.substr(1,a.length-2)},r.prototype.pattern=/.*/,r.prototype.toString=function(){return"{Type:"+this.name+"}"},r.prototype.$asArray=function(a,b){function d(a,b){function d(a,b){return function(){return a[b].apply(a,arguments)}}function e(a){return K(a)?a:G(a)?[a]:[]}function f(a){switch(a.length){case 0:return c;case 1:return"auto"===b?a[0]:a;default:return a}}function g(a){return!a}function h(a,b){return function(c){c=e(c);var d=n(c,a);return b===!0?0===m(d,g).length:f(d)}}function i(a){return function(b,c){var d=e(b),f=e(c);if(d.length!==f.length)return!1;for(var g=0;gh||"undefined"==typeof g)return 1;if(h>g||"undefined"==typeof h)return-1}}return a.n-b.n}function g(a){var b=-1,c=a.length,e=a[0],f=a[c/2|0],g=a[c-1];if(e&&"object"==typeof e&&f&&"object"==typeof f&&g&&"object"==typeof g)return!1;for(e=j(),e["false"]=e["null"]=e["true"]=e.undefined=!1,f=j(),f.k=a,f.l=e,f.push=d;++bc?0:c);++d3&&"function"==typeof g[i-2])var j=bb(g[--i-1],g[i--],2);else i>2&&"function"==typeof g[i-1]&&(j=g[--i]);for(;++h=t&&f===a,j=[];if(i){var k=g(d);k?(f=b,d=k):i=!1}for(;++ef(d,k)&&j.push(k);return i&&l(d),j}function eb(a,b,c,d){d=(d||0)-1;for(var e=a?a.length:0,f=[];++d=t&&h===a,o=e||n?i():m;for(n&&(o=g(o),h=b);++fh(o,q))&&((e||n)&&o.push(q),m.push(p))}return n?(k(o.k),l(o)):e&&k(o),m}function jb(a){return function(b,c,e){var f={};c=X.createCallback(c,e,3),e=-1;var g=b?b.length:0;if("number"==typeof g)for(;++ec?Cc(0,g+c):c)||0,Jc(a)?h=-1f&&(f=h)}}else b=null==b&&xb(a)?e:X.createCallback(b,c,3),Db(a,function(a,c,e){c=b(a,c,e),c>d&&(d=c,f=a)});return f}function Hb(a,b,c,e){if(!a)return c;var f=3>arguments.length;b=X.createCallback(b,e,4);var g=-1,h=a.length;if("number"==typeof h)for(f&&(c=a[++g]);++garguments.length;return b=X.createCallback(b,d,4),Eb(a,function(a,d,f){c=e?(e=!1,a):b(c,a,d,f)}),c}function Jb(a){var b=-1,c=a?a.length:0,d=Zb("number"==typeof c?c:0);return Db(a,function(a){var c=hb(0,++b);d[b]=d[c],d[c]=a}),d}function Kb(a,b,c){var e;b=X.createCallback(b,c,3),c=-1;var f=a?a.length:0;if("number"==typeof f)for(;++cd?Cc(0,e+d):d||0}else if(d)return d=Ob(b,c),b[d]===c?d:-1;return a(b,c,d)}function Nb(a,b,c){if("number"!=typeof b&&null!=b){var d=0,e=-1,f=a?a.length:0;for(b=X.createCallback(b,c,3);++ee;)d=e+f>>>1,c(a[d])c?0:c);++b0?k=tc(e,c):(g&&nc(g),c=l,g=k=l=o,c&&(m=Uc(),h=a.apply(j,f),k||g||(f=j=null)))}var f,g,h,i,j,k,l,m=0,n=!1,p=!0;if(!ub(a))throw new gc;if(b=Cc(0,b)||0,!0===c)var q=!0,p=!1;else vb(c)&&(q=c.leading,n="maxWait"in c&&(Cc(b,c.maxWait)||0),p="trailing"in c?c.trailing:p);return function(){if(f=arguments,i=Uc(),j=this,l=p&&(k||!q),!1===n)var c=q&&!k;else{g||q||(m=i);var o=n-(i-m),r=0>=o;r?(g&&(g=nc(g)),m=i,h=a.apply(j,f)):g||(g=tc(d,o))}return r&&k?k=nc(k):k||b===n||(k=tc(e,b)),c&&(r=!0,h=a.apply(j,f)),!r||k||g||(f=j=null),h}}function Ub(a){return a}function Vb(a,b,c){var d=!0,e=b&&sb(b);b&&(c||e.length)||(null==c&&(c=b),f=Y,b=a,a=X,e=sb(b)),!1===c?d=!1:vb(c)&&"chain"in c&&(d=c.chain);var f=a,g=ub(f);Db(e,function(c){var e=a[c]=b[c];g&&(f.prototype[c]=function(){var b=this.__chain__,c=this.__wrapped__,g=[c];if(sc.apply(g,arguments),g=e.apply(a,g),d||b){if(c===g&&vb(g))return this;g=new f(g),g.__chain__=b}return g})})}function Wb(){}function Xb(a){return function(b){return b[a]}}function Yb(){return this.__wrapped__}c=c?_.defaults(W.Object(),c,_.pick(W,H)):W;var Zb=c.Array,$b=c.Boolean,_b=c.Date,ac=c.Function,bc=c.Math,cc=c.Number,dc=c.Object,ec=c.RegExp,fc=c.String,gc=c.TypeError,hc=[],ic=dc.prototype,jc=c._,kc=ic.toString,lc=ec("^"+fc(kc).replace(/[.*+?^${}()|[\]\\]/g,"\\$&").replace(/toString| for [^\]]+/g,".*?")+"$"),mc=bc.ceil,nc=c.clearTimeout,oc=bc.floor,pc=ac.prototype.toString,qc=nb(qc=dc.getPrototypeOf)&&qc,rc=ic.hasOwnProperty,sc=hc.push,tc=c.setTimeout,uc=hc.splice,vc=hc.unshift,wc=function(){try{var a={},b=nb(b=dc.defineProperty)&&b,c=b(a,a,a)&&b}catch(d){}return c}(),xc=nb(xc=dc.create)&&xc,yc=nb(yc=Zb.isArray)&&yc,zc=c.isFinite,Ac=c.isNaN,Bc=nb(Bc=dc.keys)&&Bc,Cc=bc.max,Dc=bc.min,Ec=c.parseInt,Fc=bc.random,Gc={};Gc[J]=Zb,Gc[K]=$b,Gc[L]=_b,Gc[M]=ac,Gc[O]=dc,Gc[N]=cc,Gc[P]=ec,Gc[Q]=fc,Y.prototype=X.prototype;var Hc=X.support={};Hc.funcDecomp=!nb(c.a)&&F.test(n),Hc.funcNames="string"==typeof ac.name,X.templateSettings={escape:/<%-([\s\S]+?)%>/g,evaluate:/<%([\s\S]+?)%>/g,interpolate:C,variable:"",imports:{_:X}},xc||(ab=function(){function a(){}return function(b){if(vb(b)){a.prototype=b;var d=new a;a.prototype=null}return d||c.Object()}}());var Ic=wc?function(a,b){T.value=b,wc(a,"__bindData__",T)}:Wb,Jc=yc||function(a){return a&&"object"==typeof a&&"number"==typeof a.length&&kc.call(a)==J||!1},Kc=Bc?function(a){return vb(a)?Bc(a):[]}:V,Lc={"&":"&","<":"<",">":">",'"':""","'":"'"},Mc=tb(Lc),Nc=ec("("+Kc(Mc).join("|")+")","g"),Oc=ec("["+Kc(Lc).join("")+"]","g"),Pc=qc?function(a){if(!a||kc.call(a)!=O)return!1;var b=a.valueOf,c=nb(b)&&(c=qc(b))&&qc(c);return c?a==c||qc(a)==c:ob(a)}:ob,Qc=jb(function(a,b,c){rc.call(a,c)?a[c]++:a[c]=1}),Rc=jb(function(a,b,c){(rc.call(a,c)?a[c]:a[c]=[]).push(b)}),Sc=jb(function(a,b,c){a[c]=b}),Tc=Fb,Uc=nb(Uc=_b.now)&&Uc||function(){return(new _b).getTime()},Vc=8==Ec(v+"08")?Ec:function(a,b){return Ec(xb(a)?a.replace(D,""):a,b||0)};return X.after=function(a,b){if(!ub(b))throw new gc;return function(){return 1>--a?b.apply(this,arguments):void 0}},X.assign=u,X.at=function(a){for(var b=arguments,c=-1,d=eb(b,!0,!1,1),b=b[2]&&b[2][b[1]]===a?1:d.length,e=Zb(b);++c=t&&g(d?c[d]:m)))}var j=c[0],o=-1,p=j?j.length:0,q=[];a:for(;++o(r?b(r,n):h(m,n))){for(d=e,(r||m).push(n);--d;)if(r=f[d],0>(r?b(r,n):h(c[d],n)))continue a;q.push(n)}}for(;e--;)(r=f[e])&&l(r);return k(f),k(m),q},X.invert=tb,X.invoke=function(a,b){var c=m(arguments,2),d=-1,e="function"==typeof b,f=a?a.length:0,g=Zb("number"==typeof f?f:0);return Db(a,function(a){g[++d]=(e?b:a[b]).apply(a,c)}),g},X.keys=Kc,X.map=Fb,X.mapValues=function(a,b,c){var e={};return b=X.createCallback(b,c,3),d(a,function(a,c,d){e[c]=b(a,c,d)}),e},X.max=Gb,X.memoize=function(a,b){function c(){var d=c.cache,e=b?b.apply(this,arguments):s+arguments[0];return rc.call(d,e)?d[e]:d[e]=a.apply(this,arguments)}if(!ub(a))throw new gc;return c.cache={},c},X.merge=function(a){var b=arguments,c=2;if(!vb(a))return a;if("number"!=typeof b[2]&&(c=b.length),c>3&&"function"==typeof b[c-2])var d=bb(b[--c-1],b[c--],2);else c>2&&"function"==typeof b[c-1]&&(d=b[--c]);for(var b=m(arguments,1,c),e=-1,f=i(),g=i();++eh&&(f=h)}}else b=null==b&&xb(a)?e:X.createCallback(b,c,3),Db(a,function(a,c,e){c=b(a,c,e),d>c&&(d=c,f=a)});return f},X.omit=function(a,b,c){var d={};if("function"!=typeof b){var e=[];p(a,function(a,b){e.push(b)});for(var e=db(e,eb(arguments,!0,!1,1)),f=-1,g=e.length;++fc?Cc(0,d+c):Dc(c,d-1))+1);d--;)if(a[d]===b)return d;return-1},X.mixin=Vb,X.noConflict=function(){return c._=jc,this},X.noop=Wb,X.now=Uc,X.parseInt=Vc,X.random=function(a,b,c){var d=null==a,e=null==b;return null==c&&("boolean"==typeof a&&e?(c=a,a=1):e||"boolean"!=typeof b||(c=b,e=!0)),d&&e&&(b=1),a=+a||0,e?(b=a,a=0):b=+b||0,c||a%1||b%1?(c=Fc(),Dc(a+c*(b-a+parseFloat("1e-"+((c+"").length-1))),b)):hb(a,b)},X.reduce=Hb,X.reduceRight=Ib,X.result=function(a,b){if(a){var c=a[b];return ub(c)?a[b]():c}},X.runInContext=n,X.size=function(a){var b=a?a.length:0;return"number"==typeof b?b:Kc(a).length},X.some=Kb,X.sortedIndex=Ob,X.template=function(a,b,c){var d=X.templateSettings;a=fc(a||""),c=q({},c,d);var e,f=q({},c.imports,d.imports),d=Kc(f),f=yb(f),g=0,i=c.interpolate||E,j="__p+='",i=ec((c.escape||E).source+"|"+i.source+"|"+(i===C?z:E).source+"|"+(c.evaluate||E).source+"|$","g");a.replace(i,function(b,c,d,f,i,k){return d||(d=f),j+=a.slice(g,k).replace(G,h),c&&(j+="'+__e("+c+")+'"),i&&(e=!0,j+="';"+i+";\n__p+='"),d&&(j+="'+((__t=("+d+"))==null?'':__t)+'"),g=k+b.length,b}),j+="';",i=c=c.variable,i||(c="obj",j="with("+c+"){"+j+"}"),j=(e?j.replace(w,""):j).replace(x,"$1").replace(y,"$1;"),j="function("+c+"){"+(i?"":c+"||("+c+"={});")+"var __t,__p='',__e=_.escape"+(e?",__j=Array.prototype.join;function print(){__p+=__j.call(arguments,'')}":";")+j+"return __p}";try{var k=ac(d,"return "+j).apply(o,f)}catch(l){throw l.source=j,l}return b?k(b):(k.source=j,k)},X.unescape=function(a){return null==a?"":fc(a).replace(Nc,pb)},X.uniqueId=function(a){var b=++r;return fc(null==a?"":a)+b},X.all=Ab,X.any=Kb,X.detect=Cb,X.findWhere=Cb,X.foldl=Hb,X.foldr=Ib,X.include=zb,X.inject=Hb,Vb(function(){var a={};return d(X,function(b,c){X.prototype[c]||(a[c]=b)}),a}(),!1),X.first=Lb,X.last=function(a,b,c){var d=0,e=a?a.length:0;if("number"!=typeof b&&null!=b){var f=e;for(b=X.createCallback(b,c,3);f--&&b(a[f],f,a);)d++}else if(d=b,null==d||c)return a?a[e-1]:o;return m(a,Cc(0,e-d))},X.sample=function(a,b,c){return a&&"number"!=typeof a.length&&(a=yb(a)),null==b||c?a?a[hb(0,a.length-1)]:o:(a=Jb(a),a.length=Dc(Cc(0,b),a.length),a)},X.take=Lb,X.head=Lb,d(X,function(a,b){var c="sample"!==b;X.prototype[b]||(X.prototype[b]=function(b,d){var e=this.__chain__,f=a(this.__wrapped__,b,d);return e||null!=b&&(!d||c&&"function"==typeof b)?new Y(f,e):f})}),X.VERSION="2.4.1",X.prototype.chain=function(){return this.__chain__=!0,this},X.prototype.toString=function(){return fc(this.__wrapped__)},X.prototype.value=Yb,X.prototype.valueOf=Yb,Db(["join","pop","shift"],function(a){var b=hc[a];X.prototype[a]=function(){var a=this.__chain__,c=b.apply(this.__wrapped__,arguments);return a?new Y(c,a):c}}),Db(["push","reverse","sort","unshift"],function(a){var b=hc[a];X.prototype[a]=function(){return b.apply(this.__wrapped__,arguments),this}}),Db(["concat","slice","splice"],function(a){var b=hc[a];X.prototype[a]=function(){return new Y(b.apply(this.__wrapped__,arguments),this.__chain__)}}),X}var o,p=[],q=[],r=0,s=+new Date+"",t=75,u=40,v=" \f \n\r\u2028\u2029 ᠎              ",w=/\b__p\+='';/g,x=/\b(__p\+=)''\+/g,y=/(__e\(.*?\)|\b__t\))\+'';/g,z=/\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g,A=/\w*$/,B=/^\s*function[ \n\r\t]+\w/,C=/<%=([\s\S]+?)%>/g,D=RegExp("^["+v+"]*0+(?=.$)"),E=/($^)/,F=/\bthis\b/,G=/['\n\r\t\u2028\u2029\\]/g,H="Array Boolean Date Function Math Number Object RegExp String _ attachEvent clearTimeout isFinite isNaN parseInt setTimeout".split(" "),I="[object Arguments]",J="[object Array]",K="[object Boolean]",L="[object Date]",M="[object Function]",N="[object Number]",O="[object Object]",P="[object RegExp]",Q="[object String]",R={};R[M]=!1,R[I]=R[J]=R[K]=R[L]=R[N]=R[O]=R[P]=R[Q]=!0;var S={leading:!1,maxWait:0,trailing:!1},T={configurable:!1,enumerable:!1,value:null,writable:!1},U={"boolean":!1,"function":!0,object:!0,number:!1,string:!1,undefined:!1},V={"\\":"\\","'":"'","\n":"n","\r":"r"," ":"t","\u2028":"u2028","\u2029":"u2029"},W=U[typeof window]&&window||this,X=U[typeof exports]&&exports&&!exports.nodeType&&exports,Y=U[typeof module]&&module&&!module.nodeType&&module,Z=Y&&Y.exports===X&&X,$=U[typeof global]&&global;!$||$.global!==$&&$.window!==$||(W=$);var _=n();"function"==typeof c&&"object"==typeof c.amd&&c.amd?(W._=_,c("lodash",[],function(){return _})):X&&Y?Z?(Y.exports=_)._=_:X._=_:W._=_}.call(this),function(){var a=angular.module("restangular",[]);a.provider("Restangular",function(){var a={};a.init=function(a,b){function c(a,b,c,d){var e={};return _.each(_.keys(d),function(f){var g=d[f];g.params=_.extend({},g.params,a.defaultRequestParams[g.method.toLowerCase()]),_.isEmpty(g.params)&&delete g.params,e[f]=a.isSafe(g.method)?function(){return b(_.extend(g,{url:c}))}:function(a){return b(_.extend(g,{url:c,data:a}))}}),e}a.configuration=b;var d=["get","head","options","trace","getlist"];b.isSafe=function(a){return _.contains(d,a.toLowerCase())};var e=/^https?:\/\//i;b.isAbsoluteUrl=function(a){return _.isUndefined(b.absoluteUrl)||_.isNull(b.absoluteUrl)?a&&e.test(a):b.absoluteUrl},b.absoluteUrl=_.isUndefined(b.absoluteUrl)?!0:b.absoluteUrl,a.setSelfLinkAbsoluteUrl=function(a){b.absoluteUrl=a},b.baseUrl=_.isUndefined(b.baseUrl)?"":b.baseUrl,a.setBaseUrl=function(a){return b.baseUrl=/\/$/.test(a)?a.substring(0,a.length-1):a,this},b.extraFields=b.extraFields||[],a.setExtraFields=function(a){return b.extraFields=a,this},b.defaultHttpFields=b.defaultHttpFields||{},a.setDefaultHttpFields=function(a){return b.defaultHttpFields=a,this},b.withHttpValues=function(a,c){return _.defaults(c,a,b.defaultHttpFields)},b.encodeIds=_.isUndefined(b.encodeIds)?!0:b.encodeIds,a.setEncodeIds=function(a){b.encodeIds=a},b.defaultRequestParams=b.defaultRequestParams||{get:{},post:{},put:{},remove:{},common:{}},a.setDefaultRequestParams=function(a,c){var d=[],e=c||a;return _.isUndefined(c)?d.push("common"):_.isArray(a)?d=a:d.push(a),_.each(d,function(a){b.defaultRequestParams[a]=e}),this},a.requestParams=b.defaultRequestParams,b.defaultHeaders=b.defaultHeaders||{},a.setDefaultHeaders=function(c){return b.defaultHeaders=c,a.defaultHeaders=b.defaultHeaders,this},a.defaultHeaders=b.defaultHeaders,b.methodOverriders=b.methodOverriders||[],a.setMethodOverriders=function(a){var c=_.extend([],a);return b.isOverridenMethod("delete",c)&&c.push("remove"),b.methodOverriders=c,this},b.jsonp=_.isUndefined(b.jsonp)?!1:b.jsonp,a.setJsonp=function(a){b.jsonp=a},b.isOverridenMethod=function(a,c){var d=c||b.methodOverriders;return!_.isUndefined(_.find(d,function(b){return b.toLowerCase()===a.toLowerCase()}))},b.urlCreator=b.urlCreator||"path",a.setUrlCreator=function(a){if(!_.has(b.urlCreatorFactory,a))throw new Error("URL Path selected isn't valid");return b.urlCreator=a,this},b.restangularFields=b.restangularFields||{id:"id",route:"route",parentResource:"parentResource",restangularCollection:"restangularCollection",cannonicalId:"__cannonicalId",etag:"restangularEtag",selfLink:"href",get:"get",getList:"getList",put:"put",post:"post",remove:"remove",head:"head",trace:"trace",options:"options",patch:"patch",getRestangularUrl:"getRestangularUrl",getRequestedUrl:"getRequestedUrl",putElement:"putElement",addRestangularMethod:"addRestangularMethod",getParentList:"getParentList",clone:"clone",ids:"ids",httpConfig:"_$httpConfig",reqParams:"reqParams",one:"one",all:"all",several:"several",oneUrl:"oneUrl",allUrl:"allUrl",customPUT:"customPUT",customPOST:"customPOST",customDELETE:"customDELETE",customGET:"customGET",customGETLIST:"customGETLIST",customOperation:"customOperation",doPUT:"doPUT",doPOST:"doPOST",doDELETE:"doDELETE",doGET:"doGET",doGETLIST:"doGETLIST",fromServer:"fromServer",withConfig:"withConfig",withHttpConfig:"withHttpConfig",singleOne:"singleOne",plain:"plain",save:"save"},a.setRestangularFields=function(a){return b.restangularFields=_.extend(b.restangularFields,a),this},b.isRestangularized=function(a){return!!a[b.restangularFields.one]||!!a[b.restangularFields.all]},b.setFieldToElem=function(a,b,c){var d=a.split("."),e=b;return _.each(_.initial(d),function(a){e[a]={},e=e[a]}),e[_.last(d)]=c,this},b.getFieldFromElem=function(a,b){var c=a.split("."),d=b;return _.each(c,function(a){d&&(d=d[a])}),angular.copy(d)},b.setIdToElem=function(a,c){return b.setFieldToElem(b.restangularFields.id,a,c),this},b.getIdFromElem=function(a){return b.getFieldFromElem(b.restangularFields.id,a)},b.isValidId=function(a){return""!==a&&!_.isUndefined(a)&&!_.isNull(a)},b.setUrlToElem=function(a,c){return b.setFieldToElem(b.restangularFields.selfLink,a,c),this},b.getUrlFromElem=function(a){return b.getFieldFromElem(b.restangularFields.selfLink,a)},b.useCannonicalId=_.isUndefined(b.useCannonicalId)?!1:b.useCannonicalId,a.setUseCannonicalId=function(a){return b.useCannonicalId=a,this},b.getCannonicalIdFromElem=function(a){var c=a[b.restangularFields.cannonicalId],d=b.isValidId(c)?c:b.getIdFromElem(a);return d},b.responseInterceptors=b.responseInterceptors||[],b.defaultResponseInterceptor=function(a){return a},b.responseExtractor=function(a,c,d,e,f,g){var h=angular.copy(b.responseInterceptors);h.push(b.defaultResponseInterceptor);var i=a;return _.each(h,function(a){i=a(i,c,d,e,f,g)}),i},a.addResponseInterceptor=function(a){return b.responseInterceptors.push(a),this},a.setResponseInterceptor=a.addResponseInterceptor,a.setResponseExtractor=a.addResponseInterceptor,b.requestInterceptors=b.requestInterceptors||[],b.defaultInterceptor=function(a,b,c,d,e,f,g){return{element:a,headers:e,params:f,httpConfig:g} +},b.fullRequestInterceptor=function(a,c,d,e,f,g,h){var i=angular.copy(b.requestInterceptors),j=b.defaultInterceptor(a,c,d,e,f,g,h);return _.reduce(i,function(a,b){return _.extend(a,b(a.element,c,d,e,a.headers,a.params,a.httpConfig))},j)},a.addRequestInterceptor=function(a){return b.requestInterceptors.push(function(b,c,d,e,f,g,h){return{headers:f,params:g,element:a(b,c,d,e),httpConfig:h}}),this},a.setRequestInterceptor=a.addRequestInterceptor,a.addFullRequestInterceptor=function(a){return b.requestInterceptors.push(a),this},a.setFullRequestInterceptor=a.addFullRequestInterceptor,b.errorInterceptor=b.errorInterceptor||function(){},a.setErrorInterceptor=function(a){return b.errorInterceptor=a,this},b.onBeforeElemRestangularized=b.onBeforeElemRestangularized||function(a){return a},a.setOnBeforeElemRestangularized=function(a){return b.onBeforeElemRestangularized=a,this},b.onElemRestangularized=b.onElemRestangularized||function(a){return a},a.setOnElemRestangularized=function(a){return b.onElemRestangularized=a,this},b.shouldSaveParent=b.shouldSaveParent||function(){return!0},a.setParentless=function(a){return _.isArray(a)?b.shouldSaveParent=function(b){return!_.contains(a,b)}:_.isBoolean(a)&&(b.shouldSaveParent=function(){return!a}),this},b.suffix=_.isUndefined(b.suffix)?null:b.suffix,a.setRequestSuffix=function(a){return b.suffix=a,this},b.transformers=b.transformers||{},a.addElementTransformer=function(c,d,e){var f=null,g=null;2===arguments.length?g=d:(g=e,f=d);var h=b.transformers[c];return h||(h=b.transformers[c]=[]),h.push(function(a,b){return _.isNull(f)||a==f?g(b):b}),a},a.extendCollection=function(b,c){return a.addElementTransformer(b,!0,c)},a.extendModel=function(b,c){return a.addElementTransformer(b,!1,c)},b.transformElem=function(a,c,d,e,f){if(!f&&!b.transformLocalElements&&!a[b.restangularFields.fromServer])return a;var g=b.transformers[d],h=a;return g&&_.each(g,function(a){h=a(c,h)}),b.onElemRestangularized(h,c,d,e)},b.transformLocalElements=_.isUndefined(b.transformLocalElements)?!1:b.transformLocalElements,a.setTransformOnlyServerElements=function(a){b.transformLocalElements=!a},b.fullResponse=_.isUndefined(b.fullResponse)?!1:b.fullResponse,a.setFullResponse=function(a){return b.fullResponse=a,this},b.urlCreatorFactory={};var f=function(){};f.prototype.setConfig=function(a){return this.config=a,this},f.prototype.parentsArray=function(a){for(var b=[];a;)b.push(a),a=a[this.config.restangularFields.parentResource];return b.reverse()},f.prototype.resource=function(a,d,e,f,g,h,i,j){var k=_.defaults(g||{},this.config.defaultRequestParams.common),l=_.defaults(f||{},this.config.defaultHeaders);i&&(b.isSafe(j)?l["If-None-Match"]=i:l["If-Match"]=i);var m=this.base(a);if(h){var n="";/\/$/.test(m)||(n+="/"),n+=h,m+=n}return this.config.suffix&&-1===m.indexOf(this.config.suffix,m.length-this.config.suffix.length)&&!this.config.getUrlFromElem(a)&&(m+=this.config.suffix),a[this.config.restangularFields.httpConfig]=void 0,c(this.config,d,m,{getList:this.config.withHttpValues(e,{method:"GET",params:k,headers:l}),get:this.config.withHttpValues(e,{method:"GET",params:k,headers:l}),jsonp:this.config.withHttpValues(e,{method:"jsonp",params:k,headers:l}),put:this.config.withHttpValues(e,{method:"PUT",params:k,headers:l}),post:this.config.withHttpValues(e,{method:"POST",params:k,headers:l}),remove:this.config.withHttpValues(e,{method:"DELETE",params:k,headers:l}),head:this.config.withHttpValues(e,{method:"HEAD",params:k,headers:l}),trace:this.config.withHttpValues(e,{method:"TRACE",params:k,headers:l}),options:this.config.withHttpValues(e,{method:"OPTIONS",params:k,headers:l}),patch:this.config.withHttpValues(e,{method:"PATCH",params:k,headers:l})})};var g=function(){};g.prototype=new f,g.prototype.base=function(a){var c=this;return _.reduce(this.parentsArray(a),function(a,d){var e,f=c.config.getUrlFromElem(d);if(f){if(c.config.isAbsoluteUrl(f))return f;e=f}else if(e=d[c.config.restangularFields.route],d[c.config.restangularFields.restangularCollection]){var g=d[c.config.restangularFields.ids];g&&(e+="/"+g.join(","))}else{var h;h=c.config.useCannonicalId?c.config.getCannonicalIdFromElem(d):c.config.getIdFromElem(d),b.isValidId(h)&&!d.singleOne&&(e+="/"+(c.config.encodeIds?encodeURIComponent(h):h))}return a.replace(/\/$/,"")+"/"+e},this.config.baseUrl)},g.prototype.fetchUrl=function(a,b){var c=this.base(a);return b&&(c+="/"+b),c},g.prototype.fetchRequestedUrl=function(a,c){function d(a){var b=[];for(var c in a)a.hasOwnProperty(c)&&b.push(c);return b.sort()}function e(a,b,c){for(var e=d(a),f=0;f2?b[2]:null},b.prototype.displayList=function(a){this.$location.search("q",null),this.$location.search("page",1),this.$location.search("sortField",null),this.$location.search("sortOrder",null),this.$location.search("quickFilters",null),this.$location.search("search",null),this.$location.path("/list/"+a.name())},b.prototype.isActive=function(a){return this.currentEntity===a.name()},b.prototype.getIconForEntity=function(a){return this.$sce.trustAsHtml(a.menuView().icon())},b.prototype.destroy=function(){this.$scope=void 0,this.$location=void 0},b.$inject=["$scope","$location","$sce","NgAdminConfiguration"],b}),c("ng-admin/Main/component/service/PanelBuilder",[],function(){function a(a,b,c,d,e){this.$q=a,this.$filter=b,this.$location=c,this.RetrieveQueries=d,this.Configuration=e()}return a.prototype.getPanelsData=function(){var a,b,c=this.Configuration.getViewsOfType("DashboardView"),d=this.$location.search(),e=d.sortField,f=d.sortDir,g=[],h=this;c=this.$filter("orderElement")(c);for(b in c)a=c[b],a.isEnabled()&&g.push(h.RetrieveQueries.getAll(a,1,!0,null,e,f));return this.$q.all(g).then(function(a){var b,d,e,f=[];for(b in a)d=a[b],e=c[b],f.push({label:e.title(),viewName:e.name(),fields:e.displayedFields,entity:e.getEntity(),perPage:e.perPage(),entries:d.entries});return f})},a.$inject=["$q","$filter","$location","RetrieveQueries","NgAdminConfiguration"],a}),c("ng-admin/Main/component/service/Validator",[],function(){function a(){}return a.prototype.validate=function(a,b){var c,d,e,f=a.getFields();for(e in f)d=f[e],c=d.validation(),"function"==typeof c.validator&&c.validator(b.values[d.name()])},a.$inject=[],a}),c("ng-admin/Main/component/service/config/Configurable",[],function(){function a(a,b){var c;for(c in b)!function(b){a[b]=function(a){return arguments.length?(this.config[b]=a,this):this.config[b]}}(c)}return a}),c("ng-admin/Main/component/service/config/Application",["require","angular","ng-admin/Main/component/service/config/Configurable"],function(a){function b(a){return a}function c(){}function d(a){this.entities={},this.config=e.copy(g),this.config.title=a||this.config.title}var e=a("angular"),f=a("ng-admin/Main/component/service/config/Configurable"),g={title:"Angular admin",baseApiUrl:"http://localhost:3000/",transformParams:b,customTemplate:c};return d.prototype.addEntity=function(a){return null===a.order()&&a.order(Object.keys(this.entities).length),this.entities[a.name()]=a,this},d.prototype.hasEntity=function(a){return a in this.entities},d.prototype.getEntity=function(a){return this.entities[a]},d.prototype.getEntities=function(){return this.entities},d.prototype.getEntityNames=function(){return Object.keys(this.entities)},d.prototype.getViewsOfType=function(a){var b,c=[];for(b in this.entities)c.push(this.entities[b].getViewByType(a));return c},d.prototype.getRouteFor=function(a,b){var c=a.getEntity(),d=c.baseApiUrl()||this.baseApiUrl(),e=a.getUrl(b)||c.getUrl(a,b);return e||(e=d+c.name(),b&&(e+="/"+b)),/^(?:[a-z]+:)?\/\//.test(e)||(e=d+e),e},d.prototype.getQueryParamsFor=function(a,b){var c=a.getEntity();"undefined"==typeof b&&(b={});var d=e.copy(b);return b=this.getQueryParams(b,d),b=c.getQueryParams(b,d),b=a.getQueryParams(b,d)},d.prototype.getQueryParams=function(a,b){return"function"==typeof this.config.transformParams?this.config.transformParams(a,b):this.config.transformParams},d.prototype.getViewByEntityAndType=function(a,b){var c=this.getEntity(a);return c.getViewByType(b)},f(d.prototype,g),d}),c("ng-admin/lib/utils",[],function(){function a(a,b){var c=new Function;c.prototype=b.prototype,a.prototype=new c,a.prototype.constructor=a}function b(a){var b=a.charAt(0).toUpperCase();return a=b+a.substr(1),a.replace(/[-_](.)/g,function(a,b){return" "+b.toUpperCase()})}return{inherits:a,camelCase:b}}),c("ng-admin/Main/component/service/config/Field",["require","angular","ng-admin/Main/component/service/config/Configurable","ng-admin/lib/utils"],function(a){function b(){return""}function c(a){this.config=d.copy(h),this.config.name=a||Math.random().toString(36).substring(7),this.config.label=f.camelCase(this.config.name),this.config.isDetailLink="id"===a,this.maps=[]}var d=a("angular"),e=a("ng-admin/Main/component/service/config/Configurable"),f=a("ng-admin/lib/utils"),g=["number","string","text","wysiwyg","email","date","boolean","choice","choices","password","template"],h={name:"myField",type:"string",label:"My field",editable:!0,displayed:!0,order:null,identifier:!1,format:"yyyy-MM-dd",template:b,isDetailLink:!1,list:!0,dashboard:!0,validation:{required:!1,minlength:0,maxlength:99999},choices:[],defaultValue:null,attributes:{},cssClasses:""};return e(c.prototype,h),c.prototype.type=function(a){if(0===arguments.length)return this.config.type;if(-1===g.indexOf(a))throw new Error('Type should be one of : "'+g.join('", "')+'" but "'+a+'" was given.');return this.config.type=a,this},c.prototype.map=function(a){return this.maps.push(a),this},c.prototype.validation=function(a){if(!arguments.length)return this.config.validation;for(var b in a)a.hasOwnProperty(b)&&(null===a[b]?delete this.config.validation[b]:this.config.validation[b]=a[b]);return this},c.prototype.getMappedValue=function(a,b){for(var c in this.maps)a=this.maps[c](a,b);return a},c.prototype.getCssClasses=function(a){return"function"==typeof this.config.cssClasses?this.config.cssClasses(a):typeof this.config.cssClasses.constructor===Array?this.config.cssClasses.join(" "):this.config.cssClasses},c.prototype.getTemplateValue=function(a){return"function"==typeof this.config.template?this.config.template(a):this.config.template},c.prototype.isEditLink=function(a){return console.warn("Field.isEditLink() is deprecated - use Field.isDetailLink() instead"),0===arguments.length?this.isDetailLink():this.isDetailLink(a)},c}),c("ng-admin/Main/component/service/config/Entry",[],function(){function a(a){this.values=a||{},this.listValues={},this.identifierValue=null,this.entityName=null}return a}),c("ng-admin/Main/component/service/config/view/View",["require","angular","ng-admin/Main/component/service/config/Entry","ng-admin/Main/component/service/config/Configurable"],function(a){function b(){return{}}function c(a){return a}function d(a){this.enabled=!0,this.fields={},this.entity=null,this.config=e.copy(h),this.config.name=a||this.config.name,this.displayedFields=[]}var e=a("angular"),f=a("ng-admin/Main/component/service/config/Entry"),g=a("ng-admin/Main/component/service/config/Configurable"),h={name:"myView",title:!1,actions:null,description:"",template:null,extraParams:null,interceptor:null,transformParams:c,url:null,headers:b};return d.prototype.isEnabled=function(){return this.enabled},d.prototype.disable=function(){return this.enabled=!1,this},d.prototype.enable=function(){return this.enabled=!0,this},d.prototype.setEntity=function(a){return this.entity=a,this},d.prototype.getEntity=function(){return this.entity},d.prototype.getUrl=function(a){return"function"==typeof this.config.url?this.config.url(a):this.config.url},d.prototype.addField=function(a){return null===a.order()&&a.order(Object.keys(this.fields).length),this.fields[a.name()]=a,a.displayed()&&(this.displayedFields[a.name()]=a),this},d.prototype.getFieldsOfType=function(a){var b,c,d={};for(c in this.fields)b=this.fields[c],b.type()===a&&(d[c]=b);return d},d.prototype.getFields=function(){return this.fields},d.prototype.getField=function(a){return this.fields[a]},d.prototype.getReferences=function(){var a,b=this.getFieldsOfType("Reference"),c=this.getFieldsOfType("ReferenceMany");for(a in c)b[a]=c[a];return b},d.prototype.getReferencedLists=function(){return this.getFieldsOfType("ReferencedList")},d.prototype.getExtraParams=function(){var a={};return this.config.extraParams&&(a="function"==typeof this.config.extraParams?this.config.extraParams():this.config.extraParams),a},d.prototype.getQueryParams=function(a,b){return"function"==typeof this.config.transformParams?this.config.transformParams(a,b):this.config.transformParams},d.prototype.getHeaders=function(){var a=this.headers();return"function"==typeof a?a(this):a},d.prototype.identifier=function(){var a,b,c;for(a in this.fields)if(c=this.fields[a],c.identifier()){b=c;break}return b||(b=this.entity.identifierField),0===arguments.length?b:this},d.prototype.mapEntries=function(a){var b,c,d=[];for(b=0,c=a.length;c>b;b++)d.push(this.mapEntry(a[b]));return d},d.prototype.mapEntry=function(a){if(!a)return new f;var b,c,d=this.getFields(),e=new f,g=this.getEntity(),h=this.identifier();e.entityName=g.name(),e.values=a;for(b in d)c=d[b],c.name()in a&&(e.values[b]=c.getMappedValue(a[c.name()],a));return h&&(e.identifierValue=a[h.name()]),e},d.prototype.removeFields=function(){return this.fields={},this},d.prototype.processFieldsDefaultValue=function(a){var b,c,d=this.getFields();for(c in d)b=d[c],a.values[b.name()]=b.defaultValue();return this},g(d.prototype,h),d}),c("ng-admin/Main/component/service/config/view/ListView",["require","angular","ng-admin/Main/component/service/config/view/View","ng-admin/Main/component/service/config/Field","ng-admin/Main/component/service/config/Configurable","ng-admin/lib/utils"],function(a){function b(a,b){return{params:{_sort:a,_sortDir:b},headers:{}}}function c(a,b){return{page:a,per_page:b}}function d(a){return a}function e(a){return a}function f(a){return!a.headers&&a.data.length?a.data.length:a.headers("X-Total-Count")||a.data.length}function g(){i.apply(this,arguments),this.config=h.extend(this.config,h.copy(l)),this.type="ListView",this.quickFilters={}}var h=a("angular"),i=a("ng-admin/Main/component/service/config/view/View"),j=(a("ng-admin/Main/component/service/config/Field"),a("ng-admin/Main/component/service/config/Configurable")),k=a("ng-admin/lib/utils"),l={perPage:30,pagination:c,filterQuery:d,filterParams:e,infinitePagination:!1,totalItems:f,sortParams:b,listActions:null};return k.inherits(g,i),j(g.prototype,l),g.prototype.addQuickFilter=function(a,b){return this.quickFilters[a]=b,this},g.prototype.getQuickFilterNames=function(){return Object.keys(this.quickFilters)},g.prototype.getQuickFilterParams=function(a){var b=this.quickFilters[a];return"function"==typeof b&&(b=b()),b},g.prototype.getSortParams=function(a,b){return"function"==typeof this.config.sortParams?this.config.sortParams(a,b):this.config.sortParams},g.prototype.getAllParams=function(a,b,c){var d=this.getExtraParams(),e=this.config.pagination,f=this.perPage();if(e&&(d=h.extend(d,e(a,f))),b&&"params"in b&&(d=h.extend(d,b.params)),c){var g=this.filterQuery();d=h.extend(d,g(c))}return d},g.prototype.getAllHeaders=function(a){var b=this.getHeaders();return a&&a.headers&&(b=h.extend(b,a.headers)),b},g.prototype.getMappedValue=function(a){if(!a.length)return[];var b,c,d,e,f=this.getFields();for(c=0,d=a.length;d>c;c++)for(e in f)b=f[e],a[c].values[e]=b.getMappedValue(a[c].values[e],a[c]);return a},g.prototype.pagination=function(a){return console.warn("pagination() is deprecated. Query parameters should be customized via transformParams() instead"),0===arguments.length?this.config.pagination:(this.config.pagination=a,this)},g.prototype.sortParams=function(a){return console.warn("sortParams() is deprecated. Query parameters should be customized via transformParams() instead"),0===arguments.length?this.config.sortParams:(this.config.sortParams=a,this)},g}),c("ng-admin/Main/component/service/config/view/DashboardView",["require","angular","ng-admin/Main/component/service/config/view/ListView","ng-admin/Main/component/service/config/Configurable","ng-admin/lib/utils"],function(a){function b(){c.apply(this,arguments),this.type="DashboardView"}var c=(a("angular"),a("ng-admin/Main/component/service/config/view/ListView")),d=a("ng-admin/Main/component/service/config/Configurable"),e=a("ng-admin/lib/utils"),f={order:null};return e.inherits(b,c),d(b.prototype,f),b.prototype.limit=function(a){return this.perPage(a)},b}),c("ng-admin/Main/component/service/config/view/MenuView",["require","angular","ng-admin/Main/component/service/config/Configurable"],function(a){function b(){this.enabled=!0,this.config=c.copy(e),this.type="MenuView"}var c=a("angular"),d=a("ng-admin/Main/component/service/config/Configurable"),e={title:null,order:null,icon:''};return b.prototype.isEnabled=function(){return this.enabled},b.prototype.disable=function(){return this.enabled=!1,this},d(b.prototype,e),b}),c("ng-admin/Main/component/service/config/view/FilterView",["require","ng-admin/Main/component/service/config/view/View","ng-admin/lib/utils"],function(a){function b(){c.apply(this,arguments),this.type="FilterView"}var c=a("ng-admin/Main/component/service/config/view/View"),d=a("ng-admin/lib/utils");return d.inherits(b,c),b}),c("ng-admin/Main/component/service/config/view/ShowView",["require","angular","ng-admin/Main/component/service/config/view/View","ng-admin/lib/utils"],function(a){function b(){c.apply(this,arguments),this.type="ShowView"}var c=(a("angular"),a("ng-admin/Main/component/service/config/view/View")),d=a("ng-admin/lib/utils");return d.inherits(b,c),b}),c("ng-admin/Main/component/service/config/view/CreateView",["require","angular","ng-admin/Main/component/service/config/view/View","ng-admin/lib/utils"],function(a){function b(){c.apply(this,arguments),this.type="CreateView"}var c=(a("angular"),a("ng-admin/Main/component/service/config/view/View")),d=a("ng-admin/lib/utils");return d.inherits(b,c),b.prototype.getFormName=function(){return"createForm"},b.prototype.showAttributeSuccess=function(){return!0},b}),c("ng-admin/Main/component/service/config/view/EditView",["require","angular","ng-admin/Main/component/service/config/view/View","ng-admin/lib/utils"],function(a){function b(){c.apply(this,arguments),this.type="EditView"}var c=(a("angular"),a("ng-admin/Main/component/service/config/view/View")),d=a("ng-admin/lib/utils");return d.inherits(b,c),b.prototype.getFormName=function(){return"editForm"},b.prototype.showAttributeSuccess=function(){return!1},b}),c("ng-admin/Main/component/service/config/view/DeleteView",["require","angular","ng-admin/Main/component/service/config/view/View","ng-admin/lib/utils"],function(a){function b(){this.quickFilters={},c.apply(this,arguments),this.type="DeleteView"}var c=(a("angular"),a("ng-admin/Main/component/service/config/view/View")),d=a("ng-admin/lib/utils");return d.inherits(b,c),b}),c("ng-admin/Main/component/service/config/Entity",["require","angular","ng-admin/lib/utils","ng-admin/Main/component/service/config/Configurable","ng-admin/Main/component/service/config/Field","ng-admin/Main/component/service/config/view/DashboardView","ng-admin/Main/component/service/config/view/MenuView","ng-admin/Main/component/service/config/view/FilterView","ng-admin/Main/component/service/config/view/ListView","ng-admin/Main/component/service/config/view/ShowView","ng-admin/Main/component/service/config/view/CreateView","ng-admin/Main/component/service/config/view/EditView","ng-admin/Main/component/service/config/view/DeleteView"],function(a){function b(a){return a}function c(a){this.values={},this.config=e.copy(q),this.config.name=a||"entity",this.config.label=f.camelCase(this.config.name),this.identifierField=new h("id"),this.isReadOnly=!1,this.initViews()}function d(a){switch(a){case"DashboardView":return"dashboardView";case"ListView":return"listView";case"FilterView":return"filterView";case"ShowView":return"showView";case"CreateView":return"creationView";case"EditView":return"editionView";case"DeleteView":return"deletionView";default:throw new Error("Unknown view type "+a)}}var e=a("angular"),f=a("ng-admin/lib/utils"),g=a("ng-admin/Main/component/service/config/Configurable"),h=a("ng-admin/Main/component/service/config/Field"),i=a("ng-admin/Main/component/service/config/view/DashboardView"),j=a("ng-admin/Main/component/service/config/view/MenuView"),k=a("ng-admin/Main/component/service/config/view/FilterView"),l=a("ng-admin/Main/component/service/config/view/ListView"),m=a("ng-admin/Main/component/service/config/view/ShowView"),n=a("ng-admin/Main/component/service/config/view/CreateView"),o=a("ng-admin/Main/component/service/config/view/EditView"),p=a("ng-admin/Main/component/service/config/view/DeleteView"),q={name:"entity",label:"My entity",order:null,baseApiUrl:null,url:null,transformParams:b,dashboardView:null,filterView:null,menuView:null,listView:null,showView:null,creationView:null,editionView:null,deletionView:null}; +return g(c.prototype,q),c.prototype.getValue=function(a){return void 0!==this.values[a]?this.values[a]:null},c.prototype.setValue=function(a,b){return this.values[a]=b,this},c.prototype.getUrl=function(a,b){return"function"==typeof this.config.url?this.config.url(a,b):this.config.url},c.prototype.initViews=function(){this.config.dashboardView=(new i).setEntity(this),this.config.menuView=new j,this.config.filterView=new k,this.config.listView=(new l).setEntity(this),this.config.showView=(new m).setEntity(this),this.config.creationView=(new n).setEntity(this),this.config.editionView=(new o).setEntity(this),this.config.deletionView=(new p).setEntity(this)},c.prototype.getViewByType=function(a){return this[d(a)]()},c.prototype.addView=function(a){var b=a.type,c=d(b);return a.setEntity(this),this[c](a),console.warn("addView() is deprecated. Views are added by default, use "+c+"() instead to retrieve the view and customize it"),this},c.prototype.identifier=function(a){return 0===arguments.length?this.identifierField:(this.identifierField=a,this)},c.prototype.getMappedValue=function(a){return this.values[a]},c.prototype.getQueryParams=function(a,b){return"function"==typeof this.config.transformParams?this.config.transformParams(a,b):this.config.transformParams},c.prototype.readOnly=function(){return this.isReadOnly=!0,this.config.creationView.disable(),this.config.editionView.disable(),this.config.deletionView.disable(),this},c.prototype.addMappedField=function(){return console.warn("Entity.addMappedField() is deprecated and not useful anymore"),this},c}),c("ng-admin/Main/component/service/config/Reference",["require","angular","ng-admin/Main/component/service/config/Configurable","ng-admin/Main/component/service/config/view/ListView","ng-admin/Main/component/service/config/Field","ng-admin/lib/utils"],function(a){function b(a){f.apply(this,arguments),this.config.isDetailLink=!0,this.referencedValue=null,this.entries={},this.config.name=a||"reference",this.config.type="Reference",this.referencedView=new e,this.referencedViewConfigured=!1}var c=a("angular"),d=a("ng-admin/Main/component/service/config/Configurable"),e=a("ng-admin/Main/component/service/config/view/ListView"),f=a("ng-admin/Main/component/service/config/Field"),g=a("ng-admin/lib/utils"),h={name:"myReference",type:"Reference",label:"My reference",singleApiCall:null,targetEntity:null,targetField:null,isDetailLink:null,validation:{required:!1}};return g.inherits(b,f),d(b.prototype,h),b.prototype.getChoicesById=function(){var a,b,c,d={},e=this.targetEntity(),f=this.targetField().name(),g=e.identifier().name();for(b=0,c=this.entries.length;c>b;b++)a=this.entries[b],d[a.values[g]]=a.values[f];return d},b.prototype.choices=function(){var a,b,c,d=[],e=this.targetEntity(),f=this.targetField().name(),g=e.identifier().name();for(b=0,c=this.entries.length;c>b;b++)a=this.entries[b],d.push({value:a.values[g],label:a.values[f]});return d},b.prototype.targetEntity=function(a){return 0===arguments.length?this.config.targetEntity:(this.config.targetEntity=a,this.referencedView.setEntity(a),this)},b.prototype.targetField=function(a){return 0===arguments.length?this.config.targetField:(this.config.targetField=a,this.referencedView.removeFields().addField(a),this)},b.prototype.getReferencedView=function(){if(!this.referencedViewConfigured){var a=this.targetEntity().getViewByType("ListView");a&&(this.referencedView.config=c.copy(a.config),this.referencedView.config.pagination=!1),this.referencedViewConfigured=!0}return this.referencedView},b.prototype.getSingleApiCall=function(a){return"function"==typeof this.config.singleApiCall?this.config.singleApiCall(a):this.config.singleApiCall},b.prototype.getSortFieldName=function(){return this.getReferencedView().name()+"."+this.targetField().name()},b.prototype.getIdentifierValues=function(a){var b,c,d,e,f={},g=this.name();for(c=0,e=a.length;e>c;c++)if(b=a[c][g],b instanceof Array)for(d in b)f[b[d]]=!0;else f[b]=!0;return Object.keys(f)},b.prototype.getEntries=function(){return this.entries},b.prototype.setEntries=function(a){return this.entries=a,this},b.prototype.getListValue=function(){return this.referencedValue},b}),c("ng-admin/Main/component/service/config/ReferencedList",["require","ng-admin/Main/component/service/config/Configurable","ng-admin/Main/component/service/config/Reference","ng-admin/lib/utils"],function(a){function b(a){d.apply(this,arguments),this.config.name=a||"reference",this.config.type="ReferencedList",this.entries=[]}var c=a("ng-admin/Main/component/service/config/Configurable"),d=a("ng-admin/Main/component/service/config/Reference"),e=a("ng-admin/lib/utils"),f={name:"myReference",type:"ReferencedList",label:"My list",edition:"editable",list:!1,order:null,targetReferenceField:null,targetFields:[],isDetailLink:!1,validation:{required:!1}};return e.inherits(b,d),c(b.prototype,f),b.prototype.targetFields=function(a){if(0===arguments.length)return this.config.targetFields;var b;this.referencedView.removeFields();for(b in a)this.referencedView.addField(a[b]);return this.config.targetFields=a,this},b.prototype.getGridColumns=function(){var a,b,c,d=[];for(b=0,c=this.config.targetFields.length;c>b;b++)a=this.config.targetFields[b],a.displayed()&&d.push({field:a,label:a.label()});return d},b.prototype.getEntries=function(){return this.entries},b.prototype.setEntries=function(a){return this.entries=a,this},b.prototype.clear=function(){return this},b}),c("ng-admin/Main/component/service/config/ReferenceMany",["require","ng-admin/Main/component/service/config/Configurable","ng-admin/Main/component/service/config/Reference","ng-admin/lib/utils"],function(a){function b(a){d.apply(this,arguments),this.config.name=a||"reference-many",this.config.type="ReferenceMany"}var c=a("ng-admin/Main/component/service/config/Configurable"),d=a("ng-admin/Main/component/service/config/Reference"),e=a("ng-admin/lib/utils"),f={name:"myReference",label:"My references"};return e.inherits(b,d),c(b.prototype,f),b}),c("ng-admin/Main/component/provider/NgAdminConfiguration",[],function(){function a(){this.config=null}return a.prototype.configure=function(a){this.config=a},a.prototype.$get=function(){var a=this.config;return function(){return a}},a.$inject=[],a}),c("ng-admin/Main/component/filter/OrderElement",[],function(){function a(){return function(a){var b,c=[];for(b in a)c.push(a[b]);return c.sort(function(a,b){return a.order()-b.order()}),c}}return a.$inject=[],a}),c("text",["module"],function(a){var c,d,e,f,g,h=["Msxml2.XMLHTTP","Microsoft.XMLHTTP","Msxml2.XMLHTTP.4.0"],i=/^\s*<\?xml(\s)+version=[\'\"](\d)*.(\d)*[\'\"](\s)*\?>/im,j=/]*>\s*([\s\S]+)\s*<\/body>/im,k="undefined"!=typeof location&&location.href,l=k&&location.protocol&&location.protocol.replace(/\:/,""),m=k&&location.hostname,n=k&&(location.port||void 0),o={},p=a.config&&a.config()||{};return c={version:"2.0.12",strip:function(a){if(a){a=a.replace(i,"");var b=a.match(j);b&&(a=b[1])}else a="";return a},jsEscape:function(a){return a.replace(/(['\\])/g,"\\$1").replace(/[\f]/g,"\\f").replace(/[\b]/g,"\\b").replace(/[\n]/g,"\\n").replace(/[\t]/g,"\\t").replace(/[\r]/g,"\\r").replace(/[\u2028]/g,"\\u2028").replace(/[\u2029]/g,"\\u2029")},createXhr:p.createXhr||function(){var a,b,c;if("undefined"!=typeof XMLHttpRequest)return new XMLHttpRequest;if("undefined"!=typeof ActiveXObject)for(b=0;3>b;b+=1){c=h[b];try{a=new ActiveXObject(c)}catch(d){}if(a){h=[c];break}}return a},parseName:function(a){var b,c,d,e=!1,f=a.indexOf("."),g=0===a.indexOf("./")||0===a.indexOf("../");return-1!==f&&(!g||f>1)?(b=a.substring(0,f),c=a.substring(f+1,a.length)):b=a,d=c||b,f=d.indexOf("!"),-1!==f&&(e="strip"===d.substring(f+1),d=d.substring(0,f),c?c=d:b=d),{moduleName:b,ext:c,strip:e}},xdRegExp:/^((\w+)\:)?\/\/([^\/\\]+)/,useXhr:function(a,b,d,e){var f,g,h,i=c.xdRegExp.exec(a);return i?(f=i[2],g=i[3],g=g.split(":"),h=g[1],g=g[0],!(f&&f!==b||g&&g.toLowerCase()!==d.toLowerCase()||(h||g)&&h!==e)):!0},finishLoad:function(a,b,d,e){d=b?c.strip(d):d,p.isBuild&&(o[a]=d),e(d)},load:function(a,b,d,e){if(e&&e.isBuild&&!e.inlineText)return void d();p.isBuild=e&&e.isBuild;var f=c.parseName(a),g=f.moduleName+(f.ext?"."+f.ext:""),h=b.toUrl(g),i=p.useXhr||c.useXhr;return 0===h.indexOf("empty:")?void d():void(!k||i(h,l,m,n)?c.get(h,function(b){c.finishLoad(a,f.strip,b,d)},function(a){d.error&&d.error(a)}):b([g],function(a){c.finishLoad(f.moduleName+"."+f.ext,f.strip,a,d)}))},write:function(a,b,d){if(o.hasOwnProperty(b)){var e=c.jsEscape(o[b]);d.asModule(a+"!"+b,"define(function () { return '"+e+"';});\n")}},writeFile:function(a,b,d,e,f){var g=c.parseName(b),h=g.ext?"."+g.ext:"",i=g.moduleName+h,j=d.toUrl(g.moduleName+h)+".js";c.load(i,d,function(){var b=function(a){return e(j,a)};b.asModule=function(a,b){return e.asModule(a,j,b)},c.write(a,i,b,f)},f)}},"node"===p.env||!p.env&&"undefined"!=typeof process&&process.versions&&process.versions.node&&!process.versions["node-webkit"]?(d=b.nodeRequire("fs"),c.get=function(a,b,c){try{var e=d.readFileSync(a,"utf8");0===e.indexOf("")&&(e=e.substring(1)),b(e)}catch(f){c&&c(f)}}):"xhr"===p.env||!p.env&&c.createXhr()?c.get=function(a,b,d,e){var f,g=c.createXhr();if(g.open("GET",a,!0),e)for(f in e)e.hasOwnProperty(f)&&g.setRequestHeader(f.toLowerCase(),e[f]);p.onXhr&&p.onXhr(g,a),g.onreadystatechange=function(){var c,e;4===g.readyState&&(c=g.status||0,c>399&&600>c?(e=new Error(a+" HTTP status: "+c),e.xhr=g,d&&d(e)):b(g.responseText),p.onXhrComplete&&p.onXhrComplete(g,a))},g.send(null)}:"rhino"===p.env||!p.env&&"undefined"!=typeof Packages&&"undefined"!=typeof java?c.get=function(a,b){var c,d,e="utf-8",f=new java.io.File(a),g=java.lang.System.getProperty("line.separator"),h=new java.io.BufferedReader(new java.io.InputStreamReader(new java.io.FileInputStream(f),e)),i="";try{for(c=new java.lang.StringBuffer,d=h.readLine(),d&&d.length()&&65279===d.charAt(0)&&(d=d.substring(1)),null!==d&&c.append(d);null!==(d=h.readLine());)c.append(g),c.append(d);i=String(c.toString())}finally{h.close()}b(i)}:("xpconnect"===p.env||!p.env&&"undefined"!=typeof Components&&Components.classes&&Components.interfaces)&&(e=Components.classes,f=Components.interfaces,Components.utils["import"]("resource://gre/modules/FileUtils.jsm"),g="@mozilla.org/windows-registry-key;1"in e,c.get=function(a,b){var c,d,h,i={};g&&(a=a.replace(/\//g,"\\")),h=new FileUtils.File(a);try{c=e["@mozilla.org/network/file-input-stream;1"].createInstance(f.nsIFileInputStream),c.init(h,1,0,!1),d=e["@mozilla.org/intl/converter-input-stream;1"].createInstance(f.nsIConverterInputStream),d.init(c,"utf-8",c.available(),f.nsIConverterInputStream.DEFAULT_REPLACEMENT_CHARACTER),d.readString(c.available(),i),d.close(),c.close(),b(i.value)}catch(j){throw new Error((h&&h.path||"")+": "+j)}}),c}),c("text!ng-admin/Main/view/dashboard-panel.html",[],function(){return'
\n {{ label }}\n
\n\n\n\n'}),c("ng-admin/Main/component/directive/maDashboardPanel",["require","text!../../view/dashboard-panel.html"],function(a){function b(){return{restrict:"E",scope:{label:"@",viewName:"@",entries:"=",fields:"&",entity:"&",perPage:"="},template:c}}var c=a("text!../../view/dashboard-panel.html");return b.$inject=[],b}),c("text!ng-admin/Main/view/menu.html",[],function(){return'\n'}),c("ng-admin/Main/component/directive/Menu",["require","text!../../view/menu.html"],function(a){function b(){return{restrict:"E",template:c}}var c=a("text!../../view/menu.html");return b.$inject=[],b}),c("ng-admin/Main/config/http",[],function(){function a(a){a.useApplyAsync(!0)}return a.$inject=["$httpProvider"],a}),c("text!ng-admin/Main/view/layout.html",[],function(){return'
\n \n\n
\n
\n
\n
\n
\n'}),c("text!ng-admin/Main/view/dashboard.html",[],function(){return'
\n
\n

Dashboard

\n
\n
\n\n
\n
\n \n \n
\n
\n'}),c("ng-admin/Main/config/routing",["require","text!../view/layout.html","text!../view/dashboard.html"],function(a){function b(a,b){a.state("main",{"abstract":!0,controller:"AppController",controllerAs:"appController",template:c}),a.state("dashboard",{parent:"main",url:"/dashboard?sortField&sortDir",params:{sortField:null,sortDir:null},controller:"DashboardController",controllerAs:"dashboardController",template:d}),b.otherwise("/dashboard")}var c=a("text!../view/layout.html"),d=a("text!../view/dashboard.html");return b.$inject=["$stateProvider","$urlRouterProvider"],b}),c("ng-admin/Main/run/Loader",[],function(){function a(a,b,c){a.$on("$stateChangeStart",function(){c.start(),b.scrollTo(0,0)}),a.$on("$stateChangeSuccess",c.done.bind(c))}return a.$inject=["$rootScope","$window","progression"],a}),c("MainModule",["require","angular","angular-ui-router","restangular","ng-admin/Main/component/controller/AppController","ng-admin/Main/component/controller/DashboardController","ng-admin/Main/component/controller/SidebarController","ng-admin/Main/component/service/PanelBuilder","ng-admin/Main/component/service/Validator","ng-admin/Main/component/service/config/Application","ng-admin/Main/component/service/config/Entity","ng-admin/Main/component/service/config/Field","ng-admin/Main/component/service/config/Reference","ng-admin/Main/component/service/config/ReferencedList","ng-admin/Main/component/service/config/ReferenceMany","ng-admin/Main/component/service/config/view/MenuView","ng-admin/Main/component/service/config/view/DashboardView","ng-admin/Main/component/service/config/view/ListView","ng-admin/Main/component/service/config/view/CreateView","ng-admin/Main/component/service/config/view/EditView","ng-admin/Main/component/service/config/view/DeleteView","ng-admin/Main/component/provider/NgAdminConfiguration","ng-admin/Main/component/filter/OrderElement","ng-admin/Main/component/directive/maDashboardPanel","ng-admin/Main/component/directive/Menu","ng-admin/Main/config/http","ng-admin/Main/config/routing","ng-admin/Main/run/Loader"],function(a){var b=a("angular");a("angular-ui-router"),a("restangular");var c=b.module("main",["ui.router","restangular"]);return c.controller("AppController",a("ng-admin/Main/component/controller/AppController")),c.controller("DashboardController",a("ng-admin/Main/component/controller/DashboardController")),c.controller("SidebarController",a("ng-admin/Main/component/controller/SidebarController")),c.service("PanelBuilder",a("ng-admin/Main/component/service/PanelBuilder")),c.service("Validator",a("ng-admin/Main/component/service/Validator")),c.constant("Application",a("ng-admin/Main/component/service/config/Application")),c.constant("Entity",a("ng-admin/Main/component/service/config/Entity")),c.constant("Field",a("ng-admin/Main/component/service/config/Field")),c.constant("Reference",a("ng-admin/Main/component/service/config/Reference")),c.constant("ReferencedList",a("ng-admin/Main/component/service/config/ReferencedList")),c.constant("ReferenceMany",a("ng-admin/Main/component/service/config/ReferenceMany")),c.constant("MenuView",a("ng-admin/Main/component/service/config/view/MenuView")),c.constant("DashboardView",a("ng-admin/Main/component/service/config/view/DashboardView")),c.constant("ListView",a("ng-admin/Main/component/service/config/view/ListView")),c.constant("CreateView",a("ng-admin/Main/component/service/config/view/CreateView")),c.constant("EditView",a("ng-admin/Main/component/service/config/view/EditView")),c.constant("DeleteView",a("ng-admin/Main/component/service/config/view/DeleteView")),c.provider("NgAdminConfiguration",a("ng-admin/Main/component/provider/NgAdminConfiguration")),c.filter("orderElement",a("ng-admin/Main/component/filter/OrderElement")),c.directive("maDashboardPanel",a("ng-admin/Main/component/directive/maDashboardPanel")),c.directive("menu",a("ng-admin/Main/component/directive/Menu")),c.config(a("ng-admin/Main/config/http")),c.config(a("ng-admin/Main/config/routing")),c.run(a("ng-admin/Main/run/Loader")),c}),function(a,b){"function"==typeof c&&c.amd?c("inflection",[],b):"object"==typeof exports?module.exports=b():a.inflection=b()}(this,function(){var a=["equipment","information","rice","money","species","series","fish","sheep","moose","deer","news"],b=[[new RegExp("(m)en$","gi")],[new RegExp("(pe)ople$","gi")],[new RegExp("(child)ren$","gi")],[new RegExp("([ti])a$","gi")],[new RegExp("((a)naly|(b)a|(d)iagno|(p)arenthe|(p)rogno|(s)ynop|(t)he)ses$","gi")],[new RegExp("(hive)s$","gi")],[new RegExp("(tive)s$","gi")],[new RegExp("(curve)s$","gi")],[new RegExp("([lr])ves$","gi")],[new RegExp("([^fo])ves$","gi")],[new RegExp("([^aeiouy]|qu)ies$","gi")],[new RegExp("(s)eries$","gi")],[new RegExp("(m)ovies$","gi")],[new RegExp("(x|ch|ss|sh)es$","gi")],[new RegExp("([m|l])ice$","gi")],[new RegExp("(bus)es$","gi")],[new RegExp("(o)es$","gi")],[new RegExp("(shoe)s$","gi")],[new RegExp("(cris|ax|test)es$","gi")],[new RegExp("(octop|vir)i$","gi")],[new RegExp("(alias|status)es$","gi")],[new RegExp("^(ox)en","gi")],[new RegExp("(vert|ind)ices$","gi")],[new RegExp("(matr)ices$","gi")],[new RegExp("^feet$","gi")],[new RegExp("^teeth$","gi")],[new RegExp("^geese$","gi")],[new RegExp("(quiz)zes$","gi")],[new RegExp("(m)an$","gi"),"$1en"],[new RegExp("(pe)rson$","gi"),"$1ople"],[new RegExp("(child)$","gi"),"$1ren"],[new RegExp("^(ox)$","gi"),"$1en"],[new RegExp("(ax|test)is$","gi"),"$1es"],[new RegExp("(octop|vir)us$","gi"),"$1i"],[new RegExp("(alias|status)$","gi"),"$1es"],[new RegExp("(bu)s$","gi"),"$1ses"],[new RegExp("(buffal|tomat|potat)o$","gi"),"$1oes"],[new RegExp("([ti])um$","gi"),"$1a"],[new RegExp("sis$","gi"),"ses"],[new RegExp("(?:([^f])fe|([lr])f)$","gi"),"$1$2ves"],[new RegExp("(hive)$","gi"),"$1s"],[new RegExp("([^aeiouy]|qu)y$","gi"),"$1ies"],[new RegExp("(x|ch|ss|sh)$","gi"),"$1es"],[new RegExp("(matr|vert|ind)ix|ex$","gi"),"$1ices"],[new RegExp("([m|l])ouse$","gi"),"$1ice"],[new RegExp("^foot$","gi"),"feet"],[new RegExp("^tooth$","gi"),"teeth"],[new RegExp("^goose$","gi"),"geese"],[new RegExp("(quiz)$","gi"),"$1zes"],[new RegExp("s$","gi"),"s"],[new RegExp("$","gi"),"s"]],c=[[new RegExp("(m)an$","gi")],[new RegExp("(pe)rson$","gi")],[new RegExp("(child)$","gi")],[new RegExp("^(ox)$","gi")],[new RegExp("(ax|test)is$","gi")],[new RegExp("(octop|vir)us$","gi")],[new RegExp("(alias|status)$","gi")],[new RegExp("(bu)s$","gi")],[new RegExp("(buffal|tomat|potat)o$","gi")],[new RegExp("([ti])um$","gi")],[new RegExp("sis$","gi")],[new RegExp("(?:([^f])fe|([lr])f)$","gi")],[new RegExp("(hive)$","gi")],[new RegExp("([^aeiouy]|qu)y$","gi")],[new RegExp("(x|ch|ss|sh)$","gi")],[new RegExp("(matr|vert|ind)ix|ex$","gi")],[new RegExp("([m|l])ouse$","gi")],[new RegExp("^foot$","gi")],[new RegExp("^tooth$","gi")],[new RegExp("^goose$","gi")],[new RegExp("(quiz)$","gi")],[new RegExp("(m)en$","gi"),"$1an"],[new RegExp("(pe)ople$","gi"),"$1rson"],[new RegExp("(child)ren$","gi"),"$1"],[new RegExp("([ti])a$","gi"),"$1um"],[new RegExp("((a)naly|(b)a|(d)iagno|(p)arenthe|(p)rogno|(s)ynop|(t)he)ses$","gi"),"$1$2sis"],[new RegExp("(hive)s$","gi"),"$1"],[new RegExp("(tive)s$","gi"),"$1"],[new RegExp("(curve)s$","gi"),"$1"],[new RegExp("([lr])ves$","gi"),"$1f"],[new RegExp("([^fo])ves$","gi"),"$1fe"],[new RegExp("(m)ovies$","gi"),"$1ovie"],[new RegExp("([^aeiouy]|qu)ies$","gi"),"$1y"],[new RegExp("(s)eries$","gi"),"$1eries"],[new RegExp("(x|ch|ss|sh)es$","gi"),"$1"],[new RegExp("([m|l])ice$","gi"),"$1ouse"],[new RegExp("(bus)es$","gi"),"$1"],[new RegExp("(o)es$","gi"),"$1"],[new RegExp("(shoe)s$","gi"),"$1"],[new RegExp("(cris|ax|test)es$","gi"),"$1is"],[new RegExp("(octop|vir)i$","gi"),"$1us"],[new RegExp("(alias|status)es$","gi"),"$1"],[new RegExp("^(ox)en","gi"),"$1"],[new RegExp("(vert|ind)ices$","gi"),"$1ex"],[new RegExp("(matr)ices$","gi"),"$1ix"],[new RegExp("^feet$","gi"),"foot"],[new RegExp("^teeth$","gi"),"tooth"],[new RegExp("^geese$","gi"),"goose"],[new RegExp("(quiz)zes$","gi"),"$1"],[new RegExp("ss$","gi"),"ss"],[new RegExp("s$","gi"),""]],d=["and","or","nor","a","an","the","so","but","to","of","at","by","from","into","on","onto","off","out","in","over","with","for"],e=new RegExp("(_ids|_id)$","g"),f=new RegExp("_","g"),g=new RegExp("[ _]","g"),h=new RegExp("([A-Z])","g"),i=new RegExp("^_"),j={_apply_rules:function(a,b,c,d){if(d)a=d;else{var e=j.indexOf(c,a.toLowerCase())>-1;if(!e)for(var f=0,g=b.length;g>f;f++)if(a.match(b[f][0])){void 0!==b[f][1]&&(a=a.replace(b[f][0],b[f][1]));break}}return a},indexOf:function(a,b,c,d){c||(c=-1);for(var e=-1,f=c,g=a.length;g>f;f++)if(a[f]===b||d&&d(a[f],b)){e=f;break}return e},pluralize:function(c,d){return j._apply_rules(c,b,a,d)},singularize:function(b,d){return j._apply_rules(b,c,a,d)},inflect:function(d,e,f,g){return e=parseInt(e,10),isNaN(e)?d:0===e||e>1?j._apply_rules(d,b,a,g):j._apply_rules(d,c,a,f)},camelize:function(a,b){for(var c,d,e,f,g=a.split("/"),h=0,i=g.length;i>h;h++){for(c=g[h].split("_"),d=0,e=c.length;e>d;d++)0!==d&&(c[d]=c[d].toLowerCase()),f=c[d].charAt(0),f=b&&0===h&&0===d?f.toLowerCase():f.toUpperCase(),c[d]=f+c[d].substring(1);g[h]=c.join("")}return g.join("::")},underscore:function(a,b){if(b&&a===a.toUpperCase())return a;for(var c=a.split("::"),d=0,e=c.length;e>d;d++)c[d]=c[d].replace(h,"_$1"),c[d]=c[d].replace(i,"");return c.join("/").toLowerCase()},humanize:function(a,b){return a=a.toLowerCase(),a=a.replace(e,""),a=a.replace(f," "),b||(a=j.capitalize(a)),a},capitalize:function(a){return a=a.toLowerCase(),a.substring(0,1).toUpperCase()+a.substring(1)},dasherize:function(a){return a.replace(g,"-")},titleize:function(a){a=a.toLowerCase().replace(f," ");for(var b,c,e,g=a.split(" "),h=0,i=g.length;i>h;h++){for(b=g[h].split("-"),c=0,e=b.length;e>c;c++)j.indexOf(d,b[c].toLowerCase())<0&&(b[c]=j.capitalize(b[c]));g[h]=b.join("-")}return a=g.join(" "),a=a.substring(0,1).toUpperCase()+a.substring(1)},demodulize:function(a){var b=a.split("::");return b[b.length-1]},tableize:function(a){return a=j.underscore(a),a=j.pluralize(a)},classify:function(a){return a=j.camelize(a),a=j.singularize(a)},foreign_key:function(a,b){return a=j.demodulize(a),a=j.underscore(a)+(b?"":"_")+"id"},ordinalize:function(a){for(var b=a.split(" "),c=0,d=b.length;d>c;c++){var e=parseInt(b[c],10);if(!isNaN(e)){var f=b[c].substring(b[c].length-2),g=b[c].substring(b[c].length-1),h="th";"11"!=f&&"12"!=f&&"13"!=f&&("1"===g?h="st":"2"===g?h="nd":"3"===g&&(h="rd")),b[c]+=h}}return b.join(" ")},transform:function(a,b){for(var c=0,d=b.length;d>c;c++){var e=b[c];this.hasOwnProperty(e)&&(a=this[e](a))}return a}};return j.version="1.4.2",j}),function(a,b){function c(){this.$get=["$$sanitizeUri",function(a){return function(b){var c=[];return f(b,i(c,function(b,c){return!/^unsafe/.test(a(b,c))})),c.join("")}}]}function d(a){var c=[],d=i(c,b.noop);return d.chars(a),c.join("")}function e(a){var b,c={},d=a.split(",");for(b=0;b=0&&t[f]!=d;f--);if(f>=0){for(e=t.length-1;e>=f;e--)c.end&&c.end(t[e]);t.length=f}}"string"!=typeof a&&(a=null===a||"undefined"==typeof a?"":""+a);var f,h,i,s,t=[],v=a;for(t.last=function(){return t[t.length-1]};a;){if(s="",h=!0,t.last()&&B[t.last()]?(a=a.replace(new RegExp("(.*)<\\s*\\/\\s*"+t.last()+"[^>]*>","i"),function(a,b){return b=b.replace(p,"$1").replace(r,"$1"),c.chars&&c.chars(g(b)),""}),e("",t.last())):(0===a.indexOf("",f)===f&&(c.comment&&c.comment(a.substring(4,f)),a=a.substring(f+3),h=!1)):q.test(a)?(i=a.match(q),i&&(a=a.replace(i[0],""),h=!1)):o.test(a)?(i=a.match(l),i&&(a=a.substring(i[0].length),i[0].replace(l,e),h=!1)):n.test(a)&&(i=a.match(k),i?(i[4]&&(a=a.substring(i[0].length),i[0].replace(k,d)),h=!1):(s+="<",a=a.substring(1))),h&&(f=a.indexOf("<"),s+=0>f?a:a.substring(0,f),a=0>f?"":a.substring(f),c.chars&&c.chars(g(s)))),a==v)throw j("badparse","The sanitizer was unable to parse the following block of html: {0}",a);v=a}e()}function g(a){if(!a)return"";var b=I.exec(a),c=b[1],d=b[3],e=b[2];return e&&(H.innerHTML=e.replace(//g,">")}function i(a,c){var d=!1,e=b.bind(a,a.push);return{start:function(a,f,g){a=b.lowercase(a),!d&&B[a]&&(d=a),d||C[a]!==!0||(e("<"),e(a),b.forEach(f,function(d,f){var g=b.lowercase(f),i="img"===a&&"src"===g||"background"===g;G[g]!==!0||D[g]===!0&&!c(d,i)||(e(" "),e(f),e('="'),e(h(d)),e('"'))}),e(g?"/>":">"))},end:function(a){a=b.lowercase(a),d||C[a]!==!0||(e("")),a==d&&(d=!1)},chars:function(a){d||e(h(a))}}}var j=b.$$minErr("$sanitize"),k=/^<((?:[a-zA-Z])[\w:-]*)((?:\s+[\w:-]+(?:\s*=\s*(?:(?:"[^"]*")|(?:'[^']*')|[^>\s]+))?)*)\s*(\/?)\s*(>?)/,l=/^<\/\s*([\w:-]+)[^>]*>/,m=/([\w:-]+)(?:\s*=\s*(?:(?:"((?:[^"])*)")|(?:'((?:[^'])*)')|([^>\s]+)))?/g,n=/^/g,q=/]*?)>/i,r=//g,s=/[\uD800-\uDBFF][\uDC00-\uDFFF]/g,t=/([^\#-~| |!])/g,u=e("area,br,col,hr,img,wbr"),v=e("colgroup,dd,dt,li,p,tbody,td,tfoot,th,thead,tr"),w=e("rp,rt"),x=b.extend({},w,v),y=b.extend({},v,e("address,article,aside,blockquote,caption,center,del,dir,div,dl,figure,figcaption,footer,h1,h2,h3,h4,h5,h6,header,hgroup,hr,ins,map,menu,nav,ol,pre,script,section,table,ul")),z=b.extend({},w,e("a,abbr,acronym,b,bdi,bdo,big,br,cite,code,del,dfn,em,font,i,img,ins,kbd,label,map,mark,q,ruby,rp,rt,s,samp,small,span,strike,strong,sub,sup,time,tt,u,var")),A=e("animate,animateColor,animateMotion,animateTransform,circle,defs,desc,ellipse,font-face,font-face-name,font-face-src,g,glyph,hkern,image,linearGradient,line,marker,metadata,missing-glyph,mpath,path,polygon,polyline,radialGradient,rect,set,stop,svg,switch,text,title,tspan,use"),B=e("script,style"),C=b.extend({},u,y,z,x,A),D=e("background,cite,href,longdesc,src,usemap,xlink:href"),E=e("abbr,align,alt,axis,bgcolor,border,cellpadding,cellspacing,class,clear,color,cols,colspan,compact,coords,dir,face,headers,height,hreflang,hspace,ismap,lang,language,nohref,nowrap,rel,rev,rows,rowspan,rules,scope,scrolling,shape,size,span,start,summary,target,title,type,valign,value,vspace,width"),F=e("accent-height,accumulate,additive,alphabetic,arabic-form,ascent,attributeName,attributeType,baseProfile,bbox,begin,by,calcMode,cap-height,class,color,color-rendering,content,cx,cy,d,dx,dy,descent,display,dur,end,fill,fill-rule,font-family,font-size,font-stretch,font-style,font-variant,font-weight,from,fx,fy,g1,g2,glyph-name,gradientUnits,hanging,height,horiz-adv-x,horiz-origin-x,ideographic,k,keyPoints,keySplines,keyTimes,lang,marker-end,marker-mid,marker-start,markerHeight,markerUnits,markerWidth,mathematical,max,min,offset,opacity,orient,origin,overline-position,overline-thickness,panose-1,path,pathLength,points,preserveAspectRatio,r,refX,refY,repeatCount,repeatDur,requiredExtensions,requiredFeatures,restart,rotate,rx,ry,slope,stemh,stemv,stop-color,stop-opacity,strikethrough-position,strikethrough-thickness,stroke,stroke-dasharray,stroke-dashoffset,stroke-linecap,stroke-linejoin,stroke-miterlimit,stroke-opacity,stroke-width,systemLanguage,target,text-anchor,to,transform,type,u1,u2,underline-position,underline-thickness,unicode,unicode-range,units-per-em,values,version,viewBox,visibility,width,widths,x,x-height,x1,x2,xlink:actuate,xlink:arcrole,xlink:role,xlink:show,xlink:title,xlink:type,xml:base,xml:lang,xml:space,xmlns,xmlns:xlink,y,y1,y2,zoomAndPan"),G=b.extend({},D,F,E),H=document.createElement("pre"),I=/^(\s*)([\s\S]*?)(\s*)$/;b.module("ngSanitize",[]).provider("$sanitize",c),b.module("ngSanitize").filter("linky",["$sanitize",function(a){var c=/((ftp|https?):\/\/|(www\.)|(mailto:)?[A-Za-z0-9._%+-]+@)\S*[^\s.;,(){}<>"”’]/,e=/^mailto:/;return function(f,g){function h(a){a&&n.push(d(a))}function i(a,c){n.push("'),h(c),n.push("")}if(!f)return f;for(var j,k,l,m=f,n=[];j=m.match(c);)k=j[0],j[2]||j[4]||(k=(j[3]?"http://":"mailto:")+k),l=j.index,h(m.substr(0,l)),i(k,j[0].replace(e,"")),m=m.substring(l+j[0].length);return h(m),a(n.join(""))}}])}(window,window.angular),c("angular-sanitize",function(){}),angular.module("ui.bootstrap",["ui.bootstrap.transition","ui.bootstrap.collapse","ui.bootstrap.accordion","ui.bootstrap.alert","ui.bootstrap.bindHtml","ui.bootstrap.buttons","ui.bootstrap.carousel","ui.bootstrap.dateparser","ui.bootstrap.position","ui.bootstrap.datepicker","ui.bootstrap.dropdown","ui.bootstrap.modal","ui.bootstrap.pagination","ui.bootstrap.tooltip","ui.bootstrap.popover","ui.bootstrap.progressbar","ui.bootstrap.rating","ui.bootstrap.tabs","ui.bootstrap.timepicker","ui.bootstrap.typeahead"]),angular.module("ui.bootstrap.transition",[]).factory("$transition",["$q","$timeout","$rootScope",function(a,b,c){function d(a){for(var b in a)if(void 0!==f.style[b])return a[b]}var e=function(d,f,g){g=g||{};var h=a.defer(),i=e[g.animation?"animationEndEventName":"transitionEndEventName"],j=function(){c.$apply(function(){d.unbind(i,j),h.resolve(d)})};return i&&d.bind(i,j),b(function(){angular.isString(f)?d.addClass(f):angular.isFunction(f)?f(d):angular.isObject(f)&&d.css(f),i||h.resolve(d)}),h.promise.cancel=function(){i&&d.unbind(i,j),h.reject("Transition cancelled")},h.promise},f=document.createElement("trans"),g={WebkitTransition:"webkitTransitionEnd",MozTransition:"transitionend",OTransition:"oTransitionEnd",transition:"transitionend"},h={WebkitTransition:"webkitAnimationEnd",MozTransition:"animationend",OTransition:"oAnimationEnd",transition:"animationend"};return e.transitionEndEventName=d(g),e.animationEndEventName=d(h),e}]),angular.module("ui.bootstrap.collapse",["ui.bootstrap.transition"]).directive("collapse",["$transition",function(a){return{link:function(b,c,d){function e(b){function d(){j===e&&(j=void 0) +}var e=a(c,b);return j&&j.cancel(),j=e,e.then(d,d),e}function f(){k?(k=!1,g()):(c.removeClass("collapse").addClass("collapsing"),e({height:c[0].scrollHeight+"px"}).then(g))}function g(){c.removeClass("collapsing"),c.addClass("collapse in"),c.css({height:"auto"})}function h(){k?(k=!1,i(),c.css({height:0})):(c.css({height:c[0].scrollHeight+"px"}),c[0].offsetWidth,c.removeClass("collapse in").addClass("collapsing"),e({height:0}).then(i))}function i(){c.removeClass("collapsing"),c.addClass("collapse")}var j,k=!0;b.$watch(d.collapse,function(a){a?h():f()})}}}]),angular.module("ui.bootstrap.accordion",["ui.bootstrap.collapse"]).constant("accordionConfig",{closeOthers:!0}).controller("AccordionController",["$scope","$attrs","accordionConfig",function(a,b,c){this.groups=[],this.closeOthers=function(d){var e=angular.isDefined(b.closeOthers)?a.$eval(b.closeOthers):c.closeOthers;e&&angular.forEach(this.groups,function(a){a!==d&&(a.isOpen=!1)})},this.addGroup=function(a){var b=this;this.groups.push(a),a.$on("$destroy",function(){b.removeGroup(a)})},this.removeGroup=function(a){var b=this.groups.indexOf(a);-1!==b&&this.groups.splice(b,1)}}]).directive("accordion",function(){return{restrict:"EA",controller:"AccordionController",transclude:!0,replace:!1,templateUrl:"template/accordion/accordion.html"}}).directive("accordionGroup",function(){return{require:"^accordion",restrict:"EA",transclude:!0,replace:!0,templateUrl:"template/accordion/accordion-group.html",scope:{heading:"@",isOpen:"=?",isDisabled:"=?"},controller:function(){this.setHeading=function(a){this.heading=a}},link:function(a,b,c,d){d.addGroup(a),a.$watch("isOpen",function(b){b&&d.closeOthers(a)}),a.toggleOpen=function(){a.isDisabled||(a.isOpen=!a.isOpen)}}}}).directive("accordionHeading",function(){return{restrict:"EA",transclude:!0,template:"",replace:!0,require:"^accordionGroup",link:function(a,b,c,d,e){d.setHeading(e(a,function(){}))}}}).directive("accordionTransclude",function(){return{require:"^accordionGroup",link:function(a,b,c,d){a.$watch(function(){return d[c.accordionTransclude]},function(a){a&&(b.html(""),b.append(a))})}}}),angular.module("ui.bootstrap.alert",[]).controller("AlertController",["$scope","$attrs",function(a,b){a.closeable="close"in b,this.close=a.close}]).directive("alert",function(){return{restrict:"EA",controller:"AlertController",templateUrl:"template/alert/alert.html",transclude:!0,replace:!0,scope:{type:"@",close:"&"}}}).directive("dismissOnTimeout",["$timeout",function(a){return{require:"alert",link:function(b,c,d,e){a(function(){e.close()},parseInt(d.dismissOnTimeout,10))}}}]),angular.module("ui.bootstrap.bindHtml",[]).directive("bindHtmlUnsafe",function(){return function(a,b,c){b.addClass("ng-binding").data("$binding",c.bindHtmlUnsafe),a.$watch(c.bindHtmlUnsafe,function(a){b.html(a||"")})}}),angular.module("ui.bootstrap.buttons",[]).constant("buttonConfig",{activeClass:"active",toggleEvent:"click"}).controller("ButtonsController",["buttonConfig",function(a){this.activeClass=a.activeClass||"active",this.toggleEvent=a.toggleEvent||"click"}]).directive("btnRadio",function(){return{require:["btnRadio","ngModel"],controller:"ButtonsController",link:function(a,b,c,d){var e=d[0],f=d[1];f.$render=function(){b.toggleClass(e.activeClass,angular.equals(f.$modelValue,a.$eval(c.btnRadio)))},b.bind(e.toggleEvent,function(){var d=b.hasClass(e.activeClass);(!d||angular.isDefined(c.uncheckable))&&a.$apply(function(){f.$setViewValue(d?null:a.$eval(c.btnRadio)),f.$render()})})}}}).directive("btnCheckbox",function(){return{require:["btnCheckbox","ngModel"],controller:"ButtonsController",link:function(a,b,c,d){function e(){return g(c.btnCheckboxTrue,!0)}function f(){return g(c.btnCheckboxFalse,!1)}function g(b,c){var d=a.$eval(b);return angular.isDefined(d)?d:c}var h=d[0],i=d[1];i.$render=function(){b.toggleClass(h.activeClass,angular.equals(i.$modelValue,e()))},b.bind(h.toggleEvent,function(){a.$apply(function(){i.$setViewValue(b.hasClass(h.activeClass)?f():e()),i.$render()})})}}}),angular.module("ui.bootstrap.carousel",["ui.bootstrap.transition"]).controller("CarouselController",["$scope","$timeout","$interval","$transition",function(a,b,c,d){function e(){f();var b=+a.interval;!isNaN(b)&&b>0&&(h=c(g,b))}function f(){h&&(c.cancel(h),h=null)}function g(){var b=+a.interval;i&&!isNaN(b)&&b>0?a.next():a.pause()}var h,i,j=this,k=j.slides=a.slides=[],l=-1;j.currentSlide=null;var m=!1;j.select=a.select=function(c,f){function g(){m||(j.currentSlide&&angular.isString(f)&&!a.noTransition&&c.$element?(c.$element.addClass(f),c.$element[0].offsetWidth,angular.forEach(k,function(a){angular.extend(a,{direction:"",entering:!1,leaving:!1,active:!1})}),angular.extend(c,{direction:f,active:!0,entering:!0}),angular.extend(j.currentSlide||{},{direction:f,leaving:!0}),a.$currentTransition=d(c.$element,{}),function(b,c){a.$currentTransition.then(function(){h(b,c)},function(){h(b,c)})}(c,j.currentSlide)):h(c,j.currentSlide),j.currentSlide=c,l=i,e())}function h(b,c){angular.extend(b,{direction:"",active:!0,leaving:!1,entering:!1}),angular.extend(c||{},{direction:"",active:!1,leaving:!1,entering:!1}),a.$currentTransition=null}var i=k.indexOf(c);void 0===f&&(f=i>l?"next":"prev"),c&&c!==j.currentSlide&&(a.$currentTransition?(a.$currentTransition.cancel(),b(g)):g())},a.$on("$destroy",function(){m=!0}),j.indexOfSlide=function(a){return k.indexOf(a)},a.next=function(){var b=(l+1)%k.length;return a.$currentTransition?void 0:j.select(k[b],"next")},a.prev=function(){var b=0>l-1?k.length-1:l-1;return a.$currentTransition?void 0:j.select(k[b],"prev")},a.isActive=function(a){return j.currentSlide===a},a.$watch("interval",e),a.$on("$destroy",f),a.play=function(){i||(i=!0,e())},a.pause=function(){a.noPause||(i=!1,f())},j.addSlide=function(b,c){b.$element=c,k.push(b),1===k.length||b.active?(j.select(k[k.length-1]),1==k.length&&a.play()):b.active=!1},j.removeSlide=function(a){var b=k.indexOf(a);k.splice(b,1),k.length>0&&a.active?j.select(b>=k.length?k[b-1]:k[b]):l>b&&l--}}]).directive("carousel",[function(){return{restrict:"EA",transclude:!0,replace:!0,controller:"CarouselController",require:"carousel",templateUrl:"template/carousel/carousel.html",scope:{interval:"=",noTransition:"=",noPause:"="}}}]).directive("slide",function(){return{require:"^carousel",restrict:"EA",transclude:!0,replace:!0,templateUrl:"template/carousel/slide.html",scope:{active:"=?"},link:function(a,b,c,d){d.addSlide(a,b),a.$on("$destroy",function(){d.removeSlide(a)}),a.$watch("active",function(b){b&&d.select(a)})}}}),angular.module("ui.bootstrap.dateparser",[]).service("dateParser",["$locale","orderByFilter",function(a,b){function c(a){var c=[],d=a.split("");return angular.forEach(e,function(b,e){var f=a.indexOf(e);if(f>-1){a=a.split(""),d[f]="("+b.regex+")",a[f]="$";for(var g=f+1,h=f+e.length;h>g;g++)d[g]="",a[g]="$";a=a.join(""),c.push({index:f,apply:b.apply})}}),{regex:new RegExp("^"+d.join("")+"$"),map:b(c,"index")}}function d(a,b,c){return 1===b&&c>28?29===c&&(a%4===0&&a%100!==0||a%400===0):3===b||5===b||8===b||10===b?31>c:!0}this.parsers={};var e={yyyy:{regex:"\\d{4}",apply:function(a){this.year=+a}},yy:{regex:"\\d{2}",apply:function(a){this.year=+a+2e3}},y:{regex:"\\d{1,4}",apply:function(a){this.year=+a}},MMMM:{regex:a.DATETIME_FORMATS.MONTH.join("|"),apply:function(b){this.month=a.DATETIME_FORMATS.MONTH.indexOf(b)}},MMM:{regex:a.DATETIME_FORMATS.SHORTMONTH.join("|"),apply:function(b){this.month=a.DATETIME_FORMATS.SHORTMONTH.indexOf(b)}},MM:{regex:"0[1-9]|1[0-2]",apply:function(a){this.month=a-1}},M:{regex:"[1-9]|1[0-2]",apply:function(a){this.month=a-1}},dd:{regex:"[0-2][0-9]{1}|3[0-1]{1}",apply:function(a){this.date=+a}},d:{regex:"[1-2]?[0-9]{1}|3[0-1]{1}",apply:function(a){this.date=+a}},EEEE:{regex:a.DATETIME_FORMATS.DAY.join("|")},EEE:{regex:a.DATETIME_FORMATS.SHORTDAY.join("|")}};this.parse=function(b,e){if(!angular.isString(b)||!e)return b;e=a.DATETIME_FORMATS[e]||e,this.parsers[e]||(this.parsers[e]=c(e));var f=this.parsers[e],g=f.regex,h=f.map,i=b.match(g);if(i&&i.length){for(var j,k={year:1900,month:0,date:1,hours:0},l=1,m=i.length;m>l;l++){var n=h[l-1];n.apply&&n.apply.call(k,i[l])}return d(k.year,k.month,k.date)&&(j=new Date(k.year,k.month,k.date,k.hours)),j}}}]),angular.module("ui.bootstrap.position",[]).factory("$position",["$document","$window",function(a,b){function c(a,c){return a.currentStyle?a.currentStyle[c]:b.getComputedStyle?b.getComputedStyle(a)[c]:a.style[c]}function d(a){return"static"===(c(a,"position")||"static")}var e=function(b){for(var c=a[0],e=b.offsetParent||c;e&&e!==c&&d(e);)e=e.offsetParent;return e||c};return{position:function(b){var c=this.offset(b),d={top:0,left:0},f=e(b[0]);f!=a[0]&&(d=this.offset(angular.element(f)),d.top+=f.clientTop-f.scrollTop,d.left+=f.clientLeft-f.scrollLeft);var g=b[0].getBoundingClientRect();return{width:g.width||b.prop("offsetWidth"),height:g.height||b.prop("offsetHeight"),top:c.top-d.top,left:c.left-d.left}},offset:function(c){var d=c[0].getBoundingClientRect();return{width:d.width||c.prop("offsetWidth"),height:d.height||c.prop("offsetHeight"),top:d.top+(b.pageYOffset||a[0].documentElement.scrollTop),left:d.left+(b.pageXOffset||a[0].documentElement.scrollLeft)}},positionElements:function(a,b,c,d){var e,f,g,h,i=c.split("-"),j=i[0],k=i[1]||"center";e=d?this.offset(a):this.position(a),f=b.prop("offsetWidth"),g=b.prop("offsetHeight");var l={center:function(){return e.left+e.width/2-f/2},left:function(){return e.left},right:function(){return e.left+e.width}},m={center:function(){return e.top+e.height/2-g/2},top:function(){return e.top},bottom:function(){return e.top+e.height}};switch(j){case"right":h={top:m[k](),left:l[j]()};break;case"left":h={top:m[k](),left:e.left-f};break;case"bottom":h={top:m[j](),left:l[k]()};break;default:h={top:e.top-g,left:l[k]()}}return h}}}]),angular.module("ui.bootstrap.datepicker",["ui.bootstrap.dateparser","ui.bootstrap.position"]).constant("datepickerConfig",{formatDay:"dd",formatMonth:"MMMM",formatYear:"yyyy",formatDayHeader:"EEE",formatDayTitle:"MMMM yyyy",formatMonthTitle:"yyyy",datepickerMode:"day",minMode:"day",maxMode:"year",showWeeks:!0,startingDay:0,yearRange:20,minDate:null,maxDate:null}).controller("DatepickerController",["$scope","$attrs","$parse","$interpolate","$timeout","$log","dateFilter","datepickerConfig",function(a,b,c,d,e,f,g,h){var i=this,j={$setViewValue:angular.noop};this.modes=["day","month","year"],angular.forEach(["formatDay","formatMonth","formatYear","formatDayHeader","formatDayTitle","formatMonthTitle","minMode","maxMode","showWeeks","startingDay","yearRange"],function(c,e){i[c]=angular.isDefined(b[c])?8>e?d(b[c])(a.$parent):a.$parent.$eval(b[c]):h[c]}),angular.forEach(["minDate","maxDate"],function(d){b[d]?a.$parent.$watch(c(b[d]),function(a){i[d]=a?new Date(a):null,i.refreshView()}):i[d]=h[d]?new Date(h[d]):null}),a.datepickerMode=a.datepickerMode||h.datepickerMode,a.uniqueId="datepicker-"+a.$id+"-"+Math.floor(1e4*Math.random()),this.activeDate=angular.isDefined(b.initDate)?a.$parent.$eval(b.initDate):new Date,a.isActive=function(b){return 0===i.compare(b.date,i.activeDate)?(a.activeDateId=b.uid,!0):!1},this.init=function(a){j=a,j.$render=function(){i.render()}},this.render=function(){if(j.$modelValue){var a=new Date(j.$modelValue),b=!isNaN(a);b?this.activeDate=a:f.error('Datepicker directive: "ng-model" value must be a Date object, a number of milliseconds since 01.01.1970 or a string representing an RFC2822 or ISO 8601 date.'),j.$setValidity("date",b)}this.refreshView()},this.refreshView=function(){if(this.element){this._refreshView();var a=j.$modelValue?new Date(j.$modelValue):null;j.$setValidity("date-disabled",!a||this.element&&!this.isDisabled(a))}},this.createDateObject=function(a,b){var c=j.$modelValue?new Date(j.$modelValue):null;return{date:a,label:g(a,b),selected:c&&0===this.compare(a,c),disabled:this.isDisabled(a),current:0===this.compare(a,new Date)}},this.isDisabled=function(c){return this.minDate&&this.compare(c,this.minDate)<0||this.maxDate&&this.compare(c,this.maxDate)>0||b.dateDisabled&&a.dateDisabled({date:c,mode:a.datepickerMode})},this.split=function(a,b){for(var c=[];a.length>0;)c.push(a.splice(0,b));return c},a.select=function(b){if(a.datepickerMode===i.minMode){var c=j.$modelValue?new Date(j.$modelValue):new Date(0,0,0,0,0,0,0);c.setFullYear(b.getFullYear(),b.getMonth(),b.getDate()),j.$setViewValue(c),j.$render()}else i.activeDate=b,a.datepickerMode=i.modes[i.modes.indexOf(a.datepickerMode)-1]},a.move=function(a){var b=i.activeDate.getFullYear()+a*(i.step.years||0),c=i.activeDate.getMonth()+a*(i.step.months||0);i.activeDate.setFullYear(b,c,1),i.refreshView()},a.toggleMode=function(b){b=b||1,a.datepickerMode===i.maxMode&&1===b||a.datepickerMode===i.minMode&&-1===b||(a.datepickerMode=i.modes[i.modes.indexOf(a.datepickerMode)+b])},a.keys={13:"enter",32:"space",33:"pageup",34:"pagedown",35:"end",36:"home",37:"left",38:"up",39:"right",40:"down"};var k=function(){e(function(){i.element[0].focus()},0,!1)};a.$on("datepicker.focus",k),a.keydown=function(b){var c=a.keys[b.which];if(c&&!b.shiftKey&&!b.altKey)if(b.preventDefault(),b.stopPropagation(),"enter"===c||"space"===c){if(i.isDisabled(i.activeDate))return;a.select(i.activeDate),k()}else!b.ctrlKey||"up"!==c&&"down"!==c?(i.handleKeyDown(c,b),i.refreshView()):(a.toggleMode("up"===c?1:-1),k())}}]).directive("datepicker",function(){return{restrict:"EA",replace:!0,templateUrl:"template/datepicker/datepicker.html",scope:{datepickerMode:"=?",dateDisabled:"&"},require:["datepicker","?^ngModel"],controller:"DatepickerController",link:function(a,b,c,d){var e=d[0],f=d[1];f&&e.init(f)}}}).directive("daypicker",["dateFilter",function(a){return{restrict:"EA",replace:!0,templateUrl:"template/datepicker/day.html",require:"^datepicker",link:function(b,c,d,e){function f(a,b){return 1!==b||a%4!==0||a%100===0&&a%400!==0?i[b]:29}function g(a,b){var c=new Array(b),d=new Date(a),e=0;for(d.setHours(12);b>e;)c[e++]=new Date(d),d.setDate(d.getDate()+1);return c}function h(a){var b=new Date(a);b.setDate(b.getDate()+4-(b.getDay()||7));var c=b.getTime();return b.setMonth(0),b.setDate(1),Math.floor(Math.round((c-b)/864e5)/7)+1}b.showWeeks=e.showWeeks,e.step={months:1},e.element=c;var i=[31,28,31,30,31,30,31,31,30,31,30,31];e._refreshView=function(){var c=e.activeDate.getFullYear(),d=e.activeDate.getMonth(),f=new Date(c,d,1),i=e.startingDay-f.getDay(),j=i>0?7-i:-i,k=new Date(f);j>0&&k.setDate(-j+1);for(var l=g(k,42),m=0;42>m;m++)l[m]=angular.extend(e.createDateObject(l[m],e.formatDay),{secondary:l[m].getMonth()!==d,uid:b.uniqueId+"-"+m});b.labels=new Array(7);for(var n=0;7>n;n++)b.labels[n]={abbr:a(l[n].date,e.formatDayHeader),full:a(l[n].date,"EEEE")};if(b.title=a(e.activeDate,e.formatDayTitle),b.rows=e.split(l,7),b.showWeeks){b.weekNumbers=[];for(var o=h(b.rows[0][0].date),p=b.rows.length;b.weekNumbers.push(o++)f;f++)c[f]=angular.extend(e.createDateObject(new Date(d,f,1),e.formatMonth),{uid:b.uniqueId+"-"+f});b.title=a(e.activeDate,e.formatMonthTitle),b.rows=e.split(c,3)},e.compare=function(a,b){return new Date(a.getFullYear(),a.getMonth())-new Date(b.getFullYear(),b.getMonth())},e.handleKeyDown=function(a){var b=e.activeDate.getMonth();if("left"===a)b-=1;else if("up"===a)b-=3;else if("right"===a)b+=1;else if("down"===a)b+=3;else if("pageup"===a||"pagedown"===a){var c=e.activeDate.getFullYear()+("pageup"===a?-1:1);e.activeDate.setFullYear(c)}else"home"===a?b=0:"end"===a&&(b=11);e.activeDate.setMonth(b)},e.refreshView()}}}]).directive("yearpicker",["dateFilter",function(){return{restrict:"EA",replace:!0,templateUrl:"template/datepicker/year.html",require:"^datepicker",link:function(a,b,c,d){function e(a){return parseInt((a-1)/f,10)*f+1}var f=d.yearRange;d.step={years:f},d.element=b,d._refreshView=function(){for(var b=new Array(f),c=0,g=e(d.activeDate.getFullYear());f>c;c++)b[c]=angular.extend(d.createDateObject(new Date(g+c,0,1),d.formatYear),{uid:a.uniqueId+"-"+c});a.title=[b[0].label,b[f-1].label].join(" - "),a.rows=d.split(b,5)},d.compare=function(a,b){return a.getFullYear()-b.getFullYear()},d.handleKeyDown=function(a){var b=d.activeDate.getFullYear();"left"===a?b-=1:"up"===a?b-=5:"right"===a?b+=1:"down"===a?b+=5:"pageup"===a||"pagedown"===a?b+=("pageup"===a?-1:1)*d.step.years:"home"===a?b=e(d.activeDate.getFullYear()):"end"===a&&(b=e(d.activeDate.getFullYear())+f-1),d.activeDate.setFullYear(b)},d.refreshView()}}}]).constant("datepickerPopupConfig",{datepickerPopup:"yyyy-MM-dd",currentText:"Today",clearText:"Clear",closeText:"Done",closeOnDateSelection:!0,appendToBody:!1,showButtonBar:!0}).directive("datepickerPopup",["$compile","$parse","$document","$position","dateFilter","dateParser","datepickerPopupConfig",function(a,b,c,d,e,f,g){return{restrict:"EA",require:"ngModel",scope:{isOpen:"=?",currentText:"@",clearText:"@",closeText:"@",dateDisabled:"&"},link:function(h,i,j,k){function l(a){return a.replace(/([A-Z])/g,function(a){return"-"+a.toLowerCase()})}function m(a){if(a){if(angular.isDate(a)&&!isNaN(a))return k.$setValidity("date",!0),a;if(angular.isString(a)){var b=f.parse(a,n)||new Date(a);return isNaN(b)?void k.$setValidity("date",!1):(k.$setValidity("date",!0),b)}return void k.$setValidity("date",!1)}return k.$setValidity("date",!0),null}var n,o=angular.isDefined(j.closeOnDateSelection)?h.$parent.$eval(j.closeOnDateSelection):g.closeOnDateSelection,p=angular.isDefined(j.datepickerAppendToBody)?h.$parent.$eval(j.datepickerAppendToBody):g.appendToBody;h.showButtonBar=angular.isDefined(j.showButtonBar)?h.$parent.$eval(j.showButtonBar):g.showButtonBar,h.getText=function(a){return h[a+"Text"]||g[a+"Text"]},j.$observe("datepickerPopup",function(a){n=a||g.datepickerPopup,k.$render()});var q=angular.element("
");q.attr({"ng-model":"date","ng-change":"dateSelection()"});var r=angular.element(q.children()[0]);j.datepickerOptions&&angular.forEach(h.$parent.$eval(j.datepickerOptions),function(a,b){r.attr(l(b),a)}),h.watchData={},angular.forEach(["minDate","maxDate","datepickerMode"],function(a){if(j[a]){var c=b(j[a]);if(h.$parent.$watch(c,function(b){h.watchData[a]=b}),r.attr(l(a),"watchData."+a),"datepickerMode"===a){var d=c.assign;h.$watch("watchData."+a,function(a,b){a!==b&&d(h.$parent,a)})}}}),j.dateDisabled&&r.attr("date-disabled","dateDisabled({ date: date, mode: mode })"),k.$parsers.unshift(m),h.dateSelection=function(a){angular.isDefined(a)&&(h.date=a),k.$setViewValue(h.date),k.$render(),o&&(h.isOpen=!1,i[0].focus())},i.bind("input change keyup",function(){h.$apply(function(){h.date=k.$modelValue})}),k.$render=function(){var a=k.$viewValue?e(k.$viewValue,n):"";i.val(a),h.date=m(k.$modelValue)};var s=function(a){h.isOpen&&a.target!==i[0]&&h.$apply(function(){h.isOpen=!1})},t=function(a){h.keydown(a)};i.bind("keydown",t),h.keydown=function(a){27===a.which?(a.preventDefault(),a.stopPropagation(),h.close()):40!==a.which||h.isOpen||(h.isOpen=!0)},h.$watch("isOpen",function(a){a?(h.$broadcast("datepicker.focus"),h.position=p?d.offset(i):d.position(i),h.position.top=h.position.top+i.prop("offsetHeight"),c.bind("click",s)):c.unbind("click",s)}),h.select=function(a){if("today"===a){var b=new Date;angular.isDate(k.$modelValue)?(a=new Date(k.$modelValue),a.setFullYear(b.getFullYear(),b.getMonth(),b.getDate())):a=new Date(b.setHours(0,0,0,0))}h.dateSelection(a)},h.close=function(){h.isOpen=!1,i[0].focus()};var u=a(q)(h);q.remove(),p?c.find("body").append(u):i.after(u),h.$on("$destroy",function(){u.remove(),i.unbind("keydown",t),c.unbind("click",s)})}}}]).directive("datepickerPopupWrap",function(){return{restrict:"EA",replace:!0,transclude:!0,templateUrl:"template/datepicker/popup.html",link:function(a,b){b.bind("click",function(a){a.preventDefault(),a.stopPropagation()})}}}),angular.module("ui.bootstrap.dropdown",[]).constant("dropdownConfig",{openClass:"open"}).service("dropdownService",["$document",function(a){var b=null;this.open=function(e){b||(a.bind("click",c),a.bind("keydown",d)),b&&b!==e&&(b.isOpen=!1),b=e},this.close=function(e){b===e&&(b=null,a.unbind("click",c),a.unbind("keydown",d))};var c=function(a){if(b){var c=b.getToggleElement();a&&c&&c[0].contains(a.target)||b.$apply(function(){b.isOpen=!1})}},d=function(a){27===a.which&&(b.focusToggleElement(),c())}}]).controller("DropdownController",["$scope","$attrs","$parse","dropdownConfig","dropdownService","$animate",function(a,b,c,d,e,f){var g,h=this,i=a.$new(),j=d.openClass,k=angular.noop,l=b.onToggle?c(b.onToggle):angular.noop;this.init=function(d){h.$element=d,b.isOpen&&(g=c(b.isOpen),k=g.assign,a.$watch(g,function(a){i.isOpen=!!a}))},this.toggle=function(a){return i.isOpen=arguments.length?!!a:!i.isOpen},this.isOpen=function(){return i.isOpen},i.getToggleElement=function(){return h.toggleElement},i.focusToggleElement=function(){h.toggleElement&&h.toggleElement[0].focus()},i.$watch("isOpen",function(b,c){f[b?"addClass":"removeClass"](h.$element,j),b?(i.focusToggleElement(),e.open(i)):e.close(i),k(a,b),angular.isDefined(b)&&b!==c&&l(a,{open:!!b})}),a.$on("$locationChangeSuccess",function(){i.isOpen=!1}),a.$on("$destroy",function(){i.$destroy()})}]).directive("dropdown",function(){return{controller:"DropdownController",link:function(a,b,c,d){d.init(b)}}}).directive("dropdownToggle",function(){return{require:"?^dropdown",link:function(a,b,c,d){if(d){d.toggleElement=b;var e=function(e){e.preventDefault(),b.hasClass("disabled")||c.disabled||a.$apply(function(){d.toggle()})};b.bind("click",e),b.attr({"aria-haspopup":!0,"aria-expanded":!1}),a.$watch(d.isOpen,function(a){b.attr("aria-expanded",!!a)}),a.$on("$destroy",function(){b.unbind("click",e)})}}}}),angular.module("ui.bootstrap.modal",["ui.bootstrap.transition"]).factory("$$stackedMap",function(){return{createNew:function(){var a=[];return{add:function(b,c){a.push({key:b,value:c})},get:function(b){for(var c=0;c0),i()})}function i(){if(k&&-1==g()){var a=l;j(k,l,150,function(){a.$destroy(),a=null}),k=void 0,l=void 0}}function j(c,d,e,f){function g(){g.done||(g.done=!0,c.remove(),f&&f())}d.animate=!1;var h=a.transitionEndEventName;if(h){var i=b(g,e);c.bind(h,function(){b.cancel(i),g(),d.$apply()})}else b(g)}var k,l,m="modal-open",n=f.createNew(),o={};return e.$watch(g,function(a){l&&(l.index=a)}),c.bind("keydown",function(a){var b;27===a.which&&(b=n.top(),b&&b.value.keyboard&&(a.preventDefault(),e.$apply(function(){o.dismiss(b.key,"escape key press")})))}),o.open=function(a,b){n.add(a,{deferred:b.deferred,modalScope:b.scope,backdrop:b.backdrop,keyboard:b.keyboard});var f=c.find("body").eq(0),h=g();if(h>=0&&!k){l=e.$new(!0),l.index=h;var i=angular.element("
");i.attr("backdrop-class",b.backdropClass),k=d(i)(l),f.append(k)}var j=angular.element("
");j.attr({"template-url":b.windowTemplateUrl,"window-class":b.windowClass,size:b.size,index:n.length()-1,animate:"animate"}).html(b.content);var o=d(j)(b.scope);n.top().value.modalDomEl=o,f.append(o),f.addClass(m)},o.close=function(a,b){var c=n.get(a);c&&(c.value.deferred.resolve(b),h(a))},o.dismiss=function(a,b){var c=n.get(a);c&&(c.value.deferred.reject(b),h(a))},o.dismissAll=function(a){for(var b=this.getTop();b;)this.dismiss(b.key,a),b=this.getTop()},o.getTop=function(){return n.top()},o}]).provider("$modal",function(){var a={options:{backdrop:!0,keyboard:!0},$get:["$injector","$rootScope","$q","$http","$templateCache","$controller","$modalStack",function(b,c,d,e,f,g,h){function i(a){return a.template?d.when(a.template):e.get(angular.isFunction(a.templateUrl)?a.templateUrl():a.templateUrl,{cache:f}).then(function(a){return a.data})}function j(a){var c=[];return angular.forEach(a,function(a){(angular.isFunction(a)||angular.isArray(a))&&c.push(d.when(b.invoke(a)))}),c}var k={};return k.open=function(b){var e=d.defer(),f=d.defer(),k={result:e.promise,opened:f.promise,close:function(a){h.close(k,a)},dismiss:function(a){h.dismiss(k,a)}};if(b=angular.extend({},a.options,b),b.resolve=b.resolve||{},!b.template&&!b.templateUrl)throw new Error("One of template or templateUrl options is required.");var l=d.all([i(b)].concat(j(b.resolve)));return l.then(function(a){var d=(b.scope||c).$new();d.$close=k.close,d.$dismiss=k.dismiss;var f,i={},j=1;b.controller&&(i.$scope=d,i.$modalInstance=k,angular.forEach(b.resolve,function(b,c){i[c]=a[j++]}),f=g(b.controller,i),b.controllerAs&&(d[b.controllerAs]=f)),h.open(k,{scope:d,deferred:e,content:a[0],backdrop:b.backdrop,keyboard:b.keyboard,backdropClass:b.backdropClass,windowClass:b.windowClass,windowTemplateUrl:b.windowTemplateUrl,size:b.size})},function(a){e.reject(a)}),l.then(function(){f.resolve(!0)},function(){f.reject(!1)}),k},k}]};return a}),angular.module("ui.bootstrap.pagination",[]).controller("PaginationController",["$scope","$attrs","$parse",function(a,b,c){var d=this,e={$setViewValue:angular.noop},f=b.numPages?c(b.numPages).assign:angular.noop;this.init=function(f,g){e=f,this.config=g,e.$render=function(){d.render()},b.itemsPerPage?a.$parent.$watch(c(b.itemsPerPage),function(b){d.itemsPerPage=parseInt(b,10),a.totalPages=d.calculateTotalPages()}):this.itemsPerPage=g.itemsPerPage},this.calculateTotalPages=function(){var b=this.itemsPerPage<1?1:Math.ceil(a.totalItems/this.itemsPerPage);return Math.max(b||0,1)},this.render=function(){a.page=parseInt(e.$viewValue,10)||1},a.selectPage=function(b){a.page!==b&&b>0&&b<=a.totalPages&&(e.$setViewValue(b),e.$render())},a.getText=function(b){return a[b+"Text"]||d.config[b+"Text"]},a.noPrevious=function(){return 1===a.page},a.noNext=function(){return a.page===a.totalPages},a.$watch("totalItems",function(){a.totalPages=d.calculateTotalPages()}),a.$watch("totalPages",function(b){f(a.$parent,b),a.page>b?a.selectPage(b):e.$render()})}]).constant("paginationConfig",{itemsPerPage:10,boundaryLinks:!1,directionLinks:!0,firstText:"First",previousText:"Previous",nextText:"Next",lastText:"Last",rotate:!0}).directive("pagination",["$parse","paginationConfig",function(a,b){return{restrict:"EA",scope:{totalItems:"=",firstText:"@",previousText:"@",nextText:"@",lastText:"@"},require:["pagination","?ngModel"],controller:"PaginationController",templateUrl:"template/pagination/pagination.html",replace:!0,link:function(c,d,e,f){function g(a,b,c){return{number:a,text:b,active:c}}function h(a,b){var c=[],d=1,e=b,f=angular.isDefined(k)&&b>k;f&&(l?(d=Math.max(a-Math.floor(k/2),1),e=d+k-1,e>b&&(e=b,d=e-k+1)):(d=(Math.ceil(a/k)-1)*k+1,e=Math.min(d+k-1,b)));for(var h=d;e>=h;h++){var i=g(h,h,h===a);c.push(i)}if(f&&!l){if(d>1){var j=g(d-1,"...",!1);c.unshift(j)}if(b>e){var m=g(e+1,"...",!1);c.push(m)}}return c}var i=f[0],j=f[1];if(j){var k=angular.isDefined(e.maxSize)?c.$parent.$eval(e.maxSize):b.maxSize,l=angular.isDefined(e.rotate)?c.$parent.$eval(e.rotate):b.rotate;c.boundaryLinks=angular.isDefined(e.boundaryLinks)?c.$parent.$eval(e.boundaryLinks):b.boundaryLinks,c.directionLinks=angular.isDefined(e.directionLinks)?c.$parent.$eval(e.directionLinks):b.directionLinks,i.init(j,b),e.maxSize&&c.$parent.$watch(a(e.maxSize),function(a){k=parseInt(a,10),i.render()});var m=i.render;i.render=function(){m(),c.page>0&&c.page<=c.totalPages&&(c.pages=h(c.page,c.totalPages))}}}}}]).constant("pagerConfig",{itemsPerPage:10,previousText:"« Previous",nextText:"Next »",align:!0}).directive("pager",["pagerConfig",function(a){return{restrict:"EA",scope:{totalItems:"=",previousText:"@",nextText:"@"},require:["pager","?ngModel"],controller:"PaginationController",templateUrl:"template/pagination/pager.html",replace:!0,link:function(b,c,d,e){var f=e[0],g=e[1];g&&(b.align=angular.isDefined(d.align)?b.$parent.$eval(d.align):a.align,f.init(g,a))}}}]),angular.module("ui.bootstrap.tooltip",["ui.bootstrap.position","ui.bootstrap.bindHtml"]).provider("$tooltip",function(){function a(a){var b=/[A-Z]/g,c="-";return a.replace(b,function(a,b){return(b?c:"")+a.toLowerCase()})}var b={placement:"top",animation:!0,popupDelay:0},c={mouseenter:"mouseleave",click:"click",focus:"blur"},d={};this.options=function(a){angular.extend(d,a)},this.setTriggers=function(a){angular.extend(c,a)},this.$get=["$window","$compile","$timeout","$document","$position","$interpolate",function(e,f,g,h,i,j){return function(e,k,l){function m(a){var b=a||n.trigger||l,d=c[b]||b;return{show:b,hide:d}}var n=angular.extend({},b,d),o=a(e),p=j.startSymbol(),q=j.endSymbol(),r="
';return{restrict:"EA",compile:function(){var a=f(r);return function(b,c,d){function f(){D.isOpen?l():j()}function j(){(!C||b.$eval(d[k+"Enable"]))&&(s(),D.popupDelay?z||(z=g(o,D.popupDelay,!1),z.then(function(a){a()})):o()())}function l(){b.$apply(function(){p()})}function o(){return z=null,y&&(g.cancel(y),y=null),D.content?(q(),w.css({top:0,left:0,display:"block"}),A?h.find("body").append(w):c.after(w),E(),D.isOpen=!0,D.$digest(),E):angular.noop}function p(){D.isOpen=!1,g.cancel(z),z=null,D.animation?y||(y=g(r,500)):r()}function q(){w&&r(),x=D.$new(),w=a(x,angular.noop)}function r(){y=null,w&&(w.remove(),w=null),x&&(x.$destroy(),x=null)}function s(){t(),u()}function t(){var a=d[k+"Placement"];D.placement=angular.isDefined(a)?a:n.placement}function u(){var a=d[k+"PopupDelay"],b=parseInt(a,10);D.popupDelay=isNaN(b)?n.popupDelay:b}function v(){var a=d[k+"Trigger"];F(),B=m(a),B.show===B.hide?c.bind(B.show,f):(c.bind(B.show,j),c.bind(B.hide,l))}var w,x,y,z,A=angular.isDefined(n.appendToBody)?n.appendToBody:!1,B=m(void 0),C=angular.isDefined(d[k+"Enable"]),D=b.$new(!0),E=function(){var a=i.positionElements(c,w,D.placement,A); +a.top+="px",a.left+="px",w.css(a)};D.isOpen=!1,d.$observe(e,function(a){D.content=a,!a&&D.isOpen&&p()}),d.$observe(k+"Title",function(a){D.title=a});var F=function(){c.unbind(B.show,j),c.unbind(B.hide,l)};v();var G=b.$eval(d[k+"Animation"]);D.animation=angular.isDefined(G)?!!G:n.animation;var H=b.$eval(d[k+"AppendToBody"]);A=angular.isDefined(H)?H:A,A&&b.$on("$locationChangeSuccess",function(){D.isOpen&&p()}),b.$on("$destroy",function(){g.cancel(y),g.cancel(z),F(),r(),D=null})}}}}}]}).directive("tooltipPopup",function(){return{restrict:"EA",replace:!0,scope:{content:"@",placement:"@",animation:"&",isOpen:"&"},templateUrl:"template/tooltip/tooltip-popup.html"}}).directive("tooltip",["$tooltip",function(a){return a("tooltip","tooltip","mouseenter")}]).directive("tooltipHtmlUnsafePopup",function(){return{restrict:"EA",replace:!0,scope:{content:"@",placement:"@",animation:"&",isOpen:"&"},templateUrl:"template/tooltip/tooltip-html-unsafe-popup.html"}}).directive("tooltipHtmlUnsafe",["$tooltip",function(a){return a("tooltipHtmlUnsafe","tooltip","mouseenter")}]),angular.module("ui.bootstrap.popover",["ui.bootstrap.tooltip"]).directive("popoverPopup",function(){return{restrict:"EA",replace:!0,scope:{title:"@",content:"@",placement:"@",animation:"&",isOpen:"&"},templateUrl:"template/popover/popover.html"}}).directive("popover",["$tooltip",function(a){return a("popover","popover","click")}]),angular.module("ui.bootstrap.progressbar",[]).constant("progressConfig",{animate:!0,max:100}).controller("ProgressController",["$scope","$attrs","progressConfig",function(a,b,c){var d=this,e=angular.isDefined(b.animate)?a.$parent.$eval(b.animate):c.animate;this.bars=[],a.max=angular.isDefined(b.max)?a.$parent.$eval(b.max):c.max,this.addBar=function(b,c){e||c.css({transition:"none"}),this.bars.push(b),b.$watch("value",function(c){b.percent=+(100*c/a.max).toFixed(2)}),b.$on("$destroy",function(){c=null,d.removeBar(b)})},this.removeBar=function(a){this.bars.splice(this.bars.indexOf(a),1)}}]).directive("progress",function(){return{restrict:"EA",replace:!0,transclude:!0,controller:"ProgressController",require:"progress",scope:{},templateUrl:"template/progressbar/progress.html"}}).directive("bar",function(){return{restrict:"EA",replace:!0,transclude:!0,require:"^progress",scope:{value:"=",type:"@"},templateUrl:"template/progressbar/bar.html",link:function(a,b,c,d){d.addBar(a,b)}}}).directive("progressbar",function(){return{restrict:"EA",replace:!0,transclude:!0,controller:"ProgressController",scope:{value:"=",type:"@"},templateUrl:"template/progressbar/progressbar.html",link:function(a,b,c,d){d.addBar(a,angular.element(b.children()[0]))}}}),angular.module("ui.bootstrap.rating",[]).constant("ratingConfig",{max:5,stateOn:null,stateOff:null}).controller("RatingController",["$scope","$attrs","ratingConfig",function(a,b,c){var d={$setViewValue:angular.noop};this.init=function(e){d=e,d.$render=this.render,this.stateOn=angular.isDefined(b.stateOn)?a.$parent.$eval(b.stateOn):c.stateOn,this.stateOff=angular.isDefined(b.stateOff)?a.$parent.$eval(b.stateOff):c.stateOff;var f=angular.isDefined(b.ratingStates)?a.$parent.$eval(b.ratingStates):new Array(angular.isDefined(b.max)?a.$parent.$eval(b.max):c.max);a.range=this.buildTemplateObjects(f)},this.buildTemplateObjects=function(a){for(var b=0,c=a.length;c>b;b++)a[b]=angular.extend({index:b},{stateOn:this.stateOn,stateOff:this.stateOff},a[b]);return a},a.rate=function(b){!a.readonly&&b>=0&&b<=a.range.length&&(d.$setViewValue(b),d.$render())},a.enter=function(b){a.readonly||(a.value=b),a.onHover({value:b})},a.reset=function(){a.value=d.$viewValue,a.onLeave()},a.onKeydown=function(b){/(37|38|39|40)/.test(b.which)&&(b.preventDefault(),b.stopPropagation(),a.rate(a.value+(38===b.which||39===b.which?1:-1)))},this.render=function(){a.value=d.$viewValue}}]).directive("rating",function(){return{restrict:"EA",require:["rating","ngModel"],scope:{readonly:"=?",onHover:"&",onLeave:"&"},controller:"RatingController",templateUrl:"template/rating/rating.html",replace:!0,link:function(a,b,c,d){var e=d[0],f=d[1];f&&e.init(f)}}}),angular.module("ui.bootstrap.tabs",[]).controller("TabsetController",["$scope",function(a){var b=this,c=b.tabs=a.tabs=[];b.select=function(a){angular.forEach(c,function(b){b.active&&b!==a&&(b.active=!1,b.onDeselect())}),a.active=!0,a.onSelect()},b.addTab=function(a){c.push(a),1===c.length?a.active=!0:a.active&&b.select(a)},b.removeTab=function(a){var e=c.indexOf(a);if(a.active&&c.length>1&&!d){var f=e==c.length-1?e-1:e+1;b.select(c[f])}c.splice(e,1)};var d;a.$on("$destroy",function(){d=!0})}]).directive("tabset",function(){return{restrict:"EA",transclude:!0,replace:!0,scope:{type:"@"},controller:"TabsetController",templateUrl:"template/tabs/tabset.html",link:function(a,b,c){a.vertical=angular.isDefined(c.vertical)?a.$parent.$eval(c.vertical):!1,a.justified=angular.isDefined(c.justified)?a.$parent.$eval(c.justified):!1}}}).directive("tab",["$parse",function(a){return{require:"^tabset",restrict:"EA",replace:!0,templateUrl:"template/tabs/tab.html",transclude:!0,scope:{active:"=?",heading:"@",onSelect:"&select",onDeselect:"&deselect"},controller:function(){},compile:function(b,c,d){return function(b,c,e,f){b.$watch("active",function(a){a&&f.select(b)}),b.disabled=!1,e.disabled&&b.$parent.$watch(a(e.disabled),function(a){b.disabled=!!a}),b.select=function(){b.disabled||(b.active=!0)},f.addTab(b),b.$on("$destroy",function(){f.removeTab(b)}),b.$transcludeFn=d}}}}]).directive("tabHeadingTransclude",[function(){return{restrict:"A",require:"^tab",link:function(a,b){a.$watch("headingElement",function(a){a&&(b.html(""),b.append(a))})}}}]).directive("tabContentTransclude",function(){function a(a){return a.tagName&&(a.hasAttribute("tab-heading")||a.hasAttribute("data-tab-heading")||"tab-heading"===a.tagName.toLowerCase()||"data-tab-heading"===a.tagName.toLowerCase())}return{restrict:"A",require:"^tabset",link:function(b,c,d){var e=b.$eval(d.tabContentTransclude);e.$transcludeFn(e.$parent,function(b){angular.forEach(b,function(b){a(b)?e.headingElement=b:c.append(b)})})}}}),angular.module("ui.bootstrap.timepicker",[]).constant("timepickerConfig",{hourStep:1,minuteStep:1,showMeridian:!0,meridians:null,readonlyInput:!1,mousewheel:!0}).controller("TimepickerController",["$scope","$attrs","$parse","$log","$locale","timepickerConfig",function(a,b,c,d,e,f){function g(){var b=parseInt(a.hours,10),c=a.showMeridian?b>0&&13>b:b>=0&&24>b;return c?(a.showMeridian&&(12===b&&(b=0),a.meridian===p[1]&&(b+=12)),b):void 0}function h(){var b=parseInt(a.minutes,10);return b>=0&&60>b?b:void 0}function i(a){return angular.isDefined(a)&&a.toString().length<2?"0"+a:a}function j(a){k(),o.$setViewValue(new Date(n)),l(a)}function k(){o.$setValidity("time",!0),a.invalidHours=!1,a.invalidMinutes=!1}function l(b){var c=n.getHours(),d=n.getMinutes();a.showMeridian&&(c=0===c||12===c?12:c%12),a.hours="h"===b?c:i(c),a.minutes="m"===b?d:i(d),a.meridian=n.getHours()<12?p[0]:p[1]}function m(a){var b=new Date(n.getTime()+6e4*a);n.setHours(b.getHours(),b.getMinutes()),j()}var n=new Date,o={$setViewValue:angular.noop},p=angular.isDefined(b.meridians)?a.$parent.$eval(b.meridians):f.meridians||e.DATETIME_FORMATS.AMPMS;this.init=function(c,d){o=c,o.$render=this.render;var e=d.eq(0),g=d.eq(1),h=angular.isDefined(b.mousewheel)?a.$parent.$eval(b.mousewheel):f.mousewheel;h&&this.setupMousewheelEvents(e,g),a.readonlyInput=angular.isDefined(b.readonlyInput)?a.$parent.$eval(b.readonlyInput):f.readonlyInput,this.setupInputEvents(e,g)};var q=f.hourStep;b.hourStep&&a.$parent.$watch(c(b.hourStep),function(a){q=parseInt(a,10)});var r=f.minuteStep;b.minuteStep&&a.$parent.$watch(c(b.minuteStep),function(a){r=parseInt(a,10)}),a.showMeridian=f.showMeridian,b.showMeridian&&a.$parent.$watch(c(b.showMeridian),function(b){if(a.showMeridian=!!b,o.$error.time){var c=g(),d=h();angular.isDefined(c)&&angular.isDefined(d)&&(n.setHours(c),j())}else l()}),this.setupMousewheelEvents=function(b,c){var d=function(a){a.originalEvent&&(a=a.originalEvent);var b=a.wheelDelta?a.wheelDelta:-a.deltaY;return a.detail||b>0};b.bind("mousewheel wheel",function(b){a.$apply(d(b)?a.incrementHours():a.decrementHours()),b.preventDefault()}),c.bind("mousewheel wheel",function(b){a.$apply(d(b)?a.incrementMinutes():a.decrementMinutes()),b.preventDefault()})},this.setupInputEvents=function(b,c){if(a.readonlyInput)return a.updateHours=angular.noop,void(a.updateMinutes=angular.noop);var d=function(b,c){o.$setViewValue(null),o.$setValidity("time",!1),angular.isDefined(b)&&(a.invalidHours=b),angular.isDefined(c)&&(a.invalidMinutes=c)};a.updateHours=function(){var a=g();angular.isDefined(a)?(n.setHours(a),j("h")):d(!0)},b.bind("blur",function(){!a.invalidHours&&a.hours<10&&a.$apply(function(){a.hours=i(a.hours)})}),a.updateMinutes=function(){var a=h();angular.isDefined(a)?(n.setMinutes(a),j("m")):d(void 0,!0)},c.bind("blur",function(){!a.invalidMinutes&&a.minutes<10&&a.$apply(function(){a.minutes=i(a.minutes)})})},this.render=function(){var a=o.$modelValue?new Date(o.$modelValue):null;isNaN(a)?(o.$setValidity("time",!1),d.error('Timepicker directive: "ng-model" value must be a Date object, a number of milliseconds since 01.01.1970 or a string representing an RFC2822 or ISO 8601 date.')):(a&&(n=a),k(),l())},a.incrementHours=function(){m(60*q)},a.decrementHours=function(){m(60*-q)},a.incrementMinutes=function(){m(r)},a.decrementMinutes=function(){m(-r)},a.toggleMeridian=function(){m(720*(n.getHours()<12?1:-1))}}]).directive("timepicker",function(){return{restrict:"EA",require:["timepicker","?^ngModel"],controller:"TimepickerController",replace:!0,scope:{},templateUrl:"template/timepicker/timepicker.html",link:function(a,b,c,d){var e=d[0],f=d[1];f&&e.init(f,b.find("input"))}}}),angular.module("ui.bootstrap.typeahead",["ui.bootstrap.position","ui.bootstrap.bindHtml"]).factory("typeaheadParser",["$parse",function(a){var b=/^\s*([\s\S]+?)(?:\s+as\s+([\s\S]+?))?\s+for\s+(?:([\$\w][\$\w\d]*))\s+in\s+([\s\S]+?)$/;return{parse:function(c){var d=c.match(b);if(!d)throw new Error('Expected typeahead specification in form of "_modelValue_ (as _label_)? for _item_ in _collection_" but got "'+c+'".');return{itemName:d[3],source:a(d[4]),viewMapper:a(d[2]||d[1]),modelMapper:a(d[1])}}}}]).directive("typeahead",["$compile","$parse","$q","$timeout","$document","$position","typeaheadParser",function(a,b,c,d,e,f,g){var h=[9,13,27,38,40];return{require:"ngModel",link:function(i,j,k,l){var m,n=i.$eval(k.typeaheadMinLength)||1,o=i.$eval(k.typeaheadWaitMs)||0,p=i.$eval(k.typeaheadEditable)!==!1,q=b(k.typeaheadLoading).assign||angular.noop,r=b(k.typeaheadOnSelect),s=k.typeaheadInputFormatter?b(k.typeaheadInputFormatter):void 0,t=k.typeaheadAppendToBody?i.$eval(k.typeaheadAppendToBody):!1,u=i.$eval(k.typeaheadFocusFirst)!==!1,v=b(k.ngModel).assign,w=g.parse(k.typeahead),x=i.$new();i.$on("$destroy",function(){x.$destroy()});var y="typeahead-"+x.$id+"-"+Math.floor(1e4*Math.random());j.attr({"aria-autocomplete":"list","aria-expanded":!1,"aria-owns":y});var z=angular.element("
");z.attr({id:y,matches:"matches",active:"activeIdx",select:"select(activeIdx)",query:"query",position:"position"}),angular.isDefined(k.typeaheadTemplateUrl)&&z.attr("template-url",k.typeaheadTemplateUrl);var A=function(){x.matches=[],x.activeIdx=-1,j.attr("aria-expanded",!1)},B=function(a){return y+"-option-"+a};x.$watch("activeIdx",function(a){0>a?j.removeAttr("aria-activedescendant"):j.attr("aria-activedescendant",B(a))});var C=function(a){var b={$viewValue:a};q(i,!0),c.when(w.source(i,b)).then(function(c){var d=a===l.$viewValue;if(d&&m)if(c.length>0){x.activeIdx=u?0:-1,x.matches.length=0;for(var e=0;e=n?o>0?(F(),E(a)):C(a):(q(i,!1),F(),A()),p?a:a?void l.$setValidity("editable",!1):(l.$setValidity("editable",!0),a)}),l.$formatters.push(function(a){var b,c,d={};return s?(d.$model=a,s(i,d)):(d[w.itemName]=a,b=w.viewMapper(i,d),d[w.itemName]=void 0,c=w.viewMapper(i,d),b!==c?b:a)}),x.select=function(a){var b,c,e={};e[w.itemName]=c=x.matches[a].model,b=w.modelMapper(i,e),v(i,b),l.$setValidity("editable",!0),r(i,{$item:c,$model:b,$label:w.viewMapper(i,e)}),A(),d(function(){j[0].focus()},0,!1)},j.bind("keydown",function(a){0!==x.matches.length&&-1!==h.indexOf(a.which)&&(-1!=x.activeIdx||13!==a.which&&9!==a.which)&&(a.preventDefault(),40===a.which?(x.activeIdx=(x.activeIdx+1)%x.matches.length,x.$digest()):38===a.which?(x.activeIdx=(x.activeIdx>0?x.activeIdx:x.matches.length)-1,x.$digest()):13===a.which||9===a.which?x.$apply(function(){x.select(x.activeIdx)}):27===a.which&&(a.stopPropagation(),A(),x.$digest()))}),j.bind("blur",function(){m=!1});var G=function(a){j[0]!==a.target&&(A(),x.$digest())};e.bind("click",G),i.$on("$destroy",function(){e.unbind("click",G),t&&H.remove()});var H=a(z)(x);t?e.find("body").append(H):j.after(H)}}}]).directive("typeaheadPopup",function(){return{restrict:"EA",scope:{matches:"=",query:"=",active:"=",position:"=",select:"&"},replace:!0,templateUrl:"template/typeahead/typeahead-popup.html",link:function(a,b,c){a.templateUrl=c.templateUrl,a.isOpen=function(){return a.matches.length>0},a.isActive=function(b){return a.active==b},a.selectActive=function(b){a.active=b},a.selectMatch=function(b){a.select({activeIdx:b})}}}}).directive("typeaheadMatch",["$http","$templateCache","$compile","$parse",function(a,b,c,d){return{restrict:"EA",scope:{index:"=",match:"=",query:"="},link:function(e,f,g){var h=d(g.templateUrl)(e.$parent)||"template/typeahead/typeahead-match.html";a.get(h,{cache:b}).success(function(a){f.replaceWith(c(a.trim())(e))})}}}]).filter("typeaheadHighlight",function(){function a(a){return a.replace(/([.?*+^$[\]\\(){}|-])/g,"\\$1")}return function(b,c){return c?(""+b).replace(new RegExp(a(c),"gi"),"$&"):b}}),c("angular-bootstrap",["angular"],function(){}),angular.module("ui.bootstrap",["ui.bootstrap.tpls","ui.bootstrap.transition","ui.bootstrap.collapse","ui.bootstrap.accordion","ui.bootstrap.alert","ui.bootstrap.bindHtml","ui.bootstrap.buttons","ui.bootstrap.carousel","ui.bootstrap.dateparser","ui.bootstrap.position","ui.bootstrap.datepicker","ui.bootstrap.dropdown","ui.bootstrap.modal","ui.bootstrap.pagination","ui.bootstrap.tooltip","ui.bootstrap.popover","ui.bootstrap.progressbar","ui.bootstrap.rating","ui.bootstrap.tabs","ui.bootstrap.timepicker","ui.bootstrap.typeahead"]),angular.module("ui.bootstrap.tpls",["template/accordion/accordion-group.html","template/accordion/accordion.html","template/alert/alert.html","template/carousel/carousel.html","template/carousel/slide.html","template/datepicker/datepicker.html","template/datepicker/day.html","template/datepicker/month.html","template/datepicker/popup.html","template/datepicker/year.html","template/modal/backdrop.html","template/modal/window.html","template/pagination/pager.html","template/pagination/pagination.html","template/tooltip/tooltip-html-unsafe-popup.html","template/tooltip/tooltip-popup.html","template/popover/popover.html","template/progressbar/bar.html","template/progressbar/progress.html","template/progressbar/progressbar.html","template/rating/rating.html","template/tabs/tab.html","template/tabs/tabset.html","template/timepicker/timepicker.html","template/typeahead/typeahead-match.html","template/typeahead/typeahead-popup.html"]),angular.module("ui.bootstrap.transition",[]).factory("$transition",["$q","$timeout","$rootScope",function(a,b,c){function d(a){for(var b in a)if(void 0!==f.style[b])return a[b]}var e=function(d,f,g){g=g||{};var h=a.defer(),i=e[g.animation?"animationEndEventName":"transitionEndEventName"],j=function(){c.$apply(function(){d.unbind(i,j),h.resolve(d)})};return i&&d.bind(i,j),b(function(){angular.isString(f)?d.addClass(f):angular.isFunction(f)?f(d):angular.isObject(f)&&d.css(f),i||h.resolve(d)}),h.promise.cancel=function(){i&&d.unbind(i,j),h.reject("Transition cancelled")},h.promise},f=document.createElement("trans"),g={WebkitTransition:"webkitTransitionEnd",MozTransition:"transitionend",OTransition:"oTransitionEnd",transition:"transitionend"},h={WebkitTransition:"webkitAnimationEnd",MozTransition:"animationend",OTransition:"oAnimationEnd",transition:"animationend"};return e.transitionEndEventName=d(g),e.animationEndEventName=d(h),e}]),angular.module("ui.bootstrap.collapse",["ui.bootstrap.transition"]).directive("collapse",["$transition",function(a){return{link:function(b,c,d){function e(b){function d(){j===e&&(j=void 0)}var e=a(c,b);return j&&j.cancel(),j=e,e.then(d,d),e}function f(){k?(k=!1,g()):(c.removeClass("collapse").addClass("collapsing"),e({height:c[0].scrollHeight+"px"}).then(g))}function g(){c.removeClass("collapsing"),c.addClass("collapse in"),c.css({height:"auto"})}function h(){k?(k=!1,i(),c.css({height:0})):(c.css({height:c[0].scrollHeight+"px"}),c[0].offsetWidth,c.removeClass("collapse in").addClass("collapsing"),e({height:0}).then(i))}function i(){c.removeClass("collapsing"),c.addClass("collapse")}var j,k=!0;b.$watch(d.collapse,function(a){a?h():f()})}}}]),angular.module("ui.bootstrap.accordion",["ui.bootstrap.collapse"]).constant("accordionConfig",{closeOthers:!0}).controller("AccordionController",["$scope","$attrs","accordionConfig",function(a,b,c){this.groups=[],this.closeOthers=function(d){var e=angular.isDefined(b.closeOthers)?a.$eval(b.closeOthers):c.closeOthers;e&&angular.forEach(this.groups,function(a){a!==d&&(a.isOpen=!1)})},this.addGroup=function(a){var b=this;this.groups.push(a),a.$on("$destroy",function(){b.removeGroup(a)})},this.removeGroup=function(a){var b=this.groups.indexOf(a);-1!==b&&this.groups.splice(b,1)}}]).directive("accordion",function(){return{restrict:"EA",controller:"AccordionController",transclude:!0,replace:!1,templateUrl:"template/accordion/accordion.html"}}).directive("accordionGroup",function(){return{require:"^accordion",restrict:"EA",transclude:!0,replace:!0,templateUrl:"template/accordion/accordion-group.html",scope:{heading:"@",isOpen:"=?",isDisabled:"=?"},controller:function(){this.setHeading=function(a){this.heading=a}},link:function(a,b,c,d){d.addGroup(a),a.$watch("isOpen",function(b){b&&d.closeOthers(a)}),a.toggleOpen=function(){a.isDisabled||(a.isOpen=!a.isOpen)}}}}).directive("accordionHeading",function(){return{restrict:"EA",transclude:!0,template:"",replace:!0,require:"^accordionGroup",link:function(a,b,c,d,e){d.setHeading(e(a,function(){}))}}}).directive("accordionTransclude",function(){return{require:"^accordionGroup",link:function(a,b,c,d){a.$watch(function(){return d[c.accordionTransclude]},function(a){a&&(b.html(""),b.append(a))})}}}),angular.module("ui.bootstrap.alert",[]).controller("AlertController",["$scope","$attrs",function(a,b){a.closeable="close"in b,this.close=a.close}]).directive("alert",function(){return{restrict:"EA",controller:"AlertController",templateUrl:"template/alert/alert.html",transclude:!0,replace:!0,scope:{type:"@",close:"&"}}}).directive("dismissOnTimeout",["$timeout",function(a){return{require:"alert",link:function(b,c,d,e){a(function(){e.close()},parseInt(d.dismissOnTimeout,10))}}}]),angular.module("ui.bootstrap.bindHtml",[]).directive("bindHtmlUnsafe",function(){return function(a,b,c){b.addClass("ng-binding").data("$binding",c.bindHtmlUnsafe),a.$watch(c.bindHtmlUnsafe,function(a){b.html(a||"")})}}),angular.module("ui.bootstrap.buttons",[]).constant("buttonConfig",{activeClass:"active",toggleEvent:"click"}).controller("ButtonsController",["buttonConfig",function(a){this.activeClass=a.activeClass||"active",this.toggleEvent=a.toggleEvent||"click"}]).directive("btnRadio",function(){return{require:["btnRadio","ngModel"],controller:"ButtonsController",link:function(a,b,c,d){var e=d[0],f=d[1];f.$render=function(){b.toggleClass(e.activeClass,angular.equals(f.$modelValue,a.$eval(c.btnRadio)))},b.bind(e.toggleEvent,function(){var d=b.hasClass(e.activeClass);(!d||angular.isDefined(c.uncheckable))&&a.$apply(function(){f.$setViewValue(d?null:a.$eval(c.btnRadio)),f.$render()})})}}}).directive("btnCheckbox",function(){return{require:["btnCheckbox","ngModel"],controller:"ButtonsController",link:function(a,b,c,d){function e(){return g(c.btnCheckboxTrue,!0)}function f(){return g(c.btnCheckboxFalse,!1)}function g(b,c){var d=a.$eval(b);return angular.isDefined(d)?d:c}var h=d[0],i=d[1];i.$render=function(){b.toggleClass(h.activeClass,angular.equals(i.$modelValue,e()))},b.bind(h.toggleEvent,function(){a.$apply(function(){i.$setViewValue(b.hasClass(h.activeClass)?f():e()),i.$render()})})}}}),angular.module("ui.bootstrap.carousel",["ui.bootstrap.transition"]).controller("CarouselController",["$scope","$timeout","$interval","$transition",function(a,b,c,d){function e(){f();var b=+a.interval;!isNaN(b)&&b>0&&(h=c(g,b))}function f(){h&&(c.cancel(h),h=null)}function g(){var b=+a.interval;i&&!isNaN(b)&&b>0?a.next():a.pause()}var h,i,j=this,k=j.slides=a.slides=[],l=-1;j.currentSlide=null;var m=!1;j.select=a.select=function(c,f){function g(){m||(j.currentSlide&&angular.isString(f)&&!a.noTransition&&c.$element?(c.$element.addClass(f),c.$element[0].offsetWidth,angular.forEach(k,function(a){angular.extend(a,{direction:"",entering:!1,leaving:!1,active:!1})}),angular.extend(c,{direction:f,active:!0,entering:!0}),angular.extend(j.currentSlide||{},{direction:f,leaving:!0}),a.$currentTransition=d(c.$element,{}),function(b,c){a.$currentTransition.then(function(){h(b,c)},function(){h(b,c)})}(c,j.currentSlide)):h(c,j.currentSlide),j.currentSlide=c,l=i,e())}function h(b,c){angular.extend(b,{direction:"",active:!0,leaving:!1,entering:!1}),angular.extend(c||{},{direction:"",active:!1,leaving:!1,entering:!1}),a.$currentTransition=null}var i=k.indexOf(c);void 0===f&&(f=i>l?"next":"prev"),c&&c!==j.currentSlide&&(a.$currentTransition?(a.$currentTransition.cancel(),b(g)):g())},a.$on("$destroy",function(){m=!0}),j.indexOfSlide=function(a){return k.indexOf(a)},a.next=function(){var b=(l+1)%k.length;return a.$currentTransition?void 0:j.select(k[b],"next")},a.prev=function(){var b=0>l-1?k.length-1:l-1;return a.$currentTransition?void 0:j.select(k[b],"prev")},a.isActive=function(a){return j.currentSlide===a},a.$watch("interval",e),a.$on("$destroy",f),a.play=function(){i||(i=!0,e())},a.pause=function(){a.noPause||(i=!1,f())},j.addSlide=function(b,c){b.$element=c,k.push(b),1===k.length||b.active?(j.select(k[k.length-1]),1==k.length&&a.play()):b.active=!1},j.removeSlide=function(a){var b=k.indexOf(a);k.splice(b,1),k.length>0&&a.active?j.select(b>=k.length?k[b-1]:k[b]):l>b&&l--}}]).directive("carousel",[function(){return{restrict:"EA",transclude:!0,replace:!0,controller:"CarouselController",require:"carousel",templateUrl:"template/carousel/carousel.html",scope:{interval:"=",noTransition:"=",noPause:"="}}}]).directive("slide",function(){return{require:"^carousel",restrict:"EA",transclude:!0,replace:!0,templateUrl:"template/carousel/slide.html",scope:{active:"=?"},link:function(a,b,c,d){d.addSlide(a,b),a.$on("$destroy",function(){d.removeSlide(a)}),a.$watch("active",function(b){b&&d.select(a)})}}}),angular.module("ui.bootstrap.dateparser",[]).service("dateParser",["$locale","orderByFilter",function(a,b){function c(a){var c=[],d=a.split("");return angular.forEach(e,function(b,e){var f=a.indexOf(e);if(f>-1){a=a.split(""),d[f]="("+b.regex+")",a[f]="$";for(var g=f+1,h=f+e.length;h>g;g++)d[g]="",a[g]="$";a=a.join(""),c.push({index:f,apply:b.apply})}}),{regex:new RegExp("^"+d.join("")+"$"),map:b(c,"index")}}function d(a,b,c){return 1===b&&c>28?29===c&&(a%4===0&&a%100!==0||a%400===0):3===b||5===b||8===b||10===b?31>c:!0}this.parsers={};var e={yyyy:{regex:"\\d{4}",apply:function(a){this.year=+a}},yy:{regex:"\\d{2}",apply:function(a){this.year=+a+2e3}},y:{regex:"\\d{1,4}",apply:function(a){this.year=+a}},MMMM:{regex:a.DATETIME_FORMATS.MONTH.join("|"),apply:function(b){this.month=a.DATETIME_FORMATS.MONTH.indexOf(b)}},MMM:{regex:a.DATETIME_FORMATS.SHORTMONTH.join("|"),apply:function(b){this.month=a.DATETIME_FORMATS.SHORTMONTH.indexOf(b)}},MM:{regex:"0[1-9]|1[0-2]",apply:function(a){this.month=a-1}},M:{regex:"[1-9]|1[0-2]",apply:function(a){this.month=a-1}},dd:{regex:"[0-2][0-9]{1}|3[0-1]{1}",apply:function(a){this.date=+a}},d:{regex:"[1-2]?[0-9]{1}|3[0-1]{1}",apply:function(a){this.date=+a}},EEEE:{regex:a.DATETIME_FORMATS.DAY.join("|")},EEE:{regex:a.DATETIME_FORMATS.SHORTDAY.join("|")}};this.parse=function(b,e){if(!angular.isString(b)||!e)return b;e=a.DATETIME_FORMATS[e]||e,this.parsers[e]||(this.parsers[e]=c(e));var f=this.parsers[e],g=f.regex,h=f.map,i=b.match(g);if(i&&i.length){for(var j,k={year:1900,month:0,date:1,hours:0},l=1,m=i.length;m>l;l++){var n=h[l-1];n.apply&&n.apply.call(k,i[l])}return d(k.year,k.month,k.date)&&(j=new Date(k.year,k.month,k.date,k.hours)),j}}}]),angular.module("ui.bootstrap.position",[]).factory("$position",["$document","$window",function(a,b){function c(a,c){return a.currentStyle?a.currentStyle[c]:b.getComputedStyle?b.getComputedStyle(a)[c]:a.style[c]}function d(a){return"static"===(c(a,"position")||"static")}var e=function(b){for(var c=a[0],e=b.offsetParent||c;e&&e!==c&&d(e);)e=e.offsetParent;return e||c};return{position:function(b){var c=this.offset(b),d={top:0,left:0},f=e(b[0]);f!=a[0]&&(d=this.offset(angular.element(f)),d.top+=f.clientTop-f.scrollTop,d.left+=f.clientLeft-f.scrollLeft);var g=b[0].getBoundingClientRect();return{width:g.width||b.prop("offsetWidth"),height:g.height||b.prop("offsetHeight"),top:c.top-d.top,left:c.left-d.left}},offset:function(c){var d=c[0].getBoundingClientRect();return{width:d.width||c.prop("offsetWidth"),height:d.height||c.prop("offsetHeight"),top:d.top+(b.pageYOffset||a[0].documentElement.scrollTop),left:d.left+(b.pageXOffset||a[0].documentElement.scrollLeft)}},positionElements:function(a,b,c,d){var e,f,g,h,i=c.split("-"),j=i[0],k=i[1]||"center";e=d?this.offset(a):this.position(a),f=b.prop("offsetWidth"),g=b.prop("offsetHeight");var l={center:function(){return e.left+e.width/2-f/2},left:function(){return e.left},right:function(){return e.left+e.width}},m={center:function(){return e.top+e.height/2-g/2},top:function(){return e.top},bottom:function(){return e.top+e.height}};switch(j){case"right":h={top:m[k](),left:l[j]()};break;case"left":h={top:m[k](),left:e.left-f};break;case"bottom":h={top:m[j](),left:l[k]()};break;default:h={top:e.top-g,left:l[k]()}}return h}}}]),angular.module("ui.bootstrap.datepicker",["ui.bootstrap.dateparser","ui.bootstrap.position"]).constant("datepickerConfig",{formatDay:"dd",formatMonth:"MMMM",formatYear:"yyyy",formatDayHeader:"EEE",formatDayTitle:"MMMM yyyy",formatMonthTitle:"yyyy",datepickerMode:"day",minMode:"day",maxMode:"year",showWeeks:!0,startingDay:0,yearRange:20,minDate:null,maxDate:null}).controller("DatepickerController",["$scope","$attrs","$parse","$interpolate","$timeout","$log","dateFilter","datepickerConfig",function(a,b,c,d,e,f,g,h){var i=this,j={$setViewValue:angular.noop};this.modes=["day","month","year"],angular.forEach(["formatDay","formatMonth","formatYear","formatDayHeader","formatDayTitle","formatMonthTitle","minMode","maxMode","showWeeks","startingDay","yearRange"],function(c,e){i[c]=angular.isDefined(b[c])?8>e?d(b[c])(a.$parent):a.$parent.$eval(b[c]):h[c]}),angular.forEach(["minDate","maxDate"],function(d){b[d]?a.$parent.$watch(c(b[d]),function(a){i[d]=a?new Date(a):null,i.refreshView()}):i[d]=h[d]?new Date(h[d]):null}),a.datepickerMode=a.datepickerMode||h.datepickerMode,a.uniqueId="datepicker-"+a.$id+"-"+Math.floor(1e4*Math.random()),this.activeDate=angular.isDefined(b.initDate)?a.$parent.$eval(b.initDate):new Date,a.isActive=function(b){return 0===i.compare(b.date,i.activeDate)?(a.activeDateId=b.uid,!0):!1},this.init=function(a){j=a,j.$render=function(){i.render()}},this.render=function(){if(j.$modelValue){var a=new Date(j.$modelValue),b=!isNaN(a);b?this.activeDate=a:f.error('Datepicker directive: "ng-model" value must be a Date object, a number of milliseconds since 01.01.1970 or a string representing an RFC2822 or ISO 8601 date.'),j.$setValidity("date",b)}this.refreshView()},this.refreshView=function(){if(this.element){this._refreshView();var a=j.$modelValue?new Date(j.$modelValue):null;j.$setValidity("date-disabled",!a||this.element&&!this.isDisabled(a))}},this.createDateObject=function(a,b){var c=j.$modelValue?new Date(j.$modelValue):null;return{date:a,label:g(a,b),selected:c&&0===this.compare(a,c),disabled:this.isDisabled(a),current:0===this.compare(a,new Date)}},this.isDisabled=function(c){return this.minDate&&this.compare(c,this.minDate)<0||this.maxDate&&this.compare(c,this.maxDate)>0||b.dateDisabled&&a.dateDisabled({date:c,mode:a.datepickerMode})},this.split=function(a,b){for(var c=[];a.length>0;)c.push(a.splice(0,b));return c},a.select=function(b){if(a.datepickerMode===i.minMode){var c=j.$modelValue?new Date(j.$modelValue):new Date(0,0,0,0,0,0,0);c.setFullYear(b.getFullYear(),b.getMonth(),b.getDate()),j.$setViewValue(c),j.$render()}else i.activeDate=b,a.datepickerMode=i.modes[i.modes.indexOf(a.datepickerMode)-1]},a.move=function(a){var b=i.activeDate.getFullYear()+a*(i.step.years||0),c=i.activeDate.getMonth()+a*(i.step.months||0);i.activeDate.setFullYear(b,c,1),i.refreshView()},a.toggleMode=function(b){b=b||1,a.datepickerMode===i.maxMode&&1===b||a.datepickerMode===i.minMode&&-1===b||(a.datepickerMode=i.modes[i.modes.indexOf(a.datepickerMode)+b])},a.keys={13:"enter",32:"space",33:"pageup",34:"pagedown",35:"end",36:"home",37:"left",38:"up",39:"right",40:"down"};var k=function(){e(function(){i.element[0].focus()},0,!1)};a.$on("datepicker.focus",k),a.keydown=function(b){var c=a.keys[b.which];if(c&&!b.shiftKey&&!b.altKey)if(b.preventDefault(),b.stopPropagation(),"enter"===c||"space"===c){if(i.isDisabled(i.activeDate))return;a.select(i.activeDate),k()}else!b.ctrlKey||"up"!==c&&"down"!==c?(i.handleKeyDown(c,b),i.refreshView()):(a.toggleMode("up"===c?1:-1),k())}}]).directive("datepicker",function(){return{restrict:"EA",replace:!0,templateUrl:"template/datepicker/datepicker.html",scope:{datepickerMode:"=?",dateDisabled:"&"},require:["datepicker","?^ngModel"],controller:"DatepickerController",link:function(a,b,c,d){var e=d[0],f=d[1];f&&e.init(f)}}}).directive("daypicker",["dateFilter",function(a){return{restrict:"EA",replace:!0,templateUrl:"template/datepicker/day.html",require:"^datepicker",link:function(b,c,d,e){function f(a,b){return 1!==b||a%4!==0||a%100===0&&a%400!==0?i[b]:29}function g(a,b){var c=new Array(b),d=new Date(a),e=0;for(d.setHours(12);b>e;)c[e++]=new Date(d),d.setDate(d.getDate()+1);return c}function h(a){var b=new Date(a);b.setDate(b.getDate()+4-(b.getDay()||7));var c=b.getTime();return b.setMonth(0),b.setDate(1),Math.floor(Math.round((c-b)/864e5)/7)+1}b.showWeeks=e.showWeeks,e.step={months:1},e.element=c;var i=[31,28,31,30,31,30,31,31,30,31,30,31];e._refreshView=function(){var c=e.activeDate.getFullYear(),d=e.activeDate.getMonth(),f=new Date(c,d,1),i=e.startingDay-f.getDay(),j=i>0?7-i:-i,k=new Date(f);j>0&&k.setDate(-j+1);for(var l=g(k,42),m=0;42>m;m++)l[m]=angular.extend(e.createDateObject(l[m],e.formatDay),{secondary:l[m].getMonth()!==d,uid:b.uniqueId+"-"+m});b.labels=new Array(7);for(var n=0;7>n;n++)b.labels[n]={abbr:a(l[n].date,e.formatDayHeader),full:a(l[n].date,"EEEE")};if(b.title=a(e.activeDate,e.formatDayTitle),b.rows=e.split(l,7),b.showWeeks){b.weekNumbers=[];for(var o=h(b.rows[0][0].date),p=b.rows.length;b.weekNumbers.push(o++)f;f++)c[f]=angular.extend(e.createDateObject(new Date(d,f,1),e.formatMonth),{uid:b.uniqueId+"-"+f});b.title=a(e.activeDate,e.formatMonthTitle),b.rows=e.split(c,3)},e.compare=function(a,b){return new Date(a.getFullYear(),a.getMonth())-new Date(b.getFullYear(),b.getMonth())},e.handleKeyDown=function(a){var b=e.activeDate.getMonth();if("left"===a)b-=1;else if("up"===a)b-=3;else if("right"===a)b+=1;else if("down"===a)b+=3;else if("pageup"===a||"pagedown"===a){var c=e.activeDate.getFullYear()+("pageup"===a?-1:1);e.activeDate.setFullYear(c)}else"home"===a?b=0:"end"===a&&(b=11);e.activeDate.setMonth(b)},e.refreshView()}}}]).directive("yearpicker",["dateFilter",function(){return{restrict:"EA",replace:!0,templateUrl:"template/datepicker/year.html",require:"^datepicker",link:function(a,b,c,d){function e(a){return parseInt((a-1)/f,10)*f+1}var f=d.yearRange;d.step={years:f},d.element=b,d._refreshView=function(){for(var b=new Array(f),c=0,g=e(d.activeDate.getFullYear());f>c;c++)b[c]=angular.extend(d.createDateObject(new Date(g+c,0,1),d.formatYear),{uid:a.uniqueId+"-"+c});a.title=[b[0].label,b[f-1].label].join(" - "),a.rows=d.split(b,5)},d.compare=function(a,b){return a.getFullYear()-b.getFullYear()},d.handleKeyDown=function(a){var b=d.activeDate.getFullYear();"left"===a?b-=1:"up"===a?b-=5:"right"===a?b+=1:"down"===a?b+=5:"pageup"===a||"pagedown"===a?b+=("pageup"===a?-1:1)*d.step.years:"home"===a?b=e(d.activeDate.getFullYear()):"end"===a&&(b=e(d.activeDate.getFullYear())+f-1),d.activeDate.setFullYear(b)},d.refreshView()}}}]).constant("datepickerPopupConfig",{datepickerPopup:"yyyy-MM-dd",currentText:"Today",clearText:"Clear",closeText:"Done",closeOnDateSelection:!0,appendToBody:!1,showButtonBar:!0}).directive("datepickerPopup",["$compile","$parse","$document","$position","dateFilter","dateParser","datepickerPopupConfig",function(a,b,c,d,e,f,g){return{restrict:"EA",require:"ngModel",scope:{isOpen:"=?",currentText:"@",clearText:"@",closeText:"@",dateDisabled:"&"},link:function(h,i,j,k){function l(a){return a.replace(/([A-Z])/g,function(a){return"-"+a.toLowerCase()})}function m(a){if(a){if(angular.isDate(a)&&!isNaN(a))return k.$setValidity("date",!0),a;if(angular.isString(a)){var b=f.parse(a,n)||new Date(a);return isNaN(b)?void k.$setValidity("date",!1):(k.$setValidity("date",!0),b)}return void k.$setValidity("date",!1)}return k.$setValidity("date",!0),null}var n,o=angular.isDefined(j.closeOnDateSelection)?h.$parent.$eval(j.closeOnDateSelection):g.closeOnDateSelection,p=angular.isDefined(j.datepickerAppendToBody)?h.$parent.$eval(j.datepickerAppendToBody):g.appendToBody;h.showButtonBar=angular.isDefined(j.showButtonBar)?h.$parent.$eval(j.showButtonBar):g.showButtonBar,h.getText=function(a){return h[a+"Text"]||g[a+"Text"]},j.$observe("datepickerPopup",function(a){n=a||g.datepickerPopup,k.$render()});var q=angular.element("
");q.attr({"ng-model":"date","ng-change":"dateSelection()"});var r=angular.element(q.children()[0]);j.datepickerOptions&&angular.forEach(h.$parent.$eval(j.datepickerOptions),function(a,b){r.attr(l(b),a)}),h.watchData={},angular.forEach(["minDate","maxDate","datepickerMode"],function(a){if(j[a]){var c=b(j[a]);if(h.$parent.$watch(c,function(b){h.watchData[a]=b}),r.attr(l(a),"watchData."+a),"datepickerMode"===a){var d=c.assign;h.$watch("watchData."+a,function(a,b){a!==b&&d(h.$parent,a)})}}}),j.dateDisabled&&r.attr("date-disabled","dateDisabled({ date: date, mode: mode })"),k.$parsers.unshift(m),h.dateSelection=function(a){angular.isDefined(a)&&(h.date=a),k.$setViewValue(h.date),k.$render(),o&&(h.isOpen=!1,i[0].focus())},i.bind("input change keyup",function(){h.$apply(function(){h.date=k.$modelValue})}),k.$render=function(){var a=k.$viewValue?e(k.$viewValue,n):"";i.val(a),h.date=m(k.$modelValue)};var s=function(a){h.isOpen&&a.target!==i[0]&&h.$apply(function(){h.isOpen=!1})},t=function(a){h.keydown(a)};i.bind("keydown",t),h.keydown=function(a){27===a.which?(a.preventDefault(),a.stopPropagation(),h.close()):40!==a.which||h.isOpen||(h.isOpen=!0)},h.$watch("isOpen",function(a){a?(h.$broadcast("datepicker.focus"),h.position=p?d.offset(i):d.position(i),h.position.top=h.position.top+i.prop("offsetHeight"),c.bind("click",s)):c.unbind("click",s)}),h.select=function(a){if("today"===a){var b=new Date;angular.isDate(k.$modelValue)?(a=new Date(k.$modelValue),a.setFullYear(b.getFullYear(),b.getMonth(),b.getDate())):a=new Date(b.setHours(0,0,0,0))}h.dateSelection(a)},h.close=function(){h.isOpen=!1,i[0].focus()};var u=a(q)(h);q.remove(),p?c.find("body").append(u):i.after(u),h.$on("$destroy",function(){u.remove(),i.unbind("keydown",t),c.unbind("click",s)})}}}]).directive("datepickerPopupWrap",function(){return{restrict:"EA",replace:!0,transclude:!0,templateUrl:"template/datepicker/popup.html",link:function(a,b){b.bind("click",function(a){a.preventDefault(),a.stopPropagation()})}}}),angular.module("ui.bootstrap.dropdown",[]).constant("dropdownConfig",{openClass:"open"}).service("dropdownService",["$document",function(a){var b=null;this.open=function(e){b||(a.bind("click",c),a.bind("keydown",d)),b&&b!==e&&(b.isOpen=!1),b=e},this.close=function(e){b===e&&(b=null,a.unbind("click",c),a.unbind("keydown",d))};var c=function(a){if(b){var c=b.getToggleElement();a&&c&&c[0].contains(a.target)||b.$apply(function(){b.isOpen=!1})}},d=function(a){27===a.which&&(b.focusToggleElement(),c())}}]).controller("DropdownController",["$scope","$attrs","$parse","dropdownConfig","dropdownService","$animate",function(a,b,c,d,e,f){var g,h=this,i=a.$new(),j=d.openClass,k=angular.noop,l=b.onToggle?c(b.onToggle):angular.noop;this.init=function(d){h.$element=d,b.isOpen&&(g=c(b.isOpen),k=g.assign,a.$watch(g,function(a){i.isOpen=!!a}))},this.toggle=function(a){return i.isOpen=arguments.length?!!a:!i.isOpen},this.isOpen=function(){return i.isOpen},i.getToggleElement=function(){return h.toggleElement},i.focusToggleElement=function(){h.toggleElement&&h.toggleElement[0].focus()},i.$watch("isOpen",function(b,c){f[b?"addClass":"removeClass"](h.$element,j),b?(i.focusToggleElement(),e.open(i)):e.close(i),k(a,b),angular.isDefined(b)&&b!==c&&l(a,{open:!!b})}),a.$on("$locationChangeSuccess",function(){i.isOpen=!1}),a.$on("$destroy",function(){i.$destroy()})}]).directive("dropdown",function(){return{controller:"DropdownController",link:function(a,b,c,d){d.init(b)}}}).directive("dropdownToggle",function(){return{require:"?^dropdown",link:function(a,b,c,d){if(d){d.toggleElement=b;var e=function(e){e.preventDefault(),b.hasClass("disabled")||c.disabled||a.$apply(function(){d.toggle()})};b.bind("click",e),b.attr({"aria-haspopup":!0,"aria-expanded":!1}),a.$watch(d.isOpen,function(a){b.attr("aria-expanded",!!a)}),a.$on("$destroy",function(){b.unbind("click",e)})}}}}),angular.module("ui.bootstrap.modal",["ui.bootstrap.transition"]).factory("$$stackedMap",function(){return{createNew:function(){var a=[];return{add:function(b,c){a.push({key:b,value:c})},get:function(b){for(var c=0;c0),i()})}function i(){if(k&&-1==g()){var a=l;j(k,l,150,function(){a.$destroy(),a=null}),k=void 0,l=void 0}}function j(c,d,e,f){function g(){g.done||(g.done=!0,c.remove(),f&&f())}d.animate=!1;var h=a.transitionEndEventName;if(h){var i=b(g,e);c.bind(h,function(){b.cancel(i),g(),d.$apply()})}else b(g)}var k,l,m="modal-open",n=f.createNew(),o={};return e.$watch(g,function(a){l&&(l.index=a)}),c.bind("keydown",function(a){var b;27===a.which&&(b=n.top(),b&&b.value.keyboard&&(a.preventDefault(),e.$apply(function(){o.dismiss(b.key,"escape key press")})))}),o.open=function(a,b){n.add(a,{deferred:b.deferred,modalScope:b.scope,backdrop:b.backdrop,keyboard:b.keyboard});var f=c.find("body").eq(0),h=g();if(h>=0&&!k){l=e.$new(!0),l.index=h;var i=angular.element("
");i.attr("backdrop-class",b.backdropClass),k=d(i)(l),f.append(k)}var j=angular.element("
");j.attr({"template-url":b.windowTemplateUrl,"window-class":b.windowClass,size:b.size,index:n.length()-1,animate:"animate"}).html(b.content);var o=d(j)(b.scope);n.top().value.modalDomEl=o,f.append(o),f.addClass(m)},o.close=function(a,b){var c=n.get(a);c&&(c.value.deferred.resolve(b),h(a))},o.dismiss=function(a,b){var c=n.get(a);c&&(c.value.deferred.reject(b),h(a))},o.dismissAll=function(a){for(var b=this.getTop();b;)this.dismiss(b.key,a),b=this.getTop()},o.getTop=function(){return n.top()},o}]).provider("$modal",function(){var a={options:{backdrop:!0,keyboard:!0},$get:["$injector","$rootScope","$q","$http","$templateCache","$controller","$modalStack",function(b,c,d,e,f,g,h){function i(a){return a.template?d.when(a.template):e.get(angular.isFunction(a.templateUrl)?a.templateUrl():a.templateUrl,{cache:f}).then(function(a){return a.data})}function j(a){var c=[];return angular.forEach(a,function(a){(angular.isFunction(a)||angular.isArray(a))&&c.push(d.when(b.invoke(a)))}),c}var k={};return k.open=function(b){var e=d.defer(),f=d.defer(),k={result:e.promise,opened:f.promise,close:function(a){h.close(k,a)},dismiss:function(a){h.dismiss(k,a)}};if(b=angular.extend({},a.options,b),b.resolve=b.resolve||{},!b.template&&!b.templateUrl)throw new Error("One of template or templateUrl options is required.");var l=d.all([i(b)].concat(j(b.resolve)));return l.then(function(a){var d=(b.scope||c).$new();d.$close=k.close,d.$dismiss=k.dismiss;var f,i={},j=1;b.controller&&(i.$scope=d,i.$modalInstance=k,angular.forEach(b.resolve,function(b,c){i[c]=a[j++]}),f=g(b.controller,i),b.controllerAs&&(d[b.controllerAs]=f)),h.open(k,{scope:d,deferred:e,content:a[0],backdrop:b.backdrop,keyboard:b.keyboard,backdropClass:b.backdropClass,windowClass:b.windowClass,windowTemplateUrl:b.windowTemplateUrl,size:b.size})},function(a){e.reject(a)}),l.then(function(){f.resolve(!0)},function(){f.reject(!1)}),k},k}]};return a}),angular.module("ui.bootstrap.pagination",[]).controller("PaginationController",["$scope","$attrs","$parse",function(a,b,c){var d=this,e={$setViewValue:angular.noop},f=b.numPages?c(b.numPages).assign:angular.noop;this.init=function(f,g){e=f,this.config=g,e.$render=function(){d.render()},b.itemsPerPage?a.$parent.$watch(c(b.itemsPerPage),function(b){d.itemsPerPage=parseInt(b,10),a.totalPages=d.calculateTotalPages()}):this.itemsPerPage=g.itemsPerPage},this.calculateTotalPages=function(){var b=this.itemsPerPage<1?1:Math.ceil(a.totalItems/this.itemsPerPage);return Math.max(b||0,1)},this.render=function(){a.page=parseInt(e.$viewValue,10)||1},a.selectPage=function(b){a.page!==b&&b>0&&b<=a.totalPages&&(e.$setViewValue(b),e.$render())},a.getText=function(b){return a[b+"Text"]||d.config[b+"Text"]},a.noPrevious=function(){return 1===a.page},a.noNext=function(){return a.page===a.totalPages},a.$watch("totalItems",function(){a.totalPages=d.calculateTotalPages()}),a.$watch("totalPages",function(b){f(a.$parent,b),a.page>b?a.selectPage(b):e.$render()})}]).constant("paginationConfig",{itemsPerPage:10,boundaryLinks:!1,directionLinks:!0,firstText:"First",previousText:"Previous",nextText:"Next",lastText:"Last",rotate:!0}).directive("pagination",["$parse","paginationConfig",function(a,b){return{restrict:"EA",scope:{totalItems:"=",firstText:"@",previousText:"@",nextText:"@",lastText:"@"},require:["pagination","?ngModel"],controller:"PaginationController",templateUrl:"template/pagination/pagination.html",replace:!0,link:function(c,d,e,f){function g(a,b,c){return{number:a,text:b,active:c}}function h(a,b){var c=[],d=1,e=b,f=angular.isDefined(k)&&b>k;f&&(l?(d=Math.max(a-Math.floor(k/2),1),e=d+k-1,e>b&&(e=b,d=e-k+1)):(d=(Math.ceil(a/k)-1)*k+1,e=Math.min(d+k-1,b)));for(var h=d;e>=h;h++){var i=g(h,h,h===a);c.push(i)}if(f&&!l){if(d>1){var j=g(d-1,"...",!1);c.unshift(j)}if(b>e){var m=g(e+1,"...",!1);c.push(m)}}return c}var i=f[0],j=f[1];if(j){var k=angular.isDefined(e.maxSize)?c.$parent.$eval(e.maxSize):b.maxSize,l=angular.isDefined(e.rotate)?c.$parent.$eval(e.rotate):b.rotate;c.boundaryLinks=angular.isDefined(e.boundaryLinks)?c.$parent.$eval(e.boundaryLinks):b.boundaryLinks,c.directionLinks=angular.isDefined(e.directionLinks)?c.$parent.$eval(e.directionLinks):b.directionLinks,i.init(j,b),e.maxSize&&c.$parent.$watch(a(e.maxSize),function(a){k=parseInt(a,10),i.render()});var m=i.render;i.render=function(){m(),c.page>0&&c.page<=c.totalPages&&(c.pages=h(c.page,c.totalPages))}}}}}]).constant("pagerConfig",{itemsPerPage:10,previousText:"« Previous",nextText:"Next »",align:!0}).directive("pager",["pagerConfig",function(a){return{restrict:"EA",scope:{totalItems:"=",previousText:"@",nextText:"@"},require:["pager","?ngModel"],controller:"PaginationController",templateUrl:"template/pagination/pager.html",replace:!0,link:function(b,c,d,e){var f=e[0],g=e[1];g&&(b.align=angular.isDefined(d.align)?b.$parent.$eval(d.align):a.align,f.init(g,a))}}}]),angular.module("ui.bootstrap.tooltip",["ui.bootstrap.position","ui.bootstrap.bindHtml"]).provider("$tooltip",function(){function a(a){var b=/[A-Z]/g,c="-";return a.replace(b,function(a,b){return(b?c:"")+a.toLowerCase()})}var b={placement:"top",animation:!0,popupDelay:0},c={mouseenter:"mouseleave",click:"click",focus:"blur"},d={};this.options=function(a){angular.extend(d,a)},this.setTriggers=function(a){angular.extend(c,a)},this.$get=["$window","$compile","$timeout","$document","$position","$interpolate",function(e,f,g,h,i,j){return function(e,k,l){function m(a){var b=a||n.trigger||l,d=c[b]||b;return{show:b,hide:d}}var n=angular.extend({},b,d),o=a(e),p=j.startSymbol(),q=j.endSymbol(),r="
';return{restrict:"EA",compile:function(){var a=f(r);return function(b,c,d){function f(){D.isOpen?l():j()}function j(){(!C||b.$eval(d[k+"Enable"]))&&(s(),D.popupDelay?z||(z=g(o,D.popupDelay,!1),z.then(function(a){a()})):o()())}function l(){b.$apply(function(){p()})}function o(){return z=null,y&&(g.cancel(y),y=null),D.content?(q(),w.css({top:0,left:0,display:"block"}),A?h.find("body").append(w):c.after(w),E(),D.isOpen=!0,D.$digest(),E):angular.noop}function p(){D.isOpen=!1,g.cancel(z),z=null,D.animation?y||(y=g(r,500)):r()}function q(){w&&r(),x=D.$new(),w=a(x,angular.noop)}function r(){y=null,w&&(w.remove(),w=null),x&&(x.$destroy(),x=null)}function s(){t(),u()}function t(){var a=d[k+"Placement"];D.placement=angular.isDefined(a)?a:n.placement}function u(){var a=d[k+"PopupDelay"],b=parseInt(a,10);D.popupDelay=isNaN(b)?n.popupDelay:b}function v(){var a=d[k+"Trigger"];F(),B=m(a),B.show===B.hide?c.bind(B.show,f):(c.bind(B.show,j),c.bind(B.hide,l))}var w,x,y,z,A=angular.isDefined(n.appendToBody)?n.appendToBody:!1,B=m(void 0),C=angular.isDefined(d[k+"Enable"]),D=b.$new(!0),E=function(){var a=i.positionElements(c,w,D.placement,A);a.top+="px",a.left+="px",w.css(a)};D.isOpen=!1,d.$observe(e,function(a){D.content=a,!a&&D.isOpen&&p()}),d.$observe(k+"Title",function(a){D.title=a});var F=function(){c.unbind(B.show,j),c.unbind(B.hide,l)};v();var G=b.$eval(d[k+"Animation"]);D.animation=angular.isDefined(G)?!!G:n.animation;var H=b.$eval(d[k+"AppendToBody"]);A=angular.isDefined(H)?H:A,A&&b.$on("$locationChangeSuccess",function(){D.isOpen&&p()}),b.$on("$destroy",function(){g.cancel(y),g.cancel(z),F(),r(),D=null})}}}}}]}).directive("tooltipPopup",function(){return{restrict:"EA",replace:!0,scope:{content:"@",placement:"@",animation:"&",isOpen:"&"},templateUrl:"template/tooltip/tooltip-popup.html"}}).directive("tooltip",["$tooltip",function(a){return a("tooltip","tooltip","mouseenter")}]).directive("tooltipHtmlUnsafePopup",function(){return{restrict:"EA",replace:!0,scope:{content:"@",placement:"@",animation:"&",isOpen:"&"},templateUrl:"template/tooltip/tooltip-html-unsafe-popup.html"}}).directive("tooltipHtmlUnsafe",["$tooltip",function(a){return a("tooltipHtmlUnsafe","tooltip","mouseenter")}]),angular.module("ui.bootstrap.popover",["ui.bootstrap.tooltip"]).directive("popoverPopup",function(){return{restrict:"EA",replace:!0,scope:{title:"@",content:"@",placement:"@",animation:"&",isOpen:"&"},templateUrl:"template/popover/popover.html"}}).directive("popover",["$tooltip",function(a){return a("popover","popover","click")}]),angular.module("ui.bootstrap.progressbar",[]).constant("progressConfig",{animate:!0,max:100}).controller("ProgressController",["$scope","$attrs","progressConfig",function(a,b,c){var d=this,e=angular.isDefined(b.animate)?a.$parent.$eval(b.animate):c.animate;this.bars=[],a.max=angular.isDefined(b.max)?a.$parent.$eval(b.max):c.max,this.addBar=function(b,c){e||c.css({transition:"none"}),this.bars.push(b),b.$watch("value",function(c){b.percent=+(100*c/a.max).toFixed(2)}),b.$on("$destroy",function(){c=null,d.removeBar(b)})},this.removeBar=function(a){this.bars.splice(this.bars.indexOf(a),1)}}]).directive("progress",function(){return{restrict:"EA",replace:!0,transclude:!0,controller:"ProgressController",require:"progress",scope:{},templateUrl:"template/progressbar/progress.html"}}).directive("bar",function(){return{restrict:"EA",replace:!0,transclude:!0,require:"^progress",scope:{value:"=",type:"@"},templateUrl:"template/progressbar/bar.html",link:function(a,b,c,d){d.addBar(a,b)}}}).directive("progressbar",function(){return{restrict:"EA",replace:!0,transclude:!0,controller:"ProgressController",scope:{value:"=",type:"@"},templateUrl:"template/progressbar/progressbar.html",link:function(a,b,c,d){d.addBar(a,angular.element(b.children()[0]))}}}),angular.module("ui.bootstrap.rating",[]).constant("ratingConfig",{max:5,stateOn:null,stateOff:null}).controller("RatingController",["$scope","$attrs","ratingConfig",function(a,b,c){var d={$setViewValue:angular.noop};this.init=function(e){d=e,d.$render=this.render,this.stateOn=angular.isDefined(b.stateOn)?a.$parent.$eval(b.stateOn):c.stateOn,this.stateOff=angular.isDefined(b.stateOff)?a.$parent.$eval(b.stateOff):c.stateOff;var f=angular.isDefined(b.ratingStates)?a.$parent.$eval(b.ratingStates):new Array(angular.isDefined(b.max)?a.$parent.$eval(b.max):c.max);a.range=this.buildTemplateObjects(f)},this.buildTemplateObjects=function(a){for(var b=0,c=a.length;c>b;b++)a[b]=angular.extend({index:b},{stateOn:this.stateOn,stateOff:this.stateOff},a[b]);return a},a.rate=function(b){!a.readonly&&b>=0&&b<=a.range.length&&(d.$setViewValue(b),d.$render())},a.enter=function(b){a.readonly||(a.value=b),a.onHover({value:b})},a.reset=function(){a.value=d.$viewValue,a.onLeave()},a.onKeydown=function(b){/(37|38|39|40)/.test(b.which)&&(b.preventDefault(),b.stopPropagation(),a.rate(a.value+(38===b.which||39===b.which?1:-1)))},this.render=function(){a.value=d.$viewValue}}]).directive("rating",function(){return{restrict:"EA",require:["rating","ngModel"],scope:{readonly:"=?",onHover:"&",onLeave:"&"},controller:"RatingController",templateUrl:"template/rating/rating.html",replace:!0,link:function(a,b,c,d){var e=d[0],f=d[1];f&&e.init(f)}}}),angular.module("ui.bootstrap.tabs",[]).controller("TabsetController",["$scope",function(a){var b=this,c=b.tabs=a.tabs=[];b.select=function(a){angular.forEach(c,function(b){b.active&&b!==a&&(b.active=!1,b.onDeselect())}),a.active=!0,a.onSelect()},b.addTab=function(a){c.push(a),1===c.length?a.active=!0:a.active&&b.select(a)},b.removeTab=function(a){var e=c.indexOf(a);if(a.active&&c.length>1&&!d){var f=e==c.length-1?e-1:e+1;b.select(c[f])}c.splice(e,1)};var d;a.$on("$destroy",function(){d=!0})}]).directive("tabset",function(){return{restrict:"EA",transclude:!0,replace:!0,scope:{type:"@"},controller:"TabsetController",templateUrl:"template/tabs/tabset.html",link:function(a,b,c){a.vertical=angular.isDefined(c.vertical)?a.$parent.$eval(c.vertical):!1,a.justified=angular.isDefined(c.justified)?a.$parent.$eval(c.justified):!1}}}).directive("tab",["$parse",function(a){return{require:"^tabset",restrict:"EA",replace:!0,templateUrl:"template/tabs/tab.html",transclude:!0,scope:{active:"=?",heading:"@",onSelect:"&select",onDeselect:"&deselect"},controller:function(){},compile:function(b,c,d){return function(b,c,e,f){b.$watch("active",function(a){a&&f.select(b)}),b.disabled=!1,e.disabled&&b.$parent.$watch(a(e.disabled),function(a){b.disabled=!!a}),b.select=function(){b.disabled||(b.active=!0)},f.addTab(b),b.$on("$destroy",function(){f.removeTab(b)}),b.$transcludeFn=d}}}}]).directive("tabHeadingTransclude",[function(){return{restrict:"A",require:"^tab",link:function(a,b){a.$watch("headingElement",function(a){a&&(b.html(""),b.append(a))})}}}]).directive("tabContentTransclude",function(){function a(a){return a.tagName&&(a.hasAttribute("tab-heading")||a.hasAttribute("data-tab-heading")||"tab-heading"===a.tagName.toLowerCase()||"data-tab-heading"===a.tagName.toLowerCase())}return{restrict:"A",require:"^tabset",link:function(b,c,d){var e=b.$eval(d.tabContentTransclude);e.$transcludeFn(e.$parent,function(b){angular.forEach(b,function(b){a(b)?e.headingElement=b:c.append(b)})})}}}),angular.module("ui.bootstrap.timepicker",[]).constant("timepickerConfig",{hourStep:1,minuteStep:1,showMeridian:!0,meridians:null,readonlyInput:!1,mousewheel:!0}).controller("TimepickerController",["$scope","$attrs","$parse","$log","$locale","timepickerConfig",function(a,b,c,d,e,f){function g(){var b=parseInt(a.hours,10),c=a.showMeridian?b>0&&13>b:b>=0&&24>b;return c?(a.showMeridian&&(12===b&&(b=0),a.meridian===p[1]&&(b+=12)),b):void 0}function h(){var b=parseInt(a.minutes,10);return b>=0&&60>b?b:void 0}function i(a){return angular.isDefined(a)&&a.toString().length<2?"0"+a:a}function j(a){k(),o.$setViewValue(new Date(n)),l(a)}function k(){o.$setValidity("time",!0),a.invalidHours=!1,a.invalidMinutes=!1}function l(b){var c=n.getHours(),d=n.getMinutes();a.showMeridian&&(c=0===c||12===c?12:c%12),a.hours="h"===b?c:i(c),a.minutes="m"===b?d:i(d),a.meridian=n.getHours()<12?p[0]:p[1]}function m(a){var b=new Date(n.getTime()+6e4*a);n.setHours(b.getHours(),b.getMinutes()),j()}var n=new Date,o={$setViewValue:angular.noop},p=angular.isDefined(b.meridians)?a.$parent.$eval(b.meridians):f.meridians||e.DATETIME_FORMATS.AMPMS;this.init=function(c,d){o=c,o.$render=this.render;var e=d.eq(0),g=d.eq(1),h=angular.isDefined(b.mousewheel)?a.$parent.$eval(b.mousewheel):f.mousewheel;h&&this.setupMousewheelEvents(e,g),a.readonlyInput=angular.isDefined(b.readonlyInput)?a.$parent.$eval(b.readonlyInput):f.readonlyInput,this.setupInputEvents(e,g)};var q=f.hourStep;b.hourStep&&a.$parent.$watch(c(b.hourStep),function(a){q=parseInt(a,10)});var r=f.minuteStep;b.minuteStep&&a.$parent.$watch(c(b.minuteStep),function(a){r=parseInt(a,10)}),a.showMeridian=f.showMeridian,b.showMeridian&&a.$parent.$watch(c(b.showMeridian),function(b){if(a.showMeridian=!!b,o.$error.time){var c=g(),d=h();angular.isDefined(c)&&angular.isDefined(d)&&(n.setHours(c),j())}else l()}),this.setupMousewheelEvents=function(b,c){var d=function(a){a.originalEvent&&(a=a.originalEvent);var b=a.wheelDelta?a.wheelDelta:-a.deltaY;return a.detail||b>0};b.bind("mousewheel wheel",function(b){a.$apply(d(b)?a.incrementHours():a.decrementHours()),b.preventDefault()}),c.bind("mousewheel wheel",function(b){a.$apply(d(b)?a.incrementMinutes():a.decrementMinutes()),b.preventDefault()})},this.setupInputEvents=function(b,c){if(a.readonlyInput)return a.updateHours=angular.noop,void(a.updateMinutes=angular.noop);var d=function(b,c){o.$setViewValue(null),o.$setValidity("time",!1),angular.isDefined(b)&&(a.invalidHours=b),angular.isDefined(c)&&(a.invalidMinutes=c)};a.updateHours=function(){var a=g();angular.isDefined(a)?(n.setHours(a),j("h")):d(!0)},b.bind("blur",function(){!a.invalidHours&&a.hours<10&&a.$apply(function(){a.hours=i(a.hours)})}),a.updateMinutes=function(){var a=h();angular.isDefined(a)?(n.setMinutes(a),j("m")):d(void 0,!0)},c.bind("blur",function(){!a.invalidMinutes&&a.minutes<10&&a.$apply(function(){a.minutes=i(a.minutes)})})},this.render=function(){var a=o.$modelValue?new Date(o.$modelValue):null;isNaN(a)?(o.$setValidity("time",!1),d.error('Timepicker directive: "ng-model" value must be a Date object, a number of milliseconds since 01.01.1970 or a string representing an RFC2822 or ISO 8601 date.')):(a&&(n=a),k(),l())},a.incrementHours=function(){m(60*q)},a.decrementHours=function(){m(60*-q)},a.incrementMinutes=function(){m(r)},a.decrementMinutes=function(){m(-r)},a.toggleMeridian=function(){m(720*(n.getHours()<12?1:-1))}}]).directive("timepicker",function(){return{restrict:"EA",require:["timepicker","?^ngModel"],controller:"TimepickerController",replace:!0,scope:{},templateUrl:"template/timepicker/timepicker.html",link:function(a,b,c,d){var e=d[0],f=d[1];f&&e.init(f,b.find("input"))}}}),angular.module("ui.bootstrap.typeahead",["ui.bootstrap.position","ui.bootstrap.bindHtml"]).factory("typeaheadParser",["$parse",function(a){var b=/^\s*([\s\S]+?)(?:\s+as\s+([\s\S]+?))?\s+for\s+(?:([\$\w][\$\w\d]*))\s+in\s+([\s\S]+?)$/;return{parse:function(c){var d=c.match(b);if(!d)throw new Error('Expected typeahead specification in form of "_modelValue_ (as _label_)? for _item_ in _collection_" but got "'+c+'".');return{itemName:d[3],source:a(d[4]),viewMapper:a(d[2]||d[1]),modelMapper:a(d[1])}}}}]).directive("typeahead",["$compile","$parse","$q","$timeout","$document","$position","typeaheadParser",function(a,b,c,d,e,f,g){var h=[9,13,27,38,40];return{require:"ngModel",link:function(i,j,k,l){var m,n=i.$eval(k.typeaheadMinLength)||1,o=i.$eval(k.typeaheadWaitMs)||0,p=i.$eval(k.typeaheadEditable)!==!1,q=b(k.typeaheadLoading).assign||angular.noop,r=b(k.typeaheadOnSelect),s=k.typeaheadInputFormatter?b(k.typeaheadInputFormatter):void 0,t=k.typeaheadAppendToBody?i.$eval(k.typeaheadAppendToBody):!1,u=i.$eval(k.typeaheadFocusFirst)!==!1,v=b(k.ngModel).assign,w=g.parse(k.typeahead),x=i.$new();i.$on("$destroy",function(){x.$destroy()});var y="typeahead-"+x.$id+"-"+Math.floor(1e4*Math.random());j.attr({"aria-autocomplete":"list","aria-expanded":!1,"aria-owns":y});var z=angular.element("
");z.attr({id:y,matches:"matches",active:"activeIdx",select:"select(activeIdx)",query:"query",position:"position"}),angular.isDefined(k.typeaheadTemplateUrl)&&z.attr("template-url",k.typeaheadTemplateUrl);var A=function(){x.matches=[],x.activeIdx=-1,j.attr("aria-expanded",!1)},B=function(a){return y+"-option-"+a};x.$watch("activeIdx",function(a){0>a?j.removeAttr("aria-activedescendant"):j.attr("aria-activedescendant",B(a))});var C=function(a){var b={$viewValue:a};q(i,!0),c.when(w.source(i,b)).then(function(c){var d=a===l.$viewValue;if(d&&m)if(c.length>0){x.activeIdx=u?0:-1,x.matches.length=0;for(var e=0;e=n?o>0?(F(),E(a)):C(a):(q(i,!1),F(),A()),p?a:a?void l.$setValidity("editable",!1):(l.$setValidity("editable",!0),a)}),l.$formatters.push(function(a){var b,c,d={};return s?(d.$model=a,s(i,d)):(d[w.itemName]=a,b=w.viewMapper(i,d),d[w.itemName]=void 0,c=w.viewMapper(i,d),b!==c?b:a)}),x.select=function(a){var b,c,e={};e[w.itemName]=c=x.matches[a].model,b=w.modelMapper(i,e),v(i,b),l.$setValidity("editable",!0),r(i,{$item:c,$model:b,$label:w.viewMapper(i,e)}),A(),d(function(){j[0].focus()},0,!1)},j.bind("keydown",function(a){0!==x.matches.length&&-1!==h.indexOf(a.which)&&(-1!=x.activeIdx||13!==a.which&&9!==a.which)&&(a.preventDefault(),40===a.which?(x.activeIdx=(x.activeIdx+1)%x.matches.length,x.$digest()):38===a.which?(x.activeIdx=(x.activeIdx>0?x.activeIdx:x.matches.length)-1,x.$digest()):13===a.which||9===a.which?x.$apply(function(){x.select(x.activeIdx)}):27===a.which&&(a.stopPropagation(),A(),x.$digest()))}),j.bind("blur",function(){m=!1});var G=function(a){j[0]!==a.target&&(A(),x.$digest())};e.bind("click",G),i.$on("$destroy",function(){e.unbind("click",G),t&&H.remove()});var H=a(z)(x);t?e.find("body").append(H):j.after(H)}}}]).directive("typeaheadPopup",function(){return{restrict:"EA",scope:{matches:"=",query:"=",active:"=",position:"=",select:"&"},replace:!0,templateUrl:"template/typeahead/typeahead-popup.html",link:function(a,b,c){a.templateUrl=c.templateUrl,a.isOpen=function(){return a.matches.length>0},a.isActive=function(b){return a.active==b},a.selectActive=function(b){a.active=b},a.selectMatch=function(b){a.select({activeIdx:b})}}}}).directive("typeaheadMatch",["$http","$templateCache","$compile","$parse",function(a,b,c,d){return{restrict:"EA",scope:{index:"=",match:"=",query:"="},link:function(e,f,g){var h=d(g.templateUrl)(e.$parent)||"template/typeahead/typeahead-match.html";a.get(h,{cache:b}).success(function(a){f.replaceWith(c(a.trim())(e))})}}}]).filter("typeaheadHighlight",function(){function a(a){return a.replace(/([.?*+^$[\]\\(){}|-])/g,"\\$1")}return function(b,c){return c?(""+b).replace(new RegExp(a(c),"gi"),"$&"):b}}),angular.module("template/accordion/accordion-group.html",[]).run(["$templateCache",function(a){a.put("template/accordion/accordion-group.html",'
\n
\n

\n {{heading}}\n

\n
\n
\n
\n
\n
\n')}]),angular.module("template/accordion/accordion.html",[]).run(["$templateCache",function(a){a.put("template/accordion/accordion.html",'
')}]),angular.module("template/alert/alert.html",[]).run(["$templateCache",function(a){a.put("template/alert/alert.html",'\n') +}]),angular.module("template/carousel/carousel.html",[]).run(["$templateCache",function(a){a.put("template/carousel/carousel.html",'\n')}]),angular.module("template/carousel/slide.html",[]).run(["$templateCache",function(a){a.put("template/carousel/slide.html","
\n")}]),angular.module("template/datepicker/datepicker.html",[]).run(["$templateCache",function(a){a.put("template/datepicker/datepicker.html",'
\n \n \n \n
')}]),angular.module("template/datepicker/day.html",[]).run(["$templateCache",function(a){a.put("template/datepicker/day.html",'\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n
{{label.abbr}}
{{ weekNumbers[$index] }}\n \n
\n')}]),angular.module("template/datepicker/month.html",[]).run(["$templateCache",function(a){a.put("template/datepicker/month.html",'\n \n \n \n \n \n \n \n \n \n \n \n \n
\n \n
\n')}]),angular.module("template/datepicker/popup.html",[]).run(["$templateCache",function(a){a.put("template/datepicker/popup.html",'\n')}]),angular.module("template/datepicker/year.html",[]).run(["$templateCache",function(a){a.put("template/datepicker/year.html",'\n \n \n \n \n \n \n \n \n \n \n \n \n
\n \n
\n')}]),angular.module("template/modal/backdrop.html",[]).run(["$templateCache",function(a){a.put("template/modal/backdrop.html",'\n')}]),angular.module("template/modal/window.html",[]).run(["$templateCache",function(a){a.put("template/modal/window.html",'')}]),angular.module("template/pagination/pager.html",[]).run(["$templateCache",function(a){a.put("template/pagination/pager.html",'')}]),angular.module("template/pagination/pagination.html",[]).run(["$templateCache",function(a){a.put("template/pagination/pagination.html",'')}]),angular.module("template/tooltip/tooltip-html-unsafe-popup.html",[]).run(["$templateCache",function(a){a.put("template/tooltip/tooltip-html-unsafe-popup.html",'
\n
\n
\n
\n')}]),angular.module("template/tooltip/tooltip-popup.html",[]).run(["$templateCache",function(a){a.put("template/tooltip/tooltip-popup.html",'
\n
\n
\n
\n')}]),angular.module("template/popover/popover.html",[]).run(["$templateCache",function(a){a.put("template/popover/popover.html",'
\n
\n\n
\n

\n
\n
\n
\n')}]),angular.module("template/progressbar/bar.html",[]).run(["$templateCache",function(a){a.put("template/progressbar/bar.html",'
')}]),angular.module("template/progressbar/progress.html",[]).run(["$templateCache",function(a){a.put("template/progressbar/progress.html",'
')}]),angular.module("template/progressbar/progressbar.html",[]).run(["$templateCache",function(a){a.put("template/progressbar/progressbar.html",'
\n
\n
')}]),angular.module("template/rating/rating.html",[]).run(["$templateCache",function(a){a.put("template/rating/rating.html",'\n \n ({{ $index < value ? \'*\' : \' \' }})\n \n')}]),angular.module("template/tabs/tab.html",[]).run(["$templateCache",function(a){a.put("template/tabs/tab.html",'
  • \n {{heading}}\n
  • \n')}]),angular.module("template/tabs/tabset.html",[]).run(["$templateCache",function(a){a.put("template/tabs/tabset.html",'
    \n \n
    \n
    \n
    \n
    \n
    \n')}]),angular.module("template/timepicker/timepicker.html",[]).run(["$templateCache",function(a){a.put("template/timepicker/timepicker.html",'\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n
     
    \n \n :\n \n
     
    \n')}]),angular.module("template/typeahead/typeahead-match.html",[]).run(["$templateCache",function(a){a.put("template/typeahead/typeahead-match.html",'')}]),angular.module("template/typeahead/typeahead-popup.html",[]).run(["$templateCache",function(a){a.put("template/typeahead/typeahead-popup.html",'\n')}]),c("angular-bootstrap-tpls",["angular","angular-bootstrap"],function(){}),!function(a,b){b["true"]=a,angular.module("textAngularSetup",[]).value("taOptions",{toolbar:[["h1","h2","h3","h4","h5","h6","p","pre","quote"],["bold","italics","underline","ul","ol","redo","undo","clear"],["justifyLeft","justifyCenter","justifyRight","indent","outdent"],["html","insertImage","insertLink","insertVideo"]],classes:{focussed:"focussed",toolbar:"btn-toolbar",toolbarGroup:"btn-group",toolbarButton:"btn btn-default",toolbarButtonActive:"active",disabled:"disabled",textEditor:"form-control",htmlEditor:"form-control"},setup:{textEditorSetup:function(){},htmlEditorSetup:function(){}},defaultFileDropHandler:function(a,b){var c=new FileReader;return"image"===a.type.substring(0,5)?(c.onload=function(){""!==c.result&&b("insertImage",c.result,!0)},c.readAsDataURL(a),!0):!1}}).value("taSelectableElements",["a","img"]).value("taCustomRenderers",[{selector:"img",customAttribute:"ta-insert-video",renderLogic:function(a){var b=angular.element(""),c=a.prop("attributes");angular.forEach(c,function(a){b.attr(a.name,a.value)}),b.attr("src",b.attr("ta-insert-video")),a.replaceWith(b)}}]).constant("taTranslations",{html:{buttontext:"Toggle HTML",tooltip:"Toggle html / Rich Text"},heading:{tooltip:"Heading "},p:{tooltip:"Paragraph"},pre:{tooltip:"Preformatted text"},ul:{tooltip:"Unordered List"},ol:{tooltip:"Ordered List"},quote:{tooltip:"Quote/unqoute selection or paragraph"},undo:{tooltip:"Undo"},redo:{tooltip:"Redo"},bold:{tooltip:"Bold"},italic:{tooltip:"Italic"},underline:{tooltip:"Underline"},justifyLeft:{tooltip:"Align text left"},justifyRight:{tooltip:"Align text right"},justifyCenter:{tooltip:"Center"},indent:{tooltip:"Increase indent"},outdent:{tooltip:"Decrease indent"},clear:{tooltip:"Clear formatting"},insertImage:{dialogPrompt:"Please enter an image URL to insert",tooltip:"Insert image",hotkey:"the - possibly language dependent hotkey ... for some future implementation"},insertVideo:{tooltip:"Insert video",dialogPrompt:"Please enter a youtube URL to embed"},insertLink:{tooltip:"Insert / edit link",dialogPrompt:"Please enter a URL to insert"}}).run(["taRegisterTool","$window","taTranslations","taSelection",function(a,b,c,d){a("html",{buttontext:c.html.buttontext,tooltiptext:c.html.tooltip,action:function(){this.$editor().switchView()},activeState:function(){return this.$editor().showHtml}});var e=function(a){return function(){return this.$editor().queryFormatBlockState(a)}},f=function(){return this.$editor().wrapSelection("formatBlock","<"+this.name.toUpperCase()+">")};angular.forEach(["h1","h2","h3","h4","h5","h6"],function(b){a(b.toLowerCase(),{buttontext:b.toUpperCase(),tooltiptext:c.heading.tooltip+b.charAt(1),action:f,activeState:e(b.toLowerCase())})}),a("p",{buttontext:"P",tooltiptext:c.p.tooltip,action:function(){return this.$editor().wrapSelection("formatBlock","

    ")},activeState:function(){return this.$editor().queryFormatBlockState("p")}}),a("pre",{buttontext:"pre",tooltiptext:c.pre.tooltip,action:function(){return this.$editor().wrapSelection("formatBlock","

    ")},activeState:function(){return this.$editor().queryFormatBlockState("pre")}}),a("ul",{iconclass:"fa fa-list-ul",tooltiptext:c.ul.tooltip,action:function(){return this.$editor().wrapSelection("insertUnorderedList",null)},activeState:function(){return this.$editor().queryCommandState("insertUnorderedList")}}),a("ol",{iconclass:"fa fa-list-ol",tooltiptext:c.ol.tooltip,action:function(){return this.$editor().wrapSelection("insertOrderedList",null)},activeState:function(){return this.$editor().queryCommandState("insertOrderedList")}}),a("quote",{iconclass:"fa fa-quote-right",tooltiptext:c.quote.tooltip,action:function(){return this.$editor().wrapSelection("formatBlock","
    ")},activeState:function(){return this.$editor().queryFormatBlockState("blockquote")}}),a("undo",{iconclass:"fa fa-undo",tooltiptext:c.undo.tooltip,action:function(){return this.$editor().wrapSelection("undo",null)}}),a("redo",{iconclass:"fa fa-repeat",tooltiptext:c.redo.tooltip,action:function(){return this.$editor().wrapSelection("redo",null)}}),a("bold",{iconclass:"fa fa-bold",tooltiptext:c.bold.tooltip,action:function(){return this.$editor().wrapSelection("bold",null)},activeState:function(){return this.$editor().queryCommandState("bold")},commandKeyCode:98}),a("justifyLeft",{iconclass:"fa fa-align-left",tooltiptext:c.justifyLeft.tooltip,action:function(){return this.$editor().wrapSelection("justifyLeft",null)},activeState:function(a){var b=!1;return a&&(b="left"===a.css("text-align")||"left"===a.attr("align")||"right"!==a.css("text-align")&&"center"!==a.css("text-align")&&!this.$editor().queryCommandState("justifyRight")&&!this.$editor().queryCommandState("justifyCenter")),b=b||this.$editor().queryCommandState("justifyLeft")}}),a("justifyRight",{iconclass:"fa fa-align-right",tooltiptext:c.justifyRight.tooltip,action:function(){return this.$editor().wrapSelection("justifyRight",null)},activeState:function(a){var b=!1;return a&&(b="right"===a.css("text-align")),b=b||this.$editor().queryCommandState("justifyRight")}}),a("justifyCenter",{iconclass:"fa fa-align-center",tooltiptext:c.justifyCenter.tooltip,action:function(){return this.$editor().wrapSelection("justifyCenter",null)},activeState:function(a){var b=!1;return a&&(b="center"===a.css("text-align")),b=b||this.$editor().queryCommandState("justifyCenter")}}),a("indent",{iconclass:"fa fa-indent",tooltiptext:c.indent.tooltip,action:function(){return this.$editor().wrapSelection("indent",null)},activeState:function(){return this.$editor().queryFormatBlockState("blockquote")}}),a("outdent",{iconclass:"fa fa-outdent",tooltiptext:c.outdent.tooltip,action:function(){return this.$editor().wrapSelection("outdent",null)},activeState:function(){return!1}}),a("italics",{iconclass:"fa fa-italic",tooltiptext:c.italic.tooltip,action:function(){return this.$editor().wrapSelection("italic",null)},activeState:function(){return this.$editor().queryCommandState("italic")},commandKeyCode:105}),a("underline",{iconclass:"fa fa-underline",tooltiptext:c.underline.tooltip,action:function(){return this.$editor().wrapSelection("underline",null)},activeState:function(){return this.$editor().queryCommandState("underline")},commandKeyCode:117}),a("clear",{iconclass:"fa fa-ban",tooltiptext:c.clear.tooltip,action:function(a,b){this.$editor().wrapSelection("removeFormat",null);var c=angular.element(d.getSelectionElement()),e=function(a){a=angular.element(a);var b=a;angular.forEach(a.children(),function(a){var c=angular.element("

    ");c.html(angular.element(a).html()),b.after(c),b=c}),a.remove()};angular.forEach(c.find("ul"),e),angular.forEach(c.find("ol"),e);var f=this.$editor(),g=function(a){a=angular.element(a),a[0]!==f.displayElements.text[0]&&a.removeAttr("class"),angular.forEach(a.children(),g)};angular.forEach(c,g),"li"!==c[0].tagName.toLowerCase()&&"ol"!==c[0].tagName.toLowerCase()&&"ul"!==c[0].tagName.toLowerCase()&&this.$editor().wrapSelection("formatBlock","

    "),b()}});var g=function(a,b,c){var d=function(){c.updateTaBindtaTextElement(),c.hidePopover()};a.preventDefault(),c.displayElements.popover.css("width","375px");var e=c.displayElements.popoverContainer;e.empty();var f=angular.element('

    '),g=angular.element('');g.on("click",function(a){a.preventDefault(),b.css({width:"100%",height:""}),d()});var h=angular.element('');h.on("click",function(a){a.preventDefault(),b.css({width:"50%",height:""}),d()});var i=angular.element('');i.on("click",function(a){a.preventDefault(),b.css({width:"25%",height:""}),d()});var j=angular.element('');j.on("click",function(a){a.preventDefault(),b.css({width:"",height:""}),d()}),f.append(g),f.append(h),f.append(i),f.append(j),e.append(f),f=angular.element('
    ');var k=angular.element('');k.on("click",function(a){a.preventDefault(),b.css("float","left"),d()});var l=angular.element('');l.on("click",function(a){a.preventDefault(),b.css("float","right"),d()});var m=angular.element('');m.on("click",function(a){a.preventDefault(),b.css("float",""),d()}),f.append(k),f.append(m),f.append(l),e.append(f),f=angular.element('
    ');var n=angular.element('');n.on("click",function(a){a.preventDefault(),b.remove(),d()}),f.append(n),e.append(f),c.showPopover(b),c.showResizeOverlay(b)};a("insertImage",{iconclass:"fa fa-picture-o",tooltiptext:c.insertImage.tooltip,action:function(){var a;return a=b.prompt(c.insertImage.dialogPrompt,"http://"),a&&""!==a&&"http://"!==a?this.$editor().wrapSelection("insertImage",a,!0):void 0},onElementSelect:{element:"img",action:g}}),a("insertVideo",{iconclass:"fa fa-youtube-play",tooltiptext:c.insertVideo.tooltip,action:function(){var a;if(a=b.prompt(c.insertVideo.dialogPrompt,"http://"),a&&""!==a&&"http://"!==a){var d=a.match(/(\?|&)v=[^&]*/);if(d.length>0){var e="http://www.youtube.com/embed/"+d[0].substring(3),f='';return this.$editor().wrapSelection("insertHTML",f,!0)}}},onElementSelect:{element:"img",onlyWithAttrs:["ta-insert-video"],action:g}}),a("insertLink",{tooltiptext:c.insertLink.tooltip,iconclass:"fa fa-link",action:function(){var a;return a=b.prompt(c.insertLink.dialogPrompt,"http://"),a&&""!==a&&"http://"!==a?this.$editor().wrapSelection("createLink",a,!0):void 0},activeState:function(a){return a?"A"===a[0].tagName:!1},onElementSelect:{element:"a",action:function(a,d,e){a.preventDefault(),e.displayElements.popover.css("width","435px");var f=e.displayElements.popoverContainer;f.empty(),f.css("line-height","28px");var g=angular.element(''+d.attr("href")+"");g.css({display:"inline-block","max-width":"200px",overflow:"hidden","text-overflow":"ellipsis","white-space":"nowrap","vertical-align":"middle"}),f.append(g);var h=angular.element('
    '),i=angular.element('');i.on("click",function(a){a.preventDefault();var f=b.prompt(c.insertLink.dialogPrompt,d.attr("href"));f&&""!==f&&"http://"!==f&&(d.attr("href",f),e.updateTaBindtaTextElement()),e.hidePopover()}),h.append(i);var j=angular.element('');j.on("click",function(a){a.preventDefault(),d.replaceWith(d.contents()),e.updateTaBindtaTextElement(),e.hidePopover()}),h.append(j);var k=angular.element('');"_blank"===d.attr("target")&&k.addClass("active"),k.on("click",function(a){a.preventDefault(),d.attr("target","_blank"===d.attr("target")?"":"_blank"),k.toggleClass("active"),e.updateTaBindtaTextElement()}),h.append(k),f.append(h),e.showPopover(d)}}})}]),function(){"Use Strict";function a(a){try{return 0!==angular.element(a).length}catch(b){return!1}}function b(a,c){var d=[],e=a.children();return e.length&&angular.forEach(e,function(a){d=d.concat(b(angular.element(a),c))}),void 0!==a.attr(c)&&d.push(a),d}function c(b,c){if(!b||""===b||n.hasOwnProperty(b))throw"textAngular Error: A unique name is required for a Tool Definition";if(c.display&&(""===c.display||!a(c.display))||!c.display&&!c.buttontext&&!c.iconclass)throw'textAngular Error: Tool Definition for "'+b+'" does not have a valid display/iconclass/buttontext value';n[b]=c}var d=!1;/AppleWebKit\/([\d.]+)/.exec(navigator.userAgent)&&(document.addEventListener("click",function(){var a=window.event.target;if(d&&null!==a){for(var b=!1,c=a;null!==c&&"html"!==c.tagName.toLowerCase()&&!b;)b="true"===c.contentEditable,c=c.parentNode;b||(document.getElementById("textAngular-editableFix-010203040506070809").setSelectionRange(0,0),a.focus())}d=!1},!1),angular.element(document).ready(function(){angular.element(document.body).append(angular.element(''))}));var e=function(){var a,b=-1,c=window.navigator.userAgent,d=c.indexOf("MSIE "),e=c.indexOf("Trident/");if(d>0)b=parseInt(c.substring(d+5,c.indexOf(".",d)),10);else if(e>0){var f=c.indexOf("rv:");b=parseInt(c.substring(f+3,c.indexOf(".",f)),10)}return b>-1?b:a}();"function"!=typeof String.prototype.trim&&(String.prototype.trim=function(){return this.replace(/^\s\s*/,"").replace(/\s\s*$/,"")});var f,g,h,i,j;if(e>8||void 0===e){var k=function(){var a=document.createElement("style");return/AppleWebKit\/([\d.]+)/.exec(navigator.userAgent)&&a.appendChild(document.createTextNode("")),document.head.insertBefore(a,document.head.firstChild),a.sheet}();f=function(){var a=document.createElement("style");return/AppleWebKit\/([\d.]+)/.exec(navigator.userAgent)&&a.appendChild(document.createTextNode("")),document.head.appendChild(a),a.sheet}(),g=function(a,b){i(f,a,b)},i=function(a,b,c){var d;return a.rules?d=Math.max(a.rules.length-1,0):a.cssRules&&(d=Math.max(a.cssRules.length-1,0)),a.insertRule?a.insertRule(b+"{"+c+"}",d):a.addRule(b,c,d),d},h=function(a){j(f,a)},j=function(a,b){a.removeRule?a.removeRule(b):a.deleteRule(b)},i(k,".ta-scroll-window.form-control","height: auto; min-height: 300px; overflow: auto; font-family: inherit; font-size: 100%; position: relative; padding: 0;"),i(k,".ta-root.focussed .ta-scroll-window.form-control","border-color: #66afe9; outline: 0; -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(102, 175, 233, 0.6);"),i(k,".ta-editor.ta-html","min-height: 300px; height: auto; overflow: auto; font-family: inherit; font-size: 100%;"),i(k,".ta-scroll-window > .ta-bind","height: auto; min-height: 300px; padding: 6px 12px;"),i(k,".ta-root .ta-resizer-handle-overlay","z-index: 100; position: absolute; display: none;"),i(k,".ta-root .ta-resizer-handle-overlay > .ta-resizer-handle-info","position: absolute; bottom: 16px; right: 16px; border: 1px solid black; background-color: #FFF; padding: 0 4px; opacity: 0.7;"),i(k,".ta-root .ta-resizer-handle-overlay > .ta-resizer-handle-background","position: absolute; bottom: 5px; right: 5px; left: 5px; top: 5px; border: 1px solid black; background-color: rgba(0, 0, 0, 0.2);"),i(k,".ta-root .ta-resizer-handle-overlay > .ta-resizer-handle-corner","width: 10px; height: 10px; position: absolute;"),i(k,".ta-root .ta-resizer-handle-overlay > .ta-resizer-handle-corner-tl","top: 0; left: 0; border-left: 1px solid black; border-top: 1px solid black;"),i(k,".ta-root .ta-resizer-handle-overlay > .ta-resizer-handle-corner-tr","top: 0; right: 0; border-right: 1px solid black; border-top: 1px solid black;"),i(k,".ta-root .ta-resizer-handle-overlay > .ta-resizer-handle-corner-bl","bottom: 0; left: 0; border-left: 1px solid black; border-bottom: 1px solid black;"),i(k,".ta-root .ta-resizer-handle-overlay > .ta-resizer-handle-corner-br","bottom: 0; right: 0; border: 1px solid black; cursor: se-resize; background-color: white;")}var l=!1,m=angular.module("textAngular",["ngSanitize","textAngularSetup"]),n={};m.constant("taRegisterTool",c),m.value("taTools",n),m.config([function(){angular.forEach(n,function(a,b){delete n[b]})}]),m.directive("textAngular",["$compile","$timeout","taOptions","taSelection","taExecCommand","textAngularManager","$window","$document","$animate","$log",function(a,b,c,d,e,f,g,h,i,j){return{require:"?ngModel",scope:{},restrict:"EA",link:function(k,l,m,n){var o,p,q,r,s,t,u,v,w,x=m.serial?m.serial:Math.floor(1e16*Math.random()),y=m.name?m.name:"textAngularEditor"+x,z=function(a,c,d){b(function(){var b=function(){a.off(c,b),d()};a.on(c,b)},100)};w=e(m.taDefaultWrap),angular.extend(k,angular.copy(c),{wrapSelection:function(a,b,c){w(a,!1,b),c&&k["reApplyOnSelectorHandlerstaTextElement"+x](),k.displayElements.text[0].focus() +},showHtml:!1}),m.taFocussedClass&&(k.classes.focussed=m.taFocussedClass),m.taTextEditorClass&&(k.classes.textEditor=m.taTextEditorClass),m.taHtmlEditorClass&&(k.classes.htmlEditor=m.taHtmlEditorClass),m.taTextEditorSetup&&(k.setup.textEditorSetup=k.$parent.$eval(m.taTextEditorSetup)),m.taHtmlEditorSetup&&(k.setup.htmlEditorSetup=k.$parent.$eval(m.taHtmlEditorSetup)),k.fileDropHandler=m.taFileDrop?k.$parent.$eval(m.taFileDrop):k.defaultFileDropHandler,u=l[0].innerHTML,l[0].innerHTML="",k.displayElements={forminput:angular.element(""),html:angular.element(""),text:angular.element("
    "),scrollWindow:angular.element("
    "),popover:angular.element('
    '),popoverArrow:angular.element('
    '),popoverContainer:angular.element('
    '),resize:{overlay:angular.element('
    '),background:angular.element('
    '),anchors:[angular.element('
    '),angular.element('
    '),angular.element('
    '),angular.element('
    ')],info:angular.element('
    ')}},k.displayElements.popover.append(k.displayElements.popoverArrow),k.displayElements.popover.append(k.displayElements.popoverContainer),k.displayElements.scrollWindow.append(k.displayElements.popover),k.displayElements.popover.on("mousedown",function(a,b){return b&&angular.extend(a,b),a.preventDefault(),!1}),k.showPopover=function(a){k.displayElements.popover.css("display","block"),k.reflowPopover(a),i.addClass(k.displayElements.popover,"in"),z(l,"click keyup",function(){k.hidePopover()})},k.reflowPopover=function(a){k.displayElements.text[0].offsetHeight-51>a[0].offsetTop?(k.displayElements.popover.css("top",a[0].offsetTop+a[0].offsetHeight+"px"),k.displayElements.popover.removeClass("top").addClass("bottom")):(k.displayElements.popover.css("top",a[0].offsetTop-54+"px"),k.displayElements.popover.removeClass("bottom").addClass("top"));var b=k.displayElements.text[0].offsetWidth-k.displayElements.popover[0].offsetWidth,c=a[0].offsetLeft+a[0].offsetWidth/2-k.displayElements.popover[0].offsetWidth/2;k.displayElements.popover.css("left",Math.max(0,Math.min(b,c))+"px"),k.displayElements.popoverArrow.css("margin-left",Math.min(c,Math.max(0,c-b))-11+"px")},k.hidePopover=function(){i.removeClass(k.displayElements.popover,"in",function(){k.displayElements.popover.css("display",""),k.displayElements.popoverContainer.attr("style",""),k.displayElements.popoverContainer.attr("class","popover-content")})},k.displayElements.resize.overlay.append(k.displayElements.resize.background),angular.forEach(k.displayElements.resize.anchors,function(a){k.displayElements.resize.overlay.append(a)}),k.displayElements.resize.overlay.append(k.displayElements.resize.info),k.displayElements.scrollWindow.append(k.displayElements.resize.overlay),k.reflowResizeOverlay=function(a){a=angular.element(a)[0],k.displayElements.resize.overlay.css({display:"block",left:a.offsetLeft-5+"px",top:a.offsetTop-5+"px",width:a.offsetWidth+10+"px",height:a.offsetHeight+10+"px"}),k.displayElements.resize.info.text(a.offsetWidth+" x "+a.offsetHeight)},k.showResizeOverlay=function(a){var b=function(b){var c={width:parseInt(a.attr("width")),height:parseInt(a.attr("height")),x:b.clientX,y:b.clientY};void 0===c.width&&(c.width=a[0].offsetWidth),void 0===c.height&&(c.height=a[0].offsetHeight),k.hidePopover();var d=c.height/c.width,e=function(b){var e={x:Math.max(0,c.width+(b.clientX-c.x)),y:Math.max(0,c.height+(b.clientY-c.y))},f=function(a,b){a=angular.element(a),"img"===a[0].tagName.toLowerCase()&&(b.height&&(a.attr("height",b.height),delete b.height),b.width&&(a.attr("width",b.width),delete b.width)),a.css(b)};if(b.shiftKey){var g=e.y/e.x;f(a,{width:d>g?e.x:e.y/d,height:d>g?e.x*d:e.y})}else f(a,{width:e.x,height:e.y});k.reflowResizeOverlay(a)};h.find("body").on("mousemove",e),z(k.displayElements.resize.overlay,"mouseup",function(){h.find("body").off("mousemove",e),k.showPopover(a)}),b.stopPropagation(),b.preventDefault()};k.displayElements.resize.anchors[3].on("mousedown",b),k.reflowResizeOverlay(a),z(l,"click",function(){k.hideResizeOverlay()})},k.hideResizeOverlay=function(){k.displayElements.resize.overlay.css("display","")},k.setup.htmlEditorSetup(k.displayElements.html),k.setup.textEditorSetup(k.displayElements.text),k.displayElements.html.attr({id:"taHtmlElement"+x,"ng-show":"showHtml","ta-bind":"ta-bind","ng-model":"html"}),k.displayElements.text.attr({id:"taTextElement"+x,contentEditable:"true","ta-bind":"ta-bind","ng-model":"html"}),k.displayElements.scrollWindow.attr({"ng-hide":"showHtml"}),m.taDefaultWrap&&k.displayElements.text.attr("ta-default-wrap",m.taDefaultWrap),m.taUnsafeSanitizer&&(k.displayElements.text.attr("ta-unsafe-sanitizer",m.taUnsafeSanitizer),k.displayElements.html.attr("ta-unsafe-sanitizer",m.taUnsafeSanitizer)),k.displayElements.scrollWindow.append(k.displayElements.text),l.append(k.displayElements.scrollWindow),l.append(k.displayElements.html),k.displayElements.forminput.attr("name",y),l.append(k.displayElements.forminput),m.tabindex&&(l.removeAttr("tabindex"),k.displayElements.text.attr("tabindex",m.tabindex),k.displayElements.html.attr("tabindex",m.tabindex)),m.placeholder&&(k.displayElements.text.attr("placeholder",m.placeholder),k.displayElements.html.attr("placeholder",m.placeholder)),m.taDisabled&&(k.displayElements.text.attr("ta-readonly","disabled"),k.displayElements.html.attr("ta-readonly","disabled"),k.disabled=k.$parent.$eval(m.taDisabled),k.$parent.$watch(m.taDisabled,function(a){k.disabled=a,k.disabled?l.addClass(k.classes.disabled):l.removeClass(k.classes.disabled)})),a(k.displayElements.scrollWindow)(k),a(k.displayElements.html)(k),k.updateTaBindtaTextElement=k["updateTaBindtaTextElement"+x],k.updateTaBindtaHtmlElement=k["updateTaBindtaHtmlElement"+x],l.addClass("ta-root"),k.displayElements.scrollWindow.addClass("ta-text ta-editor "+k.classes.textEditor),k.displayElements.html.addClass("ta-html ta-editor "+k.classes.htmlEditor),k._actionRunning=!1;var A=!1;if(k.startAction=function(){return k._actionRunning=!0,g.rangy&&g.rangy.saveSelection?(A=g.rangy.saveSelection(),function(){A&&g.rangy.restoreSelection(A)}):void 0},k.endAction=function(){k._actionRunning=!1,A&&g.rangy.removeMarkers(A),A=!1,k.updateSelectedStyles(),k.showHtml||k["updateTaBindtaTextElement"+x]()},s=function(){l.addClass(k.classes.focussed),v.focus()},k.displayElements.html.on("focus",s),k.displayElements.text.on("focus",s),t=function(a){return k._actionRunning||h[0].activeElement===k.displayElements.html[0]||h[0].activeElement===k.displayElements.text[0]||(l.removeClass(k.classes.focussed),v.unfocus(),b(function(){l.triggerHandler("blur")},0)),a.preventDefault(),!1},k.displayElements.html.on("blur",t),k.displayElements.text.on("blur",t),k.queryFormatBlockState=function(a){return!k.showHtml&&a.toLowerCase()===h[0].queryCommandValue("formatBlock").toLowerCase()},k.queryCommandState=function(a){return k.showHtml?"":h[0].queryCommandState(a)},k.switchView=function(){k.showHtml=!k.showHtml,k.showHtml?b(function(){return k.displayElements.html[0].focus()},100):b(function(){return k.displayElements.text[0].focus()},100)},m.ngModel){var B=!0;n.$render=function(){if(B){B=!1;var a=k.$parent.$eval(m.ngModel);void 0!==a&&null!==a||!u||""===u||n.$setViewValue(u)}k.displayElements.forminput.val(n.$viewValue),k._elementSelectTriggered||h[0].activeElement===k.displayElements.html[0]||h[0].activeElement===k.displayElements.text[0]||(k.html=n.$viewValue||"")};var C=function(a){return m.required&&n.$setValidity("required",!(!a||""===a.trim())),a};n.$parsers.push(C),n.$formatters.push(C)}else k.displayElements.forminput.val(u),k.html=u;if(k.$watch("html",function(a,b){a!==b&&(m.ngModel&&n.$viewValue!==a&&n.$setViewValue(a),k.displayElements.forminput.val(a))}),m.taTargetToolbars)v=f.registerEditor(y,k,m.taTargetToolbars.split(","));else{var D=angular.element('
    ');m.taToolbar&&D.attr("ta-toolbar",m.taToolbar),m.taToolbarClass&&D.attr("ta-toolbar-class",m.taToolbarClass),m.taToolbarGroupClass&&D.attr("ta-toolbar-group-class",m.taToolbarGroupClass),m.taToolbarButtonClass&&D.attr("ta-toolbar-button-class",m.taToolbarButtonClass),m.taToolbarActiveButtonClass&&D.attr("ta-toolbar-active-button-class",m.taToolbarActiveButtonClass),m.taFocussedClass&&D.attr("ta-focussed-class",m.taFocussedClass),l.prepend(D),a(D)(k.$parent),v=f.registerEditor(y,k,["textAngularToolbar"+x])}k.$on("$destroy",function(){f.unregisterEditor(y)}),k.$on("ta-element-select",function(a,b){v.triggerElementSelect(a,b)}),k.$on("ta-drop-event",function(a,b,c,d){k.displayElements.text[0].focus(),d&&d.files&&d.files.length>0&&(angular.forEach(d.files,function(a){try{return k.fileDropHandler(a,k.wrapSelection)||k.fileDropHandler!==k.defaultFileDropHandler&&k.defaultFileDropHandler(a,k.wrapSelection)}catch(b){j.error(b)}}),c.preventDefault(),c.stopPropagation())}),k._bUpdateSelectedStyles=!1,k.updateSelectedStyles=function(){var a;void 0!==(a=d.getSelectionElement())&&a.parentNode!==k.displayElements.text[0]?v.updateSelectedStyles(angular.element(a)):v.updateSelectedStyles(),k._bUpdateSelectedStyles&&b(k.updateSelectedStyles,200)},o=function(){k._bUpdateSelectedStyles||(k._bUpdateSelectedStyles=!0,k.$apply(function(){k.updateSelectedStyles()}))},k.displayElements.html.on("keydown",o),k.displayElements.text.on("keydown",o),p=function(){k._bUpdateSelectedStyles=!1},k.displayElements.html.on("keyup",p),k.displayElements.text.on("keyup",p),q=function(a,b){b&&angular.extend(a,b),k.$apply(function(){return v.sendKeyCommand(a)?(k._bUpdateSelectedStyles||k.updateSelectedStyles(),a.preventDefault(),!1):void 0})},k.displayElements.html.on("keypress",q),k.displayElements.text.on("keypress",q),r=function(){k._bUpdateSelectedStyles=!1,k.$apply(function(){k.updateSelectedStyles()})},k.displayElements.html.on("mouseup",r),k.displayElements.text.on("mouseup",r)}}}]).factory("taBrowserTag",[function(){return function(a){return a?""===a?void 0===e?"div":8>=e?"P":"p":8>=e?a.toUpperCase():a:8>=e?"P":"p"}}]).factory("taExecCommand",["taSelection","taBrowserTag","$document",function(a,b,c){var d=/^(address|article|aside|audio|blockquote|canvas|dd|div|dl|fieldset|figcaption|figure|footer|form|h1|h2|h3|h4|h5|h6|header|hgroup|hr|noscript|ol|output|p|pre|section|table|tfoot|ul|video)$/gi,e=/^(ul|li|ol)$/gi,f=function(b,c){var d,e,f=b.find("li");for(e=f.length-1;e>=0;e--)d=angular.element("<"+c+">"+f[e].innerHTML+""),b.after(d);b.remove(),a.setSelectionToElementEnd(d[0])},g=function(b,c){var d=angular.element("<"+c+">"+b[0].innerHTML+"");b.after(d),b.remove(),a.setSelectionToElementEnd(d.find("li")[0])},h=function(c,d,e){for(var f="",g=0;g"+c[g].innerHTML+"";var h=angular.element("<"+e+">"+f+"");d.after(h),d.remove(),a.setSelectionToElementEnd(h.find("li")[0])};return function(i){return i=b(i),function(j,k,l){var m,n,o,p,q,r=angular.element("<"+i+">"),s=a.getSelectionElement(),t=angular.element(s);if(void 0!==s){var u=s.tagName.toLowerCase();if("insertorderedlist"===j.toLowerCase()||"insertunorderedlist"===j.toLowerCase()){var v=b("insertorderedlist"===j.toLowerCase()?"ol":"ul");if(u===v)return f(t,i);if("li"===u&&t.parent()[0].tagName.toLowerCase()===v&&1===t.parent().children().length)return f(t.parent(),i);if("li"===u&&t.parent()[0].tagName.toLowerCase()!==v&&1===t.parent().children().length)return g(t.parent(),v);if(u.match(d)&&!t.hasClass("ta-bind")){if("ol"===u||"ul"===u)return g(t,v);var w=!1;return angular.forEach(t.children(),function(a){a.tagName.match(d)&&(w=!0)}),w?h(t.children(),t,v):h([angular.element("
    "+s.innerHTML+"
    ")[0]],t,v)}if(u.match(d)){if(p=a.getOnlySelectedElements(),1===p.length&&("ol"===p[0].tagName.toLowerCase()||"ul"===p[0].tagName.toLowerCase()))return p[0].tagName.toLowerCase()===v?f(angular.element(p[0]),i):g(angular.element(p[0]),v);o="";var x=[];for(m=0;m"+y[0].innerHTML+"",x.unshift(y)}return n=angular.element("<"+v+">"+o+""),x.pop().replaceWith(n),angular.forEach(x,function(a){a.remove()}),void a.setSelectionToElementEnd(n[0])}}else if("formatblock"===j.toLowerCase()){var z=l.toLowerCase().replace(/[<>]/gi,"");for(n="li"===u?t.parent():t;!n[0].tagName.match(d);)n=n.parent(),u=n[0].tagName.toLowerCase();if(u===z){p=n.children();var A=!1;for(m=0;m"),r[0].innerHTML=D[m].outerHTML,D[m]=r[0]),C.parent()[0].insertBefore(D[m],C[0]);C.remove()}return void a.setSelectionToElementEnd(n[0])}}try{c[0].execCommand(j,k,l)}catch(E){}}}}]).directive("taBind",["taSanitize","$timeout","$window","$document","taFixChrome","taBrowserTag","taSelection","taSelectableElements","taApplyCustomRenderers","taOptions",function(a,b,c,f,i,j,k,m,n,o){return{require:"ngModel",scope:{},link:function(j,p,q,r){var s,t,u=void 0!==p.attr("contenteditable")&&p.attr("contenteditable"),v=u||"textarea"===p[0].tagName.toLowerCase()||"input"===p[0].tagName.toLowerCase(),w=!1,x=!1,y=q.taUnsafeSanitizer||o.disableSanitizer;void 0===q.taDefaultWrap&&(q.taDefaultWrap="p"),""===q.taDefaultWrap?(s="",t=void 0===e?"

    ":e>=11?"


    ":8>=e?"

     

    ":"

     

    "):(s=void 0===e||e>=11?"<"+q.taDefaultWrap+">
    ":8>=e?"<"+q.taDefaultWrap.toUpperCase()+">":"<"+q.taDefaultWrap+">",t=void 0===e||e>=11?"<"+q.taDefaultWrap+">
    ":8>=e?"<"+q.taDefaultWrap.toUpperCase()+"> ":"<"+q.taDefaultWrap+"> "),p.addClass("ta-bind");var z=function(){if(u)return p[0].innerHTML;if(v)return p.val();throw"textAngular Error: attempting to update non-editable taBind"},A=function(a){a||(a=z()),a===t?""!==r.$viewValue&&r.$setViewValue(""):r.$viewValue!==a&&r.$setViewValue(a)};if(j.$parent["updateTaBind"+(q.id||"")]=function(){w||A()},v)if(u){if(p.on("cut",function(a){w?a.preventDefault():b(function(){A()},0)}),p.on("paste",function(a,b){b&&angular.extend(a,b);var d;if(a.clipboardData||a.originalEvent&&a.originalEvent.clipboardData?d=(a.originalEvent||a).clipboardData.getData("text/plain"):c.clipboardData&&(d=c.clipboardData.getData("Text")),!d&&!w)return!0;if(a.preventDefault(),!w){var e=angular.element("
    ");if(e[0].innerHTML=d,d=e.text(),f[0].selection){var g=f[0].selection.createRange();g.pasteHTML(d)}else f[0].execCommand("insertText",!1,d);A()}}),p.on("keyup",function(a,b){if(b&&angular.extend(a,b),!w){if(""!==s&&13===a.keyCode&&!a.shiftKey){var c=k.getSelectionElement();if(c.tagName.toLowerCase()!==q.taDefaultWrap&&"li"!==c.tagName.toLowerCase()&&(""===c.innerHTML.trim()||"
    "===c.innerHTML.trim())){var d=angular.element(s);angular.element(c).replaceWith(d),k.setSelectionToElementStart(d[0])}}var e=z();""!==s&&""===e.trim()&&(p[0].innerHTML=s,k.setSelectionToElementStart(p.children()[0])),A(e)}}),p.on("blur",function(){x=!1,w||A(),r.$render()}),q.placeholder&&(e>8||void 0===e)){var B;if(!q.id)throw"textAngular Error: An unique ID is required for placeholders to work";B=g("#"+q.id+".placeholder-text:before",'content: "'+q.placeholder+'"'),j.$on("$destroy",function(){h(B)})}p.on("focus",function(){x=!0,r.$render()}),p.on("mousedown",function(a,b){b&&angular.extend(a,b),a.stopPropagation()})}else p.on("paste cut",function(){w||b(function(){r.$setViewValue(z())},0)}),p.on("change blur",function(){w||r.$setViewValue(z())});var C=function(b){return r.$oldViewValue=a(i(b),r.$oldViewValue,y)},D=function(a){return q.required&&r.$setValidity("required",!(!a||a.trim()===t||""===a.trim())),a};r.$parsers.push(C),r.$parsers.push(D),r.$formatters.push(C),r.$formatters.push(D);var E=function(a){return j.$emit("ta-element-select",this),a.preventDefault(),!1},F=function(a,c){if(c&&angular.extend(a,c),!l&&!w){l=!0;var d;d=a.originalEvent?a.originalEvent.dataTransfer:a.dataTransfer,j.$emit("ta-drop-event",this,a,d),b(function(){l=!1},100)}};j.$parent["reApplyOnSelectorHandlers"+(q.id||"")]=function(){w||angular.forEach(m,function(a){p.find(a).off("click",E).on("click",E)})};var G=function(a){p[0].innerHTML=a};r.$render=function(){var a=r.$viewValue||"";f[0].activeElement!==p[0]?u?(q.placeholder?""===a?(x?p.removeClass("placeholder-text"):p.addClass("placeholder-text"),G(s)):(p.removeClass("placeholder-text"),G(a)):G(""===a?s:a),w?p.off("drop",F):(angular.forEach(m,function(a){p.find(a).on("click",E)}),p.on("drop",F))):"textarea"!==p[0].tagName.toLowerCase()&&"input"!==p[0].tagName.toLowerCase()?G(n(a)):p.val(a):u&&p.removeClass("placeholder-text")},q.taReadonly&&(w=j.$parent.$eval(q.taReadonly),w?(p.addClass("ta-readonly"),("textarea"===p[0].tagName.toLowerCase()||"input"===p[0].tagName.toLowerCase())&&p.attr("disabled","disabled"),void 0!==p.attr("contenteditable")&&p.attr("contenteditable")&&p.removeAttr("contenteditable")):(p.removeClass("ta-readonly"),"textarea"===p[0].tagName.toLowerCase()||"input"===p[0].tagName.toLowerCase()?p.removeAttr("disabled"):u&&p.attr("contenteditable","true")),j.$parent.$watch(q.taReadonly,function(a,b){b!==a&&(a?(p.addClass("ta-readonly"),("textarea"===p[0].tagName.toLowerCase()||"input"===p[0].tagName.toLowerCase())&&p.attr("disabled","disabled"),void 0!==p.attr("contenteditable")&&p.attr("contenteditable")&&p.removeAttr("contenteditable"),angular.forEach(m,function(a){p.find(a).on("click",E)}),p.off("drop",F)):(p.removeClass("ta-readonly"),"textarea"===p[0].tagName.toLowerCase()||"input"===p[0].tagName.toLowerCase()?p.removeAttr("disabled"):u&&p.attr("contenteditable","true"),angular.forEach(m,function(a){p.find(a).off("click",E)}),p.on("drop",F)),w=a)})),u&&!w&&(angular.forEach(m,function(a){p.find(a).on("click",E)}),p.on("drop",F),p.on("blur",function(){/AppleWebKit\/([\d.]+)/.exec(navigator.userAgent)&&(d=!0)}))}}}]).factory("taApplyCustomRenderers",["taCustomRenderers",function(a){return function(c){var d=angular.element("
    ");return d[0].innerHTML=c,angular.forEach(a,function(a){var c=[];a.selector&&""!==a.selector?c=d.find(a.selector):a.customAttribute&&""!==a.customAttribute&&(c=b(d,a.customAttribute)),angular.forEach(c,function(b){b=angular.element(b),a.selector&&""!==a.selector&&a.customAttribute&&""!==a.customAttribute?void 0!==b.attr(a.customAttribute)&&a.renderLogic(b):a.renderLogic(b)})}),d[0].innerHTML}}]).directive("taMaxText",function(){return{restrict:"A",require:"ngModel",link:function(a,b,c,d){function e(a){var b=angular.element("
    ");b.html(a);var c=b.text().length;return f>=c?(d.$setValidity("taMaxText",!0),a):void d.$setValidity("taMaxText",!1)}var f=parseInt(a.$eval(c.taMaxText));if(isNaN(f))throw"Max text must be an integer";c.$observe("taMaxText",function(a){if(f=parseInt(a),isNaN(f))throw"Max text must be an integer";d.$dirty&&d.$setViewValue(d.$viewValue)}),d.$parsers.unshift(e)}}}).directive("taMinText",function(){return{restrict:"A",require:"ngModel",link:function(a,b,c,d){function e(a){var b=angular.element("
    ");b.html(a);var c=b.text().length;return!c||c>=f?(d.$setValidity("taMinText",!0),a):void d.$setValidity("taMinText",!1)}var f=parseInt(a.$eval(c.taMinText));if(isNaN(f))throw"Min text must be an integer";c.$observe("taMinText",function(a){if(f=parseInt(a),isNaN(f))throw"Min text must be an integer";d.$dirty&&d.$setViewValue(d.$viewValue)}),d.$parsers.unshift(e)}}}).factory("taFixChrome",function(){var a=function(a){for(var b=angular.element("
    "+a+"
    "),c=angular.element(b).find("span"),d=0;d0&&"BR"===e.next()[0].tagName&&e.next().remove(),e.replaceWith(e[0].innerHTML)))}var f=b[0].innerHTML.replace(/style="[^"]*?(line-height: 1.428571429;|color: inherit; line-height: 1.1;)[^"]*"/gi,"");return f!==b[0].innerHTML&&(b[0].innerHTML=f),b[0].innerHTML};return a}).factory("taSanitize",["$sanitize",function(a){return function(c,d,e){var f=angular.element("
    "+c+"
    ");angular.forEach(b(f,"align"),function(a){a.css("text-align",a.attr("align")),a.removeAttr("align")});var g;c=f[0].innerHTML;try{g=a(c),e&&(g=c)}catch(h){g=d||""}return g}}]).directive("textAngularToolbar",["$compile","textAngularManager","taOptions","taTools","taToolExecuteAction","$window",function(a,b,c,d,e,f){return{scope:{name:"@"},restrict:"EA",link:function(g,h,i){if(!g.name||""===g.name)throw"textAngular Error: A toolbar requires a name";angular.extend(g,angular.copy(c)),i.taToolbar&&(g.toolbar=g.$parent.$eval(i.taToolbar)),i.taToolbarClass&&(g.classes.toolbar=i.taToolbarClass),i.taToolbarGroupClass&&(g.classes.toolbarGroup=i.taToolbarGroupClass),i.taToolbarButtonClass&&(g.classes.toolbarButton=i.taToolbarButtonClass),i.taToolbarActiveButtonClass&&(g.classes.toolbarButtonActive=i.taToolbarActiveButtonClass),i.taFocussedClass&&(g.classes.focussed=i.taFocussedClass),g.disabled=!0,g.focussed=!1,g._$element=h,h[0].innerHTML="",h.addClass("ta-toolbar "+g.classes.toolbar),g.$watch("focussed",function(){g.focussed?h.addClass(g.classes.focussed):h.removeClass(g.classes.focussed)});var j=function(b,c){var d;if(d=angular.element(b&&b.display?b.display:"
    '}}return a.$inject=[],a}),c("ng-admin/Crud/field/maInputField",["require"],function(){function a(){return{scope:{type:"@",field:"&",value:"="},restrict:"E",link:function(a,b){var c=a.field();a.name=c.name(),a.v=c.validation();var d=b.children()[0],e=c.attributes();for(var f in e)d[f]=e[f]},template:''}}return a.$inject=[],a}),c("ng-admin/Crud/field/maCheckboxField",["require"],function(){function a(){return{scope:{field:"&",value:"="},restrict:"E",link:function(a,b){var c=a.field();a.name=c.name(),a.v=c.validation(),a.value=!!a.value;var d=b.children()[0],e=c.attributes();for(var f in e)d[f]=e[f]},template:''}}return a.$inject=[],a}),c("ng-admin/Crud/field/maTextField",["require"],function(){function a(){return{scope:{field:"&",value:"="},restrict:"E",link:function(a,b){var c=a.field();a.name=c.name(),a.v=c.validation();var d=b.children()[0],e=c.attributes();for(var f in e)d[f]=e[f]},template:''}}return a.$inject=[],a}),c("ng-admin/Crud/field/maWysiwygField",["require"],function(){function a(){return{scope:{field:"&",value:"="},restrict:"E",link:function(a){var b=a.field();a.name=b.name()},template:'
    '}}return a.$inject=[],a}),c("text!ng-admin/Crud/field/TemplateField.html",[],function(){return'\n'}),c("ng-admin/Crud/field/TemplateField",["require","text!./TemplateField.html"],function(a){function b(){return{restrict:"E",template:c}}var c=a("text!./TemplateField.html");return b.$inject=[],b}),c("text!ng-admin/Crud/list/ListActions.html",[],function(){return'\n \n \n \n \n \n\n'}),c("ng-admin/Crud/list/ListActions",["require","text!./ListActions.html"],function(a){function b(){return{restrict:"E",transclude:!0,scope:{buttons:"=",entry:"&",entity:"&"},template:c,link:function(a){a.entry=a.entry(),a.entity=a.entity(),a.customTemplate=!1,"string"==typeof a.buttons&&(a.customTemplate=a.buttons,a.buttons=null)}}}var c=a("text!./ListActions.html");return b}),c("text!ng-admin/Crud/list/Datagrid.html",[],function(){return'\n \n \n \n \n \n \n\n \n \n \n \n \n \n
    \n \n \n\n {{ field.label() }}\n \n \n Actions\n
    \n \n \n \n
    \n\n\n'}),c("ng-admin/Crud/list/DatagridController",[],function(){function a(a,b,c){a.entity=a.entity(),this.$scope=a,this.$location=b,this.$anchorScroll=c,this.filters={},this.$scope.gotoDetail=this.gotoDetail.bind(this);var d=this.$location.search();this.sortField="sortField"in d?d.sortField:"",this.sortDir="sortDir"in d?d.sortDir:""}return a.prototype.gotoDetail=function(a){this.clearRouteParams();var b=this.$scope.entity.isReadOnly?"show":"edit";this.$location.path("/"+b+"/"+a.entityName+"/"+a.identifierValue),this.$anchorScroll(0)},a.prototype.clearRouteParams=function(){this.$location.search("q",null),this.$location.search("page",null),this.$location.search("sortField",null),this.$location.search("sortDir",null)},a.prototype.isSorting=function(a){return this.sortField===this.getSortName(a)},a.prototype.itemClass=function(a){return a%2===0?"even":"odd"},a.prototype.sort=function(a){var b="ASC",c=this.getSortName(a);this.sortField===c&&(b="ASC"===this.sortDir?"DESC":"ASC"),this.$location.search("sortField",c),this.$location.search("sortDir",b)},a.prototype.getSortName=function(a){return this.$scope.name+"."+a.name()},a.$inject=["$scope","$location","$anchorScroll"],a}),c("ng-admin/Crud/list/maDatagrid",["require","text!./Datagrid.html","./DatagridController"],function(a){function b(){return{restrict:"E",template:c,scope:{name:"@",entries:"=",fields:"&",listActions:"&",entity:"&",perPage:"=",nextPage:"=",totalItems:"@",infinitePagination:"="},controllerAs:"datagrid",controller:d}}var c=a("text!./Datagrid.html"),d=a("./DatagridController");return b.$inject=[],b}),c("text!ng-admin/Crud/list/DatagridPagination.html",[],function(){return'
    \n
    \n \n {{ paginationCtrl.offsetBegin }} - {{ paginationCtrl.offsetEnd }} on {{ paginationCtrl.totalItems }}\n \n \n
    \n
    \n'}),c("ng-admin/Crud/list/DatagridPaginationController",[],function(){function a(a,b,c){this.$scope=a,this.$location=b,this.$anchorScroll=c}return a.prototype.computePagination=function(){var a=this.$scope.perPage,b=this.$location.search().page||1,c=this.$scope.totalItems;this.displayPagination=this.$scope.hasPagination&&!this.$scope.infinite,this.currentPage=b,this.offsetEnd=Math.min(b*a,c),this.offsetBegin=Math.min((b-1)*a+1,this.offsetEnd),this.totalItems=c,this.nbPages=Math.ceil(c/(a||1))||1},a.prototype.range=function(a,b){var c,d=[];for(c=a;b>=c;c++)d.push(c);return d},a.prototype.nextPage=function(){if(this.$scope.infinite&&this.currentPage!==this.nbPages){var a=this.$location.search(),b="sortField"in a?a.sortField:"",c="sortDir"in a?a.sortDir:"";this.currentPage++,this.$scope.nextPage(this.currentPage,b,c)}},a.prototype.setPage=function(a){0>=a||a>this.nbPages||(this.$location.search("page",a),this.$anchorScroll(0))},a.$inject=["$scope","$location","$anchorScroll"],a}),c("ng-admin/Crud/list/maDatagridPagination",["require","angular","text!./DatagridPagination.html","./DatagridPaginationController"],function(a){function b(a,b){return{restrict:"E",scope:{entries:"=",perPage:"=",nextPage:"=",totalItems:"@",infinite:"="},template:d,controllerAs:"paginationCtrl",controller:e,link:function(d,e,f,g){var h=f.offset||100,i=b[0].body;d.hasPagination=e.parent()[0].hasAttribute("with-pagination")?d.$eval(e.parent()[0].getAttribute("with-pagination")):!0,d.hasPagination&&g.computePagination(),c.element(a).bind("scroll",function(){i.offsetHeight-a.innerHeight-a.scrollY\n
  • \n Filters:\n
  • \n
  • \n None\n
  • \n
  • \n {{ label }}\n
  • \n\n'}),c("ng-admin/Crud/filter/QuickFilterController",[],function(){function a(a,b){this.$scope=a,this.$location=b;var c=this.$location.search();this.currentQuickFilter="quickFilter"in c?c.quickFilter:null}return a.prototype.canDisplayQuickFilters=function(){return this.$scope.quickFilters.length>0},a.prototype.filter=function(a){this.$location.search("quickFilter",a)},a.$inject=["$scope","$location"],a}),c("ng-admin/Crud/filter/maQuickFilter",["require","text!./QuickFilter.html","./QuickFilterController"],function(a){function b(){return{restrict:"E",scope:{quickFilters:"="},template:c,controllerAs:"quickFilterCtrl",controller:d}}var c=a("text!./QuickFilter.html"),d=a("./QuickFilterController");return b.$inject=[],b}),c("text!ng-admin/Crud/filter/FilterView.html",[],function(){return'\n'}),c("ng-admin/Crud/filter/FilterViewController",[],function(){function a(a,c,d,e,f){this.$scope=a,this.$state=c,this.$stateParams=d,this.$filter=e,this.values=this.$stateParams.search||{},this.view=f().getViewByEntityAndType(d.entity,"FilterView"),this.$scope.fields=this.$scope.filterFields(),this.isFilterEmpty=b(this.values)}function b(a){for(i in a)if(""!=a[i])return!1;return!0}return a.prototype.filter=function(){var a,b,c,d={},e=this.view.getFields();for(c in e)b=e[c],a=b.name(),this.values[a]&&(d[a]=this.values[a],"date"===b.type()&&(d[a]=this.$filter("date")(d[a],b.format())));this.$stateParams.search=d,this.$state.go(this.$state.current,this.$stateParams,{reload:!0,inherit:!1,notify:!0})},a.prototype.shouldFilter=function(){return Object.keys(this.$scope.fields).length},a.prototype.clearFilters=function(){var a;for(a in this.values)this.values[a]=null;this.filter()},a.$inject=["$scope","$state","$stateParams","$filter","NgAdminConfiguration"],a}),c("ng-admin/Crud/filter/maFilterView",["require","text!./FilterView.html","./FilterViewController"],function(a){function b(){return{restrict:"E",template:c,scope:{filterFields:"&"},controllerAs:"filterViewCtrl",controller:d}}var c=a("text!./FilterView.html"),d=a("./FilterViewController");return b.$inject=[],b}),c("ng-admin/Crud/column/maColumn",["require"],function(){function a(a,b,c,d){return{restrict:"E",scope:{field:"&",entry:"&",entity:"&"},link:function(e,f){return e.field=e.field(),e.entry=e.entry(),e.type=e.field.type(),e.isReference="Reference"==e.type||"ReferenceMany"==e.type,e.value=e.entry.values[e.field.name()],"ReferencedList"==e.type?(f.append(''),void c(f.contents())(e)):(e.isDetailLink=function(){if(!e.isReference)return e.field.isDetailLink();var a=e.field.targetEntity().name(),b=d().getEntity(a);return b?b.isReadOnly?b.showView().isEnabled():b.editionView().isEnabled():!1},e.gotoDetail=function(){this.clearRouteParams();var c=e.entity().isReadOnly?"show":"edit";a.path("/"+c+"/"+e.entry.entityName+"/"+e.entry.identifierValue),b(0)},e.gotoReference=function(){this.clearRouteParams();var b=e.field.targetEntity().name(),c=d().getEntity(b),f=e.entry.values[e.field.name()],g=c.isReadOnly?"show":"edit";a.path("/"+g+"/"+b+"/"+f)},void(e.clearRouteParams=function(){a.search("q",null),a.search("page",null),a.search("sortField",null),a.search("sortDir",null)}))},template:''}}return a.$inject=["$location","$anchorScroll","$compile","NgAdminConfiguration"],a}),c("ng-admin/Crud/column/maBooleanColumn",["require"],function(){function a(){return{restrict:"E",scope:{value:"&"},link:function(a){a.isOk=!!a.value()},template:""}}return a.$inject=[],a}),c("ng-admin/Crud/column/maChoicesColumn",["require"],function(){function a(){return{restrict:"E",scope:{value:"&"},template:'{{ ref }}'}}return a.$inject=[],a}),c("ng-admin/Crud/column/maDateColumn",["require"],function(){function a(){return{restrict:"E",scope:{value:"&",field:"&"},template:"{{ value() | date:field().format() }}"}}return a.$inject=[],a}),c("ng-admin/Crud/column/maPasswordColumn",["require"],function(){function a(){return{restrict:"E",scope:{},template:"xxx"} +}return a.$inject=[],a}),c("ng-admin/Crud/column/maReferencedListColumn",["require"],function(){function a(){return{restrict:"E",scope:{field:"&"},link:function(a){a.field=a.field()},template:''}}return a.$inject=[],a}),c("ng-admin/Crud/column/maReferenceManyColumn",["require"],function(){function a(){return{restrict:"E",scope:{values:"&"},template:'{{ ref }}'}}return a.$inject=[],a}),c("ng-admin/Crud/column/maReferenceManyLinkColumn",["require"],function(){function a(a,b){return{restrict:"E",scope:{field:"&",values:"&",ids:"&"},link:function(c){c.field=c.field(),c.values=c.values(),c.ids=c.ids();var d=c.field.targetEntity().name(),e=b().getEntity(d);c.gotoReference=function(b){var c=e.isReadOnly?"show":"edit";a.path("/"+c+"/"+d+"/"+b)}},template:'{{ ref }}'}}return a.$inject=["$location","NgAdminConfiguration"],a}),c("ng-admin/Crud/column/maStringColumn",["require"],function(){function a(){return{restrict:"E",scope:{value:"&"},template:"{{ value() }}"}}return a.$inject=[],a}),c("ng-admin/Crud/column/maTemplateColumn",["require"],function(){function a(){return{restrict:"E",scope:{field:"&",entry:"&",entity:"&"},link:function(a){a.field=a.field(),a.entry=a.entry(),a.entity=a.entity()},template:''}}return a.$inject=[],a}),c("ng-admin/Crud/column/maWysiwygColumn",["require"],function(){function a(){return{restrict:"E",scope:{value:"&"},template:''}}return a.$inject=[],a}),c("ng-admin/Crud/button/maBackButton",[],function(){function a(a){return{restrict:"E",scope:{size:"@"},link:function(b){b.back=function(){a.history.back()}},template:' Back'}}return a.$inject=["$window"],a}),c("ng-admin/Crud/button/maCreateButton",[],function(){function a(a){return{restrict:"E",scope:{entity:"&",size:"@"},link:function(b){b.gotoCreate=function(){a.path("/create/"+b.entity().name())}},template:' Create'}}return a.$inject=["$location"],a}),c("ng-admin/Crud/button/maEditButton",[],function(){function a(a){return{restrict:"E",scope:{entity:"&",entry:"&",size:"@"},link:function(b){b.gotoEdit=function(){var c=b.entity();a.path("/edit/"+c.name()+"/"+b.entry().identifierValue)}},template:' Edit'}}return a.$inject=["$location"],a}),c("ng-admin/Crud/button/maShowButton",[],function(){function a(a){return{restrict:"E",scope:{entity:"&",entry:"&",size:"@"},link:function(b){b.gotoShow=function(){var c=b.entity();a.path("/show/"+c.name()+"/"+b.entry().identifierValue)}},template:' Show'}}return a.$inject=["$location"],a}),c("ng-admin/Crud/button/maListButton",[],function(){function a(a){return{restrict:"E",scope:{entity:"&",size:"@"},link:function(b){b.gotoList=function(){a.path("/list/"+b.entity().name())}},template:' List'}}return a.$inject=["$location"],a}),c("ng-admin/Crud/button/maDeleteButton",[],function(){function a(a){return{restrict:"E",scope:{entity:"&",entry:"&",size:"@"},link:function(b){b.gotoDelete=function(){var c=b.entity();a.path("/delete/"+c.name()+"/"+b.entry().identifierValue)}},template:' Delete'}}return a.$inject=["$location"],a}),c("text!ng-admin/Crud/misc/view-actions.html",[],function(){return'\n \n \n \n \n \n \n\n'}),c("ng-admin/Crud/misc/ViewActions",["require","text!./view-actions.html"],function(a){function b(a){var b=a.get("$compile");return{restrict:"E",transclude:!0,scope:{override:"&",entry:"=",entity:"="},template:c,link:function(a,c,d,e,f){var g=a.override();return g?"string"==typeof g?(c.html(g),void b(c.contents())(a)):void(a.buttons=g):void f(a,function(a){c.append(a)})}}}var c=a("text!./view-actions.html");return b.$inject=["$injector"],b}),c("ng-admin/Crud/misc/Compile",[],function(){function a(a){var b=a.get("$compile");return{transclude:!0,link:function(a,c,d,e,f){a.$watch(function(a){return a.$eval(d.compile)},function(d){return!1===d?void f(a,function(a){c.append(a)}):(c.html(d),void b(c.contents())(a))})}}}return a.$inject=["$injector"],a}),c("text!ng-admin/Crud/form/edit-attribute.html",[],function(){return'
    \n \n\n
    \n \n\n \n\n \n\n \n\n \n\n \n\n \n\n \n\n \n\n \n\n \n\n \n \n\n \n\n \n\n \n\n \n
    \n\n
    \n

    {{ entry.values[field.name()] }}

    \n
    \n
    \n'}),c("ng-admin/Crud/misc/cacheTemplate",["require","text!../form/edit-attribute.html"],function(a){function b(a){a.put("ng-admin/Crud/form/edit-attribute.html",c)}var c=a("text!../form/edit-attribute.html");return b.$inject=["$templateCache"],b}),c("text!ng-admin/Crud/list/list.html",[],function(){return'
    \n\n \n \n \n\n \n\n
    \n \n \n \n
    \n
    \n\n
    \n \n \n
    \n'}),c("text!ng-admin/Crud/show/show.html",[],function(){return'
    \n\n \n \n \n \n \n\n \n\n
    \n\n\n
    \n\n
    \n\n \n\n
    \n\n \n\n
    \n
    \n\n
    \n'}),c("text!ng-admin/Crud/form/create.html",[],function(){return'
    \n\n \n \n \n\n \n\n
    \n\n
    \n
    \n
    \n\n
    \n
    \n \n
    \n
    \n
    \n
    \n'}),c("text!ng-admin/Crud/form/edit.html",[],function(){return'
    \n\n \n \n \n \n\n \n\n
    \n\n
    \n
    \n
    \n\n
    \n
    \n \n
    \n
    \n
    \n
    \n'}),c("text!ng-admin/Crud/delete/delete.html",[],function(){return'
    \n\n \n \n \n\n \n\n
    \n\n
    \n

    Are you sure ?

    \n \n \n
    \n'}),c("ng-admin/Crud/routing",["require","text!./list/list.html","text!./show/show.html","text!./form/create.html","text!./form/edit.html","text!./delete/delete.html"],function(a){function b(a,b){return["$stateParams","NgAdminConfiguration",function(c,d){var e,f=d().getViewByEntityAndType(c.entity,a);return(e=f.template())?e:(e=d().customTemplate()(a),e?e:b)}]}function c(a){return["$stateParams","NgAdminConfiguration",function(b,c){var d=c().getViewByEntityAndType(b.entity,a);if(!d.isEnabled())throw new Error("The "+a+" is disabled for this entity");return d}]}function d(a){a.state("list",{parent:"main",url:"/list/:entity?{search:json}&page&sortField&sortDir&quickFilter",params:{entity:null,page:null,search:null,quickFilter:null,sortField:null,sortDir:null},controller:"ListController",controllerAs:"listController",templateProvider:b("ListView",e),resolve:{view:c("ListView"),data:["$stateParams","RetrieveQueries","view","NgAdminConfiguration",function(a,b,c,d){var e,f=(d(),a.search),g=a.page,h=a.sortField,i=a.sortDir,j=a.quickFilter;return j&&(e=c.getQuickFilterParams(j)),b.getAll(c,g,!0,f,h,i,e)}]}}),a.state("show",{parent:"main",url:"/show/:entity/:id",controller:"ShowController",controllerAs:"showController",templateProvider:b("ShowView",f),params:{entity:{},id:null},resolve:{view:c("ShowView"),rawEntry:["$stateParams","RetrieveQueries","view",function(a,b,c){return b.getOne(c,a.id)}],referencedValues:["RetrieveQueries","view","rawEntry",function(a,b,c){return a.getReferencedValues(b,[c.values])}],referencedListValues:["$stateParams","RetrieveQueries","view","rawEntry",function(a,b,c,d){var e=a.sortField,f=a.sortDir;return b.getReferencedListValues(c,e,f,d.identifierValue)}],entry:["RetrieveQueries","rawEntry","referencedValues",function(a,b,c){return a.fillReferencesValuesFromEntry(b,c,!0)}]}}),a.state("create",{parent:"main",url:"/create/:entity",controller:"FormController",controllerAs:"formController",templateProvider:b("CreateView",g),resolve:{view:c("CreateView"),entry:["view",function(a){var b=a.mapEntry({});return a.processFieldsDefaultValue(b),b}],referencedValues:["RetrieveQueries","view",function(a,b){return a.getReferencedValues(b)}]}}),a.state("edit",{parent:"main",url:"/edit/:entity/:id?sortField&sortDir",controller:"FormController",controllerAs:"formController",templateProvider:b("EditView",h),params:{entity:{},id:null,sortField:null,sortDir:null},resolve:{view:c("EditView"),entry:["$stateParams","RetrieveQueries","view",function(a,b,c){return b.getOne(c,a.id)}],referencedValues:["RetrieveQueries","view","entry",function(a,b){return a.getReferencedValues(b,null)}],referencedListValues:["$stateParams","RetrieveQueries","view","entry",function(a,b,c,d){var e=a.sortField,f=a.sortDir;return b.getReferencedListValues(c,e,f,d.identifierValue)}]}}),a.state("delete",{parent:"main",url:"/delete/:entity/:id",controller:"DeleteController",controllerAs:"deleteController",templateProvider:b("DeleteView",i),resolve:{view:c("DeleteView"),params:["$stateParams",function(a){return a}],entry:["$stateParams","RetrieveQueries","view",function(a,b,c){return b.getOne(c,a.id)}]}})}var e=a("text!./list/list.html"),f=a("text!./show/show.html"),g=a("text!./form/create.html"),h=a("text!./form/edit.html"),i=a("text!./delete/delete.html");return d.$inject=["$stateProvider"],d}),!function(a,b,d){"undefined"!=typeof module?module.exports=d(a,b):"function"==typeof c&&"object"==typeof c.amd?c("humane",d):b[a]=d(a,b)}("humane",this,function(){var a=window,b=document,c={on:function(b,c,d){"addEventListener"in a?b.addEventListener(c,d,!1):b.attachEvent("on"+c,d)},off:function(b,c,d){"removeEventListener"in a?b.removeEventListener(c,d,!1):b.detachEvent("on"+c,d)},bind:function(a,b){return function(){a.apply(b,arguments)}},isArray:Array.isArray||function(a){return"[object Array]"===Object.prototype.toString.call(a)},config:function(a,b){return null!=a?a:b},transSupport:!1,useFilter:/msie [678]/i.test(navigator.userAgent),_checkTransition:function(){var a=b.createElement("div"),c={webkit:"webkit",Moz:"",O:"o",ms:"MS"};for(var d in c)d+"Transition"in a.style&&(this.vendorPrefix=c[d],this.transSupport=!0)}};c._checkTransition();var d=function(b){b||(b={}),this.queue=[],this.baseCls=b.baseCls||"humane",this.addnCls=b.addnCls||"",this.timeout="timeout"in b?b.timeout:2500,this.waitForMove=b.waitForMove||!1,this.clickToClose=b.clickToClose||!1,this.timeoutAfterMove=b.timeoutAfterMove||!1,this.container=b.container;try{this._setupEl()}catch(d){c.on(a,"load",c.bind(this._setupEl,this))}};return d.prototype={constructor:d,_setupEl:function(){var a=b.createElement("div");if(a.style.display="none",!this.container){if(!b.body)throw"document.body is null";this.container=b.body}this.container.appendChild(a),this.el=a,this.removeEvent=c.bind(function(){var a=c.config(this.currentMsg.timeoutAfterMove,this.timeoutAfterMove);a?setTimeout(c.bind(this.remove,this),a):this.remove()},this),this.transEvent=c.bind(this._afterAnimation,this),this._run()},_afterTimeout:function(){c.config(this.currentMsg.waitForMove,this.waitForMove)?this.removeEventsSet||(c.on(b.body,"mousemove",this.removeEvent),c.on(b.body,"click",this.removeEvent),c.on(b.body,"keypress",this.removeEvent),c.on(b.body,"touchstart",this.removeEvent),this.removeEventsSet=!0):this.remove()},_run:function(){if(!this._animating&&this.queue.length&&this.el){this._animating=!0,this.currentTimer&&(clearTimeout(this.currentTimer),this.currentTimer=null);var a=this.queue.shift(),b=c.config(a.clickToClose,this.clickToClose);b&&(c.on(this.el,"click",this.removeEvent),c.on(this.el,"touchstart",this.removeEvent));var d=c.config(a.timeout,this.timeout);d>0&&(this.currentTimer=setTimeout(c.bind(this._afterTimeout,this),d)),c.isArray(a.html)&&(a.html="
    • "+a.html.join("
    • ")+"
    "),this.el.innerHTML=a.html,this.currentMsg=a,this.el.className=this.baseCls,c.transSupport?(this.el.style.display="block",setTimeout(c.bind(this._showMsg,this),50)):this._showMsg()}},_setOpacity:function(a){if(c.useFilter)try{this.el.filters.item("DXImageTransform.Microsoft.Alpha").Opacity=100*a}catch(b){}else this.el.style.opacity=String(a)},_showMsg:function(){var a=c.config(this.currentMsg.addnCls,this.addnCls);if(c.transSupport)this.el.className=this.baseCls+" "+a+" "+this.baseCls+"-animate";else{var b=0;this.el.className=this.baseCls+" "+a+" "+this.baseCls+"-js-animate",this._setOpacity(0),this.el.style.display="block";var d=this,e=setInterval(function(){1>b?(b+=.1,b>1&&(b=1),d._setOpacity(b)):clearInterval(e)},30)}},_hideMsg:function(){var a=c.config(this.currentMsg.addnCls,this.addnCls);if(c.transSupport)this.el.className=this.baseCls+" "+a,c.on(this.el,c.vendorPrefix?c.vendorPrefix+"TransitionEnd":"transitionend",this.transEvent);else var b=1,d=this,e=setInterval(function(){b>0?(b-=.1,0>b&&(b=0),d._setOpacity(b)):(d.el.className=d.baseCls+" "+a,clearInterval(e),d._afterAnimation())},30)},_afterAnimation:function(){c.transSupport&&c.off(this.el,c.vendorPrefix?c.vendorPrefix+"TransitionEnd":"transitionend",this.transEvent),this.currentMsg.cb&&this.currentMsg.cb(),this.el.style.display="none",this._animating=!1,this._run()},remove:function(a){var d="function"==typeof a?a:null;c.off(b.body,"mousemove",this.removeEvent),c.off(b.body,"click",this.removeEvent),c.off(b.body,"keypress",this.removeEvent),c.off(b.body,"touchstart",this.removeEvent),c.off(this.el,"click",this.removeEvent),c.off(this.el,"touchstart",this.removeEvent),this.removeEventsSet=!1,d&&this.currentMsg&&(this.currentMsg.cb=d),this._animating?this._hideMsg():d&&d()},log:function(a,b,c,d){var e={};if(d)for(var f in d)e[f]=d[f];if("function"==typeof b)c=b;else if(b)for(var f in b)e[f]=b[f];return e.html=a,c&&(e.cb=c),this.queue.push(e),this._run(),this},spawn:function(a){var b=this;return function(c,d,e){return b.log.call(b,c,d,e,a),b}},create:function(a){return new d(a)}},new d}),function(a,b){"function"==typeof c&&c.amd?c("nprogress",b):"object"==typeof exports?module.exports=b():a.NProgress=b()}(this,function(){function a(a,b,c){return b>a?b:a>c?c:a}function b(a){return 100*(-1+a)}function c(a,c,d){var e;return e="translate3d"===j.positionUsing?{transform:"translate3d("+b(a)+"%,0,0)"}:"translate"===j.positionUsing?{transform:"translate("+b(a)+"%,0)"}:{"margin-left":b(a)+"%"},e.transition="all "+c+"ms "+d,e}function d(a,b){var c="string"==typeof a?a:g(a);return c.indexOf(" "+b+" ")>=0}function e(a,b){var c=g(a),e=c+b;d(c,b)||(a.className=e.substring(1))}function f(a,b){var c,e=g(a);d(a,b)&&(c=e.replace(" "+b+" "," "),a.className=c.substring(1,c.length-1))}function g(a){return(" "+(a.className||"")+" ").replace(/\s+/gi," ")}function h(a){a&&a.parentNode&&a.parentNode.removeChild(a)}var i={};i.version="0.1.6";var j=i.settings={minimum:.08,easing:"ease",positionUsing:"",speed:200,trickle:!0,trickleRate:.02,trickleSpeed:800,showSpinner:!0,barSelector:'[role="bar"]',spinnerSelector:'[role="spinner"]',parent:"body",template:'
    '};i.configure=function(a){var b,c;for(b in a)c=a[b],void 0!==c&&a.hasOwnProperty(b)&&(j[b]=c);return this},i.status=null,i.set=function(b){var d=i.isStarted();b=a(b,j.minimum,1),i.status=1===b?null:b;var e=i.render(!d),f=e.querySelector(j.barSelector),g=j.speed,h=j.easing;return e.offsetWidth,k(function(a){""===j.positionUsing&&(j.positionUsing=i.getPositioningCSS()),l(f,c(b,g,h)),1===b?(l(e,{transition:"none",opacity:1}),e.offsetWidth,setTimeout(function(){l(e,{transition:"all "+g+"ms linear",opacity:0}),setTimeout(function(){i.remove(),a()},g)},g)):setTimeout(a,g)}),this},i.isStarted=function(){return"number"==typeof i.status},i.start=function(){i.status||i.set(0);var a=function(){setTimeout(function(){i.status&&(i.trickle(),a())},j.trickleSpeed)};return j.trickle&&a(),this},i.done=function(a){return a||i.status?i.inc(.3+.5*Math.random()).set(1):this},i.inc=function(b){var c=i.status;return c?("number"!=typeof b&&(b=(1-c)*a(Math.random()*c,.1,.95)),c=a(c+b,0,.994),i.set(c)):i.start()},i.trickle=function(){return i.inc(Math.random()*j.trickleRate)},function(){var a=0,b=0;i.promise=function(c){return c&&"resolved"!=c.state()?(0==b&&i.start(),a++,b++,c.always(function(){b--,0==b?(a=0,i.done()):i.set((a-b)/a)}),this):this}}(),i.render=function(a){if(i.isRendered())return document.getElementById("nprogress");e(document.documentElement,"nprogress-busy");var c=document.createElement("div");c.id="nprogress",c.innerHTML=j.template;var d,f=c.querySelector(j.barSelector),g=a?"-100":b(i.status||0),k=document.querySelector(j.parent);return l(f,{transition:"all 0 linear",transform:"translate3d("+g+"%,0,0)"}),j.showSpinner||(d=c.querySelector(j.spinnerSelector),d&&h(d)),k!=document.body&&e(k,"nprogress-custom-parent"),k.appendChild(c),c},i.remove=function(){f(document.documentElement,"nprogress-busy"),f(document.querySelector(j.parent),"nprogress-custom-parent");var a=document.getElementById("nprogress");a&&h(a)},i.isRendered=function(){return!!document.getElementById("nprogress")},i.getPositioningCSS=function(){var a=document.body.style,b="WebkitTransform"in a?"Webkit":"MozTransform"in a?"Moz":"msTransform"in a?"ms":"OTransform"in a?"O":"";return b+"Perspective"in a?"translate3d":b+"Transform"in a?"translate":"margin"};var k=function(){function a(){var c=b.shift();c&&c(a)}var b=[];return function(c){b.push(c),1==b.length&&a()}}(),l=function(){function a(a){return a.replace(/^-ms-/,"ms-").replace(/-([\da-z])/gi,function(a,b){return b.toUpperCase()})}function b(a){var b=document.body.style;if(a in b)return a;for(var c,d=e.length,f=a.charAt(0).toUpperCase()+a.slice(1);d--;)if(c=e[d]+f,c in b)return c;return a}function c(c){return c=a(c),f[c]||(f[c]=b(c))}function d(a,b,d){b=c(b),a.style[b]=d}var e=["Webkit","O","Moz","ms"],f={};return function(a,b){var c,e,f=arguments;if(2==f.length)for(c in b)e=b[c],void 0!==e&&b.hasOwnProperty(c)&&d(a,c,e);else d(a,f[1],f[2])}}();return i});var d;return c("CrudModule",["require","angular","inflection","angular-ui-router","angular-sanitize","angular-bootstrap-tpls","textangular","ngInflection","ng-admin/Crud/list/ListController","ng-admin/Crud/show/ShowController","ng-admin/Crud/form/FormController","ng-admin/Crud/delete/DeleteController","ng-admin/Crud/repository/RetrieveQueries","ng-admin/Crud/repository/CreateQueries","ng-admin/Crud/repository/UpdateQueries","ng-admin/Crud/repository/DeleteQueries","ng-admin/Crud/field/maChoiceField","ng-admin/Crud/field/maChoicesField","ng-admin/Crud/field/maDateField","ng-admin/Crud/field/maInputField","ng-admin/Crud/field/maCheckboxField","ng-admin/Crud/field/maTextField","ng-admin/Crud/field/maWysiwygField","ng-admin/Crud/field/TemplateField","ng-admin/Crud/list/ListActions","ng-admin/Crud/list/maDatagrid","ng-admin/Crud/list/maDatagridPagination","ng-admin/Crud/filter/maQuickFilter","ng-admin/Crud/filter/maFilterView","ng-admin/Crud/column/maColumn","ng-admin/Crud/column/maBooleanColumn","ng-admin/Crud/column/maChoicesColumn","ng-admin/Crud/column/maDateColumn","ng-admin/Crud/column/maPasswordColumn","ng-admin/Crud/column/maReferencedListColumn","ng-admin/Crud/column/maReferenceManyColumn","ng-admin/Crud/column/maReferenceManyLinkColumn","ng-admin/Crud/column/maStringColumn","ng-admin/Crud/column/maTemplateColumn","ng-admin/Crud/column/maWysiwygColumn","ng-admin/Crud/button/maBackButton","ng-admin/Crud/button/maCreateButton","ng-admin/Crud/button/maEditButton","ng-admin/Crud/button/maShowButton","ng-admin/Crud/button/maListButton","ng-admin/Crud/button/maDeleteButton","ng-admin/Crud/misc/ViewActions","ng-admin/Crud/misc/Compile","ng-admin/Crud/misc/cacheTemplate","ng-admin/Crud/routing","humane","nprogress"],function(a){var b=a("angular");d=a("inflection"),a("angular-ui-router"),a("angular-sanitize"),a("angular-bootstrap-tpls"),a("textangular"),a("ngInflection");var c=b.module("crud",["ui.router","ui.bootstrap","ngSanitize","textAngular","ngInflection"]);return c.controller("ListController",a("ng-admin/Crud/list/ListController")),c.controller("ShowController",a("ng-admin/Crud/show/ShowController")),c.controller("FormController",a("ng-admin/Crud/form/FormController")),c.controller("DeleteController",a("ng-admin/Crud/delete/DeleteController")),c.service("RetrieveQueries",a("ng-admin/Crud/repository/RetrieveQueries")),c.service("CreateQueries",a("ng-admin/Crud/repository/CreateQueries")),c.service("UpdateQueries",a("ng-admin/Crud/repository/UpdateQueries")),c.service("DeleteQueries",a("ng-admin/Crud/repository/DeleteQueries")),c.directive("maChoiceField",a("ng-admin/Crud/field/maChoiceField")),c.directive("maChoicesField",a("ng-admin/Crud/field/maChoicesField")),c.directive("maDateField",a("ng-admin/Crud/field/maDateField")),c.directive("maInputField",a("ng-admin/Crud/field/maInputField")),c.directive("maCheckboxField",a("ng-admin/Crud/field/maCheckboxField")),c.directive("maTextField",a("ng-admin/Crud/field/maTextField")),c.directive("maWysiwygField",a("ng-admin/Crud/field/maWysiwygField")),c.directive("templateField",a("ng-admin/Crud/field/TemplateField")),c.directive("listActions",a("ng-admin/Crud/list/ListActions")),c.directive("maDatagrid",a("ng-admin/Crud/list/maDatagrid")),c.directive("maDatagridPagination",a("ng-admin/Crud/list/maDatagridPagination")),c.directive("maQuickFilter",a("ng-admin/Crud/filter/maQuickFilter")),c.directive("maFilterView",a("ng-admin/Crud/filter/maFilterView")),c.directive("maColumn",a("ng-admin/Crud/column/maColumn")),c.directive("maBooleanColumn",a("ng-admin/Crud/column/maBooleanColumn")),c.directive("maChoicesColumn",a("ng-admin/Crud/column/maChoicesColumn")),c.directive("maDateColumn",a("ng-admin/Crud/column/maDateColumn")),c.directive("maPasswordColumn",a("ng-admin/Crud/column/maPasswordColumn")),c.directive("maReferencedListColumn",a("ng-admin/Crud/column/maReferencedListColumn")),c.directive("maReferenceManyColumn",a("ng-admin/Crud/column/maReferenceManyColumn")),c.directive("maReferenceManyLinkColumn",a("ng-admin/Crud/column/maReferenceManyLinkColumn")),c.directive("maStringColumn",a("ng-admin/Crud/column/maStringColumn")),c.directive("maTemplateColumn",a("ng-admin/Crud/column/maTemplateColumn")),c.directive("maWysiwygColumn",a("ng-admin/Crud/column/maWysiwygColumn")),c.directive("maBackButton",a("ng-admin/Crud/button/maBackButton")),c.directive("maCreateButton",a("ng-admin/Crud/button/maCreateButton")),c.directive("maEditButton",a("ng-admin/Crud/button/maEditButton")),c.directive("maShowButton",a("ng-admin/Crud/button/maShowButton")),c.directive("maListButton",a("ng-admin/Crud/button/maListButton")),c.directive("maDeleteButton",a("ng-admin/Crud/button/maDeleteButton")),c.directive("maViewActions",a("ng-admin/Crud/misc/ViewActions")),c.directive("compile",a("ng-admin/Crud/misc/Compile")),c.run(a("ng-admin/Crud/misc/cacheTemplate")),c.config(a("ng-admin/Crud/routing")),c.factory("notification",function(){return a("humane") +}),c.factory("progression",function(){return a("nprogress")}),c.config(["$provide",function(a){a.decorator("dateParser",["$delegate",function(a){var c=a.parse;return a.parse=function(a,d){return b.isString(a)&&d?c.apply(this,arguments):a},a}])}]),c}),c("angular",[],function(){return angular}),b.config({paths:{"angular-resource":"bower_components/angular-resource/angular-resource","angular-sanitize":"bower_components/angular-sanitize/angular-sanitize","angular-ui-router":"bower_components/angular-ui-router/release/angular-ui-router",lodash:"bower_components/lodash/dist/lodash.min",text:"bower_components/requirejs-text/text","angular-bootstrap":"bower_components/angular-bootstrap/ui-bootstrap.min","angular-bootstrap-tpls":"bower_components/angular-bootstrap/ui-bootstrap-tpls.min",restangular:"bower_components/restangular/dist/restangular",ngInflection:"bower_components/ngInflection/ngInflection",inflection:"bower_components/inflection/inflection.min",humane:"bower_components/humane/humane",nprogress:"bower_components/nprogress/nprogress",textangular:"bower_components/textAngular/dist/textAngular.min",MainModule:"ng-admin/Main/MainModule",CrudModule:"ng-admin/Crud/CrudModule"},shim:{restangular:{deps:["angular","lodash"]},"angular-ui-router":{deps:["angular"]},"angular-bootstrap":{deps:["angular"]},"angular-bootstrap-tpls":{deps:["angular","angular-bootstrap"]}}}),c("ng-admin",["require","angular","MainModule","CrudModule"],function(a){var b=a("angular");a("MainModule"),a("CrudModule"),b.module("ng-admin",["main","crud"])}),b("ng-admin")}); +//# sourceMappingURL=ng-admin.min.map \ No newline at end of file diff --git a/public/assets/ngadmin/vendor/ng-admin.min.map b/public/assets/ngadmin/vendor/ng-admin.min.map new file mode 100644 index 000000000..6b51b7c4c --- /dev/null +++ b/public/assets/ngadmin/vendor/ng-admin.min.map @@ -0,0 +1 @@ +{"version":3,"file":"ng-admin.min.js","sources":["ng-admin.min.js"],"names":["root","factory","define","amd","exports","module","ngAdmin","this","requirejs","require","undef","hasProp","obj","prop","hasOwn","call","normalize","name","baseName","nameParts","nameSegment","mapValue","foundMap","lastIndex","foundI","foundStarMap","starI","i","j","part","baseParts","split","map","config","starMap","charAt","slice","length","nodeIdCompat","jsSuffixRegExp","test","replace","concat","splice","join","indexOf","substring","makeRequire","relName","forceSync","args","aps","arguments","push","req","apply","makeNormalize","makeLoad","depName","value","defined","callDep","waiting","defining","main","Error","splitPrefix","prefix","index","makeConfig","makeMap","handlers","Object","prototype","hasOwnProperty","plugin","parts","f","n","pr","p","e","id","uri","deps","callback","cjsModule","ret","usingExports","callbackType","load","undefined","alt","setTimeout","cfg","_defined","jQuery","window","angular","inherit","parent","extra","extend","merge","dst","forEach","key","ancestors","first","second","path","objectKeys","object","keys","result","val","array","Array","Number","len","from","Math","ceil","floor","inheritParams","currentParams","newParams","$current","$to","parentParams","parents","inherited","inheritList","params","equalForKeys","a","b","k","filterByKeys","values","filtered","omit","copy","filter","collection","isArray","$Resolve","$q","$injector","VISIT_IN_PROGRESS","VISIT_DONE","NOTHING","NO_DEPENDENCIES","NO_LOCALS","NO_PARENT","when","$$promises","$$values","study","invocables","visit","visited","cycle","isString","plan","get","annotate","param","pop","isResolve","isObject","then","invocableKeys","locals","self","done","wait","merged","$$inheritedValues","resolution","resolve","fail","reason","$$failure","reject","invoke","invocable","onfailure","invocation","proceed","isDefined","promise","defer","waitParams","dep","promises","ii","$TemplateFactory","$http","$templateCache","fromConfig","template","fromString","templateUrl","fromUrl","templateProvider","fromProvider","isFunction","url","cache","headers","Accept","response","data","provider","UrlMatcher","pattern","parentMatcher","addParameter","type","location","paramNames","$$UMFP","Param","quoteRegExp","string","squash","surroundPattern","matchDetails","m","isSearch","regexp","segment","last","RegExp","placeholder","searchPlaceholder","compiled","segments","$$new","ParamSet","source","exec","search","sourceSearch","sourcePath","strict","caseInsensitive","$$paramNames","Type","$UrlMatcherFactory","valToString","toString","valFromString","regexpMatches","getDefaultConfig","isStrictMode","isCaseInsensitive","isInjectable","flushTypeQueue","typeQueue","shift","$types","injector","def","defaultSquashPolicy","enqueue","defaultTypes","encode","decode","is","int","parseInt","bool","date","getFullYear","getMonth","getDate","match","capture","Date","isNaN","valueOf","equals","toISOString","json","toJson","fromJson","any","identity","$$getDefaultValue","strictMode","compile","isMatcher","o","definition","definitionFn","$get","unwrapShorthand","isShorthand","$$fn","getType","urlType","getArrayMode","arrayDefaults","arrayParamNomenclature","getSquashPolicy","isOptional","getReplace","arrayMode","configuredKeys","defaultPolicy","to","item","$value","hasReplaceVal","$replace","replacement","$asArray","dynamic","$$parent","$$keys","chain","ignore","reverse","paramset","paramValues","$$equals","paramValues1","paramValues2","equal","left","right","$$validates","$UrlRouterProvider","$locationProvider","$urlMatcherFactory","regExpPrefix","re","interpolate","what","handleIfMatch","handler","$match","$location","$rootScope","$browser","appendBasePath","isHtml5","absolute","baseHref","update","evt","check","rule","handled","defaultPrevented","ignoreUpdate","lastPushedUrl","rules","otherwise","listen","listener","$on","interceptDeferred","sync","read","urlMatcher","options","format","$$avoidResync","href","validates","html5Mode","enabled","hashPrefix","slash","port","protocol","host","redirect","handlerIsString","strategies","matcher","regex","global","sticky","deferIntercept","$inject","$StateProvider","$urlRouterProvider","isRelative","stateName","findState","stateOrName","base","isStr","rel","pathLength","current","state","states","queueState","parentName","queue","flushQueuedChildren","queued","registerState","lastIndexOf","stateBuilder","$delegates","abstractKey","$stateParams","$state","navigable","transitionTo","isGlob","text","doesStateMatchGlob","glob","globSegments","unshift","MAX_VALUE","l","decorator","func","$view","$resolve","$urlRouter","handleRedirect","$broadcast","TransitionAborted","retry","$retry","TransitionFailed","retryTransition","transition","TransitionSuperseded","toParams","resolveState","paramsAreFiltered","globals","views","view","injectables","$template","notify","controllerProvider","injectLocals","$$controller","controller","$$state","$$controllerAs","controllerAs","all","TransitionPrevented","reload","go","relative","fromParams","fromPath","toState","redirectResult","toPath","keep","toLocals","ownParams","shouldTriggerReload","reloadOnSearch","resolved","entering","exiting","onExit","onEnter","error","includes","lossy","nav","context","compositeName","abstract","$ViewProvider","$templateFactory","defaults","async","$ViewScrollProvider","useAnchorScroll","$anchorScroll","$timeout","$element","scrollIntoView","$ViewDirective","$uiViewScroll","$interpolate","getService","service","has","getRenderer","attrs","scope","statics","enter","element","target","cb","after","leave","remove","$animate","$animator","animate","directive","restrict","terminal","priority","transclude","tElement","tAttrs","$transclude","cleanupLastView","previousEl","currentScope","$destroy","currentEl","renderer","updateView","firstTime","newScope","getUiViewName","previousLocals","latestLocals","$new","clone","$emit","autoScrollExp","$eval","onloadExp","onload","autoscroll","$ViewDirectiveFill","$compile","$controller","initial","html","link","contents","$scope","children","uiView","inheritedData","parseStateRef","ref","parsed","preparsed","paramExpr","stateContext","el","stateData","$StateRefDirective","allowedOptions","uiSrefActive","uiSref","newHref","isAnchor","isForm","nodeName","attr","optionsOverride","uiSrefOpts","option","newVal","activeDirective","$$setStateInfo","$set","$watch","bind","button","which","ctrlKey","metaKey","shiftKey","preventDefault","ignorePreventDefaultCount","cancel","$StateRefActiveDirective","$attrs","isMatch","addClass","activeClass","removeClass","uiSrefActiveEq","newState","$IsStateFilter","isFilter","$stateful","$IncludedByStateFilter","includesFilter","defaultConfig","searchParams","decodePathArray","reverseString","str","unquoteDashes","allReversed","paramName","parameters","nTotal","nPath","paramVal","encodeDashes","encodeURIComponent","c","charCodeAt","toUpperCase","isPathParam","isDefaultValue","encoded","nextSegment","$subPattern","sub","substr","mode","ArrayType","bindTo","callbackName","arrayWrap","arrayUnwrap","falsey","arrayHandler","allTruthyMode","arrayEqualsHandler","val1","val2","$arrayMode","run","t","r","u","U","h","g","false","null","number","true","_","s","V","tt","Fe","H","me","J","Te","Q","__chain__","__wrapped__","X","be","nt","wt","$e","Z","ce","K","Ae","T","F","W","P","z","C","input","St","ke","Ut","__bindData__","De","funcNames","funcDecomp","ge","O","E","Mt","et","v","rt","st","ut","yt","ot","D","q","oe","$","constructor","dt","it","Pe","at","he","Re","ft","y","lt","createCallback","ct","ie","we","pt","Be","Wt","vt","pe","ht","gt","We","mt","bt","sort","_t","jt","kt","xt","Xt","Ct","Ie","Ot","Nt","It","Et","Rt","At","Dt","$t","Tt","Ft","Bt","Se","zt","qt","Pt","Kt","Ve","Lt","Vt","ve","Ue","_e","leading","maxWait","trailing","Gt","Ht","Jt","Qt","Y","G","pick","A","Yt","Boolean","Zt","ne","Function","te","ee","ue","String","TypeError","ae","fe","le","se","clearTimeout","ye","getPrototypeOf","de","je","defineProperty","create","xe","Ce","isFinite","Oe","Ne","max","min","Ee","random","B","support","templateSettings","escape","evaluate","N","variable","imports","M","&","<",">","\"","'","qe","ze","Ke","Le","Me","now","getTime","Ge","d","I","assign","bindAll","bindKey","compact","compose","constant","countBy","curry","debounce","delay","difference","flatten","forEachRight","forIn","forInRight","forOwn","forOwnRight","functions","groupBy","indexBy","intersection","invert","mapValues","memoize","once","pairs","partial","partialRight","pluck","property","pull","range","rest","shuffle","sortBy","tap","throttle","L","times","toArray","transform","union","uniq","where","without","wrap","xor","zip","zipObject","collect","drop","each","eachRight","methods","select","tail","unique","unzip","cloneDeep","contains","every","find","findIndex","findKey","findLast","findLastIndex","findLastKey","isArguments","isBoolean","isDate","isElement","nodeType","isEmpty","isEqual","parseFloat","isNull","isNumber","isPlainObject","isRegExp","isUndefined","mixin","noConflict","noop","reduce","reduceRight","runInContext","size","some","sortedIndex","S","x","R","w","unescape","uniqueId","detect","findWhere","foldl","foldr","include","inject","sample","take","head","VERSION","configurable","enumerable","writable","boolean","function","\\","\n","\r","\t","
","
","Configurer","init","RestangularResource","configurer","resource","defaultRequestParams","method","toLowerCase","isSafe","configuration","safeMethods","operation","absolutePattern","isAbsoluteUrl","absoluteUrl","setSelfLinkAbsoluteUrl","baseUrl","setBaseUrl","newBaseUrl","extraFields","setExtraFields","newExtraFields","defaultHttpFields","setDefaultHttpFields","withHttpValues","httpLocalConfig","encodeIds","setEncodeIds","post","put","common","setDefaultRequestParams","param1","param2","requestParams","defaultHeaders","setDefaultHeaders","methodOverriders","setMethodOverriders","overriders","isOverridenMethod","jsonp","setJsonp","active","one","urlCreator","setUrlCreator","urlCreatorFactory","restangularFields","route","parentResource","restangularCollection","cannonicalId","etag","selfLink","getList","trace","patch","getRestangularUrl","getRequestedUrl","putElement","addRestangularMethod","getParentList","ids","httpConfig","reqParams","several","oneUrl","allUrl","customPUT","customPOST","customDELETE","customGET","customGETLIST","customOperation","doPUT","doPOST","doDELETE","doGET","doGETLIST","fromServer","withConfig","withHttpConfig","singleOne","plain","save","setRestangularFields","resFields","isRestangularized","setFieldToElem","field","elem","properties","idValue","getFieldFromElem","setIdToElem","getIdFromElem","isValidId","elemId","setUrlToElem","getUrlFromElem","useCannonicalId","setUseCannonicalId","getCannonicalIdFromElem","actualId","responseInterceptors","defaultResponseInterceptor","responseExtractor","deferred","interceptors","theData","interceptor","addResponseInterceptor","extractor","setResponseInterceptor","setResponseExtractor","requestInterceptors","defaultInterceptor","fullRequestInterceptor","defaultRequest","request","addRequestInterceptor","setRequestInterceptor","addFullRequestInterceptor","setFullRequestInterceptor","errorInterceptor","setErrorInterceptor","onBeforeElemRestangularized","setOnBeforeElemRestangularized","onElemRestangularized","setOnElemRestangularized","shouldSaveParent","setParentless","suffix","setRequestSuffix","newSuffix","transformers","addElementTransformer","secondArg","thirdArg","isCollection","transformer","typeTransformers","coll","extendCollection","fn","extendModel","transformElem","Restangular","force","transformLocalElements","changedElem","setTransformOnlyServerElements","fullResponse","setFullResponse","full","BaseCreator","setConfig","parentsArray","localHttpConfig","callHeaders","callParams","add","Path","__this","acum","elemUrl","elemSelfLink","fetchUrl","fetchRequestedUrl","sortedKeys","forEachSorted","iterator","encodeUriQuery","pctEncodeSpaces","globalConfiguration","createServiceForConfiguration","restangularizeBase","urlHandler","addRestangularMethodFunction","copyRestangularizedElement","stripRestangular","parentId","parentUrl","restangularFieldsForParent","restangularizeElem","restangularizeCollection","restangularizePromise","valueToFill","promiseCall","promiseGet","$object","callArgs","filledValue","resolvePromise","addCustomOperation","customFunction","oper","alias","callFunction","callOperation","fetchFunction","fromElement","toElement","copiedElement","localElem","getFunction","putFunction","postFunction","deleteFunction","headFunction","traceFunction","optionsFunction","patchFunction","putElementFunction","getById","restangularizeCollectionAndElements","idx","elemToPut","filledArray","serverElem","newArray","parseResponse","resData","whatFetched","fullParams","processedData","status","elemFunction","resParams","callObj","filledObject","okCallback","errorCallback","isOverrideOperation","X-HTTP-Method-Override","defaultParams","defaultElem","bindedFunction","createdFunction","withConfigurationFunction","newConfig","toService","serv","restangularizeElement","AppController","Configuration","applicationName","title","destroy","displayHome","DashboardController","PanelBuilder","edit","retrievePanels","panels","getPanelsData","entry","entityName","identifierValue","getEntities","entitiesWithOrder","entity","menuView","isEnabled","order","entities","SidebarController","$sce","computeCurrentEntity","urlParts","currentEntity","displayList","isActive","getIconForEntity","trustAsHtml","icon","$filter","RetrieveQueries","dashboardView","dashboardViews","getViewsOfType","sortField","sortDir","getAll","panelData","label","viewName","fields","displayedFields","getEntity","perPage","entries","Validator","validate","validation","getFields","validator","propertyName","defaultTransformParams","defaultCustomTemplate","Application","Configurable","baseApiUrl","transformParams","customTemplate","addEntity","hasEntity","getEntityNames","getViewByType","getRouteFor","entityId","getUrl","getQueryParamsFor","oldParams","getQueryParams","getViewByEntityAndType","inherits","child","Wrapper","camelCase","group1","defaultValueTemplate","Field","fieldName","utils","isDetailLink","maps","availableTypes","editable","displayed","identifier","list","dashboard","required","minlength","maxlength","choices","defaultValue","attributes","cssClasses","getMappedValue","getCssClasses","getTemplateValue","isEditLink","console","warn","Entry","listValues","View","actions","description","extraParams","disable","enable","setEntity","addField","getFieldsOfType","results","getField","getReferences","references","referencesMany","getReferencedLists","getExtraParams","getHeaders","identifierField","mapEntries","rawEntries","mapEntry","rawEntry","resultEntity","removeFields","processFieldsDefaultValue","defaultSortParams","dir","_sort","_sortDir","defaultPaginationLink","page","maxPerPage","per_page","defaultFilterQuery","defaultFilterParams","defaultTotalItems","ListView","quickFilters","pagination","filterQuery","filterParams","infinitePagination","totalItems","sortParams","listActions","addQuickFilter","getQuickFilterNames","getQuickFilterParams","getSortParams","getAllParams","getAllHeaders","DashboardView","limit","MenuView","FilterView","ShowView","CreateView","getFormName","showAttributeSuccess","EditView","DeleteView","Entity","isReadOnly","initViews","getPropertyNameBasedOnViewType","viewType","filterView","listView","showView","creationView","editionView","deletionView","getValue","setValue","addView","readOnly","addMappedField","Reference","referencedValue","referencedView","referencedViewConfigured","singleApiCall","targetEntity","targetField","getChoicesById","targetLabel","targetIdentifier","getReferencedView","getSingleApiCall","identifiers","getSortFieldName","getIdentifierValues","rawValues","identifierName","getEntries","setEntries","getListValue","ReferencedList","edition","targetReferenceField","targetFields","getGridColumns","columns","clear","ReferenceMany","NgAdminConfiguration","configure","OrderElement","objectKey","field1","field2","fs","Cc","Ci","xpcIsWindows","progIds","xmlRegExp","bodyRegExp","hasLocation","defaultProtocol","defaultHostName","hostname","defaultPort","buildMap","masterConfig","version","strip","content","matches","jsEscape","createXhr","xhr","progId","XMLHttpRequest","ActiveXObject","parseName","modName","ext","temp","moduleName","xdRegExp","useXhr","uProtocol","uHostName","uPort","finishLoad","onLoad","isBuild","inlineText","nonStripName","toUrl","err","write","pluginName","asModule","writeFile","extPart","fileName","textWrite","env","process","versions","node","nodeRequire","errback","file","readFileSync","header","open","setRequestHeader","onXhr","onreadystatechange","readyState","responseText","onXhrComplete","send","Packages","java","stringBuffer","line","encoding","io","File","lineSeparator","lang","System","getProperty","BufferedReader","InputStreamReader","FileInputStream","StringBuffer","readLine","append","close","Components","classes","interfaces","inStream","convertStream","fileObj","readData","FileUtils","createInstance","nsIFileInputStream","nsIConverterInputStream","available","DEFAULT_REPLACEMENT_CHARACTER","readString","maDashboardPanel","dashboardPanelView","Menu","http","$httpProvider","useApplyAsync","routing","$stateProvider","layoutTemplate","dashboardTemplate","loader","$window","progression","start","scrollTo","MainModule","inflection","_apply_rules","pluralize","singularize","inflect","camelize","underscore","humanize","capitalize","dasherize","titleize","demodulize","tableize","classify","foreign_key","ordinalize","$SanitizeProvider","$$sanitizeUri","buf","htmlParser","htmlSanitizeWriter","isImage","sanitizeText","chars","writer","items","parseStartTag","tag","tagName","unary","lowercase","blockElements","stack","inlineElements","parseEndTag","optionalEndTagElements","voidElements","ATTR_REGEXP","doubleQuotedValue","singleQuotedValue","unquotedValue","decodeEntities","pos","end","specialElements","COMMENT_REGEXP","CDATA_REGEXP","comment","DOCTYPE_REGEXP","BEGING_END_TAGE_REGEXP","END_TAG_REGEXP","BEGIN_TAG_REGEXP","START_TAG_REGEXP","$sanitizeMinErr","spaceRe","spaceBefore","spaceAfter","hiddenPre","innerHTML","textContent","innerText","encodeEntities","SURROGATE_PAIR_REGEXP","hi","low","NON_ALPHANUMERIC_REGEXP","uriValidator","out","validElements","lkey","validAttrs","uriAttrs","$$minErr","optionalEndTagBlockElements","optionalEndTagInlineElements","svgElements","htmlAttrs","svgAttrs","document","createElement","$sanitize","LINKY_URL_REGEXP","MAILTO_REGEXP","addText","addLink","raw","style","animation","$apply","unbind","css","WebkitTransition","MozTransition","OTransition","transitionEndEventName","animationEndEventName","height","scrollHeight","offsetWidth","collapse","closeOthers","groups","isOpen","addGroup","removeGroup","heading","isDisabled","setHeading","toggleOpen","accordionTransclude","closeable","dismissOnTimeout","bindHtmlUnsafe","toggleEvent","$render","toggleClass","$modelValue","btnRadio","hasClass","uncheckable","$setViewValue","btnCheckboxTrue","btnCheckboxFalse","interval","next","pause","slides","currentSlide","noTransition","direction","leaving","$currentTransition","indexOfSlide","prev","play","noPause","addSlide","removeSlide","parsers","yyyy","year","yy","MMMM","DATETIME_FORMATS","MONTH","month","MMM","SHORTMONTH","MM","dd","EEEE","DAY","EEE","SHORTDAY","parse","hours","currentStyle","getComputedStyle","offsetParent","position","offset","top","clientTop","scrollTop","clientLeft","scrollLeft","getBoundingClientRect","width","pageYOffset","documentElement","pageXOffset","positionElements","center","bottom","formatDay","formatMonth","formatYear","formatDayHeader","formatDayTitle","formatMonthTitle","datepickerMode","minMode","maxMode","showWeeks","startingDay","yearRange","minDate","maxDate","modes","$parent","refreshView","$id","activeDate","initDate","compare","activeDateId","uid","render","$setValidity","_refreshView","createDateObject","selected","disabled","dateDisabled","setFullYear","move","step","years","months","toggleMode",13,32,33,34,35,36,37,38,39,40,"focus","keydown","altKey","stopPropagation","handleKeyDown","setHours","setDate","getDay","setMonth","round","secondary","labels","abbr","rows","weekNumbers","datepickerPopup","currentText","clearText","closeText","closeOnDateSelection","appendToBody","showButtonBar","datepickerAppendToBody","getText","$observe","ng-model","ng-change","datepickerOptions","watchData","$parsers","dateSelection","$viewValue","openClass","getToggleElement","focusToggleElement","onToggle","toggle","toggleElement","aria-haspopup","aria-expanded","createNew","removeTop","backdropClass","windowClass","querySelectorAll","getTop","backdrop","currentTarget","dismiss","empty","eq","modalDomEl","modalScope","keyboard","template-url","windowTemplateUrl","window-class","dismissAll","opened","$close","$dismiss","$modalInstance","numPages","itemsPerPage","totalPages","calculateTotalPages","selectPage","noPrevious","noNext","boundaryLinks","directionLinks","firstText","previousText","nextText","lastText","rotate","maxSize","pages","align","placement","popupDelay","mouseenter","click","setTriggers","trigger","show","hide","startSymbol","endSymbol","display","$digest","bars","addBar","percent","toFixed","removeBar","stateOn","stateOff","ratingStates","buildTemplateObjects","rate","readonly","onHover","reset","onLeave","onKeydown","tabs","onDeselect","onSelect","addTab","removeTab","vertical","justified","$transcludeFn","hasAttribute","tabContentTransclude","headingElement","hourStep","minuteStep","showMeridian","meridians","readonlyInput","mousewheel","meridian","minutes","invalidHours","invalidMinutes","getHours","getMinutes","AMPMS","setupMousewheelEvents","setupInputEvents","$error","time","originalEvent","wheelDelta","deltaY","detail","incrementHours","decrementHours","incrementMinutes","decrementMinutes","updateHours","updateMinutes","setMinutes","toggleMeridian","itemName","viewMapper","modelMapper","typeaheadMinLength","typeaheadWaitMs","typeaheadEditable","typeaheadLoading","typeaheadOnSelect","typeaheadInputFormatter","typeaheadAppendToBody","typeaheadFocusFirst","ngModel","typeahead","aria-autocomplete","aria-owns","query","typeaheadTemplateUrl","activeIdx","removeAttr","model","$formatters","$model","$item","$label","selectActive","selectMatch","success","replaceWith","trim","toolbar","focussed","toolbarGroup","toolbarButton","toolbarButtonActive","textEditor","htmlEditor","setup","textEditorSetup","htmlEditorSetup","defaultFileDropHandler","FileReader","readAsDataURL","selector","customAttribute","renderLogic","buttontext","tooltip","pre","ul","ol","quote","undo","redo","bold","italic","underline","justifyLeft","justifyRight","justifyCenter","indent","outdent","insertImage","dialogPrompt","hotkey","insertVideo","insertLink","tooltiptext","action","$editor","switchView","activeState","showHtml","queryFormatBlockState","wrapSelection","iconclass","queryCommandState","commandKeyCode","getSelectionElement","displayElements","updateTaBindtaTextElement","hidePopover","popover","popoverContainer","on","showPopover","showResizeOverlay","prompt","onElementSelect","onlyWithAttrs","max-width","overflow","text-overflow","white-space","vertical-align","navigator","userAgent","addEventListener","event","contentEditable","parentNode","getElementById","setSelectionRange","ready","body","appendChild","createTextNode","insertBefore","firstChild","sheet","cssRules","insertRule","addRule","removeRule","deleteRule","serial","off","taDefaultWrap","taFocussedClass","taTextEditorClass","taHtmlEditorClass","taTextEditorSetup","taHtmlEditorSetup","fileDropHandler","taFileDrop","forminput","scrollWindow","popoverArrow","resize","overlay","background","anchors","info","reflowPopover","offsetHeight","offsetTop","offsetLeft","reflowResizeOverlay","clientX","clientY","hideResizeOverlay","ng-show","ta-bind","ng-hide","taUnsafeSanitizer","tabindex","taDisabled","updateTaBindtaHtmlElement","_actionRunning","startAction","rangy","saveSelection","restoreSelection","endAction","removeMarkers","updateSelectedStyles","activeElement","unfocus","triggerHandler","queryCommandValue","_elementSelectTriggered","taTargetToolbars","registerEditor","taToolbar","taToolbarClass","taToolbarGroupClass","taToolbarButtonClass","taToolbarActiveButtonClass","prepend","unregisterEditor","triggerElementSelect","files","_bUpdateSelectedStyles","sendKeyCommand","setSelectionToElementEnd","getOnlySelectedElements","childNodes","outerHTML","removeChild","execCommand","disableSanitizer","clipboardData","getData","selection","createRange","pasteHTML","keyCode","setSelectionToElementStart","$oldViewValue","dataTransfer","taReadonly","taMaxText","$dirty","taMinText","_$element","_display","_lastToolDefinition","tools","_parent","displayActiveToolClass","executeAction","updateToolDisplay","addTool","registerToolbar","unregisterToolbar","toolbars","_registerToolbar","editorFunctions","tool","retrieveEditor","retrieveToolbar","retrieveToolbarsViaEditor","updateToolsDisplay","resetToolsDisplay","resetToolDisplay","updateToolbarToolDisplay","resetToolbarToolDisplay","removeTool","group","addToolToToolbar","refreshEditor","$$phase","hasChildNodes","nextSibling","startContainer","endContainer","commonAncestorContainer","getSelection","isCollapsed","getRangeAt","parentElement","rangeCount","setStart","anchorNode","anchorOffset","setEnd","focusNode","focusOffset","collapsed","selectNodeContents","removeAllRanges","addRange","createTextRange","moveToElementText","moveEnd","moveStart","arr","ListController","loadingPage","filters","hasFilters","nextPageCallback","nextPage","nextData","ShowController","FormController","CreateQueries","UpdateQueries","notification","form","$event","mappedObject","log","addnCls","submitCreation","$valid","createOne","handleError","getValidationClassForField","submitEdition","updateOne","JSON","stringify","DeleteController","DeleteQueries","entityLabel","deleteOne","back","Queries","getOne","routeUrl","fillSimpleReference","referencedValues","getRawValues","getReferencedValues","refValues","fillReferencesValuesFromCollection","currentPage","sortView","singleCallFilters","reference","calls","responses","getReferencedListValues","referenceList","referenceLists","fillReferencesValuesFromEntry","referenceField","rawEntity","maChoiceField","maChoicesField","maDateField","toggleDatePicker","maInputField","maCheckboxField","maTextField","maWysiwygField","TemplateField","templateFieldView","ListActionsDirective","buttons","listActionsTemplate","DatagridController","gotoDetail","clearRouteParams","isSorting","getSortName","itemClass","maDatagridDirective","datagridView","DatagridPaginationController","computePagination","displayPagination","hasPagination","infinite","offsetEnd","offsetBegin","nbPages","setPage","DatagridPaginationDirective","$document","paginationView","getAttribute","innerHeight","scrollY","QuickFilterController","currentQuickFilter","quickFilter","canDisplayQuickFilters","maQuickFilterDirective","quickFilterView","FilterViewController","filterFields","isFilterEmpty","shouldFilter","clearFilters","maFilterViewDirective","maColumn","isReference","referenceEntity","relatedEntity","gotoReference","referenceId","maBooleanColumn","isOk","maChoicesColumn","maDateColumn","maPasswordColumn","maReferencedListColumn","maReferenceManyColumn","maReferenceManyLinkColumn","maStringColumn","maTemplateColumn","maWysiwygColumn","maBackButtonDirective","history","maCreateButtonDirective","gotoCreate","maEditButtonDirective","gotoEdit","maShowButtonDirective","gotoShow","maListButtonDirective","gotoList","maDeleteButtonDirective","gotoDelete","ViewActionsDirective","override","viewActionsTemplate","transcludeFn","Compile","cacheTemplate","editAttributeTemplate","defaultView","viewProvider","listTemplate","showTemplate","referencedListValues","createTemplate","editTemplate","deleteTemplate","win","doc","ENV","attachEvent","removeEventListener","detachEvent","ctx","preferred","fallback","transSupport","useFilter","_checkTransition","vendors","webkit","Moz","ms","vendor","vendorPrefix","Humane","baseCls","timeout","waitForMove","clickToClose","timeoutAfterMove","container","_setupEl","removeEvent","currentMsg","transEvent","_afterAnimation","_run","_afterTimeout","removeEventsSet","_animating","currentTimer","msg","className","_showMsg","_setOpacity","opacity","Opacity","setInterval","clearInterval","_hideMsg","opt","spawn","NProgress","clamp","toBarPerc","barPositionCSS","speed","ease","barCSS","Settings","positionUsing","margin-left","classList","oldList","newList","removeElement","settings","minimum","easing","trickle","trickleRate","trickleSpeed","showSpinner","barSelector","spinnerSelector","set","started","isStarted","progress","bar","querySelector","getPositioningCSS","work","inc","amount","$promise","always","fromStart","isRendered","spinner","perc","bodyStyle","pending","letter","getVendorProp","vendorName","cssPrefixes","capName","getStyleProp","cssProps","applyCss","CrudModule","$provide","$delegate","oldParse","paths","angular-resource","angular-sanitize","angular-ui-router","lodash","angular-bootstrap","angular-bootstrap-tpls","restangular","ngInflection","humane","nprogress","textangular","shim"],"mappings":"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"} \ No newline at end of file From 522791bd7356bda17fa6a4525ce8281534ff1a55 Mon Sep 17 00:00:00 2001 From: thangngoc89 Date: Tue, 30 Dec 2014 23:37:01 +0700 Subject: [PATCH 10/19] Wrap User::destroy in try ... catch ... block --- app/controllers/api/UserV2Controller.php | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/app/controllers/api/UserV2Controller.php b/app/controllers/api/UserV2Controller.php index 5c0d44a9f..988a5fd94 100644 --- a/app/controllers/api/UserV2Controller.php +++ b/app/controllers/api/UserV2Controller.php @@ -17,7 +17,7 @@ public function index() { try{ $statusCode = 200; - $builder = ApiHandler::parseMultiple($this->user->with('history'), array('name,username'), $this->passParams('users')); + $builder = ApiHandler::parseMultiple($this->user, array('name,email'), $this->passParams('users')); $users = $builder->getResult(); $response = []; foreach($users as $user){ @@ -86,9 +86,19 @@ public function update($id) */ public function destroy($id) { - $user = $this->user->findOrFail($id); - $user->delete(); - return 'Deleted'; + try{ + $statusCode = 200; + $user = $this->user->findOrFail($id); + $user->delete(); + + $response = "Deleted User ID $id"; + return Response::json($response,$statusCode); + + }catch (Exception $e){ + $statusCode = 500; + $error = $e->getMessage(); + return Response::json($error, $statusCode); + } } private function responseMap($object) From 576657bbd5abdf52ea914d7c7786c77733f842d4 Mon Sep 17 00:00:00 2001 From: thangngoc89 Date: Tue, 30 Dec 2014 23:52:18 +0700 Subject: [PATCH 11/19] Minor fixes in API --- app/controllers/api/APIController.php | 34 ++++++++++++++++++++++++ app/controllers/api/UserV2Controller.php | 3 ++- 2 files changed, 36 insertions(+), 1 deletion(-) diff --git a/app/controllers/api/APIController.php b/app/controllers/api/APIController.php index 835c0a94f..6cd5099bd 100644 --- a/app/controllers/api/APIController.php +++ b/app/controllers/api/APIController.php @@ -12,6 +12,12 @@ public function __construct() parent::__construct(); } + + /** + * Transform ng-admin request into Laravel Api Handler + * @param $table_name + * @return array + */ public function passParams($table_name){ //Print out all table's columns $columns = Schema::getColumnListing($table_name); @@ -52,7 +58,35 @@ public function passParams($table_name){ $params ['_config'] = 'meta-filter-count'; return $params; } + + /** + * Make a quick response with pagination supported + * @param $response + * @param $statusCode + * @param $builder + * @return mixed + */ public function makeResponse($response,$statusCode, $builder){ return Response::json($response,$statusCode)->header('X-Total-Count', $builder->getHeaders()['Meta-Filter-Count']); } + + /* Testing purpose + public function returnIndex($eloquentModel, $fulltext = [], $table_name){ + try{ + $statusCode = 200; + $builder = ApiHandler::parseMultiple($eloquentModel, $fulltext = [], $this->passParams($table_name)); + $users = $builder->getResult(); + $response = []; + + foreach($users as $user){ + $response[] = $this->responseMap($user); + } + + return Response::json($response,$statusCode)->header('X-Total-Count', $builder->getHeaders()['Meta-Filter-Count']); + } catch (Exception $e){ + $statusCode = 500; + $message = $e->getMessage(); + return Response::json($message, $statusCode); + } + }*/ } \ No newline at end of file diff --git a/app/controllers/api/UserV2Controller.php b/app/controllers/api/UserV2Controller.php index 988a5fd94..dd0e50e8e 100644 --- a/app/controllers/api/UserV2Controller.php +++ b/app/controllers/api/UserV2Controller.php @@ -20,12 +20,13 @@ public function index() $builder = ApiHandler::parseMultiple($this->user, array('name,email'), $this->passParams('users')); $users = $builder->getResult(); $response = []; + foreach($users as $user){ $response[] = $this->responseMap($user); } return $this->makeResponse($response,$statusCode, $builder); - }catch (Exception $e){ + } catch (Exception $e){ $statusCode = 500; $message = $e->getMessage(); return Response::json($message, $statusCode); From e62ef74f9d6182e46bc1e4134470830e46a5754c Mon Sep 17 00:00:00 2001 From: thangngoc89 Date: Wed, 31 Dec 2014 00:39:57 +0700 Subject: [PATCH 12/19] Use Bower to manage assets --- public/admincp/app.js | 161 + public/admincp/bower.json | 10 + .../angular-bootstrap/.bower.json | 29 + .../angular-bootstrap/bower.json | 17 + .../angular-bootstrap/ui-bootstrap-tpls.js | 4212 +++ .../ui-bootstrap-tpls.min.js | 10 + .../angular-bootstrap/ui-bootstrap.js | 3901 +++ .../angular-bootstrap/ui-bootstrap.min.js | 9 + .../angular-cookies/.bower.json | 19 + .../angular-cookies/README.md | 77 + .../angular-cookies/angular-cookies.js | 206 + .../angular-cookies/angular-cookies.min.js | 8 + .../angular-cookies.min.js.map | 8 + .../angular-cookies/bower.json | 9 + .../angular-cookies/package.json | 26 + .../angular-resource/.bower.json | 19 + .../angular-resource/README.md | 77 + .../angular-resource/angular-resource.js | 667 + .../angular-resource/angular-resource.min.js | 13 + .../angular-resource.min.js.map | 8 + .../angular-resource/bower.json | 9 + .../angular-resource/package.json | 26 + .../angular-sanitize/.bower.json | 19 + .../angular-sanitize/README.md | 77 + .../angular-sanitize/angular-sanitize.js | 680 + .../angular-sanitize/angular-sanitize.min.js | 16 + .../angular-sanitize.min.js.map | 8 + .../angular-sanitize/bower.json | 9 + .../angular-sanitize/package.json | 26 + .../angular-ui-router/.bower.json | 33 + .../angular-ui-router/CHANGELOG.md | 197 + .../angular-ui-router/CONTRIBUTING.md | 65 + .../angular-ui-router/LICENSE | 21 + .../angular-ui-router/README.md | 243 + .../api/angular-ui-router.d.ts | 126 + .../angular-ui-router/bower.json | 23 + .../release/angular-ui-router.js | 4232 +++ .../release/angular-ui-router.min.js | 7 + .../angular-ui-router/src/common.js | 292 + .../angular-ui-router/src/resolve.js | 252 + .../angular-ui-router/src/state.js | 1373 + .../angular-ui-router/src/stateDirectives.js | 268 + .../angular-ui-router/src/stateFilters.js | 39 + .../angular-ui-router/src/templateFactory.js | 110 + .../src/urlMatcherFactory.js | 1036 + .../angular-ui-router/src/urlRouter.js | 413 + .../angular-ui-router/src/view.js | 71 + .../angular-ui-router/src/viewDirective.js | 302 + .../angular-ui-router/src/viewScroll.js | 52 + .../bower_components/angular/.bower.json | 17 + .../bower_components/angular/README.md | 67 + .../bower_components/angular/angular-csp.css | 13 + .../bower_components/angular/angular.js | 26070 ++++++++++++++++ .../bower_components/angular}/angular.min.js | 0 .../angular/angular.min.js.gzip | Bin 0 -> 45930 bytes .../angular/angular.min.js.map | 8 + .../bower_components/angular/bower.json | 8 + .../bower_components/angular/package.json | 25 + .../bootstrap-sass-official/.bower.json | 59 + .../bootstrap-sass-official/CHANGELOG.md | 160 + .../bootstrap-sass-official/CONTRIBUTING.md | 79 + .../bootstrap-sass-official/LICENSE | 21 + .../bootstrap-sass-official/README.md | 346 + .../glyphicons-halflings-regular.eot | Bin 0 -> 20335 bytes .../glyphicons-halflings-regular.svg | 229 + .../glyphicons-halflings-regular.ttf | Bin 0 -> 41280 bytes .../glyphicons-halflings-regular.woff | Bin 0 -> 23320 bytes .../assets/javascripts/bootstrap-sprockets.js | 12 + .../assets/javascripts/bootstrap.js | 2304 ++ .../assets/javascripts/bootstrap/affix.js | 162 + .../assets/javascripts/bootstrap/alert.js | 94 + .../assets/javascripts/bootstrap/button.js | 116 + .../assets/javascripts/bootstrap/carousel.js | 240 + .../assets/javascripts/bootstrap/collapse.js | 211 + .../assets/javascripts/bootstrap/dropdown.js | 161 + .../assets/javascripts/bootstrap/modal.js | 324 + .../assets/javascripts/bootstrap/popover.js | 119 + .../assets/javascripts/bootstrap/scrollspy.js | 175 + .../assets/javascripts/bootstrap/tab.js | 153 + .../assets/javascripts/bootstrap/tooltip.js | 478 + .../javascripts/bootstrap/transition.js | 59 + .../stylesheets/_bootstrap-compass.scss | 7 + .../assets/stylesheets/_bootstrap-mincer.scss | 17 + .../stylesheets/_bootstrap-sprockets.scss | 7 + .../assets/stylesheets/_bootstrap.scss | 50 + .../assets/stylesheets/bootstrap/_alerts.scss | 68 + .../assets/stylesheets/bootstrap/_badges.scss | 63 + .../stylesheets/bootstrap/_breadcrumbs.scss | 26 + .../stylesheets/bootstrap/_button-groups.scss | 243 + .../stylesheets/bootstrap/_buttons.scss | 160 + .../stylesheets/bootstrap/_carousel.scss | 267 + .../assets/stylesheets/bootstrap/_close.scss | 35 + .../assets/stylesheets/bootstrap/_code.scss | 69 + .../bootstrap/_component-animations.scss | 38 + .../stylesheets/bootstrap/_dropdowns.scss | 213 + .../assets/stylesheets/bootstrap/_forms.scss | 548 + .../stylesheets/bootstrap/_glyphicons.scss | 234 + .../assets/stylesheets/bootstrap/_grid.scss | 84 + .../stylesheets/bootstrap/_input-groups.scss | 166 + .../stylesheets/bootstrap/_jumbotron.scss | 49 + .../assets/stylesheets/bootstrap/_labels.scss | 66 + .../stylesheets/bootstrap/_list-group.scss | 124 + .../assets/stylesheets/bootstrap/_media.scss | 47 + .../assets/stylesheets/bootstrap/_mixins.scss | 39 + .../assets/stylesheets/bootstrap/_modals.scss | 148 + .../assets/stylesheets/bootstrap/_navbar.scss | 662 + .../assets/stylesheets/bootstrap/_navs.scss | 244 + .../stylesheets/bootstrap/_normalize.scss | 427 + .../assets/stylesheets/bootstrap/_pager.scss | 54 + .../stylesheets/bootstrap/_pagination.scss | 88 + .../assets/stylesheets/bootstrap/_panels.scss | 261 + .../stylesheets/bootstrap/_popovers.scss | 135 + .../assets/stylesheets/bootstrap/_print.scss | 107 + .../stylesheets/bootstrap/_progress-bars.scss | 87 + .../bootstrap/_responsive-embed.scss | 35 + .../bootstrap/_responsive-utilities.scss | 174 + .../stylesheets/bootstrap/_scaffolding.scss | 150 + .../assets/stylesheets/bootstrap/_tables.scss | 234 + .../assets/stylesheets/bootstrap/_theme.scss | 272 + .../stylesheets/bootstrap/_thumbnails.scss | 38 + .../stylesheets/bootstrap/_tooltip.scss | 103 + .../assets/stylesheets/bootstrap/_type.scss | 298 + .../stylesheets/bootstrap/_utilities.scss | 56 + .../stylesheets/bootstrap/_variables.scss | 864 + .../assets/stylesheets/bootstrap/_wells.scss | 29 + .../stylesheets/bootstrap/mixins/_alerts.scss | 14 + .../bootstrap/mixins/_background-variant.scss | 11 + .../bootstrap/mixins/_border-radius.scss | 18 + .../bootstrap/mixins/_buttons.scss | 52 + .../bootstrap/mixins/_center-block.scss | 7 + .../bootstrap/mixins/_clearfix.scss | 22 + .../stylesheets/bootstrap/mixins/_forms.scss | 88 + .../bootstrap/mixins/_gradients.scss | 58 + .../bootstrap/mixins/_grid-framework.scss | 81 + .../stylesheets/bootstrap/mixins/_grid.scss | 122 + .../bootstrap/mixins/_hide-text.scss | 21 + .../stylesheets/bootstrap/mixins/_image.scss | 33 + .../stylesheets/bootstrap/mixins/_labels.scss | 12 + .../bootstrap/mixins/_list-group.scss | 31 + .../bootstrap/mixins/_nav-divider.scss | 10 + .../bootstrap/mixins/_nav-vertical-align.scss | 9 + .../bootstrap/mixins/_opacity.scss | 8 + .../bootstrap/mixins/_pagination.scss | 23 + .../stylesheets/bootstrap/mixins/_panels.scss | 24 + .../bootstrap/mixins/_progress-bar.scss | 10 + .../bootstrap/mixins/_reset-filter.scss | 8 + .../stylesheets/bootstrap/mixins/_resize.scss | 6 + .../mixins/_responsive-visibility.scss | 21 + .../stylesheets/bootstrap/mixins/_size.scss | 10 + .../bootstrap/mixins/_tab-focus.scss | 9 + .../bootstrap/mixins/_table-row.scss | 28 + .../bootstrap/mixins/_text-emphasis.scss | 11 + .../bootstrap/mixins/_text-overflow.scss | 8 + .../bootstrap/mixins/_vendor-prefixes.scss | 222 + .../bootstrap-sass-official/bower.json | 50 + .../bootstrap-sass-official/composer.json | 35 + .../bootstrap-sass-official/package.json | 30 + .../bootstrap-sass-official/sache.json | 5 + .../bower_components/bootstrap/.bower.json | 47 + .../bower_components/bootstrap/Gruntfile.js | 472 + .../bower_components/bootstrap/LICENSE | 21 + .../bower_components/bootstrap/README.md | 129 + .../bower_components/bootstrap/bower.json | 38 + .../bootstrap/dist/css/bootstrap-theme.css | 470 + .../dist/css/bootstrap-theme.css.map | 1 + .../dist/css/bootstrap-theme.min.css | 5 + .../bootstrap/dist/css/bootstrap.css | 6332 ++++ .../bootstrap/dist/css/bootstrap.css.map | 1 + .../bootstrap/dist/css/bootstrap.min.css | 5 + .../fonts/glyphicons-halflings-regular.eot | Bin 0 -> 20335 bytes .../fonts/glyphicons-halflings-regular.svg | 229 + .../fonts/glyphicons-halflings-regular.ttf | Bin 0 -> 41280 bytes .../fonts/glyphicons-halflings-regular.woff | Bin 0 -> 23320 bytes .../bootstrap/dist/js/bootstrap.js | 2320 ++ .../bootstrap/dist/js/bootstrap.min.js | 7 + .../bower_components/bootstrap/dist/js/npm.js | 13 + .../fonts/glyphicons-halflings-regular.eot | Bin 0 -> 20335 bytes .../fonts/glyphicons-halflings-regular.svg | 229 + .../fonts/glyphicons-halflings-regular.ttf | Bin 0 -> 41280 bytes .../fonts/glyphicons-halflings-regular.woff | Bin 0 -> 23320 bytes .../bootstrap/grunt/.jshintrc | 7 + .../bootstrap/grunt/bs-commonjs-generator.js | 23 + .../bootstrap/grunt/bs-lessdoc-parser.js | 238 + .../bootstrap/grunt/bs-raw-files-generator.js | 46 + .../bootstrap/grunt/configBridge.json | 44 + .../bootstrap/grunt/sauce_browsers.yml | 82 + .../bower_components/bootstrap/js/.jscsrc | 34 + .../bower_components/bootstrap/js/.jshintrc | 15 + .../bower_components/bootstrap/js/affix.js | 162 + .../bower_components/bootstrap/js/alert.js | 94 + .../bower_components/bootstrap/js/button.js | 116 + .../bower_components/bootstrap/js/carousel.js | 240 + .../bower_components/bootstrap/js/collapse.js | 211 + .../bower_components/bootstrap/js/dropdown.js | 161 + .../bower_components/bootstrap/js/modal.js | 324 + .../bower_components/bootstrap/js/popover.js | 119 + .../bootstrap/js/scrollspy.js | 175 + .../bower_components/bootstrap/js/tab.js | 153 + .../bower_components/bootstrap/js/tooltip.js | 478 + .../bootstrap/js/transition.js | 59 + .../bootstrap/less/.csscomb.json | 304 + .../bootstrap/less/.csslintrc | 19 + .../bootstrap/less/alerts.less | 68 + .../bootstrap/less/badges.less | 61 + .../bootstrap/less/bootstrap.less | 50 + .../bootstrap/less/breadcrumbs.less | 26 + .../bootstrap/less/button-groups.less | 243 + .../bootstrap/less/buttons.less | 160 + .../bootstrap/less/carousel.less | 267 + .../bootstrap/less/close.less | 33 + .../bower_components/bootstrap/less/code.less | 69 + .../bootstrap/less/component-animations.less | 34 + .../bootstrap/less/dropdowns.less | 213 + .../bootstrap/less/forms.less | 546 + .../bootstrap/less/glyphicons.less | 234 + .../bower_components/bootstrap/less/grid.less | 84 + .../bootstrap/less/input-groups.less | 166 + .../bootstrap/less/jumbotron.less | 49 + .../bootstrap/less/labels.less | 64 + .../bootstrap/less/list-group.less | 124 + .../bootstrap/less/media.less | 47 + .../bootstrap/less/mixins.less | 39 + .../bootstrap/less/mixins/alerts.less | 14 + .../less/mixins/background-variant.less | 8 + .../bootstrap/less/mixins/border-radius.less | 18 + .../bootstrap/less/mixins/buttons.less | 52 + .../bootstrap/less/mixins/center-block.less | 7 + .../bootstrap/less/mixins/clearfix.less | 22 + .../bootstrap/less/mixins/forms.less | 85 + .../bootstrap/less/mixins/gradients.less | 59 + .../bootstrap/less/mixins/grid-framework.less | 91 + .../bootstrap/less/mixins/grid.less | 122 + .../bootstrap/less/mixins/hide-text.less | 21 + .../bootstrap/less/mixins/image.less | 33 + .../bootstrap/less/mixins/labels.less | 12 + .../bootstrap/less/mixins/list-group.less | 29 + .../bootstrap/less/mixins/nav-divider.less | 10 + .../less/mixins/nav-vertical-align.less | 9 + .../bootstrap/less/mixins/opacity.less | 8 + .../bootstrap/less/mixins/pagination.less | 23 + .../bootstrap/less/mixins/panels.less | 24 + .../bootstrap/less/mixins/progress-bar.less | 10 + .../bootstrap/less/mixins/reset-filter.less | 8 + .../bootstrap/less/mixins/resize.less | 6 + .../less/mixins/responsive-visibility.less | 15 + .../bootstrap/less/mixins/size.less | 10 + .../bootstrap/less/mixins/tab-focus.less | 9 + .../bootstrap/less/mixins/table-row.less | 28 + .../bootstrap/less/mixins/text-emphasis.less | 8 + .../bootstrap/less/mixins/text-overflow.less | 8 + .../less/mixins/vendor-prefixes.less | 227 + .../bootstrap/less/modals.less | 148 + .../bootstrap/less/navbar.less | 660 + .../bower_components/bootstrap/less/navs.less | 244 + .../bootstrap/less/normalize.less | 427 + .../bootstrap/less/pager.less | 54 + .../bootstrap/less/pagination.less | 88 + .../bootstrap/less/panels.less | 261 + .../bootstrap/less/popovers.less | 135 + .../bootstrap/less/print.less | 107 + .../bootstrap/less/progress-bars.less | 87 + .../bootstrap/less/responsive-embed.less | 35 + .../bootstrap/less/responsive-utilities.less | 194 + .../bootstrap/less/scaffolding.less | 150 + .../bootstrap/less/tables.less | 234 + .../bootstrap/less/theme.less | 272 + .../bootstrap/less/thumbnails.less | 36 + .../bootstrap/less/tooltip.less | 103 + .../bower_components/bootstrap/less/type.less | 302 + .../bootstrap/less/utilities.less | 56 + .../bootstrap/less/variables.less | 856 + .../bootstrap/less/wells.less | 29 + .../bower_components/bootstrap/package.json | 82 + .../bower_components/es5-shim/.bower.json | 14 + .../bower_components/es5-shim/.gitignore | 2 + .../admincp/bower_components/es5-shim/CHANGES | 93 + .../bower_components/es5-shim/CONTRIBUTORS.md | 25 + .../admincp/bower_components/es5-shim/LICENSE | 19 + .../bower_components/es5-shim/README.md | 161 + .../bower_components/es5-shim/es5-sham.js | 444 + .../bower_components/es5-shim/es5-sham.map | 1 + .../bower_components/es5-shim/es5-sham.min.js | 4 + .../bower_components/es5-shim/es5-shim.js | 1314 + .../bower_components/es5-shim/es5-shim.map | 1 + .../bower_components/es5-shim/es5-shim.min.js | 4 + .../bower_components/es5-shim/package.json | 34 + .../es5-shim/tests/helpers/h-kill.js | 64 + .../es5-shim/tests/helpers/h-matchers.js | 34 + .../es5-shim/tests/helpers/h.js | 3 + .../es5-shim/tests/index.html | 64 + .../es5-shim/tests/index.min.html | 63 + .../es5-shim/tests/lib/jasmine-html.js | 190 + .../es5-shim/tests/lib/jasmine.css | 166 + .../es5-shim/tests/lib/jasmine.js | 2477 ++ .../es5-shim/tests/lib/jasmine_favicon.png | Bin 0 -> 905 bytes .../es5-shim/tests/lib/json2.js | 478 + .../es5-shim/tests/spec/s-array.js | 1223 + .../es5-shim/tests/spec/s-date.js | 152 + .../es5-shim/tests/spec/s-function.js | 147 + .../es5-shim/tests/spec/s-number.js | 14 + .../es5-shim/tests/spec/s-object.js | 181 + .../es5-shim/tests/spec/s-string.js | 204 + .../bower_components/fontawesome/.bower.json | 36 + .../bower_components/fontawesome/.gitignore | 32 + .../bower_components/fontawesome/.npmignore | 42 + .../bower_components/fontawesome/bower.json | 23 + .../fontawesome/css/font-awesome.css | 1566 + .../fontawesome/css/font-awesome.min.css | 4 + .../fontawesome/fonts/FontAwesome.otf | Bin 0 -> 75188 bytes .../fontawesome/fonts/fontawesome-webfont.eot | Bin 0 -> 72449 bytes .../fontawesome/fonts/fontawesome-webfont.svg | 504 + .../fontawesome/fonts/fontawesome-webfont.ttf | Bin 0 -> 141564 bytes .../fonts/fontawesome-webfont.woff | Bin 0 -> 83760 bytes .../fontawesome/less/bordered-pulled.less | 16 + .../fontawesome/less/core.less | 12 + .../fontawesome/less/extras.less | 2 + .../fontawesome/less/fixed-width.less | 6 + .../fontawesome/less/font-awesome.less | 17 + .../fontawesome/less/icons.less | 506 + .../fontawesome/less/larger.less | 13 + .../fontawesome/less/list.less | 19 + .../fontawesome/less/mixins.less | 20 + .../fontawesome/less/path.less | 14 + .../fontawesome/less/rotated-flipped.less | 9 + .../fontawesome/less/spinning.less | 32 + .../fontawesome/less/stacked.less | 20 + .../fontawesome/less/variables.less | 515 + .../fontawesome/scss/_bordered-pulled.scss | 16 + .../fontawesome/scss/_core.scss | 12 + .../fontawesome/scss/_extras.scss | 44 + .../fontawesome/scss/_fixed-width.scss | 6 + .../fontawesome/scss/_icons.scss | 506 + .../fontawesome/scss/_larger.scss | 13 + .../fontawesome/scss/_list.scss | 19 + .../fontawesome/scss/_mixins.scss | 20 + .../fontawesome/scss/_path.scss | 14 + .../fontawesome/scss/_rotated-flipped.scss | 9 + .../fontawesome/scss/_spinning.scss | 32 + .../fontawesome/scss/_stacked.scss | 20 + .../fontawesome/scss/_variables.scss | 515 + .../fontawesome/scss/font-awesome.scss | 17 + .../bower_components/humane/.bower.json | 21 + .../bower_components/humane/.gitignore | 2 + .../bower_components/humane/bower.json | 8 + .../bower_components/humane/changelog.md | 165 + .../admincp/bower_components/humane/humane.js | 238 + .../bower_components/humane/humane.min.js | 11 + .../bower_components/humane/index.html | 190 + .../bower_components/humane/package.json | 25 + .../admincp/bower_components/humane/readme.md | 85 + .../bower_components/humane/test/issue23.html | 11 + .../bower_components/humane/test/issue36.html | 9 + .../bower_components/humane/test/issue38.html | 15 + .../bower_components/humane/test/issue49.html | 9 + .../humane/theme-src/bigbox.styl | 65 + .../humane/theme-src/boldlight.styl | 64 + .../humane/theme-src/jackedup.styl | 69 + .../humane/theme-src/libnotify.styl | 61 + .../humane/theme-src/original.styl | 51 + .../bower_components/humane/themes/bigbox.css | 123 + .../humane/themes/boldlight.css | 122 + .../bower_components/humane/themes/flatty.css | 94 + .../humane/themes/jackedup.css | 123 + .../humane/themes/libnotify.css | 115 + .../humane/themes/original.css | 72 + .../bower_components/inflection/.bower.json | 91 + .../bower_components/inflection/History.md | 154 + .../bower_components/inflection/Readme.md | 492 + .../bower_components/inflection/bower.json | 51 + .../inflection/component.json | 30 + .../inflection/inflection.min.js | 30 + .../inflection/lib/inflection.js | 685 + .../bower_components/inflection/package.json | 43 + .../bower_components/jquery/.bower.json | 37 + .../bower_components/jquery/MIT-LICENSE.txt | 21 + .../bower_components/jquery/bower.json | 27 + .../bower_components/jquery/dist/jquery.js | 10346 ++++++ .../jquery/dist/jquery.min.js | 5 + .../jquery/dist/jquery.min.map | 1 + .../bower_components/jquery/src/ajax.js | 801 + .../bower_components/jquery/src/ajax/jsonp.js | 89 + .../bower_components/jquery/src/ajax/load.js | 75 + .../jquery/src/ajax/parseJSON.js | 51 + .../jquery/src/ajax/parseXML.js | 31 + .../jquery/src/ajax/script.js | 93 + .../jquery/src/ajax/var/nonce.js | 5 + .../jquery/src/ajax/var/rquery.js | 3 + .../bower_components/jquery/src/ajax/xhr.js | 197 + .../bower_components/jquery/src/attributes.js | 11 + .../jquery/src/attributes/attr.js | 271 + .../jquery/src/attributes/classes.js | 157 + .../jquery/src/attributes/prop.js | 134 + .../jquery/src/attributes/support.js | 62 + .../jquery/src/attributes/val.js | 178 + .../bower_components/jquery/src/callbacks.js | 205 + .../bower_components/jquery/src/core.js | 535 + .../jquery/src/core/access.js | 60 + .../bower_components/jquery/src/core/init.js | 132 + .../jquery/src/core/parseHTML.js | 39 + .../bower_components/jquery/src/core/ready.js | 152 + .../jquery/src/core/var/rsingleTag.js | 4 + .../bower_components/jquery/src/css.js | 504 + .../jquery/src/css/addGetHookIf.js | 32 + .../bower_components/jquery/src/css/curCSS.js | 124 + .../jquery/src/css/defaultDisplay.js | 69 + .../jquery/src/css/hiddenVisibleSelectors.js | 20 + .../jquery/src/css/support.js | 151 + .../bower_components/jquery/src/css/swap.js | 28 + .../jquery/src/css/var/cssExpand.js | 3 + .../jquery/src/css/var/isHidden.js | 13 + .../jquery/src/css/var/rmargin.js | 3 + .../jquery/src/css/var/rnumnonpx.js | 5 + .../bower_components/jquery/src/data.js | 335 + .../jquery/src/data/accepts.js | 21 + .../jquery/src/data/support.js | 25 + .../bower_components/jquery/src/deferred.js | 150 + .../bower_components/jquery/src/deprecated.js | 13 + .../bower_components/jquery/src/dimensions.js | 50 + .../bower_components/jquery/src/effects.js | 656 + .../jquery/src/effects/Tween.js | 114 + .../jquery/src/effects/animatedSelector.js | 13 + .../jquery/src/effects/support.js | 55 + .../bower_components/jquery/src/event.js | 1037 + .../bower_components/jquery/src/event/ajax.js | 13 + .../jquery/src/event/alias.js | 39 + .../jquery/src/event/support.js | 26 + .../jquery/src/exports/amd.js | 24 + .../jquery/src/exports/global.js | 32 + .../bower_components/jquery/src/intro.js | 44 + .../bower_components/jquery/src/jquery.js | 38 + .../jquery/src/manipulation.js | 744 + .../jquery/src/manipulation/_evalUrl.js | 18 + .../jquery/src/manipulation/support.js | 76 + .../src/manipulation/var/rcheckableType.js | 3 + .../bower_components/jquery/src/offset.js | 211 + .../bower_components/jquery/src/outro.js | 1 + .../bower_components/jquery/src/queue.js | 142 + .../jquery/src/queue/delay.js | 22 + .../jquery/src/selector-sizzle.js | 14 + .../bower_components/jquery/src/selector.js | 1 + .../bower_components/jquery/src/serialize.js | 110 + .../jquery/src/sizzle/dist/sizzle.js | 2067 ++ .../jquery/src/sizzle/dist/sizzle.min.js | 3 + .../jquery/src/sizzle/dist/sizzle.min.map | 1 + .../bower_components/jquery/src/support.js | 58 + .../bower_components/jquery/src/traversing.js | 200 + .../jquery/src/traversing/findFilter.js | 100 + .../src/traversing/var/rneedsContext.js | 6 + .../jquery/src/var/class2type.js | 4 + .../bower_components/jquery/src/var/concat.js | 5 + .../jquery/src/var/deletedIds.js | 3 + .../bower_components/jquery/src/var/hasOwn.js | 5 + .../jquery/src/var/indexOf.js | 5 + .../bower_components/jquery/src/var/pnum.js | 3 + .../bower_components/jquery/src/var/push.js | 5 + .../jquery/src/var/rnotwhite.js | 3 + .../bower_components/jquery/src/var/slice.js | 5 + .../jquery/src/var/strundefined.js | 3 + .../jquery/src/var/support.js | 4 + .../jquery/src/var/toString.js | 5 + .../bower_components/jquery/src/wrap.js | 76 + .../bower_components/json3/.bower.json | 31 + public/admincp/bower_components/json3/LICENSE | 20 + .../admincp/bower_components/json3/README.md | 126 + .../admincp/bower_components/json3/bower.json | 21 + .../bower_components/json3/lib/json3.js | 861 + .../bower_components/json3/lib/json3.min.js | 18 + .../bower_components/lodash/.bower.json | 33 + .../bower_components/lodash/LICENSE.txt | 22 + .../bower_components/lodash/bower.json | 23 + .../lodash/dist/lodash.compat.js | 7157 +++++ .../lodash/dist/lodash.compat.min.js | 61 + .../bower_components/lodash/dist/lodash.js | 6785 ++++ .../lodash/dist/lodash.min.js | 56 + .../lodash/dist/lodash.underscore.js | 4979 +++ .../lodash/dist/lodash.underscore.min.js | 39 + .../bower_components/ng-admin/.bower.json | 57 + .../admincp/bower_components/ng-admin/LICENSE | 19 + .../bower_components/ng-admin/README.md | 882 + .../ng-admin/assets/fonts/FontAwesome.otf | Bin 0 -> 85908 bytes .../assets/fonts/fontawesome-webfont.eot | Bin 0 -> 56006 bytes .../assets/fonts/fontawesome-webfont.svg | 520 + .../assets/fonts/fontawesome-webfont.ttf | Bin 0 -> 112160 bytes .../assets/fonts/fontawesome-webfont.woff | Bin 0 -> 65452 bytes .../bower_components/ng-admin/bower.json | 48 + .../ng-admin/build}/ng-admin.min.css | 0 .../ng-admin/build}/ng-admin.min.js | 0 .../ng-admin/build}/ng-admin.min.map | 0 .../bower_components/ngInflection/.bower.json | 49 + .../bower_components/ngInflection/.gitignore | 2 + .../bower_components/ngInflection/bower.json | 40 + .../ngInflection/ngInflection.js | 17 + .../bower_components/nprogress/.bower.json | 40 + .../bower_components/nprogress/History.md | 50 + .../bower_components/nprogress/License.md | 19 + .../bower_components/nprogress/Notes.md | 25 + .../bower_components/nprogress/Readme.md | 195 + .../bower_components/nprogress/bower.json | 27 + .../bower_components/nprogress/component.json | 22 + .../bower_components/nprogress/index.html | 84 + .../bower_components/nprogress/nprogress.css | 74 + .../bower_components/nprogress/nprogress.js | 476 + .../nprogress/support/extras.css | 4 + .../nprogress/support/style.css | 215 + .../requirejs-text/.bower.json | 14 + .../bower_components/requirejs-text/LICENSE | 58 + .../bower_components/requirejs-text/README.md | 198 + .../requirejs-text/package.json | 30 + .../bower_components/requirejs-text/text.js | 390 + .../bower_components/requirejs/.bower.json | 23 + .../bower_components/requirejs/README.md | 4 + .../bower_components/requirejs/bower.json | 14 + .../bower_components/requirejs/require.js | 2076 ++ .../bower_components/restangular/.bower.json | 29 + .../bower_components/restangular/.gitignore | 17 + .../bower_components/restangular/.travis.yml | 9 + .../bower_components/restangular/CHANGELOG.md | 160 + .../restangular/CONTRIBUTE.md | 17 + .../bower_components/restangular/Gruntfile.js | 164 + .../bower_components/restangular/README.md | 1194 + .../bower_components/restangular/bower.json | 19 + .../restangular/dist/restangular.js | 1305 + .../restangular/dist/restangular.min.js | 6 + .../restangular/dist/restangular.zip | Bin 0 -> 75378 bytes .../restangular/karma.conf.js | 74 + .../restangular/karma.underscore.conf.js | 74 + .../bower_components/restangular/license.md | 21 + .../bower_components/restangular/package.json | 54 + .../restangular/src/restangular.js | 1300 + .../restangular/test/restangularSpec.js | 787 + .../bower_components/textAngular/.bower.json | 42 + .../textAngular/CONTRIBUTING.md | 190 + .../bower_components/textAngular/README.md | 103 + .../bower_components/textAngular/bower.json | 33 + .../bower_components/textAngular/changelog.md | 112 + .../dist/textAngular-sanitize.min.js | 1 + .../textAngular/dist/textAngular.min.js | 2 + .../textAngular/karma-jqlite.conf.js | 86 + .../textAngular/karma-jquery.conf.js | 86 + .../textAngular/src/textAngular-sanitize.js | 710 + .../textAngular/src/textAngular.js | 2018 ++ .../textAngular/src/textAngularSetup.js | 571 + public/{assets/ngadmin => admincp}/style.css | 0 public/assets/ngadmin/app.js | 289 - 544 files changed, 152841 insertions(+), 289 deletions(-) create mode 100644 public/admincp/app.js create mode 100644 public/admincp/bower.json create mode 100644 public/admincp/bower_components/angular-bootstrap/.bower.json create mode 100644 public/admincp/bower_components/angular-bootstrap/bower.json create mode 100644 public/admincp/bower_components/angular-bootstrap/ui-bootstrap-tpls.js create mode 100644 public/admincp/bower_components/angular-bootstrap/ui-bootstrap-tpls.min.js create mode 100644 public/admincp/bower_components/angular-bootstrap/ui-bootstrap.js create mode 100644 public/admincp/bower_components/angular-bootstrap/ui-bootstrap.min.js create mode 100644 public/admincp/bower_components/angular-cookies/.bower.json create mode 100644 public/admincp/bower_components/angular-cookies/README.md create mode 100644 public/admincp/bower_components/angular-cookies/angular-cookies.js create mode 100644 public/admincp/bower_components/angular-cookies/angular-cookies.min.js create mode 100644 public/admincp/bower_components/angular-cookies/angular-cookies.min.js.map create mode 100644 public/admincp/bower_components/angular-cookies/bower.json create mode 100644 public/admincp/bower_components/angular-cookies/package.json create mode 100644 public/admincp/bower_components/angular-resource/.bower.json create mode 100644 public/admincp/bower_components/angular-resource/README.md create mode 100644 public/admincp/bower_components/angular-resource/angular-resource.js create mode 100644 public/admincp/bower_components/angular-resource/angular-resource.min.js create mode 100644 public/admincp/bower_components/angular-resource/angular-resource.min.js.map create mode 100644 public/admincp/bower_components/angular-resource/bower.json create mode 100644 public/admincp/bower_components/angular-resource/package.json create mode 100644 public/admincp/bower_components/angular-sanitize/.bower.json create mode 100644 public/admincp/bower_components/angular-sanitize/README.md create mode 100644 public/admincp/bower_components/angular-sanitize/angular-sanitize.js create mode 100644 public/admincp/bower_components/angular-sanitize/angular-sanitize.min.js create mode 100644 public/admincp/bower_components/angular-sanitize/angular-sanitize.min.js.map create mode 100644 public/admincp/bower_components/angular-sanitize/bower.json create mode 100644 public/admincp/bower_components/angular-sanitize/package.json create mode 100644 public/admincp/bower_components/angular-ui-router/.bower.json create mode 100644 public/admincp/bower_components/angular-ui-router/CHANGELOG.md create mode 100644 public/admincp/bower_components/angular-ui-router/CONTRIBUTING.md create mode 100644 public/admincp/bower_components/angular-ui-router/LICENSE create mode 100644 public/admincp/bower_components/angular-ui-router/README.md create mode 100644 public/admincp/bower_components/angular-ui-router/api/angular-ui-router.d.ts create mode 100644 public/admincp/bower_components/angular-ui-router/bower.json create mode 100644 public/admincp/bower_components/angular-ui-router/release/angular-ui-router.js create mode 100644 public/admincp/bower_components/angular-ui-router/release/angular-ui-router.min.js create mode 100644 public/admincp/bower_components/angular-ui-router/src/common.js create mode 100644 public/admincp/bower_components/angular-ui-router/src/resolve.js create mode 100644 public/admincp/bower_components/angular-ui-router/src/state.js create mode 100644 public/admincp/bower_components/angular-ui-router/src/stateDirectives.js create mode 100644 public/admincp/bower_components/angular-ui-router/src/stateFilters.js create mode 100644 public/admincp/bower_components/angular-ui-router/src/templateFactory.js create mode 100644 public/admincp/bower_components/angular-ui-router/src/urlMatcherFactory.js create mode 100644 public/admincp/bower_components/angular-ui-router/src/urlRouter.js create mode 100644 public/admincp/bower_components/angular-ui-router/src/view.js create mode 100644 public/admincp/bower_components/angular-ui-router/src/viewDirective.js create mode 100644 public/admincp/bower_components/angular-ui-router/src/viewScroll.js create mode 100644 public/admincp/bower_components/angular/.bower.json create mode 100644 public/admincp/bower_components/angular/README.md create mode 100644 public/admincp/bower_components/angular/angular-csp.css create mode 100644 public/admincp/bower_components/angular/angular.js rename public/{assets/ngadmin/vendor => admincp/bower_components/angular}/angular.min.js (100%) create mode 100644 public/admincp/bower_components/angular/angular.min.js.gzip create mode 100644 public/admincp/bower_components/angular/angular.min.js.map create mode 100644 public/admincp/bower_components/angular/bower.json create mode 100644 public/admincp/bower_components/angular/package.json create mode 100644 public/admincp/bower_components/bootstrap-sass-official/.bower.json create mode 100644 public/admincp/bower_components/bootstrap-sass-official/CHANGELOG.md create mode 100644 public/admincp/bower_components/bootstrap-sass-official/CONTRIBUTING.md create mode 100644 public/admincp/bower_components/bootstrap-sass-official/LICENSE create mode 100644 public/admincp/bower_components/bootstrap-sass-official/README.md create mode 100644 public/admincp/bower_components/bootstrap-sass-official/assets/fonts/bootstrap/glyphicons-halflings-regular.eot create mode 100644 public/admincp/bower_components/bootstrap-sass-official/assets/fonts/bootstrap/glyphicons-halflings-regular.svg create mode 100644 public/admincp/bower_components/bootstrap-sass-official/assets/fonts/bootstrap/glyphicons-halflings-regular.ttf create mode 100644 public/admincp/bower_components/bootstrap-sass-official/assets/fonts/bootstrap/glyphicons-halflings-regular.woff create mode 100644 public/admincp/bower_components/bootstrap-sass-official/assets/javascripts/bootstrap-sprockets.js create mode 100644 public/admincp/bower_components/bootstrap-sass-official/assets/javascripts/bootstrap.js create mode 100644 public/admincp/bower_components/bootstrap-sass-official/assets/javascripts/bootstrap/affix.js create mode 100644 public/admincp/bower_components/bootstrap-sass-official/assets/javascripts/bootstrap/alert.js create mode 100644 public/admincp/bower_components/bootstrap-sass-official/assets/javascripts/bootstrap/button.js create mode 100644 public/admincp/bower_components/bootstrap-sass-official/assets/javascripts/bootstrap/carousel.js create mode 100644 public/admincp/bower_components/bootstrap-sass-official/assets/javascripts/bootstrap/collapse.js create mode 100644 public/admincp/bower_components/bootstrap-sass-official/assets/javascripts/bootstrap/dropdown.js create mode 100644 public/admincp/bower_components/bootstrap-sass-official/assets/javascripts/bootstrap/modal.js create mode 100644 public/admincp/bower_components/bootstrap-sass-official/assets/javascripts/bootstrap/popover.js create mode 100644 public/admincp/bower_components/bootstrap-sass-official/assets/javascripts/bootstrap/scrollspy.js create mode 100644 public/admincp/bower_components/bootstrap-sass-official/assets/javascripts/bootstrap/tab.js create mode 100644 public/admincp/bower_components/bootstrap-sass-official/assets/javascripts/bootstrap/tooltip.js create mode 100644 public/admincp/bower_components/bootstrap-sass-official/assets/javascripts/bootstrap/transition.js create mode 100644 public/admincp/bower_components/bootstrap-sass-official/assets/stylesheets/_bootstrap-compass.scss create mode 100644 public/admincp/bower_components/bootstrap-sass-official/assets/stylesheets/_bootstrap-mincer.scss create mode 100644 public/admincp/bower_components/bootstrap-sass-official/assets/stylesheets/_bootstrap-sprockets.scss create mode 100644 public/admincp/bower_components/bootstrap-sass-official/assets/stylesheets/_bootstrap.scss create mode 100644 public/admincp/bower_components/bootstrap-sass-official/assets/stylesheets/bootstrap/_alerts.scss create mode 100644 public/admincp/bower_components/bootstrap-sass-official/assets/stylesheets/bootstrap/_badges.scss create mode 100644 public/admincp/bower_components/bootstrap-sass-official/assets/stylesheets/bootstrap/_breadcrumbs.scss create mode 100644 public/admincp/bower_components/bootstrap-sass-official/assets/stylesheets/bootstrap/_button-groups.scss create mode 100644 public/admincp/bower_components/bootstrap-sass-official/assets/stylesheets/bootstrap/_buttons.scss create mode 100644 public/admincp/bower_components/bootstrap-sass-official/assets/stylesheets/bootstrap/_carousel.scss create mode 100644 public/admincp/bower_components/bootstrap-sass-official/assets/stylesheets/bootstrap/_close.scss create mode 100644 public/admincp/bower_components/bootstrap-sass-official/assets/stylesheets/bootstrap/_code.scss create mode 100644 public/admincp/bower_components/bootstrap-sass-official/assets/stylesheets/bootstrap/_component-animations.scss create mode 100644 public/admincp/bower_components/bootstrap-sass-official/assets/stylesheets/bootstrap/_dropdowns.scss create mode 100644 public/admincp/bower_components/bootstrap-sass-official/assets/stylesheets/bootstrap/_forms.scss create mode 100644 public/admincp/bower_components/bootstrap-sass-official/assets/stylesheets/bootstrap/_glyphicons.scss create mode 100644 public/admincp/bower_components/bootstrap-sass-official/assets/stylesheets/bootstrap/_grid.scss create mode 100644 public/admincp/bower_components/bootstrap-sass-official/assets/stylesheets/bootstrap/_input-groups.scss create mode 100644 public/admincp/bower_components/bootstrap-sass-official/assets/stylesheets/bootstrap/_jumbotron.scss create mode 100644 public/admincp/bower_components/bootstrap-sass-official/assets/stylesheets/bootstrap/_labels.scss create mode 100644 public/admincp/bower_components/bootstrap-sass-official/assets/stylesheets/bootstrap/_list-group.scss create mode 100644 public/admincp/bower_components/bootstrap-sass-official/assets/stylesheets/bootstrap/_media.scss create mode 100644 public/admincp/bower_components/bootstrap-sass-official/assets/stylesheets/bootstrap/_mixins.scss create mode 100644 public/admincp/bower_components/bootstrap-sass-official/assets/stylesheets/bootstrap/_modals.scss create mode 100644 public/admincp/bower_components/bootstrap-sass-official/assets/stylesheets/bootstrap/_navbar.scss create mode 100644 public/admincp/bower_components/bootstrap-sass-official/assets/stylesheets/bootstrap/_navs.scss create mode 100644 public/admincp/bower_components/bootstrap-sass-official/assets/stylesheets/bootstrap/_normalize.scss create mode 100644 public/admincp/bower_components/bootstrap-sass-official/assets/stylesheets/bootstrap/_pager.scss create mode 100644 public/admincp/bower_components/bootstrap-sass-official/assets/stylesheets/bootstrap/_pagination.scss create mode 100644 public/admincp/bower_components/bootstrap-sass-official/assets/stylesheets/bootstrap/_panels.scss create mode 100644 public/admincp/bower_components/bootstrap-sass-official/assets/stylesheets/bootstrap/_popovers.scss create mode 100644 public/admincp/bower_components/bootstrap-sass-official/assets/stylesheets/bootstrap/_print.scss create mode 100644 public/admincp/bower_components/bootstrap-sass-official/assets/stylesheets/bootstrap/_progress-bars.scss create mode 100644 public/admincp/bower_components/bootstrap-sass-official/assets/stylesheets/bootstrap/_responsive-embed.scss create mode 100644 public/admincp/bower_components/bootstrap-sass-official/assets/stylesheets/bootstrap/_responsive-utilities.scss create mode 100644 public/admincp/bower_components/bootstrap-sass-official/assets/stylesheets/bootstrap/_scaffolding.scss create mode 100644 public/admincp/bower_components/bootstrap-sass-official/assets/stylesheets/bootstrap/_tables.scss create mode 100644 public/admincp/bower_components/bootstrap-sass-official/assets/stylesheets/bootstrap/_theme.scss create mode 100644 public/admincp/bower_components/bootstrap-sass-official/assets/stylesheets/bootstrap/_thumbnails.scss create mode 100644 public/admincp/bower_components/bootstrap-sass-official/assets/stylesheets/bootstrap/_tooltip.scss create mode 100644 public/admincp/bower_components/bootstrap-sass-official/assets/stylesheets/bootstrap/_type.scss create mode 100644 public/admincp/bower_components/bootstrap-sass-official/assets/stylesheets/bootstrap/_utilities.scss create mode 100644 public/admincp/bower_components/bootstrap-sass-official/assets/stylesheets/bootstrap/_variables.scss create mode 100644 public/admincp/bower_components/bootstrap-sass-official/assets/stylesheets/bootstrap/_wells.scss create mode 100644 public/admincp/bower_components/bootstrap-sass-official/assets/stylesheets/bootstrap/mixins/_alerts.scss create mode 100644 public/admincp/bower_components/bootstrap-sass-official/assets/stylesheets/bootstrap/mixins/_background-variant.scss create mode 100644 public/admincp/bower_components/bootstrap-sass-official/assets/stylesheets/bootstrap/mixins/_border-radius.scss create mode 100644 public/admincp/bower_components/bootstrap-sass-official/assets/stylesheets/bootstrap/mixins/_buttons.scss create mode 100644 public/admincp/bower_components/bootstrap-sass-official/assets/stylesheets/bootstrap/mixins/_center-block.scss create mode 100644 public/admincp/bower_components/bootstrap-sass-official/assets/stylesheets/bootstrap/mixins/_clearfix.scss create mode 100644 public/admincp/bower_components/bootstrap-sass-official/assets/stylesheets/bootstrap/mixins/_forms.scss create mode 100644 public/admincp/bower_components/bootstrap-sass-official/assets/stylesheets/bootstrap/mixins/_gradients.scss create mode 100644 public/admincp/bower_components/bootstrap-sass-official/assets/stylesheets/bootstrap/mixins/_grid-framework.scss create mode 100644 public/admincp/bower_components/bootstrap-sass-official/assets/stylesheets/bootstrap/mixins/_grid.scss create mode 100644 public/admincp/bower_components/bootstrap-sass-official/assets/stylesheets/bootstrap/mixins/_hide-text.scss create mode 100644 public/admincp/bower_components/bootstrap-sass-official/assets/stylesheets/bootstrap/mixins/_image.scss create mode 100644 public/admincp/bower_components/bootstrap-sass-official/assets/stylesheets/bootstrap/mixins/_labels.scss create mode 100644 public/admincp/bower_components/bootstrap-sass-official/assets/stylesheets/bootstrap/mixins/_list-group.scss create mode 100644 public/admincp/bower_components/bootstrap-sass-official/assets/stylesheets/bootstrap/mixins/_nav-divider.scss create mode 100644 public/admincp/bower_components/bootstrap-sass-official/assets/stylesheets/bootstrap/mixins/_nav-vertical-align.scss create mode 100644 public/admincp/bower_components/bootstrap-sass-official/assets/stylesheets/bootstrap/mixins/_opacity.scss create mode 100644 public/admincp/bower_components/bootstrap-sass-official/assets/stylesheets/bootstrap/mixins/_pagination.scss create mode 100644 public/admincp/bower_components/bootstrap-sass-official/assets/stylesheets/bootstrap/mixins/_panels.scss create mode 100644 public/admincp/bower_components/bootstrap-sass-official/assets/stylesheets/bootstrap/mixins/_progress-bar.scss create mode 100644 public/admincp/bower_components/bootstrap-sass-official/assets/stylesheets/bootstrap/mixins/_reset-filter.scss create mode 100644 public/admincp/bower_components/bootstrap-sass-official/assets/stylesheets/bootstrap/mixins/_resize.scss create mode 100644 public/admincp/bower_components/bootstrap-sass-official/assets/stylesheets/bootstrap/mixins/_responsive-visibility.scss create mode 100644 public/admincp/bower_components/bootstrap-sass-official/assets/stylesheets/bootstrap/mixins/_size.scss create mode 100644 public/admincp/bower_components/bootstrap-sass-official/assets/stylesheets/bootstrap/mixins/_tab-focus.scss create mode 100644 public/admincp/bower_components/bootstrap-sass-official/assets/stylesheets/bootstrap/mixins/_table-row.scss create mode 100644 public/admincp/bower_components/bootstrap-sass-official/assets/stylesheets/bootstrap/mixins/_text-emphasis.scss create mode 100644 public/admincp/bower_components/bootstrap-sass-official/assets/stylesheets/bootstrap/mixins/_text-overflow.scss create mode 100644 public/admincp/bower_components/bootstrap-sass-official/assets/stylesheets/bootstrap/mixins/_vendor-prefixes.scss create mode 100644 public/admincp/bower_components/bootstrap-sass-official/bower.json create mode 100644 public/admincp/bower_components/bootstrap-sass-official/composer.json create mode 100644 public/admincp/bower_components/bootstrap-sass-official/package.json create mode 100644 public/admincp/bower_components/bootstrap-sass-official/sache.json create mode 100644 public/admincp/bower_components/bootstrap/.bower.json create mode 100644 public/admincp/bower_components/bootstrap/Gruntfile.js create mode 100644 public/admincp/bower_components/bootstrap/LICENSE create mode 100644 public/admincp/bower_components/bootstrap/README.md create mode 100644 public/admincp/bower_components/bootstrap/bower.json create mode 100644 public/admincp/bower_components/bootstrap/dist/css/bootstrap-theme.css create mode 100644 public/admincp/bower_components/bootstrap/dist/css/bootstrap-theme.css.map create mode 100644 public/admincp/bower_components/bootstrap/dist/css/bootstrap-theme.min.css create mode 100644 public/admincp/bower_components/bootstrap/dist/css/bootstrap.css create mode 100644 public/admincp/bower_components/bootstrap/dist/css/bootstrap.css.map create mode 100644 public/admincp/bower_components/bootstrap/dist/css/bootstrap.min.css create mode 100644 public/admincp/bower_components/bootstrap/dist/fonts/glyphicons-halflings-regular.eot create mode 100644 public/admincp/bower_components/bootstrap/dist/fonts/glyphicons-halflings-regular.svg create mode 100644 public/admincp/bower_components/bootstrap/dist/fonts/glyphicons-halflings-regular.ttf create mode 100644 public/admincp/bower_components/bootstrap/dist/fonts/glyphicons-halflings-regular.woff create mode 100644 public/admincp/bower_components/bootstrap/dist/js/bootstrap.js create mode 100644 public/admincp/bower_components/bootstrap/dist/js/bootstrap.min.js create mode 100644 public/admincp/bower_components/bootstrap/dist/js/npm.js create mode 100644 public/admincp/bower_components/bootstrap/fonts/glyphicons-halflings-regular.eot create mode 100644 public/admincp/bower_components/bootstrap/fonts/glyphicons-halflings-regular.svg create mode 100644 public/admincp/bower_components/bootstrap/fonts/glyphicons-halflings-regular.ttf create mode 100644 public/admincp/bower_components/bootstrap/fonts/glyphicons-halflings-regular.woff create mode 100644 public/admincp/bower_components/bootstrap/grunt/.jshintrc create mode 100644 public/admincp/bower_components/bootstrap/grunt/bs-commonjs-generator.js create mode 100644 public/admincp/bower_components/bootstrap/grunt/bs-lessdoc-parser.js create mode 100644 public/admincp/bower_components/bootstrap/grunt/bs-raw-files-generator.js create mode 100644 public/admincp/bower_components/bootstrap/grunt/configBridge.json create mode 100644 public/admincp/bower_components/bootstrap/grunt/sauce_browsers.yml create mode 100644 public/admincp/bower_components/bootstrap/js/.jscsrc create mode 100644 public/admincp/bower_components/bootstrap/js/.jshintrc create mode 100644 public/admincp/bower_components/bootstrap/js/affix.js create mode 100644 public/admincp/bower_components/bootstrap/js/alert.js create mode 100644 public/admincp/bower_components/bootstrap/js/button.js create mode 100644 public/admincp/bower_components/bootstrap/js/carousel.js create mode 100644 public/admincp/bower_components/bootstrap/js/collapse.js create mode 100644 public/admincp/bower_components/bootstrap/js/dropdown.js create mode 100644 public/admincp/bower_components/bootstrap/js/modal.js create mode 100644 public/admincp/bower_components/bootstrap/js/popover.js create mode 100644 public/admincp/bower_components/bootstrap/js/scrollspy.js create mode 100644 public/admincp/bower_components/bootstrap/js/tab.js create mode 100644 public/admincp/bower_components/bootstrap/js/tooltip.js create mode 100644 public/admincp/bower_components/bootstrap/js/transition.js create mode 100644 public/admincp/bower_components/bootstrap/less/.csscomb.json create mode 100644 public/admincp/bower_components/bootstrap/less/.csslintrc create mode 100644 public/admincp/bower_components/bootstrap/less/alerts.less create mode 100644 public/admincp/bower_components/bootstrap/less/badges.less create mode 100644 public/admincp/bower_components/bootstrap/less/bootstrap.less create mode 100644 public/admincp/bower_components/bootstrap/less/breadcrumbs.less create mode 100644 public/admincp/bower_components/bootstrap/less/button-groups.less create mode 100644 public/admincp/bower_components/bootstrap/less/buttons.less create mode 100644 public/admincp/bower_components/bootstrap/less/carousel.less create mode 100644 public/admincp/bower_components/bootstrap/less/close.less create mode 100644 public/admincp/bower_components/bootstrap/less/code.less create mode 100644 public/admincp/bower_components/bootstrap/less/component-animations.less create mode 100644 public/admincp/bower_components/bootstrap/less/dropdowns.less create mode 100644 public/admincp/bower_components/bootstrap/less/forms.less create mode 100644 public/admincp/bower_components/bootstrap/less/glyphicons.less create mode 100644 public/admincp/bower_components/bootstrap/less/grid.less create mode 100644 public/admincp/bower_components/bootstrap/less/input-groups.less create mode 100644 public/admincp/bower_components/bootstrap/less/jumbotron.less create mode 100644 public/admincp/bower_components/bootstrap/less/labels.less create mode 100644 public/admincp/bower_components/bootstrap/less/list-group.less create mode 100644 public/admincp/bower_components/bootstrap/less/media.less create mode 100644 public/admincp/bower_components/bootstrap/less/mixins.less create mode 100644 public/admincp/bower_components/bootstrap/less/mixins/alerts.less create mode 100644 public/admincp/bower_components/bootstrap/less/mixins/background-variant.less create mode 100644 public/admincp/bower_components/bootstrap/less/mixins/border-radius.less create mode 100644 public/admincp/bower_components/bootstrap/less/mixins/buttons.less create mode 100644 public/admincp/bower_components/bootstrap/less/mixins/center-block.less create mode 100644 public/admincp/bower_components/bootstrap/less/mixins/clearfix.less create mode 100644 public/admincp/bower_components/bootstrap/less/mixins/forms.less create mode 100644 public/admincp/bower_components/bootstrap/less/mixins/gradients.less create mode 100644 public/admincp/bower_components/bootstrap/less/mixins/grid-framework.less create mode 100644 public/admincp/bower_components/bootstrap/less/mixins/grid.less create mode 100644 public/admincp/bower_components/bootstrap/less/mixins/hide-text.less create mode 100644 public/admincp/bower_components/bootstrap/less/mixins/image.less create mode 100644 public/admincp/bower_components/bootstrap/less/mixins/labels.less create mode 100644 public/admincp/bower_components/bootstrap/less/mixins/list-group.less create mode 100644 public/admincp/bower_components/bootstrap/less/mixins/nav-divider.less create mode 100644 public/admincp/bower_components/bootstrap/less/mixins/nav-vertical-align.less create mode 100644 public/admincp/bower_components/bootstrap/less/mixins/opacity.less create mode 100644 public/admincp/bower_components/bootstrap/less/mixins/pagination.less create mode 100644 public/admincp/bower_components/bootstrap/less/mixins/panels.less create mode 100644 public/admincp/bower_components/bootstrap/less/mixins/progress-bar.less create mode 100644 public/admincp/bower_components/bootstrap/less/mixins/reset-filter.less create mode 100644 public/admincp/bower_components/bootstrap/less/mixins/resize.less create mode 100644 public/admincp/bower_components/bootstrap/less/mixins/responsive-visibility.less create mode 100644 public/admincp/bower_components/bootstrap/less/mixins/size.less create mode 100644 public/admincp/bower_components/bootstrap/less/mixins/tab-focus.less create mode 100644 public/admincp/bower_components/bootstrap/less/mixins/table-row.less create mode 100644 public/admincp/bower_components/bootstrap/less/mixins/text-emphasis.less create mode 100644 public/admincp/bower_components/bootstrap/less/mixins/text-overflow.less create mode 100644 public/admincp/bower_components/bootstrap/less/mixins/vendor-prefixes.less create mode 100644 public/admincp/bower_components/bootstrap/less/modals.less create mode 100644 public/admincp/bower_components/bootstrap/less/navbar.less create mode 100644 public/admincp/bower_components/bootstrap/less/navs.less create mode 100644 public/admincp/bower_components/bootstrap/less/normalize.less create mode 100644 public/admincp/bower_components/bootstrap/less/pager.less create mode 100644 public/admincp/bower_components/bootstrap/less/pagination.less create mode 100644 public/admincp/bower_components/bootstrap/less/panels.less create mode 100644 public/admincp/bower_components/bootstrap/less/popovers.less create mode 100644 public/admincp/bower_components/bootstrap/less/print.less create mode 100644 public/admincp/bower_components/bootstrap/less/progress-bars.less create mode 100644 public/admincp/bower_components/bootstrap/less/responsive-embed.less create mode 100644 public/admincp/bower_components/bootstrap/less/responsive-utilities.less create mode 100644 public/admincp/bower_components/bootstrap/less/scaffolding.less create mode 100644 public/admincp/bower_components/bootstrap/less/tables.less create mode 100644 public/admincp/bower_components/bootstrap/less/theme.less create mode 100644 public/admincp/bower_components/bootstrap/less/thumbnails.less create mode 100644 public/admincp/bower_components/bootstrap/less/tooltip.less create mode 100644 public/admincp/bower_components/bootstrap/less/type.less create mode 100644 public/admincp/bower_components/bootstrap/less/utilities.less create mode 100644 public/admincp/bower_components/bootstrap/less/variables.less create mode 100644 public/admincp/bower_components/bootstrap/less/wells.less create mode 100644 public/admincp/bower_components/bootstrap/package.json create mode 100644 public/admincp/bower_components/es5-shim/.bower.json create mode 100644 public/admincp/bower_components/es5-shim/.gitignore create mode 100644 public/admincp/bower_components/es5-shim/CHANGES create mode 100644 public/admincp/bower_components/es5-shim/CONTRIBUTORS.md create mode 100644 public/admincp/bower_components/es5-shim/LICENSE create mode 100644 public/admincp/bower_components/es5-shim/README.md create mode 100644 public/admincp/bower_components/es5-shim/es5-sham.js create mode 100644 public/admincp/bower_components/es5-shim/es5-sham.map create mode 100644 public/admincp/bower_components/es5-shim/es5-sham.min.js create mode 100644 public/admincp/bower_components/es5-shim/es5-shim.js create mode 100644 public/admincp/bower_components/es5-shim/es5-shim.map create mode 100644 public/admincp/bower_components/es5-shim/es5-shim.min.js create mode 100644 public/admincp/bower_components/es5-shim/package.json create mode 100644 public/admincp/bower_components/es5-shim/tests/helpers/h-kill.js create mode 100644 public/admincp/bower_components/es5-shim/tests/helpers/h-matchers.js create mode 100644 public/admincp/bower_components/es5-shim/tests/helpers/h.js create mode 100644 public/admincp/bower_components/es5-shim/tests/index.html create mode 100644 public/admincp/bower_components/es5-shim/tests/index.min.html create mode 100644 public/admincp/bower_components/es5-shim/tests/lib/jasmine-html.js create mode 100644 public/admincp/bower_components/es5-shim/tests/lib/jasmine.css create mode 100644 public/admincp/bower_components/es5-shim/tests/lib/jasmine.js create mode 100644 public/admincp/bower_components/es5-shim/tests/lib/jasmine_favicon.png create mode 100644 public/admincp/bower_components/es5-shim/tests/lib/json2.js create mode 100644 public/admincp/bower_components/es5-shim/tests/spec/s-array.js create mode 100644 public/admincp/bower_components/es5-shim/tests/spec/s-date.js create mode 100644 public/admincp/bower_components/es5-shim/tests/spec/s-function.js create mode 100644 public/admincp/bower_components/es5-shim/tests/spec/s-number.js create mode 100644 public/admincp/bower_components/es5-shim/tests/spec/s-object.js create mode 100644 public/admincp/bower_components/es5-shim/tests/spec/s-string.js create mode 100644 public/admincp/bower_components/fontawesome/.bower.json create mode 100644 public/admincp/bower_components/fontawesome/.gitignore create mode 100644 public/admincp/bower_components/fontawesome/.npmignore create mode 100644 public/admincp/bower_components/fontawesome/bower.json create mode 100644 public/admincp/bower_components/fontawesome/css/font-awesome.css create mode 100644 public/admincp/bower_components/fontawesome/css/font-awesome.min.css create mode 100644 public/admincp/bower_components/fontawesome/fonts/FontAwesome.otf create mode 100644 public/admincp/bower_components/fontawesome/fonts/fontawesome-webfont.eot create mode 100644 public/admincp/bower_components/fontawesome/fonts/fontawesome-webfont.svg create mode 100644 public/admincp/bower_components/fontawesome/fonts/fontawesome-webfont.ttf create mode 100644 public/admincp/bower_components/fontawesome/fonts/fontawesome-webfont.woff create mode 100644 public/admincp/bower_components/fontawesome/less/bordered-pulled.less create mode 100644 public/admincp/bower_components/fontawesome/less/core.less create mode 100644 public/admincp/bower_components/fontawesome/less/extras.less create mode 100644 public/admincp/bower_components/fontawesome/less/fixed-width.less create mode 100644 public/admincp/bower_components/fontawesome/less/font-awesome.less create mode 100644 public/admincp/bower_components/fontawesome/less/icons.less create mode 100644 public/admincp/bower_components/fontawesome/less/larger.less create mode 100644 public/admincp/bower_components/fontawesome/less/list.less create mode 100644 public/admincp/bower_components/fontawesome/less/mixins.less create mode 100644 public/admincp/bower_components/fontawesome/less/path.less create mode 100644 public/admincp/bower_components/fontawesome/less/rotated-flipped.less create mode 100644 public/admincp/bower_components/fontawesome/less/spinning.less create mode 100644 public/admincp/bower_components/fontawesome/less/stacked.less create mode 100644 public/admincp/bower_components/fontawesome/less/variables.less create mode 100644 public/admincp/bower_components/fontawesome/scss/_bordered-pulled.scss create mode 100644 public/admincp/bower_components/fontawesome/scss/_core.scss create mode 100644 public/admincp/bower_components/fontawesome/scss/_extras.scss create mode 100644 public/admincp/bower_components/fontawesome/scss/_fixed-width.scss create mode 100644 public/admincp/bower_components/fontawesome/scss/_icons.scss create mode 100644 public/admincp/bower_components/fontawesome/scss/_larger.scss create mode 100644 public/admincp/bower_components/fontawesome/scss/_list.scss create mode 100644 public/admincp/bower_components/fontawesome/scss/_mixins.scss create mode 100644 public/admincp/bower_components/fontawesome/scss/_path.scss create mode 100644 public/admincp/bower_components/fontawesome/scss/_rotated-flipped.scss create mode 100644 public/admincp/bower_components/fontawesome/scss/_spinning.scss create mode 100644 public/admincp/bower_components/fontawesome/scss/_stacked.scss create mode 100644 public/admincp/bower_components/fontawesome/scss/_variables.scss create mode 100644 public/admincp/bower_components/fontawesome/scss/font-awesome.scss create mode 100644 public/admincp/bower_components/humane/.bower.json create mode 100644 public/admincp/bower_components/humane/.gitignore create mode 100644 public/admincp/bower_components/humane/bower.json create mode 100644 public/admincp/bower_components/humane/changelog.md create mode 100644 public/admincp/bower_components/humane/humane.js create mode 100644 public/admincp/bower_components/humane/humane.min.js create mode 100644 public/admincp/bower_components/humane/index.html create mode 100644 public/admincp/bower_components/humane/package.json create mode 100644 public/admincp/bower_components/humane/readme.md create mode 100644 public/admincp/bower_components/humane/test/issue23.html create mode 100644 public/admincp/bower_components/humane/test/issue36.html create mode 100644 public/admincp/bower_components/humane/test/issue38.html create mode 100644 public/admincp/bower_components/humane/test/issue49.html create mode 100644 public/admincp/bower_components/humane/theme-src/bigbox.styl create mode 100644 public/admincp/bower_components/humane/theme-src/boldlight.styl create mode 100644 public/admincp/bower_components/humane/theme-src/jackedup.styl create mode 100644 public/admincp/bower_components/humane/theme-src/libnotify.styl create mode 100644 public/admincp/bower_components/humane/theme-src/original.styl create mode 100644 public/admincp/bower_components/humane/themes/bigbox.css create mode 100644 public/admincp/bower_components/humane/themes/boldlight.css create mode 100644 public/admincp/bower_components/humane/themes/flatty.css create mode 100644 public/admincp/bower_components/humane/themes/jackedup.css create mode 100644 public/admincp/bower_components/humane/themes/libnotify.css create mode 100644 public/admincp/bower_components/humane/themes/original.css create mode 100644 public/admincp/bower_components/inflection/.bower.json create mode 100644 public/admincp/bower_components/inflection/History.md create mode 100644 public/admincp/bower_components/inflection/Readme.md create mode 100644 public/admincp/bower_components/inflection/bower.json create mode 100644 public/admincp/bower_components/inflection/component.json create mode 100644 public/admincp/bower_components/inflection/inflection.min.js create mode 100644 public/admincp/bower_components/inflection/lib/inflection.js create mode 100644 public/admincp/bower_components/inflection/package.json create mode 100644 public/admincp/bower_components/jquery/.bower.json create mode 100644 public/admincp/bower_components/jquery/MIT-LICENSE.txt create mode 100644 public/admincp/bower_components/jquery/bower.json create mode 100644 public/admincp/bower_components/jquery/dist/jquery.js create mode 100644 public/admincp/bower_components/jquery/dist/jquery.min.js create mode 100644 public/admincp/bower_components/jquery/dist/jquery.min.map create mode 100644 public/admincp/bower_components/jquery/src/ajax.js create mode 100644 public/admincp/bower_components/jquery/src/ajax/jsonp.js create mode 100644 public/admincp/bower_components/jquery/src/ajax/load.js create mode 100644 public/admincp/bower_components/jquery/src/ajax/parseJSON.js create mode 100644 public/admincp/bower_components/jquery/src/ajax/parseXML.js create mode 100644 public/admincp/bower_components/jquery/src/ajax/script.js create mode 100644 public/admincp/bower_components/jquery/src/ajax/var/nonce.js create mode 100644 public/admincp/bower_components/jquery/src/ajax/var/rquery.js create mode 100644 public/admincp/bower_components/jquery/src/ajax/xhr.js create mode 100644 public/admincp/bower_components/jquery/src/attributes.js create mode 100644 public/admincp/bower_components/jquery/src/attributes/attr.js create mode 100644 public/admincp/bower_components/jquery/src/attributes/classes.js create mode 100644 public/admincp/bower_components/jquery/src/attributes/prop.js create mode 100644 public/admincp/bower_components/jquery/src/attributes/support.js create mode 100644 public/admincp/bower_components/jquery/src/attributes/val.js create mode 100644 public/admincp/bower_components/jquery/src/callbacks.js create mode 100644 public/admincp/bower_components/jquery/src/core.js create mode 100644 public/admincp/bower_components/jquery/src/core/access.js create mode 100644 public/admincp/bower_components/jquery/src/core/init.js create mode 100644 public/admincp/bower_components/jquery/src/core/parseHTML.js create mode 100644 public/admincp/bower_components/jquery/src/core/ready.js create mode 100644 public/admincp/bower_components/jquery/src/core/var/rsingleTag.js create mode 100644 public/admincp/bower_components/jquery/src/css.js create mode 100644 public/admincp/bower_components/jquery/src/css/addGetHookIf.js create mode 100644 public/admincp/bower_components/jquery/src/css/curCSS.js create mode 100644 public/admincp/bower_components/jquery/src/css/defaultDisplay.js create mode 100644 public/admincp/bower_components/jquery/src/css/hiddenVisibleSelectors.js create mode 100644 public/admincp/bower_components/jquery/src/css/support.js create mode 100644 public/admincp/bower_components/jquery/src/css/swap.js create mode 100644 public/admincp/bower_components/jquery/src/css/var/cssExpand.js create mode 100644 public/admincp/bower_components/jquery/src/css/var/isHidden.js create mode 100644 public/admincp/bower_components/jquery/src/css/var/rmargin.js create mode 100644 public/admincp/bower_components/jquery/src/css/var/rnumnonpx.js create mode 100644 public/admincp/bower_components/jquery/src/data.js create mode 100644 public/admincp/bower_components/jquery/src/data/accepts.js create mode 100644 public/admincp/bower_components/jquery/src/data/support.js create mode 100644 public/admincp/bower_components/jquery/src/deferred.js create mode 100644 public/admincp/bower_components/jquery/src/deprecated.js create mode 100644 public/admincp/bower_components/jquery/src/dimensions.js create mode 100644 public/admincp/bower_components/jquery/src/effects.js create mode 100644 public/admincp/bower_components/jquery/src/effects/Tween.js create mode 100644 public/admincp/bower_components/jquery/src/effects/animatedSelector.js create mode 100644 public/admincp/bower_components/jquery/src/effects/support.js create mode 100644 public/admincp/bower_components/jquery/src/event.js create mode 100644 public/admincp/bower_components/jquery/src/event/ajax.js create mode 100644 public/admincp/bower_components/jquery/src/event/alias.js create mode 100644 public/admincp/bower_components/jquery/src/event/support.js create mode 100644 public/admincp/bower_components/jquery/src/exports/amd.js create mode 100644 public/admincp/bower_components/jquery/src/exports/global.js create mode 100644 public/admincp/bower_components/jquery/src/intro.js create mode 100644 public/admincp/bower_components/jquery/src/jquery.js create mode 100644 public/admincp/bower_components/jquery/src/manipulation.js create mode 100644 public/admincp/bower_components/jquery/src/manipulation/_evalUrl.js create mode 100644 public/admincp/bower_components/jquery/src/manipulation/support.js create mode 100644 public/admincp/bower_components/jquery/src/manipulation/var/rcheckableType.js create mode 100644 public/admincp/bower_components/jquery/src/offset.js create mode 100644 public/admincp/bower_components/jquery/src/outro.js create mode 100644 public/admincp/bower_components/jquery/src/queue.js create mode 100644 public/admincp/bower_components/jquery/src/queue/delay.js create mode 100644 public/admincp/bower_components/jquery/src/selector-sizzle.js create mode 100644 public/admincp/bower_components/jquery/src/selector.js create mode 100644 public/admincp/bower_components/jquery/src/serialize.js create mode 100644 public/admincp/bower_components/jquery/src/sizzle/dist/sizzle.js create mode 100644 public/admincp/bower_components/jquery/src/sizzle/dist/sizzle.min.js create mode 100644 public/admincp/bower_components/jquery/src/sizzle/dist/sizzle.min.map create mode 100644 public/admincp/bower_components/jquery/src/support.js create mode 100644 public/admincp/bower_components/jquery/src/traversing.js create mode 100644 public/admincp/bower_components/jquery/src/traversing/findFilter.js create mode 100644 public/admincp/bower_components/jquery/src/traversing/var/rneedsContext.js create mode 100644 public/admincp/bower_components/jquery/src/var/class2type.js create mode 100644 public/admincp/bower_components/jquery/src/var/concat.js create mode 100644 public/admincp/bower_components/jquery/src/var/deletedIds.js create mode 100644 public/admincp/bower_components/jquery/src/var/hasOwn.js create mode 100644 public/admincp/bower_components/jquery/src/var/indexOf.js create mode 100644 public/admincp/bower_components/jquery/src/var/pnum.js create mode 100644 public/admincp/bower_components/jquery/src/var/push.js create mode 100644 public/admincp/bower_components/jquery/src/var/rnotwhite.js create mode 100644 public/admincp/bower_components/jquery/src/var/slice.js create mode 100644 public/admincp/bower_components/jquery/src/var/strundefined.js create mode 100644 public/admincp/bower_components/jquery/src/var/support.js create mode 100644 public/admincp/bower_components/jquery/src/var/toString.js create mode 100644 public/admincp/bower_components/jquery/src/wrap.js create mode 100644 public/admincp/bower_components/json3/.bower.json create mode 100644 public/admincp/bower_components/json3/LICENSE create mode 100644 public/admincp/bower_components/json3/README.md create mode 100644 public/admincp/bower_components/json3/bower.json create mode 100644 public/admincp/bower_components/json3/lib/json3.js create mode 100644 public/admincp/bower_components/json3/lib/json3.min.js create mode 100644 public/admincp/bower_components/lodash/.bower.json create mode 100644 public/admincp/bower_components/lodash/LICENSE.txt create mode 100644 public/admincp/bower_components/lodash/bower.json create mode 100644 public/admincp/bower_components/lodash/dist/lodash.compat.js create mode 100644 public/admincp/bower_components/lodash/dist/lodash.compat.min.js create mode 100644 public/admincp/bower_components/lodash/dist/lodash.js create mode 100644 public/admincp/bower_components/lodash/dist/lodash.min.js create mode 100644 public/admincp/bower_components/lodash/dist/lodash.underscore.js create mode 100644 public/admincp/bower_components/lodash/dist/lodash.underscore.min.js create mode 100644 public/admincp/bower_components/ng-admin/.bower.json create mode 100644 public/admincp/bower_components/ng-admin/LICENSE create mode 100644 public/admincp/bower_components/ng-admin/README.md create mode 100644 public/admincp/bower_components/ng-admin/assets/fonts/FontAwesome.otf create mode 100644 public/admincp/bower_components/ng-admin/assets/fonts/fontawesome-webfont.eot create mode 100644 public/admincp/bower_components/ng-admin/assets/fonts/fontawesome-webfont.svg create mode 100644 public/admincp/bower_components/ng-admin/assets/fonts/fontawesome-webfont.ttf create mode 100644 public/admincp/bower_components/ng-admin/assets/fonts/fontawesome-webfont.woff create mode 100644 public/admincp/bower_components/ng-admin/bower.json rename public/{assets/ngadmin/vendor => admincp/bower_components/ng-admin/build}/ng-admin.min.css (100%) rename public/{assets/ngadmin/vendor => admincp/bower_components/ng-admin/build}/ng-admin.min.js (100%) rename public/{assets/ngadmin/vendor => admincp/bower_components/ng-admin/build}/ng-admin.min.map (100%) create mode 100644 public/admincp/bower_components/ngInflection/.bower.json create mode 100644 public/admincp/bower_components/ngInflection/.gitignore create mode 100644 public/admincp/bower_components/ngInflection/bower.json create mode 100644 public/admincp/bower_components/ngInflection/ngInflection.js create mode 100644 public/admincp/bower_components/nprogress/.bower.json create mode 100644 public/admincp/bower_components/nprogress/History.md create mode 100644 public/admincp/bower_components/nprogress/License.md create mode 100644 public/admincp/bower_components/nprogress/Notes.md create mode 100644 public/admincp/bower_components/nprogress/Readme.md create mode 100644 public/admincp/bower_components/nprogress/bower.json create mode 100644 public/admincp/bower_components/nprogress/component.json create mode 100644 public/admincp/bower_components/nprogress/index.html create mode 100644 public/admincp/bower_components/nprogress/nprogress.css create mode 100644 public/admincp/bower_components/nprogress/nprogress.js create mode 100644 public/admincp/bower_components/nprogress/support/extras.css create mode 100644 public/admincp/bower_components/nprogress/support/style.css create mode 100644 public/admincp/bower_components/requirejs-text/.bower.json create mode 100644 public/admincp/bower_components/requirejs-text/LICENSE create mode 100644 public/admincp/bower_components/requirejs-text/README.md create mode 100644 public/admincp/bower_components/requirejs-text/package.json create mode 100644 public/admincp/bower_components/requirejs-text/text.js create mode 100644 public/admincp/bower_components/requirejs/.bower.json create mode 100644 public/admincp/bower_components/requirejs/README.md create mode 100644 public/admincp/bower_components/requirejs/bower.json create mode 100644 public/admincp/bower_components/requirejs/require.js create mode 100644 public/admincp/bower_components/restangular/.bower.json create mode 100644 public/admincp/bower_components/restangular/.gitignore create mode 100644 public/admincp/bower_components/restangular/.travis.yml create mode 100644 public/admincp/bower_components/restangular/CHANGELOG.md create mode 100644 public/admincp/bower_components/restangular/CONTRIBUTE.md create mode 100644 public/admincp/bower_components/restangular/Gruntfile.js create mode 100644 public/admincp/bower_components/restangular/README.md create mode 100644 public/admincp/bower_components/restangular/bower.json create mode 100644 public/admincp/bower_components/restangular/dist/restangular.js create mode 100644 public/admincp/bower_components/restangular/dist/restangular.min.js create mode 100644 public/admincp/bower_components/restangular/dist/restangular.zip create mode 100644 public/admincp/bower_components/restangular/karma.conf.js create mode 100644 public/admincp/bower_components/restangular/karma.underscore.conf.js create mode 100644 public/admincp/bower_components/restangular/license.md create mode 100644 public/admincp/bower_components/restangular/package.json create mode 100644 public/admincp/bower_components/restangular/src/restangular.js create mode 100644 public/admincp/bower_components/restangular/test/restangularSpec.js create mode 100644 public/admincp/bower_components/textAngular/.bower.json create mode 100644 public/admincp/bower_components/textAngular/CONTRIBUTING.md create mode 100644 public/admincp/bower_components/textAngular/README.md create mode 100644 public/admincp/bower_components/textAngular/bower.json create mode 100644 public/admincp/bower_components/textAngular/changelog.md create mode 100644 public/admincp/bower_components/textAngular/dist/textAngular-sanitize.min.js create mode 100644 public/admincp/bower_components/textAngular/dist/textAngular.min.js create mode 100644 public/admincp/bower_components/textAngular/karma-jqlite.conf.js create mode 100644 public/admincp/bower_components/textAngular/karma-jquery.conf.js create mode 100644 public/admincp/bower_components/textAngular/src/textAngular-sanitize.js create mode 100644 public/admincp/bower_components/textAngular/src/textAngular.js create mode 100644 public/admincp/bower_components/textAngular/src/textAngularSetup.js rename public/{assets/ngadmin => admincp}/style.css (100%) delete mode 100644 public/assets/ngadmin/app.js diff --git a/public/admincp/app.js b/public/admincp/app.js new file mode 100644 index 000000000..0f7e863cf --- /dev/null +++ b/public/admincp/app.js @@ -0,0 +1,161 @@ +/*global angular*/ +(function () { + "use strict"; + + var app = angular.module('myApp', ['ng-admin']); + + app.controller('main', function ($scope, $rootScope, $location) { + $rootScope.$on('$stateChangeSuccess', function () { + $scope.displayBanner = $location.$$path === '/dashboard'; + }); + }); + + app.directive('testEditLink', function () { + return { + restrict: 'E', + template: '' + + ' Sửa' + }; + }); + app.directive('testShowLink', function () { + return { + restrict: 'E', + template: '' + + ' Xem' + }; + }); + app.directive('color', function () { + return { + restrict: 'E', + template: '' + + '#{{entry.values.color}}' + }; + }); + app.directive('createdAt', function () { + return { + restrict: 'E', + template: '{{entry.values.created_at.date}}' + }; + }); + + /* Pass csrf token to X-CSRF-TOKEN header on every request */ + app.config(['$httpProvider',function($httpProvider){ + $httpProvider.defaults.headers.common['X-CSRF-TOKEN'] = document.getElementsByTagName('csrf')[0].getAttribute("content") + }]); + + app.config(function (NgAdminConfigurationProvider, Application, Entity, Field, Reference, ReferencedList, ReferenceMany) { + function truncate(value) { + if (!value) { + return ''; + } + return value.length > 40 ? value.substr(0, 40) + '...' : value; + } + function transformParams (params) { + params._sort = 'name'; + return params; + } + function dateParser(value){ + console.log(value.date); + return value.date; + } + var app = new Application('ng-admmin Admin CP') // application main title + // remember to change the following to your api link + .baseApiUrl('http://localhost/laravel-ngadmin/public/api/') + .transformParams(function(params) { + // Default parameters to override: page, per_page, q, _sort, _sortDir. + if (typeof params._sort === 'undefined') { + params._sort = 'id'; + } + return params; + }); + + var user = new Entity('users'); + var role = new Entity('roles'); + var permission = new Entity('permissions'); + + app + .addEntity(user) + .addEntity(role) + .addEntity(permission); + + /* + * Menu View + */ + user.menuView().icon(' '); + + role.dashboardView().disable(); + permission.dashboardView().disable(); + + permission.listView() + .title('All permissions') + .addField(new Field('id')) + .addField(new Field('name') + .isDetailLink(true) + ) + .addField(new Field('display_name') + .label('Display Name') + .isDetailLink(true) + ) + + /* + * Role section + * + */ + role.listView() + .title('All roles') + .addField(new Field('id')) + .addField(new Field('name').isDetailLink(true)) + .addField(new Field('count').label('# of Users')) + .addField(new Field().type('template').label('Created Date') + .template('') + ) + .listActions(['edit', 'delete']); + role.creationView() + .addField(new Field('name').validation({required: true, minlength: 3}) ) + .addField(new ReferenceMany('permissions') + .targetEntity(permission) + .targetField(new Field('display_name')) + ) + role.editionView() + .addField(new Field('name').validation({required: true, minlength: 3}) ) + .addField(new ReferenceMany('permissions') + .targetEntity(permission) + .targetField(new Field('display_name')) + ) + + /* + * User section + * + */ + user.filterView() + .addField( new Field('query').label('Search').attributes({placeholder: 'Name / Email'}) ); + + user.dashboardView() + .title('New User') + .order(3) + .limit(10) + .addField(new Field('id').label('ID')) + .addField(new Field('username')) + .addField(new Field('name')); + + user.listView() + .infinitePagination(true) + .title('All users') + .addField(new Field('id')) + .addField(new Field('username')) + .addField(new Field('email')) + .filterQuery(function(searchQuery) { + return { q: searchQuery }; + }) + .listActions(['edit', 'delete']); + + user.editionView() + .title('Edit user "{{ entry.values.user }}"') + .actions(['list', 'delete']) + .addField(new Field('id')) + .addField(new Field('username')) + .addField(new Field('email')); + + NgAdminConfigurationProvider.configure(app); + }); +}()); diff --git a/public/admincp/bower.json b/public/admincp/bower.json new file mode 100644 index 000000000..058b67a8a --- /dev/null +++ b/public/admincp/bower.json @@ -0,0 +1,10 @@ +{ + "name": "Laravel ng-admin", + "version": "1.0.0", + "dependencies": { + "ng-admin": "master" + }, + "resolutions": { + "angular": "~1.3.1" + } +} diff --git a/public/admincp/bower_components/angular-bootstrap/.bower.json b/public/admincp/bower_components/angular-bootstrap/.bower.json new file mode 100644 index 000000000..1f23dea87 --- /dev/null +++ b/public/admincp/bower_components/angular-bootstrap/.bower.json @@ -0,0 +1,29 @@ +{ + "author": { + "name": "https://github.com/angular-ui/bootstrap/graphs/contributors" + }, + "name": "angular-bootstrap", + "keywords": [ + "angular", + "angular-ui", + "bootstrap" + ], + "description": "Native AngularJS (Angular) directives for Bootstrap.", + "version": "0.12.0", + "main": [ + "./ui-bootstrap-tpls.js" + ], + "dependencies": { + "angular": ">=1 <1.3.0" + }, + "homepage": "https://github.com/angular-ui/bootstrap-bower", + "_release": "0.12.0", + "_resolution": { + "type": "version", + "tag": "0.12.0", + "commit": "b7a256c24b4545e633920ca9a9545b35ed425412" + }, + "_source": "git://github.com/angular-ui/bootstrap-bower.git", + "_target": "~0.12.0", + "_originalSource": "angular-bootstrap" +} \ No newline at end of file diff --git a/public/admincp/bower_components/angular-bootstrap/bower.json b/public/admincp/bower_components/angular-bootstrap/bower.json new file mode 100644 index 000000000..6953a51bd --- /dev/null +++ b/public/admincp/bower_components/angular-bootstrap/bower.json @@ -0,0 +1,17 @@ +{ + "author": { + "name": "https://github.com/angular-ui/bootstrap/graphs/contributors" + }, + "name": "angular-bootstrap", + "keywords": [ + "angular", + "angular-ui", + "bootstrap" + ], + "description": "Native AngularJS (Angular) directives for Bootstrap.", + "version": "0.12.0", + "main": ["./ui-bootstrap-tpls.js"], + "dependencies": { + "angular": ">=1 <1.3.0" + } +} diff --git a/public/admincp/bower_components/angular-bootstrap/ui-bootstrap-tpls.js b/public/admincp/bower_components/angular-bootstrap/ui-bootstrap-tpls.js new file mode 100644 index 000000000..f0cdbb034 --- /dev/null +++ b/public/admincp/bower_components/angular-bootstrap/ui-bootstrap-tpls.js @@ -0,0 +1,4212 @@ +/* + * angular-ui-bootstrap + * http://angular-ui.github.io/bootstrap/ + + * Version: 0.12.0 - 2014-11-16 + * License: MIT + */ +angular.module("ui.bootstrap", ["ui.bootstrap.tpls", "ui.bootstrap.transition","ui.bootstrap.collapse","ui.bootstrap.accordion","ui.bootstrap.alert","ui.bootstrap.bindHtml","ui.bootstrap.buttons","ui.bootstrap.carousel","ui.bootstrap.dateparser","ui.bootstrap.position","ui.bootstrap.datepicker","ui.bootstrap.dropdown","ui.bootstrap.modal","ui.bootstrap.pagination","ui.bootstrap.tooltip","ui.bootstrap.popover","ui.bootstrap.progressbar","ui.bootstrap.rating","ui.bootstrap.tabs","ui.bootstrap.timepicker","ui.bootstrap.typeahead"]); +angular.module("ui.bootstrap.tpls", ["template/accordion/accordion-group.html","template/accordion/accordion.html","template/alert/alert.html","template/carousel/carousel.html","template/carousel/slide.html","template/datepicker/datepicker.html","template/datepicker/day.html","template/datepicker/month.html","template/datepicker/popup.html","template/datepicker/year.html","template/modal/backdrop.html","template/modal/window.html","template/pagination/pager.html","template/pagination/pagination.html","template/tooltip/tooltip-html-unsafe-popup.html","template/tooltip/tooltip-popup.html","template/popover/popover.html","template/progressbar/bar.html","template/progressbar/progress.html","template/progressbar/progressbar.html","template/rating/rating.html","template/tabs/tab.html","template/tabs/tabset.html","template/timepicker/timepicker.html","template/typeahead/typeahead-match.html","template/typeahead/typeahead-popup.html"]); +angular.module('ui.bootstrap.transition', []) + +/** + * $transition service provides a consistent interface to trigger CSS 3 transitions and to be informed when they complete. + * @param {DOMElement} element The DOMElement that will be animated. + * @param {string|object|function} trigger The thing that will cause the transition to start: + * - As a string, it represents the css class to be added to the element. + * - As an object, it represents a hash of style attributes to be applied to the element. + * - As a function, it represents a function to be called that will cause the transition to occur. + * @return {Promise} A promise that is resolved when the transition finishes. + */ +.factory('$transition', ['$q', '$timeout', '$rootScope', function($q, $timeout, $rootScope) { + + var $transition = function(element, trigger, options) { + options = options || {}; + var deferred = $q.defer(); + var endEventName = $transition[options.animation ? 'animationEndEventName' : 'transitionEndEventName']; + + var transitionEndHandler = function(event) { + $rootScope.$apply(function() { + element.unbind(endEventName, transitionEndHandler); + deferred.resolve(element); + }); + }; + + if (endEventName) { + element.bind(endEventName, transitionEndHandler); + } + + // Wrap in a timeout to allow the browser time to update the DOM before the transition is to occur + $timeout(function() { + if ( angular.isString(trigger) ) { + element.addClass(trigger); + } else if ( angular.isFunction(trigger) ) { + trigger(element); + } else if ( angular.isObject(trigger) ) { + element.css(trigger); + } + //If browser does not support transitions, instantly resolve + if ( !endEventName ) { + deferred.resolve(element); + } + }); + + // Add our custom cancel function to the promise that is returned + // We can call this if we are about to run a new transition, which we know will prevent this transition from ending, + // i.e. it will therefore never raise a transitionEnd event for that transition + deferred.promise.cancel = function() { + if ( endEventName ) { + element.unbind(endEventName, transitionEndHandler); + } + deferred.reject('Transition cancelled'); + }; + + return deferred.promise; + }; + + // Work out the name of the transitionEnd event + var transElement = document.createElement('trans'); + var transitionEndEventNames = { + 'WebkitTransition': 'webkitTransitionEnd', + 'MozTransition': 'transitionend', + 'OTransition': 'oTransitionEnd', + 'transition': 'transitionend' + }; + var animationEndEventNames = { + 'WebkitTransition': 'webkitAnimationEnd', + 'MozTransition': 'animationend', + 'OTransition': 'oAnimationEnd', + 'transition': 'animationend' + }; + function findEndEventName(endEventNames) { + for (var name in endEventNames){ + if (transElement.style[name] !== undefined) { + return endEventNames[name]; + } + } + } + $transition.transitionEndEventName = findEndEventName(transitionEndEventNames); + $transition.animationEndEventName = findEndEventName(animationEndEventNames); + return $transition; +}]); + +angular.module('ui.bootstrap.collapse', ['ui.bootstrap.transition']) + + .directive('collapse', ['$transition', function ($transition) { + + return { + link: function (scope, element, attrs) { + + var initialAnimSkip = true; + var currentTransition; + + function doTransition(change) { + var newTransition = $transition(element, change); + if (currentTransition) { + currentTransition.cancel(); + } + currentTransition = newTransition; + newTransition.then(newTransitionDone, newTransitionDone); + return newTransition; + + function newTransitionDone() { + // Make sure it's this transition, otherwise, leave it alone. + if (currentTransition === newTransition) { + currentTransition = undefined; + } + } + } + + function expand() { + if (initialAnimSkip) { + initialAnimSkip = false; + expandDone(); + } else { + element.removeClass('collapse').addClass('collapsing'); + doTransition({ height: element[0].scrollHeight + 'px' }).then(expandDone); + } + } + + function expandDone() { + element.removeClass('collapsing'); + element.addClass('collapse in'); + element.css({height: 'auto'}); + } + + function collapse() { + if (initialAnimSkip) { + initialAnimSkip = false; + collapseDone(); + element.css({height: 0}); + } else { + // CSS transitions don't work with height: auto, so we have to manually change the height to a specific value + element.css({ height: element[0].scrollHeight + 'px' }); + //trigger reflow so a browser realizes that height was updated from auto to a specific value + var x = element[0].offsetWidth; + + element.removeClass('collapse in').addClass('collapsing'); + + doTransition({ height: 0 }).then(collapseDone); + } + } + + function collapseDone() { + element.removeClass('collapsing'); + element.addClass('collapse'); + } + + scope.$watch(attrs.collapse, function (shouldCollapse) { + if (shouldCollapse) { + collapse(); + } else { + expand(); + } + }); + } + }; + }]); + +angular.module('ui.bootstrap.accordion', ['ui.bootstrap.collapse']) + +.constant('accordionConfig', { + closeOthers: true +}) + +.controller('AccordionController', ['$scope', '$attrs', 'accordionConfig', function ($scope, $attrs, accordionConfig) { + + // This array keeps track of the accordion groups + this.groups = []; + + // Ensure that all the groups in this accordion are closed, unless close-others explicitly says not to + this.closeOthers = function(openGroup) { + var closeOthers = angular.isDefined($attrs.closeOthers) ? $scope.$eval($attrs.closeOthers) : accordionConfig.closeOthers; + if ( closeOthers ) { + angular.forEach(this.groups, function (group) { + if ( group !== openGroup ) { + group.isOpen = false; + } + }); + } + }; + + // This is called from the accordion-group directive to add itself to the accordion + this.addGroup = function(groupScope) { + var that = this; + this.groups.push(groupScope); + + groupScope.$on('$destroy', function (event) { + that.removeGroup(groupScope); + }); + }; + + // This is called from the accordion-group directive when to remove itself + this.removeGroup = function(group) { + var index = this.groups.indexOf(group); + if ( index !== -1 ) { + this.groups.splice(index, 1); + } + }; + +}]) + +// The accordion directive simply sets up the directive controller +// and adds an accordion CSS class to itself element. +.directive('accordion', function () { + return { + restrict:'EA', + controller:'AccordionController', + transclude: true, + replace: false, + templateUrl: 'template/accordion/accordion.html' + }; +}) + +// The accordion-group directive indicates a block of html that will expand and collapse in an accordion +.directive('accordionGroup', function() { + return { + require:'^accordion', // We need this directive to be inside an accordion + restrict:'EA', + transclude:true, // It transcludes the contents of the directive into the template + replace: true, // The element containing the directive will be replaced with the template + templateUrl:'template/accordion/accordion-group.html', + scope: { + heading: '@', // Interpolate the heading attribute onto this scope + isOpen: '=?', + isDisabled: '=?' + }, + controller: function() { + this.setHeading = function(element) { + this.heading = element; + }; + }, + link: function(scope, element, attrs, accordionCtrl) { + accordionCtrl.addGroup(scope); + + scope.$watch('isOpen', function(value) { + if ( value ) { + accordionCtrl.closeOthers(scope); + } + }); + + scope.toggleOpen = function() { + if ( !scope.isDisabled ) { + scope.isOpen = !scope.isOpen; + } + }; + } + }; +}) + +// Use accordion-heading below an accordion-group to provide a heading containing HTML +// +// Heading containing HTML - +// +.directive('accordionHeading', function() { + return { + restrict: 'EA', + transclude: true, // Grab the contents to be used as the heading + template: '', // In effect remove this element! + replace: true, + require: '^accordionGroup', + link: function(scope, element, attr, accordionGroupCtrl, transclude) { + // Pass the heading to the accordion-group controller + // so that it can be transcluded into the right place in the template + // [The second parameter to transclude causes the elements to be cloned so that they work in ng-repeat] + accordionGroupCtrl.setHeading(transclude(scope, function() {})); + } + }; +}) + +// Use in the accordion-group template to indicate where you want the heading to be transcluded +// You must provide the property on the accordion-group controller that will hold the transcluded element +//
    +// +// ... +//
    +.directive('accordionTransclude', function() { + return { + require: '^accordionGroup', + link: function(scope, element, attr, controller) { + scope.$watch(function() { return controller[attr.accordionTransclude]; }, function(heading) { + if ( heading ) { + element.html(''); + element.append(heading); + } + }); + } + }; +}); + +angular.module('ui.bootstrap.alert', []) + +.controller('AlertController', ['$scope', '$attrs', function ($scope, $attrs) { + $scope.closeable = 'close' in $attrs; + this.close = $scope.close; +}]) + +.directive('alert', function () { + return { + restrict:'EA', + controller:'AlertController', + templateUrl:'template/alert/alert.html', + transclude:true, + replace:true, + scope: { + type: '@', + close: '&' + } + }; +}) + +.directive('dismissOnTimeout', ['$timeout', function($timeout) { + return { + require: 'alert', + link: function(scope, element, attrs, alertCtrl) { + $timeout(function(){ + alertCtrl.close(); + }, parseInt(attrs.dismissOnTimeout, 10)); + } + }; +}]); + +angular.module('ui.bootstrap.bindHtml', []) + + .directive('bindHtmlUnsafe', function () { + return function (scope, element, attr) { + element.addClass('ng-binding').data('$binding', attr.bindHtmlUnsafe); + scope.$watch(attr.bindHtmlUnsafe, function bindHtmlUnsafeWatchAction(value) { + element.html(value || ''); + }); + }; + }); +angular.module('ui.bootstrap.buttons', []) + +.constant('buttonConfig', { + activeClass: 'active', + toggleEvent: 'click' +}) + +.controller('ButtonsController', ['buttonConfig', function(buttonConfig) { + this.activeClass = buttonConfig.activeClass || 'active'; + this.toggleEvent = buttonConfig.toggleEvent || 'click'; +}]) + +.directive('btnRadio', function () { + return { + require: ['btnRadio', 'ngModel'], + controller: 'ButtonsController', + link: function (scope, element, attrs, ctrls) { + var buttonsCtrl = ctrls[0], ngModelCtrl = ctrls[1]; + + //model -> UI + ngModelCtrl.$render = function () { + element.toggleClass(buttonsCtrl.activeClass, angular.equals(ngModelCtrl.$modelValue, scope.$eval(attrs.btnRadio))); + }; + + //ui->model + element.bind(buttonsCtrl.toggleEvent, function () { + var isActive = element.hasClass(buttonsCtrl.activeClass); + + if (!isActive || angular.isDefined(attrs.uncheckable)) { + scope.$apply(function () { + ngModelCtrl.$setViewValue(isActive ? null : scope.$eval(attrs.btnRadio)); + ngModelCtrl.$render(); + }); + } + }); + } + }; +}) + +.directive('btnCheckbox', function () { + return { + require: ['btnCheckbox', 'ngModel'], + controller: 'ButtonsController', + link: function (scope, element, attrs, ctrls) { + var buttonsCtrl = ctrls[0], ngModelCtrl = ctrls[1]; + + function getTrueValue() { + return getCheckboxValue(attrs.btnCheckboxTrue, true); + } + + function getFalseValue() { + return getCheckboxValue(attrs.btnCheckboxFalse, false); + } + + function getCheckboxValue(attributeValue, defaultValue) { + var val = scope.$eval(attributeValue); + return angular.isDefined(val) ? val : defaultValue; + } + + //model -> UI + ngModelCtrl.$render = function () { + element.toggleClass(buttonsCtrl.activeClass, angular.equals(ngModelCtrl.$modelValue, getTrueValue())); + }; + + //ui->model + element.bind(buttonsCtrl.toggleEvent, function () { + scope.$apply(function () { + ngModelCtrl.$setViewValue(element.hasClass(buttonsCtrl.activeClass) ? getFalseValue() : getTrueValue()); + ngModelCtrl.$render(); + }); + }); + } + }; +}); + +/** +* @ngdoc overview +* @name ui.bootstrap.carousel +* +* @description +* AngularJS version of an image carousel. +* +*/ +angular.module('ui.bootstrap.carousel', ['ui.bootstrap.transition']) +.controller('CarouselController', ['$scope', '$timeout', '$interval', '$transition', function ($scope, $timeout, $interval, $transition) { + var self = this, + slides = self.slides = $scope.slides = [], + currentIndex = -1, + currentInterval, isPlaying; + self.currentSlide = null; + + var destroyed = false; + /* direction: "prev" or "next" */ + self.select = $scope.select = function(nextSlide, direction) { + var nextIndex = slides.indexOf(nextSlide); + //Decide direction if it's not given + if (direction === undefined) { + direction = nextIndex > currentIndex ? 'next' : 'prev'; + } + if (nextSlide && nextSlide !== self.currentSlide) { + if ($scope.$currentTransition) { + $scope.$currentTransition.cancel(); + //Timeout so ng-class in template has time to fix classes for finished slide + $timeout(goNext); + } else { + goNext(); + } + } + function goNext() { + // Scope has been destroyed, stop here. + if (destroyed) { return; } + //If we have a slide to transition from and we have a transition type and we're allowed, go + if (self.currentSlide && angular.isString(direction) && !$scope.noTransition && nextSlide.$element) { + //We shouldn't do class manip in here, but it's the same weird thing bootstrap does. need to fix sometime + nextSlide.$element.addClass(direction); + var reflow = nextSlide.$element[0].offsetWidth; //force reflow + + //Set all other slides to stop doing their stuff for the new transition + angular.forEach(slides, function(slide) { + angular.extend(slide, {direction: '', entering: false, leaving: false, active: false}); + }); + angular.extend(nextSlide, {direction: direction, active: true, entering: true}); + angular.extend(self.currentSlide||{}, {direction: direction, leaving: true}); + + $scope.$currentTransition = $transition(nextSlide.$element, {}); + //We have to create new pointers inside a closure since next & current will change + (function(next,current) { + $scope.$currentTransition.then( + function(){ transitionDone(next, current); }, + function(){ transitionDone(next, current); } + ); + }(nextSlide, self.currentSlide)); + } else { + transitionDone(nextSlide, self.currentSlide); + } + self.currentSlide = nextSlide; + currentIndex = nextIndex; + //every time you change slides, reset the timer + restartTimer(); + } + function transitionDone(next, current) { + angular.extend(next, {direction: '', active: true, leaving: false, entering: false}); + angular.extend(current||{}, {direction: '', active: false, leaving: false, entering: false}); + $scope.$currentTransition = null; + } + }; + $scope.$on('$destroy', function () { + destroyed = true; + }); + + /* Allow outside people to call indexOf on slides array */ + self.indexOfSlide = function(slide) { + return slides.indexOf(slide); + }; + + $scope.next = function() { + var newIndex = (currentIndex + 1) % slides.length; + + //Prevent this user-triggered transition from occurring if there is already one in progress + if (!$scope.$currentTransition) { + return self.select(slides[newIndex], 'next'); + } + }; + + $scope.prev = function() { + var newIndex = currentIndex - 1 < 0 ? slides.length - 1 : currentIndex - 1; + + //Prevent this user-triggered transition from occurring if there is already one in progress + if (!$scope.$currentTransition) { + return self.select(slides[newIndex], 'prev'); + } + }; + + $scope.isActive = function(slide) { + return self.currentSlide === slide; + }; + + $scope.$watch('interval', restartTimer); + $scope.$on('$destroy', resetTimer); + + function restartTimer() { + resetTimer(); + var interval = +$scope.interval; + if (!isNaN(interval) && interval > 0) { + currentInterval = $interval(timerFn, interval); + } + } + + function resetTimer() { + if (currentInterval) { + $interval.cancel(currentInterval); + currentInterval = null; + } + } + + function timerFn() { + var interval = +$scope.interval; + if (isPlaying && !isNaN(interval) && interval > 0) { + $scope.next(); + } else { + $scope.pause(); + } + } + + $scope.play = function() { + if (!isPlaying) { + isPlaying = true; + restartTimer(); + } + }; + $scope.pause = function() { + if (!$scope.noPause) { + isPlaying = false; + resetTimer(); + } + }; + + self.addSlide = function(slide, element) { + slide.$element = element; + slides.push(slide); + //if this is the first slide or the slide is set to active, select it + if(slides.length === 1 || slide.active) { + self.select(slides[slides.length-1]); + if (slides.length == 1) { + $scope.play(); + } + } else { + slide.active = false; + } + }; + + self.removeSlide = function(slide) { + //get the index of the slide inside the carousel + var index = slides.indexOf(slide); + slides.splice(index, 1); + if (slides.length > 0 && slide.active) { + if (index >= slides.length) { + self.select(slides[index-1]); + } else { + self.select(slides[index]); + } + } else if (currentIndex > index) { + currentIndex--; + } + }; + +}]) + +/** + * @ngdoc directive + * @name ui.bootstrap.carousel.directive:carousel + * @restrict EA + * + * @description + * Carousel is the outer container for a set of image 'slides' to showcase. + * + * @param {number=} interval The time, in milliseconds, that it will take the carousel to go to the next slide. + * @param {boolean=} noTransition Whether to disable transitions on the carousel. + * @param {boolean=} noPause Whether to disable pausing on the carousel (by default, the carousel interval pauses on hover). + * + * @example + + + + + + + + + + + + + + + .carousel-indicators { + top: auto; + bottom: 15px; + } + + + */ +.directive('carousel', [function() { + return { + restrict: 'EA', + transclude: true, + replace: true, + controller: 'CarouselController', + require: 'carousel', + templateUrl: 'template/carousel/carousel.html', + scope: { + interval: '=', + noTransition: '=', + noPause: '=' + } + }; +}]) + +/** + * @ngdoc directive + * @name ui.bootstrap.carousel.directive:slide + * @restrict EA + * + * @description + * Creates a slide inside a {@link ui.bootstrap.carousel.directive:carousel carousel}. Must be placed as a child of a carousel element. + * + * @param {boolean=} active Model binding, whether or not this slide is currently active. + * + * @example + + +
    + + + + + + + Interval, in milliseconds: +
    Enter a negative number to stop the interval. +
    +
    + +function CarouselDemoCtrl($scope) { + $scope.myInterval = 5000; +} + + + .carousel-indicators { + top: auto; + bottom: 15px; + } + +
    +*/ + +.directive('slide', function() { + return { + require: '^carousel', + restrict: 'EA', + transclude: true, + replace: true, + templateUrl: 'template/carousel/slide.html', + scope: { + active: '=?' + }, + link: function (scope, element, attrs, carouselCtrl) { + carouselCtrl.addSlide(scope, element); + //when the scope is destroyed then remove the slide from the current slides array + scope.$on('$destroy', function() { + carouselCtrl.removeSlide(scope); + }); + + scope.$watch('active', function(active) { + if (active) { + carouselCtrl.select(scope); + } + }); + } + }; +}); + +angular.module('ui.bootstrap.dateparser', []) + +.service('dateParser', ['$locale', 'orderByFilter', function($locale, orderByFilter) { + + this.parsers = {}; + + var formatCodeToRegex = { + 'yyyy': { + regex: '\\d{4}', + apply: function(value) { this.year = +value; } + }, + 'yy': { + regex: '\\d{2}', + apply: function(value) { this.year = +value + 2000; } + }, + 'y': { + regex: '\\d{1,4}', + apply: function(value) { this.year = +value; } + }, + 'MMMM': { + regex: $locale.DATETIME_FORMATS.MONTH.join('|'), + apply: function(value) { this.month = $locale.DATETIME_FORMATS.MONTH.indexOf(value); } + }, + 'MMM': { + regex: $locale.DATETIME_FORMATS.SHORTMONTH.join('|'), + apply: function(value) { this.month = $locale.DATETIME_FORMATS.SHORTMONTH.indexOf(value); } + }, + 'MM': { + regex: '0[1-9]|1[0-2]', + apply: function(value) { this.month = value - 1; } + }, + 'M': { + regex: '[1-9]|1[0-2]', + apply: function(value) { this.month = value - 1; } + }, + 'dd': { + regex: '[0-2][0-9]{1}|3[0-1]{1}', + apply: function(value) { this.date = +value; } + }, + 'd': { + regex: '[1-2]?[0-9]{1}|3[0-1]{1}', + apply: function(value) { this.date = +value; } + }, + 'EEEE': { + regex: $locale.DATETIME_FORMATS.DAY.join('|') + }, + 'EEE': { + regex: $locale.DATETIME_FORMATS.SHORTDAY.join('|') + } + }; + + function createParser(format) { + var map = [], regex = format.split(''); + + angular.forEach(formatCodeToRegex, function(data, code) { + var index = format.indexOf(code); + + if (index > -1) { + format = format.split(''); + + regex[index] = '(' + data.regex + ')'; + format[index] = '$'; // Custom symbol to define consumed part of format + for (var i = index + 1, n = index + code.length; i < n; i++) { + regex[i] = ''; + format[i] = '$'; + } + format = format.join(''); + + map.push({ index: index, apply: data.apply }); + } + }); + + return { + regex: new RegExp('^' + regex.join('') + '$'), + map: orderByFilter(map, 'index') + }; + } + + this.parse = function(input, format) { + if ( !angular.isString(input) || !format ) { + return input; + } + + format = $locale.DATETIME_FORMATS[format] || format; + + if ( !this.parsers[format] ) { + this.parsers[format] = createParser(format); + } + + var parser = this.parsers[format], + regex = parser.regex, + map = parser.map, + results = input.match(regex); + + if ( results && results.length ) { + var fields = { year: 1900, month: 0, date: 1, hours: 0 }, dt; + + for( var i = 1, n = results.length; i < n; i++ ) { + var mapper = map[i-1]; + if ( mapper.apply ) { + mapper.apply.call(fields, results[i]); + } + } + + if ( isValid(fields.year, fields.month, fields.date) ) { + dt = new Date( fields.year, fields.month, fields.date, fields.hours); + } + + return dt; + } + }; + + // Check if date is valid for specific month (and year for February). + // Month: 0 = Jan, 1 = Feb, etc + function isValid(year, month, date) { + if ( month === 1 && date > 28) { + return date === 29 && ((year % 4 === 0 && year % 100 !== 0) || year % 400 === 0); + } + + if ( month === 3 || month === 5 || month === 8 || month === 10) { + return date < 31; + } + + return true; + } +}]); + +angular.module('ui.bootstrap.position', []) + +/** + * A set of utility methods that can be use to retrieve position of DOM elements. + * It is meant to be used where we need to absolute-position DOM elements in + * relation to other, existing elements (this is the case for tooltips, popovers, + * typeahead suggestions etc.). + */ + .factory('$position', ['$document', '$window', function ($document, $window) { + + function getStyle(el, cssprop) { + if (el.currentStyle) { //IE + return el.currentStyle[cssprop]; + } else if ($window.getComputedStyle) { + return $window.getComputedStyle(el)[cssprop]; + } + // finally try and get inline style + return el.style[cssprop]; + } + + /** + * Checks if a given element is statically positioned + * @param element - raw DOM element + */ + function isStaticPositioned(element) { + return (getStyle(element, 'position') || 'static' ) === 'static'; + } + + /** + * returns the closest, non-statically positioned parentOffset of a given element + * @param element + */ + var parentOffsetEl = function (element) { + var docDomEl = $document[0]; + var offsetParent = element.offsetParent || docDomEl; + while (offsetParent && offsetParent !== docDomEl && isStaticPositioned(offsetParent) ) { + offsetParent = offsetParent.offsetParent; + } + return offsetParent || docDomEl; + }; + + return { + /** + * Provides read-only equivalent of jQuery's position function: + * http://api.jquery.com/position/ + */ + position: function (element) { + var elBCR = this.offset(element); + var offsetParentBCR = { top: 0, left: 0 }; + var offsetParentEl = parentOffsetEl(element[0]); + if (offsetParentEl != $document[0]) { + offsetParentBCR = this.offset(angular.element(offsetParentEl)); + offsetParentBCR.top += offsetParentEl.clientTop - offsetParentEl.scrollTop; + offsetParentBCR.left += offsetParentEl.clientLeft - offsetParentEl.scrollLeft; + } + + var boundingClientRect = element[0].getBoundingClientRect(); + return { + width: boundingClientRect.width || element.prop('offsetWidth'), + height: boundingClientRect.height || element.prop('offsetHeight'), + top: elBCR.top - offsetParentBCR.top, + left: elBCR.left - offsetParentBCR.left + }; + }, + + /** + * Provides read-only equivalent of jQuery's offset function: + * http://api.jquery.com/offset/ + */ + offset: function (element) { + var boundingClientRect = element[0].getBoundingClientRect(); + return { + width: boundingClientRect.width || element.prop('offsetWidth'), + height: boundingClientRect.height || element.prop('offsetHeight'), + top: boundingClientRect.top + ($window.pageYOffset || $document[0].documentElement.scrollTop), + left: boundingClientRect.left + ($window.pageXOffset || $document[0].documentElement.scrollLeft) + }; + }, + + /** + * Provides coordinates for the targetEl in relation to hostEl + */ + positionElements: function (hostEl, targetEl, positionStr, appendToBody) { + + var positionStrParts = positionStr.split('-'); + var pos0 = positionStrParts[0], pos1 = positionStrParts[1] || 'center'; + + var hostElPos, + targetElWidth, + targetElHeight, + targetElPos; + + hostElPos = appendToBody ? this.offset(hostEl) : this.position(hostEl); + + targetElWidth = targetEl.prop('offsetWidth'); + targetElHeight = targetEl.prop('offsetHeight'); + + var shiftWidth = { + center: function () { + return hostElPos.left + hostElPos.width / 2 - targetElWidth / 2; + }, + left: function () { + return hostElPos.left; + }, + right: function () { + return hostElPos.left + hostElPos.width; + } + }; + + var shiftHeight = { + center: function () { + return hostElPos.top + hostElPos.height / 2 - targetElHeight / 2; + }, + top: function () { + return hostElPos.top; + }, + bottom: function () { + return hostElPos.top + hostElPos.height; + } + }; + + switch (pos0) { + case 'right': + targetElPos = { + top: shiftHeight[pos1](), + left: shiftWidth[pos0]() + }; + break; + case 'left': + targetElPos = { + top: shiftHeight[pos1](), + left: hostElPos.left - targetElWidth + }; + break; + case 'bottom': + targetElPos = { + top: shiftHeight[pos0](), + left: shiftWidth[pos1]() + }; + break; + default: + targetElPos = { + top: hostElPos.top - targetElHeight, + left: shiftWidth[pos1]() + }; + break; + } + + return targetElPos; + } + }; + }]); + +angular.module('ui.bootstrap.datepicker', ['ui.bootstrap.dateparser', 'ui.bootstrap.position']) + +.constant('datepickerConfig', { + formatDay: 'dd', + formatMonth: 'MMMM', + formatYear: 'yyyy', + formatDayHeader: 'EEE', + formatDayTitle: 'MMMM yyyy', + formatMonthTitle: 'yyyy', + datepickerMode: 'day', + minMode: 'day', + maxMode: 'year', + showWeeks: true, + startingDay: 0, + yearRange: 20, + minDate: null, + maxDate: null +}) + +.controller('DatepickerController', ['$scope', '$attrs', '$parse', '$interpolate', '$timeout', '$log', 'dateFilter', 'datepickerConfig', function($scope, $attrs, $parse, $interpolate, $timeout, $log, dateFilter, datepickerConfig) { + var self = this, + ngModelCtrl = { $setViewValue: angular.noop }; // nullModelCtrl; + + // Modes chain + this.modes = ['day', 'month', 'year']; + + // Configuration attributes + angular.forEach(['formatDay', 'formatMonth', 'formatYear', 'formatDayHeader', 'formatDayTitle', 'formatMonthTitle', + 'minMode', 'maxMode', 'showWeeks', 'startingDay', 'yearRange'], function( key, index ) { + self[key] = angular.isDefined($attrs[key]) ? (index < 8 ? $interpolate($attrs[key])($scope.$parent) : $scope.$parent.$eval($attrs[key])) : datepickerConfig[key]; + }); + + // Watchable date attributes + angular.forEach(['minDate', 'maxDate'], function( key ) { + if ( $attrs[key] ) { + $scope.$parent.$watch($parse($attrs[key]), function(value) { + self[key] = value ? new Date(value) : null; + self.refreshView(); + }); + } else { + self[key] = datepickerConfig[key] ? new Date(datepickerConfig[key]) : null; + } + }); + + $scope.datepickerMode = $scope.datepickerMode || datepickerConfig.datepickerMode; + $scope.uniqueId = 'datepicker-' + $scope.$id + '-' + Math.floor(Math.random() * 10000); + this.activeDate = angular.isDefined($attrs.initDate) ? $scope.$parent.$eval($attrs.initDate) : new Date(); + + $scope.isActive = function(dateObject) { + if (self.compare(dateObject.date, self.activeDate) === 0) { + $scope.activeDateId = dateObject.uid; + return true; + } + return false; + }; + + this.init = function( ngModelCtrl_ ) { + ngModelCtrl = ngModelCtrl_; + + ngModelCtrl.$render = function() { + self.render(); + }; + }; + + this.render = function() { + if ( ngModelCtrl.$modelValue ) { + var date = new Date( ngModelCtrl.$modelValue ), + isValid = !isNaN(date); + + if ( isValid ) { + this.activeDate = date; + } else { + $log.error('Datepicker directive: "ng-model" value must be a Date object, a number of milliseconds since 01.01.1970 or a string representing an RFC2822 or ISO 8601 date.'); + } + ngModelCtrl.$setValidity('date', isValid); + } + this.refreshView(); + }; + + this.refreshView = function() { + if ( this.element ) { + this._refreshView(); + + var date = ngModelCtrl.$modelValue ? new Date(ngModelCtrl.$modelValue) : null; + ngModelCtrl.$setValidity('date-disabled', !date || (this.element && !this.isDisabled(date))); + } + }; + + this.createDateObject = function(date, format) { + var model = ngModelCtrl.$modelValue ? new Date(ngModelCtrl.$modelValue) : null; + return { + date: date, + label: dateFilter(date, format), + selected: model && this.compare(date, model) === 0, + disabled: this.isDisabled(date), + current: this.compare(date, new Date()) === 0 + }; + }; + + this.isDisabled = function( date ) { + return ((this.minDate && this.compare(date, this.minDate) < 0) || (this.maxDate && this.compare(date, this.maxDate) > 0) || ($attrs.dateDisabled && $scope.dateDisabled({date: date, mode: $scope.datepickerMode}))); + }; + + // Split array into smaller arrays + this.split = function(arr, size) { + var arrays = []; + while (arr.length > 0) { + arrays.push(arr.splice(0, size)); + } + return arrays; + }; + + $scope.select = function( date ) { + if ( $scope.datepickerMode === self.minMode ) { + var dt = ngModelCtrl.$modelValue ? new Date( ngModelCtrl.$modelValue ) : new Date(0, 0, 0, 0, 0, 0, 0); + dt.setFullYear( date.getFullYear(), date.getMonth(), date.getDate() ); + ngModelCtrl.$setViewValue( dt ); + ngModelCtrl.$render(); + } else { + self.activeDate = date; + $scope.datepickerMode = self.modes[ self.modes.indexOf( $scope.datepickerMode ) - 1 ]; + } + }; + + $scope.move = function( direction ) { + var year = self.activeDate.getFullYear() + direction * (self.step.years || 0), + month = self.activeDate.getMonth() + direction * (self.step.months || 0); + self.activeDate.setFullYear(year, month, 1); + self.refreshView(); + }; + + $scope.toggleMode = function( direction ) { + direction = direction || 1; + + if (($scope.datepickerMode === self.maxMode && direction === 1) || ($scope.datepickerMode === self.minMode && direction === -1)) { + return; + } + + $scope.datepickerMode = self.modes[ self.modes.indexOf( $scope.datepickerMode ) + direction ]; + }; + + // Key event mapper + $scope.keys = { 13:'enter', 32:'space', 33:'pageup', 34:'pagedown', 35:'end', 36:'home', 37:'left', 38:'up', 39:'right', 40:'down' }; + + var focusElement = function() { + $timeout(function() { + self.element[0].focus(); + }, 0 , false); + }; + + // Listen for focus requests from popup directive + $scope.$on('datepicker.focus', focusElement); + + $scope.keydown = function( evt ) { + var key = $scope.keys[evt.which]; + + if ( !key || evt.shiftKey || evt.altKey ) { + return; + } + + evt.preventDefault(); + evt.stopPropagation(); + + if (key === 'enter' || key === 'space') { + if ( self.isDisabled(self.activeDate)) { + return; // do nothing + } + $scope.select(self.activeDate); + focusElement(); + } else if (evt.ctrlKey && (key === 'up' || key === 'down')) { + $scope.toggleMode(key === 'up' ? 1 : -1); + focusElement(); + } else { + self.handleKeyDown(key, evt); + self.refreshView(); + } + }; +}]) + +.directive( 'datepicker', function () { + return { + restrict: 'EA', + replace: true, + templateUrl: 'template/datepicker/datepicker.html', + scope: { + datepickerMode: '=?', + dateDisabled: '&' + }, + require: ['datepicker', '?^ngModel'], + controller: 'DatepickerController', + link: function(scope, element, attrs, ctrls) { + var datepickerCtrl = ctrls[0], ngModelCtrl = ctrls[1]; + + if ( ngModelCtrl ) { + datepickerCtrl.init( ngModelCtrl ); + } + } + }; +}) + +.directive('daypicker', ['dateFilter', function (dateFilter) { + return { + restrict: 'EA', + replace: true, + templateUrl: 'template/datepicker/day.html', + require: '^datepicker', + link: function(scope, element, attrs, ctrl) { + scope.showWeeks = ctrl.showWeeks; + + ctrl.step = { months: 1 }; + ctrl.element = element; + + var DAYS_IN_MONTH = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]; + function getDaysInMonth( year, month ) { + return ((month === 1) && (year % 4 === 0) && ((year % 100 !== 0) || (year % 400 === 0))) ? 29 : DAYS_IN_MONTH[month]; + } + + function getDates(startDate, n) { + var dates = new Array(n), current = new Date(startDate), i = 0; + current.setHours(12); // Prevent repeated dates because of timezone bug + while ( i < n ) { + dates[i++] = new Date(current); + current.setDate( current.getDate() + 1 ); + } + return dates; + } + + ctrl._refreshView = function() { + var year = ctrl.activeDate.getFullYear(), + month = ctrl.activeDate.getMonth(), + firstDayOfMonth = new Date(year, month, 1), + difference = ctrl.startingDay - firstDayOfMonth.getDay(), + numDisplayedFromPreviousMonth = (difference > 0) ? 7 - difference : - difference, + firstDate = new Date(firstDayOfMonth); + + if ( numDisplayedFromPreviousMonth > 0 ) { + firstDate.setDate( - numDisplayedFromPreviousMonth + 1 ); + } + + // 42 is the number of days on a six-month calendar + var days = getDates(firstDate, 42); + for (var i = 0; i < 42; i ++) { + days[i] = angular.extend(ctrl.createDateObject(days[i], ctrl.formatDay), { + secondary: days[i].getMonth() !== month, + uid: scope.uniqueId + '-' + i + }); + } + + scope.labels = new Array(7); + for (var j = 0; j < 7; j++) { + scope.labels[j] = { + abbr: dateFilter(days[j].date, ctrl.formatDayHeader), + full: dateFilter(days[j].date, 'EEEE') + }; + } + + scope.title = dateFilter(ctrl.activeDate, ctrl.formatDayTitle); + scope.rows = ctrl.split(days, 7); + + if ( scope.showWeeks ) { + scope.weekNumbers = []; + var weekNumber = getISO8601WeekNumber( scope.rows[0][0].date ), + numWeeks = scope.rows.length; + while( scope.weekNumbers.push(weekNumber++) < numWeeks ) {} + } + }; + + ctrl.compare = function(date1, date2) { + return (new Date( date1.getFullYear(), date1.getMonth(), date1.getDate() ) - new Date( date2.getFullYear(), date2.getMonth(), date2.getDate() ) ); + }; + + function getISO8601WeekNumber(date) { + var checkDate = new Date(date); + checkDate.setDate(checkDate.getDate() + 4 - (checkDate.getDay() || 7)); // Thursday + var time = checkDate.getTime(); + checkDate.setMonth(0); // Compare with Jan 1 + checkDate.setDate(1); + return Math.floor(Math.round((time - checkDate) / 86400000) / 7) + 1; + } + + ctrl.handleKeyDown = function( key, evt ) { + var date = ctrl.activeDate.getDate(); + + if (key === 'left') { + date = date - 1; // up + } else if (key === 'up') { + date = date - 7; // down + } else if (key === 'right') { + date = date + 1; // down + } else if (key === 'down') { + date = date + 7; + } else if (key === 'pageup' || key === 'pagedown') { + var month = ctrl.activeDate.getMonth() + (key === 'pageup' ? - 1 : 1); + ctrl.activeDate.setMonth(month, 1); + date = Math.min(getDaysInMonth(ctrl.activeDate.getFullYear(), ctrl.activeDate.getMonth()), date); + } else if (key === 'home') { + date = 1; + } else if (key === 'end') { + date = getDaysInMonth(ctrl.activeDate.getFullYear(), ctrl.activeDate.getMonth()); + } + ctrl.activeDate.setDate(date); + }; + + ctrl.refreshView(); + } + }; +}]) + +.directive('monthpicker', ['dateFilter', function (dateFilter) { + return { + restrict: 'EA', + replace: true, + templateUrl: 'template/datepicker/month.html', + require: '^datepicker', + link: function(scope, element, attrs, ctrl) { + ctrl.step = { years: 1 }; + ctrl.element = element; + + ctrl._refreshView = function() { + var months = new Array(12), + year = ctrl.activeDate.getFullYear(); + + for ( var i = 0; i < 12; i++ ) { + months[i] = angular.extend(ctrl.createDateObject(new Date(year, i, 1), ctrl.formatMonth), { + uid: scope.uniqueId + '-' + i + }); + } + + scope.title = dateFilter(ctrl.activeDate, ctrl.formatMonthTitle); + scope.rows = ctrl.split(months, 3); + }; + + ctrl.compare = function(date1, date2) { + return new Date( date1.getFullYear(), date1.getMonth() ) - new Date( date2.getFullYear(), date2.getMonth() ); + }; + + ctrl.handleKeyDown = function( key, evt ) { + var date = ctrl.activeDate.getMonth(); + + if (key === 'left') { + date = date - 1; // up + } else if (key === 'up') { + date = date - 3; // down + } else if (key === 'right') { + date = date + 1; // down + } else if (key === 'down') { + date = date + 3; + } else if (key === 'pageup' || key === 'pagedown') { + var year = ctrl.activeDate.getFullYear() + (key === 'pageup' ? - 1 : 1); + ctrl.activeDate.setFullYear(year); + } else if (key === 'home') { + date = 0; + } else if (key === 'end') { + date = 11; + } + ctrl.activeDate.setMonth(date); + }; + + ctrl.refreshView(); + } + }; +}]) + +.directive('yearpicker', ['dateFilter', function (dateFilter) { + return { + restrict: 'EA', + replace: true, + templateUrl: 'template/datepicker/year.html', + require: '^datepicker', + link: function(scope, element, attrs, ctrl) { + var range = ctrl.yearRange; + + ctrl.step = { years: range }; + ctrl.element = element; + + function getStartingYear( year ) { + return parseInt((year - 1) / range, 10) * range + 1; + } + + ctrl._refreshView = function() { + var years = new Array(range); + + for ( var i = 0, start = getStartingYear(ctrl.activeDate.getFullYear()); i < range; i++ ) { + years[i] = angular.extend(ctrl.createDateObject(new Date(start + i, 0, 1), ctrl.formatYear), { + uid: scope.uniqueId + '-' + i + }); + } + + scope.title = [years[0].label, years[range - 1].label].join(' - '); + scope.rows = ctrl.split(years, 5); + }; + + ctrl.compare = function(date1, date2) { + return date1.getFullYear() - date2.getFullYear(); + }; + + ctrl.handleKeyDown = function( key, evt ) { + var date = ctrl.activeDate.getFullYear(); + + if (key === 'left') { + date = date - 1; // up + } else if (key === 'up') { + date = date - 5; // down + } else if (key === 'right') { + date = date + 1; // down + } else if (key === 'down') { + date = date + 5; + } else if (key === 'pageup' || key === 'pagedown') { + date += (key === 'pageup' ? - 1 : 1) * ctrl.step.years; + } else if (key === 'home') { + date = getStartingYear( ctrl.activeDate.getFullYear() ); + } else if (key === 'end') { + date = getStartingYear( ctrl.activeDate.getFullYear() ) + range - 1; + } + ctrl.activeDate.setFullYear(date); + }; + + ctrl.refreshView(); + } + }; +}]) + +.constant('datepickerPopupConfig', { + datepickerPopup: 'yyyy-MM-dd', + currentText: 'Today', + clearText: 'Clear', + closeText: 'Done', + closeOnDateSelection: true, + appendToBody: false, + showButtonBar: true +}) + +.directive('datepickerPopup', ['$compile', '$parse', '$document', '$position', 'dateFilter', 'dateParser', 'datepickerPopupConfig', +function ($compile, $parse, $document, $position, dateFilter, dateParser, datepickerPopupConfig) { + return { + restrict: 'EA', + require: 'ngModel', + scope: { + isOpen: '=?', + currentText: '@', + clearText: '@', + closeText: '@', + dateDisabled: '&' + }, + link: function(scope, element, attrs, ngModel) { + var dateFormat, + closeOnDateSelection = angular.isDefined(attrs.closeOnDateSelection) ? scope.$parent.$eval(attrs.closeOnDateSelection) : datepickerPopupConfig.closeOnDateSelection, + appendToBody = angular.isDefined(attrs.datepickerAppendToBody) ? scope.$parent.$eval(attrs.datepickerAppendToBody) : datepickerPopupConfig.appendToBody; + + scope.showButtonBar = angular.isDefined(attrs.showButtonBar) ? scope.$parent.$eval(attrs.showButtonBar) : datepickerPopupConfig.showButtonBar; + + scope.getText = function( key ) { + return scope[key + 'Text'] || datepickerPopupConfig[key + 'Text']; + }; + + attrs.$observe('datepickerPopup', function(value) { + dateFormat = value || datepickerPopupConfig.datepickerPopup; + ngModel.$render(); + }); + + // popup element used to display calendar + var popupEl = angular.element('
    '); + popupEl.attr({ + 'ng-model': 'date', + 'ng-change': 'dateSelection()' + }); + + function cameltoDash( string ){ + return string.replace(/([A-Z])/g, function($1) { return '-' + $1.toLowerCase(); }); + } + + // datepicker element + var datepickerEl = angular.element(popupEl.children()[0]); + if ( attrs.datepickerOptions ) { + angular.forEach(scope.$parent.$eval(attrs.datepickerOptions), function( value, option ) { + datepickerEl.attr( cameltoDash(option), value ); + }); + } + + scope.watchData = {}; + angular.forEach(['minDate', 'maxDate', 'datepickerMode'], function( key ) { + if ( attrs[key] ) { + var getAttribute = $parse(attrs[key]); + scope.$parent.$watch(getAttribute, function(value){ + scope.watchData[key] = value; + }); + datepickerEl.attr(cameltoDash(key), 'watchData.' + key); + + // Propagate changes from datepicker to outside + if ( key === 'datepickerMode' ) { + var setAttribute = getAttribute.assign; + scope.$watch('watchData.' + key, function(value, oldvalue) { + if ( value !== oldvalue ) { + setAttribute(scope.$parent, value); + } + }); + } + } + }); + if (attrs.dateDisabled) { + datepickerEl.attr('date-disabled', 'dateDisabled({ date: date, mode: mode })'); + } + + function parseDate(viewValue) { + if (!viewValue) { + ngModel.$setValidity('date', true); + return null; + } else if (angular.isDate(viewValue) && !isNaN(viewValue)) { + ngModel.$setValidity('date', true); + return viewValue; + } else if (angular.isString(viewValue)) { + var date = dateParser.parse(viewValue, dateFormat) || new Date(viewValue); + if (isNaN(date)) { + ngModel.$setValidity('date', false); + return undefined; + } else { + ngModel.$setValidity('date', true); + return date; + } + } else { + ngModel.$setValidity('date', false); + return undefined; + } + } + ngModel.$parsers.unshift(parseDate); + + // Inner change + scope.dateSelection = function(dt) { + if (angular.isDefined(dt)) { + scope.date = dt; + } + ngModel.$setViewValue(scope.date); + ngModel.$render(); + + if ( closeOnDateSelection ) { + scope.isOpen = false; + element[0].focus(); + } + }; + + element.bind('input change keyup', function() { + scope.$apply(function() { + scope.date = ngModel.$modelValue; + }); + }); + + // Outter change + ngModel.$render = function() { + var date = ngModel.$viewValue ? dateFilter(ngModel.$viewValue, dateFormat) : ''; + element.val(date); + scope.date = parseDate( ngModel.$modelValue ); + }; + + var documentClickBind = function(event) { + if (scope.isOpen && event.target !== element[0]) { + scope.$apply(function() { + scope.isOpen = false; + }); + } + }; + + var keydown = function(evt, noApply) { + scope.keydown(evt); + }; + element.bind('keydown', keydown); + + scope.keydown = function(evt) { + if (evt.which === 27) { + evt.preventDefault(); + evt.stopPropagation(); + scope.close(); + } else if (evt.which === 40 && !scope.isOpen) { + scope.isOpen = true; + } + }; + + scope.$watch('isOpen', function(value) { + if (value) { + scope.$broadcast('datepicker.focus'); + scope.position = appendToBody ? $position.offset(element) : $position.position(element); + scope.position.top = scope.position.top + element.prop('offsetHeight'); + + $document.bind('click', documentClickBind); + } else { + $document.unbind('click', documentClickBind); + } + }); + + scope.select = function( date ) { + if (date === 'today') { + var today = new Date(); + if (angular.isDate(ngModel.$modelValue)) { + date = new Date(ngModel.$modelValue); + date.setFullYear(today.getFullYear(), today.getMonth(), today.getDate()); + } else { + date = new Date(today.setHours(0, 0, 0, 0)); + } + } + scope.dateSelection( date ); + }; + + scope.close = function() { + scope.isOpen = false; + element[0].focus(); + }; + + var $popup = $compile(popupEl)(scope); + // Prevent jQuery cache memory leak (template is now redundant after linking) + popupEl.remove(); + + if ( appendToBody ) { + $document.find('body').append($popup); + } else { + element.after($popup); + } + + scope.$on('$destroy', function() { + $popup.remove(); + element.unbind('keydown', keydown); + $document.unbind('click', documentClickBind); + }); + } + }; +}]) + +.directive('datepickerPopupWrap', function() { + return { + restrict:'EA', + replace: true, + transclude: true, + templateUrl: 'template/datepicker/popup.html', + link:function (scope, element, attrs) { + element.bind('click', function(event) { + event.preventDefault(); + event.stopPropagation(); + }); + } + }; +}); + +angular.module('ui.bootstrap.dropdown', []) + +.constant('dropdownConfig', { + openClass: 'open' +}) + +.service('dropdownService', ['$document', function($document) { + var openScope = null; + + this.open = function( dropdownScope ) { + if ( !openScope ) { + $document.bind('click', closeDropdown); + $document.bind('keydown', escapeKeyBind); + } + + if ( openScope && openScope !== dropdownScope ) { + openScope.isOpen = false; + } + + openScope = dropdownScope; + }; + + this.close = function( dropdownScope ) { + if ( openScope === dropdownScope ) { + openScope = null; + $document.unbind('click', closeDropdown); + $document.unbind('keydown', escapeKeyBind); + } + }; + + var closeDropdown = function( evt ) { + // This method may still be called during the same mouse event that + // unbound this event handler. So check openScope before proceeding. + if (!openScope) { return; } + + var toggleElement = openScope.getToggleElement(); + if ( evt && toggleElement && toggleElement[0].contains(evt.target) ) { + return; + } + + openScope.$apply(function() { + openScope.isOpen = false; + }); + }; + + var escapeKeyBind = function( evt ) { + if ( evt.which === 27 ) { + openScope.focusToggleElement(); + closeDropdown(); + } + }; +}]) + +.controller('DropdownController', ['$scope', '$attrs', '$parse', 'dropdownConfig', 'dropdownService', '$animate', function($scope, $attrs, $parse, dropdownConfig, dropdownService, $animate) { + var self = this, + scope = $scope.$new(), // create a child scope so we are not polluting original one + openClass = dropdownConfig.openClass, + getIsOpen, + setIsOpen = angular.noop, + toggleInvoker = $attrs.onToggle ? $parse($attrs.onToggle) : angular.noop; + + this.init = function( element ) { + self.$element = element; + + if ( $attrs.isOpen ) { + getIsOpen = $parse($attrs.isOpen); + setIsOpen = getIsOpen.assign; + + $scope.$watch(getIsOpen, function(value) { + scope.isOpen = !!value; + }); + } + }; + + this.toggle = function( open ) { + return scope.isOpen = arguments.length ? !!open : !scope.isOpen; + }; + + // Allow other directives to watch status + this.isOpen = function() { + return scope.isOpen; + }; + + scope.getToggleElement = function() { + return self.toggleElement; + }; + + scope.focusToggleElement = function() { + if ( self.toggleElement ) { + self.toggleElement[0].focus(); + } + }; + + scope.$watch('isOpen', function( isOpen, wasOpen ) { + $animate[isOpen ? 'addClass' : 'removeClass'](self.$element, openClass); + + if ( isOpen ) { + scope.focusToggleElement(); + dropdownService.open( scope ); + } else { + dropdownService.close( scope ); + } + + setIsOpen($scope, isOpen); + if (angular.isDefined(isOpen) && isOpen !== wasOpen) { + toggleInvoker($scope, { open: !!isOpen }); + } + }); + + $scope.$on('$locationChangeSuccess', function() { + scope.isOpen = false; + }); + + $scope.$on('$destroy', function() { + scope.$destroy(); + }); +}]) + +.directive('dropdown', function() { + return { + controller: 'DropdownController', + link: function(scope, element, attrs, dropdownCtrl) { + dropdownCtrl.init( element ); + } + }; +}) + +.directive('dropdownToggle', function() { + return { + require: '?^dropdown', + link: function(scope, element, attrs, dropdownCtrl) { + if ( !dropdownCtrl ) { + return; + } + + dropdownCtrl.toggleElement = element; + + var toggleDropdown = function(event) { + event.preventDefault(); + + if ( !element.hasClass('disabled') && !attrs.disabled ) { + scope.$apply(function() { + dropdownCtrl.toggle(); + }); + } + }; + + element.bind('click', toggleDropdown); + + // WAI-ARIA + element.attr({ 'aria-haspopup': true, 'aria-expanded': false }); + scope.$watch(dropdownCtrl.isOpen, function( isOpen ) { + element.attr('aria-expanded', !!isOpen); + }); + + scope.$on('$destroy', function() { + element.unbind('click', toggleDropdown); + }); + } + }; +}); + +angular.module('ui.bootstrap.modal', ['ui.bootstrap.transition']) + +/** + * A helper, internal data structure that acts as a map but also allows getting / removing + * elements in the LIFO order + */ + .factory('$$stackedMap', function () { + return { + createNew: function () { + var stack = []; + + return { + add: function (key, value) { + stack.push({ + key: key, + value: value + }); + }, + get: function (key) { + for (var i = 0; i < stack.length; i++) { + if (key == stack[i].key) { + return stack[i]; + } + } + }, + keys: function() { + var keys = []; + for (var i = 0; i < stack.length; i++) { + keys.push(stack[i].key); + } + return keys; + }, + top: function () { + return stack[stack.length - 1]; + }, + remove: function (key) { + var idx = -1; + for (var i = 0; i < stack.length; i++) { + if (key == stack[i].key) { + idx = i; + break; + } + } + return stack.splice(idx, 1)[0]; + }, + removeTop: function () { + return stack.splice(stack.length - 1, 1)[0]; + }, + length: function () { + return stack.length; + } + }; + } + }; + }) + +/** + * A helper directive for the $modal service. It creates a backdrop element. + */ + .directive('modalBackdrop', ['$timeout', function ($timeout) { + return { + restrict: 'EA', + replace: true, + templateUrl: 'template/modal/backdrop.html', + link: function (scope, element, attrs) { + scope.backdropClass = attrs.backdropClass || ''; + + scope.animate = false; + + //trigger CSS transitions + $timeout(function () { + scope.animate = true; + }); + } + }; + }]) + + .directive('modalWindow', ['$modalStack', '$timeout', function ($modalStack, $timeout) { + return { + restrict: 'EA', + scope: { + index: '@', + animate: '=' + }, + replace: true, + transclude: true, + templateUrl: function(tElement, tAttrs) { + return tAttrs.templateUrl || 'template/modal/window.html'; + }, + link: function (scope, element, attrs) { + element.addClass(attrs.windowClass || ''); + scope.size = attrs.size; + + $timeout(function () { + // trigger CSS transitions + scope.animate = true; + + /** + * Auto-focusing of a freshly-opened modal element causes any child elements + * with the autofocus attribute to lose focus. This is an issue on touch + * based devices which will show and then hide the onscreen keyboard. + * Attempts to refocus the autofocus element via JavaScript will not reopen + * the onscreen keyboard. Fixed by updated the focusing logic to only autofocus + * the modal element if the modal does not contain an autofocus element. + */ + if (!element[0].querySelectorAll('[autofocus]').length) { + element[0].focus(); + } + }); + + scope.close = function (evt) { + var modal = $modalStack.getTop(); + if (modal && modal.value.backdrop && modal.value.backdrop != 'static' && (evt.target === evt.currentTarget)) { + evt.preventDefault(); + evt.stopPropagation(); + $modalStack.dismiss(modal.key, 'backdrop click'); + } + }; + } + }; + }]) + + .directive('modalTransclude', function () { + return { + link: function($scope, $element, $attrs, controller, $transclude) { + $transclude($scope.$parent, function(clone) { + $element.empty(); + $element.append(clone); + }); + } + }; + }) + + .factory('$modalStack', ['$transition', '$timeout', '$document', '$compile', '$rootScope', '$$stackedMap', + function ($transition, $timeout, $document, $compile, $rootScope, $$stackedMap) { + + var OPENED_MODAL_CLASS = 'modal-open'; + + var backdropDomEl, backdropScope; + var openedWindows = $$stackedMap.createNew(); + var $modalStack = {}; + + function backdropIndex() { + var topBackdropIndex = -1; + var opened = openedWindows.keys(); + for (var i = 0; i < opened.length; i++) { + if (openedWindows.get(opened[i]).value.backdrop) { + topBackdropIndex = i; + } + } + return topBackdropIndex; + } + + $rootScope.$watch(backdropIndex, function(newBackdropIndex){ + if (backdropScope) { + backdropScope.index = newBackdropIndex; + } + }); + + function removeModalWindow(modalInstance) { + + var body = $document.find('body').eq(0); + var modalWindow = openedWindows.get(modalInstance).value; + + //clean up the stack + openedWindows.remove(modalInstance); + + //remove window DOM element + removeAfterAnimate(modalWindow.modalDomEl, modalWindow.modalScope, 300, function() { + modalWindow.modalScope.$destroy(); + body.toggleClass(OPENED_MODAL_CLASS, openedWindows.length() > 0); + checkRemoveBackdrop(); + }); + } + + function checkRemoveBackdrop() { + //remove backdrop if no longer needed + if (backdropDomEl && backdropIndex() == -1) { + var backdropScopeRef = backdropScope; + removeAfterAnimate(backdropDomEl, backdropScope, 150, function () { + backdropScopeRef.$destroy(); + backdropScopeRef = null; + }); + backdropDomEl = undefined; + backdropScope = undefined; + } + } + + function removeAfterAnimate(domEl, scope, emulateTime, done) { + // Closing animation + scope.animate = false; + + var transitionEndEventName = $transition.transitionEndEventName; + if (transitionEndEventName) { + // transition out + var timeout = $timeout(afterAnimating, emulateTime); + + domEl.bind(transitionEndEventName, function () { + $timeout.cancel(timeout); + afterAnimating(); + scope.$apply(); + }); + } else { + // Ensure this call is async + $timeout(afterAnimating); + } + + function afterAnimating() { + if (afterAnimating.done) { + return; + } + afterAnimating.done = true; + + domEl.remove(); + if (done) { + done(); + } + } + } + + $document.bind('keydown', function (evt) { + var modal; + + if (evt.which === 27) { + modal = openedWindows.top(); + if (modal && modal.value.keyboard) { + evt.preventDefault(); + $rootScope.$apply(function () { + $modalStack.dismiss(modal.key, 'escape key press'); + }); + } + } + }); + + $modalStack.open = function (modalInstance, modal) { + + openedWindows.add(modalInstance, { + deferred: modal.deferred, + modalScope: modal.scope, + backdrop: modal.backdrop, + keyboard: modal.keyboard + }); + + var body = $document.find('body').eq(0), + currBackdropIndex = backdropIndex(); + + if (currBackdropIndex >= 0 && !backdropDomEl) { + backdropScope = $rootScope.$new(true); + backdropScope.index = currBackdropIndex; + var angularBackgroundDomEl = angular.element('
    '); + angularBackgroundDomEl.attr('backdrop-class', modal.backdropClass); + backdropDomEl = $compile(angularBackgroundDomEl)(backdropScope); + body.append(backdropDomEl); + } + + var angularDomEl = angular.element('
    '); + angularDomEl.attr({ + 'template-url': modal.windowTemplateUrl, + 'window-class': modal.windowClass, + 'size': modal.size, + 'index': openedWindows.length() - 1, + 'animate': 'animate' + }).html(modal.content); + + var modalDomEl = $compile(angularDomEl)(modal.scope); + openedWindows.top().value.modalDomEl = modalDomEl; + body.append(modalDomEl); + body.addClass(OPENED_MODAL_CLASS); + }; + + $modalStack.close = function (modalInstance, result) { + var modalWindow = openedWindows.get(modalInstance); + if (modalWindow) { + modalWindow.value.deferred.resolve(result); + removeModalWindow(modalInstance); + } + }; + + $modalStack.dismiss = function (modalInstance, reason) { + var modalWindow = openedWindows.get(modalInstance); + if (modalWindow) { + modalWindow.value.deferred.reject(reason); + removeModalWindow(modalInstance); + } + }; + + $modalStack.dismissAll = function (reason) { + var topModal = this.getTop(); + while (topModal) { + this.dismiss(topModal.key, reason); + topModal = this.getTop(); + } + }; + + $modalStack.getTop = function () { + return openedWindows.top(); + }; + + return $modalStack; + }]) + + .provider('$modal', function () { + + var $modalProvider = { + options: { + backdrop: true, //can be also false or 'static' + keyboard: true + }, + $get: ['$injector', '$rootScope', '$q', '$http', '$templateCache', '$controller', '$modalStack', + function ($injector, $rootScope, $q, $http, $templateCache, $controller, $modalStack) { + + var $modal = {}; + + function getTemplatePromise(options) { + return options.template ? $q.when(options.template) : + $http.get(angular.isFunction(options.templateUrl) ? (options.templateUrl)() : options.templateUrl, + {cache: $templateCache}).then(function (result) { + return result.data; + }); + } + + function getResolvePromises(resolves) { + var promisesArr = []; + angular.forEach(resolves, function (value) { + if (angular.isFunction(value) || angular.isArray(value)) { + promisesArr.push($q.when($injector.invoke(value))); + } + }); + return promisesArr; + } + + $modal.open = function (modalOptions) { + + var modalResultDeferred = $q.defer(); + var modalOpenedDeferred = $q.defer(); + + //prepare an instance of a modal to be injected into controllers and returned to a caller + var modalInstance = { + result: modalResultDeferred.promise, + opened: modalOpenedDeferred.promise, + close: function (result) { + $modalStack.close(modalInstance, result); + }, + dismiss: function (reason) { + $modalStack.dismiss(modalInstance, reason); + } + }; + + //merge and clean up options + modalOptions = angular.extend({}, $modalProvider.options, modalOptions); + modalOptions.resolve = modalOptions.resolve || {}; + + //verify options + if (!modalOptions.template && !modalOptions.templateUrl) { + throw new Error('One of template or templateUrl options is required.'); + } + + var templateAndResolvePromise = + $q.all([getTemplatePromise(modalOptions)].concat(getResolvePromises(modalOptions.resolve))); + + + templateAndResolvePromise.then(function resolveSuccess(tplAndVars) { + + var modalScope = (modalOptions.scope || $rootScope).$new(); + modalScope.$close = modalInstance.close; + modalScope.$dismiss = modalInstance.dismiss; + + var ctrlInstance, ctrlLocals = {}; + var resolveIter = 1; + + //controllers + if (modalOptions.controller) { + ctrlLocals.$scope = modalScope; + ctrlLocals.$modalInstance = modalInstance; + angular.forEach(modalOptions.resolve, function (value, key) { + ctrlLocals[key] = tplAndVars[resolveIter++]; + }); + + ctrlInstance = $controller(modalOptions.controller, ctrlLocals); + if (modalOptions.controllerAs) { + modalScope[modalOptions.controllerAs] = ctrlInstance; + } + } + + $modalStack.open(modalInstance, { + scope: modalScope, + deferred: modalResultDeferred, + content: tplAndVars[0], + backdrop: modalOptions.backdrop, + keyboard: modalOptions.keyboard, + backdropClass: modalOptions.backdropClass, + windowClass: modalOptions.windowClass, + windowTemplateUrl: modalOptions.windowTemplateUrl, + size: modalOptions.size + }); + + }, function resolveError(reason) { + modalResultDeferred.reject(reason); + }); + + templateAndResolvePromise.then(function () { + modalOpenedDeferred.resolve(true); + }, function () { + modalOpenedDeferred.reject(false); + }); + + return modalInstance; + }; + + return $modal; + }] + }; + + return $modalProvider; + }); + +angular.module('ui.bootstrap.pagination', []) + +.controller('PaginationController', ['$scope', '$attrs', '$parse', function ($scope, $attrs, $parse) { + var self = this, + ngModelCtrl = { $setViewValue: angular.noop }, // nullModelCtrl + setNumPages = $attrs.numPages ? $parse($attrs.numPages).assign : angular.noop; + + this.init = function(ngModelCtrl_, config) { + ngModelCtrl = ngModelCtrl_; + this.config = config; + + ngModelCtrl.$render = function() { + self.render(); + }; + + if ($attrs.itemsPerPage) { + $scope.$parent.$watch($parse($attrs.itemsPerPage), function(value) { + self.itemsPerPage = parseInt(value, 10); + $scope.totalPages = self.calculateTotalPages(); + }); + } else { + this.itemsPerPage = config.itemsPerPage; + } + }; + + this.calculateTotalPages = function() { + var totalPages = this.itemsPerPage < 1 ? 1 : Math.ceil($scope.totalItems / this.itemsPerPage); + return Math.max(totalPages || 0, 1); + }; + + this.render = function() { + $scope.page = parseInt(ngModelCtrl.$viewValue, 10) || 1; + }; + + $scope.selectPage = function(page) { + if ( $scope.page !== page && page > 0 && page <= $scope.totalPages) { + ngModelCtrl.$setViewValue(page); + ngModelCtrl.$render(); + } + }; + + $scope.getText = function( key ) { + return $scope[key + 'Text'] || self.config[key + 'Text']; + }; + $scope.noPrevious = function() { + return $scope.page === 1; + }; + $scope.noNext = function() { + return $scope.page === $scope.totalPages; + }; + + $scope.$watch('totalItems', function() { + $scope.totalPages = self.calculateTotalPages(); + }); + + $scope.$watch('totalPages', function(value) { + setNumPages($scope.$parent, value); // Readonly variable + + if ( $scope.page > value ) { + $scope.selectPage(value); + } else { + ngModelCtrl.$render(); + } + }); +}]) + +.constant('paginationConfig', { + itemsPerPage: 10, + boundaryLinks: false, + directionLinks: true, + firstText: 'First', + previousText: 'Previous', + nextText: 'Next', + lastText: 'Last', + rotate: true +}) + +.directive('pagination', ['$parse', 'paginationConfig', function($parse, paginationConfig) { + return { + restrict: 'EA', + scope: { + totalItems: '=', + firstText: '@', + previousText: '@', + nextText: '@', + lastText: '@' + }, + require: ['pagination', '?ngModel'], + controller: 'PaginationController', + templateUrl: 'template/pagination/pagination.html', + replace: true, + link: function(scope, element, attrs, ctrls) { + var paginationCtrl = ctrls[0], ngModelCtrl = ctrls[1]; + + if (!ngModelCtrl) { + return; // do nothing if no ng-model + } + + // Setup configuration parameters + var maxSize = angular.isDefined(attrs.maxSize) ? scope.$parent.$eval(attrs.maxSize) : paginationConfig.maxSize, + rotate = angular.isDefined(attrs.rotate) ? scope.$parent.$eval(attrs.rotate) : paginationConfig.rotate; + scope.boundaryLinks = angular.isDefined(attrs.boundaryLinks) ? scope.$parent.$eval(attrs.boundaryLinks) : paginationConfig.boundaryLinks; + scope.directionLinks = angular.isDefined(attrs.directionLinks) ? scope.$parent.$eval(attrs.directionLinks) : paginationConfig.directionLinks; + + paginationCtrl.init(ngModelCtrl, paginationConfig); + + if (attrs.maxSize) { + scope.$parent.$watch($parse(attrs.maxSize), function(value) { + maxSize = parseInt(value, 10); + paginationCtrl.render(); + }); + } + + // Create page object used in template + function makePage(number, text, isActive) { + return { + number: number, + text: text, + active: isActive + }; + } + + function getPages(currentPage, totalPages) { + var pages = []; + + // Default page limits + var startPage = 1, endPage = totalPages; + var isMaxSized = ( angular.isDefined(maxSize) && maxSize < totalPages ); + + // recompute if maxSize + if ( isMaxSized ) { + if ( rotate ) { + // Current page is displayed in the middle of the visible ones + startPage = Math.max(currentPage - Math.floor(maxSize/2), 1); + endPage = startPage + maxSize - 1; + + // Adjust if limit is exceeded + if (endPage > totalPages) { + endPage = totalPages; + startPage = endPage - maxSize + 1; + } + } else { + // Visible pages are paginated with maxSize + startPage = ((Math.ceil(currentPage / maxSize) - 1) * maxSize) + 1; + + // Adjust last page if limit is exceeded + endPage = Math.min(startPage + maxSize - 1, totalPages); + } + } + + // Add page number links + for (var number = startPage; number <= endPage; number++) { + var page = makePage(number, number, number === currentPage); + pages.push(page); + } + + // Add links to move between page sets + if ( isMaxSized && ! rotate ) { + if ( startPage > 1 ) { + var previousPageSet = makePage(startPage - 1, '...', false); + pages.unshift(previousPageSet); + } + + if ( endPage < totalPages ) { + var nextPageSet = makePage(endPage + 1, '...', false); + pages.push(nextPageSet); + } + } + + return pages; + } + + var originalRender = paginationCtrl.render; + paginationCtrl.render = function() { + originalRender(); + if (scope.page > 0 && scope.page <= scope.totalPages) { + scope.pages = getPages(scope.page, scope.totalPages); + } + }; + } + }; +}]) + +.constant('pagerConfig', { + itemsPerPage: 10, + previousText: '« Previous', + nextText: 'Next »', + align: true +}) + +.directive('pager', ['pagerConfig', function(pagerConfig) { + return { + restrict: 'EA', + scope: { + totalItems: '=', + previousText: '@', + nextText: '@' + }, + require: ['pager', '?ngModel'], + controller: 'PaginationController', + templateUrl: 'template/pagination/pager.html', + replace: true, + link: function(scope, element, attrs, ctrls) { + var paginationCtrl = ctrls[0], ngModelCtrl = ctrls[1]; + + if (!ngModelCtrl) { + return; // do nothing if no ng-model + } + + scope.align = angular.isDefined(attrs.align) ? scope.$parent.$eval(attrs.align) : pagerConfig.align; + paginationCtrl.init(ngModelCtrl, pagerConfig); + } + }; +}]); + +/** + * The following features are still outstanding: animation as a + * function, placement as a function, inside, support for more triggers than + * just mouse enter/leave, html tooltips, and selector delegation. + */ +angular.module( 'ui.bootstrap.tooltip', [ 'ui.bootstrap.position', 'ui.bootstrap.bindHtml' ] ) + +/** + * The $tooltip service creates tooltip- and popover-like directives as well as + * houses global options for them. + */ +.provider( '$tooltip', function () { + // The default options tooltip and popover. + var defaultOptions = { + placement: 'top', + animation: true, + popupDelay: 0 + }; + + // Default hide triggers for each show trigger + var triggerMap = { + 'mouseenter': 'mouseleave', + 'click': 'click', + 'focus': 'blur' + }; + + // The options specified to the provider globally. + var globalOptions = {}; + + /** + * `options({})` allows global configuration of all tooltips in the + * application. + * + * var app = angular.module( 'App', ['ui.bootstrap.tooltip'], function( $tooltipProvider ) { + * // place tooltips left instead of top by default + * $tooltipProvider.options( { placement: 'left' } ); + * }); + */ + this.options = function( value ) { + angular.extend( globalOptions, value ); + }; + + /** + * This allows you to extend the set of trigger mappings available. E.g.: + * + * $tooltipProvider.setTriggers( 'openTrigger': 'closeTrigger' ); + */ + this.setTriggers = function setTriggers ( triggers ) { + angular.extend( triggerMap, triggers ); + }; + + /** + * This is a helper function for translating camel-case to snake-case. + */ + function snake_case(name){ + var regexp = /[A-Z]/g; + var separator = '-'; + return name.replace(regexp, function(letter, pos) { + return (pos ? separator : '') + letter.toLowerCase(); + }); + } + + /** + * Returns the actual instance of the $tooltip service. + * TODO support multiple triggers + */ + this.$get = [ '$window', '$compile', '$timeout', '$document', '$position', '$interpolate', function ( $window, $compile, $timeout, $document, $position, $interpolate ) { + return function $tooltip ( type, prefix, defaultTriggerShow ) { + var options = angular.extend( {}, defaultOptions, globalOptions ); + + /** + * Returns an object of show and hide triggers. + * + * If a trigger is supplied, + * it is used to show the tooltip; otherwise, it will use the `trigger` + * option passed to the `$tooltipProvider.options` method; else it will + * default to the trigger supplied to this directive factory. + * + * The hide trigger is based on the show trigger. If the `trigger` option + * was passed to the `$tooltipProvider.options` method, it will use the + * mapped trigger from `triggerMap` or the passed trigger if the map is + * undefined; otherwise, it uses the `triggerMap` value of the show + * trigger; else it will just use the show trigger. + */ + function getTriggers ( trigger ) { + var show = trigger || options.trigger || defaultTriggerShow; + var hide = triggerMap[show] || show; + return { + show: show, + hide: hide + }; + } + + var directiveName = snake_case( type ); + + var startSym = $interpolate.startSymbol(); + var endSym = $interpolate.endSymbol(); + var template = + '
    '+ + '
    '; + + return { + restrict: 'EA', + compile: function (tElem, tAttrs) { + var tooltipLinker = $compile( template ); + + return function link ( scope, element, attrs ) { + var tooltip; + var tooltipLinkedScope; + var transitionTimeout; + var popupTimeout; + var appendToBody = angular.isDefined( options.appendToBody ) ? options.appendToBody : false; + var triggers = getTriggers( undefined ); + var hasEnableExp = angular.isDefined(attrs[prefix+'Enable']); + var ttScope = scope.$new(true); + + var positionTooltip = function () { + + var ttPosition = $position.positionElements(element, tooltip, ttScope.placement, appendToBody); + ttPosition.top += 'px'; + ttPosition.left += 'px'; + + // Now set the calculated positioning. + tooltip.css( ttPosition ); + }; + + // By default, the tooltip is not open. + // TODO add ability to start tooltip opened + ttScope.isOpen = false; + + function toggleTooltipBind () { + if ( ! ttScope.isOpen ) { + showTooltipBind(); + } else { + hideTooltipBind(); + } + } + + // Show the tooltip with delay if specified, otherwise show it immediately + function showTooltipBind() { + if(hasEnableExp && !scope.$eval(attrs[prefix+'Enable'])) { + return; + } + + prepareTooltip(); + + if ( ttScope.popupDelay ) { + // Do nothing if the tooltip was already scheduled to pop-up. + // This happens if show is triggered multiple times before any hide is triggered. + if (!popupTimeout) { + popupTimeout = $timeout( show, ttScope.popupDelay, false ); + popupTimeout.then(function(reposition){reposition();}); + } + } else { + show()(); + } + } + + function hideTooltipBind () { + scope.$apply(function () { + hide(); + }); + } + + // Show the tooltip popup element. + function show() { + + popupTimeout = null; + + // If there is a pending remove transition, we must cancel it, lest the + // tooltip be mysteriously removed. + if ( transitionTimeout ) { + $timeout.cancel( transitionTimeout ); + transitionTimeout = null; + } + + // Don't show empty tooltips. + if ( ! ttScope.content ) { + return angular.noop; + } + + createTooltip(); + + // Set the initial positioning. + tooltip.css({ top: 0, left: 0, display: 'block' }); + + // Now we add it to the DOM because need some info about it. But it's not + // visible yet anyway. + if ( appendToBody ) { + $document.find( 'body' ).append( tooltip ); + } else { + element.after( tooltip ); + } + + positionTooltip(); + + // And show the tooltip. + ttScope.isOpen = true; + ttScope.$digest(); // digest required as $apply is not called + + // Return positioning function as promise callback for correct + // positioning after draw. + return positionTooltip; + } + + // Hide the tooltip popup element. + function hide() { + // First things first: we don't show it anymore. + ttScope.isOpen = false; + + //if tooltip is going to be shown after delay, we must cancel this + $timeout.cancel( popupTimeout ); + popupTimeout = null; + + // And now we remove it from the DOM. However, if we have animation, we + // need to wait for it to expire beforehand. + // FIXME: this is a placeholder for a port of the transitions library. + if ( ttScope.animation ) { + if (!transitionTimeout) { + transitionTimeout = $timeout(removeTooltip, 500); + } + } else { + removeTooltip(); + } + } + + function createTooltip() { + // There can only be one tooltip element per directive shown at once. + if (tooltip) { + removeTooltip(); + } + tooltipLinkedScope = ttScope.$new(); + tooltip = tooltipLinker(tooltipLinkedScope, angular.noop); + } + + function removeTooltip() { + transitionTimeout = null; + if (tooltip) { + tooltip.remove(); + tooltip = null; + } + if (tooltipLinkedScope) { + tooltipLinkedScope.$destroy(); + tooltipLinkedScope = null; + } + } + + function prepareTooltip() { + prepPlacement(); + prepPopupDelay(); + } + + /** + * Observe the relevant attributes. + */ + attrs.$observe( type, function ( val ) { + ttScope.content = val; + + if (!val && ttScope.isOpen ) { + hide(); + } + }); + + attrs.$observe( prefix+'Title', function ( val ) { + ttScope.title = val; + }); + + function prepPlacement() { + var val = attrs[ prefix + 'Placement' ]; + ttScope.placement = angular.isDefined( val ) ? val : options.placement; + } + + function prepPopupDelay() { + var val = attrs[ prefix + 'PopupDelay' ]; + var delay = parseInt( val, 10 ); + ttScope.popupDelay = ! isNaN(delay) ? delay : options.popupDelay; + } + + var unregisterTriggers = function () { + element.unbind(triggers.show, showTooltipBind); + element.unbind(triggers.hide, hideTooltipBind); + }; + + function prepTriggers() { + var val = attrs[ prefix + 'Trigger' ]; + unregisterTriggers(); + + triggers = getTriggers( val ); + + if ( triggers.show === triggers.hide ) { + element.bind( triggers.show, toggleTooltipBind ); + } else { + element.bind( triggers.show, showTooltipBind ); + element.bind( triggers.hide, hideTooltipBind ); + } + } + prepTriggers(); + + var animation = scope.$eval(attrs[prefix + 'Animation']); + ttScope.animation = angular.isDefined(animation) ? !!animation : options.animation; + + var appendToBodyVal = scope.$eval(attrs[prefix + 'AppendToBody']); + appendToBody = angular.isDefined(appendToBodyVal) ? appendToBodyVal : appendToBody; + + // if a tooltip is attached to we need to remove it on + // location change as its parent scope will probably not be destroyed + // by the change. + if ( appendToBody ) { + scope.$on('$locationChangeSuccess', function closeTooltipOnLocationChangeSuccess () { + if ( ttScope.isOpen ) { + hide(); + } + }); + } + + // Make sure tooltip is destroyed and removed. + scope.$on('$destroy', function onDestroyTooltip() { + $timeout.cancel( transitionTimeout ); + $timeout.cancel( popupTimeout ); + unregisterTriggers(); + removeTooltip(); + ttScope = null; + }); + }; + } + }; + }; + }]; +}) + +.directive( 'tooltipPopup', function () { + return { + restrict: 'EA', + replace: true, + scope: { content: '@', placement: '@', animation: '&', isOpen: '&' }, + templateUrl: 'template/tooltip/tooltip-popup.html' + }; +}) + +.directive( 'tooltip', [ '$tooltip', function ( $tooltip ) { + return $tooltip( 'tooltip', 'tooltip', 'mouseenter' ); +}]) + +.directive( 'tooltipHtmlUnsafePopup', function () { + return { + restrict: 'EA', + replace: true, + scope: { content: '@', placement: '@', animation: '&', isOpen: '&' }, + templateUrl: 'template/tooltip/tooltip-html-unsafe-popup.html' + }; +}) + +.directive( 'tooltipHtmlUnsafe', [ '$tooltip', function ( $tooltip ) { + return $tooltip( 'tooltipHtmlUnsafe', 'tooltip', 'mouseenter' ); +}]); + +/** + * The following features are still outstanding: popup delay, animation as a + * function, placement as a function, inside, support for more triggers than + * just mouse enter/leave, html popovers, and selector delegatation. + */ +angular.module( 'ui.bootstrap.popover', [ 'ui.bootstrap.tooltip' ] ) + +.directive( 'popoverPopup', function () { + return { + restrict: 'EA', + replace: true, + scope: { title: '@', content: '@', placement: '@', animation: '&', isOpen: '&' }, + templateUrl: 'template/popover/popover.html' + }; +}) + +.directive( 'popover', [ '$tooltip', function ( $tooltip ) { + return $tooltip( 'popover', 'popover', 'click' ); +}]); + +angular.module('ui.bootstrap.progressbar', []) + +.constant('progressConfig', { + animate: true, + max: 100 +}) + +.controller('ProgressController', ['$scope', '$attrs', 'progressConfig', function($scope, $attrs, progressConfig) { + var self = this, + animate = angular.isDefined($attrs.animate) ? $scope.$parent.$eval($attrs.animate) : progressConfig.animate; + + this.bars = []; + $scope.max = angular.isDefined($attrs.max) ? $scope.$parent.$eval($attrs.max) : progressConfig.max; + + this.addBar = function(bar, element) { + if ( !animate ) { + element.css({'transition': 'none'}); + } + + this.bars.push(bar); + + bar.$watch('value', function( value ) { + bar.percent = +(100 * value / $scope.max).toFixed(2); + }); + + bar.$on('$destroy', function() { + element = null; + self.removeBar(bar); + }); + }; + + this.removeBar = function(bar) { + this.bars.splice(this.bars.indexOf(bar), 1); + }; +}]) + +.directive('progress', function() { + return { + restrict: 'EA', + replace: true, + transclude: true, + controller: 'ProgressController', + require: 'progress', + scope: {}, + templateUrl: 'template/progressbar/progress.html' + }; +}) + +.directive('bar', function() { + return { + restrict: 'EA', + replace: true, + transclude: true, + require: '^progress', + scope: { + value: '=', + type: '@' + }, + templateUrl: 'template/progressbar/bar.html', + link: function(scope, element, attrs, progressCtrl) { + progressCtrl.addBar(scope, element); + } + }; +}) + +.directive('progressbar', function() { + return { + restrict: 'EA', + replace: true, + transclude: true, + controller: 'ProgressController', + scope: { + value: '=', + type: '@' + }, + templateUrl: 'template/progressbar/progressbar.html', + link: function(scope, element, attrs, progressCtrl) { + progressCtrl.addBar(scope, angular.element(element.children()[0])); + } + }; +}); +angular.module('ui.bootstrap.rating', []) + +.constant('ratingConfig', { + max: 5, + stateOn: null, + stateOff: null +}) + +.controller('RatingController', ['$scope', '$attrs', 'ratingConfig', function($scope, $attrs, ratingConfig) { + var ngModelCtrl = { $setViewValue: angular.noop }; + + this.init = function(ngModelCtrl_) { + ngModelCtrl = ngModelCtrl_; + ngModelCtrl.$render = this.render; + + this.stateOn = angular.isDefined($attrs.stateOn) ? $scope.$parent.$eval($attrs.stateOn) : ratingConfig.stateOn; + this.stateOff = angular.isDefined($attrs.stateOff) ? $scope.$parent.$eval($attrs.stateOff) : ratingConfig.stateOff; + + var ratingStates = angular.isDefined($attrs.ratingStates) ? $scope.$parent.$eval($attrs.ratingStates) : + new Array( angular.isDefined($attrs.max) ? $scope.$parent.$eval($attrs.max) : ratingConfig.max ); + $scope.range = this.buildTemplateObjects(ratingStates); + }; + + this.buildTemplateObjects = function(states) { + for (var i = 0, n = states.length; i < n; i++) { + states[i] = angular.extend({ index: i }, { stateOn: this.stateOn, stateOff: this.stateOff }, states[i]); + } + return states; + }; + + $scope.rate = function(value) { + if ( !$scope.readonly && value >= 0 && value <= $scope.range.length ) { + ngModelCtrl.$setViewValue(value); + ngModelCtrl.$render(); + } + }; + + $scope.enter = function(value) { + if ( !$scope.readonly ) { + $scope.value = value; + } + $scope.onHover({value: value}); + }; + + $scope.reset = function() { + $scope.value = ngModelCtrl.$viewValue; + $scope.onLeave(); + }; + + $scope.onKeydown = function(evt) { + if (/(37|38|39|40)/.test(evt.which)) { + evt.preventDefault(); + evt.stopPropagation(); + $scope.rate( $scope.value + (evt.which === 38 || evt.which === 39 ? 1 : -1) ); + } + }; + + this.render = function() { + $scope.value = ngModelCtrl.$viewValue; + }; +}]) + +.directive('rating', function() { + return { + restrict: 'EA', + require: ['rating', 'ngModel'], + scope: { + readonly: '=?', + onHover: '&', + onLeave: '&' + }, + controller: 'RatingController', + templateUrl: 'template/rating/rating.html', + replace: true, + link: function(scope, element, attrs, ctrls) { + var ratingCtrl = ctrls[0], ngModelCtrl = ctrls[1]; + + if ( ngModelCtrl ) { + ratingCtrl.init( ngModelCtrl ); + } + } + }; +}); + +/** + * @ngdoc overview + * @name ui.bootstrap.tabs + * + * @description + * AngularJS version of the tabs directive. + */ + +angular.module('ui.bootstrap.tabs', []) + +.controller('TabsetController', ['$scope', function TabsetCtrl($scope) { + var ctrl = this, + tabs = ctrl.tabs = $scope.tabs = []; + + ctrl.select = function(selectedTab) { + angular.forEach(tabs, function(tab) { + if (tab.active && tab !== selectedTab) { + tab.active = false; + tab.onDeselect(); + } + }); + selectedTab.active = true; + selectedTab.onSelect(); + }; + + ctrl.addTab = function addTab(tab) { + tabs.push(tab); + // we can't run the select function on the first tab + // since that would select it twice + if (tabs.length === 1) { + tab.active = true; + } else if (tab.active) { + ctrl.select(tab); + } + }; + + ctrl.removeTab = function removeTab(tab) { + var index = tabs.indexOf(tab); + //Select a new tab if the tab to be removed is selected and not destroyed + if (tab.active && tabs.length > 1 && !destroyed) { + //If this is the last tab, select the previous tab. else, the next tab. + var newActiveIndex = index == tabs.length - 1 ? index - 1 : index + 1; + ctrl.select(tabs[newActiveIndex]); + } + tabs.splice(index, 1); + }; + + var destroyed; + $scope.$on('$destroy', function() { + destroyed = true; + }); +}]) + +/** + * @ngdoc directive + * @name ui.bootstrap.tabs.directive:tabset + * @restrict EA + * + * @description + * Tabset is the outer container for the tabs directive + * + * @param {boolean=} vertical Whether or not to use vertical styling for the tabs. + * @param {boolean=} justified Whether or not to use justified styling for the tabs. + * + * @example + + + + First Content! + Second Content! + +
    + + First Vertical Content! + Second Vertical Content! + + + First Justified Content! + Second Justified Content! + +
    +
    + */ +.directive('tabset', function() { + return { + restrict: 'EA', + transclude: true, + replace: true, + scope: { + type: '@' + }, + controller: 'TabsetController', + templateUrl: 'template/tabs/tabset.html', + link: function(scope, element, attrs) { + scope.vertical = angular.isDefined(attrs.vertical) ? scope.$parent.$eval(attrs.vertical) : false; + scope.justified = angular.isDefined(attrs.justified) ? scope.$parent.$eval(attrs.justified) : false; + } + }; +}) + +/** + * @ngdoc directive + * @name ui.bootstrap.tabs.directive:tab + * @restrict EA + * + * @param {string=} heading The visible heading, or title, of the tab. Set HTML headings with {@link ui.bootstrap.tabs.directive:tabHeading tabHeading}. + * @param {string=} select An expression to evaluate when the tab is selected. + * @param {boolean=} active A binding, telling whether or not this tab is selected. + * @param {boolean=} disabled A binding, telling whether or not this tab is disabled. + * + * @description + * Creates a tab with a heading and content. Must be placed within a {@link ui.bootstrap.tabs.directive:tabset tabset}. + * + * @example + + +
    + + +
    + + First Tab + + Alert me! + Second Tab, with alert callback and html heading! + + + {{item.content}} + + +
    +
    + + function TabsDemoCtrl($scope) { + $scope.items = [ + { title:"Dynamic Title 1", content:"Dynamic Item 0" }, + { title:"Dynamic Title 2", content:"Dynamic Item 1", disabled: true } + ]; + + $scope.alertMe = function() { + setTimeout(function() { + alert("You've selected the alert tab!"); + }); + }; + }; + +
    + */ + +/** + * @ngdoc directive + * @name ui.bootstrap.tabs.directive:tabHeading + * @restrict EA + * + * @description + * Creates an HTML heading for a {@link ui.bootstrap.tabs.directive:tab tab}. Must be placed as a child of a tab element. + * + * @example + + + + + HTML in my titles?! + And some content, too! + + + Icon heading?!? + That's right. + + + + + */ +.directive('tab', ['$parse', function($parse) { + return { + require: '^tabset', + restrict: 'EA', + replace: true, + templateUrl: 'template/tabs/tab.html', + transclude: true, + scope: { + active: '=?', + heading: '@', + onSelect: '&select', //This callback is called in contentHeadingTransclude + //once it inserts the tab's content into the dom + onDeselect: '&deselect' + }, + controller: function() { + //Empty controller so other directives can require being 'under' a tab + }, + compile: function(elm, attrs, transclude) { + return function postLink(scope, elm, attrs, tabsetCtrl) { + scope.$watch('active', function(active) { + if (active) { + tabsetCtrl.select(scope); + } + }); + + scope.disabled = false; + if ( attrs.disabled ) { + scope.$parent.$watch($parse(attrs.disabled), function(value) { + scope.disabled = !! value; + }); + } + + scope.select = function() { + if ( !scope.disabled ) { + scope.active = true; + } + }; + + tabsetCtrl.addTab(scope); + scope.$on('$destroy', function() { + tabsetCtrl.removeTab(scope); + }); + + //We need to transclude later, once the content container is ready. + //when this link happens, we're inside a tab heading. + scope.$transcludeFn = transclude; + }; + } + }; +}]) + +.directive('tabHeadingTransclude', [function() { + return { + restrict: 'A', + require: '^tab', + link: function(scope, elm, attrs, tabCtrl) { + scope.$watch('headingElement', function updateHeadingElement(heading) { + if (heading) { + elm.html(''); + elm.append(heading); + } + }); + } + }; +}]) + +.directive('tabContentTransclude', function() { + return { + restrict: 'A', + require: '^tabset', + link: function(scope, elm, attrs) { + var tab = scope.$eval(attrs.tabContentTransclude); + + //Now our tab is ready to be transcluded: both the tab heading area + //and the tab content area are loaded. Transclude 'em both. + tab.$transcludeFn(tab.$parent, function(contents) { + angular.forEach(contents, function(node) { + if (isTabHeading(node)) { + //Let tabHeadingTransclude know. + tab.headingElement = node; + } else { + elm.append(node); + } + }); + }); + } + }; + function isTabHeading(node) { + return node.tagName && ( + node.hasAttribute('tab-heading') || + node.hasAttribute('data-tab-heading') || + node.tagName.toLowerCase() === 'tab-heading' || + node.tagName.toLowerCase() === 'data-tab-heading' + ); + } +}) + +; + +angular.module('ui.bootstrap.timepicker', []) + +.constant('timepickerConfig', { + hourStep: 1, + minuteStep: 1, + showMeridian: true, + meridians: null, + readonlyInput: false, + mousewheel: true +}) + +.controller('TimepickerController', ['$scope', '$attrs', '$parse', '$log', '$locale', 'timepickerConfig', function($scope, $attrs, $parse, $log, $locale, timepickerConfig) { + var selected = new Date(), + ngModelCtrl = { $setViewValue: angular.noop }, // nullModelCtrl + meridians = angular.isDefined($attrs.meridians) ? $scope.$parent.$eval($attrs.meridians) : timepickerConfig.meridians || $locale.DATETIME_FORMATS.AMPMS; + + this.init = function( ngModelCtrl_, inputs ) { + ngModelCtrl = ngModelCtrl_; + ngModelCtrl.$render = this.render; + + var hoursInputEl = inputs.eq(0), + minutesInputEl = inputs.eq(1); + + var mousewheel = angular.isDefined($attrs.mousewheel) ? $scope.$parent.$eval($attrs.mousewheel) : timepickerConfig.mousewheel; + if ( mousewheel ) { + this.setupMousewheelEvents( hoursInputEl, minutesInputEl ); + } + + $scope.readonlyInput = angular.isDefined($attrs.readonlyInput) ? $scope.$parent.$eval($attrs.readonlyInput) : timepickerConfig.readonlyInput; + this.setupInputEvents( hoursInputEl, minutesInputEl ); + }; + + var hourStep = timepickerConfig.hourStep; + if ($attrs.hourStep) { + $scope.$parent.$watch($parse($attrs.hourStep), function(value) { + hourStep = parseInt(value, 10); + }); + } + + var minuteStep = timepickerConfig.minuteStep; + if ($attrs.minuteStep) { + $scope.$parent.$watch($parse($attrs.minuteStep), function(value) { + minuteStep = parseInt(value, 10); + }); + } + + // 12H / 24H mode + $scope.showMeridian = timepickerConfig.showMeridian; + if ($attrs.showMeridian) { + $scope.$parent.$watch($parse($attrs.showMeridian), function(value) { + $scope.showMeridian = !!value; + + if ( ngModelCtrl.$error.time ) { + // Evaluate from template + var hours = getHoursFromTemplate(), minutes = getMinutesFromTemplate(); + if (angular.isDefined( hours ) && angular.isDefined( minutes )) { + selected.setHours( hours ); + refresh(); + } + } else { + updateTemplate(); + } + }); + } + + // Get $scope.hours in 24H mode if valid + function getHoursFromTemplate ( ) { + var hours = parseInt( $scope.hours, 10 ); + var valid = ( $scope.showMeridian ) ? (hours > 0 && hours < 13) : (hours >= 0 && hours < 24); + if ( !valid ) { + return undefined; + } + + if ( $scope.showMeridian ) { + if ( hours === 12 ) { + hours = 0; + } + if ( $scope.meridian === meridians[1] ) { + hours = hours + 12; + } + } + return hours; + } + + function getMinutesFromTemplate() { + var minutes = parseInt($scope.minutes, 10); + return ( minutes >= 0 && minutes < 60 ) ? minutes : undefined; + } + + function pad( value ) { + return ( angular.isDefined(value) && value.toString().length < 2 ) ? '0' + value : value; + } + + // Respond on mousewheel spin + this.setupMousewheelEvents = function( hoursInputEl, minutesInputEl ) { + var isScrollingUp = function(e) { + if (e.originalEvent) { + e = e.originalEvent; + } + //pick correct delta variable depending on event + var delta = (e.wheelDelta) ? e.wheelDelta : -e.deltaY; + return (e.detail || delta > 0); + }; + + hoursInputEl.bind('mousewheel wheel', function(e) { + $scope.$apply( (isScrollingUp(e)) ? $scope.incrementHours() : $scope.decrementHours() ); + e.preventDefault(); + }); + + minutesInputEl.bind('mousewheel wheel', function(e) { + $scope.$apply( (isScrollingUp(e)) ? $scope.incrementMinutes() : $scope.decrementMinutes() ); + e.preventDefault(); + }); + + }; + + this.setupInputEvents = function( hoursInputEl, minutesInputEl ) { + if ( $scope.readonlyInput ) { + $scope.updateHours = angular.noop; + $scope.updateMinutes = angular.noop; + return; + } + + var invalidate = function(invalidHours, invalidMinutes) { + ngModelCtrl.$setViewValue( null ); + ngModelCtrl.$setValidity('time', false); + if (angular.isDefined(invalidHours)) { + $scope.invalidHours = invalidHours; + } + if (angular.isDefined(invalidMinutes)) { + $scope.invalidMinutes = invalidMinutes; + } + }; + + $scope.updateHours = function() { + var hours = getHoursFromTemplate(); + + if ( angular.isDefined(hours) ) { + selected.setHours( hours ); + refresh( 'h' ); + } else { + invalidate(true); + } + }; + + hoursInputEl.bind('blur', function(e) { + if ( !$scope.invalidHours && $scope.hours < 10) { + $scope.$apply( function() { + $scope.hours = pad( $scope.hours ); + }); + } + }); + + $scope.updateMinutes = function() { + var minutes = getMinutesFromTemplate(); + + if ( angular.isDefined(minutes) ) { + selected.setMinutes( minutes ); + refresh( 'm' ); + } else { + invalidate(undefined, true); + } + }; + + minutesInputEl.bind('blur', function(e) { + if ( !$scope.invalidMinutes && $scope.minutes < 10 ) { + $scope.$apply( function() { + $scope.minutes = pad( $scope.minutes ); + }); + } + }); + + }; + + this.render = function() { + var date = ngModelCtrl.$modelValue ? new Date( ngModelCtrl.$modelValue ) : null; + + if ( isNaN(date) ) { + ngModelCtrl.$setValidity('time', false); + $log.error('Timepicker directive: "ng-model" value must be a Date object, a number of milliseconds since 01.01.1970 or a string representing an RFC2822 or ISO 8601 date.'); + } else { + if ( date ) { + selected = date; + } + makeValid(); + updateTemplate(); + } + }; + + // Call internally when we know that model is valid. + function refresh( keyboardChange ) { + makeValid(); + ngModelCtrl.$setViewValue( new Date(selected) ); + updateTemplate( keyboardChange ); + } + + function makeValid() { + ngModelCtrl.$setValidity('time', true); + $scope.invalidHours = false; + $scope.invalidMinutes = false; + } + + function updateTemplate( keyboardChange ) { + var hours = selected.getHours(), minutes = selected.getMinutes(); + + if ( $scope.showMeridian ) { + hours = ( hours === 0 || hours === 12 ) ? 12 : hours % 12; // Convert 24 to 12 hour system + } + + $scope.hours = keyboardChange === 'h' ? hours : pad(hours); + $scope.minutes = keyboardChange === 'm' ? minutes : pad(minutes); + $scope.meridian = selected.getHours() < 12 ? meridians[0] : meridians[1]; + } + + function addMinutes( minutes ) { + var dt = new Date( selected.getTime() + minutes * 60000 ); + selected.setHours( dt.getHours(), dt.getMinutes() ); + refresh(); + } + + $scope.incrementHours = function() { + addMinutes( hourStep * 60 ); + }; + $scope.decrementHours = function() { + addMinutes( - hourStep * 60 ); + }; + $scope.incrementMinutes = function() { + addMinutes( minuteStep ); + }; + $scope.decrementMinutes = function() { + addMinutes( - minuteStep ); + }; + $scope.toggleMeridian = function() { + addMinutes( 12 * 60 * (( selected.getHours() < 12 ) ? 1 : -1) ); + }; +}]) + +.directive('timepicker', function () { + return { + restrict: 'EA', + require: ['timepicker', '?^ngModel'], + controller:'TimepickerController', + replace: true, + scope: {}, + templateUrl: 'template/timepicker/timepicker.html', + link: function(scope, element, attrs, ctrls) { + var timepickerCtrl = ctrls[0], ngModelCtrl = ctrls[1]; + + if ( ngModelCtrl ) { + timepickerCtrl.init( ngModelCtrl, element.find('input') ); + } + } + }; +}); + +angular.module('ui.bootstrap.typeahead', ['ui.bootstrap.position', 'ui.bootstrap.bindHtml']) + +/** + * A helper service that can parse typeahead's syntax (string provided by users) + * Extracted to a separate service for ease of unit testing + */ + .factory('typeaheadParser', ['$parse', function ($parse) { + + // 00000111000000000000022200000000000000003333333333333330000000000044000 + var TYPEAHEAD_REGEXP = /^\s*([\s\S]+?)(?:\s+as\s+([\s\S]+?))?\s+for\s+(?:([\$\w][\$\w\d]*))\s+in\s+([\s\S]+?)$/; + + return { + parse:function (input) { + + var match = input.match(TYPEAHEAD_REGEXP); + if (!match) { + throw new Error( + 'Expected typeahead specification in form of "_modelValue_ (as _label_)? for _item_ in _collection_"' + + ' but got "' + input + '".'); + } + + return { + itemName:match[3], + source:$parse(match[4]), + viewMapper:$parse(match[2] || match[1]), + modelMapper:$parse(match[1]) + }; + } + }; +}]) + + .directive('typeahead', ['$compile', '$parse', '$q', '$timeout', '$document', '$position', 'typeaheadParser', + function ($compile, $parse, $q, $timeout, $document, $position, typeaheadParser) { + + var HOT_KEYS = [9, 13, 27, 38, 40]; + + return { + require:'ngModel', + link:function (originalScope, element, attrs, modelCtrl) { + + //SUPPORTED ATTRIBUTES (OPTIONS) + + //minimal no of characters that needs to be entered before typeahead kicks-in + var minSearch = originalScope.$eval(attrs.typeaheadMinLength) || 1; + + //minimal wait time after last character typed before typehead kicks-in + var waitTime = originalScope.$eval(attrs.typeaheadWaitMs) || 0; + + //should it restrict model values to the ones selected from the popup only? + var isEditable = originalScope.$eval(attrs.typeaheadEditable) !== false; + + //binding to a variable that indicates if matches are being retrieved asynchronously + var isLoadingSetter = $parse(attrs.typeaheadLoading).assign || angular.noop; + + //a callback executed when a match is selected + var onSelectCallback = $parse(attrs.typeaheadOnSelect); + + var inputFormatter = attrs.typeaheadInputFormatter ? $parse(attrs.typeaheadInputFormatter) : undefined; + + var appendToBody = attrs.typeaheadAppendToBody ? originalScope.$eval(attrs.typeaheadAppendToBody) : false; + + var focusFirst = originalScope.$eval(attrs.typeaheadFocusFirst) !== false; + + //INTERNAL VARIABLES + + //model setter executed upon match selection + var $setModelValue = $parse(attrs.ngModel).assign; + + //expressions used by typeahead + var parserResult = typeaheadParser.parse(attrs.typeahead); + + var hasFocus; + + //create a child scope for the typeahead directive so we are not polluting original scope + //with typeahead-specific data (matches, query etc.) + var scope = originalScope.$new(); + originalScope.$on('$destroy', function(){ + scope.$destroy(); + }); + + // WAI-ARIA + var popupId = 'typeahead-' + scope.$id + '-' + Math.floor(Math.random() * 10000); + element.attr({ + 'aria-autocomplete': 'list', + 'aria-expanded': false, + 'aria-owns': popupId + }); + + //pop-up element used to display matches + var popUpEl = angular.element('
    '); + popUpEl.attr({ + id: popupId, + matches: 'matches', + active: 'activeIdx', + select: 'select(activeIdx)', + query: 'query', + position: 'position' + }); + //custom item template + if (angular.isDefined(attrs.typeaheadTemplateUrl)) { + popUpEl.attr('template-url', attrs.typeaheadTemplateUrl); + } + + var resetMatches = function() { + scope.matches = []; + scope.activeIdx = -1; + element.attr('aria-expanded', false); + }; + + var getMatchId = function(index) { + return popupId + '-option-' + index; + }; + + // Indicate that the specified match is the active (pre-selected) item in the list owned by this typeahead. + // This attribute is added or removed automatically when the `activeIdx` changes. + scope.$watch('activeIdx', function(index) { + if (index < 0) { + element.removeAttr('aria-activedescendant'); + } else { + element.attr('aria-activedescendant', getMatchId(index)); + } + }); + + var getMatchesAsync = function(inputValue) { + + var locals = {$viewValue: inputValue}; + isLoadingSetter(originalScope, true); + $q.when(parserResult.source(originalScope, locals)).then(function(matches) { + + //it might happen that several async queries were in progress if a user were typing fast + //but we are interested only in responses that correspond to the current view value + var onCurrentRequest = (inputValue === modelCtrl.$viewValue); + if (onCurrentRequest && hasFocus) { + if (matches.length > 0) { + + scope.activeIdx = focusFirst ? 0 : -1; + scope.matches.length = 0; + + //transform labels + for(var i=0; i= minSearch) { + if (waitTime > 0) { + cancelPreviousTimeout(); + scheduleSearchWithTimeout(inputValue); + } else { + getMatchesAsync(inputValue); + } + } else { + isLoadingSetter(originalScope, false); + cancelPreviousTimeout(); + resetMatches(); + } + + if (isEditable) { + return inputValue; + } else { + if (!inputValue) { + // Reset in case user had typed something previously. + modelCtrl.$setValidity('editable', true); + return inputValue; + } else { + modelCtrl.$setValidity('editable', false); + return undefined; + } + } + }); + + modelCtrl.$formatters.push(function (modelValue) { + + var candidateViewValue, emptyViewValue; + var locals = {}; + + if (inputFormatter) { + + locals.$model = modelValue; + return inputFormatter(originalScope, locals); + + } else { + + //it might happen that we don't have enough info to properly render input value + //we need to check for this situation and simply return model value if we can't apply custom formatting + locals[parserResult.itemName] = modelValue; + candidateViewValue = parserResult.viewMapper(originalScope, locals); + locals[parserResult.itemName] = undefined; + emptyViewValue = parserResult.viewMapper(originalScope, locals); + + return candidateViewValue!== emptyViewValue ? candidateViewValue : modelValue; + } + }); + + scope.select = function (activeIdx) { + //called from within the $digest() cycle + var locals = {}; + var model, item; + + locals[parserResult.itemName] = item = scope.matches[activeIdx].model; + model = parserResult.modelMapper(originalScope, locals); + $setModelValue(originalScope, model); + modelCtrl.$setValidity('editable', true); + + onSelectCallback(originalScope, { + $item: item, + $model: model, + $label: parserResult.viewMapper(originalScope, locals) + }); + + resetMatches(); + + //return focus to the input element if a match was selected via a mouse click event + // use timeout to avoid $rootScope:inprog error + $timeout(function() { element[0].focus(); }, 0, false); + }; + + //bind keyboard events: arrows up(38) / down(40), enter(13) and tab(9), esc(27) + element.bind('keydown', function (evt) { + + //typeahead is open and an "interesting" key was pressed + if (scope.matches.length === 0 || HOT_KEYS.indexOf(evt.which) === -1) { + return; + } + + // if there's nothing selected (i.e. focusFirst) and enter is hit, don't do anything + if (scope.activeIdx == -1 && (evt.which === 13 || evt.which === 9)) { + return; + } + + evt.preventDefault(); + + if (evt.which === 40) { + scope.activeIdx = (scope.activeIdx + 1) % scope.matches.length; + scope.$digest(); + + } else if (evt.which === 38) { + scope.activeIdx = (scope.activeIdx > 0 ? scope.activeIdx : scope.matches.length) - 1; + scope.$digest(); + + } else if (evt.which === 13 || evt.which === 9) { + scope.$apply(function () { + scope.select(scope.activeIdx); + }); + + } else if (evt.which === 27) { + evt.stopPropagation(); + + resetMatches(); + scope.$digest(); + } + }); + + element.bind('blur', function (evt) { + hasFocus = false; + }); + + // Keep reference to click handler to unbind it. + var dismissClickHandler = function (evt) { + if (element[0] !== evt.target) { + resetMatches(); + scope.$digest(); + } + }; + + $document.bind('click', dismissClickHandler); + + originalScope.$on('$destroy', function(){ + $document.unbind('click', dismissClickHandler); + if (appendToBody) { + $popup.remove(); + } + }); + + var $popup = $compile(popUpEl)(scope); + if (appendToBody) { + $document.find('body').append($popup); + } else { + element.after($popup); + } + } + }; + +}]) + + .directive('typeaheadPopup', function () { + return { + restrict:'EA', + scope:{ + matches:'=', + query:'=', + active:'=', + position:'=', + select:'&' + }, + replace:true, + templateUrl:'template/typeahead/typeahead-popup.html', + link:function (scope, element, attrs) { + + scope.templateUrl = attrs.templateUrl; + + scope.isOpen = function () { + return scope.matches.length > 0; + }; + + scope.isActive = function (matchIdx) { + return scope.active == matchIdx; + }; + + scope.selectActive = function (matchIdx) { + scope.active = matchIdx; + }; + + scope.selectMatch = function (activeIdx) { + scope.select({activeIdx:activeIdx}); + }; + } + }; + }) + + .directive('typeaheadMatch', ['$http', '$templateCache', '$compile', '$parse', function ($http, $templateCache, $compile, $parse) { + return { + restrict:'EA', + scope:{ + index:'=', + match:'=', + query:'=' + }, + link:function (scope, element, attrs) { + var tplUrl = $parse(attrs.templateUrl)(scope.$parent) || 'template/typeahead/typeahead-match.html'; + $http.get(tplUrl, {cache: $templateCache}).success(function(tplContent){ + element.replaceWith($compile(tplContent.trim())(scope)); + }); + } + }; + }]) + + .filter('typeaheadHighlight', function() { + + function escapeRegexp(queryToEscape) { + return queryToEscape.replace(/([.?*+^$[\]\\(){}|-])/g, '\\$1'); + } + + return function(matchItem, query) { + return query ? ('' + matchItem).replace(new RegExp(escapeRegexp(query), 'gi'), '$&') : matchItem; + }; + }); + +angular.module("template/accordion/accordion-group.html", []).run(["$templateCache", function($templateCache) { + $templateCache.put("template/accordion/accordion-group.html", + "
    \n" + + "
    \n" + + "

    \n" + + " {{heading}}\n" + + "

    \n" + + "
    \n" + + "
    \n" + + "
    \n" + + "
    \n" + + "
    \n" + + ""); +}]); + +angular.module("template/accordion/accordion.html", []).run(["$templateCache", function($templateCache) { + $templateCache.put("template/accordion/accordion.html", + "
    "); +}]); + +angular.module("template/alert/alert.html", []).run(["$templateCache", function($templateCache) { + $templateCache.put("template/alert/alert.html", + "
    \n" + + " \n" + + "
    \n" + + "
    \n" + + ""); +}]); + +angular.module("template/carousel/carousel.html", []).run(["$templateCache", function($templateCache) { + $templateCache.put("template/carousel/carousel.html", + "
    \n" + + "
      1\">\n" + + "
    1. \n" + + "
    \n" + + "
    \n" + + " 1\">\n" + + " 1\">\n" + + "
    \n" + + ""); +}]); + +angular.module("template/carousel/slide.html", []).run(["$templateCache", function($templateCache) { + $templateCache.put("template/carousel/slide.html", + "
    \n" + + ""); +}]); + +angular.module("template/datepicker/datepicker.html", []).run(["$templateCache", function($templateCache) { + $templateCache.put("template/datepicker/datepicker.html", + "
    \n" + + " \n" + + " \n" + + " \n" + + "
    "); +}]); + +angular.module("template/datepicker/day.html", []).run(["$templateCache", function($templateCache) { + $templateCache.put("template/datepicker/day.html", + "\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + "
    {{label.abbr}}
    {{ weekNumbers[$index] }}\n" + + " \n" + + "
    \n" + + ""); +}]); + +angular.module("template/datepicker/month.html", []).run(["$templateCache", function($templateCache) { + $templateCache.put("template/datepicker/month.html", + "\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + "
    \n" + + " \n" + + "
    \n" + + ""); +}]); + +angular.module("template/datepicker/popup.html", []).run(["$templateCache", function($templateCache) { + $templateCache.put("template/datepicker/popup.html", + "
      \n" + + "
    • \n" + + "
    • \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + "
    • \n" + + "
    \n" + + ""); +}]); + +angular.module("template/datepicker/year.html", []).run(["$templateCache", function($templateCache) { + $templateCache.put("template/datepicker/year.html", + "\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + "
    \n" + + " \n" + + "
    \n" + + ""); +}]); + +angular.module("template/modal/backdrop.html", []).run(["$templateCache", function($templateCache) { + $templateCache.put("template/modal/backdrop.html", + "
    \n" + + ""); +}]); + +angular.module("template/modal/window.html", []).run(["$templateCache", function($templateCache) { + $templateCache.put("template/modal/window.html", + "
    \n" + + "
    \n" + + "
    "); +}]); + +angular.module("template/pagination/pager.html", []).run(["$templateCache", function($templateCache) { + $templateCache.put("template/pagination/pager.html", + ""); +}]); + +angular.module("template/pagination/pagination.html", []).run(["$templateCache", function($templateCache) { + $templateCache.put("template/pagination/pagination.html", + ""); +}]); + +angular.module("template/tooltip/tooltip-html-unsafe-popup.html", []).run(["$templateCache", function($templateCache) { + $templateCache.put("template/tooltip/tooltip-html-unsafe-popup.html", + "
    \n" + + "
    \n" + + "
    \n" + + "
    \n" + + ""); +}]); + +angular.module("template/tooltip/tooltip-popup.html", []).run(["$templateCache", function($templateCache) { + $templateCache.put("template/tooltip/tooltip-popup.html", + "
    \n" + + "
    \n" + + "
    \n" + + "
    \n" + + ""); +}]); + +angular.module("template/popover/popover.html", []).run(["$templateCache", function($templateCache) { + $templateCache.put("template/popover/popover.html", + "
    \n" + + "
    \n" + + "\n" + + "
    \n" + + "

    \n" + + "
    \n" + + "
    \n" + + "
    \n" + + ""); +}]); + +angular.module("template/progressbar/bar.html", []).run(["$templateCache", function($templateCache) { + $templateCache.put("template/progressbar/bar.html", + "
    "); +}]); + +angular.module("template/progressbar/progress.html", []).run(["$templateCache", function($templateCache) { + $templateCache.put("template/progressbar/progress.html", + "
    "); +}]); + +angular.module("template/progressbar/progressbar.html", []).run(["$templateCache", function($templateCache) { + $templateCache.put("template/progressbar/progressbar.html", + "
    \n" + + "
    \n" + + "
    "); +}]); + +angular.module("template/rating/rating.html", []).run(["$templateCache", function($templateCache) { + $templateCache.put("template/rating/rating.html", + "\n" + + " \n" + + " ({{ $index < value ? '*' : ' ' }})\n" + + " \n" + + ""); +}]); + +angular.module("template/tabs/tab.html", []).run(["$templateCache", function($templateCache) { + $templateCache.put("template/tabs/tab.html", + "
  • \n" + + " {{heading}}\n" + + "
  • \n" + + ""); +}]); + +angular.module("template/tabs/tabset.html", []).run(["$templateCache", function($templateCache) { + $templateCache.put("template/tabs/tabset.html", + "
    \n" + + "
      \n" + + "
      \n" + + "
      \n" + + "
      \n" + + "
      \n" + + "
      \n" + + ""); +}]); + +angular.module("template/timepicker/timepicker.html", []).run(["$templateCache", function($templateCache) { + $templateCache.put("template/timepicker/timepicker.html", + "\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + "
       
      \n" + + " \n" + + " :\n" + + " \n" + + "
       
      \n" + + ""); +}]); + +angular.module("template/typeahead/typeahead-match.html", []).run(["$templateCache", function($templateCache) { + $templateCache.put("template/typeahead/typeahead-match.html", + ""); +}]); + +angular.module("template/typeahead/typeahead-popup.html", []).run(["$templateCache", function($templateCache) { + $templateCache.put("template/typeahead/typeahead-popup.html", + "
        \n" + + "
      • \n" + + "
        \n" + + "
      • \n" + + "
      \n" + + ""); +}]); diff --git a/public/admincp/bower_components/angular-bootstrap/ui-bootstrap-tpls.min.js b/public/admincp/bower_components/angular-bootstrap/ui-bootstrap-tpls.min.js new file mode 100644 index 000000000..ae71363e6 --- /dev/null +++ b/public/admincp/bower_components/angular-bootstrap/ui-bootstrap-tpls.min.js @@ -0,0 +1,10 @@ +/* + * angular-ui-bootstrap + * http://angular-ui.github.io/bootstrap/ + + * Version: 0.12.0 - 2014-11-16 + * License: MIT + */ +angular.module("ui.bootstrap",["ui.bootstrap.tpls","ui.bootstrap.transition","ui.bootstrap.collapse","ui.bootstrap.accordion","ui.bootstrap.alert","ui.bootstrap.bindHtml","ui.bootstrap.buttons","ui.bootstrap.carousel","ui.bootstrap.dateparser","ui.bootstrap.position","ui.bootstrap.datepicker","ui.bootstrap.dropdown","ui.bootstrap.modal","ui.bootstrap.pagination","ui.bootstrap.tooltip","ui.bootstrap.popover","ui.bootstrap.progressbar","ui.bootstrap.rating","ui.bootstrap.tabs","ui.bootstrap.timepicker","ui.bootstrap.typeahead"]),angular.module("ui.bootstrap.tpls",["template/accordion/accordion-group.html","template/accordion/accordion.html","template/alert/alert.html","template/carousel/carousel.html","template/carousel/slide.html","template/datepicker/datepicker.html","template/datepicker/day.html","template/datepicker/month.html","template/datepicker/popup.html","template/datepicker/year.html","template/modal/backdrop.html","template/modal/window.html","template/pagination/pager.html","template/pagination/pagination.html","template/tooltip/tooltip-html-unsafe-popup.html","template/tooltip/tooltip-popup.html","template/popover/popover.html","template/progressbar/bar.html","template/progressbar/progress.html","template/progressbar/progressbar.html","template/rating/rating.html","template/tabs/tab.html","template/tabs/tabset.html","template/timepicker/timepicker.html","template/typeahead/typeahead-match.html","template/typeahead/typeahead-popup.html"]),angular.module("ui.bootstrap.transition",[]).factory("$transition",["$q","$timeout","$rootScope",function(a,b,c){function d(a){for(var b in a)if(void 0!==f.style[b])return a[b]}var e=function(d,f,g){g=g||{};var h=a.defer(),i=e[g.animation?"animationEndEventName":"transitionEndEventName"],j=function(){c.$apply(function(){d.unbind(i,j),h.resolve(d)})};return i&&d.bind(i,j),b(function(){angular.isString(f)?d.addClass(f):angular.isFunction(f)?f(d):angular.isObject(f)&&d.css(f),i||h.resolve(d)}),h.promise.cancel=function(){i&&d.unbind(i,j),h.reject("Transition cancelled")},h.promise},f=document.createElement("trans"),g={WebkitTransition:"webkitTransitionEnd",MozTransition:"transitionend",OTransition:"oTransitionEnd",transition:"transitionend"},h={WebkitTransition:"webkitAnimationEnd",MozTransition:"animationend",OTransition:"oAnimationEnd",transition:"animationend"};return e.transitionEndEventName=d(g),e.animationEndEventName=d(h),e}]),angular.module("ui.bootstrap.collapse",["ui.bootstrap.transition"]).directive("collapse",["$transition",function(a){return{link:function(b,c,d){function e(b){function d(){j===e&&(j=void 0)}var e=a(c,b);return j&&j.cancel(),j=e,e.then(d,d),e}function f(){k?(k=!1,g()):(c.removeClass("collapse").addClass("collapsing"),e({height:c[0].scrollHeight+"px"}).then(g))}function g(){c.removeClass("collapsing"),c.addClass("collapse in"),c.css({height:"auto"})}function h(){if(k)k=!1,i(),c.css({height:0});else{c.css({height:c[0].scrollHeight+"px"});{c[0].offsetWidth}c.removeClass("collapse in").addClass("collapsing"),e({height:0}).then(i)}}function i(){c.removeClass("collapsing"),c.addClass("collapse")}var j,k=!0;b.$watch(d.collapse,function(a){a?h():f()})}}}]),angular.module("ui.bootstrap.accordion",["ui.bootstrap.collapse"]).constant("accordionConfig",{closeOthers:!0}).controller("AccordionController",["$scope","$attrs","accordionConfig",function(a,b,c){this.groups=[],this.closeOthers=function(d){var e=angular.isDefined(b.closeOthers)?a.$eval(b.closeOthers):c.closeOthers;e&&angular.forEach(this.groups,function(a){a!==d&&(a.isOpen=!1)})},this.addGroup=function(a){var b=this;this.groups.push(a),a.$on("$destroy",function(){b.removeGroup(a)})},this.removeGroup=function(a){var b=this.groups.indexOf(a);-1!==b&&this.groups.splice(b,1)}}]).directive("accordion",function(){return{restrict:"EA",controller:"AccordionController",transclude:!0,replace:!1,templateUrl:"template/accordion/accordion.html"}}).directive("accordionGroup",function(){return{require:"^accordion",restrict:"EA",transclude:!0,replace:!0,templateUrl:"template/accordion/accordion-group.html",scope:{heading:"@",isOpen:"=?",isDisabled:"=?"},controller:function(){this.setHeading=function(a){this.heading=a}},link:function(a,b,c,d){d.addGroup(a),a.$watch("isOpen",function(b){b&&d.closeOthers(a)}),a.toggleOpen=function(){a.isDisabled||(a.isOpen=!a.isOpen)}}}}).directive("accordionHeading",function(){return{restrict:"EA",transclude:!0,template:"",replace:!0,require:"^accordionGroup",link:function(a,b,c,d,e){d.setHeading(e(a,function(){}))}}}).directive("accordionTransclude",function(){return{require:"^accordionGroup",link:function(a,b,c,d){a.$watch(function(){return d[c.accordionTransclude]},function(a){a&&(b.html(""),b.append(a))})}}}),angular.module("ui.bootstrap.alert",[]).controller("AlertController",["$scope","$attrs",function(a,b){a.closeable="close"in b,this.close=a.close}]).directive("alert",function(){return{restrict:"EA",controller:"AlertController",templateUrl:"template/alert/alert.html",transclude:!0,replace:!0,scope:{type:"@",close:"&"}}}).directive("dismissOnTimeout",["$timeout",function(a){return{require:"alert",link:function(b,c,d,e){a(function(){e.close()},parseInt(d.dismissOnTimeout,10))}}}]),angular.module("ui.bootstrap.bindHtml",[]).directive("bindHtmlUnsafe",function(){return function(a,b,c){b.addClass("ng-binding").data("$binding",c.bindHtmlUnsafe),a.$watch(c.bindHtmlUnsafe,function(a){b.html(a||"")})}}),angular.module("ui.bootstrap.buttons",[]).constant("buttonConfig",{activeClass:"active",toggleEvent:"click"}).controller("ButtonsController",["buttonConfig",function(a){this.activeClass=a.activeClass||"active",this.toggleEvent=a.toggleEvent||"click"}]).directive("btnRadio",function(){return{require:["btnRadio","ngModel"],controller:"ButtonsController",link:function(a,b,c,d){var e=d[0],f=d[1];f.$render=function(){b.toggleClass(e.activeClass,angular.equals(f.$modelValue,a.$eval(c.btnRadio)))},b.bind(e.toggleEvent,function(){var d=b.hasClass(e.activeClass);(!d||angular.isDefined(c.uncheckable))&&a.$apply(function(){f.$setViewValue(d?null:a.$eval(c.btnRadio)),f.$render()})})}}}).directive("btnCheckbox",function(){return{require:["btnCheckbox","ngModel"],controller:"ButtonsController",link:function(a,b,c,d){function e(){return g(c.btnCheckboxTrue,!0)}function f(){return g(c.btnCheckboxFalse,!1)}function g(b,c){var d=a.$eval(b);return angular.isDefined(d)?d:c}var h=d[0],i=d[1];i.$render=function(){b.toggleClass(h.activeClass,angular.equals(i.$modelValue,e()))},b.bind(h.toggleEvent,function(){a.$apply(function(){i.$setViewValue(b.hasClass(h.activeClass)?f():e()),i.$render()})})}}}),angular.module("ui.bootstrap.carousel",["ui.bootstrap.transition"]).controller("CarouselController",["$scope","$timeout","$interval","$transition",function(a,b,c,d){function e(){f();var b=+a.interval;!isNaN(b)&&b>0&&(h=c(g,b))}function f(){h&&(c.cancel(h),h=null)}function g(){var b=+a.interval;i&&!isNaN(b)&&b>0?a.next():a.pause()}var h,i,j=this,k=j.slides=a.slides=[],l=-1;j.currentSlide=null;var m=!1;j.select=a.select=function(c,f){function g(){if(!m){if(j.currentSlide&&angular.isString(f)&&!a.noTransition&&c.$element){c.$element.addClass(f);{c.$element[0].offsetWidth}angular.forEach(k,function(a){angular.extend(a,{direction:"",entering:!1,leaving:!1,active:!1})}),angular.extend(c,{direction:f,active:!0,entering:!0}),angular.extend(j.currentSlide||{},{direction:f,leaving:!0}),a.$currentTransition=d(c.$element,{}),function(b,c){a.$currentTransition.then(function(){h(b,c)},function(){h(b,c)})}(c,j.currentSlide)}else h(c,j.currentSlide);j.currentSlide=c,l=i,e()}}function h(b,c){angular.extend(b,{direction:"",active:!0,leaving:!1,entering:!1}),angular.extend(c||{},{direction:"",active:!1,leaving:!1,entering:!1}),a.$currentTransition=null}var i=k.indexOf(c);void 0===f&&(f=i>l?"next":"prev"),c&&c!==j.currentSlide&&(a.$currentTransition?(a.$currentTransition.cancel(),b(g)):g())},a.$on("$destroy",function(){m=!0}),j.indexOfSlide=function(a){return k.indexOf(a)},a.next=function(){var b=(l+1)%k.length;return a.$currentTransition?void 0:j.select(k[b],"next")},a.prev=function(){var b=0>l-1?k.length-1:l-1;return a.$currentTransition?void 0:j.select(k[b],"prev")},a.isActive=function(a){return j.currentSlide===a},a.$watch("interval",e),a.$on("$destroy",f),a.play=function(){i||(i=!0,e())},a.pause=function(){a.noPause||(i=!1,f())},j.addSlide=function(b,c){b.$element=c,k.push(b),1===k.length||b.active?(j.select(k[k.length-1]),1==k.length&&a.play()):b.active=!1},j.removeSlide=function(a){var b=k.indexOf(a);k.splice(b,1),k.length>0&&a.active?j.select(b>=k.length?k[b-1]:k[b]):l>b&&l--}}]).directive("carousel",[function(){return{restrict:"EA",transclude:!0,replace:!0,controller:"CarouselController",require:"carousel",templateUrl:"template/carousel/carousel.html",scope:{interval:"=",noTransition:"=",noPause:"="}}}]).directive("slide",function(){return{require:"^carousel",restrict:"EA",transclude:!0,replace:!0,templateUrl:"template/carousel/slide.html",scope:{active:"=?"},link:function(a,b,c,d){d.addSlide(a,b),a.$on("$destroy",function(){d.removeSlide(a)}),a.$watch("active",function(b){b&&d.select(a)})}}}),angular.module("ui.bootstrap.dateparser",[]).service("dateParser",["$locale","orderByFilter",function(a,b){function c(a){var c=[],d=a.split("");return angular.forEach(e,function(b,e){var f=a.indexOf(e);if(f>-1){a=a.split(""),d[f]="("+b.regex+")",a[f]="$";for(var g=f+1,h=f+e.length;h>g;g++)d[g]="",a[g]="$";a=a.join(""),c.push({index:f,apply:b.apply})}}),{regex:new RegExp("^"+d.join("")+"$"),map:b(c,"index")}}function d(a,b,c){return 1===b&&c>28?29===c&&(a%4===0&&a%100!==0||a%400===0):3===b||5===b||8===b||10===b?31>c:!0}this.parsers={};var e={yyyy:{regex:"\\d{4}",apply:function(a){this.year=+a}},yy:{regex:"\\d{2}",apply:function(a){this.year=+a+2e3}},y:{regex:"\\d{1,4}",apply:function(a){this.year=+a}},MMMM:{regex:a.DATETIME_FORMATS.MONTH.join("|"),apply:function(b){this.month=a.DATETIME_FORMATS.MONTH.indexOf(b)}},MMM:{regex:a.DATETIME_FORMATS.SHORTMONTH.join("|"),apply:function(b){this.month=a.DATETIME_FORMATS.SHORTMONTH.indexOf(b)}},MM:{regex:"0[1-9]|1[0-2]",apply:function(a){this.month=a-1}},M:{regex:"[1-9]|1[0-2]",apply:function(a){this.month=a-1}},dd:{regex:"[0-2][0-9]{1}|3[0-1]{1}",apply:function(a){this.date=+a}},d:{regex:"[1-2]?[0-9]{1}|3[0-1]{1}",apply:function(a){this.date=+a}},EEEE:{regex:a.DATETIME_FORMATS.DAY.join("|")},EEE:{regex:a.DATETIME_FORMATS.SHORTDAY.join("|")}};this.parse=function(b,e){if(!angular.isString(b)||!e)return b;e=a.DATETIME_FORMATS[e]||e,this.parsers[e]||(this.parsers[e]=c(e));var f=this.parsers[e],g=f.regex,h=f.map,i=b.match(g);if(i&&i.length){for(var j,k={year:1900,month:0,date:1,hours:0},l=1,m=i.length;m>l;l++){var n=h[l-1];n.apply&&n.apply.call(k,i[l])}return d(k.year,k.month,k.date)&&(j=new Date(k.year,k.month,k.date,k.hours)),j}}}]),angular.module("ui.bootstrap.position",[]).factory("$position",["$document","$window",function(a,b){function c(a,c){return a.currentStyle?a.currentStyle[c]:b.getComputedStyle?b.getComputedStyle(a)[c]:a.style[c]}function d(a){return"static"===(c(a,"position")||"static")}var e=function(b){for(var c=a[0],e=b.offsetParent||c;e&&e!==c&&d(e);)e=e.offsetParent;return e||c};return{position:function(b){var c=this.offset(b),d={top:0,left:0},f=e(b[0]);f!=a[0]&&(d=this.offset(angular.element(f)),d.top+=f.clientTop-f.scrollTop,d.left+=f.clientLeft-f.scrollLeft);var g=b[0].getBoundingClientRect();return{width:g.width||b.prop("offsetWidth"),height:g.height||b.prop("offsetHeight"),top:c.top-d.top,left:c.left-d.left}},offset:function(c){var d=c[0].getBoundingClientRect();return{width:d.width||c.prop("offsetWidth"),height:d.height||c.prop("offsetHeight"),top:d.top+(b.pageYOffset||a[0].documentElement.scrollTop),left:d.left+(b.pageXOffset||a[0].documentElement.scrollLeft)}},positionElements:function(a,b,c,d){var e,f,g,h,i=c.split("-"),j=i[0],k=i[1]||"center";e=d?this.offset(a):this.position(a),f=b.prop("offsetWidth"),g=b.prop("offsetHeight");var l={center:function(){return e.left+e.width/2-f/2},left:function(){return e.left},right:function(){return e.left+e.width}},m={center:function(){return e.top+e.height/2-g/2},top:function(){return e.top},bottom:function(){return e.top+e.height}};switch(j){case"right":h={top:m[k](),left:l[j]()};break;case"left":h={top:m[k](),left:e.left-f};break;case"bottom":h={top:m[j](),left:l[k]()};break;default:h={top:e.top-g,left:l[k]()}}return h}}}]),angular.module("ui.bootstrap.datepicker",["ui.bootstrap.dateparser","ui.bootstrap.position"]).constant("datepickerConfig",{formatDay:"dd",formatMonth:"MMMM",formatYear:"yyyy",formatDayHeader:"EEE",formatDayTitle:"MMMM yyyy",formatMonthTitle:"yyyy",datepickerMode:"day",minMode:"day",maxMode:"year",showWeeks:!0,startingDay:0,yearRange:20,minDate:null,maxDate:null}).controller("DatepickerController",["$scope","$attrs","$parse","$interpolate","$timeout","$log","dateFilter","datepickerConfig",function(a,b,c,d,e,f,g,h){var i=this,j={$setViewValue:angular.noop};this.modes=["day","month","year"],angular.forEach(["formatDay","formatMonth","formatYear","formatDayHeader","formatDayTitle","formatMonthTitle","minMode","maxMode","showWeeks","startingDay","yearRange"],function(c,e){i[c]=angular.isDefined(b[c])?8>e?d(b[c])(a.$parent):a.$parent.$eval(b[c]):h[c]}),angular.forEach(["minDate","maxDate"],function(d){b[d]?a.$parent.$watch(c(b[d]),function(a){i[d]=a?new Date(a):null,i.refreshView()}):i[d]=h[d]?new Date(h[d]):null}),a.datepickerMode=a.datepickerMode||h.datepickerMode,a.uniqueId="datepicker-"+a.$id+"-"+Math.floor(1e4*Math.random()),this.activeDate=angular.isDefined(b.initDate)?a.$parent.$eval(b.initDate):new Date,a.isActive=function(b){return 0===i.compare(b.date,i.activeDate)?(a.activeDateId=b.uid,!0):!1},this.init=function(a){j=a,j.$render=function(){i.render()}},this.render=function(){if(j.$modelValue){var a=new Date(j.$modelValue),b=!isNaN(a);b?this.activeDate=a:f.error('Datepicker directive: "ng-model" value must be a Date object, a number of milliseconds since 01.01.1970 or a string representing an RFC2822 or ISO 8601 date.'),j.$setValidity("date",b)}this.refreshView()},this.refreshView=function(){if(this.element){this._refreshView();var a=j.$modelValue?new Date(j.$modelValue):null;j.$setValidity("date-disabled",!a||this.element&&!this.isDisabled(a))}},this.createDateObject=function(a,b){var c=j.$modelValue?new Date(j.$modelValue):null;return{date:a,label:g(a,b),selected:c&&0===this.compare(a,c),disabled:this.isDisabled(a),current:0===this.compare(a,new Date)}},this.isDisabled=function(c){return this.minDate&&this.compare(c,this.minDate)<0||this.maxDate&&this.compare(c,this.maxDate)>0||b.dateDisabled&&a.dateDisabled({date:c,mode:a.datepickerMode})},this.split=function(a,b){for(var c=[];a.length>0;)c.push(a.splice(0,b));return c},a.select=function(b){if(a.datepickerMode===i.minMode){var c=j.$modelValue?new Date(j.$modelValue):new Date(0,0,0,0,0,0,0);c.setFullYear(b.getFullYear(),b.getMonth(),b.getDate()),j.$setViewValue(c),j.$render()}else i.activeDate=b,a.datepickerMode=i.modes[i.modes.indexOf(a.datepickerMode)-1]},a.move=function(a){var b=i.activeDate.getFullYear()+a*(i.step.years||0),c=i.activeDate.getMonth()+a*(i.step.months||0);i.activeDate.setFullYear(b,c,1),i.refreshView()},a.toggleMode=function(b){b=b||1,a.datepickerMode===i.maxMode&&1===b||a.datepickerMode===i.minMode&&-1===b||(a.datepickerMode=i.modes[i.modes.indexOf(a.datepickerMode)+b])},a.keys={13:"enter",32:"space",33:"pageup",34:"pagedown",35:"end",36:"home",37:"left",38:"up",39:"right",40:"down"};var k=function(){e(function(){i.element[0].focus()},0,!1)};a.$on("datepicker.focus",k),a.keydown=function(b){var c=a.keys[b.which];if(c&&!b.shiftKey&&!b.altKey)if(b.preventDefault(),b.stopPropagation(),"enter"===c||"space"===c){if(i.isDisabled(i.activeDate))return;a.select(i.activeDate),k()}else!b.ctrlKey||"up"!==c&&"down"!==c?(i.handleKeyDown(c,b),i.refreshView()):(a.toggleMode("up"===c?1:-1),k())}}]).directive("datepicker",function(){return{restrict:"EA",replace:!0,templateUrl:"template/datepicker/datepicker.html",scope:{datepickerMode:"=?",dateDisabled:"&"},require:["datepicker","?^ngModel"],controller:"DatepickerController",link:function(a,b,c,d){var e=d[0],f=d[1];f&&e.init(f)}}}).directive("daypicker",["dateFilter",function(a){return{restrict:"EA",replace:!0,templateUrl:"template/datepicker/day.html",require:"^datepicker",link:function(b,c,d,e){function f(a,b){return 1!==b||a%4!==0||a%100===0&&a%400!==0?i[b]:29}function g(a,b){var c=new Array(b),d=new Date(a),e=0;for(d.setHours(12);b>e;)c[e++]=new Date(d),d.setDate(d.getDate()+1);return c}function h(a){var b=new Date(a);b.setDate(b.getDate()+4-(b.getDay()||7));var c=b.getTime();return b.setMonth(0),b.setDate(1),Math.floor(Math.round((c-b)/864e5)/7)+1}b.showWeeks=e.showWeeks,e.step={months:1},e.element=c;var i=[31,28,31,30,31,30,31,31,30,31,30,31];e._refreshView=function(){var c=e.activeDate.getFullYear(),d=e.activeDate.getMonth(),f=new Date(c,d,1),i=e.startingDay-f.getDay(),j=i>0?7-i:-i,k=new Date(f);j>0&&k.setDate(-j+1);for(var l=g(k,42),m=0;42>m;m++)l[m]=angular.extend(e.createDateObject(l[m],e.formatDay),{secondary:l[m].getMonth()!==d,uid:b.uniqueId+"-"+m});b.labels=new Array(7);for(var n=0;7>n;n++)b.labels[n]={abbr:a(l[n].date,e.formatDayHeader),full:a(l[n].date,"EEEE")};if(b.title=a(e.activeDate,e.formatDayTitle),b.rows=e.split(l,7),b.showWeeks){b.weekNumbers=[];for(var o=h(b.rows[0][0].date),p=b.rows.length;b.weekNumbers.push(o++)f;f++)c[f]=angular.extend(e.createDateObject(new Date(d,f,1),e.formatMonth),{uid:b.uniqueId+"-"+f});b.title=a(e.activeDate,e.formatMonthTitle),b.rows=e.split(c,3)},e.compare=function(a,b){return new Date(a.getFullYear(),a.getMonth())-new Date(b.getFullYear(),b.getMonth())},e.handleKeyDown=function(a){var b=e.activeDate.getMonth();if("left"===a)b-=1;else if("up"===a)b-=3;else if("right"===a)b+=1;else if("down"===a)b+=3;else if("pageup"===a||"pagedown"===a){var c=e.activeDate.getFullYear()+("pageup"===a?-1:1);e.activeDate.setFullYear(c)}else"home"===a?b=0:"end"===a&&(b=11);e.activeDate.setMonth(b)},e.refreshView()}}}]).directive("yearpicker",["dateFilter",function(){return{restrict:"EA",replace:!0,templateUrl:"template/datepicker/year.html",require:"^datepicker",link:function(a,b,c,d){function e(a){return parseInt((a-1)/f,10)*f+1}var f=d.yearRange;d.step={years:f},d.element=b,d._refreshView=function(){for(var b=new Array(f),c=0,g=e(d.activeDate.getFullYear());f>c;c++)b[c]=angular.extend(d.createDateObject(new Date(g+c,0,1),d.formatYear),{uid:a.uniqueId+"-"+c});a.title=[b[0].label,b[f-1].label].join(" - "),a.rows=d.split(b,5)},d.compare=function(a,b){return a.getFullYear()-b.getFullYear()},d.handleKeyDown=function(a){var b=d.activeDate.getFullYear();"left"===a?b-=1:"up"===a?b-=5:"right"===a?b+=1:"down"===a?b+=5:"pageup"===a||"pagedown"===a?b+=("pageup"===a?-1:1)*d.step.years:"home"===a?b=e(d.activeDate.getFullYear()):"end"===a&&(b=e(d.activeDate.getFullYear())+f-1),d.activeDate.setFullYear(b)},d.refreshView()}}}]).constant("datepickerPopupConfig",{datepickerPopup:"yyyy-MM-dd",currentText:"Today",clearText:"Clear",closeText:"Done",closeOnDateSelection:!0,appendToBody:!1,showButtonBar:!0}).directive("datepickerPopup",["$compile","$parse","$document","$position","dateFilter","dateParser","datepickerPopupConfig",function(a,b,c,d,e,f,g){return{restrict:"EA",require:"ngModel",scope:{isOpen:"=?",currentText:"@",clearText:"@",closeText:"@",dateDisabled:"&"},link:function(h,i,j,k){function l(a){return a.replace(/([A-Z])/g,function(a){return"-"+a.toLowerCase()})}function m(a){if(a){if(angular.isDate(a)&&!isNaN(a))return k.$setValidity("date",!0),a;if(angular.isString(a)){var b=f.parse(a,n)||new Date(a);return isNaN(b)?void k.$setValidity("date",!1):(k.$setValidity("date",!0),b)}return void k.$setValidity("date",!1)}return k.$setValidity("date",!0),null}var n,o=angular.isDefined(j.closeOnDateSelection)?h.$parent.$eval(j.closeOnDateSelection):g.closeOnDateSelection,p=angular.isDefined(j.datepickerAppendToBody)?h.$parent.$eval(j.datepickerAppendToBody):g.appendToBody;h.showButtonBar=angular.isDefined(j.showButtonBar)?h.$parent.$eval(j.showButtonBar):g.showButtonBar,h.getText=function(a){return h[a+"Text"]||g[a+"Text"]},j.$observe("datepickerPopup",function(a){n=a||g.datepickerPopup,k.$render()});var q=angular.element("
      ");q.attr({"ng-model":"date","ng-change":"dateSelection()"});var r=angular.element(q.children()[0]);j.datepickerOptions&&angular.forEach(h.$parent.$eval(j.datepickerOptions),function(a,b){r.attr(l(b),a)}),h.watchData={},angular.forEach(["minDate","maxDate","datepickerMode"],function(a){if(j[a]){var c=b(j[a]);if(h.$parent.$watch(c,function(b){h.watchData[a]=b}),r.attr(l(a),"watchData."+a),"datepickerMode"===a){var d=c.assign;h.$watch("watchData."+a,function(a,b){a!==b&&d(h.$parent,a)})}}}),j.dateDisabled&&r.attr("date-disabled","dateDisabled({ date: date, mode: mode })"),k.$parsers.unshift(m),h.dateSelection=function(a){angular.isDefined(a)&&(h.date=a),k.$setViewValue(h.date),k.$render(),o&&(h.isOpen=!1,i[0].focus())},i.bind("input change keyup",function(){h.$apply(function(){h.date=k.$modelValue})}),k.$render=function(){var a=k.$viewValue?e(k.$viewValue,n):"";i.val(a),h.date=m(k.$modelValue)};var s=function(a){h.isOpen&&a.target!==i[0]&&h.$apply(function(){h.isOpen=!1})},t=function(a){h.keydown(a)};i.bind("keydown",t),h.keydown=function(a){27===a.which?(a.preventDefault(),a.stopPropagation(),h.close()):40!==a.which||h.isOpen||(h.isOpen=!0)},h.$watch("isOpen",function(a){a?(h.$broadcast("datepicker.focus"),h.position=p?d.offset(i):d.position(i),h.position.top=h.position.top+i.prop("offsetHeight"),c.bind("click",s)):c.unbind("click",s)}),h.select=function(a){if("today"===a){var b=new Date;angular.isDate(k.$modelValue)?(a=new Date(k.$modelValue),a.setFullYear(b.getFullYear(),b.getMonth(),b.getDate())):a=new Date(b.setHours(0,0,0,0))}h.dateSelection(a)},h.close=function(){h.isOpen=!1,i[0].focus()};var u=a(q)(h);q.remove(),p?c.find("body").append(u):i.after(u),h.$on("$destroy",function(){u.remove(),i.unbind("keydown",t),c.unbind("click",s)})}}}]).directive("datepickerPopupWrap",function(){return{restrict:"EA",replace:!0,transclude:!0,templateUrl:"template/datepicker/popup.html",link:function(a,b){b.bind("click",function(a){a.preventDefault(),a.stopPropagation()})}}}),angular.module("ui.bootstrap.dropdown",[]).constant("dropdownConfig",{openClass:"open"}).service("dropdownService",["$document",function(a){var b=null;this.open=function(e){b||(a.bind("click",c),a.bind("keydown",d)),b&&b!==e&&(b.isOpen=!1),b=e},this.close=function(e){b===e&&(b=null,a.unbind("click",c),a.unbind("keydown",d))};var c=function(a){if(b){var c=b.getToggleElement();a&&c&&c[0].contains(a.target)||b.$apply(function(){b.isOpen=!1})}},d=function(a){27===a.which&&(b.focusToggleElement(),c())}}]).controller("DropdownController",["$scope","$attrs","$parse","dropdownConfig","dropdownService","$animate",function(a,b,c,d,e,f){var g,h=this,i=a.$new(),j=d.openClass,k=angular.noop,l=b.onToggle?c(b.onToggle):angular.noop;this.init=function(d){h.$element=d,b.isOpen&&(g=c(b.isOpen),k=g.assign,a.$watch(g,function(a){i.isOpen=!!a}))},this.toggle=function(a){return i.isOpen=arguments.length?!!a:!i.isOpen},this.isOpen=function(){return i.isOpen},i.getToggleElement=function(){return h.toggleElement},i.focusToggleElement=function(){h.toggleElement&&h.toggleElement[0].focus()},i.$watch("isOpen",function(b,c){f[b?"addClass":"removeClass"](h.$element,j),b?(i.focusToggleElement(),e.open(i)):e.close(i),k(a,b),angular.isDefined(b)&&b!==c&&l(a,{open:!!b})}),a.$on("$locationChangeSuccess",function(){i.isOpen=!1}),a.$on("$destroy",function(){i.$destroy()})}]).directive("dropdown",function(){return{controller:"DropdownController",link:function(a,b,c,d){d.init(b)}}}).directive("dropdownToggle",function(){return{require:"?^dropdown",link:function(a,b,c,d){if(d){d.toggleElement=b;var e=function(e){e.preventDefault(),b.hasClass("disabled")||c.disabled||a.$apply(function(){d.toggle()})};b.bind("click",e),b.attr({"aria-haspopup":!0,"aria-expanded":!1}),a.$watch(d.isOpen,function(a){b.attr("aria-expanded",!!a)}),a.$on("$destroy",function(){b.unbind("click",e)})}}}}),angular.module("ui.bootstrap.modal",["ui.bootstrap.transition"]).factory("$$stackedMap",function(){return{createNew:function(){var a=[];return{add:function(b,c){a.push({key:b,value:c})},get:function(b){for(var c=0;c0),i()})}function i(){if(k&&-1==g()){var a=l;j(k,l,150,function(){a.$destroy(),a=null}),k=void 0,l=void 0}}function j(c,d,e,f){function g(){g.done||(g.done=!0,c.remove(),f&&f())}d.animate=!1;var h=a.transitionEndEventName;if(h){var i=b(g,e);c.bind(h,function(){b.cancel(i),g(),d.$apply()})}else b(g)}var k,l,m="modal-open",n=f.createNew(),o={};return e.$watch(g,function(a){l&&(l.index=a)}),c.bind("keydown",function(a){var b;27===a.which&&(b=n.top(),b&&b.value.keyboard&&(a.preventDefault(),e.$apply(function(){o.dismiss(b.key,"escape key press")})))}),o.open=function(a,b){n.add(a,{deferred:b.deferred,modalScope:b.scope,backdrop:b.backdrop,keyboard:b.keyboard});var f=c.find("body").eq(0),h=g();if(h>=0&&!k){l=e.$new(!0),l.index=h;var i=angular.element("
      ");i.attr("backdrop-class",b.backdropClass),k=d(i)(l),f.append(k)}var j=angular.element("
      ");j.attr({"template-url":b.windowTemplateUrl,"window-class":b.windowClass,size:b.size,index:n.length()-1,animate:"animate"}).html(b.content);var o=d(j)(b.scope);n.top().value.modalDomEl=o,f.append(o),f.addClass(m)},o.close=function(a,b){var c=n.get(a);c&&(c.value.deferred.resolve(b),h(a))},o.dismiss=function(a,b){var c=n.get(a);c&&(c.value.deferred.reject(b),h(a))},o.dismissAll=function(a){for(var b=this.getTop();b;)this.dismiss(b.key,a),b=this.getTop()},o.getTop=function(){return n.top()},o}]).provider("$modal",function(){var a={options:{backdrop:!0,keyboard:!0},$get:["$injector","$rootScope","$q","$http","$templateCache","$controller","$modalStack",function(b,c,d,e,f,g,h){function i(a){return a.template?d.when(a.template):e.get(angular.isFunction(a.templateUrl)?a.templateUrl():a.templateUrl,{cache:f}).then(function(a){return a.data})}function j(a){var c=[];return angular.forEach(a,function(a){(angular.isFunction(a)||angular.isArray(a))&&c.push(d.when(b.invoke(a)))}),c}var k={};return k.open=function(b){var e=d.defer(),f=d.defer(),k={result:e.promise,opened:f.promise,close:function(a){h.close(k,a)},dismiss:function(a){h.dismiss(k,a)}};if(b=angular.extend({},a.options,b),b.resolve=b.resolve||{},!b.template&&!b.templateUrl)throw new Error("One of template or templateUrl options is required.");var l=d.all([i(b)].concat(j(b.resolve)));return l.then(function(a){var d=(b.scope||c).$new();d.$close=k.close,d.$dismiss=k.dismiss;var f,i={},j=1;b.controller&&(i.$scope=d,i.$modalInstance=k,angular.forEach(b.resolve,function(b,c){i[c]=a[j++]}),f=g(b.controller,i),b.controllerAs&&(d[b.controllerAs]=f)),h.open(k,{scope:d,deferred:e,content:a[0],backdrop:b.backdrop,keyboard:b.keyboard,backdropClass:b.backdropClass,windowClass:b.windowClass,windowTemplateUrl:b.windowTemplateUrl,size:b.size})},function(a){e.reject(a)}),l.then(function(){f.resolve(!0)},function(){f.reject(!1)}),k},k}]};return a}),angular.module("ui.bootstrap.pagination",[]).controller("PaginationController",["$scope","$attrs","$parse",function(a,b,c){var d=this,e={$setViewValue:angular.noop},f=b.numPages?c(b.numPages).assign:angular.noop;this.init=function(f,g){e=f,this.config=g,e.$render=function(){d.render()},b.itemsPerPage?a.$parent.$watch(c(b.itemsPerPage),function(b){d.itemsPerPage=parseInt(b,10),a.totalPages=d.calculateTotalPages()}):this.itemsPerPage=g.itemsPerPage},this.calculateTotalPages=function(){var b=this.itemsPerPage<1?1:Math.ceil(a.totalItems/this.itemsPerPage);return Math.max(b||0,1)},this.render=function(){a.page=parseInt(e.$viewValue,10)||1},a.selectPage=function(b){a.page!==b&&b>0&&b<=a.totalPages&&(e.$setViewValue(b),e.$render())},a.getText=function(b){return a[b+"Text"]||d.config[b+"Text"]},a.noPrevious=function(){return 1===a.page},a.noNext=function(){return a.page===a.totalPages},a.$watch("totalItems",function(){a.totalPages=d.calculateTotalPages()}),a.$watch("totalPages",function(b){f(a.$parent,b),a.page>b?a.selectPage(b):e.$render()})}]).constant("paginationConfig",{itemsPerPage:10,boundaryLinks:!1,directionLinks:!0,firstText:"First",previousText:"Previous",nextText:"Next",lastText:"Last",rotate:!0}).directive("pagination",["$parse","paginationConfig",function(a,b){return{restrict:"EA",scope:{totalItems:"=",firstText:"@",previousText:"@",nextText:"@",lastText:"@"},require:["pagination","?ngModel"],controller:"PaginationController",templateUrl:"template/pagination/pagination.html",replace:!0,link:function(c,d,e,f){function g(a,b,c){return{number:a,text:b,active:c}}function h(a,b){var c=[],d=1,e=b,f=angular.isDefined(k)&&b>k;f&&(l?(d=Math.max(a-Math.floor(k/2),1),e=d+k-1,e>b&&(e=b,d=e-k+1)):(d=(Math.ceil(a/k)-1)*k+1,e=Math.min(d+k-1,b)));for(var h=d;e>=h;h++){var i=g(h,h,h===a);c.push(i)}if(f&&!l){if(d>1){var j=g(d-1,"...",!1);c.unshift(j)}if(b>e){var m=g(e+1,"...",!1);c.push(m)}}return c}var i=f[0],j=f[1];if(j){var k=angular.isDefined(e.maxSize)?c.$parent.$eval(e.maxSize):b.maxSize,l=angular.isDefined(e.rotate)?c.$parent.$eval(e.rotate):b.rotate;c.boundaryLinks=angular.isDefined(e.boundaryLinks)?c.$parent.$eval(e.boundaryLinks):b.boundaryLinks,c.directionLinks=angular.isDefined(e.directionLinks)?c.$parent.$eval(e.directionLinks):b.directionLinks,i.init(j,b),e.maxSize&&c.$parent.$watch(a(e.maxSize),function(a){k=parseInt(a,10),i.render() +});var m=i.render;i.render=function(){m(),c.page>0&&c.page<=c.totalPages&&(c.pages=h(c.page,c.totalPages))}}}}}]).constant("pagerConfig",{itemsPerPage:10,previousText:"« Previous",nextText:"Next »",align:!0}).directive("pager",["pagerConfig",function(a){return{restrict:"EA",scope:{totalItems:"=",previousText:"@",nextText:"@"},require:["pager","?ngModel"],controller:"PaginationController",templateUrl:"template/pagination/pager.html",replace:!0,link:function(b,c,d,e){var f=e[0],g=e[1];g&&(b.align=angular.isDefined(d.align)?b.$parent.$eval(d.align):a.align,f.init(g,a))}}}]),angular.module("ui.bootstrap.tooltip",["ui.bootstrap.position","ui.bootstrap.bindHtml"]).provider("$tooltip",function(){function a(a){var b=/[A-Z]/g,c="-";return a.replace(b,function(a,b){return(b?c:"")+a.toLowerCase()})}var b={placement:"top",animation:!0,popupDelay:0},c={mouseenter:"mouseleave",click:"click",focus:"blur"},d={};this.options=function(a){angular.extend(d,a)},this.setTriggers=function(a){angular.extend(c,a)},this.$get=["$window","$compile","$timeout","$document","$position","$interpolate",function(e,f,g,h,i,j){return function(e,k,l){function m(a){var b=a||n.trigger||l,d=c[b]||b;return{show:b,hide:d}}var n=angular.extend({},b,d),o=a(e),p=j.startSymbol(),q=j.endSymbol(),r="
      ';return{restrict:"EA",compile:function(){var a=f(r);return function(b,c,d){function f(){D.isOpen?l():j()}function j(){(!C||b.$eval(d[k+"Enable"]))&&(s(),D.popupDelay?z||(z=g(o,D.popupDelay,!1),z.then(function(a){a()})):o()())}function l(){b.$apply(function(){p()})}function o(){return z=null,y&&(g.cancel(y),y=null),D.content?(q(),w.css({top:0,left:0,display:"block"}),A?h.find("body").append(w):c.after(w),E(),D.isOpen=!0,D.$digest(),E):angular.noop}function p(){D.isOpen=!1,g.cancel(z),z=null,D.animation?y||(y=g(r,500)):r()}function q(){w&&r(),x=D.$new(),w=a(x,angular.noop)}function r(){y=null,w&&(w.remove(),w=null),x&&(x.$destroy(),x=null)}function s(){t(),u()}function t(){var a=d[k+"Placement"];D.placement=angular.isDefined(a)?a:n.placement}function u(){var a=d[k+"PopupDelay"],b=parseInt(a,10);D.popupDelay=isNaN(b)?n.popupDelay:b}function v(){var a=d[k+"Trigger"];F(),B=m(a),B.show===B.hide?c.bind(B.show,f):(c.bind(B.show,j),c.bind(B.hide,l))}var w,x,y,z,A=angular.isDefined(n.appendToBody)?n.appendToBody:!1,B=m(void 0),C=angular.isDefined(d[k+"Enable"]),D=b.$new(!0),E=function(){var a=i.positionElements(c,w,D.placement,A);a.top+="px",a.left+="px",w.css(a)};D.isOpen=!1,d.$observe(e,function(a){D.content=a,!a&&D.isOpen&&p()}),d.$observe(k+"Title",function(a){D.title=a});var F=function(){c.unbind(B.show,j),c.unbind(B.hide,l)};v();var G=b.$eval(d[k+"Animation"]);D.animation=angular.isDefined(G)?!!G:n.animation;var H=b.$eval(d[k+"AppendToBody"]);A=angular.isDefined(H)?H:A,A&&b.$on("$locationChangeSuccess",function(){D.isOpen&&p()}),b.$on("$destroy",function(){g.cancel(y),g.cancel(z),F(),r(),D=null})}}}}}]}).directive("tooltipPopup",function(){return{restrict:"EA",replace:!0,scope:{content:"@",placement:"@",animation:"&",isOpen:"&"},templateUrl:"template/tooltip/tooltip-popup.html"}}).directive("tooltip",["$tooltip",function(a){return a("tooltip","tooltip","mouseenter")}]).directive("tooltipHtmlUnsafePopup",function(){return{restrict:"EA",replace:!0,scope:{content:"@",placement:"@",animation:"&",isOpen:"&"},templateUrl:"template/tooltip/tooltip-html-unsafe-popup.html"}}).directive("tooltipHtmlUnsafe",["$tooltip",function(a){return a("tooltipHtmlUnsafe","tooltip","mouseenter")}]),angular.module("ui.bootstrap.popover",["ui.bootstrap.tooltip"]).directive("popoverPopup",function(){return{restrict:"EA",replace:!0,scope:{title:"@",content:"@",placement:"@",animation:"&",isOpen:"&"},templateUrl:"template/popover/popover.html"}}).directive("popover",["$tooltip",function(a){return a("popover","popover","click")}]),angular.module("ui.bootstrap.progressbar",[]).constant("progressConfig",{animate:!0,max:100}).controller("ProgressController",["$scope","$attrs","progressConfig",function(a,b,c){var d=this,e=angular.isDefined(b.animate)?a.$parent.$eval(b.animate):c.animate;this.bars=[],a.max=angular.isDefined(b.max)?a.$parent.$eval(b.max):c.max,this.addBar=function(b,c){e||c.css({transition:"none"}),this.bars.push(b),b.$watch("value",function(c){b.percent=+(100*c/a.max).toFixed(2)}),b.$on("$destroy",function(){c=null,d.removeBar(b)})},this.removeBar=function(a){this.bars.splice(this.bars.indexOf(a),1)}}]).directive("progress",function(){return{restrict:"EA",replace:!0,transclude:!0,controller:"ProgressController",require:"progress",scope:{},templateUrl:"template/progressbar/progress.html"}}).directive("bar",function(){return{restrict:"EA",replace:!0,transclude:!0,require:"^progress",scope:{value:"=",type:"@"},templateUrl:"template/progressbar/bar.html",link:function(a,b,c,d){d.addBar(a,b)}}}).directive("progressbar",function(){return{restrict:"EA",replace:!0,transclude:!0,controller:"ProgressController",scope:{value:"=",type:"@"},templateUrl:"template/progressbar/progressbar.html",link:function(a,b,c,d){d.addBar(a,angular.element(b.children()[0]))}}}),angular.module("ui.bootstrap.rating",[]).constant("ratingConfig",{max:5,stateOn:null,stateOff:null}).controller("RatingController",["$scope","$attrs","ratingConfig",function(a,b,c){var d={$setViewValue:angular.noop};this.init=function(e){d=e,d.$render=this.render,this.stateOn=angular.isDefined(b.stateOn)?a.$parent.$eval(b.stateOn):c.stateOn,this.stateOff=angular.isDefined(b.stateOff)?a.$parent.$eval(b.stateOff):c.stateOff;var f=angular.isDefined(b.ratingStates)?a.$parent.$eval(b.ratingStates):new Array(angular.isDefined(b.max)?a.$parent.$eval(b.max):c.max);a.range=this.buildTemplateObjects(f)},this.buildTemplateObjects=function(a){for(var b=0,c=a.length;c>b;b++)a[b]=angular.extend({index:b},{stateOn:this.stateOn,stateOff:this.stateOff},a[b]);return a},a.rate=function(b){!a.readonly&&b>=0&&b<=a.range.length&&(d.$setViewValue(b),d.$render())},a.enter=function(b){a.readonly||(a.value=b),a.onHover({value:b})},a.reset=function(){a.value=d.$viewValue,a.onLeave()},a.onKeydown=function(b){/(37|38|39|40)/.test(b.which)&&(b.preventDefault(),b.stopPropagation(),a.rate(a.value+(38===b.which||39===b.which?1:-1)))},this.render=function(){a.value=d.$viewValue}}]).directive("rating",function(){return{restrict:"EA",require:["rating","ngModel"],scope:{readonly:"=?",onHover:"&",onLeave:"&"},controller:"RatingController",templateUrl:"template/rating/rating.html",replace:!0,link:function(a,b,c,d){var e=d[0],f=d[1];f&&e.init(f)}}}),angular.module("ui.bootstrap.tabs",[]).controller("TabsetController",["$scope",function(a){var b=this,c=b.tabs=a.tabs=[];b.select=function(a){angular.forEach(c,function(b){b.active&&b!==a&&(b.active=!1,b.onDeselect())}),a.active=!0,a.onSelect()},b.addTab=function(a){c.push(a),1===c.length?a.active=!0:a.active&&b.select(a)},b.removeTab=function(a){var e=c.indexOf(a);if(a.active&&c.length>1&&!d){var f=e==c.length-1?e-1:e+1;b.select(c[f])}c.splice(e,1)};var d;a.$on("$destroy",function(){d=!0})}]).directive("tabset",function(){return{restrict:"EA",transclude:!0,replace:!0,scope:{type:"@"},controller:"TabsetController",templateUrl:"template/tabs/tabset.html",link:function(a,b,c){a.vertical=angular.isDefined(c.vertical)?a.$parent.$eval(c.vertical):!1,a.justified=angular.isDefined(c.justified)?a.$parent.$eval(c.justified):!1}}}).directive("tab",["$parse",function(a){return{require:"^tabset",restrict:"EA",replace:!0,templateUrl:"template/tabs/tab.html",transclude:!0,scope:{active:"=?",heading:"@",onSelect:"&select",onDeselect:"&deselect"},controller:function(){},compile:function(b,c,d){return function(b,c,e,f){b.$watch("active",function(a){a&&f.select(b)}),b.disabled=!1,e.disabled&&b.$parent.$watch(a(e.disabled),function(a){b.disabled=!!a}),b.select=function(){b.disabled||(b.active=!0)},f.addTab(b),b.$on("$destroy",function(){f.removeTab(b)}),b.$transcludeFn=d}}}}]).directive("tabHeadingTransclude",[function(){return{restrict:"A",require:"^tab",link:function(a,b){a.$watch("headingElement",function(a){a&&(b.html(""),b.append(a))})}}}]).directive("tabContentTransclude",function(){function a(a){return a.tagName&&(a.hasAttribute("tab-heading")||a.hasAttribute("data-tab-heading")||"tab-heading"===a.tagName.toLowerCase()||"data-tab-heading"===a.tagName.toLowerCase())}return{restrict:"A",require:"^tabset",link:function(b,c,d){var e=b.$eval(d.tabContentTransclude);e.$transcludeFn(e.$parent,function(b){angular.forEach(b,function(b){a(b)?e.headingElement=b:c.append(b)})})}}}),angular.module("ui.bootstrap.timepicker",[]).constant("timepickerConfig",{hourStep:1,minuteStep:1,showMeridian:!0,meridians:null,readonlyInput:!1,mousewheel:!0}).controller("TimepickerController",["$scope","$attrs","$parse","$log","$locale","timepickerConfig",function(a,b,c,d,e,f){function g(){var b=parseInt(a.hours,10),c=a.showMeridian?b>0&&13>b:b>=0&&24>b;return c?(a.showMeridian&&(12===b&&(b=0),a.meridian===p[1]&&(b+=12)),b):void 0}function h(){var b=parseInt(a.minutes,10);return b>=0&&60>b?b:void 0}function i(a){return angular.isDefined(a)&&a.toString().length<2?"0"+a:a}function j(a){k(),o.$setViewValue(new Date(n)),l(a)}function k(){o.$setValidity("time",!0),a.invalidHours=!1,a.invalidMinutes=!1}function l(b){var c=n.getHours(),d=n.getMinutes();a.showMeridian&&(c=0===c||12===c?12:c%12),a.hours="h"===b?c:i(c),a.minutes="m"===b?d:i(d),a.meridian=n.getHours()<12?p[0]:p[1]}function m(a){var b=new Date(n.getTime()+6e4*a);n.setHours(b.getHours(),b.getMinutes()),j()}var n=new Date,o={$setViewValue:angular.noop},p=angular.isDefined(b.meridians)?a.$parent.$eval(b.meridians):f.meridians||e.DATETIME_FORMATS.AMPMS;this.init=function(c,d){o=c,o.$render=this.render;var e=d.eq(0),g=d.eq(1),h=angular.isDefined(b.mousewheel)?a.$parent.$eval(b.mousewheel):f.mousewheel;h&&this.setupMousewheelEvents(e,g),a.readonlyInput=angular.isDefined(b.readonlyInput)?a.$parent.$eval(b.readonlyInput):f.readonlyInput,this.setupInputEvents(e,g)};var q=f.hourStep;b.hourStep&&a.$parent.$watch(c(b.hourStep),function(a){q=parseInt(a,10)});var r=f.minuteStep;b.minuteStep&&a.$parent.$watch(c(b.minuteStep),function(a){r=parseInt(a,10)}),a.showMeridian=f.showMeridian,b.showMeridian&&a.$parent.$watch(c(b.showMeridian),function(b){if(a.showMeridian=!!b,o.$error.time){var c=g(),d=h();angular.isDefined(c)&&angular.isDefined(d)&&(n.setHours(c),j())}else l()}),this.setupMousewheelEvents=function(b,c){var d=function(a){a.originalEvent&&(a=a.originalEvent);var b=a.wheelDelta?a.wheelDelta:-a.deltaY;return a.detail||b>0};b.bind("mousewheel wheel",function(b){a.$apply(d(b)?a.incrementHours():a.decrementHours()),b.preventDefault()}),c.bind("mousewheel wheel",function(b){a.$apply(d(b)?a.incrementMinutes():a.decrementMinutes()),b.preventDefault()})},this.setupInputEvents=function(b,c){if(a.readonlyInput)return a.updateHours=angular.noop,void(a.updateMinutes=angular.noop);var d=function(b,c){o.$setViewValue(null),o.$setValidity("time",!1),angular.isDefined(b)&&(a.invalidHours=b),angular.isDefined(c)&&(a.invalidMinutes=c)};a.updateHours=function(){var a=g();angular.isDefined(a)?(n.setHours(a),j("h")):d(!0)},b.bind("blur",function(){!a.invalidHours&&a.hours<10&&a.$apply(function(){a.hours=i(a.hours)})}),a.updateMinutes=function(){var a=h();angular.isDefined(a)?(n.setMinutes(a),j("m")):d(void 0,!0)},c.bind("blur",function(){!a.invalidMinutes&&a.minutes<10&&a.$apply(function(){a.minutes=i(a.minutes)})})},this.render=function(){var a=o.$modelValue?new Date(o.$modelValue):null;isNaN(a)?(o.$setValidity("time",!1),d.error('Timepicker directive: "ng-model" value must be a Date object, a number of milliseconds since 01.01.1970 or a string representing an RFC2822 or ISO 8601 date.')):(a&&(n=a),k(),l())},a.incrementHours=function(){m(60*q)},a.decrementHours=function(){m(60*-q)},a.incrementMinutes=function(){m(r)},a.decrementMinutes=function(){m(-r)},a.toggleMeridian=function(){m(720*(n.getHours()<12?1:-1))}}]).directive("timepicker",function(){return{restrict:"EA",require:["timepicker","?^ngModel"],controller:"TimepickerController",replace:!0,scope:{},templateUrl:"template/timepicker/timepicker.html",link:function(a,b,c,d){var e=d[0],f=d[1];f&&e.init(f,b.find("input"))}}}),angular.module("ui.bootstrap.typeahead",["ui.bootstrap.position","ui.bootstrap.bindHtml"]).factory("typeaheadParser",["$parse",function(a){var b=/^\s*([\s\S]+?)(?:\s+as\s+([\s\S]+?))?\s+for\s+(?:([\$\w][\$\w\d]*))\s+in\s+([\s\S]+?)$/;return{parse:function(c){var d=c.match(b);if(!d)throw new Error('Expected typeahead specification in form of "_modelValue_ (as _label_)? for _item_ in _collection_" but got "'+c+'".');return{itemName:d[3],source:a(d[4]),viewMapper:a(d[2]||d[1]),modelMapper:a(d[1])}}}}]).directive("typeahead",["$compile","$parse","$q","$timeout","$document","$position","typeaheadParser",function(a,b,c,d,e,f,g){var h=[9,13,27,38,40];return{require:"ngModel",link:function(i,j,k,l){var m,n=i.$eval(k.typeaheadMinLength)||1,o=i.$eval(k.typeaheadWaitMs)||0,p=i.$eval(k.typeaheadEditable)!==!1,q=b(k.typeaheadLoading).assign||angular.noop,r=b(k.typeaheadOnSelect),s=k.typeaheadInputFormatter?b(k.typeaheadInputFormatter):void 0,t=k.typeaheadAppendToBody?i.$eval(k.typeaheadAppendToBody):!1,u=i.$eval(k.typeaheadFocusFirst)!==!1,v=b(k.ngModel).assign,w=g.parse(k.typeahead),x=i.$new();i.$on("$destroy",function(){x.$destroy()});var y="typeahead-"+x.$id+"-"+Math.floor(1e4*Math.random());j.attr({"aria-autocomplete":"list","aria-expanded":!1,"aria-owns":y});var z=angular.element("
      ");z.attr({id:y,matches:"matches",active:"activeIdx",select:"select(activeIdx)",query:"query",position:"position"}),angular.isDefined(k.typeaheadTemplateUrl)&&z.attr("template-url",k.typeaheadTemplateUrl);var A=function(){x.matches=[],x.activeIdx=-1,j.attr("aria-expanded",!1)},B=function(a){return y+"-option-"+a};x.$watch("activeIdx",function(a){0>a?j.removeAttr("aria-activedescendant"):j.attr("aria-activedescendant",B(a))});var C=function(a){var b={$viewValue:a};q(i,!0),c.when(w.source(i,b)).then(function(c){var d=a===l.$viewValue;if(d&&m)if(c.length>0){x.activeIdx=u?0:-1,x.matches.length=0;for(var e=0;e=n?o>0?(F(),E(a)):C(a):(q(i,!1),F(),A()),p?a:a?void l.$setValidity("editable",!1):(l.$setValidity("editable",!0),a)}),l.$formatters.push(function(a){var b,c,d={};return s?(d.$model=a,s(i,d)):(d[w.itemName]=a,b=w.viewMapper(i,d),d[w.itemName]=void 0,c=w.viewMapper(i,d),b!==c?b:a)}),x.select=function(a){var b,c,e={};e[w.itemName]=c=x.matches[a].model,b=w.modelMapper(i,e),v(i,b),l.$setValidity("editable",!0),r(i,{$item:c,$model:b,$label:w.viewMapper(i,e)}),A(),d(function(){j[0].focus()},0,!1)},j.bind("keydown",function(a){0!==x.matches.length&&-1!==h.indexOf(a.which)&&(-1!=x.activeIdx||13!==a.which&&9!==a.which)&&(a.preventDefault(),40===a.which?(x.activeIdx=(x.activeIdx+1)%x.matches.length,x.$digest()):38===a.which?(x.activeIdx=(x.activeIdx>0?x.activeIdx:x.matches.length)-1,x.$digest()):13===a.which||9===a.which?x.$apply(function(){x.select(x.activeIdx)}):27===a.which&&(a.stopPropagation(),A(),x.$digest()))}),j.bind("blur",function(){m=!1});var G=function(a){j[0]!==a.target&&(A(),x.$digest())};e.bind("click",G),i.$on("$destroy",function(){e.unbind("click",G),t&&H.remove()});var H=a(z)(x);t?e.find("body").append(H):j.after(H)}}}]).directive("typeaheadPopup",function(){return{restrict:"EA",scope:{matches:"=",query:"=",active:"=",position:"=",select:"&"},replace:!0,templateUrl:"template/typeahead/typeahead-popup.html",link:function(a,b,c){a.templateUrl=c.templateUrl,a.isOpen=function(){return a.matches.length>0},a.isActive=function(b){return a.active==b},a.selectActive=function(b){a.active=b},a.selectMatch=function(b){a.select({activeIdx:b})}}}}).directive("typeaheadMatch",["$http","$templateCache","$compile","$parse",function(a,b,c,d){return{restrict:"EA",scope:{index:"=",match:"=",query:"="},link:function(e,f,g){var h=d(g.templateUrl)(e.$parent)||"template/typeahead/typeahead-match.html";a.get(h,{cache:b}).success(function(a){f.replaceWith(c(a.trim())(e))})}}}]).filter("typeaheadHighlight",function(){function a(a){return a.replace(/([.?*+^$[\]\\(){}|-])/g,"\\$1")}return function(b,c){return c?(""+b).replace(new RegExp(a(c),"gi"),"$&"):b}}),angular.module("template/accordion/accordion-group.html",[]).run(["$templateCache",function(a){a.put("template/accordion/accordion-group.html",'
      \n
      \n

      \n {{heading}}\n

      \n
      \n
      \n
      \n
      \n
      \n')}]),angular.module("template/accordion/accordion.html",[]).run(["$templateCache",function(a){a.put("template/accordion/accordion.html",'
      ')}]),angular.module("template/alert/alert.html",[]).run(["$templateCache",function(a){a.put("template/alert/alert.html",'\n')}]),angular.module("template/carousel/carousel.html",[]).run(["$templateCache",function(a){a.put("template/carousel/carousel.html",'\n')}]),angular.module("template/carousel/slide.html",[]).run(["$templateCache",function(a){a.put("template/carousel/slide.html","
      \n")}]),angular.module("template/datepicker/datepicker.html",[]).run(["$templateCache",function(a){a.put("template/datepicker/datepicker.html",'
      \n \n \n \n
      ')}]),angular.module("template/datepicker/day.html",[]).run(["$templateCache",function(a){a.put("template/datepicker/day.html",'\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n
      {{label.abbr}}
      {{ weekNumbers[$index] }}\n \n
      \n')}]),angular.module("template/datepicker/month.html",[]).run(["$templateCache",function(a){a.put("template/datepicker/month.html",'\n \n \n \n \n \n \n \n \n \n \n \n \n
      \n \n
      \n')}]),angular.module("template/datepicker/popup.html",[]).run(["$templateCache",function(a){a.put("template/datepicker/popup.html",'\n')}]),angular.module("template/datepicker/year.html",[]).run(["$templateCache",function(a){a.put("template/datepicker/year.html",'\n \n \n \n \n \n \n \n \n \n \n \n \n
      \n \n
      \n')}]),angular.module("template/modal/backdrop.html",[]).run(["$templateCache",function(a){a.put("template/modal/backdrop.html",'\n')}]),angular.module("template/modal/window.html",[]).run(["$templateCache",function(a){a.put("template/modal/window.html",'')}]),angular.module("template/pagination/pager.html",[]).run(["$templateCache",function(a){a.put("template/pagination/pager.html",'')}]),angular.module("template/pagination/pagination.html",[]).run(["$templateCache",function(a){a.put("template/pagination/pagination.html",'')}]),angular.module("template/tooltip/tooltip-html-unsafe-popup.html",[]).run(["$templateCache",function(a){a.put("template/tooltip/tooltip-html-unsafe-popup.html",'
      \n
      \n
      \n
      \n')}]),angular.module("template/tooltip/tooltip-popup.html",[]).run(["$templateCache",function(a){a.put("template/tooltip/tooltip-popup.html",'
      \n
      \n
      \n
      \n')}]),angular.module("template/popover/popover.html",[]).run(["$templateCache",function(a){a.put("template/popover/popover.html",'
      \n
      \n\n
      \n

      \n
      \n
      \n
      \n')}]),angular.module("template/progressbar/bar.html",[]).run(["$templateCache",function(a){a.put("template/progressbar/bar.html",'
      ')}]),angular.module("template/progressbar/progress.html",[]).run(["$templateCache",function(a){a.put("template/progressbar/progress.html",'
      ')}]),angular.module("template/progressbar/progressbar.html",[]).run(["$templateCache",function(a){a.put("template/progressbar/progressbar.html",'
      \n
      \n
      ')}]),angular.module("template/rating/rating.html",[]).run(["$templateCache",function(a){a.put("template/rating/rating.html",'\n \n ({{ $index < value ? \'*\' : \' \' }})\n \n')}]),angular.module("template/tabs/tab.html",[]).run(["$templateCache",function(a){a.put("template/tabs/tab.html",'
    • \n {{heading}}\n
    • \n')}]),angular.module("template/tabs/tabset.html",[]).run(["$templateCache",function(a){a.put("template/tabs/tabset.html",'
      \n \n
      \n
      \n
      \n
      \n
      \n')}]),angular.module("template/timepicker/timepicker.html",[]).run(["$templateCache",function(a){a.put("template/timepicker/timepicker.html",'\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n
       
      \n \n :\n \n
       
      \n')}]),angular.module("template/typeahead/typeahead-match.html",[]).run(["$templateCache",function(a){a.put("template/typeahead/typeahead-match.html",'') +}]),angular.module("template/typeahead/typeahead-popup.html",[]).run(["$templateCache",function(a){a.put("template/typeahead/typeahead-popup.html",'\n')}]); \ No newline at end of file diff --git a/public/admincp/bower_components/angular-bootstrap/ui-bootstrap.js b/public/admincp/bower_components/angular-bootstrap/ui-bootstrap.js new file mode 100644 index 000000000..199597931 --- /dev/null +++ b/public/admincp/bower_components/angular-bootstrap/ui-bootstrap.js @@ -0,0 +1,3901 @@ +/* + * angular-ui-bootstrap + * http://angular-ui.github.io/bootstrap/ + + * Version: 0.12.0 - 2014-11-16 + * License: MIT + */ +angular.module("ui.bootstrap", ["ui.bootstrap.transition","ui.bootstrap.collapse","ui.bootstrap.accordion","ui.bootstrap.alert","ui.bootstrap.bindHtml","ui.bootstrap.buttons","ui.bootstrap.carousel","ui.bootstrap.dateparser","ui.bootstrap.position","ui.bootstrap.datepicker","ui.bootstrap.dropdown","ui.bootstrap.modal","ui.bootstrap.pagination","ui.bootstrap.tooltip","ui.bootstrap.popover","ui.bootstrap.progressbar","ui.bootstrap.rating","ui.bootstrap.tabs","ui.bootstrap.timepicker","ui.bootstrap.typeahead"]); +angular.module('ui.bootstrap.transition', []) + +/** + * $transition service provides a consistent interface to trigger CSS 3 transitions and to be informed when they complete. + * @param {DOMElement} element The DOMElement that will be animated. + * @param {string|object|function} trigger The thing that will cause the transition to start: + * - As a string, it represents the css class to be added to the element. + * - As an object, it represents a hash of style attributes to be applied to the element. + * - As a function, it represents a function to be called that will cause the transition to occur. + * @return {Promise} A promise that is resolved when the transition finishes. + */ +.factory('$transition', ['$q', '$timeout', '$rootScope', function($q, $timeout, $rootScope) { + + var $transition = function(element, trigger, options) { + options = options || {}; + var deferred = $q.defer(); + var endEventName = $transition[options.animation ? 'animationEndEventName' : 'transitionEndEventName']; + + var transitionEndHandler = function(event) { + $rootScope.$apply(function() { + element.unbind(endEventName, transitionEndHandler); + deferred.resolve(element); + }); + }; + + if (endEventName) { + element.bind(endEventName, transitionEndHandler); + } + + // Wrap in a timeout to allow the browser time to update the DOM before the transition is to occur + $timeout(function() { + if ( angular.isString(trigger) ) { + element.addClass(trigger); + } else if ( angular.isFunction(trigger) ) { + trigger(element); + } else if ( angular.isObject(trigger) ) { + element.css(trigger); + } + //If browser does not support transitions, instantly resolve + if ( !endEventName ) { + deferred.resolve(element); + } + }); + + // Add our custom cancel function to the promise that is returned + // We can call this if we are about to run a new transition, which we know will prevent this transition from ending, + // i.e. it will therefore never raise a transitionEnd event for that transition + deferred.promise.cancel = function() { + if ( endEventName ) { + element.unbind(endEventName, transitionEndHandler); + } + deferred.reject('Transition cancelled'); + }; + + return deferred.promise; + }; + + // Work out the name of the transitionEnd event + var transElement = document.createElement('trans'); + var transitionEndEventNames = { + 'WebkitTransition': 'webkitTransitionEnd', + 'MozTransition': 'transitionend', + 'OTransition': 'oTransitionEnd', + 'transition': 'transitionend' + }; + var animationEndEventNames = { + 'WebkitTransition': 'webkitAnimationEnd', + 'MozTransition': 'animationend', + 'OTransition': 'oAnimationEnd', + 'transition': 'animationend' + }; + function findEndEventName(endEventNames) { + for (var name in endEventNames){ + if (transElement.style[name] !== undefined) { + return endEventNames[name]; + } + } + } + $transition.transitionEndEventName = findEndEventName(transitionEndEventNames); + $transition.animationEndEventName = findEndEventName(animationEndEventNames); + return $transition; +}]); + +angular.module('ui.bootstrap.collapse', ['ui.bootstrap.transition']) + + .directive('collapse', ['$transition', function ($transition) { + + return { + link: function (scope, element, attrs) { + + var initialAnimSkip = true; + var currentTransition; + + function doTransition(change) { + var newTransition = $transition(element, change); + if (currentTransition) { + currentTransition.cancel(); + } + currentTransition = newTransition; + newTransition.then(newTransitionDone, newTransitionDone); + return newTransition; + + function newTransitionDone() { + // Make sure it's this transition, otherwise, leave it alone. + if (currentTransition === newTransition) { + currentTransition = undefined; + } + } + } + + function expand() { + if (initialAnimSkip) { + initialAnimSkip = false; + expandDone(); + } else { + element.removeClass('collapse').addClass('collapsing'); + doTransition({ height: element[0].scrollHeight + 'px' }).then(expandDone); + } + } + + function expandDone() { + element.removeClass('collapsing'); + element.addClass('collapse in'); + element.css({height: 'auto'}); + } + + function collapse() { + if (initialAnimSkip) { + initialAnimSkip = false; + collapseDone(); + element.css({height: 0}); + } else { + // CSS transitions don't work with height: auto, so we have to manually change the height to a specific value + element.css({ height: element[0].scrollHeight + 'px' }); + //trigger reflow so a browser realizes that height was updated from auto to a specific value + var x = element[0].offsetWidth; + + element.removeClass('collapse in').addClass('collapsing'); + + doTransition({ height: 0 }).then(collapseDone); + } + } + + function collapseDone() { + element.removeClass('collapsing'); + element.addClass('collapse'); + } + + scope.$watch(attrs.collapse, function (shouldCollapse) { + if (shouldCollapse) { + collapse(); + } else { + expand(); + } + }); + } + }; + }]); + +angular.module('ui.bootstrap.accordion', ['ui.bootstrap.collapse']) + +.constant('accordionConfig', { + closeOthers: true +}) + +.controller('AccordionController', ['$scope', '$attrs', 'accordionConfig', function ($scope, $attrs, accordionConfig) { + + // This array keeps track of the accordion groups + this.groups = []; + + // Ensure that all the groups in this accordion are closed, unless close-others explicitly says not to + this.closeOthers = function(openGroup) { + var closeOthers = angular.isDefined($attrs.closeOthers) ? $scope.$eval($attrs.closeOthers) : accordionConfig.closeOthers; + if ( closeOthers ) { + angular.forEach(this.groups, function (group) { + if ( group !== openGroup ) { + group.isOpen = false; + } + }); + } + }; + + // This is called from the accordion-group directive to add itself to the accordion + this.addGroup = function(groupScope) { + var that = this; + this.groups.push(groupScope); + + groupScope.$on('$destroy', function (event) { + that.removeGroup(groupScope); + }); + }; + + // This is called from the accordion-group directive when to remove itself + this.removeGroup = function(group) { + var index = this.groups.indexOf(group); + if ( index !== -1 ) { + this.groups.splice(index, 1); + } + }; + +}]) + +// The accordion directive simply sets up the directive controller +// and adds an accordion CSS class to itself element. +.directive('accordion', function () { + return { + restrict:'EA', + controller:'AccordionController', + transclude: true, + replace: false, + templateUrl: 'template/accordion/accordion.html' + }; +}) + +// The accordion-group directive indicates a block of html that will expand and collapse in an accordion +.directive('accordionGroup', function() { + return { + require:'^accordion', // We need this directive to be inside an accordion + restrict:'EA', + transclude:true, // It transcludes the contents of the directive into the template + replace: true, // The element containing the directive will be replaced with the template + templateUrl:'template/accordion/accordion-group.html', + scope: { + heading: '@', // Interpolate the heading attribute onto this scope + isOpen: '=?', + isDisabled: '=?' + }, + controller: function() { + this.setHeading = function(element) { + this.heading = element; + }; + }, + link: function(scope, element, attrs, accordionCtrl) { + accordionCtrl.addGroup(scope); + + scope.$watch('isOpen', function(value) { + if ( value ) { + accordionCtrl.closeOthers(scope); + } + }); + + scope.toggleOpen = function() { + if ( !scope.isDisabled ) { + scope.isOpen = !scope.isOpen; + } + }; + } + }; +}) + +// Use accordion-heading below an accordion-group to provide a heading containing HTML +// +// Heading containing HTML - +// +.directive('accordionHeading', function() { + return { + restrict: 'EA', + transclude: true, // Grab the contents to be used as the heading + template: '', // In effect remove this element! + replace: true, + require: '^accordionGroup', + link: function(scope, element, attr, accordionGroupCtrl, transclude) { + // Pass the heading to the accordion-group controller + // so that it can be transcluded into the right place in the template + // [The second parameter to transclude causes the elements to be cloned so that they work in ng-repeat] + accordionGroupCtrl.setHeading(transclude(scope, function() {})); + } + }; +}) + +// Use in the accordion-group template to indicate where you want the heading to be transcluded +// You must provide the property on the accordion-group controller that will hold the transcluded element +//
      +// +// ... +//
      +.directive('accordionTransclude', function() { + return { + require: '^accordionGroup', + link: function(scope, element, attr, controller) { + scope.$watch(function() { return controller[attr.accordionTransclude]; }, function(heading) { + if ( heading ) { + element.html(''); + element.append(heading); + } + }); + } + }; +}); + +angular.module('ui.bootstrap.alert', []) + +.controller('AlertController', ['$scope', '$attrs', function ($scope, $attrs) { + $scope.closeable = 'close' in $attrs; + this.close = $scope.close; +}]) + +.directive('alert', function () { + return { + restrict:'EA', + controller:'AlertController', + templateUrl:'template/alert/alert.html', + transclude:true, + replace:true, + scope: { + type: '@', + close: '&' + } + }; +}) + +.directive('dismissOnTimeout', ['$timeout', function($timeout) { + return { + require: 'alert', + link: function(scope, element, attrs, alertCtrl) { + $timeout(function(){ + alertCtrl.close(); + }, parseInt(attrs.dismissOnTimeout, 10)); + } + }; +}]); + +angular.module('ui.bootstrap.bindHtml', []) + + .directive('bindHtmlUnsafe', function () { + return function (scope, element, attr) { + element.addClass('ng-binding').data('$binding', attr.bindHtmlUnsafe); + scope.$watch(attr.bindHtmlUnsafe, function bindHtmlUnsafeWatchAction(value) { + element.html(value || ''); + }); + }; + }); +angular.module('ui.bootstrap.buttons', []) + +.constant('buttonConfig', { + activeClass: 'active', + toggleEvent: 'click' +}) + +.controller('ButtonsController', ['buttonConfig', function(buttonConfig) { + this.activeClass = buttonConfig.activeClass || 'active'; + this.toggleEvent = buttonConfig.toggleEvent || 'click'; +}]) + +.directive('btnRadio', function () { + return { + require: ['btnRadio', 'ngModel'], + controller: 'ButtonsController', + link: function (scope, element, attrs, ctrls) { + var buttonsCtrl = ctrls[0], ngModelCtrl = ctrls[1]; + + //model -> UI + ngModelCtrl.$render = function () { + element.toggleClass(buttonsCtrl.activeClass, angular.equals(ngModelCtrl.$modelValue, scope.$eval(attrs.btnRadio))); + }; + + //ui->model + element.bind(buttonsCtrl.toggleEvent, function () { + var isActive = element.hasClass(buttonsCtrl.activeClass); + + if (!isActive || angular.isDefined(attrs.uncheckable)) { + scope.$apply(function () { + ngModelCtrl.$setViewValue(isActive ? null : scope.$eval(attrs.btnRadio)); + ngModelCtrl.$render(); + }); + } + }); + } + }; +}) + +.directive('btnCheckbox', function () { + return { + require: ['btnCheckbox', 'ngModel'], + controller: 'ButtonsController', + link: function (scope, element, attrs, ctrls) { + var buttonsCtrl = ctrls[0], ngModelCtrl = ctrls[1]; + + function getTrueValue() { + return getCheckboxValue(attrs.btnCheckboxTrue, true); + } + + function getFalseValue() { + return getCheckboxValue(attrs.btnCheckboxFalse, false); + } + + function getCheckboxValue(attributeValue, defaultValue) { + var val = scope.$eval(attributeValue); + return angular.isDefined(val) ? val : defaultValue; + } + + //model -> UI + ngModelCtrl.$render = function () { + element.toggleClass(buttonsCtrl.activeClass, angular.equals(ngModelCtrl.$modelValue, getTrueValue())); + }; + + //ui->model + element.bind(buttonsCtrl.toggleEvent, function () { + scope.$apply(function () { + ngModelCtrl.$setViewValue(element.hasClass(buttonsCtrl.activeClass) ? getFalseValue() : getTrueValue()); + ngModelCtrl.$render(); + }); + }); + } + }; +}); + +/** +* @ngdoc overview +* @name ui.bootstrap.carousel +* +* @description +* AngularJS version of an image carousel. +* +*/ +angular.module('ui.bootstrap.carousel', ['ui.bootstrap.transition']) +.controller('CarouselController', ['$scope', '$timeout', '$interval', '$transition', function ($scope, $timeout, $interval, $transition) { + var self = this, + slides = self.slides = $scope.slides = [], + currentIndex = -1, + currentInterval, isPlaying; + self.currentSlide = null; + + var destroyed = false; + /* direction: "prev" or "next" */ + self.select = $scope.select = function(nextSlide, direction) { + var nextIndex = slides.indexOf(nextSlide); + //Decide direction if it's not given + if (direction === undefined) { + direction = nextIndex > currentIndex ? 'next' : 'prev'; + } + if (nextSlide && nextSlide !== self.currentSlide) { + if ($scope.$currentTransition) { + $scope.$currentTransition.cancel(); + //Timeout so ng-class in template has time to fix classes for finished slide + $timeout(goNext); + } else { + goNext(); + } + } + function goNext() { + // Scope has been destroyed, stop here. + if (destroyed) { return; } + //If we have a slide to transition from and we have a transition type and we're allowed, go + if (self.currentSlide && angular.isString(direction) && !$scope.noTransition && nextSlide.$element) { + //We shouldn't do class manip in here, but it's the same weird thing bootstrap does. need to fix sometime + nextSlide.$element.addClass(direction); + var reflow = nextSlide.$element[0].offsetWidth; //force reflow + + //Set all other slides to stop doing their stuff for the new transition + angular.forEach(slides, function(slide) { + angular.extend(slide, {direction: '', entering: false, leaving: false, active: false}); + }); + angular.extend(nextSlide, {direction: direction, active: true, entering: true}); + angular.extend(self.currentSlide||{}, {direction: direction, leaving: true}); + + $scope.$currentTransition = $transition(nextSlide.$element, {}); + //We have to create new pointers inside a closure since next & current will change + (function(next,current) { + $scope.$currentTransition.then( + function(){ transitionDone(next, current); }, + function(){ transitionDone(next, current); } + ); + }(nextSlide, self.currentSlide)); + } else { + transitionDone(nextSlide, self.currentSlide); + } + self.currentSlide = nextSlide; + currentIndex = nextIndex; + //every time you change slides, reset the timer + restartTimer(); + } + function transitionDone(next, current) { + angular.extend(next, {direction: '', active: true, leaving: false, entering: false}); + angular.extend(current||{}, {direction: '', active: false, leaving: false, entering: false}); + $scope.$currentTransition = null; + } + }; + $scope.$on('$destroy', function () { + destroyed = true; + }); + + /* Allow outside people to call indexOf on slides array */ + self.indexOfSlide = function(slide) { + return slides.indexOf(slide); + }; + + $scope.next = function() { + var newIndex = (currentIndex + 1) % slides.length; + + //Prevent this user-triggered transition from occurring if there is already one in progress + if (!$scope.$currentTransition) { + return self.select(slides[newIndex], 'next'); + } + }; + + $scope.prev = function() { + var newIndex = currentIndex - 1 < 0 ? slides.length - 1 : currentIndex - 1; + + //Prevent this user-triggered transition from occurring if there is already one in progress + if (!$scope.$currentTransition) { + return self.select(slides[newIndex], 'prev'); + } + }; + + $scope.isActive = function(slide) { + return self.currentSlide === slide; + }; + + $scope.$watch('interval', restartTimer); + $scope.$on('$destroy', resetTimer); + + function restartTimer() { + resetTimer(); + var interval = +$scope.interval; + if (!isNaN(interval) && interval > 0) { + currentInterval = $interval(timerFn, interval); + } + } + + function resetTimer() { + if (currentInterval) { + $interval.cancel(currentInterval); + currentInterval = null; + } + } + + function timerFn() { + var interval = +$scope.interval; + if (isPlaying && !isNaN(interval) && interval > 0) { + $scope.next(); + } else { + $scope.pause(); + } + } + + $scope.play = function() { + if (!isPlaying) { + isPlaying = true; + restartTimer(); + } + }; + $scope.pause = function() { + if (!$scope.noPause) { + isPlaying = false; + resetTimer(); + } + }; + + self.addSlide = function(slide, element) { + slide.$element = element; + slides.push(slide); + //if this is the first slide or the slide is set to active, select it + if(slides.length === 1 || slide.active) { + self.select(slides[slides.length-1]); + if (slides.length == 1) { + $scope.play(); + } + } else { + slide.active = false; + } + }; + + self.removeSlide = function(slide) { + //get the index of the slide inside the carousel + var index = slides.indexOf(slide); + slides.splice(index, 1); + if (slides.length > 0 && slide.active) { + if (index >= slides.length) { + self.select(slides[index-1]); + } else { + self.select(slides[index]); + } + } else if (currentIndex > index) { + currentIndex--; + } + }; + +}]) + +/** + * @ngdoc directive + * @name ui.bootstrap.carousel.directive:carousel + * @restrict EA + * + * @description + * Carousel is the outer container for a set of image 'slides' to showcase. + * + * @param {number=} interval The time, in milliseconds, that it will take the carousel to go to the next slide. + * @param {boolean=} noTransition Whether to disable transitions on the carousel. + * @param {boolean=} noPause Whether to disable pausing on the carousel (by default, the carousel interval pauses on hover). + * + * @example + + + + + + + + + + + + + + + .carousel-indicators { + top: auto; + bottom: 15px; + } + + + */ +.directive('carousel', [function() { + return { + restrict: 'EA', + transclude: true, + replace: true, + controller: 'CarouselController', + require: 'carousel', + templateUrl: 'template/carousel/carousel.html', + scope: { + interval: '=', + noTransition: '=', + noPause: '=' + } + }; +}]) + +/** + * @ngdoc directive + * @name ui.bootstrap.carousel.directive:slide + * @restrict EA + * + * @description + * Creates a slide inside a {@link ui.bootstrap.carousel.directive:carousel carousel}. Must be placed as a child of a carousel element. + * + * @param {boolean=} active Model binding, whether or not this slide is currently active. + * + * @example + + +
      + + + + + + + Interval, in milliseconds: +
      Enter a negative number to stop the interval. +
      +
      + +function CarouselDemoCtrl($scope) { + $scope.myInterval = 5000; +} + + + .carousel-indicators { + top: auto; + bottom: 15px; + } + +
      +*/ + +.directive('slide', function() { + return { + require: '^carousel', + restrict: 'EA', + transclude: true, + replace: true, + templateUrl: 'template/carousel/slide.html', + scope: { + active: '=?' + }, + link: function (scope, element, attrs, carouselCtrl) { + carouselCtrl.addSlide(scope, element); + //when the scope is destroyed then remove the slide from the current slides array + scope.$on('$destroy', function() { + carouselCtrl.removeSlide(scope); + }); + + scope.$watch('active', function(active) { + if (active) { + carouselCtrl.select(scope); + } + }); + } + }; +}); + +angular.module('ui.bootstrap.dateparser', []) + +.service('dateParser', ['$locale', 'orderByFilter', function($locale, orderByFilter) { + + this.parsers = {}; + + var formatCodeToRegex = { + 'yyyy': { + regex: '\\d{4}', + apply: function(value) { this.year = +value; } + }, + 'yy': { + regex: '\\d{2}', + apply: function(value) { this.year = +value + 2000; } + }, + 'y': { + regex: '\\d{1,4}', + apply: function(value) { this.year = +value; } + }, + 'MMMM': { + regex: $locale.DATETIME_FORMATS.MONTH.join('|'), + apply: function(value) { this.month = $locale.DATETIME_FORMATS.MONTH.indexOf(value); } + }, + 'MMM': { + regex: $locale.DATETIME_FORMATS.SHORTMONTH.join('|'), + apply: function(value) { this.month = $locale.DATETIME_FORMATS.SHORTMONTH.indexOf(value); } + }, + 'MM': { + regex: '0[1-9]|1[0-2]', + apply: function(value) { this.month = value - 1; } + }, + 'M': { + regex: '[1-9]|1[0-2]', + apply: function(value) { this.month = value - 1; } + }, + 'dd': { + regex: '[0-2][0-9]{1}|3[0-1]{1}', + apply: function(value) { this.date = +value; } + }, + 'd': { + regex: '[1-2]?[0-9]{1}|3[0-1]{1}', + apply: function(value) { this.date = +value; } + }, + 'EEEE': { + regex: $locale.DATETIME_FORMATS.DAY.join('|') + }, + 'EEE': { + regex: $locale.DATETIME_FORMATS.SHORTDAY.join('|') + } + }; + + function createParser(format) { + var map = [], regex = format.split(''); + + angular.forEach(formatCodeToRegex, function(data, code) { + var index = format.indexOf(code); + + if (index > -1) { + format = format.split(''); + + regex[index] = '(' + data.regex + ')'; + format[index] = '$'; // Custom symbol to define consumed part of format + for (var i = index + 1, n = index + code.length; i < n; i++) { + regex[i] = ''; + format[i] = '$'; + } + format = format.join(''); + + map.push({ index: index, apply: data.apply }); + } + }); + + return { + regex: new RegExp('^' + regex.join('') + '$'), + map: orderByFilter(map, 'index') + }; + } + + this.parse = function(input, format) { + if ( !angular.isString(input) || !format ) { + return input; + } + + format = $locale.DATETIME_FORMATS[format] || format; + + if ( !this.parsers[format] ) { + this.parsers[format] = createParser(format); + } + + var parser = this.parsers[format], + regex = parser.regex, + map = parser.map, + results = input.match(regex); + + if ( results && results.length ) { + var fields = { year: 1900, month: 0, date: 1, hours: 0 }, dt; + + for( var i = 1, n = results.length; i < n; i++ ) { + var mapper = map[i-1]; + if ( mapper.apply ) { + mapper.apply.call(fields, results[i]); + } + } + + if ( isValid(fields.year, fields.month, fields.date) ) { + dt = new Date( fields.year, fields.month, fields.date, fields.hours); + } + + return dt; + } + }; + + // Check if date is valid for specific month (and year for February). + // Month: 0 = Jan, 1 = Feb, etc + function isValid(year, month, date) { + if ( month === 1 && date > 28) { + return date === 29 && ((year % 4 === 0 && year % 100 !== 0) || year % 400 === 0); + } + + if ( month === 3 || month === 5 || month === 8 || month === 10) { + return date < 31; + } + + return true; + } +}]); + +angular.module('ui.bootstrap.position', []) + +/** + * A set of utility methods that can be use to retrieve position of DOM elements. + * It is meant to be used where we need to absolute-position DOM elements in + * relation to other, existing elements (this is the case for tooltips, popovers, + * typeahead suggestions etc.). + */ + .factory('$position', ['$document', '$window', function ($document, $window) { + + function getStyle(el, cssprop) { + if (el.currentStyle) { //IE + return el.currentStyle[cssprop]; + } else if ($window.getComputedStyle) { + return $window.getComputedStyle(el)[cssprop]; + } + // finally try and get inline style + return el.style[cssprop]; + } + + /** + * Checks if a given element is statically positioned + * @param element - raw DOM element + */ + function isStaticPositioned(element) { + return (getStyle(element, 'position') || 'static' ) === 'static'; + } + + /** + * returns the closest, non-statically positioned parentOffset of a given element + * @param element + */ + var parentOffsetEl = function (element) { + var docDomEl = $document[0]; + var offsetParent = element.offsetParent || docDomEl; + while (offsetParent && offsetParent !== docDomEl && isStaticPositioned(offsetParent) ) { + offsetParent = offsetParent.offsetParent; + } + return offsetParent || docDomEl; + }; + + return { + /** + * Provides read-only equivalent of jQuery's position function: + * http://api.jquery.com/position/ + */ + position: function (element) { + var elBCR = this.offset(element); + var offsetParentBCR = { top: 0, left: 0 }; + var offsetParentEl = parentOffsetEl(element[0]); + if (offsetParentEl != $document[0]) { + offsetParentBCR = this.offset(angular.element(offsetParentEl)); + offsetParentBCR.top += offsetParentEl.clientTop - offsetParentEl.scrollTop; + offsetParentBCR.left += offsetParentEl.clientLeft - offsetParentEl.scrollLeft; + } + + var boundingClientRect = element[0].getBoundingClientRect(); + return { + width: boundingClientRect.width || element.prop('offsetWidth'), + height: boundingClientRect.height || element.prop('offsetHeight'), + top: elBCR.top - offsetParentBCR.top, + left: elBCR.left - offsetParentBCR.left + }; + }, + + /** + * Provides read-only equivalent of jQuery's offset function: + * http://api.jquery.com/offset/ + */ + offset: function (element) { + var boundingClientRect = element[0].getBoundingClientRect(); + return { + width: boundingClientRect.width || element.prop('offsetWidth'), + height: boundingClientRect.height || element.prop('offsetHeight'), + top: boundingClientRect.top + ($window.pageYOffset || $document[0].documentElement.scrollTop), + left: boundingClientRect.left + ($window.pageXOffset || $document[0].documentElement.scrollLeft) + }; + }, + + /** + * Provides coordinates for the targetEl in relation to hostEl + */ + positionElements: function (hostEl, targetEl, positionStr, appendToBody) { + + var positionStrParts = positionStr.split('-'); + var pos0 = positionStrParts[0], pos1 = positionStrParts[1] || 'center'; + + var hostElPos, + targetElWidth, + targetElHeight, + targetElPos; + + hostElPos = appendToBody ? this.offset(hostEl) : this.position(hostEl); + + targetElWidth = targetEl.prop('offsetWidth'); + targetElHeight = targetEl.prop('offsetHeight'); + + var shiftWidth = { + center: function () { + return hostElPos.left + hostElPos.width / 2 - targetElWidth / 2; + }, + left: function () { + return hostElPos.left; + }, + right: function () { + return hostElPos.left + hostElPos.width; + } + }; + + var shiftHeight = { + center: function () { + return hostElPos.top + hostElPos.height / 2 - targetElHeight / 2; + }, + top: function () { + return hostElPos.top; + }, + bottom: function () { + return hostElPos.top + hostElPos.height; + } + }; + + switch (pos0) { + case 'right': + targetElPos = { + top: shiftHeight[pos1](), + left: shiftWidth[pos0]() + }; + break; + case 'left': + targetElPos = { + top: shiftHeight[pos1](), + left: hostElPos.left - targetElWidth + }; + break; + case 'bottom': + targetElPos = { + top: shiftHeight[pos0](), + left: shiftWidth[pos1]() + }; + break; + default: + targetElPos = { + top: hostElPos.top - targetElHeight, + left: shiftWidth[pos1]() + }; + break; + } + + return targetElPos; + } + }; + }]); + +angular.module('ui.bootstrap.datepicker', ['ui.bootstrap.dateparser', 'ui.bootstrap.position']) + +.constant('datepickerConfig', { + formatDay: 'dd', + formatMonth: 'MMMM', + formatYear: 'yyyy', + formatDayHeader: 'EEE', + formatDayTitle: 'MMMM yyyy', + formatMonthTitle: 'yyyy', + datepickerMode: 'day', + minMode: 'day', + maxMode: 'year', + showWeeks: true, + startingDay: 0, + yearRange: 20, + minDate: null, + maxDate: null +}) + +.controller('DatepickerController', ['$scope', '$attrs', '$parse', '$interpolate', '$timeout', '$log', 'dateFilter', 'datepickerConfig', function($scope, $attrs, $parse, $interpolate, $timeout, $log, dateFilter, datepickerConfig) { + var self = this, + ngModelCtrl = { $setViewValue: angular.noop }; // nullModelCtrl; + + // Modes chain + this.modes = ['day', 'month', 'year']; + + // Configuration attributes + angular.forEach(['formatDay', 'formatMonth', 'formatYear', 'formatDayHeader', 'formatDayTitle', 'formatMonthTitle', + 'minMode', 'maxMode', 'showWeeks', 'startingDay', 'yearRange'], function( key, index ) { + self[key] = angular.isDefined($attrs[key]) ? (index < 8 ? $interpolate($attrs[key])($scope.$parent) : $scope.$parent.$eval($attrs[key])) : datepickerConfig[key]; + }); + + // Watchable date attributes + angular.forEach(['minDate', 'maxDate'], function( key ) { + if ( $attrs[key] ) { + $scope.$parent.$watch($parse($attrs[key]), function(value) { + self[key] = value ? new Date(value) : null; + self.refreshView(); + }); + } else { + self[key] = datepickerConfig[key] ? new Date(datepickerConfig[key]) : null; + } + }); + + $scope.datepickerMode = $scope.datepickerMode || datepickerConfig.datepickerMode; + $scope.uniqueId = 'datepicker-' + $scope.$id + '-' + Math.floor(Math.random() * 10000); + this.activeDate = angular.isDefined($attrs.initDate) ? $scope.$parent.$eval($attrs.initDate) : new Date(); + + $scope.isActive = function(dateObject) { + if (self.compare(dateObject.date, self.activeDate) === 0) { + $scope.activeDateId = dateObject.uid; + return true; + } + return false; + }; + + this.init = function( ngModelCtrl_ ) { + ngModelCtrl = ngModelCtrl_; + + ngModelCtrl.$render = function() { + self.render(); + }; + }; + + this.render = function() { + if ( ngModelCtrl.$modelValue ) { + var date = new Date( ngModelCtrl.$modelValue ), + isValid = !isNaN(date); + + if ( isValid ) { + this.activeDate = date; + } else { + $log.error('Datepicker directive: "ng-model" value must be a Date object, a number of milliseconds since 01.01.1970 or a string representing an RFC2822 or ISO 8601 date.'); + } + ngModelCtrl.$setValidity('date', isValid); + } + this.refreshView(); + }; + + this.refreshView = function() { + if ( this.element ) { + this._refreshView(); + + var date = ngModelCtrl.$modelValue ? new Date(ngModelCtrl.$modelValue) : null; + ngModelCtrl.$setValidity('date-disabled', !date || (this.element && !this.isDisabled(date))); + } + }; + + this.createDateObject = function(date, format) { + var model = ngModelCtrl.$modelValue ? new Date(ngModelCtrl.$modelValue) : null; + return { + date: date, + label: dateFilter(date, format), + selected: model && this.compare(date, model) === 0, + disabled: this.isDisabled(date), + current: this.compare(date, new Date()) === 0 + }; + }; + + this.isDisabled = function( date ) { + return ((this.minDate && this.compare(date, this.minDate) < 0) || (this.maxDate && this.compare(date, this.maxDate) > 0) || ($attrs.dateDisabled && $scope.dateDisabled({date: date, mode: $scope.datepickerMode}))); + }; + + // Split array into smaller arrays + this.split = function(arr, size) { + var arrays = []; + while (arr.length > 0) { + arrays.push(arr.splice(0, size)); + } + return arrays; + }; + + $scope.select = function( date ) { + if ( $scope.datepickerMode === self.minMode ) { + var dt = ngModelCtrl.$modelValue ? new Date( ngModelCtrl.$modelValue ) : new Date(0, 0, 0, 0, 0, 0, 0); + dt.setFullYear( date.getFullYear(), date.getMonth(), date.getDate() ); + ngModelCtrl.$setViewValue( dt ); + ngModelCtrl.$render(); + } else { + self.activeDate = date; + $scope.datepickerMode = self.modes[ self.modes.indexOf( $scope.datepickerMode ) - 1 ]; + } + }; + + $scope.move = function( direction ) { + var year = self.activeDate.getFullYear() + direction * (self.step.years || 0), + month = self.activeDate.getMonth() + direction * (self.step.months || 0); + self.activeDate.setFullYear(year, month, 1); + self.refreshView(); + }; + + $scope.toggleMode = function( direction ) { + direction = direction || 1; + + if (($scope.datepickerMode === self.maxMode && direction === 1) || ($scope.datepickerMode === self.minMode && direction === -1)) { + return; + } + + $scope.datepickerMode = self.modes[ self.modes.indexOf( $scope.datepickerMode ) + direction ]; + }; + + // Key event mapper + $scope.keys = { 13:'enter', 32:'space', 33:'pageup', 34:'pagedown', 35:'end', 36:'home', 37:'left', 38:'up', 39:'right', 40:'down' }; + + var focusElement = function() { + $timeout(function() { + self.element[0].focus(); + }, 0 , false); + }; + + // Listen for focus requests from popup directive + $scope.$on('datepicker.focus', focusElement); + + $scope.keydown = function( evt ) { + var key = $scope.keys[evt.which]; + + if ( !key || evt.shiftKey || evt.altKey ) { + return; + } + + evt.preventDefault(); + evt.stopPropagation(); + + if (key === 'enter' || key === 'space') { + if ( self.isDisabled(self.activeDate)) { + return; // do nothing + } + $scope.select(self.activeDate); + focusElement(); + } else if (evt.ctrlKey && (key === 'up' || key === 'down')) { + $scope.toggleMode(key === 'up' ? 1 : -1); + focusElement(); + } else { + self.handleKeyDown(key, evt); + self.refreshView(); + } + }; +}]) + +.directive( 'datepicker', function () { + return { + restrict: 'EA', + replace: true, + templateUrl: 'template/datepicker/datepicker.html', + scope: { + datepickerMode: '=?', + dateDisabled: '&' + }, + require: ['datepicker', '?^ngModel'], + controller: 'DatepickerController', + link: function(scope, element, attrs, ctrls) { + var datepickerCtrl = ctrls[0], ngModelCtrl = ctrls[1]; + + if ( ngModelCtrl ) { + datepickerCtrl.init( ngModelCtrl ); + } + } + }; +}) + +.directive('daypicker', ['dateFilter', function (dateFilter) { + return { + restrict: 'EA', + replace: true, + templateUrl: 'template/datepicker/day.html', + require: '^datepicker', + link: function(scope, element, attrs, ctrl) { + scope.showWeeks = ctrl.showWeeks; + + ctrl.step = { months: 1 }; + ctrl.element = element; + + var DAYS_IN_MONTH = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]; + function getDaysInMonth( year, month ) { + return ((month === 1) && (year % 4 === 0) && ((year % 100 !== 0) || (year % 400 === 0))) ? 29 : DAYS_IN_MONTH[month]; + } + + function getDates(startDate, n) { + var dates = new Array(n), current = new Date(startDate), i = 0; + current.setHours(12); // Prevent repeated dates because of timezone bug + while ( i < n ) { + dates[i++] = new Date(current); + current.setDate( current.getDate() + 1 ); + } + return dates; + } + + ctrl._refreshView = function() { + var year = ctrl.activeDate.getFullYear(), + month = ctrl.activeDate.getMonth(), + firstDayOfMonth = new Date(year, month, 1), + difference = ctrl.startingDay - firstDayOfMonth.getDay(), + numDisplayedFromPreviousMonth = (difference > 0) ? 7 - difference : - difference, + firstDate = new Date(firstDayOfMonth); + + if ( numDisplayedFromPreviousMonth > 0 ) { + firstDate.setDate( - numDisplayedFromPreviousMonth + 1 ); + } + + // 42 is the number of days on a six-month calendar + var days = getDates(firstDate, 42); + for (var i = 0; i < 42; i ++) { + days[i] = angular.extend(ctrl.createDateObject(days[i], ctrl.formatDay), { + secondary: days[i].getMonth() !== month, + uid: scope.uniqueId + '-' + i + }); + } + + scope.labels = new Array(7); + for (var j = 0; j < 7; j++) { + scope.labels[j] = { + abbr: dateFilter(days[j].date, ctrl.formatDayHeader), + full: dateFilter(days[j].date, 'EEEE') + }; + } + + scope.title = dateFilter(ctrl.activeDate, ctrl.formatDayTitle); + scope.rows = ctrl.split(days, 7); + + if ( scope.showWeeks ) { + scope.weekNumbers = []; + var weekNumber = getISO8601WeekNumber( scope.rows[0][0].date ), + numWeeks = scope.rows.length; + while( scope.weekNumbers.push(weekNumber++) < numWeeks ) {} + } + }; + + ctrl.compare = function(date1, date2) { + return (new Date( date1.getFullYear(), date1.getMonth(), date1.getDate() ) - new Date( date2.getFullYear(), date2.getMonth(), date2.getDate() ) ); + }; + + function getISO8601WeekNumber(date) { + var checkDate = new Date(date); + checkDate.setDate(checkDate.getDate() + 4 - (checkDate.getDay() || 7)); // Thursday + var time = checkDate.getTime(); + checkDate.setMonth(0); // Compare with Jan 1 + checkDate.setDate(1); + return Math.floor(Math.round((time - checkDate) / 86400000) / 7) + 1; + } + + ctrl.handleKeyDown = function( key, evt ) { + var date = ctrl.activeDate.getDate(); + + if (key === 'left') { + date = date - 1; // up + } else if (key === 'up') { + date = date - 7; // down + } else if (key === 'right') { + date = date + 1; // down + } else if (key === 'down') { + date = date + 7; + } else if (key === 'pageup' || key === 'pagedown') { + var month = ctrl.activeDate.getMonth() + (key === 'pageup' ? - 1 : 1); + ctrl.activeDate.setMonth(month, 1); + date = Math.min(getDaysInMonth(ctrl.activeDate.getFullYear(), ctrl.activeDate.getMonth()), date); + } else if (key === 'home') { + date = 1; + } else if (key === 'end') { + date = getDaysInMonth(ctrl.activeDate.getFullYear(), ctrl.activeDate.getMonth()); + } + ctrl.activeDate.setDate(date); + }; + + ctrl.refreshView(); + } + }; +}]) + +.directive('monthpicker', ['dateFilter', function (dateFilter) { + return { + restrict: 'EA', + replace: true, + templateUrl: 'template/datepicker/month.html', + require: '^datepicker', + link: function(scope, element, attrs, ctrl) { + ctrl.step = { years: 1 }; + ctrl.element = element; + + ctrl._refreshView = function() { + var months = new Array(12), + year = ctrl.activeDate.getFullYear(); + + for ( var i = 0; i < 12; i++ ) { + months[i] = angular.extend(ctrl.createDateObject(new Date(year, i, 1), ctrl.formatMonth), { + uid: scope.uniqueId + '-' + i + }); + } + + scope.title = dateFilter(ctrl.activeDate, ctrl.formatMonthTitle); + scope.rows = ctrl.split(months, 3); + }; + + ctrl.compare = function(date1, date2) { + return new Date( date1.getFullYear(), date1.getMonth() ) - new Date( date2.getFullYear(), date2.getMonth() ); + }; + + ctrl.handleKeyDown = function( key, evt ) { + var date = ctrl.activeDate.getMonth(); + + if (key === 'left') { + date = date - 1; // up + } else if (key === 'up') { + date = date - 3; // down + } else if (key === 'right') { + date = date + 1; // down + } else if (key === 'down') { + date = date + 3; + } else if (key === 'pageup' || key === 'pagedown') { + var year = ctrl.activeDate.getFullYear() + (key === 'pageup' ? - 1 : 1); + ctrl.activeDate.setFullYear(year); + } else if (key === 'home') { + date = 0; + } else if (key === 'end') { + date = 11; + } + ctrl.activeDate.setMonth(date); + }; + + ctrl.refreshView(); + } + }; +}]) + +.directive('yearpicker', ['dateFilter', function (dateFilter) { + return { + restrict: 'EA', + replace: true, + templateUrl: 'template/datepicker/year.html', + require: '^datepicker', + link: function(scope, element, attrs, ctrl) { + var range = ctrl.yearRange; + + ctrl.step = { years: range }; + ctrl.element = element; + + function getStartingYear( year ) { + return parseInt((year - 1) / range, 10) * range + 1; + } + + ctrl._refreshView = function() { + var years = new Array(range); + + for ( var i = 0, start = getStartingYear(ctrl.activeDate.getFullYear()); i < range; i++ ) { + years[i] = angular.extend(ctrl.createDateObject(new Date(start + i, 0, 1), ctrl.formatYear), { + uid: scope.uniqueId + '-' + i + }); + } + + scope.title = [years[0].label, years[range - 1].label].join(' - '); + scope.rows = ctrl.split(years, 5); + }; + + ctrl.compare = function(date1, date2) { + return date1.getFullYear() - date2.getFullYear(); + }; + + ctrl.handleKeyDown = function( key, evt ) { + var date = ctrl.activeDate.getFullYear(); + + if (key === 'left') { + date = date - 1; // up + } else if (key === 'up') { + date = date - 5; // down + } else if (key === 'right') { + date = date + 1; // down + } else if (key === 'down') { + date = date + 5; + } else if (key === 'pageup' || key === 'pagedown') { + date += (key === 'pageup' ? - 1 : 1) * ctrl.step.years; + } else if (key === 'home') { + date = getStartingYear( ctrl.activeDate.getFullYear() ); + } else if (key === 'end') { + date = getStartingYear( ctrl.activeDate.getFullYear() ) + range - 1; + } + ctrl.activeDate.setFullYear(date); + }; + + ctrl.refreshView(); + } + }; +}]) + +.constant('datepickerPopupConfig', { + datepickerPopup: 'yyyy-MM-dd', + currentText: 'Today', + clearText: 'Clear', + closeText: 'Done', + closeOnDateSelection: true, + appendToBody: false, + showButtonBar: true +}) + +.directive('datepickerPopup', ['$compile', '$parse', '$document', '$position', 'dateFilter', 'dateParser', 'datepickerPopupConfig', +function ($compile, $parse, $document, $position, dateFilter, dateParser, datepickerPopupConfig) { + return { + restrict: 'EA', + require: 'ngModel', + scope: { + isOpen: '=?', + currentText: '@', + clearText: '@', + closeText: '@', + dateDisabled: '&' + }, + link: function(scope, element, attrs, ngModel) { + var dateFormat, + closeOnDateSelection = angular.isDefined(attrs.closeOnDateSelection) ? scope.$parent.$eval(attrs.closeOnDateSelection) : datepickerPopupConfig.closeOnDateSelection, + appendToBody = angular.isDefined(attrs.datepickerAppendToBody) ? scope.$parent.$eval(attrs.datepickerAppendToBody) : datepickerPopupConfig.appendToBody; + + scope.showButtonBar = angular.isDefined(attrs.showButtonBar) ? scope.$parent.$eval(attrs.showButtonBar) : datepickerPopupConfig.showButtonBar; + + scope.getText = function( key ) { + return scope[key + 'Text'] || datepickerPopupConfig[key + 'Text']; + }; + + attrs.$observe('datepickerPopup', function(value) { + dateFormat = value || datepickerPopupConfig.datepickerPopup; + ngModel.$render(); + }); + + // popup element used to display calendar + var popupEl = angular.element('
      '); + popupEl.attr({ + 'ng-model': 'date', + 'ng-change': 'dateSelection()' + }); + + function cameltoDash( string ){ + return string.replace(/([A-Z])/g, function($1) { return '-' + $1.toLowerCase(); }); + } + + // datepicker element + var datepickerEl = angular.element(popupEl.children()[0]); + if ( attrs.datepickerOptions ) { + angular.forEach(scope.$parent.$eval(attrs.datepickerOptions), function( value, option ) { + datepickerEl.attr( cameltoDash(option), value ); + }); + } + + scope.watchData = {}; + angular.forEach(['minDate', 'maxDate', 'datepickerMode'], function( key ) { + if ( attrs[key] ) { + var getAttribute = $parse(attrs[key]); + scope.$parent.$watch(getAttribute, function(value){ + scope.watchData[key] = value; + }); + datepickerEl.attr(cameltoDash(key), 'watchData.' + key); + + // Propagate changes from datepicker to outside + if ( key === 'datepickerMode' ) { + var setAttribute = getAttribute.assign; + scope.$watch('watchData.' + key, function(value, oldvalue) { + if ( value !== oldvalue ) { + setAttribute(scope.$parent, value); + } + }); + } + } + }); + if (attrs.dateDisabled) { + datepickerEl.attr('date-disabled', 'dateDisabled({ date: date, mode: mode })'); + } + + function parseDate(viewValue) { + if (!viewValue) { + ngModel.$setValidity('date', true); + return null; + } else if (angular.isDate(viewValue) && !isNaN(viewValue)) { + ngModel.$setValidity('date', true); + return viewValue; + } else if (angular.isString(viewValue)) { + var date = dateParser.parse(viewValue, dateFormat) || new Date(viewValue); + if (isNaN(date)) { + ngModel.$setValidity('date', false); + return undefined; + } else { + ngModel.$setValidity('date', true); + return date; + } + } else { + ngModel.$setValidity('date', false); + return undefined; + } + } + ngModel.$parsers.unshift(parseDate); + + // Inner change + scope.dateSelection = function(dt) { + if (angular.isDefined(dt)) { + scope.date = dt; + } + ngModel.$setViewValue(scope.date); + ngModel.$render(); + + if ( closeOnDateSelection ) { + scope.isOpen = false; + element[0].focus(); + } + }; + + element.bind('input change keyup', function() { + scope.$apply(function() { + scope.date = ngModel.$modelValue; + }); + }); + + // Outter change + ngModel.$render = function() { + var date = ngModel.$viewValue ? dateFilter(ngModel.$viewValue, dateFormat) : ''; + element.val(date); + scope.date = parseDate( ngModel.$modelValue ); + }; + + var documentClickBind = function(event) { + if (scope.isOpen && event.target !== element[0]) { + scope.$apply(function() { + scope.isOpen = false; + }); + } + }; + + var keydown = function(evt, noApply) { + scope.keydown(evt); + }; + element.bind('keydown', keydown); + + scope.keydown = function(evt) { + if (evt.which === 27) { + evt.preventDefault(); + evt.stopPropagation(); + scope.close(); + } else if (evt.which === 40 && !scope.isOpen) { + scope.isOpen = true; + } + }; + + scope.$watch('isOpen', function(value) { + if (value) { + scope.$broadcast('datepicker.focus'); + scope.position = appendToBody ? $position.offset(element) : $position.position(element); + scope.position.top = scope.position.top + element.prop('offsetHeight'); + + $document.bind('click', documentClickBind); + } else { + $document.unbind('click', documentClickBind); + } + }); + + scope.select = function( date ) { + if (date === 'today') { + var today = new Date(); + if (angular.isDate(ngModel.$modelValue)) { + date = new Date(ngModel.$modelValue); + date.setFullYear(today.getFullYear(), today.getMonth(), today.getDate()); + } else { + date = new Date(today.setHours(0, 0, 0, 0)); + } + } + scope.dateSelection( date ); + }; + + scope.close = function() { + scope.isOpen = false; + element[0].focus(); + }; + + var $popup = $compile(popupEl)(scope); + // Prevent jQuery cache memory leak (template is now redundant after linking) + popupEl.remove(); + + if ( appendToBody ) { + $document.find('body').append($popup); + } else { + element.after($popup); + } + + scope.$on('$destroy', function() { + $popup.remove(); + element.unbind('keydown', keydown); + $document.unbind('click', documentClickBind); + }); + } + }; +}]) + +.directive('datepickerPopupWrap', function() { + return { + restrict:'EA', + replace: true, + transclude: true, + templateUrl: 'template/datepicker/popup.html', + link:function (scope, element, attrs) { + element.bind('click', function(event) { + event.preventDefault(); + event.stopPropagation(); + }); + } + }; +}); + +angular.module('ui.bootstrap.dropdown', []) + +.constant('dropdownConfig', { + openClass: 'open' +}) + +.service('dropdownService', ['$document', function($document) { + var openScope = null; + + this.open = function( dropdownScope ) { + if ( !openScope ) { + $document.bind('click', closeDropdown); + $document.bind('keydown', escapeKeyBind); + } + + if ( openScope && openScope !== dropdownScope ) { + openScope.isOpen = false; + } + + openScope = dropdownScope; + }; + + this.close = function( dropdownScope ) { + if ( openScope === dropdownScope ) { + openScope = null; + $document.unbind('click', closeDropdown); + $document.unbind('keydown', escapeKeyBind); + } + }; + + var closeDropdown = function( evt ) { + // This method may still be called during the same mouse event that + // unbound this event handler. So check openScope before proceeding. + if (!openScope) { return; } + + var toggleElement = openScope.getToggleElement(); + if ( evt && toggleElement && toggleElement[0].contains(evt.target) ) { + return; + } + + openScope.$apply(function() { + openScope.isOpen = false; + }); + }; + + var escapeKeyBind = function( evt ) { + if ( evt.which === 27 ) { + openScope.focusToggleElement(); + closeDropdown(); + } + }; +}]) + +.controller('DropdownController', ['$scope', '$attrs', '$parse', 'dropdownConfig', 'dropdownService', '$animate', function($scope, $attrs, $parse, dropdownConfig, dropdownService, $animate) { + var self = this, + scope = $scope.$new(), // create a child scope so we are not polluting original one + openClass = dropdownConfig.openClass, + getIsOpen, + setIsOpen = angular.noop, + toggleInvoker = $attrs.onToggle ? $parse($attrs.onToggle) : angular.noop; + + this.init = function( element ) { + self.$element = element; + + if ( $attrs.isOpen ) { + getIsOpen = $parse($attrs.isOpen); + setIsOpen = getIsOpen.assign; + + $scope.$watch(getIsOpen, function(value) { + scope.isOpen = !!value; + }); + } + }; + + this.toggle = function( open ) { + return scope.isOpen = arguments.length ? !!open : !scope.isOpen; + }; + + // Allow other directives to watch status + this.isOpen = function() { + return scope.isOpen; + }; + + scope.getToggleElement = function() { + return self.toggleElement; + }; + + scope.focusToggleElement = function() { + if ( self.toggleElement ) { + self.toggleElement[0].focus(); + } + }; + + scope.$watch('isOpen', function( isOpen, wasOpen ) { + $animate[isOpen ? 'addClass' : 'removeClass'](self.$element, openClass); + + if ( isOpen ) { + scope.focusToggleElement(); + dropdownService.open( scope ); + } else { + dropdownService.close( scope ); + } + + setIsOpen($scope, isOpen); + if (angular.isDefined(isOpen) && isOpen !== wasOpen) { + toggleInvoker($scope, { open: !!isOpen }); + } + }); + + $scope.$on('$locationChangeSuccess', function() { + scope.isOpen = false; + }); + + $scope.$on('$destroy', function() { + scope.$destroy(); + }); +}]) + +.directive('dropdown', function() { + return { + controller: 'DropdownController', + link: function(scope, element, attrs, dropdownCtrl) { + dropdownCtrl.init( element ); + } + }; +}) + +.directive('dropdownToggle', function() { + return { + require: '?^dropdown', + link: function(scope, element, attrs, dropdownCtrl) { + if ( !dropdownCtrl ) { + return; + } + + dropdownCtrl.toggleElement = element; + + var toggleDropdown = function(event) { + event.preventDefault(); + + if ( !element.hasClass('disabled') && !attrs.disabled ) { + scope.$apply(function() { + dropdownCtrl.toggle(); + }); + } + }; + + element.bind('click', toggleDropdown); + + // WAI-ARIA + element.attr({ 'aria-haspopup': true, 'aria-expanded': false }); + scope.$watch(dropdownCtrl.isOpen, function( isOpen ) { + element.attr('aria-expanded', !!isOpen); + }); + + scope.$on('$destroy', function() { + element.unbind('click', toggleDropdown); + }); + } + }; +}); + +angular.module('ui.bootstrap.modal', ['ui.bootstrap.transition']) + +/** + * A helper, internal data structure that acts as a map but also allows getting / removing + * elements in the LIFO order + */ + .factory('$$stackedMap', function () { + return { + createNew: function () { + var stack = []; + + return { + add: function (key, value) { + stack.push({ + key: key, + value: value + }); + }, + get: function (key) { + for (var i = 0; i < stack.length; i++) { + if (key == stack[i].key) { + return stack[i]; + } + } + }, + keys: function() { + var keys = []; + for (var i = 0; i < stack.length; i++) { + keys.push(stack[i].key); + } + return keys; + }, + top: function () { + return stack[stack.length - 1]; + }, + remove: function (key) { + var idx = -1; + for (var i = 0; i < stack.length; i++) { + if (key == stack[i].key) { + idx = i; + break; + } + } + return stack.splice(idx, 1)[0]; + }, + removeTop: function () { + return stack.splice(stack.length - 1, 1)[0]; + }, + length: function () { + return stack.length; + } + }; + } + }; + }) + +/** + * A helper directive for the $modal service. It creates a backdrop element. + */ + .directive('modalBackdrop', ['$timeout', function ($timeout) { + return { + restrict: 'EA', + replace: true, + templateUrl: 'template/modal/backdrop.html', + link: function (scope, element, attrs) { + scope.backdropClass = attrs.backdropClass || ''; + + scope.animate = false; + + //trigger CSS transitions + $timeout(function () { + scope.animate = true; + }); + } + }; + }]) + + .directive('modalWindow', ['$modalStack', '$timeout', function ($modalStack, $timeout) { + return { + restrict: 'EA', + scope: { + index: '@', + animate: '=' + }, + replace: true, + transclude: true, + templateUrl: function(tElement, tAttrs) { + return tAttrs.templateUrl || 'template/modal/window.html'; + }, + link: function (scope, element, attrs) { + element.addClass(attrs.windowClass || ''); + scope.size = attrs.size; + + $timeout(function () { + // trigger CSS transitions + scope.animate = true; + + /** + * Auto-focusing of a freshly-opened modal element causes any child elements + * with the autofocus attribute to lose focus. This is an issue on touch + * based devices which will show and then hide the onscreen keyboard. + * Attempts to refocus the autofocus element via JavaScript will not reopen + * the onscreen keyboard. Fixed by updated the focusing logic to only autofocus + * the modal element if the modal does not contain an autofocus element. + */ + if (!element[0].querySelectorAll('[autofocus]').length) { + element[0].focus(); + } + }); + + scope.close = function (evt) { + var modal = $modalStack.getTop(); + if (modal && modal.value.backdrop && modal.value.backdrop != 'static' && (evt.target === evt.currentTarget)) { + evt.preventDefault(); + evt.stopPropagation(); + $modalStack.dismiss(modal.key, 'backdrop click'); + } + }; + } + }; + }]) + + .directive('modalTransclude', function () { + return { + link: function($scope, $element, $attrs, controller, $transclude) { + $transclude($scope.$parent, function(clone) { + $element.empty(); + $element.append(clone); + }); + } + }; + }) + + .factory('$modalStack', ['$transition', '$timeout', '$document', '$compile', '$rootScope', '$$stackedMap', + function ($transition, $timeout, $document, $compile, $rootScope, $$stackedMap) { + + var OPENED_MODAL_CLASS = 'modal-open'; + + var backdropDomEl, backdropScope; + var openedWindows = $$stackedMap.createNew(); + var $modalStack = {}; + + function backdropIndex() { + var topBackdropIndex = -1; + var opened = openedWindows.keys(); + for (var i = 0; i < opened.length; i++) { + if (openedWindows.get(opened[i]).value.backdrop) { + topBackdropIndex = i; + } + } + return topBackdropIndex; + } + + $rootScope.$watch(backdropIndex, function(newBackdropIndex){ + if (backdropScope) { + backdropScope.index = newBackdropIndex; + } + }); + + function removeModalWindow(modalInstance) { + + var body = $document.find('body').eq(0); + var modalWindow = openedWindows.get(modalInstance).value; + + //clean up the stack + openedWindows.remove(modalInstance); + + //remove window DOM element + removeAfterAnimate(modalWindow.modalDomEl, modalWindow.modalScope, 300, function() { + modalWindow.modalScope.$destroy(); + body.toggleClass(OPENED_MODAL_CLASS, openedWindows.length() > 0); + checkRemoveBackdrop(); + }); + } + + function checkRemoveBackdrop() { + //remove backdrop if no longer needed + if (backdropDomEl && backdropIndex() == -1) { + var backdropScopeRef = backdropScope; + removeAfterAnimate(backdropDomEl, backdropScope, 150, function () { + backdropScopeRef.$destroy(); + backdropScopeRef = null; + }); + backdropDomEl = undefined; + backdropScope = undefined; + } + } + + function removeAfterAnimate(domEl, scope, emulateTime, done) { + // Closing animation + scope.animate = false; + + var transitionEndEventName = $transition.transitionEndEventName; + if (transitionEndEventName) { + // transition out + var timeout = $timeout(afterAnimating, emulateTime); + + domEl.bind(transitionEndEventName, function () { + $timeout.cancel(timeout); + afterAnimating(); + scope.$apply(); + }); + } else { + // Ensure this call is async + $timeout(afterAnimating); + } + + function afterAnimating() { + if (afterAnimating.done) { + return; + } + afterAnimating.done = true; + + domEl.remove(); + if (done) { + done(); + } + } + } + + $document.bind('keydown', function (evt) { + var modal; + + if (evt.which === 27) { + modal = openedWindows.top(); + if (modal && modal.value.keyboard) { + evt.preventDefault(); + $rootScope.$apply(function () { + $modalStack.dismiss(modal.key, 'escape key press'); + }); + } + } + }); + + $modalStack.open = function (modalInstance, modal) { + + openedWindows.add(modalInstance, { + deferred: modal.deferred, + modalScope: modal.scope, + backdrop: modal.backdrop, + keyboard: modal.keyboard + }); + + var body = $document.find('body').eq(0), + currBackdropIndex = backdropIndex(); + + if (currBackdropIndex >= 0 && !backdropDomEl) { + backdropScope = $rootScope.$new(true); + backdropScope.index = currBackdropIndex; + var angularBackgroundDomEl = angular.element('
      '); + angularBackgroundDomEl.attr('backdrop-class', modal.backdropClass); + backdropDomEl = $compile(angularBackgroundDomEl)(backdropScope); + body.append(backdropDomEl); + } + + var angularDomEl = angular.element('
      '); + angularDomEl.attr({ + 'template-url': modal.windowTemplateUrl, + 'window-class': modal.windowClass, + 'size': modal.size, + 'index': openedWindows.length() - 1, + 'animate': 'animate' + }).html(modal.content); + + var modalDomEl = $compile(angularDomEl)(modal.scope); + openedWindows.top().value.modalDomEl = modalDomEl; + body.append(modalDomEl); + body.addClass(OPENED_MODAL_CLASS); + }; + + $modalStack.close = function (modalInstance, result) { + var modalWindow = openedWindows.get(modalInstance); + if (modalWindow) { + modalWindow.value.deferred.resolve(result); + removeModalWindow(modalInstance); + } + }; + + $modalStack.dismiss = function (modalInstance, reason) { + var modalWindow = openedWindows.get(modalInstance); + if (modalWindow) { + modalWindow.value.deferred.reject(reason); + removeModalWindow(modalInstance); + } + }; + + $modalStack.dismissAll = function (reason) { + var topModal = this.getTop(); + while (topModal) { + this.dismiss(topModal.key, reason); + topModal = this.getTop(); + } + }; + + $modalStack.getTop = function () { + return openedWindows.top(); + }; + + return $modalStack; + }]) + + .provider('$modal', function () { + + var $modalProvider = { + options: { + backdrop: true, //can be also false or 'static' + keyboard: true + }, + $get: ['$injector', '$rootScope', '$q', '$http', '$templateCache', '$controller', '$modalStack', + function ($injector, $rootScope, $q, $http, $templateCache, $controller, $modalStack) { + + var $modal = {}; + + function getTemplatePromise(options) { + return options.template ? $q.when(options.template) : + $http.get(angular.isFunction(options.templateUrl) ? (options.templateUrl)() : options.templateUrl, + {cache: $templateCache}).then(function (result) { + return result.data; + }); + } + + function getResolvePromises(resolves) { + var promisesArr = []; + angular.forEach(resolves, function (value) { + if (angular.isFunction(value) || angular.isArray(value)) { + promisesArr.push($q.when($injector.invoke(value))); + } + }); + return promisesArr; + } + + $modal.open = function (modalOptions) { + + var modalResultDeferred = $q.defer(); + var modalOpenedDeferred = $q.defer(); + + //prepare an instance of a modal to be injected into controllers and returned to a caller + var modalInstance = { + result: modalResultDeferred.promise, + opened: modalOpenedDeferred.promise, + close: function (result) { + $modalStack.close(modalInstance, result); + }, + dismiss: function (reason) { + $modalStack.dismiss(modalInstance, reason); + } + }; + + //merge and clean up options + modalOptions = angular.extend({}, $modalProvider.options, modalOptions); + modalOptions.resolve = modalOptions.resolve || {}; + + //verify options + if (!modalOptions.template && !modalOptions.templateUrl) { + throw new Error('One of template or templateUrl options is required.'); + } + + var templateAndResolvePromise = + $q.all([getTemplatePromise(modalOptions)].concat(getResolvePromises(modalOptions.resolve))); + + + templateAndResolvePromise.then(function resolveSuccess(tplAndVars) { + + var modalScope = (modalOptions.scope || $rootScope).$new(); + modalScope.$close = modalInstance.close; + modalScope.$dismiss = modalInstance.dismiss; + + var ctrlInstance, ctrlLocals = {}; + var resolveIter = 1; + + //controllers + if (modalOptions.controller) { + ctrlLocals.$scope = modalScope; + ctrlLocals.$modalInstance = modalInstance; + angular.forEach(modalOptions.resolve, function (value, key) { + ctrlLocals[key] = tplAndVars[resolveIter++]; + }); + + ctrlInstance = $controller(modalOptions.controller, ctrlLocals); + if (modalOptions.controllerAs) { + modalScope[modalOptions.controllerAs] = ctrlInstance; + } + } + + $modalStack.open(modalInstance, { + scope: modalScope, + deferred: modalResultDeferred, + content: tplAndVars[0], + backdrop: modalOptions.backdrop, + keyboard: modalOptions.keyboard, + backdropClass: modalOptions.backdropClass, + windowClass: modalOptions.windowClass, + windowTemplateUrl: modalOptions.windowTemplateUrl, + size: modalOptions.size + }); + + }, function resolveError(reason) { + modalResultDeferred.reject(reason); + }); + + templateAndResolvePromise.then(function () { + modalOpenedDeferred.resolve(true); + }, function () { + modalOpenedDeferred.reject(false); + }); + + return modalInstance; + }; + + return $modal; + }] + }; + + return $modalProvider; + }); + +angular.module('ui.bootstrap.pagination', []) + +.controller('PaginationController', ['$scope', '$attrs', '$parse', function ($scope, $attrs, $parse) { + var self = this, + ngModelCtrl = { $setViewValue: angular.noop }, // nullModelCtrl + setNumPages = $attrs.numPages ? $parse($attrs.numPages).assign : angular.noop; + + this.init = function(ngModelCtrl_, config) { + ngModelCtrl = ngModelCtrl_; + this.config = config; + + ngModelCtrl.$render = function() { + self.render(); + }; + + if ($attrs.itemsPerPage) { + $scope.$parent.$watch($parse($attrs.itemsPerPage), function(value) { + self.itemsPerPage = parseInt(value, 10); + $scope.totalPages = self.calculateTotalPages(); + }); + } else { + this.itemsPerPage = config.itemsPerPage; + } + }; + + this.calculateTotalPages = function() { + var totalPages = this.itemsPerPage < 1 ? 1 : Math.ceil($scope.totalItems / this.itemsPerPage); + return Math.max(totalPages || 0, 1); + }; + + this.render = function() { + $scope.page = parseInt(ngModelCtrl.$viewValue, 10) || 1; + }; + + $scope.selectPage = function(page) { + if ( $scope.page !== page && page > 0 && page <= $scope.totalPages) { + ngModelCtrl.$setViewValue(page); + ngModelCtrl.$render(); + } + }; + + $scope.getText = function( key ) { + return $scope[key + 'Text'] || self.config[key + 'Text']; + }; + $scope.noPrevious = function() { + return $scope.page === 1; + }; + $scope.noNext = function() { + return $scope.page === $scope.totalPages; + }; + + $scope.$watch('totalItems', function() { + $scope.totalPages = self.calculateTotalPages(); + }); + + $scope.$watch('totalPages', function(value) { + setNumPages($scope.$parent, value); // Readonly variable + + if ( $scope.page > value ) { + $scope.selectPage(value); + } else { + ngModelCtrl.$render(); + } + }); +}]) + +.constant('paginationConfig', { + itemsPerPage: 10, + boundaryLinks: false, + directionLinks: true, + firstText: 'First', + previousText: 'Previous', + nextText: 'Next', + lastText: 'Last', + rotate: true +}) + +.directive('pagination', ['$parse', 'paginationConfig', function($parse, paginationConfig) { + return { + restrict: 'EA', + scope: { + totalItems: '=', + firstText: '@', + previousText: '@', + nextText: '@', + lastText: '@' + }, + require: ['pagination', '?ngModel'], + controller: 'PaginationController', + templateUrl: 'template/pagination/pagination.html', + replace: true, + link: function(scope, element, attrs, ctrls) { + var paginationCtrl = ctrls[0], ngModelCtrl = ctrls[1]; + + if (!ngModelCtrl) { + return; // do nothing if no ng-model + } + + // Setup configuration parameters + var maxSize = angular.isDefined(attrs.maxSize) ? scope.$parent.$eval(attrs.maxSize) : paginationConfig.maxSize, + rotate = angular.isDefined(attrs.rotate) ? scope.$parent.$eval(attrs.rotate) : paginationConfig.rotate; + scope.boundaryLinks = angular.isDefined(attrs.boundaryLinks) ? scope.$parent.$eval(attrs.boundaryLinks) : paginationConfig.boundaryLinks; + scope.directionLinks = angular.isDefined(attrs.directionLinks) ? scope.$parent.$eval(attrs.directionLinks) : paginationConfig.directionLinks; + + paginationCtrl.init(ngModelCtrl, paginationConfig); + + if (attrs.maxSize) { + scope.$parent.$watch($parse(attrs.maxSize), function(value) { + maxSize = parseInt(value, 10); + paginationCtrl.render(); + }); + } + + // Create page object used in template + function makePage(number, text, isActive) { + return { + number: number, + text: text, + active: isActive + }; + } + + function getPages(currentPage, totalPages) { + var pages = []; + + // Default page limits + var startPage = 1, endPage = totalPages; + var isMaxSized = ( angular.isDefined(maxSize) && maxSize < totalPages ); + + // recompute if maxSize + if ( isMaxSized ) { + if ( rotate ) { + // Current page is displayed in the middle of the visible ones + startPage = Math.max(currentPage - Math.floor(maxSize/2), 1); + endPage = startPage + maxSize - 1; + + // Adjust if limit is exceeded + if (endPage > totalPages) { + endPage = totalPages; + startPage = endPage - maxSize + 1; + } + } else { + // Visible pages are paginated with maxSize + startPage = ((Math.ceil(currentPage / maxSize) - 1) * maxSize) + 1; + + // Adjust last page if limit is exceeded + endPage = Math.min(startPage + maxSize - 1, totalPages); + } + } + + // Add page number links + for (var number = startPage; number <= endPage; number++) { + var page = makePage(number, number, number === currentPage); + pages.push(page); + } + + // Add links to move between page sets + if ( isMaxSized && ! rotate ) { + if ( startPage > 1 ) { + var previousPageSet = makePage(startPage - 1, '...', false); + pages.unshift(previousPageSet); + } + + if ( endPage < totalPages ) { + var nextPageSet = makePage(endPage + 1, '...', false); + pages.push(nextPageSet); + } + } + + return pages; + } + + var originalRender = paginationCtrl.render; + paginationCtrl.render = function() { + originalRender(); + if (scope.page > 0 && scope.page <= scope.totalPages) { + scope.pages = getPages(scope.page, scope.totalPages); + } + }; + } + }; +}]) + +.constant('pagerConfig', { + itemsPerPage: 10, + previousText: '« Previous', + nextText: 'Next »', + align: true +}) + +.directive('pager', ['pagerConfig', function(pagerConfig) { + return { + restrict: 'EA', + scope: { + totalItems: '=', + previousText: '@', + nextText: '@' + }, + require: ['pager', '?ngModel'], + controller: 'PaginationController', + templateUrl: 'template/pagination/pager.html', + replace: true, + link: function(scope, element, attrs, ctrls) { + var paginationCtrl = ctrls[0], ngModelCtrl = ctrls[1]; + + if (!ngModelCtrl) { + return; // do nothing if no ng-model + } + + scope.align = angular.isDefined(attrs.align) ? scope.$parent.$eval(attrs.align) : pagerConfig.align; + paginationCtrl.init(ngModelCtrl, pagerConfig); + } + }; +}]); + +/** + * The following features are still outstanding: animation as a + * function, placement as a function, inside, support for more triggers than + * just mouse enter/leave, html tooltips, and selector delegation. + */ +angular.module( 'ui.bootstrap.tooltip', [ 'ui.bootstrap.position', 'ui.bootstrap.bindHtml' ] ) + +/** + * The $tooltip service creates tooltip- and popover-like directives as well as + * houses global options for them. + */ +.provider( '$tooltip', function () { + // The default options tooltip and popover. + var defaultOptions = { + placement: 'top', + animation: true, + popupDelay: 0 + }; + + // Default hide triggers for each show trigger + var triggerMap = { + 'mouseenter': 'mouseleave', + 'click': 'click', + 'focus': 'blur' + }; + + // The options specified to the provider globally. + var globalOptions = {}; + + /** + * `options({})` allows global configuration of all tooltips in the + * application. + * + * var app = angular.module( 'App', ['ui.bootstrap.tooltip'], function( $tooltipProvider ) { + * // place tooltips left instead of top by default + * $tooltipProvider.options( { placement: 'left' } ); + * }); + */ + this.options = function( value ) { + angular.extend( globalOptions, value ); + }; + + /** + * This allows you to extend the set of trigger mappings available. E.g.: + * + * $tooltipProvider.setTriggers( 'openTrigger': 'closeTrigger' ); + */ + this.setTriggers = function setTriggers ( triggers ) { + angular.extend( triggerMap, triggers ); + }; + + /** + * This is a helper function for translating camel-case to snake-case. + */ + function snake_case(name){ + var regexp = /[A-Z]/g; + var separator = '-'; + return name.replace(regexp, function(letter, pos) { + return (pos ? separator : '') + letter.toLowerCase(); + }); + } + + /** + * Returns the actual instance of the $tooltip service. + * TODO support multiple triggers + */ + this.$get = [ '$window', '$compile', '$timeout', '$document', '$position', '$interpolate', function ( $window, $compile, $timeout, $document, $position, $interpolate ) { + return function $tooltip ( type, prefix, defaultTriggerShow ) { + var options = angular.extend( {}, defaultOptions, globalOptions ); + + /** + * Returns an object of show and hide triggers. + * + * If a trigger is supplied, + * it is used to show the tooltip; otherwise, it will use the `trigger` + * option passed to the `$tooltipProvider.options` method; else it will + * default to the trigger supplied to this directive factory. + * + * The hide trigger is based on the show trigger. If the `trigger` option + * was passed to the `$tooltipProvider.options` method, it will use the + * mapped trigger from `triggerMap` or the passed trigger if the map is + * undefined; otherwise, it uses the `triggerMap` value of the show + * trigger; else it will just use the show trigger. + */ + function getTriggers ( trigger ) { + var show = trigger || options.trigger || defaultTriggerShow; + var hide = triggerMap[show] || show; + return { + show: show, + hide: hide + }; + } + + var directiveName = snake_case( type ); + + var startSym = $interpolate.startSymbol(); + var endSym = $interpolate.endSymbol(); + var template = + '
      '+ + '
      '; + + return { + restrict: 'EA', + compile: function (tElem, tAttrs) { + var tooltipLinker = $compile( template ); + + return function link ( scope, element, attrs ) { + var tooltip; + var tooltipLinkedScope; + var transitionTimeout; + var popupTimeout; + var appendToBody = angular.isDefined( options.appendToBody ) ? options.appendToBody : false; + var triggers = getTriggers( undefined ); + var hasEnableExp = angular.isDefined(attrs[prefix+'Enable']); + var ttScope = scope.$new(true); + + var positionTooltip = function () { + + var ttPosition = $position.positionElements(element, tooltip, ttScope.placement, appendToBody); + ttPosition.top += 'px'; + ttPosition.left += 'px'; + + // Now set the calculated positioning. + tooltip.css( ttPosition ); + }; + + // By default, the tooltip is not open. + // TODO add ability to start tooltip opened + ttScope.isOpen = false; + + function toggleTooltipBind () { + if ( ! ttScope.isOpen ) { + showTooltipBind(); + } else { + hideTooltipBind(); + } + } + + // Show the tooltip with delay if specified, otherwise show it immediately + function showTooltipBind() { + if(hasEnableExp && !scope.$eval(attrs[prefix+'Enable'])) { + return; + } + + prepareTooltip(); + + if ( ttScope.popupDelay ) { + // Do nothing if the tooltip was already scheduled to pop-up. + // This happens if show is triggered multiple times before any hide is triggered. + if (!popupTimeout) { + popupTimeout = $timeout( show, ttScope.popupDelay, false ); + popupTimeout.then(function(reposition){reposition();}); + } + } else { + show()(); + } + } + + function hideTooltipBind () { + scope.$apply(function () { + hide(); + }); + } + + // Show the tooltip popup element. + function show() { + + popupTimeout = null; + + // If there is a pending remove transition, we must cancel it, lest the + // tooltip be mysteriously removed. + if ( transitionTimeout ) { + $timeout.cancel( transitionTimeout ); + transitionTimeout = null; + } + + // Don't show empty tooltips. + if ( ! ttScope.content ) { + return angular.noop; + } + + createTooltip(); + + // Set the initial positioning. + tooltip.css({ top: 0, left: 0, display: 'block' }); + + // Now we add it to the DOM because need some info about it. But it's not + // visible yet anyway. + if ( appendToBody ) { + $document.find( 'body' ).append( tooltip ); + } else { + element.after( tooltip ); + } + + positionTooltip(); + + // And show the tooltip. + ttScope.isOpen = true; + ttScope.$digest(); // digest required as $apply is not called + + // Return positioning function as promise callback for correct + // positioning after draw. + return positionTooltip; + } + + // Hide the tooltip popup element. + function hide() { + // First things first: we don't show it anymore. + ttScope.isOpen = false; + + //if tooltip is going to be shown after delay, we must cancel this + $timeout.cancel( popupTimeout ); + popupTimeout = null; + + // And now we remove it from the DOM. However, if we have animation, we + // need to wait for it to expire beforehand. + // FIXME: this is a placeholder for a port of the transitions library. + if ( ttScope.animation ) { + if (!transitionTimeout) { + transitionTimeout = $timeout(removeTooltip, 500); + } + } else { + removeTooltip(); + } + } + + function createTooltip() { + // There can only be one tooltip element per directive shown at once. + if (tooltip) { + removeTooltip(); + } + tooltipLinkedScope = ttScope.$new(); + tooltip = tooltipLinker(tooltipLinkedScope, angular.noop); + } + + function removeTooltip() { + transitionTimeout = null; + if (tooltip) { + tooltip.remove(); + tooltip = null; + } + if (tooltipLinkedScope) { + tooltipLinkedScope.$destroy(); + tooltipLinkedScope = null; + } + } + + function prepareTooltip() { + prepPlacement(); + prepPopupDelay(); + } + + /** + * Observe the relevant attributes. + */ + attrs.$observe( type, function ( val ) { + ttScope.content = val; + + if (!val && ttScope.isOpen ) { + hide(); + } + }); + + attrs.$observe( prefix+'Title', function ( val ) { + ttScope.title = val; + }); + + function prepPlacement() { + var val = attrs[ prefix + 'Placement' ]; + ttScope.placement = angular.isDefined( val ) ? val : options.placement; + } + + function prepPopupDelay() { + var val = attrs[ prefix + 'PopupDelay' ]; + var delay = parseInt( val, 10 ); + ttScope.popupDelay = ! isNaN(delay) ? delay : options.popupDelay; + } + + var unregisterTriggers = function () { + element.unbind(triggers.show, showTooltipBind); + element.unbind(triggers.hide, hideTooltipBind); + }; + + function prepTriggers() { + var val = attrs[ prefix + 'Trigger' ]; + unregisterTriggers(); + + triggers = getTriggers( val ); + + if ( triggers.show === triggers.hide ) { + element.bind( triggers.show, toggleTooltipBind ); + } else { + element.bind( triggers.show, showTooltipBind ); + element.bind( triggers.hide, hideTooltipBind ); + } + } + prepTriggers(); + + var animation = scope.$eval(attrs[prefix + 'Animation']); + ttScope.animation = angular.isDefined(animation) ? !!animation : options.animation; + + var appendToBodyVal = scope.$eval(attrs[prefix + 'AppendToBody']); + appendToBody = angular.isDefined(appendToBodyVal) ? appendToBodyVal : appendToBody; + + // if a tooltip is attached to we need to remove it on + // location change as its parent scope will probably not be destroyed + // by the change. + if ( appendToBody ) { + scope.$on('$locationChangeSuccess', function closeTooltipOnLocationChangeSuccess () { + if ( ttScope.isOpen ) { + hide(); + } + }); + } + + // Make sure tooltip is destroyed and removed. + scope.$on('$destroy', function onDestroyTooltip() { + $timeout.cancel( transitionTimeout ); + $timeout.cancel( popupTimeout ); + unregisterTriggers(); + removeTooltip(); + ttScope = null; + }); + }; + } + }; + }; + }]; +}) + +.directive( 'tooltipPopup', function () { + return { + restrict: 'EA', + replace: true, + scope: { content: '@', placement: '@', animation: '&', isOpen: '&' }, + templateUrl: 'template/tooltip/tooltip-popup.html' + }; +}) + +.directive( 'tooltip', [ '$tooltip', function ( $tooltip ) { + return $tooltip( 'tooltip', 'tooltip', 'mouseenter' ); +}]) + +.directive( 'tooltipHtmlUnsafePopup', function () { + return { + restrict: 'EA', + replace: true, + scope: { content: '@', placement: '@', animation: '&', isOpen: '&' }, + templateUrl: 'template/tooltip/tooltip-html-unsafe-popup.html' + }; +}) + +.directive( 'tooltipHtmlUnsafe', [ '$tooltip', function ( $tooltip ) { + return $tooltip( 'tooltipHtmlUnsafe', 'tooltip', 'mouseenter' ); +}]); + +/** + * The following features are still outstanding: popup delay, animation as a + * function, placement as a function, inside, support for more triggers than + * just mouse enter/leave, html popovers, and selector delegatation. + */ +angular.module( 'ui.bootstrap.popover', [ 'ui.bootstrap.tooltip' ] ) + +.directive( 'popoverPopup', function () { + return { + restrict: 'EA', + replace: true, + scope: { title: '@', content: '@', placement: '@', animation: '&', isOpen: '&' }, + templateUrl: 'template/popover/popover.html' + }; +}) + +.directive( 'popover', [ '$tooltip', function ( $tooltip ) { + return $tooltip( 'popover', 'popover', 'click' ); +}]); + +angular.module('ui.bootstrap.progressbar', []) + +.constant('progressConfig', { + animate: true, + max: 100 +}) + +.controller('ProgressController', ['$scope', '$attrs', 'progressConfig', function($scope, $attrs, progressConfig) { + var self = this, + animate = angular.isDefined($attrs.animate) ? $scope.$parent.$eval($attrs.animate) : progressConfig.animate; + + this.bars = []; + $scope.max = angular.isDefined($attrs.max) ? $scope.$parent.$eval($attrs.max) : progressConfig.max; + + this.addBar = function(bar, element) { + if ( !animate ) { + element.css({'transition': 'none'}); + } + + this.bars.push(bar); + + bar.$watch('value', function( value ) { + bar.percent = +(100 * value / $scope.max).toFixed(2); + }); + + bar.$on('$destroy', function() { + element = null; + self.removeBar(bar); + }); + }; + + this.removeBar = function(bar) { + this.bars.splice(this.bars.indexOf(bar), 1); + }; +}]) + +.directive('progress', function() { + return { + restrict: 'EA', + replace: true, + transclude: true, + controller: 'ProgressController', + require: 'progress', + scope: {}, + templateUrl: 'template/progressbar/progress.html' + }; +}) + +.directive('bar', function() { + return { + restrict: 'EA', + replace: true, + transclude: true, + require: '^progress', + scope: { + value: '=', + type: '@' + }, + templateUrl: 'template/progressbar/bar.html', + link: function(scope, element, attrs, progressCtrl) { + progressCtrl.addBar(scope, element); + } + }; +}) + +.directive('progressbar', function() { + return { + restrict: 'EA', + replace: true, + transclude: true, + controller: 'ProgressController', + scope: { + value: '=', + type: '@' + }, + templateUrl: 'template/progressbar/progressbar.html', + link: function(scope, element, attrs, progressCtrl) { + progressCtrl.addBar(scope, angular.element(element.children()[0])); + } + }; +}); +angular.module('ui.bootstrap.rating', []) + +.constant('ratingConfig', { + max: 5, + stateOn: null, + stateOff: null +}) + +.controller('RatingController', ['$scope', '$attrs', 'ratingConfig', function($scope, $attrs, ratingConfig) { + var ngModelCtrl = { $setViewValue: angular.noop }; + + this.init = function(ngModelCtrl_) { + ngModelCtrl = ngModelCtrl_; + ngModelCtrl.$render = this.render; + + this.stateOn = angular.isDefined($attrs.stateOn) ? $scope.$parent.$eval($attrs.stateOn) : ratingConfig.stateOn; + this.stateOff = angular.isDefined($attrs.stateOff) ? $scope.$parent.$eval($attrs.stateOff) : ratingConfig.stateOff; + + var ratingStates = angular.isDefined($attrs.ratingStates) ? $scope.$parent.$eval($attrs.ratingStates) : + new Array( angular.isDefined($attrs.max) ? $scope.$parent.$eval($attrs.max) : ratingConfig.max ); + $scope.range = this.buildTemplateObjects(ratingStates); + }; + + this.buildTemplateObjects = function(states) { + for (var i = 0, n = states.length; i < n; i++) { + states[i] = angular.extend({ index: i }, { stateOn: this.stateOn, stateOff: this.stateOff }, states[i]); + } + return states; + }; + + $scope.rate = function(value) { + if ( !$scope.readonly && value >= 0 && value <= $scope.range.length ) { + ngModelCtrl.$setViewValue(value); + ngModelCtrl.$render(); + } + }; + + $scope.enter = function(value) { + if ( !$scope.readonly ) { + $scope.value = value; + } + $scope.onHover({value: value}); + }; + + $scope.reset = function() { + $scope.value = ngModelCtrl.$viewValue; + $scope.onLeave(); + }; + + $scope.onKeydown = function(evt) { + if (/(37|38|39|40)/.test(evt.which)) { + evt.preventDefault(); + evt.stopPropagation(); + $scope.rate( $scope.value + (evt.which === 38 || evt.which === 39 ? 1 : -1) ); + } + }; + + this.render = function() { + $scope.value = ngModelCtrl.$viewValue; + }; +}]) + +.directive('rating', function() { + return { + restrict: 'EA', + require: ['rating', 'ngModel'], + scope: { + readonly: '=?', + onHover: '&', + onLeave: '&' + }, + controller: 'RatingController', + templateUrl: 'template/rating/rating.html', + replace: true, + link: function(scope, element, attrs, ctrls) { + var ratingCtrl = ctrls[0], ngModelCtrl = ctrls[1]; + + if ( ngModelCtrl ) { + ratingCtrl.init( ngModelCtrl ); + } + } + }; +}); + +/** + * @ngdoc overview + * @name ui.bootstrap.tabs + * + * @description + * AngularJS version of the tabs directive. + */ + +angular.module('ui.bootstrap.tabs', []) + +.controller('TabsetController', ['$scope', function TabsetCtrl($scope) { + var ctrl = this, + tabs = ctrl.tabs = $scope.tabs = []; + + ctrl.select = function(selectedTab) { + angular.forEach(tabs, function(tab) { + if (tab.active && tab !== selectedTab) { + tab.active = false; + tab.onDeselect(); + } + }); + selectedTab.active = true; + selectedTab.onSelect(); + }; + + ctrl.addTab = function addTab(tab) { + tabs.push(tab); + // we can't run the select function on the first tab + // since that would select it twice + if (tabs.length === 1) { + tab.active = true; + } else if (tab.active) { + ctrl.select(tab); + } + }; + + ctrl.removeTab = function removeTab(tab) { + var index = tabs.indexOf(tab); + //Select a new tab if the tab to be removed is selected and not destroyed + if (tab.active && tabs.length > 1 && !destroyed) { + //If this is the last tab, select the previous tab. else, the next tab. + var newActiveIndex = index == tabs.length - 1 ? index - 1 : index + 1; + ctrl.select(tabs[newActiveIndex]); + } + tabs.splice(index, 1); + }; + + var destroyed; + $scope.$on('$destroy', function() { + destroyed = true; + }); +}]) + +/** + * @ngdoc directive + * @name ui.bootstrap.tabs.directive:tabset + * @restrict EA + * + * @description + * Tabset is the outer container for the tabs directive + * + * @param {boolean=} vertical Whether or not to use vertical styling for the tabs. + * @param {boolean=} justified Whether or not to use justified styling for the tabs. + * + * @example + + + + First Content! + Second Content! + +
      + + First Vertical Content! + Second Vertical Content! + + + First Justified Content! + Second Justified Content! + +
      +
      + */ +.directive('tabset', function() { + return { + restrict: 'EA', + transclude: true, + replace: true, + scope: { + type: '@' + }, + controller: 'TabsetController', + templateUrl: 'template/tabs/tabset.html', + link: function(scope, element, attrs) { + scope.vertical = angular.isDefined(attrs.vertical) ? scope.$parent.$eval(attrs.vertical) : false; + scope.justified = angular.isDefined(attrs.justified) ? scope.$parent.$eval(attrs.justified) : false; + } + }; +}) + +/** + * @ngdoc directive + * @name ui.bootstrap.tabs.directive:tab + * @restrict EA + * + * @param {string=} heading The visible heading, or title, of the tab. Set HTML headings with {@link ui.bootstrap.tabs.directive:tabHeading tabHeading}. + * @param {string=} select An expression to evaluate when the tab is selected. + * @param {boolean=} active A binding, telling whether or not this tab is selected. + * @param {boolean=} disabled A binding, telling whether or not this tab is disabled. + * + * @description + * Creates a tab with a heading and content. Must be placed within a {@link ui.bootstrap.tabs.directive:tabset tabset}. + * + * @example + + +
      + + +
      + + First Tab + + Alert me! + Second Tab, with alert callback and html heading! + + + {{item.content}} + + +
      +
      + + function TabsDemoCtrl($scope) { + $scope.items = [ + { title:"Dynamic Title 1", content:"Dynamic Item 0" }, + { title:"Dynamic Title 2", content:"Dynamic Item 1", disabled: true } + ]; + + $scope.alertMe = function() { + setTimeout(function() { + alert("You've selected the alert tab!"); + }); + }; + }; + +
      + */ + +/** + * @ngdoc directive + * @name ui.bootstrap.tabs.directive:tabHeading + * @restrict EA + * + * @description + * Creates an HTML heading for a {@link ui.bootstrap.tabs.directive:tab tab}. Must be placed as a child of a tab element. + * + * @example + + + + + HTML in my titles?! + And some content, too! + + + Icon heading?!? + That's right. + + + + + */ +.directive('tab', ['$parse', function($parse) { + return { + require: '^tabset', + restrict: 'EA', + replace: true, + templateUrl: 'template/tabs/tab.html', + transclude: true, + scope: { + active: '=?', + heading: '@', + onSelect: '&select', //This callback is called in contentHeadingTransclude + //once it inserts the tab's content into the dom + onDeselect: '&deselect' + }, + controller: function() { + //Empty controller so other directives can require being 'under' a tab + }, + compile: function(elm, attrs, transclude) { + return function postLink(scope, elm, attrs, tabsetCtrl) { + scope.$watch('active', function(active) { + if (active) { + tabsetCtrl.select(scope); + } + }); + + scope.disabled = false; + if ( attrs.disabled ) { + scope.$parent.$watch($parse(attrs.disabled), function(value) { + scope.disabled = !! value; + }); + } + + scope.select = function() { + if ( !scope.disabled ) { + scope.active = true; + } + }; + + tabsetCtrl.addTab(scope); + scope.$on('$destroy', function() { + tabsetCtrl.removeTab(scope); + }); + + //We need to transclude later, once the content container is ready. + //when this link happens, we're inside a tab heading. + scope.$transcludeFn = transclude; + }; + } + }; +}]) + +.directive('tabHeadingTransclude', [function() { + return { + restrict: 'A', + require: '^tab', + link: function(scope, elm, attrs, tabCtrl) { + scope.$watch('headingElement', function updateHeadingElement(heading) { + if (heading) { + elm.html(''); + elm.append(heading); + } + }); + } + }; +}]) + +.directive('tabContentTransclude', function() { + return { + restrict: 'A', + require: '^tabset', + link: function(scope, elm, attrs) { + var tab = scope.$eval(attrs.tabContentTransclude); + + //Now our tab is ready to be transcluded: both the tab heading area + //and the tab content area are loaded. Transclude 'em both. + tab.$transcludeFn(tab.$parent, function(contents) { + angular.forEach(contents, function(node) { + if (isTabHeading(node)) { + //Let tabHeadingTransclude know. + tab.headingElement = node; + } else { + elm.append(node); + } + }); + }); + } + }; + function isTabHeading(node) { + return node.tagName && ( + node.hasAttribute('tab-heading') || + node.hasAttribute('data-tab-heading') || + node.tagName.toLowerCase() === 'tab-heading' || + node.tagName.toLowerCase() === 'data-tab-heading' + ); + } +}) + +; + +angular.module('ui.bootstrap.timepicker', []) + +.constant('timepickerConfig', { + hourStep: 1, + minuteStep: 1, + showMeridian: true, + meridians: null, + readonlyInput: false, + mousewheel: true +}) + +.controller('TimepickerController', ['$scope', '$attrs', '$parse', '$log', '$locale', 'timepickerConfig', function($scope, $attrs, $parse, $log, $locale, timepickerConfig) { + var selected = new Date(), + ngModelCtrl = { $setViewValue: angular.noop }, // nullModelCtrl + meridians = angular.isDefined($attrs.meridians) ? $scope.$parent.$eval($attrs.meridians) : timepickerConfig.meridians || $locale.DATETIME_FORMATS.AMPMS; + + this.init = function( ngModelCtrl_, inputs ) { + ngModelCtrl = ngModelCtrl_; + ngModelCtrl.$render = this.render; + + var hoursInputEl = inputs.eq(0), + minutesInputEl = inputs.eq(1); + + var mousewheel = angular.isDefined($attrs.mousewheel) ? $scope.$parent.$eval($attrs.mousewheel) : timepickerConfig.mousewheel; + if ( mousewheel ) { + this.setupMousewheelEvents( hoursInputEl, minutesInputEl ); + } + + $scope.readonlyInput = angular.isDefined($attrs.readonlyInput) ? $scope.$parent.$eval($attrs.readonlyInput) : timepickerConfig.readonlyInput; + this.setupInputEvents( hoursInputEl, minutesInputEl ); + }; + + var hourStep = timepickerConfig.hourStep; + if ($attrs.hourStep) { + $scope.$parent.$watch($parse($attrs.hourStep), function(value) { + hourStep = parseInt(value, 10); + }); + } + + var minuteStep = timepickerConfig.minuteStep; + if ($attrs.minuteStep) { + $scope.$parent.$watch($parse($attrs.minuteStep), function(value) { + minuteStep = parseInt(value, 10); + }); + } + + // 12H / 24H mode + $scope.showMeridian = timepickerConfig.showMeridian; + if ($attrs.showMeridian) { + $scope.$parent.$watch($parse($attrs.showMeridian), function(value) { + $scope.showMeridian = !!value; + + if ( ngModelCtrl.$error.time ) { + // Evaluate from template + var hours = getHoursFromTemplate(), minutes = getMinutesFromTemplate(); + if (angular.isDefined( hours ) && angular.isDefined( minutes )) { + selected.setHours( hours ); + refresh(); + } + } else { + updateTemplate(); + } + }); + } + + // Get $scope.hours in 24H mode if valid + function getHoursFromTemplate ( ) { + var hours = parseInt( $scope.hours, 10 ); + var valid = ( $scope.showMeridian ) ? (hours > 0 && hours < 13) : (hours >= 0 && hours < 24); + if ( !valid ) { + return undefined; + } + + if ( $scope.showMeridian ) { + if ( hours === 12 ) { + hours = 0; + } + if ( $scope.meridian === meridians[1] ) { + hours = hours + 12; + } + } + return hours; + } + + function getMinutesFromTemplate() { + var minutes = parseInt($scope.minutes, 10); + return ( minutes >= 0 && minutes < 60 ) ? minutes : undefined; + } + + function pad( value ) { + return ( angular.isDefined(value) && value.toString().length < 2 ) ? '0' + value : value; + } + + // Respond on mousewheel spin + this.setupMousewheelEvents = function( hoursInputEl, minutesInputEl ) { + var isScrollingUp = function(e) { + if (e.originalEvent) { + e = e.originalEvent; + } + //pick correct delta variable depending on event + var delta = (e.wheelDelta) ? e.wheelDelta : -e.deltaY; + return (e.detail || delta > 0); + }; + + hoursInputEl.bind('mousewheel wheel', function(e) { + $scope.$apply( (isScrollingUp(e)) ? $scope.incrementHours() : $scope.decrementHours() ); + e.preventDefault(); + }); + + minutesInputEl.bind('mousewheel wheel', function(e) { + $scope.$apply( (isScrollingUp(e)) ? $scope.incrementMinutes() : $scope.decrementMinutes() ); + e.preventDefault(); + }); + + }; + + this.setupInputEvents = function( hoursInputEl, minutesInputEl ) { + if ( $scope.readonlyInput ) { + $scope.updateHours = angular.noop; + $scope.updateMinutes = angular.noop; + return; + } + + var invalidate = function(invalidHours, invalidMinutes) { + ngModelCtrl.$setViewValue( null ); + ngModelCtrl.$setValidity('time', false); + if (angular.isDefined(invalidHours)) { + $scope.invalidHours = invalidHours; + } + if (angular.isDefined(invalidMinutes)) { + $scope.invalidMinutes = invalidMinutes; + } + }; + + $scope.updateHours = function() { + var hours = getHoursFromTemplate(); + + if ( angular.isDefined(hours) ) { + selected.setHours( hours ); + refresh( 'h' ); + } else { + invalidate(true); + } + }; + + hoursInputEl.bind('blur', function(e) { + if ( !$scope.invalidHours && $scope.hours < 10) { + $scope.$apply( function() { + $scope.hours = pad( $scope.hours ); + }); + } + }); + + $scope.updateMinutes = function() { + var minutes = getMinutesFromTemplate(); + + if ( angular.isDefined(minutes) ) { + selected.setMinutes( minutes ); + refresh( 'm' ); + } else { + invalidate(undefined, true); + } + }; + + minutesInputEl.bind('blur', function(e) { + if ( !$scope.invalidMinutes && $scope.minutes < 10 ) { + $scope.$apply( function() { + $scope.minutes = pad( $scope.minutes ); + }); + } + }); + + }; + + this.render = function() { + var date = ngModelCtrl.$modelValue ? new Date( ngModelCtrl.$modelValue ) : null; + + if ( isNaN(date) ) { + ngModelCtrl.$setValidity('time', false); + $log.error('Timepicker directive: "ng-model" value must be a Date object, a number of milliseconds since 01.01.1970 or a string representing an RFC2822 or ISO 8601 date.'); + } else { + if ( date ) { + selected = date; + } + makeValid(); + updateTemplate(); + } + }; + + // Call internally when we know that model is valid. + function refresh( keyboardChange ) { + makeValid(); + ngModelCtrl.$setViewValue( new Date(selected) ); + updateTemplate( keyboardChange ); + } + + function makeValid() { + ngModelCtrl.$setValidity('time', true); + $scope.invalidHours = false; + $scope.invalidMinutes = false; + } + + function updateTemplate( keyboardChange ) { + var hours = selected.getHours(), minutes = selected.getMinutes(); + + if ( $scope.showMeridian ) { + hours = ( hours === 0 || hours === 12 ) ? 12 : hours % 12; // Convert 24 to 12 hour system + } + + $scope.hours = keyboardChange === 'h' ? hours : pad(hours); + $scope.minutes = keyboardChange === 'm' ? minutes : pad(minutes); + $scope.meridian = selected.getHours() < 12 ? meridians[0] : meridians[1]; + } + + function addMinutes( minutes ) { + var dt = new Date( selected.getTime() + minutes * 60000 ); + selected.setHours( dt.getHours(), dt.getMinutes() ); + refresh(); + } + + $scope.incrementHours = function() { + addMinutes( hourStep * 60 ); + }; + $scope.decrementHours = function() { + addMinutes( - hourStep * 60 ); + }; + $scope.incrementMinutes = function() { + addMinutes( minuteStep ); + }; + $scope.decrementMinutes = function() { + addMinutes( - minuteStep ); + }; + $scope.toggleMeridian = function() { + addMinutes( 12 * 60 * (( selected.getHours() < 12 ) ? 1 : -1) ); + }; +}]) + +.directive('timepicker', function () { + return { + restrict: 'EA', + require: ['timepicker', '?^ngModel'], + controller:'TimepickerController', + replace: true, + scope: {}, + templateUrl: 'template/timepicker/timepicker.html', + link: function(scope, element, attrs, ctrls) { + var timepickerCtrl = ctrls[0], ngModelCtrl = ctrls[1]; + + if ( ngModelCtrl ) { + timepickerCtrl.init( ngModelCtrl, element.find('input') ); + } + } + }; +}); + +angular.module('ui.bootstrap.typeahead', ['ui.bootstrap.position', 'ui.bootstrap.bindHtml']) + +/** + * A helper service that can parse typeahead's syntax (string provided by users) + * Extracted to a separate service for ease of unit testing + */ + .factory('typeaheadParser', ['$parse', function ($parse) { + + // 00000111000000000000022200000000000000003333333333333330000000000044000 + var TYPEAHEAD_REGEXP = /^\s*([\s\S]+?)(?:\s+as\s+([\s\S]+?))?\s+for\s+(?:([\$\w][\$\w\d]*))\s+in\s+([\s\S]+?)$/; + + return { + parse:function (input) { + + var match = input.match(TYPEAHEAD_REGEXP); + if (!match) { + throw new Error( + 'Expected typeahead specification in form of "_modelValue_ (as _label_)? for _item_ in _collection_"' + + ' but got "' + input + '".'); + } + + return { + itemName:match[3], + source:$parse(match[4]), + viewMapper:$parse(match[2] || match[1]), + modelMapper:$parse(match[1]) + }; + } + }; +}]) + + .directive('typeahead', ['$compile', '$parse', '$q', '$timeout', '$document', '$position', 'typeaheadParser', + function ($compile, $parse, $q, $timeout, $document, $position, typeaheadParser) { + + var HOT_KEYS = [9, 13, 27, 38, 40]; + + return { + require:'ngModel', + link:function (originalScope, element, attrs, modelCtrl) { + + //SUPPORTED ATTRIBUTES (OPTIONS) + + //minimal no of characters that needs to be entered before typeahead kicks-in + var minSearch = originalScope.$eval(attrs.typeaheadMinLength) || 1; + + //minimal wait time after last character typed before typehead kicks-in + var waitTime = originalScope.$eval(attrs.typeaheadWaitMs) || 0; + + //should it restrict model values to the ones selected from the popup only? + var isEditable = originalScope.$eval(attrs.typeaheadEditable) !== false; + + //binding to a variable that indicates if matches are being retrieved asynchronously + var isLoadingSetter = $parse(attrs.typeaheadLoading).assign || angular.noop; + + //a callback executed when a match is selected + var onSelectCallback = $parse(attrs.typeaheadOnSelect); + + var inputFormatter = attrs.typeaheadInputFormatter ? $parse(attrs.typeaheadInputFormatter) : undefined; + + var appendToBody = attrs.typeaheadAppendToBody ? originalScope.$eval(attrs.typeaheadAppendToBody) : false; + + var focusFirst = originalScope.$eval(attrs.typeaheadFocusFirst) !== false; + + //INTERNAL VARIABLES + + //model setter executed upon match selection + var $setModelValue = $parse(attrs.ngModel).assign; + + //expressions used by typeahead + var parserResult = typeaheadParser.parse(attrs.typeahead); + + var hasFocus; + + //create a child scope for the typeahead directive so we are not polluting original scope + //with typeahead-specific data (matches, query etc.) + var scope = originalScope.$new(); + originalScope.$on('$destroy', function(){ + scope.$destroy(); + }); + + // WAI-ARIA + var popupId = 'typeahead-' + scope.$id + '-' + Math.floor(Math.random() * 10000); + element.attr({ + 'aria-autocomplete': 'list', + 'aria-expanded': false, + 'aria-owns': popupId + }); + + //pop-up element used to display matches + var popUpEl = angular.element('
      '); + popUpEl.attr({ + id: popupId, + matches: 'matches', + active: 'activeIdx', + select: 'select(activeIdx)', + query: 'query', + position: 'position' + }); + //custom item template + if (angular.isDefined(attrs.typeaheadTemplateUrl)) { + popUpEl.attr('template-url', attrs.typeaheadTemplateUrl); + } + + var resetMatches = function() { + scope.matches = []; + scope.activeIdx = -1; + element.attr('aria-expanded', false); + }; + + var getMatchId = function(index) { + return popupId + '-option-' + index; + }; + + // Indicate that the specified match is the active (pre-selected) item in the list owned by this typeahead. + // This attribute is added or removed automatically when the `activeIdx` changes. + scope.$watch('activeIdx', function(index) { + if (index < 0) { + element.removeAttr('aria-activedescendant'); + } else { + element.attr('aria-activedescendant', getMatchId(index)); + } + }); + + var getMatchesAsync = function(inputValue) { + + var locals = {$viewValue: inputValue}; + isLoadingSetter(originalScope, true); + $q.when(parserResult.source(originalScope, locals)).then(function(matches) { + + //it might happen that several async queries were in progress if a user were typing fast + //but we are interested only in responses that correspond to the current view value + var onCurrentRequest = (inputValue === modelCtrl.$viewValue); + if (onCurrentRequest && hasFocus) { + if (matches.length > 0) { + + scope.activeIdx = focusFirst ? 0 : -1; + scope.matches.length = 0; + + //transform labels + for(var i=0; i= minSearch) { + if (waitTime > 0) { + cancelPreviousTimeout(); + scheduleSearchWithTimeout(inputValue); + } else { + getMatchesAsync(inputValue); + } + } else { + isLoadingSetter(originalScope, false); + cancelPreviousTimeout(); + resetMatches(); + } + + if (isEditable) { + return inputValue; + } else { + if (!inputValue) { + // Reset in case user had typed something previously. + modelCtrl.$setValidity('editable', true); + return inputValue; + } else { + modelCtrl.$setValidity('editable', false); + return undefined; + } + } + }); + + modelCtrl.$formatters.push(function (modelValue) { + + var candidateViewValue, emptyViewValue; + var locals = {}; + + if (inputFormatter) { + + locals.$model = modelValue; + return inputFormatter(originalScope, locals); + + } else { + + //it might happen that we don't have enough info to properly render input value + //we need to check for this situation and simply return model value if we can't apply custom formatting + locals[parserResult.itemName] = modelValue; + candidateViewValue = parserResult.viewMapper(originalScope, locals); + locals[parserResult.itemName] = undefined; + emptyViewValue = parserResult.viewMapper(originalScope, locals); + + return candidateViewValue!== emptyViewValue ? candidateViewValue : modelValue; + } + }); + + scope.select = function (activeIdx) { + //called from within the $digest() cycle + var locals = {}; + var model, item; + + locals[parserResult.itemName] = item = scope.matches[activeIdx].model; + model = parserResult.modelMapper(originalScope, locals); + $setModelValue(originalScope, model); + modelCtrl.$setValidity('editable', true); + + onSelectCallback(originalScope, { + $item: item, + $model: model, + $label: parserResult.viewMapper(originalScope, locals) + }); + + resetMatches(); + + //return focus to the input element if a match was selected via a mouse click event + // use timeout to avoid $rootScope:inprog error + $timeout(function() { element[0].focus(); }, 0, false); + }; + + //bind keyboard events: arrows up(38) / down(40), enter(13) and tab(9), esc(27) + element.bind('keydown', function (evt) { + + //typeahead is open and an "interesting" key was pressed + if (scope.matches.length === 0 || HOT_KEYS.indexOf(evt.which) === -1) { + return; + } + + // if there's nothing selected (i.e. focusFirst) and enter is hit, don't do anything + if (scope.activeIdx == -1 && (evt.which === 13 || evt.which === 9)) { + return; + } + + evt.preventDefault(); + + if (evt.which === 40) { + scope.activeIdx = (scope.activeIdx + 1) % scope.matches.length; + scope.$digest(); + + } else if (evt.which === 38) { + scope.activeIdx = (scope.activeIdx > 0 ? scope.activeIdx : scope.matches.length) - 1; + scope.$digest(); + + } else if (evt.which === 13 || evt.which === 9) { + scope.$apply(function () { + scope.select(scope.activeIdx); + }); + + } else if (evt.which === 27) { + evt.stopPropagation(); + + resetMatches(); + scope.$digest(); + } + }); + + element.bind('blur', function (evt) { + hasFocus = false; + }); + + // Keep reference to click handler to unbind it. + var dismissClickHandler = function (evt) { + if (element[0] !== evt.target) { + resetMatches(); + scope.$digest(); + } + }; + + $document.bind('click', dismissClickHandler); + + originalScope.$on('$destroy', function(){ + $document.unbind('click', dismissClickHandler); + if (appendToBody) { + $popup.remove(); + } + }); + + var $popup = $compile(popUpEl)(scope); + if (appendToBody) { + $document.find('body').append($popup); + } else { + element.after($popup); + } + } + }; + +}]) + + .directive('typeaheadPopup', function () { + return { + restrict:'EA', + scope:{ + matches:'=', + query:'=', + active:'=', + position:'=', + select:'&' + }, + replace:true, + templateUrl:'template/typeahead/typeahead-popup.html', + link:function (scope, element, attrs) { + + scope.templateUrl = attrs.templateUrl; + + scope.isOpen = function () { + return scope.matches.length > 0; + }; + + scope.isActive = function (matchIdx) { + return scope.active == matchIdx; + }; + + scope.selectActive = function (matchIdx) { + scope.active = matchIdx; + }; + + scope.selectMatch = function (activeIdx) { + scope.select({activeIdx:activeIdx}); + }; + } + }; + }) + + .directive('typeaheadMatch', ['$http', '$templateCache', '$compile', '$parse', function ($http, $templateCache, $compile, $parse) { + return { + restrict:'EA', + scope:{ + index:'=', + match:'=', + query:'=' + }, + link:function (scope, element, attrs) { + var tplUrl = $parse(attrs.templateUrl)(scope.$parent) || 'template/typeahead/typeahead-match.html'; + $http.get(tplUrl, {cache: $templateCache}).success(function(tplContent){ + element.replaceWith($compile(tplContent.trim())(scope)); + }); + } + }; + }]) + + .filter('typeaheadHighlight', function() { + + function escapeRegexp(queryToEscape) { + return queryToEscape.replace(/([.?*+^$[\]\\(){}|-])/g, '\\$1'); + } + + return function(matchItem, query) { + return query ? ('' + matchItem).replace(new RegExp(escapeRegexp(query), 'gi'), '$&') : matchItem; + }; + }); diff --git a/public/admincp/bower_components/angular-bootstrap/ui-bootstrap.min.js b/public/admincp/bower_components/angular-bootstrap/ui-bootstrap.min.js new file mode 100644 index 000000000..10c1160b7 --- /dev/null +++ b/public/admincp/bower_components/angular-bootstrap/ui-bootstrap.min.js @@ -0,0 +1,9 @@ +/* + * angular-ui-bootstrap + * http://angular-ui.github.io/bootstrap/ + + * Version: 0.12.0 - 2014-11-16 + * License: MIT + */ +angular.module("ui.bootstrap",["ui.bootstrap.transition","ui.bootstrap.collapse","ui.bootstrap.accordion","ui.bootstrap.alert","ui.bootstrap.bindHtml","ui.bootstrap.buttons","ui.bootstrap.carousel","ui.bootstrap.dateparser","ui.bootstrap.position","ui.bootstrap.datepicker","ui.bootstrap.dropdown","ui.bootstrap.modal","ui.bootstrap.pagination","ui.bootstrap.tooltip","ui.bootstrap.popover","ui.bootstrap.progressbar","ui.bootstrap.rating","ui.bootstrap.tabs","ui.bootstrap.timepicker","ui.bootstrap.typeahead"]),angular.module("ui.bootstrap.transition",[]).factory("$transition",["$q","$timeout","$rootScope",function(a,b,c){function d(a){for(var b in a)if(void 0!==f.style[b])return a[b]}var e=function(d,f,g){g=g||{};var h=a.defer(),i=e[g.animation?"animationEndEventName":"transitionEndEventName"],j=function(){c.$apply(function(){d.unbind(i,j),h.resolve(d)})};return i&&d.bind(i,j),b(function(){angular.isString(f)?d.addClass(f):angular.isFunction(f)?f(d):angular.isObject(f)&&d.css(f),i||h.resolve(d)}),h.promise.cancel=function(){i&&d.unbind(i,j),h.reject("Transition cancelled")},h.promise},f=document.createElement("trans"),g={WebkitTransition:"webkitTransitionEnd",MozTransition:"transitionend",OTransition:"oTransitionEnd",transition:"transitionend"},h={WebkitTransition:"webkitAnimationEnd",MozTransition:"animationend",OTransition:"oAnimationEnd",transition:"animationend"};return e.transitionEndEventName=d(g),e.animationEndEventName=d(h),e}]),angular.module("ui.bootstrap.collapse",["ui.bootstrap.transition"]).directive("collapse",["$transition",function(a){return{link:function(b,c,d){function e(b){function d(){j===e&&(j=void 0)}var e=a(c,b);return j&&j.cancel(),j=e,e.then(d,d),e}function f(){k?(k=!1,g()):(c.removeClass("collapse").addClass("collapsing"),e({height:c[0].scrollHeight+"px"}).then(g))}function g(){c.removeClass("collapsing"),c.addClass("collapse in"),c.css({height:"auto"})}function h(){if(k)k=!1,i(),c.css({height:0});else{c.css({height:c[0].scrollHeight+"px"});{c[0].offsetWidth}c.removeClass("collapse in").addClass("collapsing"),e({height:0}).then(i)}}function i(){c.removeClass("collapsing"),c.addClass("collapse")}var j,k=!0;b.$watch(d.collapse,function(a){a?h():f()})}}}]),angular.module("ui.bootstrap.accordion",["ui.bootstrap.collapse"]).constant("accordionConfig",{closeOthers:!0}).controller("AccordionController",["$scope","$attrs","accordionConfig",function(a,b,c){this.groups=[],this.closeOthers=function(d){var e=angular.isDefined(b.closeOthers)?a.$eval(b.closeOthers):c.closeOthers;e&&angular.forEach(this.groups,function(a){a!==d&&(a.isOpen=!1)})},this.addGroup=function(a){var b=this;this.groups.push(a),a.$on("$destroy",function(){b.removeGroup(a)})},this.removeGroup=function(a){var b=this.groups.indexOf(a);-1!==b&&this.groups.splice(b,1)}}]).directive("accordion",function(){return{restrict:"EA",controller:"AccordionController",transclude:!0,replace:!1,templateUrl:"template/accordion/accordion.html"}}).directive("accordionGroup",function(){return{require:"^accordion",restrict:"EA",transclude:!0,replace:!0,templateUrl:"template/accordion/accordion-group.html",scope:{heading:"@",isOpen:"=?",isDisabled:"=?"},controller:function(){this.setHeading=function(a){this.heading=a}},link:function(a,b,c,d){d.addGroup(a),a.$watch("isOpen",function(b){b&&d.closeOthers(a)}),a.toggleOpen=function(){a.isDisabled||(a.isOpen=!a.isOpen)}}}}).directive("accordionHeading",function(){return{restrict:"EA",transclude:!0,template:"",replace:!0,require:"^accordionGroup",link:function(a,b,c,d,e){d.setHeading(e(a,function(){}))}}}).directive("accordionTransclude",function(){return{require:"^accordionGroup",link:function(a,b,c,d){a.$watch(function(){return d[c.accordionTransclude]},function(a){a&&(b.html(""),b.append(a))})}}}),angular.module("ui.bootstrap.alert",[]).controller("AlertController",["$scope","$attrs",function(a,b){a.closeable="close"in b,this.close=a.close}]).directive("alert",function(){return{restrict:"EA",controller:"AlertController",templateUrl:"template/alert/alert.html",transclude:!0,replace:!0,scope:{type:"@",close:"&"}}}).directive("dismissOnTimeout",["$timeout",function(a){return{require:"alert",link:function(b,c,d,e){a(function(){e.close()},parseInt(d.dismissOnTimeout,10))}}}]),angular.module("ui.bootstrap.bindHtml",[]).directive("bindHtmlUnsafe",function(){return function(a,b,c){b.addClass("ng-binding").data("$binding",c.bindHtmlUnsafe),a.$watch(c.bindHtmlUnsafe,function(a){b.html(a||"")})}}),angular.module("ui.bootstrap.buttons",[]).constant("buttonConfig",{activeClass:"active",toggleEvent:"click"}).controller("ButtonsController",["buttonConfig",function(a){this.activeClass=a.activeClass||"active",this.toggleEvent=a.toggleEvent||"click"}]).directive("btnRadio",function(){return{require:["btnRadio","ngModel"],controller:"ButtonsController",link:function(a,b,c,d){var e=d[0],f=d[1];f.$render=function(){b.toggleClass(e.activeClass,angular.equals(f.$modelValue,a.$eval(c.btnRadio)))},b.bind(e.toggleEvent,function(){var d=b.hasClass(e.activeClass);(!d||angular.isDefined(c.uncheckable))&&a.$apply(function(){f.$setViewValue(d?null:a.$eval(c.btnRadio)),f.$render()})})}}}).directive("btnCheckbox",function(){return{require:["btnCheckbox","ngModel"],controller:"ButtonsController",link:function(a,b,c,d){function e(){return g(c.btnCheckboxTrue,!0)}function f(){return g(c.btnCheckboxFalse,!1)}function g(b,c){var d=a.$eval(b);return angular.isDefined(d)?d:c}var h=d[0],i=d[1];i.$render=function(){b.toggleClass(h.activeClass,angular.equals(i.$modelValue,e()))},b.bind(h.toggleEvent,function(){a.$apply(function(){i.$setViewValue(b.hasClass(h.activeClass)?f():e()),i.$render()})})}}}),angular.module("ui.bootstrap.carousel",["ui.bootstrap.transition"]).controller("CarouselController",["$scope","$timeout","$interval","$transition",function(a,b,c,d){function e(){f();var b=+a.interval;!isNaN(b)&&b>0&&(h=c(g,b))}function f(){h&&(c.cancel(h),h=null)}function g(){var b=+a.interval;i&&!isNaN(b)&&b>0?a.next():a.pause()}var h,i,j=this,k=j.slides=a.slides=[],l=-1;j.currentSlide=null;var m=!1;j.select=a.select=function(c,f){function g(){if(!m){if(j.currentSlide&&angular.isString(f)&&!a.noTransition&&c.$element){c.$element.addClass(f);{c.$element[0].offsetWidth}angular.forEach(k,function(a){angular.extend(a,{direction:"",entering:!1,leaving:!1,active:!1})}),angular.extend(c,{direction:f,active:!0,entering:!0}),angular.extend(j.currentSlide||{},{direction:f,leaving:!0}),a.$currentTransition=d(c.$element,{}),function(b,c){a.$currentTransition.then(function(){h(b,c)},function(){h(b,c)})}(c,j.currentSlide)}else h(c,j.currentSlide);j.currentSlide=c,l=i,e()}}function h(b,c){angular.extend(b,{direction:"",active:!0,leaving:!1,entering:!1}),angular.extend(c||{},{direction:"",active:!1,leaving:!1,entering:!1}),a.$currentTransition=null}var i=k.indexOf(c);void 0===f&&(f=i>l?"next":"prev"),c&&c!==j.currentSlide&&(a.$currentTransition?(a.$currentTransition.cancel(),b(g)):g())},a.$on("$destroy",function(){m=!0}),j.indexOfSlide=function(a){return k.indexOf(a)},a.next=function(){var b=(l+1)%k.length;return a.$currentTransition?void 0:j.select(k[b],"next")},a.prev=function(){var b=0>l-1?k.length-1:l-1;return a.$currentTransition?void 0:j.select(k[b],"prev")},a.isActive=function(a){return j.currentSlide===a},a.$watch("interval",e),a.$on("$destroy",f),a.play=function(){i||(i=!0,e())},a.pause=function(){a.noPause||(i=!1,f())},j.addSlide=function(b,c){b.$element=c,k.push(b),1===k.length||b.active?(j.select(k[k.length-1]),1==k.length&&a.play()):b.active=!1},j.removeSlide=function(a){var b=k.indexOf(a);k.splice(b,1),k.length>0&&a.active?j.select(b>=k.length?k[b-1]:k[b]):l>b&&l--}}]).directive("carousel",[function(){return{restrict:"EA",transclude:!0,replace:!0,controller:"CarouselController",require:"carousel",templateUrl:"template/carousel/carousel.html",scope:{interval:"=",noTransition:"=",noPause:"="}}}]).directive("slide",function(){return{require:"^carousel",restrict:"EA",transclude:!0,replace:!0,templateUrl:"template/carousel/slide.html",scope:{active:"=?"},link:function(a,b,c,d){d.addSlide(a,b),a.$on("$destroy",function(){d.removeSlide(a)}),a.$watch("active",function(b){b&&d.select(a)})}}}),angular.module("ui.bootstrap.dateparser",[]).service("dateParser",["$locale","orderByFilter",function(a,b){function c(a){var c=[],d=a.split("");return angular.forEach(e,function(b,e){var f=a.indexOf(e);if(f>-1){a=a.split(""),d[f]="("+b.regex+")",a[f]="$";for(var g=f+1,h=f+e.length;h>g;g++)d[g]="",a[g]="$";a=a.join(""),c.push({index:f,apply:b.apply})}}),{regex:new RegExp("^"+d.join("")+"$"),map:b(c,"index")}}function d(a,b,c){return 1===b&&c>28?29===c&&(a%4===0&&a%100!==0||a%400===0):3===b||5===b||8===b||10===b?31>c:!0}this.parsers={};var e={yyyy:{regex:"\\d{4}",apply:function(a){this.year=+a}},yy:{regex:"\\d{2}",apply:function(a){this.year=+a+2e3}},y:{regex:"\\d{1,4}",apply:function(a){this.year=+a}},MMMM:{regex:a.DATETIME_FORMATS.MONTH.join("|"),apply:function(b){this.month=a.DATETIME_FORMATS.MONTH.indexOf(b)}},MMM:{regex:a.DATETIME_FORMATS.SHORTMONTH.join("|"),apply:function(b){this.month=a.DATETIME_FORMATS.SHORTMONTH.indexOf(b)}},MM:{regex:"0[1-9]|1[0-2]",apply:function(a){this.month=a-1}},M:{regex:"[1-9]|1[0-2]",apply:function(a){this.month=a-1}},dd:{regex:"[0-2][0-9]{1}|3[0-1]{1}",apply:function(a){this.date=+a}},d:{regex:"[1-2]?[0-9]{1}|3[0-1]{1}",apply:function(a){this.date=+a}},EEEE:{regex:a.DATETIME_FORMATS.DAY.join("|")},EEE:{regex:a.DATETIME_FORMATS.SHORTDAY.join("|")}};this.parse=function(b,e){if(!angular.isString(b)||!e)return b;e=a.DATETIME_FORMATS[e]||e,this.parsers[e]||(this.parsers[e]=c(e));var f=this.parsers[e],g=f.regex,h=f.map,i=b.match(g);if(i&&i.length){for(var j,k={year:1900,month:0,date:1,hours:0},l=1,m=i.length;m>l;l++){var n=h[l-1];n.apply&&n.apply.call(k,i[l])}return d(k.year,k.month,k.date)&&(j=new Date(k.year,k.month,k.date,k.hours)),j}}}]),angular.module("ui.bootstrap.position",[]).factory("$position",["$document","$window",function(a,b){function c(a,c){return a.currentStyle?a.currentStyle[c]:b.getComputedStyle?b.getComputedStyle(a)[c]:a.style[c]}function d(a){return"static"===(c(a,"position")||"static")}var e=function(b){for(var c=a[0],e=b.offsetParent||c;e&&e!==c&&d(e);)e=e.offsetParent;return e||c};return{position:function(b){var c=this.offset(b),d={top:0,left:0},f=e(b[0]);f!=a[0]&&(d=this.offset(angular.element(f)),d.top+=f.clientTop-f.scrollTop,d.left+=f.clientLeft-f.scrollLeft);var g=b[0].getBoundingClientRect();return{width:g.width||b.prop("offsetWidth"),height:g.height||b.prop("offsetHeight"),top:c.top-d.top,left:c.left-d.left}},offset:function(c){var d=c[0].getBoundingClientRect();return{width:d.width||c.prop("offsetWidth"),height:d.height||c.prop("offsetHeight"),top:d.top+(b.pageYOffset||a[0].documentElement.scrollTop),left:d.left+(b.pageXOffset||a[0].documentElement.scrollLeft)}},positionElements:function(a,b,c,d){var e,f,g,h,i=c.split("-"),j=i[0],k=i[1]||"center";e=d?this.offset(a):this.position(a),f=b.prop("offsetWidth"),g=b.prop("offsetHeight");var l={center:function(){return e.left+e.width/2-f/2},left:function(){return e.left},right:function(){return e.left+e.width}},m={center:function(){return e.top+e.height/2-g/2},top:function(){return e.top},bottom:function(){return e.top+e.height}};switch(j){case"right":h={top:m[k](),left:l[j]()};break;case"left":h={top:m[k](),left:e.left-f};break;case"bottom":h={top:m[j](),left:l[k]()};break;default:h={top:e.top-g,left:l[k]()}}return h}}}]),angular.module("ui.bootstrap.datepicker",["ui.bootstrap.dateparser","ui.bootstrap.position"]).constant("datepickerConfig",{formatDay:"dd",formatMonth:"MMMM",formatYear:"yyyy",formatDayHeader:"EEE",formatDayTitle:"MMMM yyyy",formatMonthTitle:"yyyy",datepickerMode:"day",minMode:"day",maxMode:"year",showWeeks:!0,startingDay:0,yearRange:20,minDate:null,maxDate:null}).controller("DatepickerController",["$scope","$attrs","$parse","$interpolate","$timeout","$log","dateFilter","datepickerConfig",function(a,b,c,d,e,f,g,h){var i=this,j={$setViewValue:angular.noop};this.modes=["day","month","year"],angular.forEach(["formatDay","formatMonth","formatYear","formatDayHeader","formatDayTitle","formatMonthTitle","minMode","maxMode","showWeeks","startingDay","yearRange"],function(c,e){i[c]=angular.isDefined(b[c])?8>e?d(b[c])(a.$parent):a.$parent.$eval(b[c]):h[c]}),angular.forEach(["minDate","maxDate"],function(d){b[d]?a.$parent.$watch(c(b[d]),function(a){i[d]=a?new Date(a):null,i.refreshView()}):i[d]=h[d]?new Date(h[d]):null}),a.datepickerMode=a.datepickerMode||h.datepickerMode,a.uniqueId="datepicker-"+a.$id+"-"+Math.floor(1e4*Math.random()),this.activeDate=angular.isDefined(b.initDate)?a.$parent.$eval(b.initDate):new Date,a.isActive=function(b){return 0===i.compare(b.date,i.activeDate)?(a.activeDateId=b.uid,!0):!1},this.init=function(a){j=a,j.$render=function(){i.render()}},this.render=function(){if(j.$modelValue){var a=new Date(j.$modelValue),b=!isNaN(a);b?this.activeDate=a:f.error('Datepicker directive: "ng-model" value must be a Date object, a number of milliseconds since 01.01.1970 or a string representing an RFC2822 or ISO 8601 date.'),j.$setValidity("date",b)}this.refreshView()},this.refreshView=function(){if(this.element){this._refreshView();var a=j.$modelValue?new Date(j.$modelValue):null;j.$setValidity("date-disabled",!a||this.element&&!this.isDisabled(a))}},this.createDateObject=function(a,b){var c=j.$modelValue?new Date(j.$modelValue):null;return{date:a,label:g(a,b),selected:c&&0===this.compare(a,c),disabled:this.isDisabled(a),current:0===this.compare(a,new Date)}},this.isDisabled=function(c){return this.minDate&&this.compare(c,this.minDate)<0||this.maxDate&&this.compare(c,this.maxDate)>0||b.dateDisabled&&a.dateDisabled({date:c,mode:a.datepickerMode})},this.split=function(a,b){for(var c=[];a.length>0;)c.push(a.splice(0,b));return c},a.select=function(b){if(a.datepickerMode===i.minMode){var c=j.$modelValue?new Date(j.$modelValue):new Date(0,0,0,0,0,0,0);c.setFullYear(b.getFullYear(),b.getMonth(),b.getDate()),j.$setViewValue(c),j.$render()}else i.activeDate=b,a.datepickerMode=i.modes[i.modes.indexOf(a.datepickerMode)-1]},a.move=function(a){var b=i.activeDate.getFullYear()+a*(i.step.years||0),c=i.activeDate.getMonth()+a*(i.step.months||0);i.activeDate.setFullYear(b,c,1),i.refreshView()},a.toggleMode=function(b){b=b||1,a.datepickerMode===i.maxMode&&1===b||a.datepickerMode===i.minMode&&-1===b||(a.datepickerMode=i.modes[i.modes.indexOf(a.datepickerMode)+b])},a.keys={13:"enter",32:"space",33:"pageup",34:"pagedown",35:"end",36:"home",37:"left",38:"up",39:"right",40:"down"};var k=function(){e(function(){i.element[0].focus()},0,!1)};a.$on("datepicker.focus",k),a.keydown=function(b){var c=a.keys[b.which];if(c&&!b.shiftKey&&!b.altKey)if(b.preventDefault(),b.stopPropagation(),"enter"===c||"space"===c){if(i.isDisabled(i.activeDate))return;a.select(i.activeDate),k()}else!b.ctrlKey||"up"!==c&&"down"!==c?(i.handleKeyDown(c,b),i.refreshView()):(a.toggleMode("up"===c?1:-1),k())}}]).directive("datepicker",function(){return{restrict:"EA",replace:!0,templateUrl:"template/datepicker/datepicker.html",scope:{datepickerMode:"=?",dateDisabled:"&"},require:["datepicker","?^ngModel"],controller:"DatepickerController",link:function(a,b,c,d){var e=d[0],f=d[1];f&&e.init(f)}}}).directive("daypicker",["dateFilter",function(a){return{restrict:"EA",replace:!0,templateUrl:"template/datepicker/day.html",require:"^datepicker",link:function(b,c,d,e){function f(a,b){return 1!==b||a%4!==0||a%100===0&&a%400!==0?i[b]:29}function g(a,b){var c=new Array(b),d=new Date(a),e=0;for(d.setHours(12);b>e;)c[e++]=new Date(d),d.setDate(d.getDate()+1);return c}function h(a){var b=new Date(a);b.setDate(b.getDate()+4-(b.getDay()||7));var c=b.getTime();return b.setMonth(0),b.setDate(1),Math.floor(Math.round((c-b)/864e5)/7)+1}b.showWeeks=e.showWeeks,e.step={months:1},e.element=c;var i=[31,28,31,30,31,30,31,31,30,31,30,31];e._refreshView=function(){var c=e.activeDate.getFullYear(),d=e.activeDate.getMonth(),f=new Date(c,d,1),i=e.startingDay-f.getDay(),j=i>0?7-i:-i,k=new Date(f);j>0&&k.setDate(-j+1);for(var l=g(k,42),m=0;42>m;m++)l[m]=angular.extend(e.createDateObject(l[m],e.formatDay),{secondary:l[m].getMonth()!==d,uid:b.uniqueId+"-"+m});b.labels=new Array(7);for(var n=0;7>n;n++)b.labels[n]={abbr:a(l[n].date,e.formatDayHeader),full:a(l[n].date,"EEEE")};if(b.title=a(e.activeDate,e.formatDayTitle),b.rows=e.split(l,7),b.showWeeks){b.weekNumbers=[];for(var o=h(b.rows[0][0].date),p=b.rows.length;b.weekNumbers.push(o++)f;f++)c[f]=angular.extend(e.createDateObject(new Date(d,f,1),e.formatMonth),{uid:b.uniqueId+"-"+f});b.title=a(e.activeDate,e.formatMonthTitle),b.rows=e.split(c,3)},e.compare=function(a,b){return new Date(a.getFullYear(),a.getMonth())-new Date(b.getFullYear(),b.getMonth())},e.handleKeyDown=function(a){var b=e.activeDate.getMonth();if("left"===a)b-=1;else if("up"===a)b-=3;else if("right"===a)b+=1;else if("down"===a)b+=3;else if("pageup"===a||"pagedown"===a){var c=e.activeDate.getFullYear()+("pageup"===a?-1:1);e.activeDate.setFullYear(c)}else"home"===a?b=0:"end"===a&&(b=11);e.activeDate.setMonth(b)},e.refreshView()}}}]).directive("yearpicker",["dateFilter",function(){return{restrict:"EA",replace:!0,templateUrl:"template/datepicker/year.html",require:"^datepicker",link:function(a,b,c,d){function e(a){return parseInt((a-1)/f,10)*f+1}var f=d.yearRange;d.step={years:f},d.element=b,d._refreshView=function(){for(var b=new Array(f),c=0,g=e(d.activeDate.getFullYear());f>c;c++)b[c]=angular.extend(d.createDateObject(new Date(g+c,0,1),d.formatYear),{uid:a.uniqueId+"-"+c});a.title=[b[0].label,b[f-1].label].join(" - "),a.rows=d.split(b,5)},d.compare=function(a,b){return a.getFullYear()-b.getFullYear()},d.handleKeyDown=function(a){var b=d.activeDate.getFullYear();"left"===a?b-=1:"up"===a?b-=5:"right"===a?b+=1:"down"===a?b+=5:"pageup"===a||"pagedown"===a?b+=("pageup"===a?-1:1)*d.step.years:"home"===a?b=e(d.activeDate.getFullYear()):"end"===a&&(b=e(d.activeDate.getFullYear())+f-1),d.activeDate.setFullYear(b)},d.refreshView()}}}]).constant("datepickerPopupConfig",{datepickerPopup:"yyyy-MM-dd",currentText:"Today",clearText:"Clear",closeText:"Done",closeOnDateSelection:!0,appendToBody:!1,showButtonBar:!0}).directive("datepickerPopup",["$compile","$parse","$document","$position","dateFilter","dateParser","datepickerPopupConfig",function(a,b,c,d,e,f,g){return{restrict:"EA",require:"ngModel",scope:{isOpen:"=?",currentText:"@",clearText:"@",closeText:"@",dateDisabled:"&"},link:function(h,i,j,k){function l(a){return a.replace(/([A-Z])/g,function(a){return"-"+a.toLowerCase()})}function m(a){if(a){if(angular.isDate(a)&&!isNaN(a))return k.$setValidity("date",!0),a;if(angular.isString(a)){var b=f.parse(a,n)||new Date(a);return isNaN(b)?void k.$setValidity("date",!1):(k.$setValidity("date",!0),b)}return void k.$setValidity("date",!1)}return k.$setValidity("date",!0),null}var n,o=angular.isDefined(j.closeOnDateSelection)?h.$parent.$eval(j.closeOnDateSelection):g.closeOnDateSelection,p=angular.isDefined(j.datepickerAppendToBody)?h.$parent.$eval(j.datepickerAppendToBody):g.appendToBody;h.showButtonBar=angular.isDefined(j.showButtonBar)?h.$parent.$eval(j.showButtonBar):g.showButtonBar,h.getText=function(a){return h[a+"Text"]||g[a+"Text"]},j.$observe("datepickerPopup",function(a){n=a||g.datepickerPopup,k.$render()});var q=angular.element("
      ");q.attr({"ng-model":"date","ng-change":"dateSelection()"});var r=angular.element(q.children()[0]);j.datepickerOptions&&angular.forEach(h.$parent.$eval(j.datepickerOptions),function(a,b){r.attr(l(b),a)}),h.watchData={},angular.forEach(["minDate","maxDate","datepickerMode"],function(a){if(j[a]){var c=b(j[a]);if(h.$parent.$watch(c,function(b){h.watchData[a]=b}),r.attr(l(a),"watchData."+a),"datepickerMode"===a){var d=c.assign;h.$watch("watchData."+a,function(a,b){a!==b&&d(h.$parent,a)})}}}),j.dateDisabled&&r.attr("date-disabled","dateDisabled({ date: date, mode: mode })"),k.$parsers.unshift(m),h.dateSelection=function(a){angular.isDefined(a)&&(h.date=a),k.$setViewValue(h.date),k.$render(),o&&(h.isOpen=!1,i[0].focus())},i.bind("input change keyup",function(){h.$apply(function(){h.date=k.$modelValue})}),k.$render=function(){var a=k.$viewValue?e(k.$viewValue,n):"";i.val(a),h.date=m(k.$modelValue)};var s=function(a){h.isOpen&&a.target!==i[0]&&h.$apply(function(){h.isOpen=!1})},t=function(a){h.keydown(a)};i.bind("keydown",t),h.keydown=function(a){27===a.which?(a.preventDefault(),a.stopPropagation(),h.close()):40!==a.which||h.isOpen||(h.isOpen=!0)},h.$watch("isOpen",function(a){a?(h.$broadcast("datepicker.focus"),h.position=p?d.offset(i):d.position(i),h.position.top=h.position.top+i.prop("offsetHeight"),c.bind("click",s)):c.unbind("click",s)}),h.select=function(a){if("today"===a){var b=new Date;angular.isDate(k.$modelValue)?(a=new Date(k.$modelValue),a.setFullYear(b.getFullYear(),b.getMonth(),b.getDate())):a=new Date(b.setHours(0,0,0,0))}h.dateSelection(a)},h.close=function(){h.isOpen=!1,i[0].focus()};var u=a(q)(h);q.remove(),p?c.find("body").append(u):i.after(u),h.$on("$destroy",function(){u.remove(),i.unbind("keydown",t),c.unbind("click",s)})}}}]).directive("datepickerPopupWrap",function(){return{restrict:"EA",replace:!0,transclude:!0,templateUrl:"template/datepicker/popup.html",link:function(a,b){b.bind("click",function(a){a.preventDefault(),a.stopPropagation()})}}}),angular.module("ui.bootstrap.dropdown",[]).constant("dropdownConfig",{openClass:"open"}).service("dropdownService",["$document",function(a){var b=null;this.open=function(e){b||(a.bind("click",c),a.bind("keydown",d)),b&&b!==e&&(b.isOpen=!1),b=e},this.close=function(e){b===e&&(b=null,a.unbind("click",c),a.unbind("keydown",d))};var c=function(a){if(b){var c=b.getToggleElement();a&&c&&c[0].contains(a.target)||b.$apply(function(){b.isOpen=!1})}},d=function(a){27===a.which&&(b.focusToggleElement(),c())}}]).controller("DropdownController",["$scope","$attrs","$parse","dropdownConfig","dropdownService","$animate",function(a,b,c,d,e,f){var g,h=this,i=a.$new(),j=d.openClass,k=angular.noop,l=b.onToggle?c(b.onToggle):angular.noop;this.init=function(d){h.$element=d,b.isOpen&&(g=c(b.isOpen),k=g.assign,a.$watch(g,function(a){i.isOpen=!!a}))},this.toggle=function(a){return i.isOpen=arguments.length?!!a:!i.isOpen},this.isOpen=function(){return i.isOpen},i.getToggleElement=function(){return h.toggleElement},i.focusToggleElement=function(){h.toggleElement&&h.toggleElement[0].focus()},i.$watch("isOpen",function(b,c){f[b?"addClass":"removeClass"](h.$element,j),b?(i.focusToggleElement(),e.open(i)):e.close(i),k(a,b),angular.isDefined(b)&&b!==c&&l(a,{open:!!b})}),a.$on("$locationChangeSuccess",function(){i.isOpen=!1}),a.$on("$destroy",function(){i.$destroy()})}]).directive("dropdown",function(){return{controller:"DropdownController",link:function(a,b,c,d){d.init(b)}}}).directive("dropdownToggle",function(){return{require:"?^dropdown",link:function(a,b,c,d){if(d){d.toggleElement=b;var e=function(e){e.preventDefault(),b.hasClass("disabled")||c.disabled||a.$apply(function(){d.toggle()})};b.bind("click",e),b.attr({"aria-haspopup":!0,"aria-expanded":!1}),a.$watch(d.isOpen,function(a){b.attr("aria-expanded",!!a)}),a.$on("$destroy",function(){b.unbind("click",e)})}}}}),angular.module("ui.bootstrap.modal",["ui.bootstrap.transition"]).factory("$$stackedMap",function(){return{createNew:function(){var a=[];return{add:function(b,c){a.push({key:b,value:c})},get:function(b){for(var c=0;c0),i()})}function i(){if(k&&-1==g()){var a=l;j(k,l,150,function(){a.$destroy(),a=null}),k=void 0,l=void 0}}function j(c,d,e,f){function g(){g.done||(g.done=!0,c.remove(),f&&f())}d.animate=!1;var h=a.transitionEndEventName;if(h){var i=b(g,e);c.bind(h,function(){b.cancel(i),g(),d.$apply()})}else b(g)}var k,l,m="modal-open",n=f.createNew(),o={};return e.$watch(g,function(a){l&&(l.index=a)}),c.bind("keydown",function(a){var b;27===a.which&&(b=n.top(),b&&b.value.keyboard&&(a.preventDefault(),e.$apply(function(){o.dismiss(b.key,"escape key press")})))}),o.open=function(a,b){n.add(a,{deferred:b.deferred,modalScope:b.scope,backdrop:b.backdrop,keyboard:b.keyboard});var f=c.find("body").eq(0),h=g();if(h>=0&&!k){l=e.$new(!0),l.index=h;var i=angular.element("
      ");i.attr("backdrop-class",b.backdropClass),k=d(i)(l),f.append(k)}var j=angular.element("
      ");j.attr({"template-url":b.windowTemplateUrl,"window-class":b.windowClass,size:b.size,index:n.length()-1,animate:"animate"}).html(b.content);var o=d(j)(b.scope);n.top().value.modalDomEl=o,f.append(o),f.addClass(m)},o.close=function(a,b){var c=n.get(a);c&&(c.value.deferred.resolve(b),h(a))},o.dismiss=function(a,b){var c=n.get(a);c&&(c.value.deferred.reject(b),h(a))},o.dismissAll=function(a){for(var b=this.getTop();b;)this.dismiss(b.key,a),b=this.getTop()},o.getTop=function(){return n.top()},o}]).provider("$modal",function(){var a={options:{backdrop:!0,keyboard:!0},$get:["$injector","$rootScope","$q","$http","$templateCache","$controller","$modalStack",function(b,c,d,e,f,g,h){function i(a){return a.template?d.when(a.template):e.get(angular.isFunction(a.templateUrl)?a.templateUrl():a.templateUrl,{cache:f}).then(function(a){return a.data})}function j(a){var c=[];return angular.forEach(a,function(a){(angular.isFunction(a)||angular.isArray(a))&&c.push(d.when(b.invoke(a)))}),c}var k={};return k.open=function(b){var e=d.defer(),f=d.defer(),k={result:e.promise,opened:f.promise,close:function(a){h.close(k,a)},dismiss:function(a){h.dismiss(k,a)}};if(b=angular.extend({},a.options,b),b.resolve=b.resolve||{},!b.template&&!b.templateUrl)throw new Error("One of template or templateUrl options is required.");var l=d.all([i(b)].concat(j(b.resolve)));return l.then(function(a){var d=(b.scope||c).$new();d.$close=k.close,d.$dismiss=k.dismiss;var f,i={},j=1;b.controller&&(i.$scope=d,i.$modalInstance=k,angular.forEach(b.resolve,function(b,c){i[c]=a[j++]}),f=g(b.controller,i),b.controllerAs&&(d[b.controllerAs]=f)),h.open(k,{scope:d,deferred:e,content:a[0],backdrop:b.backdrop,keyboard:b.keyboard,backdropClass:b.backdropClass,windowClass:b.windowClass,windowTemplateUrl:b.windowTemplateUrl,size:b.size})},function(a){e.reject(a)}),l.then(function(){f.resolve(!0)},function(){f.reject(!1)}),k},k}]};return a}),angular.module("ui.bootstrap.pagination",[]).controller("PaginationController",["$scope","$attrs","$parse",function(a,b,c){var d=this,e={$setViewValue:angular.noop},f=b.numPages?c(b.numPages).assign:angular.noop;this.init=function(f,g){e=f,this.config=g,e.$render=function(){d.render()},b.itemsPerPage?a.$parent.$watch(c(b.itemsPerPage),function(b){d.itemsPerPage=parseInt(b,10),a.totalPages=d.calculateTotalPages()}):this.itemsPerPage=g.itemsPerPage},this.calculateTotalPages=function(){var b=this.itemsPerPage<1?1:Math.ceil(a.totalItems/this.itemsPerPage);return Math.max(b||0,1)},this.render=function(){a.page=parseInt(e.$viewValue,10)||1},a.selectPage=function(b){a.page!==b&&b>0&&b<=a.totalPages&&(e.$setViewValue(b),e.$render())},a.getText=function(b){return a[b+"Text"]||d.config[b+"Text"]},a.noPrevious=function(){return 1===a.page},a.noNext=function(){return a.page===a.totalPages},a.$watch("totalItems",function(){a.totalPages=d.calculateTotalPages()}),a.$watch("totalPages",function(b){f(a.$parent,b),a.page>b?a.selectPage(b):e.$render()})}]).constant("paginationConfig",{itemsPerPage:10,boundaryLinks:!1,directionLinks:!0,firstText:"First",previousText:"Previous",nextText:"Next",lastText:"Last",rotate:!0}).directive("pagination",["$parse","paginationConfig",function(a,b){return{restrict:"EA",scope:{totalItems:"=",firstText:"@",previousText:"@",nextText:"@",lastText:"@"},require:["pagination","?ngModel"],controller:"PaginationController",templateUrl:"template/pagination/pagination.html",replace:!0,link:function(c,d,e,f){function g(a,b,c){return{number:a,text:b,active:c}}function h(a,b){var c=[],d=1,e=b,f=angular.isDefined(k)&&b>k;f&&(l?(d=Math.max(a-Math.floor(k/2),1),e=d+k-1,e>b&&(e=b,d=e-k+1)):(d=(Math.ceil(a/k)-1)*k+1,e=Math.min(d+k-1,b)));for(var h=d;e>=h;h++){var i=g(h,h,h===a);c.push(i)}if(f&&!l){if(d>1){var j=g(d-1,"...",!1);c.unshift(j)}if(b>e){var m=g(e+1,"...",!1);c.push(m)}}return c}var i=f[0],j=f[1];if(j){var k=angular.isDefined(e.maxSize)?c.$parent.$eval(e.maxSize):b.maxSize,l=angular.isDefined(e.rotate)?c.$parent.$eval(e.rotate):b.rotate;c.boundaryLinks=angular.isDefined(e.boundaryLinks)?c.$parent.$eval(e.boundaryLinks):b.boundaryLinks,c.directionLinks=angular.isDefined(e.directionLinks)?c.$parent.$eval(e.directionLinks):b.directionLinks,i.init(j,b),e.maxSize&&c.$parent.$watch(a(e.maxSize),function(a){k=parseInt(a,10),i.render()});var m=i.render;i.render=function(){m(),c.page>0&&c.page<=c.totalPages&&(c.pages=h(c.page,c.totalPages))}}}}}]).constant("pagerConfig",{itemsPerPage:10,previousText:"« Previous",nextText:"Next »",align:!0}).directive("pager",["pagerConfig",function(a){return{restrict:"EA",scope:{totalItems:"=",previousText:"@",nextText:"@"},require:["pager","?ngModel"],controller:"PaginationController",templateUrl:"template/pagination/pager.html",replace:!0,link:function(b,c,d,e){var f=e[0],g=e[1];g&&(b.align=angular.isDefined(d.align)?b.$parent.$eval(d.align):a.align,f.init(g,a))}}}]),angular.module("ui.bootstrap.tooltip",["ui.bootstrap.position","ui.bootstrap.bindHtml"]).provider("$tooltip",function(){function a(a){var b=/[A-Z]/g,c="-";return a.replace(b,function(a,b){return(b?c:"")+a.toLowerCase() +})}var b={placement:"top",animation:!0,popupDelay:0},c={mouseenter:"mouseleave",click:"click",focus:"blur"},d={};this.options=function(a){angular.extend(d,a)},this.setTriggers=function(a){angular.extend(c,a)},this.$get=["$window","$compile","$timeout","$document","$position","$interpolate",function(e,f,g,h,i,j){return function(e,k,l){function m(a){var b=a||n.trigger||l,d=c[b]||b;return{show:b,hide:d}}var n=angular.extend({},b,d),o=a(e),p=j.startSymbol(),q=j.endSymbol(),r="
      ';return{restrict:"EA",compile:function(){var a=f(r);return function(b,c,d){function f(){D.isOpen?l():j()}function j(){(!C||b.$eval(d[k+"Enable"]))&&(s(),D.popupDelay?z||(z=g(o,D.popupDelay,!1),z.then(function(a){a()})):o()())}function l(){b.$apply(function(){p()})}function o(){return z=null,y&&(g.cancel(y),y=null),D.content?(q(),w.css({top:0,left:0,display:"block"}),A?h.find("body").append(w):c.after(w),E(),D.isOpen=!0,D.$digest(),E):angular.noop}function p(){D.isOpen=!1,g.cancel(z),z=null,D.animation?y||(y=g(r,500)):r()}function q(){w&&r(),x=D.$new(),w=a(x,angular.noop)}function r(){y=null,w&&(w.remove(),w=null),x&&(x.$destroy(),x=null)}function s(){t(),u()}function t(){var a=d[k+"Placement"];D.placement=angular.isDefined(a)?a:n.placement}function u(){var a=d[k+"PopupDelay"],b=parseInt(a,10);D.popupDelay=isNaN(b)?n.popupDelay:b}function v(){var a=d[k+"Trigger"];F(),B=m(a),B.show===B.hide?c.bind(B.show,f):(c.bind(B.show,j),c.bind(B.hide,l))}var w,x,y,z,A=angular.isDefined(n.appendToBody)?n.appendToBody:!1,B=m(void 0),C=angular.isDefined(d[k+"Enable"]),D=b.$new(!0),E=function(){var a=i.positionElements(c,w,D.placement,A);a.top+="px",a.left+="px",w.css(a)};D.isOpen=!1,d.$observe(e,function(a){D.content=a,!a&&D.isOpen&&p()}),d.$observe(k+"Title",function(a){D.title=a});var F=function(){c.unbind(B.show,j),c.unbind(B.hide,l)};v();var G=b.$eval(d[k+"Animation"]);D.animation=angular.isDefined(G)?!!G:n.animation;var H=b.$eval(d[k+"AppendToBody"]);A=angular.isDefined(H)?H:A,A&&b.$on("$locationChangeSuccess",function(){D.isOpen&&p()}),b.$on("$destroy",function(){g.cancel(y),g.cancel(z),F(),r(),D=null})}}}}}]}).directive("tooltipPopup",function(){return{restrict:"EA",replace:!0,scope:{content:"@",placement:"@",animation:"&",isOpen:"&"},templateUrl:"template/tooltip/tooltip-popup.html"}}).directive("tooltip",["$tooltip",function(a){return a("tooltip","tooltip","mouseenter")}]).directive("tooltipHtmlUnsafePopup",function(){return{restrict:"EA",replace:!0,scope:{content:"@",placement:"@",animation:"&",isOpen:"&"},templateUrl:"template/tooltip/tooltip-html-unsafe-popup.html"}}).directive("tooltipHtmlUnsafe",["$tooltip",function(a){return a("tooltipHtmlUnsafe","tooltip","mouseenter")}]),angular.module("ui.bootstrap.popover",["ui.bootstrap.tooltip"]).directive("popoverPopup",function(){return{restrict:"EA",replace:!0,scope:{title:"@",content:"@",placement:"@",animation:"&",isOpen:"&"},templateUrl:"template/popover/popover.html"}}).directive("popover",["$tooltip",function(a){return a("popover","popover","click")}]),angular.module("ui.bootstrap.progressbar",[]).constant("progressConfig",{animate:!0,max:100}).controller("ProgressController",["$scope","$attrs","progressConfig",function(a,b,c){var d=this,e=angular.isDefined(b.animate)?a.$parent.$eval(b.animate):c.animate;this.bars=[],a.max=angular.isDefined(b.max)?a.$parent.$eval(b.max):c.max,this.addBar=function(b,c){e||c.css({transition:"none"}),this.bars.push(b),b.$watch("value",function(c){b.percent=+(100*c/a.max).toFixed(2)}),b.$on("$destroy",function(){c=null,d.removeBar(b)})},this.removeBar=function(a){this.bars.splice(this.bars.indexOf(a),1)}}]).directive("progress",function(){return{restrict:"EA",replace:!0,transclude:!0,controller:"ProgressController",require:"progress",scope:{},templateUrl:"template/progressbar/progress.html"}}).directive("bar",function(){return{restrict:"EA",replace:!0,transclude:!0,require:"^progress",scope:{value:"=",type:"@"},templateUrl:"template/progressbar/bar.html",link:function(a,b,c,d){d.addBar(a,b)}}}).directive("progressbar",function(){return{restrict:"EA",replace:!0,transclude:!0,controller:"ProgressController",scope:{value:"=",type:"@"},templateUrl:"template/progressbar/progressbar.html",link:function(a,b,c,d){d.addBar(a,angular.element(b.children()[0]))}}}),angular.module("ui.bootstrap.rating",[]).constant("ratingConfig",{max:5,stateOn:null,stateOff:null}).controller("RatingController",["$scope","$attrs","ratingConfig",function(a,b,c){var d={$setViewValue:angular.noop};this.init=function(e){d=e,d.$render=this.render,this.stateOn=angular.isDefined(b.stateOn)?a.$parent.$eval(b.stateOn):c.stateOn,this.stateOff=angular.isDefined(b.stateOff)?a.$parent.$eval(b.stateOff):c.stateOff;var f=angular.isDefined(b.ratingStates)?a.$parent.$eval(b.ratingStates):new Array(angular.isDefined(b.max)?a.$parent.$eval(b.max):c.max);a.range=this.buildTemplateObjects(f)},this.buildTemplateObjects=function(a){for(var b=0,c=a.length;c>b;b++)a[b]=angular.extend({index:b},{stateOn:this.stateOn,stateOff:this.stateOff},a[b]);return a},a.rate=function(b){!a.readonly&&b>=0&&b<=a.range.length&&(d.$setViewValue(b),d.$render())},a.enter=function(b){a.readonly||(a.value=b),a.onHover({value:b})},a.reset=function(){a.value=d.$viewValue,a.onLeave()},a.onKeydown=function(b){/(37|38|39|40)/.test(b.which)&&(b.preventDefault(),b.stopPropagation(),a.rate(a.value+(38===b.which||39===b.which?1:-1)))},this.render=function(){a.value=d.$viewValue}}]).directive("rating",function(){return{restrict:"EA",require:["rating","ngModel"],scope:{readonly:"=?",onHover:"&",onLeave:"&"},controller:"RatingController",templateUrl:"template/rating/rating.html",replace:!0,link:function(a,b,c,d){var e=d[0],f=d[1];f&&e.init(f)}}}),angular.module("ui.bootstrap.tabs",[]).controller("TabsetController",["$scope",function(a){var b=this,c=b.tabs=a.tabs=[];b.select=function(a){angular.forEach(c,function(b){b.active&&b!==a&&(b.active=!1,b.onDeselect())}),a.active=!0,a.onSelect()},b.addTab=function(a){c.push(a),1===c.length?a.active=!0:a.active&&b.select(a)},b.removeTab=function(a){var e=c.indexOf(a);if(a.active&&c.length>1&&!d){var f=e==c.length-1?e-1:e+1;b.select(c[f])}c.splice(e,1)};var d;a.$on("$destroy",function(){d=!0})}]).directive("tabset",function(){return{restrict:"EA",transclude:!0,replace:!0,scope:{type:"@"},controller:"TabsetController",templateUrl:"template/tabs/tabset.html",link:function(a,b,c){a.vertical=angular.isDefined(c.vertical)?a.$parent.$eval(c.vertical):!1,a.justified=angular.isDefined(c.justified)?a.$parent.$eval(c.justified):!1}}}).directive("tab",["$parse",function(a){return{require:"^tabset",restrict:"EA",replace:!0,templateUrl:"template/tabs/tab.html",transclude:!0,scope:{active:"=?",heading:"@",onSelect:"&select",onDeselect:"&deselect"},controller:function(){},compile:function(b,c,d){return function(b,c,e,f){b.$watch("active",function(a){a&&f.select(b)}),b.disabled=!1,e.disabled&&b.$parent.$watch(a(e.disabled),function(a){b.disabled=!!a}),b.select=function(){b.disabled||(b.active=!0)},f.addTab(b),b.$on("$destroy",function(){f.removeTab(b)}),b.$transcludeFn=d}}}}]).directive("tabHeadingTransclude",[function(){return{restrict:"A",require:"^tab",link:function(a,b){a.$watch("headingElement",function(a){a&&(b.html(""),b.append(a))})}}}]).directive("tabContentTransclude",function(){function a(a){return a.tagName&&(a.hasAttribute("tab-heading")||a.hasAttribute("data-tab-heading")||"tab-heading"===a.tagName.toLowerCase()||"data-tab-heading"===a.tagName.toLowerCase())}return{restrict:"A",require:"^tabset",link:function(b,c,d){var e=b.$eval(d.tabContentTransclude);e.$transcludeFn(e.$parent,function(b){angular.forEach(b,function(b){a(b)?e.headingElement=b:c.append(b)})})}}}),angular.module("ui.bootstrap.timepicker",[]).constant("timepickerConfig",{hourStep:1,minuteStep:1,showMeridian:!0,meridians:null,readonlyInput:!1,mousewheel:!0}).controller("TimepickerController",["$scope","$attrs","$parse","$log","$locale","timepickerConfig",function(a,b,c,d,e,f){function g(){var b=parseInt(a.hours,10),c=a.showMeridian?b>0&&13>b:b>=0&&24>b;return c?(a.showMeridian&&(12===b&&(b=0),a.meridian===p[1]&&(b+=12)),b):void 0}function h(){var b=parseInt(a.minutes,10);return b>=0&&60>b?b:void 0}function i(a){return angular.isDefined(a)&&a.toString().length<2?"0"+a:a}function j(a){k(),o.$setViewValue(new Date(n)),l(a)}function k(){o.$setValidity("time",!0),a.invalidHours=!1,a.invalidMinutes=!1}function l(b){var c=n.getHours(),d=n.getMinutes();a.showMeridian&&(c=0===c||12===c?12:c%12),a.hours="h"===b?c:i(c),a.minutes="m"===b?d:i(d),a.meridian=n.getHours()<12?p[0]:p[1]}function m(a){var b=new Date(n.getTime()+6e4*a);n.setHours(b.getHours(),b.getMinutes()),j()}var n=new Date,o={$setViewValue:angular.noop},p=angular.isDefined(b.meridians)?a.$parent.$eval(b.meridians):f.meridians||e.DATETIME_FORMATS.AMPMS;this.init=function(c,d){o=c,o.$render=this.render;var e=d.eq(0),g=d.eq(1),h=angular.isDefined(b.mousewheel)?a.$parent.$eval(b.mousewheel):f.mousewheel;h&&this.setupMousewheelEvents(e,g),a.readonlyInput=angular.isDefined(b.readonlyInput)?a.$parent.$eval(b.readonlyInput):f.readonlyInput,this.setupInputEvents(e,g)};var q=f.hourStep;b.hourStep&&a.$parent.$watch(c(b.hourStep),function(a){q=parseInt(a,10)});var r=f.minuteStep;b.minuteStep&&a.$parent.$watch(c(b.minuteStep),function(a){r=parseInt(a,10)}),a.showMeridian=f.showMeridian,b.showMeridian&&a.$parent.$watch(c(b.showMeridian),function(b){if(a.showMeridian=!!b,o.$error.time){var c=g(),d=h();angular.isDefined(c)&&angular.isDefined(d)&&(n.setHours(c),j())}else l()}),this.setupMousewheelEvents=function(b,c){var d=function(a){a.originalEvent&&(a=a.originalEvent);var b=a.wheelDelta?a.wheelDelta:-a.deltaY;return a.detail||b>0};b.bind("mousewheel wheel",function(b){a.$apply(d(b)?a.incrementHours():a.decrementHours()),b.preventDefault()}),c.bind("mousewheel wheel",function(b){a.$apply(d(b)?a.incrementMinutes():a.decrementMinutes()),b.preventDefault()})},this.setupInputEvents=function(b,c){if(a.readonlyInput)return a.updateHours=angular.noop,void(a.updateMinutes=angular.noop);var d=function(b,c){o.$setViewValue(null),o.$setValidity("time",!1),angular.isDefined(b)&&(a.invalidHours=b),angular.isDefined(c)&&(a.invalidMinutes=c)};a.updateHours=function(){var a=g();angular.isDefined(a)?(n.setHours(a),j("h")):d(!0)},b.bind("blur",function(){!a.invalidHours&&a.hours<10&&a.$apply(function(){a.hours=i(a.hours)})}),a.updateMinutes=function(){var a=h();angular.isDefined(a)?(n.setMinutes(a),j("m")):d(void 0,!0)},c.bind("blur",function(){!a.invalidMinutes&&a.minutes<10&&a.$apply(function(){a.minutes=i(a.minutes)})})},this.render=function(){var a=o.$modelValue?new Date(o.$modelValue):null;isNaN(a)?(o.$setValidity("time",!1),d.error('Timepicker directive: "ng-model" value must be a Date object, a number of milliseconds since 01.01.1970 or a string representing an RFC2822 or ISO 8601 date.')):(a&&(n=a),k(),l())},a.incrementHours=function(){m(60*q)},a.decrementHours=function(){m(60*-q)},a.incrementMinutes=function(){m(r)},a.decrementMinutes=function(){m(-r)},a.toggleMeridian=function(){m(720*(n.getHours()<12?1:-1))}}]).directive("timepicker",function(){return{restrict:"EA",require:["timepicker","?^ngModel"],controller:"TimepickerController",replace:!0,scope:{},templateUrl:"template/timepicker/timepicker.html",link:function(a,b,c,d){var e=d[0],f=d[1];f&&e.init(f,b.find("input"))}}}),angular.module("ui.bootstrap.typeahead",["ui.bootstrap.position","ui.bootstrap.bindHtml"]).factory("typeaheadParser",["$parse",function(a){var b=/^\s*([\s\S]+?)(?:\s+as\s+([\s\S]+?))?\s+for\s+(?:([\$\w][\$\w\d]*))\s+in\s+([\s\S]+?)$/;return{parse:function(c){var d=c.match(b);if(!d)throw new Error('Expected typeahead specification in form of "_modelValue_ (as _label_)? for _item_ in _collection_" but got "'+c+'".');return{itemName:d[3],source:a(d[4]),viewMapper:a(d[2]||d[1]),modelMapper:a(d[1])}}}}]).directive("typeahead",["$compile","$parse","$q","$timeout","$document","$position","typeaheadParser",function(a,b,c,d,e,f,g){var h=[9,13,27,38,40];return{require:"ngModel",link:function(i,j,k,l){var m,n=i.$eval(k.typeaheadMinLength)||1,o=i.$eval(k.typeaheadWaitMs)||0,p=i.$eval(k.typeaheadEditable)!==!1,q=b(k.typeaheadLoading).assign||angular.noop,r=b(k.typeaheadOnSelect),s=k.typeaheadInputFormatter?b(k.typeaheadInputFormatter):void 0,t=k.typeaheadAppendToBody?i.$eval(k.typeaheadAppendToBody):!1,u=i.$eval(k.typeaheadFocusFirst)!==!1,v=b(k.ngModel).assign,w=g.parse(k.typeahead),x=i.$new();i.$on("$destroy",function(){x.$destroy()});var y="typeahead-"+x.$id+"-"+Math.floor(1e4*Math.random());j.attr({"aria-autocomplete":"list","aria-expanded":!1,"aria-owns":y});var z=angular.element("
      ");z.attr({id:y,matches:"matches",active:"activeIdx",select:"select(activeIdx)",query:"query",position:"position"}),angular.isDefined(k.typeaheadTemplateUrl)&&z.attr("template-url",k.typeaheadTemplateUrl);var A=function(){x.matches=[],x.activeIdx=-1,j.attr("aria-expanded",!1)},B=function(a){return y+"-option-"+a};x.$watch("activeIdx",function(a){0>a?j.removeAttr("aria-activedescendant"):j.attr("aria-activedescendant",B(a))});var C=function(a){var b={$viewValue:a};q(i,!0),c.when(w.source(i,b)).then(function(c){var d=a===l.$viewValue;if(d&&m)if(c.length>0){x.activeIdx=u?0:-1,x.matches.length=0;for(var e=0;e=n?o>0?(F(),E(a)):C(a):(q(i,!1),F(),A()),p?a:a?void l.$setValidity("editable",!1):(l.$setValidity("editable",!0),a)}),l.$formatters.push(function(a){var b,c,d={};return s?(d.$model=a,s(i,d)):(d[w.itemName]=a,b=w.viewMapper(i,d),d[w.itemName]=void 0,c=w.viewMapper(i,d),b!==c?b:a)}),x.select=function(a){var b,c,e={};e[w.itemName]=c=x.matches[a].model,b=w.modelMapper(i,e),v(i,b),l.$setValidity("editable",!0),r(i,{$item:c,$model:b,$label:w.viewMapper(i,e)}),A(),d(function(){j[0].focus()},0,!1)},j.bind("keydown",function(a){0!==x.matches.length&&-1!==h.indexOf(a.which)&&(-1!=x.activeIdx||13!==a.which&&9!==a.which)&&(a.preventDefault(),40===a.which?(x.activeIdx=(x.activeIdx+1)%x.matches.length,x.$digest()):38===a.which?(x.activeIdx=(x.activeIdx>0?x.activeIdx:x.matches.length)-1,x.$digest()):13===a.which||9===a.which?x.$apply(function(){x.select(x.activeIdx)}):27===a.which&&(a.stopPropagation(),A(),x.$digest()))}),j.bind("blur",function(){m=!1});var G=function(a){j[0]!==a.target&&(A(),x.$digest())};e.bind("click",G),i.$on("$destroy",function(){e.unbind("click",G),t&&H.remove()});var H=a(z)(x);t?e.find("body").append(H):j.after(H)}}}]).directive("typeaheadPopup",function(){return{restrict:"EA",scope:{matches:"=",query:"=",active:"=",position:"=",select:"&"},replace:!0,templateUrl:"template/typeahead/typeahead-popup.html",link:function(a,b,c){a.templateUrl=c.templateUrl,a.isOpen=function(){return a.matches.length>0},a.isActive=function(b){return a.active==b},a.selectActive=function(b){a.active=b},a.selectMatch=function(b){a.select({activeIdx:b})}}}}).directive("typeaheadMatch",["$http","$templateCache","$compile","$parse",function(a,b,c,d){return{restrict:"EA",scope:{index:"=",match:"=",query:"="},link:function(e,f,g){var h=d(g.templateUrl)(e.$parent)||"template/typeahead/typeahead-match.html";a.get(h,{cache:b}).success(function(a){f.replaceWith(c(a.trim())(e))})}}}]).filter("typeaheadHighlight",function(){function a(a){return a.replace(/([.?*+^$[\]\\(){}|-])/g,"\\$1")}return function(b,c){return c?(""+b).replace(new RegExp(a(c),"gi"),"$&"):b}}); \ No newline at end of file diff --git a/public/admincp/bower_components/angular-cookies/.bower.json b/public/admincp/bower_components/angular-cookies/.bower.json new file mode 100644 index 000000000..e3bb851f0 --- /dev/null +++ b/public/admincp/bower_components/angular-cookies/.bower.json @@ -0,0 +1,19 @@ +{ + "name": "angular-cookies", + "version": "1.3.8", + "main": "./angular-cookies.js", + "ignore": [], + "dependencies": { + "angular": "1.3.8" + }, + "homepage": "https://github.com/angular/bower-angular-cookies", + "_release": "1.3.8", + "_resolution": { + "type": "version", + "tag": "v1.3.8", + "commit": "9596f90e57ce1cd534fe3f0afdf3642aae343668" + }, + "_source": "git://github.com/angular/bower-angular-cookies.git", + "_target": "~1.3.1", + "_originalSource": "angular-cookies" +} \ No newline at end of file diff --git a/public/admincp/bower_components/angular-cookies/README.md b/public/admincp/bower_components/angular-cookies/README.md new file mode 100644 index 000000000..a1dc09bc5 --- /dev/null +++ b/public/admincp/bower_components/angular-cookies/README.md @@ -0,0 +1,77 @@ +# packaged angular-cookies + +This repo is for distribution on `npm` and `bower`. The source for this module is in the +[main AngularJS repo](https://github.com/angular/angular.js/tree/master/src/ngCookies). +Please file issues and pull requests against that repo. + +## Install + +You can install this package either with `npm` or with `bower`. + +### npm + +```shell +npm install angular-cookies +``` + +Add a ` +``` + +Then add `ngCookies` as a dependency for your app: + +```javascript +angular.module('myApp', ['ngCookies']); +``` + +Note that this package is not in CommonJS format, so doing `require('angular-cookies')` will +return `undefined`. + +### bower + +```shell +bower install angular-cookies +``` + +Add a ` +``` + +Then add `ngCookies` as a dependency for your app: + +```javascript +angular.module('myApp', ['ngCookies']); +``` + +## Documentation + +Documentation is available on the +[AngularJS docs site](http://docs.angularjs.org/api/ngCookies). + +## License + +The MIT License + +Copyright (c) 2010-2012 Google, Inc. http://angularjs.org + +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/public/admincp/bower_components/angular-cookies/angular-cookies.js b/public/admincp/bower_components/angular-cookies/angular-cookies.js new file mode 100644 index 000000000..ab6748fb3 --- /dev/null +++ b/public/admincp/bower_components/angular-cookies/angular-cookies.js @@ -0,0 +1,206 @@ +/** + * @license AngularJS v1.3.8 + * (c) 2010-2014 Google, Inc. http://angularjs.org + * License: MIT + */ +(function(window, angular, undefined) {'use strict'; + +/** + * @ngdoc module + * @name ngCookies + * @description + * + * # ngCookies + * + * The `ngCookies` module provides a convenient wrapper for reading and writing browser cookies. + * + * + *
      + * + * See {@link ngCookies.$cookies `$cookies`} and + * {@link ngCookies.$cookieStore `$cookieStore`} for usage. + */ + + +angular.module('ngCookies', ['ng']). + /** + * @ngdoc service + * @name $cookies + * + * @description + * Provides read/write access to browser's cookies. + * + * Only a simple Object is exposed and by adding or removing properties to/from this object, new + * cookies are created/deleted at the end of current $eval. + * The object's properties can only be strings. + * + * Requires the {@link ngCookies `ngCookies`} module to be installed. + * + * @example + * + * ```js + * angular.module('cookiesExample', ['ngCookies']) + * .controller('ExampleController', ['$cookies', function($cookies) { + * // Retrieving a cookie + * var favoriteCookie = $cookies.myFavorite; + * // Setting a cookie + * $cookies.myFavorite = 'oatmeal'; + * }]); + * ``` + */ + factory('$cookies', ['$rootScope', '$browser', function($rootScope, $browser) { + var cookies = {}, + lastCookies = {}, + lastBrowserCookies, + runEval = false, + copy = angular.copy, + isUndefined = angular.isUndefined; + + //creates a poller fn that copies all cookies from the $browser to service & inits the service + $browser.addPollFn(function() { + var currentCookies = $browser.cookies(); + if (lastBrowserCookies != currentCookies) { //relies on browser.cookies() impl + lastBrowserCookies = currentCookies; + copy(currentCookies, lastCookies); + copy(currentCookies, cookies); + if (runEval) $rootScope.$apply(); + } + })(); + + runEval = true; + + //at the end of each eval, push cookies + //TODO: this should happen before the "delayed" watches fire, because if some cookies are not + // strings or browser refuses to store some cookies, we update the model in the push fn. + $rootScope.$watch(push); + + return cookies; + + + /** + * Pushes all the cookies from the service to the browser and verifies if all cookies were + * stored. + */ + function push() { + var name, + value, + browserCookies, + updated; + + //delete any cookies deleted in $cookies + for (name in lastCookies) { + if (isUndefined(cookies[name])) { + $browser.cookies(name, undefined); + } + } + + //update all cookies updated in $cookies + for (name in cookies) { + value = cookies[name]; + if (!angular.isString(value)) { + value = '' + value; + cookies[name] = value; + } + if (value !== lastCookies[name]) { + $browser.cookies(name, value); + updated = true; + } + } + + //verify what was actually stored + if (updated) { + updated = false; + browserCookies = $browser.cookies(); + + for (name in cookies) { + if (cookies[name] !== browserCookies[name]) { + //delete or reset all cookies that the browser dropped from $cookies + if (isUndefined(browserCookies[name])) { + delete cookies[name]; + } else { + cookies[name] = browserCookies[name]; + } + updated = true; + } + } + } + } + }]). + + + /** + * @ngdoc service + * @name $cookieStore + * @requires $cookies + * + * @description + * Provides a key-value (string-object) storage, that is backed by session cookies. + * Objects put or retrieved from this storage are automatically serialized or + * deserialized by angular's toJson/fromJson. + * + * Requires the {@link ngCookies `ngCookies`} module to be installed. + * + * @example + * + * ```js + * angular.module('cookieStoreExample', ['ngCookies']) + * .controller('ExampleController', ['$cookieStore', function($cookieStore) { + * // Put cookie + * $cookieStore.put('myFavorite','oatmeal'); + * // Get cookie + * var favoriteCookie = $cookieStore.get('myFavorite'); + * // Removing a cookie + * $cookieStore.remove('myFavorite'); + * }]); + * ``` + */ + factory('$cookieStore', ['$cookies', function($cookies) { + + return { + /** + * @ngdoc method + * @name $cookieStore#get + * + * @description + * Returns the value of given cookie key + * + * @param {string} key Id to use for lookup. + * @returns {Object} Deserialized cookie value. + */ + get: function(key) { + var value = $cookies[key]; + return value ? angular.fromJson(value) : value; + }, + + /** + * @ngdoc method + * @name $cookieStore#put + * + * @description + * Sets a value for given cookie key + * + * @param {string} key Id for the `value`. + * @param {Object} value Value to be stored. + */ + put: function(key, value) { + $cookies[key] = angular.toJson(value); + }, + + /** + * @ngdoc method + * @name $cookieStore#remove + * + * @description + * Remove given cookie + * + * @param {string} key Id of the key-value pair to delete. + */ + remove: function(key) { + delete $cookies[key]; + } + }; + + }]); + + +})(window, window.angular); diff --git a/public/admincp/bower_components/angular-cookies/angular-cookies.min.js b/public/admincp/bower_components/angular-cookies/angular-cookies.min.js new file mode 100644 index 000000000..a1393208a --- /dev/null +++ b/public/admincp/bower_components/angular-cookies/angular-cookies.min.js @@ -0,0 +1,8 @@ +/* + AngularJS v1.3.8 + (c) 2010-2014 Google, Inc. http://angularjs.org + License: MIT +*/ +(function(p,f,n){'use strict';f.module("ngCookies",["ng"]).factory("$cookies",["$rootScope","$browser",function(e,b){var c={},g={},h,k=!1,l=f.copy,m=f.isUndefined;b.addPollFn(function(){var a=b.cookies();h!=a&&(h=a,l(a,g),l(a,c),k&&e.$apply())})();k=!0;e.$watch(function(){var a,d,e;for(a in g)m(c[a])&&b.cookies(a,n);for(a in c)d=c[a],f.isString(d)||(d=""+d,c[a]=d),d!==g[a]&&(b.cookies(a,d),e=!0);if(e)for(a in d=b.cookies(),c)c[a]!==d[a]&&(m(d[a])?delete c[a]:c[a]=d[a])});return c}]).factory("$cookieStore", +["$cookies",function(e){return{get:function(b){return(b=e[b])?f.fromJson(b):b},put:function(b,c){e[b]=f.toJson(c)},remove:function(b){delete e[b]}}}])})(window,window.angular); +//# sourceMappingURL=angular-cookies.min.js.map diff --git a/public/admincp/bower_components/angular-cookies/angular-cookies.min.js.map b/public/admincp/bower_components/angular-cookies/angular-cookies.min.js.map new file mode 100644 index 000000000..677960c59 --- /dev/null +++ b/public/admincp/bower_components/angular-cookies/angular-cookies.min.js.map @@ -0,0 +1,8 @@ +{ +"version":3, +"file":"angular-cookies.min.js", +"lineCount":7, +"mappings":"A;;;;;aAKC,SAAQ,CAACA,CAAD,CAASC,CAAT,CAAkBC,CAAlB,CAA6B,CAmBtCD,CAAAE,OAAA,CAAe,WAAf,CAA4B,CAAC,IAAD,CAA5B,CAAAC,QAAA,CA0BW,UA1BX,CA0BuB,CAAC,YAAD,CAAe,UAAf,CAA2B,QAAQ,CAACC,CAAD,CAAaC,CAAb,CAAuB,CAAA,IACvEC,EAAU,EAD6D,CAEvEC,EAAc,EAFyD,CAGvEC,CAHuE,CAIvEC,EAAU,CAAA,CAJ6D,CAKvEC,EAAOV,CAAAU,KALgE,CAMvEC,EAAcX,CAAAW,YAGlBN,EAAAO,UAAA,CAAmB,QAAQ,EAAG,CAC5B,IAAIC,EAAiBR,CAAAC,QAAA,EACjBE,EAAJ,EAA0BK,CAA1B,GACEL,CAGA,CAHqBK,CAGrB,CAFAH,CAAA,CAAKG,CAAL,CAAqBN,CAArB,CAEA,CADAG,CAAA,CAAKG,CAAL,CAAqBP,CAArB,CACA,CAAIG,CAAJ,EAAaL,CAAAU,OAAA,EAJf,CAF4B,CAA9B,CAAA,EAUAL,EAAA,CAAU,CAAA,CAKVL,EAAAW,OAAA,CASAC,QAAa,EAAG,CAAA,IACVC,CADU,CAEVC,CAFU,CAIVC,CAGJ,KAAKF,CAAL,GAAaV,EAAb,CACMI,CAAA,CAAYL,CAAA,CAAQW,CAAR,CAAZ,CAAJ,EACEZ,CAAAC,QAAA,CAAiBW,CAAjB,CAAuBhB,CAAvB,CAKJ,KAAKgB,CAAL,GAAaX,EAAb,CACEY,CAKA,CALQZ,CAAA,CAAQW,CAAR,CAKR,CAJKjB,CAAAoB,SAAA,CAAiBF,CAAjB,CAIL,GAHEA,CACA,CADQ,EACR,CADaA,CACb,CAAAZ,CAAA,CAAQW,CAAR,CAAA,CAAgBC,CAElB,EAAIA,CAAJ,GAAcX,CAAA,CAAYU,CAAZ,CAAd,GACEZ,CAAAC,QAAA,CAAiBW,CAAjB,CAAuBC,CAAvB,CACA,CAAAC,CAAA,CAAU,CAAA,CAFZ,CAOF,IAAIA,CAAJ,CAIE,IAAKF,CAAL,GAFAI,EAEaf,CAFID,CAAAC,QAAA,EAEJA,CAAAA,CAAb,CACMA,CAAA,CAAQW,CAAR,CAAJ,GAAsBI,CAAA,CAAeJ,CAAf,CAAtB,GAEMN,CAAA,CAAYU,CAAA,CAAeJ,CAAf,CAAZ,CAAJ,CACE,OAAOX,CAAA,CAAQW,CAAR,CADT,CAGEX,CAAA,CAAQW,CAAR,CAHF,CAGkBI,CAAA,CAAeJ,CAAf,CALpB,CAhCU,CAThB,CAEA,OAAOX,EA1BoE,CAA1D,CA1BvB,CAAAH,QAAA,CAoIW,cApIX;AAoI2B,CAAC,UAAD,CAAa,QAAQ,CAACmB,CAAD,CAAW,CAErD,MAAO,CAWLC,IAAKA,QAAQ,CAACC,CAAD,CAAM,CAEjB,MAAO,CADHN,CACG,CADKI,CAAA,CAASE,CAAT,CACL,EAAQxB,CAAAyB,SAAA,CAAiBP,CAAjB,CAAR,CAAkCA,CAFxB,CAXd,CA0BLQ,IAAKA,QAAQ,CAACF,CAAD,CAAMN,CAAN,CAAa,CACxBI,CAAA,CAASE,CAAT,CAAA,CAAgBxB,CAAA2B,OAAA,CAAeT,CAAf,CADQ,CA1BrB,CAuCLU,OAAQA,QAAQ,CAACJ,CAAD,CAAM,CACpB,OAAOF,CAAA,CAASE,CAAT,CADa,CAvCjB,CAF8C,CAAhC,CApI3B,CAnBsC,CAArC,CAAD,CAwMGzB,MAxMH,CAwMWA,MAAAC,QAxMX;", +"sources":["angular-cookies.js"], +"names":["window","angular","undefined","module","factory","$rootScope","$browser","cookies","lastCookies","lastBrowserCookies","runEval","copy","isUndefined","addPollFn","currentCookies","$apply","$watch","push","name","value","updated","isString","browserCookies","$cookies","get","key","fromJson","put","toJson","remove"] +} diff --git a/public/admincp/bower_components/angular-cookies/bower.json b/public/admincp/bower_components/angular-cookies/bower.json new file mode 100644 index 000000000..ae2912461 --- /dev/null +++ b/public/admincp/bower_components/angular-cookies/bower.json @@ -0,0 +1,9 @@ +{ + "name": "angular-cookies", + "version": "1.3.8", + "main": "./angular-cookies.js", + "ignore": [], + "dependencies": { + "angular": "1.3.8" + } +} diff --git a/public/admincp/bower_components/angular-cookies/package.json b/public/admincp/bower_components/angular-cookies/package.json new file mode 100644 index 000000000..da9229684 --- /dev/null +++ b/public/admincp/bower_components/angular-cookies/package.json @@ -0,0 +1,26 @@ +{ + "name": "angular-cookies", + "version": "1.3.8", + "description": "AngularJS module for cookies", + "main": "angular-cookies.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "repository": { + "type": "git", + "url": "https://github.com/angular/angular.js.git" + }, + "keywords": [ + "angular", + "framework", + "browser", + "cookies", + "client-side" + ], + "author": "Angular Core Team ", + "license": "MIT", + "bugs": { + "url": "https://github.com/angular/angular.js/issues" + }, + "homepage": "http://angularjs.org" +} diff --git a/public/admincp/bower_components/angular-resource/.bower.json b/public/admincp/bower_components/angular-resource/.bower.json new file mode 100644 index 000000000..88646058a --- /dev/null +++ b/public/admincp/bower_components/angular-resource/.bower.json @@ -0,0 +1,19 @@ +{ + "name": "angular-resource", + "version": "1.3.8", + "main": "./angular-resource.js", + "ignore": [], + "dependencies": { + "angular": "1.3.8" + }, + "homepage": "https://github.com/angular/bower-angular-resource", + "_release": "1.3.8", + "_resolution": { + "type": "version", + "tag": "v1.3.8", + "commit": "6a0ac09fd580dc8d78c355f7785a696c0f95846b" + }, + "_source": "git://github.com/angular/bower-angular-resource.git", + "_target": "~1.3.1", + "_originalSource": "angular-resource" +} \ No newline at end of file diff --git a/public/admincp/bower_components/angular-resource/README.md b/public/admincp/bower_components/angular-resource/README.md new file mode 100644 index 000000000..b09e0a7b6 --- /dev/null +++ b/public/admincp/bower_components/angular-resource/README.md @@ -0,0 +1,77 @@ +# packaged angular-resource + +This repo is for distribution on `npm` and `bower`. The source for this module is in the +[main AngularJS repo](https://github.com/angular/angular.js/tree/master/src/ngResource). +Please file issues and pull requests against that repo. + +## Install + +You can install this package either with `npm` or with `bower`. + +### npm + +```shell +npm install angular-resource +``` + +Add a ` +``` + +Then add `ngResource` as a dependency for your app: + +```javascript +angular.module('myApp', ['ngResource']); +``` + +Note that this package is not in CommonJS format, so doing `require('angular-resource')` will +return `undefined`. + +### bower + +```shell +bower install angular-resource +``` + +Add a ` +``` + +Then add `ngResource` as a dependency for your app: + +```javascript +angular.module('myApp', ['ngResource']); +``` + +## Documentation + +Documentation is available on the +[AngularJS docs site](http://docs.angularjs.org/api/ngResource). + +## License + +The MIT License + +Copyright (c) 2010-2012 Google, Inc. http://angularjs.org + +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/public/admincp/bower_components/angular-resource/angular-resource.js b/public/admincp/bower_components/angular-resource/angular-resource.js new file mode 100644 index 000000000..50afdc88f --- /dev/null +++ b/public/admincp/bower_components/angular-resource/angular-resource.js @@ -0,0 +1,667 @@ +/** + * @license AngularJS v1.3.8 + * (c) 2010-2014 Google, Inc. http://angularjs.org + * License: MIT + */ +(function(window, angular, undefined) {'use strict'; + +var $resourceMinErr = angular.$$minErr('$resource'); + +// Helper functions and regex to lookup a dotted path on an object +// stopping at undefined/null. The path must be composed of ASCII +// identifiers (just like $parse) +var MEMBER_NAME_REGEX = /^(\.[a-zA-Z_$][0-9a-zA-Z_$]*)+$/; + +function isValidDottedPath(path) { + return (path != null && path !== '' && path !== 'hasOwnProperty' && + MEMBER_NAME_REGEX.test('.' + path)); +} + +function lookupDottedPath(obj, path) { + if (!isValidDottedPath(path)) { + throw $resourceMinErr('badmember', 'Dotted member path "@{0}" is invalid.', path); + } + var keys = path.split('.'); + for (var i = 0, ii = keys.length; i < ii && obj !== undefined; i++) { + var key = keys[i]; + obj = (obj !== null) ? obj[key] : undefined; + } + return obj; +} + +/** + * Create a shallow copy of an object and clear other fields from the destination + */ +function shallowClearAndCopy(src, dst) { + dst = dst || {}; + + angular.forEach(dst, function(value, key) { + delete dst[key]; + }); + + for (var key in src) { + if (src.hasOwnProperty(key) && !(key.charAt(0) === '$' && key.charAt(1) === '$')) { + dst[key] = src[key]; + } + } + + return dst; +} + +/** + * @ngdoc module + * @name ngResource + * @description + * + * # ngResource + * + * The `ngResource` module provides interaction support with RESTful services + * via the $resource service. + * + * + *
      + * + * See {@link ngResource.$resource `$resource`} for usage. + */ + +/** + * @ngdoc service + * @name $resource + * @requires $http + * + * @description + * A factory which creates a resource object that lets you interact with + * [RESTful](http://en.wikipedia.org/wiki/Representational_State_Transfer) server-side data sources. + * + * The returned resource object has action methods which provide high-level behaviors without + * the need to interact with the low level {@link ng.$http $http} service. + * + * Requires the {@link ngResource `ngResource`} module to be installed. + * + * By default, trailing slashes will be stripped from the calculated URLs, + * which can pose problems with server backends that do not expect that + * behavior. This can be disabled by configuring the `$resourceProvider` like + * this: + * + * ```js + app.config(['$resourceProvider', function($resourceProvider) { + // Don't strip trailing slashes from calculated URLs + $resourceProvider.defaults.stripTrailingSlashes = false; + }]); + * ``` + * + * @param {string} url A parametrized URL template with parameters prefixed by `:` as in + * `/user/:username`. If you are using a URL with a port number (e.g. + * `http://example.com:8080/api`), it will be respected. + * + * If you are using a url with a suffix, just add the suffix, like this: + * `$resource('http://example.com/resource.json')` or `$resource('http://example.com/:id.json')` + * or even `$resource('http://example.com/resource/:resource_id.:format')` + * If the parameter before the suffix is empty, :resource_id in this case, then the `/.` will be + * collapsed down to a single `.`. If you need this sequence to appear and not collapse then you + * can escape it with `/\.`. + * + * @param {Object=} paramDefaults Default values for `url` parameters. These can be overridden in + * `actions` methods. If any of the parameter value is a function, it will be executed every time + * when a param value needs to be obtained for a request (unless the param was overridden). + * + * Each key value in the parameter object is first bound to url template if present and then any + * excess keys are appended to the url search query after the `?`. + * + * Given a template `/path/:verb` and parameter `{verb:'greet', salutation:'Hello'}` results in + * URL `/path/greet?salutation=Hello`. + * + * If the parameter value is prefixed with `@` then the value for that parameter will be extracted + * from the corresponding property on the `data` object (provided when calling an action method). For + * example, if the `defaultParam` object is `{someParam: '@someProp'}` then the value of `someParam` + * will be `data.someProp`. + * + * @param {Object.=} actions Hash with declaration of custom actions that should extend + * the default set of resource actions. The declaration should be created in the format of {@link + * ng.$http#usage $http.config}: + * + * {action1: {method:?, params:?, isArray:?, headers:?, ...}, + * action2: {method:?, params:?, isArray:?, headers:?, ...}, + * ...} + * + * Where: + * + * - **`action`** – {string} – The name of action. This name becomes the name of the method on + * your resource object. + * - **`method`** – {string} – Case insensitive HTTP method (e.g. `GET`, `POST`, `PUT`, + * `DELETE`, `JSONP`, etc). + * - **`params`** – {Object=} – Optional set of pre-bound parameters for this action. If any of + * the parameter value is a function, it will be executed every time when a param value needs to + * be obtained for a request (unless the param was overridden). + * - **`url`** – {string} – action specific `url` override. The url templating is supported just + * like for the resource-level urls. + * - **`isArray`** – {boolean=} – If true then the returned object for this action is an array, + * see `returns` section. + * - **`transformRequest`** – + * `{function(data, headersGetter)|Array.}` – + * transform function or an array of such functions. The transform function takes the http + * request body and headers and returns its transformed (typically serialized) version. + * By default, transformRequest will contain one function that checks if the request data is + * an object and serializes to using `angular.toJson`. To prevent this behavior, set + * `transformRequest` to an empty array: `transformRequest: []` + * - **`transformResponse`** – + * `{function(data, headersGetter)|Array.}` – + * transform function or an array of such functions. The transform function takes the http + * response body and headers and returns its transformed (typically deserialized) version. + * By default, transformResponse will contain one function that checks if the response looks like + * a JSON string and deserializes it using `angular.fromJson`. To prevent this behavior, set + * `transformResponse` to an empty array: `transformResponse: []` + * - **`cache`** – `{boolean|Cache}` – If true, a default $http cache will be used to cache the + * GET request, otherwise if a cache instance built with + * {@link ng.$cacheFactory $cacheFactory}, this cache will be used for + * caching. + * - **`timeout`** – `{number|Promise}` – timeout in milliseconds, or {@link ng.$q promise} that + * should abort the request when resolved. + * - **`withCredentials`** - `{boolean}` - whether to set the `withCredentials` flag on the + * XHR object. See + * [requests with credentials](https://developer.mozilla.org/en/http_access_control#section_5) + * for more information. + * - **`responseType`** - `{string}` - see + * [requestType](https://developer.mozilla.org/en-US/docs/DOM/XMLHttpRequest#responseType). + * - **`interceptor`** - `{Object=}` - The interceptor object has two optional methods - + * `response` and `responseError`. Both `response` and `responseError` interceptors get called + * with `http response` object. See {@link ng.$http $http interceptors}. + * + * @param {Object} options Hash with custom settings that should extend the + * default `$resourceProvider` behavior. The only supported option is + * + * Where: + * + * - **`stripTrailingSlashes`** – {boolean} – If true then the trailing + * slashes from any calculated URL will be stripped. (Defaults to true.) + * + * @returns {Object} A resource "class" object with methods for the default set of resource actions + * optionally extended with custom `actions`. The default set contains these actions: + * ```js + * { 'get': {method:'GET'}, + * 'save': {method:'POST'}, + * 'query': {method:'GET', isArray:true}, + * 'remove': {method:'DELETE'}, + * 'delete': {method:'DELETE'} }; + * ``` + * + * Calling these methods invoke an {@link ng.$http} with the specified http method, + * destination and parameters. When the data is returned from the server then the object is an + * instance of the resource class. The actions `save`, `remove` and `delete` are available on it + * as methods with the `$` prefix. This allows you to easily perform CRUD operations (create, + * read, update, delete) on server-side data like this: + * ```js + * var User = $resource('/user/:userId', {userId:'@id'}); + * var user = User.get({userId:123}, function() { + * user.abc = true; + * user.$save(); + * }); + * ``` + * + * It is important to realize that invoking a $resource object method immediately returns an + * empty reference (object or array depending on `isArray`). Once the data is returned from the + * server the existing reference is populated with the actual data. This is a useful trick since + * usually the resource is assigned to a model which is then rendered by the view. Having an empty + * object results in no rendering, once the data arrives from the server then the object is + * populated with the data and the view automatically re-renders itself showing the new data. This + * means that in most cases one never has to write a callback function for the action methods. + * + * The action methods on the class object or instance object can be invoked with the following + * parameters: + * + * - HTTP GET "class" actions: `Resource.action([parameters], [success], [error])` + * - non-GET "class" actions: `Resource.action([parameters], postData, [success], [error])` + * - non-GET instance actions: `instance.$action([parameters], [success], [error])` + * + * Success callback is called with (value, responseHeaders) arguments. Error callback is called + * with (httpResponse) argument. + * + * Class actions return empty instance (with additional properties below). + * Instance actions return promise of the action. + * + * The Resource instances and collection have these additional properties: + * + * - `$promise`: the {@link ng.$q promise} of the original server interaction that created this + * instance or collection. + * + * On success, the promise is resolved with the same resource instance or collection object, + * updated with data from server. This makes it easy to use in + * {@link ngRoute.$routeProvider resolve section of $routeProvider.when()} to defer view + * rendering until the resource(s) are loaded. + * + * On failure, the promise is resolved with the {@link ng.$http http response} object, without + * the `resource` property. + * + * If an interceptor object was provided, the promise will instead be resolved with the value + * returned by the interceptor. + * + * - `$resolved`: `true` after first server interaction is completed (either with success or + * rejection), `false` before that. Knowing if the Resource has been resolved is useful in + * data-binding. + * + * @example + * + * # Credit card resource + * + * ```js + // Define CreditCard class + var CreditCard = $resource('/user/:userId/card/:cardId', + {userId:123, cardId:'@id'}, { + charge: {method:'POST', params:{charge:true}} + }); + + // We can retrieve a collection from the server + var cards = CreditCard.query(function() { + // GET: /user/123/card + // server returns: [ {id:456, number:'1234', name:'Smith'} ]; + + var card = cards[0]; + // each item is an instance of CreditCard + expect(card instanceof CreditCard).toEqual(true); + card.name = "J. Smith"; + // non GET methods are mapped onto the instances + card.$save(); + // POST: /user/123/card/456 {id:456, number:'1234', name:'J. Smith'} + // server returns: {id:456, number:'1234', name: 'J. Smith'}; + + // our custom method is mapped as well. + card.$charge({amount:9.99}); + // POST: /user/123/card/456?amount=9.99&charge=true {id:456, number:'1234', name:'J. Smith'} + }); + + // we can create an instance as well + var newCard = new CreditCard({number:'0123'}); + newCard.name = "Mike Smith"; + newCard.$save(); + // POST: /user/123/card {number:'0123', name:'Mike Smith'} + // server returns: {id:789, number:'0123', name: 'Mike Smith'}; + expect(newCard.id).toEqual(789); + * ``` + * + * The object returned from this function execution is a resource "class" which has "static" method + * for each action in the definition. + * + * Calling these methods invoke `$http` on the `url` template with the given `method`, `params` and + * `headers`. + * When the data is returned from the server then the object is an instance of the resource type and + * all of the non-GET methods are available with `$` prefix. This allows you to easily support CRUD + * operations (create, read, update, delete) on server-side data. + + ```js + var User = $resource('/user/:userId', {userId:'@id'}); + User.get({userId:123}, function(user) { + user.abc = true; + user.$save(); + }); + ``` + * + * It's worth noting that the success callback for `get`, `query` and other methods gets passed + * in the response that came from the server as well as $http header getter function, so one + * could rewrite the above example and get access to http headers as: + * + ```js + var User = $resource('/user/:userId', {userId:'@id'}); + User.get({userId:123}, function(u, getResponseHeaders){ + u.abc = true; + u.$save(function(u, putResponseHeaders) { + //u => saved user object + //putResponseHeaders => $http header getter + }); + }); + ``` + * + * You can also access the raw `$http` promise via the `$promise` property on the object returned + * + ``` + var User = $resource('/user/:userId', {userId:'@id'}); + User.get({userId:123}) + .$promise.then(function(user) { + $scope.user = user; + }); + ``` + + * # Creating a custom 'PUT' request + * In this example we create a custom method on our resource to make a PUT request + * ```js + * var app = angular.module('app', ['ngResource', 'ngRoute']); + * + * // Some APIs expect a PUT request in the format URL/object/ID + * // Here we are creating an 'update' method + * app.factory('Notes', ['$resource', function($resource) { + * return $resource('/notes/:id', null, + * { + * 'update': { method:'PUT' } + * }); + * }]); + * + * // In our controller we get the ID from the URL using ngRoute and $routeParams + * // We pass in $routeParams and our Notes factory along with $scope + * app.controller('NotesCtrl', ['$scope', '$routeParams', 'Notes', + function($scope, $routeParams, Notes) { + * // First get a note object from the factory + * var note = Notes.get({ id:$routeParams.id }); + * $id = note.id; + * + * // Now call update passing in the ID first then the object you are updating + * Notes.update({ id:$id }, note); + * + * // This will PUT /notes/ID with the note object in the request payload + * }]); + * ``` + */ +angular.module('ngResource', ['ng']). + provider('$resource', function() { + var provider = this; + + this.defaults = { + // Strip slashes by default + stripTrailingSlashes: true, + + // Default actions configuration + actions: { + 'get': {method: 'GET'}, + 'save': {method: 'POST'}, + 'query': {method: 'GET', isArray: true}, + 'remove': {method: 'DELETE'}, + 'delete': {method: 'DELETE'} + } + }; + + this.$get = ['$http', '$q', function($http, $q) { + + var noop = angular.noop, + forEach = angular.forEach, + extend = angular.extend, + copy = angular.copy, + isFunction = angular.isFunction; + + /** + * We need our custom method because encodeURIComponent is too aggressive and doesn't follow + * http://www.ietf.org/rfc/rfc3986.txt with regards to the character set + * (pchar) allowed in path segments: + * segment = *pchar + * pchar = unreserved / pct-encoded / sub-delims / ":" / "@" + * pct-encoded = "%" HEXDIG HEXDIG + * unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~" + * sub-delims = "!" / "$" / "&" / "'" / "(" / ")" + * / "*" / "+" / "," / ";" / "=" + */ + function encodeUriSegment(val) { + return encodeUriQuery(val, true). + replace(/%26/gi, '&'). + replace(/%3D/gi, '='). + replace(/%2B/gi, '+'); + } + + + /** + * This method is intended for encoding *key* or *value* parts of query component. We need a + * custom method because encodeURIComponent is too aggressive and encodes stuff that doesn't + * have to be encoded per http://tools.ietf.org/html/rfc3986: + * query = *( pchar / "/" / "?" ) + * pchar = unreserved / pct-encoded / sub-delims / ":" / "@" + * unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~" + * pct-encoded = "%" HEXDIG HEXDIG + * sub-delims = "!" / "$" / "&" / "'" / "(" / ")" + * / "*" / "+" / "," / ";" / "=" + */ + function encodeUriQuery(val, pctEncodeSpaces) { + return encodeURIComponent(val). + replace(/%40/gi, '@'). + replace(/%3A/gi, ':'). + replace(/%24/g, '$'). + replace(/%2C/gi, ','). + replace(/%20/g, (pctEncodeSpaces ? '%20' : '+')); + } + + function Route(template, defaults) { + this.template = template; + this.defaults = extend({}, provider.defaults, defaults); + this.urlParams = {}; + } + + Route.prototype = { + setUrlParams: function(config, params, actionUrl) { + var self = this, + url = actionUrl || self.template, + val, + encodedVal; + + var urlParams = self.urlParams = {}; + forEach(url.split(/\W/), function(param) { + if (param === 'hasOwnProperty') { + throw $resourceMinErr('badname', "hasOwnProperty is not a valid parameter name."); + } + if (!(new RegExp("^\\d+$").test(param)) && param && + (new RegExp("(^|[^\\\\]):" + param + "(\\W|$)").test(url))) { + urlParams[param] = true; + } + }); + url = url.replace(/\\:/g, ':'); + + params = params || {}; + forEach(self.urlParams, function(_, urlParam) { + val = params.hasOwnProperty(urlParam) ? params[urlParam] : self.defaults[urlParam]; + if (angular.isDefined(val) && val !== null) { + encodedVal = encodeUriSegment(val); + url = url.replace(new RegExp(":" + urlParam + "(\\W|$)", "g"), function(match, p1) { + return encodedVal + p1; + }); + } else { + url = url.replace(new RegExp("(\/?):" + urlParam + "(\\W|$)", "g"), function(match, + leadingSlashes, tail) { + if (tail.charAt(0) == '/') { + return tail; + } else { + return leadingSlashes + tail; + } + }); + } + }); + + // strip trailing slashes and set the url (unless this behavior is specifically disabled) + if (self.defaults.stripTrailingSlashes) { + url = url.replace(/\/+$/, '') || '/'; + } + + // then replace collapse `/.` if found in the last URL path segment before the query + // E.g. `http://url.com/id./format?q=x` becomes `http://url.com/id.format?q=x` + url = url.replace(/\/\.(?=\w+($|\?))/, '.'); + // replace escaped `/\.` with `/.` + config.url = url.replace(/\/\\\./, '/.'); + + + // set params - delegate param encoding to $http + forEach(params, function(value, key) { + if (!self.urlParams[key]) { + config.params = config.params || {}; + config.params[key] = value; + } + }); + } + }; + + + function resourceFactory(url, paramDefaults, actions, options) { + var route = new Route(url, options); + + actions = extend({}, provider.defaults.actions, actions); + + function extractParams(data, actionParams) { + var ids = {}; + actionParams = extend({}, paramDefaults, actionParams); + forEach(actionParams, function(value, key) { + if (isFunction(value)) { value = value(); } + ids[key] = value && value.charAt && value.charAt(0) == '@' ? + lookupDottedPath(data, value.substr(1)) : value; + }); + return ids; + } + + function defaultResponseInterceptor(response) { + return response.resource; + } + + function Resource(value) { + shallowClearAndCopy(value || {}, this); + } + + Resource.prototype.toJSON = function() { + var data = extend({}, this); + delete data.$promise; + delete data.$resolved; + return data; + }; + + forEach(actions, function(action, name) { + var hasBody = /^(POST|PUT|PATCH)$/i.test(action.method); + + Resource[name] = function(a1, a2, a3, a4) { + var params = {}, data, success, error; + + /* jshint -W086 */ /* (purposefully fall through case statements) */ + switch (arguments.length) { + case 4: + error = a4; + success = a3; + //fallthrough + case 3: + case 2: + if (isFunction(a2)) { + if (isFunction(a1)) { + success = a1; + error = a2; + break; + } + + success = a2; + error = a3; + //fallthrough + } else { + params = a1; + data = a2; + success = a3; + break; + } + case 1: + if (isFunction(a1)) success = a1; + else if (hasBody) data = a1; + else params = a1; + break; + case 0: break; + default: + throw $resourceMinErr('badargs', + "Expected up to 4 arguments [params, data, success, error], got {0} arguments", + arguments.length); + } + /* jshint +W086 */ /* (purposefully fall through case statements) */ + + var isInstanceCall = this instanceof Resource; + var value = isInstanceCall ? data : (action.isArray ? [] : new Resource(data)); + var httpConfig = {}; + var responseInterceptor = action.interceptor && action.interceptor.response || + defaultResponseInterceptor; + var responseErrorInterceptor = action.interceptor && action.interceptor.responseError || + undefined; + + forEach(action, function(value, key) { + if (key != 'params' && key != 'isArray' && key != 'interceptor') { + httpConfig[key] = copy(value); + } + }); + + if (hasBody) httpConfig.data = data; + route.setUrlParams(httpConfig, + extend({}, extractParams(data, action.params || {}), params), + action.url); + + var promise = $http(httpConfig).then(function(response) { + var data = response.data, + promise = value.$promise; + + if (data) { + // Need to convert action.isArray to boolean in case it is undefined + // jshint -W018 + if (angular.isArray(data) !== (!!action.isArray)) { + throw $resourceMinErr('badcfg', + 'Error in resource configuration for action `{0}`. Expected response to ' + + 'contain an {1} but got an {2}', name, action.isArray ? 'array' : 'object', + angular.isArray(data) ? 'array' : 'object'); + } + // jshint +W018 + if (action.isArray) { + value.length = 0; + forEach(data, function(item) { + if (typeof item === "object") { + value.push(new Resource(item)); + } else { + // Valid JSON values may be string literals, and these should not be converted + // into objects. These items will not have access to the Resource prototype + // methods, but unfortunately there + value.push(item); + } + }); + } else { + shallowClearAndCopy(data, value); + value.$promise = promise; + } + } + + value.$resolved = true; + + response.resource = value; + + return response; + }, function(response) { + value.$resolved = true; + + (error || noop)(response); + + return $q.reject(response); + }); + + promise = promise.then( + function(response) { + var value = responseInterceptor(response); + (success || noop)(value, response.headers); + return value; + }, + responseErrorInterceptor); + + if (!isInstanceCall) { + // we are creating instance / collection + // - set the initial promise + // - return the instance / collection + value.$promise = promise; + value.$resolved = false; + + return value; + } + + // instance call + return promise; + }; + + + Resource.prototype['$' + name] = function(params, success, error) { + if (isFunction(params)) { + error = success; success = params; params = {}; + } + var result = Resource[name].call(this, params, this, success, error); + return result.$promise || result; + }; + }); + + Resource.bind = function(additionalParamDefaults) { + return resourceFactory(url, extend({}, paramDefaults, additionalParamDefaults), actions); + }; + + return Resource; + } + + return resourceFactory; + }]; + }); + + +})(window, window.angular); diff --git a/public/admincp/bower_components/angular-resource/angular-resource.min.js b/public/admincp/bower_components/angular-resource/angular-resource.min.js new file mode 100644 index 000000000..c71e53b7a --- /dev/null +++ b/public/admincp/bower_components/angular-resource/angular-resource.min.js @@ -0,0 +1,13 @@ +/* + AngularJS v1.3.8 + (c) 2010-2014 Google, Inc. http://angularjs.org + License: MIT +*/ +(function(I,d,B){'use strict';function D(f,q){q=q||{};d.forEach(q,function(d,h){delete q[h]});for(var h in f)!f.hasOwnProperty(h)||"$"===h.charAt(0)&&"$"===h.charAt(1)||(q[h]=f[h]);return q}var w=d.$$minErr("$resource"),C=/^(\.[a-zA-Z_$][0-9a-zA-Z_$]*)+$/;d.module("ngResource",["ng"]).provider("$resource",function(){var f=this;this.defaults={stripTrailingSlashes:!0,actions:{get:{method:"GET"},save:{method:"POST"},query:{method:"GET",isArray:!0},remove:{method:"DELETE"},"delete":{method:"DELETE"}}}; +this.$get=["$http","$q",function(q,h){function t(d,g){this.template=d;this.defaults=s({},f.defaults,g);this.urlParams={}}function v(x,g,l,m){function c(b,k){var c={};k=s({},g,k);r(k,function(a,k){u(a)&&(a=a());var d;if(a&&a.charAt&&"@"==a.charAt(0)){d=b;var e=a.substr(1);if(null==e||""===e||"hasOwnProperty"===e||!C.test("."+e))throw w("badmember",e);for(var e=e.split("."),n=0,g=e.length;n", + "license": "MIT", + "bugs": { + "url": "https://github.com/angular/angular.js/issues" + }, + "homepage": "http://angularjs.org" +} diff --git a/public/admincp/bower_components/angular-sanitize/.bower.json b/public/admincp/bower_components/angular-sanitize/.bower.json new file mode 100644 index 000000000..9ff2a6ec9 --- /dev/null +++ b/public/admincp/bower_components/angular-sanitize/.bower.json @@ -0,0 +1,19 @@ +{ + "name": "angular-sanitize", + "version": "1.3.8", + "main": "./angular-sanitize.js", + "ignore": [], + "dependencies": { + "angular": "1.3.8" + }, + "homepage": "https://github.com/angular/bower-angular-sanitize", + "_release": "1.3.8", + "_resolution": { + "type": "version", + "tag": "v1.3.8", + "commit": "9028ede5ed6a114cb30a72185ff07c04af4582df" + }, + "_source": "git://github.com/angular/bower-angular-sanitize.git", + "_target": "~1.3.1", + "_originalSource": "angular-sanitize" +} \ No newline at end of file diff --git a/public/admincp/bower_components/angular-sanitize/README.md b/public/admincp/bower_components/angular-sanitize/README.md new file mode 100644 index 000000000..6bc0a3013 --- /dev/null +++ b/public/admincp/bower_components/angular-sanitize/README.md @@ -0,0 +1,77 @@ +# packaged angular-sanitize + +This repo is for distribution on `npm` and `bower`. The source for this module is in the +[main AngularJS repo](https://github.com/angular/angular.js/tree/master/src/ngSanitize). +Please file issues and pull requests against that repo. + +## Install + +You can install this package either with `npm` or with `bower`. + +### npm + +```shell +npm install angular-sanitize +``` + +Add a ` +``` + +Then add `ngSanitize` as a dependency for your app: + +```javascript +angular.module('myApp', ['ngSanitize']); +``` + +Note that this package is not in CommonJS format, so doing `require('angular-sanitize')` will +return `undefined`. + +### bower + +```shell +bower install angular-sanitize +``` + +Add a ` +``` + +Then add `ngSanitize` as a dependency for your app: + +```javascript +angular.module('myApp', ['ngSanitize']); +``` + +## Documentation + +Documentation is available on the +[AngularJS docs site](http://docs.angularjs.org/api/ngSanitize). + +## License + +The MIT License + +Copyright (c) 2010-2012 Google, Inc. http://angularjs.org + +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/public/admincp/bower_components/angular-sanitize/angular-sanitize.js b/public/admincp/bower_components/angular-sanitize/angular-sanitize.js new file mode 100644 index 000000000..8b5f4e703 --- /dev/null +++ b/public/admincp/bower_components/angular-sanitize/angular-sanitize.js @@ -0,0 +1,680 @@ +/** + * @license AngularJS v1.3.8 + * (c) 2010-2014 Google, Inc. http://angularjs.org + * License: MIT + */ +(function(window, angular, undefined) {'use strict'; + +var $sanitizeMinErr = angular.$$minErr('$sanitize'); + +/** + * @ngdoc module + * @name ngSanitize + * @description + * + * # ngSanitize + * + * The `ngSanitize` module provides functionality to sanitize HTML. + * + * + *
      + * + * See {@link ngSanitize.$sanitize `$sanitize`} for usage. + */ + +/* + * HTML Parser By Misko Hevery (misko@hevery.com) + * based on: HTML Parser By John Resig (ejohn.org) + * Original code by Erik Arvidsson, Mozilla Public License + * http://erik.eae.net/simplehtmlparser/simplehtmlparser.js + * + * // Use like so: + * htmlParser(htmlString, { + * start: function(tag, attrs, unary) {}, + * end: function(tag) {}, + * chars: function(text) {}, + * comment: function(text) {} + * }); + * + */ + + +/** + * @ngdoc service + * @name $sanitize + * @kind function + * + * @description + * The input is sanitized by parsing the HTML into tokens. All safe tokens (from a whitelist) are + * then serialized back to properly escaped html string. This means that no unsafe input can make + * it into the returned string, however, since our parser is more strict than a typical browser + * parser, it's possible that some obscure input, which would be recognized as valid HTML by a + * browser, won't make it through the sanitizer. The input may also contain SVG markup. + * The whitelist is configured using the functions `aHrefSanitizationWhitelist` and + * `imgSrcSanitizationWhitelist` of {@link ng.$compileProvider `$compileProvider`}. + * + * @param {string} html HTML input. + * @returns {string} Sanitized HTML. + * + * @example + + + +
      + Snippet: + + + + + + + + + + + + + + + + + + + + + + + + + +
      DirectiveHowSourceRendered
      ng-bind-htmlAutomatically uses $sanitize
      <div ng-bind-html="snippet">
      </div>
      ng-bind-htmlBypass $sanitize by explicitly trusting the dangerous value +
      <div ng-bind-html="deliberatelyTrustDangerousSnippet()">
      +</div>
      +
      ng-bindAutomatically escapes
      <div ng-bind="snippet">
      </div>
      +
      +
      + + it('should sanitize the html snippet by default', function() { + expect(element(by.css('#bind-html-with-sanitize div')).getInnerHtml()). + toBe('

      an html\nclick here\nsnippet

      '); + }); + + it('should inline raw snippet if bound to a trusted value', function() { + expect(element(by.css('#bind-html-with-trust div')).getInnerHtml()). + toBe("

      an html\n" + + "click here\n" + + "snippet

      "); + }); + + it('should escape snippet without any filter', function() { + expect(element(by.css('#bind-default div')).getInnerHtml()). + toBe("<p style=\"color:blue\">an html\n" + + "<em onmouseover=\"this.textContent='PWN3D!'\">click here</em>\n" + + "snippet</p>"); + }); + + it('should update', function() { + element(by.model('snippet')).clear(); + element(by.model('snippet')).sendKeys('new text'); + expect(element(by.css('#bind-html-with-sanitize div')).getInnerHtml()). + toBe('new text'); + expect(element(by.css('#bind-html-with-trust div')).getInnerHtml()).toBe( + 'new text'); + expect(element(by.css('#bind-default div')).getInnerHtml()).toBe( + "new <b onclick=\"alert(1)\">text</b>"); + }); +
      +
      + */ +function $SanitizeProvider() { + this.$get = ['$$sanitizeUri', function($$sanitizeUri) { + return function(html) { + var buf = []; + htmlParser(html, htmlSanitizeWriter(buf, function(uri, isImage) { + return !/^unsafe/.test($$sanitizeUri(uri, isImage)); + })); + return buf.join(''); + }; + }]; +} + +function sanitizeText(chars) { + var buf = []; + var writer = htmlSanitizeWriter(buf, angular.noop); + writer.chars(chars); + return buf.join(''); +} + + +// Regular Expressions for parsing tags and attributes +var START_TAG_REGEXP = + /^<((?:[a-zA-Z])[\w:-]*)((?:\s+[\w:-]+(?:\s*=\s*(?:(?:"[^"]*")|(?:'[^']*')|[^>\s]+))?)*)\s*(\/?)\s*(>?)/, + END_TAG_REGEXP = /^<\/\s*([\w:-]+)[^>]*>/, + ATTR_REGEXP = /([\w:-]+)(?:\s*=\s*(?:(?:"((?:[^"])*)")|(?:'((?:[^'])*)')|([^>\s]+)))?/g, + BEGIN_TAG_REGEXP = /^/g, + DOCTYPE_REGEXP = /]*?)>/i, + CDATA_REGEXP = //g, + SURROGATE_PAIR_REGEXP = /[\uD800-\uDBFF][\uDC00-\uDFFF]/g, + // Match everything outside of normal chars and " (quote character) + NON_ALPHANUMERIC_REGEXP = /([^\#-~| |!])/g; + + +// Good source of info about elements and attributes +// http://dev.w3.org/html5/spec/Overview.html#semantics +// http://simon.html5.org/html-elements + +// Safe Void Elements - HTML5 +// http://dev.w3.org/html5/spec/Overview.html#void-elements +var voidElements = makeMap("area,br,col,hr,img,wbr"); + +// Elements that you can, intentionally, leave open (and which close themselves) +// http://dev.w3.org/html5/spec/Overview.html#optional-tags +var optionalEndTagBlockElements = makeMap("colgroup,dd,dt,li,p,tbody,td,tfoot,th,thead,tr"), + optionalEndTagInlineElements = makeMap("rp,rt"), + optionalEndTagElements = angular.extend({}, + optionalEndTagInlineElements, + optionalEndTagBlockElements); + +// Safe Block Elements - HTML5 +var blockElements = angular.extend({}, optionalEndTagBlockElements, makeMap("address,article," + + "aside,blockquote,caption,center,del,dir,div,dl,figure,figcaption,footer,h1,h2,h3,h4,h5," + + "h6,header,hgroup,hr,ins,map,menu,nav,ol,pre,script,section,table,ul")); + +// Inline Elements - HTML5 +var inlineElements = angular.extend({}, optionalEndTagInlineElements, makeMap("a,abbr,acronym,b," + + "bdi,bdo,big,br,cite,code,del,dfn,em,font,i,img,ins,kbd,label,map,mark,q,ruby,rp,rt,s," + + "samp,small,span,strike,strong,sub,sup,time,tt,u,var")); + +// SVG Elements +// https://wiki.whatwg.org/wiki/Sanitization_rules#svg_Elements +var svgElements = makeMap("animate,animateColor,animateMotion,animateTransform,circle,defs," + + "desc,ellipse,font-face,font-face-name,font-face-src,g,glyph,hkern,image,linearGradient," + + "line,marker,metadata,missing-glyph,mpath,path,polygon,polyline,radialGradient,rect,set," + + "stop,svg,switch,text,title,tspan,use"); + +// Special Elements (can contain anything) +var specialElements = makeMap("script,style"); + +var validElements = angular.extend({}, + voidElements, + blockElements, + inlineElements, + optionalEndTagElements, + svgElements); + +//Attributes that have href and hence need to be sanitized +var uriAttrs = makeMap("background,cite,href,longdesc,src,usemap,xlink:href"); + +var htmlAttrs = makeMap('abbr,align,alt,axis,bgcolor,border,cellpadding,cellspacing,class,clear,' + + 'color,cols,colspan,compact,coords,dir,face,headers,height,hreflang,hspace,' + + 'ismap,lang,language,nohref,nowrap,rel,rev,rows,rowspan,rules,' + + 'scope,scrolling,shape,size,span,start,summary,target,title,type,' + + 'valign,value,vspace,width'); + +// SVG attributes (without "id" and "name" attributes) +// https://wiki.whatwg.org/wiki/Sanitization_rules#svg_Attributes +var svgAttrs = makeMap('accent-height,accumulate,additive,alphabetic,arabic-form,ascent,' + + 'attributeName,attributeType,baseProfile,bbox,begin,by,calcMode,cap-height,class,color,' + + 'color-rendering,content,cx,cy,d,dx,dy,descent,display,dur,end,fill,fill-rule,font-family,' + + 'font-size,font-stretch,font-style,font-variant,font-weight,from,fx,fy,g1,g2,glyph-name,' + + 'gradientUnits,hanging,height,horiz-adv-x,horiz-origin-x,ideographic,k,keyPoints,' + + 'keySplines,keyTimes,lang,marker-end,marker-mid,marker-start,markerHeight,markerUnits,' + + 'markerWidth,mathematical,max,min,offset,opacity,orient,origin,overline-position,' + + 'overline-thickness,panose-1,path,pathLength,points,preserveAspectRatio,r,refX,refY,' + + 'repeatCount,repeatDur,requiredExtensions,requiredFeatures,restart,rotate,rx,ry,slope,stemh,' + + 'stemv,stop-color,stop-opacity,strikethrough-position,strikethrough-thickness,stroke,' + + 'stroke-dasharray,stroke-dashoffset,stroke-linecap,stroke-linejoin,stroke-miterlimit,' + + 'stroke-opacity,stroke-width,systemLanguage,target,text-anchor,to,transform,type,u1,u2,' + + 'underline-position,underline-thickness,unicode,unicode-range,units-per-em,values,version,' + + 'viewBox,visibility,width,widths,x,x-height,x1,x2,xlink:actuate,xlink:arcrole,xlink:role,' + + 'xlink:show,xlink:title,xlink:type,xml:base,xml:lang,xml:space,xmlns,xmlns:xlink,y,y1,y2,' + + 'zoomAndPan'); + +var validAttrs = angular.extend({}, + uriAttrs, + svgAttrs, + htmlAttrs); + +function makeMap(str) { + var obj = {}, items = str.split(','), i; + for (i = 0; i < items.length; i++) obj[items[i]] = true; + return obj; +} + + +/** + * @example + * htmlParser(htmlString, { + * start: function(tag, attrs, unary) {}, + * end: function(tag) {}, + * chars: function(text) {}, + * comment: function(text) {} + * }); + * + * @param {string} html string + * @param {object} handler + */ +function htmlParser(html, handler) { + if (typeof html !== 'string') { + if (html === null || typeof html === 'undefined') { + html = ''; + } else { + html = '' + html; + } + } + var index, chars, match, stack = [], last = html, text; + stack.last = function() { return stack[ stack.length - 1 ]; }; + + while (html) { + text = ''; + chars = true; + + // Make sure we're not in a script or style element + if (!stack.last() || !specialElements[ stack.last() ]) { + + // Comment + if (html.indexOf("", index) === index) { + if (handler.comment) handler.comment(html.substring(4, index)); + html = html.substring(index + 3); + chars = false; + } + // DOCTYPE + } else if (DOCTYPE_REGEXP.test(html)) { + match = html.match(DOCTYPE_REGEXP); + + if (match) { + html = html.replace(match[0], ''); + chars = false; + } + // end tag + } else if (BEGING_END_TAGE_REGEXP.test(html)) { + match = html.match(END_TAG_REGEXP); + + if (match) { + html = html.substring(match[0].length); + match[0].replace(END_TAG_REGEXP, parseEndTag); + chars = false; + } + + // start tag + } else if (BEGIN_TAG_REGEXP.test(html)) { + match = html.match(START_TAG_REGEXP); + + if (match) { + // We only have a valid start-tag if there is a '>'. + if (match[4]) { + html = html.substring(match[0].length); + match[0].replace(START_TAG_REGEXP, parseStartTag); + } + chars = false; + } else { + // no ending tag found --- this piece should be encoded as an entity. + text += '<'; + html = html.substring(1); + } + } + + if (chars) { + index = html.indexOf("<"); + + text += index < 0 ? html : html.substring(0, index); + html = index < 0 ? "" : html.substring(index); + + if (handler.chars) handler.chars(decodeEntities(text)); + } + + } else { + html = html.replace(new RegExp("(.*)<\\s*\\/\\s*" + stack.last() + "[^>]*>", 'i'), + function(all, text) { + text = text.replace(COMMENT_REGEXP, "$1").replace(CDATA_REGEXP, "$1"); + + if (handler.chars) handler.chars(decodeEntities(text)); + + return ""; + }); + + parseEndTag("", stack.last()); + } + + if (html == last) { + throw $sanitizeMinErr('badparse', "The sanitizer was unable to parse the following block " + + "of html: {0}", html); + } + last = html; + } + + // Clean up any remaining tags + parseEndTag(); + + function parseStartTag(tag, tagName, rest, unary) { + tagName = angular.lowercase(tagName); + if (blockElements[ tagName ]) { + while (stack.last() && inlineElements[ stack.last() ]) { + parseEndTag("", stack.last()); + } + } + + if (optionalEndTagElements[ tagName ] && stack.last() == tagName) { + parseEndTag("", tagName); + } + + unary = voidElements[ tagName ] || !!unary; + + if (!unary) + stack.push(tagName); + + var attrs = {}; + + rest.replace(ATTR_REGEXP, + function(match, name, doubleQuotedValue, singleQuotedValue, unquotedValue) { + var value = doubleQuotedValue + || singleQuotedValue + || unquotedValue + || ''; + + attrs[name] = decodeEntities(value); + }); + if (handler.start) handler.start(tagName, attrs, unary); + } + + function parseEndTag(tag, tagName) { + var pos = 0, i; + tagName = angular.lowercase(tagName); + if (tagName) + // Find the closest opened tag of the same type + for (pos = stack.length - 1; pos >= 0; pos--) + if (stack[ pos ] == tagName) + break; + + if (pos >= 0) { + // Close all the open elements, up the stack + for (i = stack.length - 1; i >= pos; i--) + if (handler.end) handler.end(stack[ i ]); + + // Remove the open elements from the stack + stack.length = pos; + } + } +} + +var hiddenPre=document.createElement("pre"); +var spaceRe = /^(\s*)([\s\S]*?)(\s*)$/; +/** + * decodes all entities into regular string + * @param value + * @returns {string} A string with decoded entities. + */ +function decodeEntities(value) { + if (!value) { return ''; } + + // Note: IE8 does not preserve spaces at the start/end of innerHTML + // so we must capture them and reattach them afterward + var parts = spaceRe.exec(value); + var spaceBefore = parts[1]; + var spaceAfter = parts[3]; + var content = parts[2]; + if (content) { + hiddenPre.innerHTML=content.replace(//g, '>'); +} + +/** + * create an HTML/XML writer which writes to buffer + * @param {Array} buf use buf.jain('') to get out sanitized html string + * @returns {object} in the form of { + * start: function(tag, attrs, unary) {}, + * end: function(tag) {}, + * chars: function(text) {}, + * comment: function(text) {} + * } + */ +function htmlSanitizeWriter(buf, uriValidator) { + var ignore = false; + var out = angular.bind(buf, buf.push); + return { + start: function(tag, attrs, unary) { + tag = angular.lowercase(tag); + if (!ignore && specialElements[tag]) { + ignore = tag; + } + if (!ignore && validElements[tag] === true) { + out('<'); + out(tag); + angular.forEach(attrs, function(value, key) { + var lkey=angular.lowercase(key); + var isImage = (tag === 'img' && lkey === 'src') || (lkey === 'background'); + if (validAttrs[lkey] === true && + (uriAttrs[lkey] !== true || uriValidator(value, isImage))) { + out(' '); + out(key); + out('="'); + out(encodeEntities(value)); + out('"'); + } + }); + out(unary ? '/>' : '>'); + } + }, + end: function(tag) { + tag = angular.lowercase(tag); + if (!ignore && validElements[tag] === true) { + out(''); + } + if (tag == ignore) { + ignore = false; + } + }, + chars: function(chars) { + if (!ignore) { + out(encodeEntities(chars)); + } + } + }; +} + + +// define ngSanitize module and register $sanitize service +angular.module('ngSanitize', []).provider('$sanitize', $SanitizeProvider); + +/* global sanitizeText: false */ + +/** + * @ngdoc filter + * @name linky + * @kind function + * + * @description + * Finds links in text input and turns them into html links. Supports http/https/ftp/mailto and + * plain email address links. + * + * Requires the {@link ngSanitize `ngSanitize`} module to be installed. + * + * @param {string} text Input text. + * @param {string} target Window (_blank|_self|_parent|_top) or named frame to open links in. + * @returns {string} Html-linkified text. + * + * @usage + + * + * @example + + + +
      + Snippet: + + + + + + + + + + + + + + + + + + + + + +
      FilterSourceRendered
      linky filter +
      <div ng-bind-html="snippet | linky">
      </div>
      +
      +
      +
      linky target +
      <div ng-bind-html="snippetWithTarget | linky:'_blank'">
      </div>
      +
      +
      +
      no filter
      <div ng-bind="snippet">
      </div>
      + + + it('should linkify the snippet with urls', function() { + expect(element(by.id('linky-filter')).element(by.binding('snippet | linky')).getText()). + toBe('Pretty text with some links: http://angularjs.org/, us@somewhere.org, ' + + 'another@somewhere.org, and one more: ftp://127.0.0.1/.'); + expect(element.all(by.css('#linky-filter a')).count()).toEqual(4); + }); + + it('should not linkify snippet without the linky filter', function() { + expect(element(by.id('escaped-html')).element(by.binding('snippet')).getText()). + toBe('Pretty text with some links: http://angularjs.org/, mailto:us@somewhere.org, ' + + 'another@somewhere.org, and one more: ftp://127.0.0.1/.'); + expect(element.all(by.css('#escaped-html a')).count()).toEqual(0); + }); + + it('should update', function() { + element(by.model('snippet')).clear(); + element(by.model('snippet')).sendKeys('new http://link.'); + expect(element(by.id('linky-filter')).element(by.binding('snippet | linky')).getText()). + toBe('new http://link.'); + expect(element.all(by.css('#linky-filter a')).count()).toEqual(1); + expect(element(by.id('escaped-html')).element(by.binding('snippet')).getText()) + .toBe('new http://link.'); + }); + + it('should work with the target property', function() { + expect(element(by.id('linky-target')). + element(by.binding("snippetWithTarget | linky:'_blank'")).getText()). + toBe('http://angularjs.org/'); + expect(element(by.css('#linky-target a')).getAttribute('target')).toEqual('_blank'); + }); + + + */ +angular.module('ngSanitize').filter('linky', ['$sanitize', function($sanitize) { + var LINKY_URL_REGEXP = + /((ftp|https?):\/\/|(www\.)|(mailto:)?[A-Za-z0-9._%+-]+@)\S*[^\s.;,(){}<>"”’]/, + MAILTO_REGEXP = /^mailto:/; + + return function(text, target) { + if (!text) return text; + var match; + var raw = text; + var html = []; + var url; + var i; + while ((match = raw.match(LINKY_URL_REGEXP))) { + // We can not end in these as they are sometimes found at the end of the sentence + url = match[0]; + // if we did not match ftp/http/www/mailto then assume mailto + if (!match[2] && !match[4]) { + url = (match[3] ? 'http://' : 'mailto:') + url; + } + i = match.index; + addText(raw.substr(0, i)); + addLink(url, match[0].replace(MAILTO_REGEXP, '')); + raw = raw.substring(i + match[0].length); + } + addText(raw); + return $sanitize(html.join('')); + + function addText(text) { + if (!text) { + return; + } + html.push(sanitizeText(text)); + } + + function addLink(url, text) { + html.push(''); + addText(text); + html.push(''); + } + }; +}]); + + +})(window, window.angular); diff --git a/public/admincp/bower_components/angular-sanitize/angular-sanitize.min.js b/public/admincp/bower_components/angular-sanitize/angular-sanitize.min.js new file mode 100644 index 000000000..d70e63fc8 --- /dev/null +++ b/public/admincp/bower_components/angular-sanitize/angular-sanitize.min.js @@ -0,0 +1,16 @@ +/* + AngularJS v1.3.8 + (c) 2010-2014 Google, Inc. http://angularjs.org + License: MIT +*/ +(function(n,h,p){'use strict';function E(a){var d=[];s(d,h.noop).chars(a);return d.join("")}function g(a){var d={};a=a.split(",");var c;for(c=0;c=c;e--)d.end&&d.end(f[e]);f.length=c}}"string"!==typeof a&&(a=null===a||"undefined"===typeof a?"":""+a);var b,k,f=[],m=a,l;for(f.last=function(){return f[f.length-1]};a;){l="";k=!0;if(f.last()&&x[f.last()])a=a.replace(new RegExp("(.*)<\\s*\\/\\s*"+f.last()+"[^>]*>","i"),function(a,b){b=b.replace(H,"$1").replace(I,"$1");d.chars&&d.chars(r(b));return""}),e("",f.last());else{if(0===a.indexOf("\x3c!--"))b=a.indexOf("--",4),0<=b&&a.lastIndexOf("--\x3e",b)===b&&(d.comment&&d.comment(a.substring(4, +b)),a=a.substring(b+3),k=!1);else if(y.test(a)){if(b=a.match(y))a=a.replace(b[0],""),k=!1}else if(J.test(a)){if(b=a.match(z))a=a.substring(b[0].length),b[0].replace(z,e),k=!1}else K.test(a)&&((b=a.match(A))?(b[4]&&(a=a.substring(b[0].length),b[0].replace(A,c)),k=!1):(l+="<",a=a.substring(1)));k&&(b=a.indexOf("<"),l+=0>b?a:a.substring(0,b),a=0>b?"":a.substring(b),d.chars&&d.chars(r(l)))}if(a==m)throw L("badparse",a);m=a}e()}function r(a){if(!a)return"";var d=M.exec(a);a=d[1];var c=d[3];if(d=d[2])q.innerHTML= +d.replace(//g,">")}function s(a,d){var c=!1,e=h.bind(a,a.push);return{start:function(a,k,f){a=h.lowercase(a);!c&&x[a]&&(c=a);c||!0!==C[a]||(e("<"),e(a),h.forEach(k,function(c,f){var k= +h.lowercase(f),g="img"===a&&"src"===k||"background"===k;!0!==P[k]||!0===D[k]&&!d(c,g)||(e(" "),e(f),e('="'),e(B(c)),e('"'))}),e(f?"/>":">"))},end:function(a){a=h.lowercase(a);c||!0!==C[a]||(e(""));a==c&&(c=!1)},chars:function(a){c||e(B(a))}}}var L=h.$$minErr("$sanitize"),A=/^<((?:[a-zA-Z])[\w:-]*)((?:\s+[\w:-]+(?:\s*=\s*(?:(?:"[^"]*")|(?:'[^']*')|[^>\s]+))?)*)\s*(\/?)\s*(>?)/,z=/^<\/\s*([\w:-]+)[^>]*>/,G=/([\w:-]+)(?:\s*=\s*(?:(?:"((?:[^"])*)")|(?:'((?:[^'])*)')|([^>\s]+)))?/g,K=/^]*?)>/i,I=/"\u201d\u2019]/,c=/^mailto:/;return function(e,b){function k(a){a&&g.push(E(a))} +function f(a,c){g.push("');k(c);g.push("")}if(!e)return e;for(var m,l=e,g=[],n,p;m=l.match(d);)n=m[0],m[2]||m[4]||(n=(m[3]?"http://":"mailto:")+n),p=m.index,k(l.substr(0,p)),f(n,m[0].replace(c,"")),l=l.substring(p+m[0].length);k(l);return a(g.join(""))}}])})(window,window.angular); +//# sourceMappingURL=angular-sanitize.min.js.map diff --git a/public/admincp/bower_components/angular-sanitize/angular-sanitize.min.js.map b/public/admincp/bower_components/angular-sanitize/angular-sanitize.min.js.map new file mode 100644 index 000000000..80a888924 --- /dev/null +++ b/public/admincp/bower_components/angular-sanitize/angular-sanitize.min.js.map @@ -0,0 +1,8 @@ +{ +"version":3, +"file":"angular-sanitize.min.js", +"lineCount":15, +"mappings":"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", +"sources":["angular-sanitize.js"], +"names":["window","angular","undefined","sanitizeText","chars","buf","htmlSanitizeWriter","writer","noop","join","makeMap","str","obj","items","split","i","length","htmlParser","html","handler","parseStartTag","tag","tagName","rest","unary","lowercase","blockElements","stack","last","inlineElements","parseEndTag","optionalEndTagElements","voidElements","push","attrs","replace","ATTR_REGEXP","match","name","doubleQuotedValue","singleQuotedValue","unquotedValue","decodeEntities","start","pos","end","index","text","stack.last","specialElements","RegExp","all","COMMENT_REGEXP","CDATA_REGEXP","indexOf","lastIndexOf","comment","substring","DOCTYPE_REGEXP","test","BEGING_END_TAGE_REGEXP","END_TAG_REGEXP","BEGIN_TAG_REGEXP","START_TAG_REGEXP","$sanitizeMinErr","value","parts","spaceRe","exec","spaceBefore","spaceAfter","content","hiddenPre","innerHTML","textContent","innerText","encodeEntities","SURROGATE_PAIR_REGEXP","hi","charCodeAt","low","NON_ALPHANUMERIC_REGEXP","uriValidator","ignore","out","bind","validElements","forEach","key","lkey","isImage","validAttrs","uriAttrs","$$minErr","optionalEndTagBlockElements","optionalEndTagInlineElements","extend","svgElements","htmlAttrs","svgAttrs","document","createElement","module","provider","$SanitizeProvider","$get","$$sanitizeUri","uri","filter","$sanitize","LINKY_URL_REGEXP","MAILTO_REGEXP","target","addText","addLink","url","isDefined","raw","substr"] +} diff --git a/public/admincp/bower_components/angular-sanitize/bower.json b/public/admincp/bower_components/angular-sanitize/bower.json new file mode 100644 index 000000000..6ffba993b --- /dev/null +++ b/public/admincp/bower_components/angular-sanitize/bower.json @@ -0,0 +1,9 @@ +{ + "name": "angular-sanitize", + "version": "1.3.8", + "main": "./angular-sanitize.js", + "ignore": [], + "dependencies": { + "angular": "1.3.8" + } +} diff --git a/public/admincp/bower_components/angular-sanitize/package.json b/public/admincp/bower_components/angular-sanitize/package.json new file mode 100644 index 000000000..348a307d4 --- /dev/null +++ b/public/admincp/bower_components/angular-sanitize/package.json @@ -0,0 +1,26 @@ +{ + "name": "angular-sanitize", + "version": "1.3.8", + "description": "AngularJS module for sanitizing HTML", + "main": "angular-sanitize.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "repository": { + "type": "git", + "url": "https://github.com/angular/angular.js.git" + }, + "keywords": [ + "angular", + "framework", + "browser", + "html", + "client-side" + ], + "author": "Angular Core Team ", + "license": "MIT", + "bugs": { + "url": "https://github.com/angular/angular.js/issues" + }, + "homepage": "http://angularjs.org" +} diff --git a/public/admincp/bower_components/angular-ui-router/.bower.json b/public/admincp/bower_components/angular-ui-router/.bower.json new file mode 100644 index 000000000..ae19fb7aa --- /dev/null +++ b/public/admincp/bower_components/angular-ui-router/.bower.json @@ -0,0 +1,33 @@ +{ + "name": "angular-ui-router", + "version": "0.2.13", + "main": "./release/angular-ui-router.js", + "dependencies": { + "angular": ">= 1.0.8" + }, + "ignore": [ + "**/.*", + "node_modules", + "bower_components", + "component.json", + "package.json", + "lib", + "config", + "sample", + "test", + "tests", + "ngdoc_assets", + "Gruntfile.js", + "files.js" + ], + "homepage": "https://github.com/angular-ui/ui-router", + "_release": "0.2.13", + "_resolution": { + "type": "version", + "tag": "0.2.13", + "commit": "c3d543aae43d4600512520a0d70723ac31f2cb62" + }, + "_source": "git://github.com/angular-ui/ui-router.git", + "_target": "~0.2.13", + "_originalSource": "angular-ui-router" +} \ No newline at end of file diff --git a/public/admincp/bower_components/angular-ui-router/CHANGELOG.md b/public/admincp/bower_components/angular-ui-router/CHANGELOG.md new file mode 100644 index 000000000..e0848c38c --- /dev/null +++ b/public/admincp/bower_components/angular-ui-router/CHANGELOG.md @@ -0,0 +1,197 @@ + +### 0.2.13 (2014-11-20) + +This release primarily fixes issues reported against 0.2.12 + +#### Bug Fixes + +* **$state:** fix $state.includes/.is to apply param types before comparisions fix(uiSref): ma ([19715d15](https://github.com/angular-ui/ui-router/commit/19715d15e3cbfff724519e9febedd05b49c75baa), closes [#1513](https://github.com/angular-ui/ui-router/issues/1513)) + * Avoid re-synchronizing from url after .transitionTo ([b267ecd3](https://github.com/angular-ui/ui-router/commit/b267ecd348e5c415233573ef95ebdbd051875f52), closes [#1573](https://github.com/angular-ui/ui-router/issues/1573)) +* **$urlMatcherFactory:** + * Built-in date type uses local time zone ([d726bedc](https://github.com/angular-ui/ui-router/commit/d726bedcbb5f70a5660addf43fd52ec730790293)) + * make date type fn check .is before running ([aa94ce3b](https://github.com/angular-ui/ui-router/commit/aa94ce3b86632ad05301530a2213099da73a3dc0), closes [#1564](https://github.com/angular-ui/ui-router/issues/1564)) + * early binding of array handler bypasses type resolution ([ada4bc27](https://github.com/angular-ui/ui-router/commit/ada4bc27df5eff3ba3ab0de94a09bd91b0f7a28c)) + * add 'any' Type for non-encoding non-url params ([3bfd75ab](https://github.com/angular-ui/ui-router/commit/3bfd75ab445ee2f1dd55275465059ed116b10b27), closes [#1562](https://github.com/angular-ui/ui-router/issues/1562)) + * fix encoding slashes in params ([0c983a08](https://github.com/angular-ui/ui-router/commit/0c983a08e2947f999683571477debd73038e95cf), closes [#1119](https://github.com/angular-ui/ui-router/issues/1119)) + * fix mixed path/query params ordering problem ([a479fbd0](https://github.com/angular-ui/ui-router/commit/a479fbd0b8eb393a94320973e5b9a62d83912ee2), closes [#1543](https://github.com/angular-ui/ui-router/issues/1543)) +* **ArrayType:** + * specify empty array mapping corner case ([74aa6091](https://github.com/angular-ui/ui-router/commit/74aa60917e996b0b4e27bbb4eb88c3c03832021d), closes [#1511](https://github.com/angular-ui/ui-router/issues/1511)) + * fix .equals for array types ([5e6783b7](https://github.com/angular-ui/ui-router/commit/5e6783b77af9a90ddff154f990b43dbb17eeda6e), closes [#1538](https://github.com/angular-ui/ui-router/issues/1538)) +* **Param:** fix default value shorthand declaration ([831d812a](https://github.com/angular-ui/ui-router/commit/831d812a524524c71f0ee1c9afaf0487a5a66230), closes [#1554](https://github.com/angular-ui/ui-router/issues/1554)) +* **common:** fixed the _.filter clone to not create sparse arrays ([750f5cf5](https://github.com/angular-ui/ui-router/commit/750f5cf5fd91f9ada96f39e50d39aceb2caf22b6), closes [#1563](https://github.com/angular-ui/ui-router/issues/1563)) +* **ie8:** fix calls to indexOf and filter ([dcb31b84](https://github.com/angular-ui/ui-router/commit/dcb31b843391b3e61dee4de13f368c109541813e), closes [#1556](https://github.com/angular-ui/ui-router/issues/1556)) + + +#### Features + +* add json parameter Type ([027f1fcf](https://github.com/angular-ui/ui-router/commit/027f1fcf9c0916cea651e88981345da6f9ff214a)) + + + +### 0.2.12 (2014-11-13) + +#### Bug Fixes + +* **$resolve:** use resolve fn result, not parent resolved value of same name ([67f5e00c](https://github.com/angular-ui/ui-router/commit/67f5e00cc9aa006ce3fe6cde9dff261c28eab70a), closes [#1317], [#1353]) +* **$state:** + * populate default params in .transitionTo. ([3f60fbe6](https://github.com/angular-ui/ui-router/commit/3f60fbe6d65ebeca8d97952c05aa1d269f1b7ba1), closes [#1396]) + * reload() now reinvokes controllers ([73443420](https://github.com/angular-ui/ui-router/commit/7344342018847902594dc1fc62d30a5c30f01763), closes [#582]) + * do not emit $viewContentLoading if notify: false ([74255feb](https://github.com/angular-ui/ui-router/commit/74255febdf48ae082a02ca1e735165f2c369a463), closes [#1387](https://github.com/angular-ui/ui-router/issues/1387)) + * register states at config-time ([4533fe36](https://github.com/angular-ui/ui-router/commit/4533fe36e0ab2f0143edd854a4145deaa013915a)) + * handle parent.name when parent is obj ([4533fe36](https://github.com/angular-ui/ui-router/commit/4533fe36e0ab2f0143edd854a4145deaa013915a)) +* **$urlMatcherFactory:** + * register types at config ([4533fe36](https://github.com/angular-ui/ui-router/commit/4533fe36e0ab2f0143edd854a4145deaa013915a), closes [#1476]) + * made path params default value "" for backwards compat ([8f998e71](https://github.com/angular-ui/ui-router/commit/8f998e71e43a0b31293331c981f5db0f0097b8ba)) + * Pre-replace certain param values for better mapping ([6374a3e2](https://github.com/angular-ui/ui-router/commit/6374a3e29ab932014a7c77d2e1ab884cc841a2e3)) + * fixed ParamSet.$$keys() ordering ([9136fecb](https://github.com/angular-ui/ui-router/commit/9136fecbc2bfd4fda748a9914f0225a46c933860)) + * empty string policy now respected in Param.value() ([db12c85c](https://github.com/angular-ui/ui-router/commit/db12c85c16f2d105415f9bbbdeb11863f64728e0)) + * "string" type now encodes/decodes slashes ([3045e415](https://github.com/angular-ui/ui-router/commit/3045e41577a8b8b8afc6039f42adddf5f3c061ec), closes [#1119]) + * allow arrays in both path and query params ([fdd2f2c1](https://github.com/angular-ui/ui-router/commit/fdd2f2c191c4a67c874fdb9ec9a34f8dde9ad180), closes [#1073], [#1045], [#1486], [#1394]) + * typed params in search ([8d4cab69](https://github.com/angular-ui/ui-router/commit/8d4cab69dd67058e1a716892cc37b7d80a57037f), closes [#1488](https://github.com/angular-ui/ui-router/issues/1488)) + * no longer generate unroutable urls ([cb9fd9d8](https://github.com/angular-ui/ui-router/commit/cb9fd9d8943cb26c7223f6990db29c82ae8740f8), closes [#1487](https://github.com/angular-ui/ui-router/issues/1487)) + * handle optional parameter followed by required parameter in url format. ([efc72106](https://github.com/angular-ui/ui-router/commit/efc72106ddcc4774b48ea176a505ef9e95193b41)) + * default to parameter string coersion. ([13a468a7](https://github.com/angular-ui/ui-router/commit/13a468a7d54c2fb0751b94c0c1841d580b71e6dc), closes [#1414](https://github.com/angular-ui/ui-router/issues/1414)) + * concat respects strictMode/caseInsensitive ([dd72e103](https://github.com/angular-ui/ui-router/commit/dd72e103edb342d9cf802816fe127e1bbd68fd5f), closes [#1395]) +* **ui-sref:** + * Allow sref state options to take a scope object ([b5f7b596](https://github.com/angular-ui/ui-router/commit/b5f7b59692ce4933e2d63eb5df3f50a4ba68ccc0)) + * replace raw href modification with attrs. ([08c96782](https://github.com/angular-ui/ui-router/commit/08c96782faf881b0c7ab00afc233ee6729548fa0)) + * nagivate to state when url is "" fix($state.href): generate href for state with ([656b5aab](https://github.com/angular-ui/ui-router/commit/656b5aab906e5749db9b5a080c6a83b95f50fd91), closes [#1363](https://github.com/angular-ui/ui-router/issues/1363)) + * Check that state is defined in isMatch() ([92aebc75](https://github.com/angular-ui/ui-router/commit/92aebc7520f88babdc6e266536086e07263514c3), closes [#1314](https://github.com/angular-ui/ui-router/issues/1314), [#1332](https://github.com/angular-ui/ui-router/issues/1332)) +* **uiView:** + * allow inteprolated ui-view names ([81f6a19a](https://github.com/angular-ui/ui-router/commit/81f6a19a432dac9198fd33243855bfd3b4fea8c0), closes [#1324](https://github.com/angular-ui/ui-router/issues/1324)) + * Made anim work with angular 1.3 ([c3bb7ad9](https://github.com/angular-ui/ui-router/commit/c3bb7ad903da1e1f3c91019cfd255be8489ff4ef), closes [#1367](https://github.com/angular-ui/ui-router/issues/1367), [#1345](https://github.com/angular-ui/ui-router/issues/1345)) +* **urlRouter:** html5Mode accepts an object from angular v1.3.0-rc.3 ([7fea1e9d](https://github.com/angular-ui/ui-router/commit/7fea1e9d0d8c6e09cc6c895ecb93d4221e9adf48)) +* **stateFilters:** mark state filters as stateful. ([a00b353e](https://github.com/angular-ui/ui-router/commit/a00b353e3036f64a81245c4e7898646ba218f833), closes [#1479]) +* **ui-router:** re-add IE8 compatibility for map/filter/keys ([8ce69d9f](https://github.com/angular-ui/ui-router/commit/8ce69d9f7c886888ab53eca7e53536f36b428aae), closes [#1518], [#1383]) +* **package:** point 'main' to a valid filename ([ac903350](https://github.com/angular-ui/ui-router/commit/ac9033501debb63364539d91fbf3a0cba4579f8e)) +* **travis:** make CI build faster ([0531de05](https://github.com/angular-ui/ui-router/commit/0531de052e414a8d839fbb4e7635e923e94865b3)) + + +#### Features + +##### Default and Typed params + +This release includes a lot of bug fixes around default/optional and typed parameters. As such, 0.2.12 is the first release where we recommend those features be used. + +* **$state:** + * add state params validation ([b1379e6a](https://github.com/angular-ui/ui-router/commit/b1379e6a4d38f7ed7436e05873932d7c279af578), closes [#1433](https://github.com/angular-ui/ui-router/issues/1433)) + * is/includes/get work on relative stateOrName ([232e94b3](https://github.com/angular-ui/ui-router/commit/232e94b3c2ca2c764bb9510046e4b61690c87852)) + * .reload() returns state transition promise ([639e0565](https://github.com/angular-ui/ui-router/commit/639e0565dece9d5544cc93b3eee6e11c99bd7373)) +* **$templateFactory:** request templateURL as text/html ([ccd60769](https://github.com/angular-ui/ui-router/commit/ccd6076904a4b801d77b47f6e2de4c06ce9962f8), closes [#1287]) +* **$urlMatcherFactory:** Made a Params and ParamSet class ([0cc1e6cc](https://github.com/angular-ui/ui-router/commit/0cc1e6cc461a4640618e2bb594566551c54834e2)) + + + + +### 0.2.11 (2014-08-26) + + +#### Bug Fixes + +* **$resolve:** Resolves only inherit from immediate parent fixes #702 ([df34e20c](https://github.com/angular-ui/ui-router/commit/df34e20c576299e7a3c8bd4ebc68d42341c0ace9)) +* **$state:** + * change $state.href default options.inherit to true ([deea695f](https://github.com/angular-ui/ui-router/commit/deea695f5cacc55de351ab985144fd233c02a769)) + * sanity-check state lookups ([456fd5ae](https://github.com/angular-ui/ui-router/commit/456fd5aec9ea507518927bfabd62b4afad4cf714), closes [#980](https://github.com/angular-ui/ui-router/issues/980)) + * didn't comply to inherit parameter ([09836781](https://github.com/angular-ui/ui-router/commit/09836781f126c1c485b06551eb9cfd4fa0f45c35)) + * allow view content loading broadcast ([7b78edee](https://github.com/angular-ui/ui-router/commit/7b78edeeb52a74abf4d3f00f79534033d5a08d1a)) +* **$urlMatcherFactory:** + * detect injected functions ([91f75ae6](https://github.com/angular-ui/ui-router/commit/91f75ae66c4d129f6f69e53bd547594e9661f5d5)) + * syntax ([1ebed370](https://github.com/angular-ui/ui-router/commit/1ebed37069bae8614d41541d56521f5c45f703f3)) +* **UrlMatcher:** + * query param function defaults ([f9c20530](https://github.com/angular-ui/ui-router/commit/f9c205304f10d8a4ebe7efe9025e642016479a51)) + * don't decode default values ([63607bdb](https://github.com/angular-ui/ui-router/commit/63607bdbbcb432d3fb37856a1cb3da0cd496804e)) +* **travis:** update Node version to fix build ([d6b95ef2](https://github.com/angular-ui/ui-router/commit/d6b95ef23d9dacb4eba08897f5190a0bcddb3a48)) +* **uiSref:** + * Generate an href for states with a blank url. closes #1293 ([691745b1](https://github.com/angular-ui/ui-router/commit/691745b12fa05d3700dd28f0c8d25f8a105074ad)) + * should inherit params by default ([b973dad1](https://github.com/angular-ui/ui-router/commit/b973dad155ad09a7975e1476bd096f7b2c758eeb)) + * cancel transition if preventDefault() has been called ([2e6d9167](https://github.com/angular-ui/ui-router/commit/2e6d9167d3afbfbca6427e53e012f94fb5fb8022)) +* **uiView:** Fixed infinite loop when is called .go() from a controller. ([e13988b8](https://github.com/angular-ui/ui-router/commit/e13988b8cd6231d75c78876ee9d012cc87f4a8d9), closes [#1194](https://github.com/angular-ui/ui-router/issues/1194)) +* **docs:** + * Fixed link to milestones ([6c0ae500](https://github.com/angular-ui/ui-router/commit/6c0ae500cc238ea9fc95adcc15415c55fc9e1f33)) + * fix bug in decorator example ([4bd00af5](https://github.com/angular-ui/ui-router/commit/4bd00af50b8b88a49d1545a76290731cb8e0feb1)) + * Removed an incorrect semi-colon ([af97cef8](https://github.com/angular-ui/ui-router/commit/af97cef8b967f2e32177e539ef41450dca131a7d)) + * Explain return value of rule as function ([5e887890](https://github.com/angular-ui/ui-router/commit/5e8878900a6ffe59a81aed531a3925e34a297377)) + + +#### Features + +* **$state:** + * allow parameters to pass unharmed ([8939d057](https://github.com/angular-ui/ui-router/commit/8939d0572ab1316e458ef016317ecff53131a822)) + * **BREAKING CHANGE**: state parameters are no longer automatically coerced to strings, and unspecified parameter values are now set to undefined rather than null. + * allow prevent syncUrl on failure ([753060b9](https://github.com/angular-ui/ui-router/commit/753060b910d5d2da600a6fa0757976e401c33172)) +* **typescript:** Add typescript definitions for component builds ([521ceb3f](https://github.com/angular-ui/ui-router/commit/521ceb3fd7850646422f411921e21ce5e7d82e0f)) +* **uiSref:** extend syntax for ui-sref ([71cad3d6](https://github.com/angular-ui/ui-router/commit/71cad3d636508b5a9fe004775ad1f1adc0c80c3e)) +* **uiSrefActive:** + * Also activate for child states. ([bf163ad6](https://github.com/angular-ui/ui-router/commit/bf163ad6ce176ce28792696c8302d7cdf5c05a01), closes [#818](https://github.com/angular-ui/ui-router/issues/818)) + * **BREAKING CHANGE** Since ui-sref-active now activates even when child states are active you may need to swap out your ui-sref-active with ui-sref-active-eq, thought typically we think devs want the auto inheritance. + + * uiSrefActiveEq: new directive with old ui-sref-active behavior +* **$urlRouter:** + * defer URL change interception ([c72d8ce1](https://github.com/angular-ui/ui-router/commit/c72d8ce11916d0ac22c81b409c9e61d7048554d7)) + * force URLs to have valid params ([d48505cd](https://github.com/angular-ui/ui-router/commit/d48505cd328d83e39d5706e085ba319715f999a6)) + * abstract $location handling ([08b4636b](https://github.com/angular-ui/ui-router/commit/08b4636b294611f08db35f00641eb5211686fb50)) +* **$urlMatcherFactory:** + * fail on bad parameters ([d8f124c1](https://github.com/angular-ui/ui-router/commit/d8f124c10d00c7e5dde88c602d966db261aea221)) + * date type support ([b7f074ff](https://github.com/angular-ui/ui-router/commit/b7f074ff65ca150a3cdbda4d5ad6cb17107300eb)) + * implement type support ([450b1f0e](https://github.com/angular-ui/ui-router/commit/450b1f0e8e03c738174ff967f688b9a6373290f4)) +* **UrlMatcher:** + * handle query string arrays ([9cf764ef](https://github.com/angular-ui/ui-router/commit/9cf764efab45fa9309368688d535ddf6e96d6449), closes [#373](https://github.com/angular-ui/ui-router/issues/373)) + * injectable functions as defaults ([00966ecd](https://github.com/angular-ui/ui-router/commit/00966ecd91fb745846039160cab707bfca8b3bec)) + * default values & type decoding for query params ([a472b301](https://github.com/angular-ui/ui-router/commit/a472b301389fbe84d1c1fa9f24852b492a569d11)) + * allow shorthand definitions ([5b724304](https://github.com/angular-ui/ui-router/commit/5b7243049793505e44b6608ea09878c37c95b1f5)) + * validates whole interface ([32b27db1](https://github.com/angular-ui/ui-router/commit/32b27db173722e9194ef1d5c0ea7d93f25a98d11)) + * implement non-strict matching ([a3e21366](https://github.com/angular-ui/ui-router/commit/a3e21366bee0475c9795a1ec76f70eec41c5b4e3)) + * add per-param config support ([07b3029f](https://github.com/angular-ui/ui-router/commit/07b3029f4d409cf955780113df92e36401b47580)) + * **BREAKING CHANGE**: the `params` option in state configurations must now be an object keyed by parameter name. + +### 0.2.10 (2014-03-12) + + +#### Bug Fixes + +* **$state:** use $browser.baseHref() when generating urls with .href() ([cbcc8488](https://github.com/angular-ui/ui-router/commit/cbcc84887d6b6d35258adabb97c714cd9c1e272d)) +* **bower.json:** JS files should not be ignored ([ccdab193](https://github.com/angular-ui/ui-router/commit/ccdab193315f304eb3be5f5b97c47a926c79263e)) +* **dev:** karma:background task is missing, can't run grunt:dev. ([d9f7b898](https://github.com/angular-ui/ui-router/commit/d9f7b898e8e3abb8c846b0faa16a382913d7b22b)) +* **sample:** Contacts menu button not staying active when navigating to detail states. Need t ([2fcb8443](https://github.com/angular-ui/ui-router/commit/2fcb84437cb43ade12682a92b764f13cac77dfe7)) +* **uiSref:** support mock-clicks/events with no data ([717d3ff7](https://github.com/angular-ui/ui-router/commit/717d3ff7d0ba72d239892dee562b401cdf90e418)) +* **uiView:** + * Do NOT autoscroll when autoscroll attr is missing ([affe5bd7](https://github.com/angular-ui/ui-router/commit/affe5bd785cdc3f02b7a9f64a52e3900386ec3a0), closes [#807](https://github.com/angular-ui/ui-router/issues/807)) + * Refactoring uiView directive to copy ngView logic ([548fab6a](https://github.com/angular-ui/ui-router/commit/548fab6ab9debc9904c5865c8bc68b4fc3271dd0), closes [#857](https://github.com/angular-ui/ui-router/issues/857), [#552](https://github.com/angular-ui/ui-router/issues/552)) + + +#### Features + +* **$state:** includes() allows glob patterns for state matching. ([2d5f6b37](https://github.com/angular-ui/ui-router/commit/2d5f6b37191a3135f4a6d9e8f344c54edcdc065b)) +* **UrlMatcher:** Add support for case insensitive url matching ([642d5247](https://github.com/angular-ui/ui-router/commit/642d524799f604811e680331002feec7199a1fb5)) +* **uiSref:** add support for transition options ([2ed7a728](https://github.com/angular-ui/ui-router/commit/2ed7a728cee6854b38501fbc1df6139d3de5b28a)) +* **uiView:** add controllerAs config with function ([1ee7334a](https://github.com/angular-ui/ui-router/commit/1ee7334a73efeccc9b95340e315cdfd59944762d)) + + +### 0.2.9 (2014-01-17) + + +This release is identical to 0.2.8. 0.2.8 was re-tagged in git to fix a problem with bower. + + +### 0.2.8 (2014-01-16) + + +#### Bug Fixes + +* **$state:** allow null to be passed as 'params' param ([094dc30e](https://github.com/angular-ui/ui-router/commit/094dc30e883e1bd14e50a475553bafeaade3b178)) +* **$state.go:** param inheritance shouldn't inherit from siblings ([aea872e0](https://github.com/angular-ui/ui-router/commit/aea872e0b983cb433436ce5875df10c838fccedb)) +* **bower.json:** fixes bower.json ([eed3cc4d](https://github.com/angular-ui/ui-router/commit/eed3cc4d4dfef1d3ef84b9fd063127538ebf59d3)) +* **uiSrefActive:** annotate controller injection ([85921422](https://github.com/angular-ui/ui-router/commit/85921422ff7fb0effed358136426d616cce3d583), closes [#671](https://github.com/angular-ui/ui-router/issues/671)) +* **uiView:** + * autoscroll tests pass on 1.2.4 & 1.1.5 ([86eacac0](https://github.com/angular-ui/ui-router/commit/86eacac09ca5e9000bd3b9c7ba6e2cc95d883a3a)) + * don't animate initial load ([83b6634d](https://github.com/angular-ui/ui-router/commit/83b6634d27942ca74766b2b1244a7fc52c5643d9)) + * test pass against 1.0.8 and 1.2.4 ([a402415a](https://github.com/angular-ui/ui-router/commit/a402415a2a28b360c43b9fe8f4f54c540f6c33de)) + * it should autoscroll when expr is missing. ([8bb9e27a](https://github.com/angular-ui/ui-router/commit/8bb9e27a2986725f45daf44c4c9f846385095aff)) + + +#### Features + +* **uiSref:** add target attribute behaviour ([c12bf9a5](https://github.com/angular-ui/ui-router/commit/c12bf9a520d30d70294e3d82de7661900f8e394e)) +* **uiView:** + * merge autoscroll expression test. ([b89e0f87](https://github.com/angular-ui/ui-router/commit/b89e0f871d5cc35c10925ede986c10684d5c9252)) + * cache and test autoscroll expression ([ee262282](https://github.com/angular-ui/ui-router/commit/ee2622828c2ce83807f006a459ac4e11406d9258)) diff --git a/public/admincp/bower_components/angular-ui-router/CONTRIBUTING.md b/public/admincp/bower_components/angular-ui-router/CONTRIBUTING.md new file mode 100644 index 000000000..63829a549 --- /dev/null +++ b/public/admincp/bower_components/angular-ui-router/CONTRIBUTING.md @@ -0,0 +1,65 @@ + +# Report an Issue + +Help us make UI-Router better! If you think you might have found a bug, or some other weirdness, start by making sure +it hasn't already been reported. You can [search through existing issues](https://github.com/angular-ui/ui-router/search?q=wat%3F&type=Issues) +to see if someone's reported one similar to yours. + +If not, then [create a plunkr](http://bit.ly/UIR-Plunk) that demonstrates the problem (try to use as little code +as possible: the more minimalist, the faster we can debug it). + +Next, [create a new issue](https://github.com/angular-ui/ui-router/issues/new) that briefly explains the problem, +and provides a bit of background as to the circumstances that triggered it. Don't forget to include the link to +that plunkr you created! + +**Note**: If you're unsure how a feature is used, or are encountering some unexpected behavior that you aren't sure +is a bug, it's best to talk it out on +[StackOverflow](http://stackoverflow.com/questions/ask?tags=angularjs,angular-ui-router) before reporting it. This +keeps development streamlined, and helps us focus on building great software. + + +Issues only! | +-------------| +Please keep in mind that the issue tracker is for *issues*. Please do *not* post an issue if you need help or support. Instead, see one of the above-mentioned forums or [IRC](irc://irc.freenode.net/#angularjs). | + +####Purple Labels +A purple label means that **you** need to take some further action. + - ![Not Actionable - Need Info](http://angular-ui.github.io/ui-router/images/notactionable.png): Your issue is not specific enough, or there is no clear action that we can take. Please clarify and refine your issue. + - ![Plunkr Please](http://angular-ui.github.io/ui-router/images/plunkrplease.png): Please [create a plunkr](http://bit.ly/UIR-Plunk) + - ![StackOverflow](http://angular-ui.github.io/ui-router/images/stackoverflow.png): We suspect your issue is really a help request, or could be answered by the community. Please ask your question on [StackOverflow](http://stackoverflow.com/questions/ask?tags=angularjs,angular-ui-router). If you determine that is an actual issue, please explain why. + +If your issue gets labeled with purple label, no further action will be taken until you respond to the label appropriately. + +# Contribute + +**(1)** See the **[Developing](#developing)** section below, to get the development version of UI-Router up and running on your local machine. + +**(2)** Check out the [roadmap](https://github.com/angular-ui/ui-router/milestones) to see where the project is headed, and if your feature idea fits with where we're headed. + +**(3)** If you're not sure, [open an RFC](https://github.com/angular-ui/ui-router/issues/new?title=RFC:%20My%20idea) to get some feedback on your idea. + +**(4)** Finally, commit some code and open a pull request. Code & commits should abide by the following rules: + +- *Always* have test coverage for new features (or regression tests for bug fixes), and *never* break existing tests +- Commits should represent one logical change each; if a feature goes through multiple iterations, squash your commits down to one +- Make sure to follow the [Angular commit message format](https://github.com/angular/angular.js/blob/master/CONTRIBUTING.md#commit-message-format) so your change will appear in the changelog of the next release. +- Changes should always respect the coding style of the project + + + +# Developing + +UI-Router uses grunt >= 0.4.x. Make sure to upgrade your environment and read the +[Migration Guide](http://gruntjs.com/upgrading-from-0.3-to-0.4). + +Dependencies for building from source and running tests: + +* [grunt-cli](https://github.com/gruntjs/grunt-cli) - run: `$ npm install -g grunt-cli` +* Then, install the development dependencies by running `$ npm install` from the project directory + +There are a number of targets in the gruntfile that are used to generating different builds: + +* `grunt`: Perform a normal build, runs jshint and karma tests +* `grunt build`: Perform a normal build +* `grunt dist`: Perform a clean build and generate documentation +* `grunt dev`: Run dev server (sample app) and watch for changes, builds and runs karma tests on changes. diff --git a/public/admincp/bower_components/angular-ui-router/LICENSE b/public/admincp/bower_components/angular-ui-router/LICENSE new file mode 100644 index 000000000..939f8f8a7 --- /dev/null +++ b/public/admincp/bower_components/angular-ui-router/LICENSE @@ -0,0 +1,21 @@ +The MIT License + +Copyright (c) 2014 The AngularUI Team, Karsten Sperling + +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/public/admincp/bower_components/angular-ui-router/README.md b/public/admincp/bower_components/angular-ui-router/README.md new file mode 100644 index 000000000..f02d83bcb --- /dev/null +++ b/public/admincp/bower_components/angular-ui-router/README.md @@ -0,0 +1,243 @@ +# AngularUI Router  [![Build Status](https://travis-ci.org/angular-ui/ui-router.svg?branch=master)](https://travis-ci.org/angular-ui/ui-router) + +#### The de-facto solution to flexible routing with nested views +--- +**[Download 0.2.11](http://angular-ui.github.io/ui-router/release/angular-ui-router.js)** (or **[Minified](http://angular-ui.github.io/ui-router/release/angular-ui-router.min.js)**) **|** +**[Guide](https://github.com/angular-ui/ui-router/wiki) |** +**[API](http://angular-ui.github.io/ui-router/site) |** +**[Sample](http://angular-ui.github.com/ui-router/sample/) ([Src](https://github.com/angular-ui/ui-router/tree/gh-pages/sample)) |** +**[FAQ](https://github.com/angular-ui/ui-router/wiki/Frequently-Asked-Questions) |** +**[Resources](#resources) |** +**[Report an Issue](https://github.com/angular-ui/ui-router/blob/master/CONTRIBUTING.md#report-an-issue) |** +**[Contribute](https://github.com/angular-ui/ui-router/blob/master/CONTRIBUTING.md#contribute) |** +**[Help!](http://stackoverflow.com/questions/ask?tags=angularjs,angular-ui-router) |** +**[Discuss](https://groups.google.com/forum/#!categories/angular-ui/router)** + +--- + +AngularUI Router is a routing framework for [AngularJS](http://angularjs.org), which allows you to organize the +parts of your interface into a [*state machine*](https://en.wikipedia.org/wiki/Finite-state_machine). Unlike the +[`$route` service](http://docs.angularjs.org/api/ngRoute.$route) in the Angular ngRoute module, which is organized around URL +routes, UI-Router is organized around [*states*](https://github.com/angular-ui/ui-router/wiki), +which may optionally have routes, as well as other behavior, attached. + +States are bound to *named*, *nested* and *parallel views*, allowing you to powerfully manage your application's interface. + +Check out the sample app: http://angular-ui.github.io/ui-router/sample/ + +- +**Note:** *UI-Router is under active development. As such, while this library is well-tested, the API may change. Consider using it in production applications only if you're comfortable following a changelog and updating your usage accordingly.* + + +## Get Started + +**(1)** Get UI-Router in one of the following ways: + - clone & [build](CONTRIBUTING.md#developing) this repository + - [download the release](http://angular-ui.github.io/ui-router/release/angular-ui-router.js) (or [minified](http://angular-ui.github.io/ui-router/release/angular-ui-router.min.js)) + - via **[Bower](http://bower.io/)**: by running `$ bower install angular-ui-router` from your console + - or via **[npm](https://www.npmjs.org/)**: by running `$ npm install angular-ui-router` from your console + - or via **[Component](https://github.com/component/component)**: by running `$ component install angular-ui/ui-router` from your console + +**(2)** Include `angular-ui-router.js` (or `angular-ui-router.min.js`) in your `index.html`, after including Angular itself (For Component users: ignore this step) + +**(3)** Add `'ui.router'` to your main module's list of dependencies (For Component users: replace `'ui.router'` with `require('angular-ui-router')`) + +When you're done, your setup should look similar to the following: + +> +```html + + + + + + + ... + + + ... + + +``` + +### [Nested States & Views](http://plnkr.co/edit/u18KQc?p=preview) + +The majority of UI-Router's power is in its ability to nest states & views. + +**(1)** First, follow the [setup](#get-started) instructions detailed above. + +**(2)** Then, add a [`ui-view` directive](https://github.com/angular-ui/ui-router/wiki/Quick-Reference#ui-view) to the `` of your app. + +> +```html + + +
      + + State 1 + State 2 + +``` + +**(3)** You'll notice we also added some links with [`ui-sref` directives](https://github.com/angular-ui/ui-router/wiki/Quick-Reference#ui-sref). In addition to managing state transitions, this directive auto-generates the `href` attribute of the `` element it's attached to, if the corresponding state has a URL. Next we'll add some templates. These will plug into the `ui-view` within `index.html`. Notice that they have their own `ui-view` as well! That is the key to nesting states and views. + +> +```html + +

      State 1

      +
      +
      Show List +
      +``` +```html + +

      State 2

      +
      +Show List +
      +``` + +**(4)** Next, we'll add some child templates. *These* will get plugged into the `ui-view` of their parent state templates. + +> +```html + +

      List of State 1 Items

      +
        +
      • {{ item }}
      • +
      +``` + +> +```html + +

      List of State 2 Things

      +
        +
      • {{ thing }}
      • +
      +``` + +**(5)** Finally, we'll wire it all up with `$stateProvider`. Set up your states in the module config, as in the following: + + +> +```javascript +myApp.config(function($stateProvider, $urlRouterProvider) { + // + // For any unmatched url, redirect to /state1 + $urlRouterProvider.otherwise("/state1"); + // + // Now set up the states + $stateProvider + .state('state1', { + url: "/state1", + templateUrl: "partials/state1.html" + }) + .state('state1.list', { + url: "/list", + templateUrl: "partials/state1.list.html", + controller: function($scope) { + $scope.items = ["A", "List", "Of", "Items"]; + } + }) + .state('state2', { + url: "/state2", + templateUrl: "partials/state2.html" + }) + .state('state2.list', { + url: "/list", + templateUrl: "partials/state2.list.html", + controller: function($scope) { + $scope.things = ["A", "Set", "Of", "Things"]; + } + }); +}); +``` + +**(6)** See this quick start example in action. +>**[Go to Quick Start Plunker for Nested States & Views](http://plnkr.co/edit/u18KQc?p=preview)** + +**(7)** This only scratches the surface +>**[Dive Deeper!](https://github.com/angular-ui/ui-router/wiki)** + + +### [Multiple & Named Views](http://plnkr.co/edit/SDOcGS?p=preview) + +Another great feature is the ability to have multiple `ui-view`s view per template. + +**Pro Tip:** *While multiple parallel views are a powerful feature, you'll often be able to manage your +interfaces more effectively by nesting your views, and pairing those views with nested states.* + +**(1)** Follow the [setup](#get-started) instructions detailed above. + +**(2)** Add one or more `ui-view` to your app, give them names. +> +```html + + +
      +
      + + Route 1 + Route 2 + +``` + +**(3)** Set up your states in the module config: +> +```javascript +myApp.config(function($stateProvider) { + $stateProvider + .state('index', { + url: "", + views: { + "viewA": { template: "index.viewA" }, + "viewB": { template: "index.viewB" } + } + }) + .state('route1', { + url: "/route1", + views: { + "viewA": { template: "route1.viewA" }, + "viewB": { template: "route1.viewB" } + } + }) + .state('route2', { + url: "/route2", + views: { + "viewA": { template: "route2.viewA" }, + "viewB": { template: "route2.viewB" } + } + }) +}); +``` + +**(4)** See this quick start example in action. +>**[Go to Quick Start Plunker for Multiple & Named Views](http://plnkr.co/edit/SDOcGS?p=preview)** + + +## Resources + +* [In-Depth Guide](https://github.com/angular-ui/ui-router/wiki) +* [API Reference](http://angular-ui.github.io/ui-router/site) +* [Sample App](http://angular-ui.github.com/ui-router/sample/) ([Source](https://github.com/angular-ui/ui-router/tree/gh-pages/sample)) +* [FAQ](https://github.com/angular-ui/ui-router/wiki/Frequently-Asked-Questions) +* [Slides comparing ngRoute to ui-router](http://slid.es/timkindberg/ui-router#/) +* [UI-Router Extras / Addons](http://christopherthielen.github.io/ui-router-extras/#/home) (@christopherthielen) + +### Videos + +* [Introduction Video](https://egghead.io/lessons/angularjs-introduction-ui-router) (egghead.io) +* [Tim Kindberg on Angular UI-Router](https://www.youtube.com/watch?v=lBqiZSemrqg) +* [Activating States](https://egghead.io/lessons/angularjs-ui-router-activating-states) (egghead.io) +* [Learn Angular.js using UI-Router](http://youtu.be/QETUuZ27N0w) (LearnCode.academy) + + + +## Reporting issues and Contributing + +Please read our [Contributor guidelines](CONTRIBUTING.md) before reporting an issue or creating a pull request. diff --git a/public/admincp/bower_components/angular-ui-router/api/angular-ui-router.d.ts b/public/admincp/bower_components/angular-ui-router/api/angular-ui-router.d.ts new file mode 100644 index 000000000..55c5d5e07 --- /dev/null +++ b/public/admincp/bower_components/angular-ui-router/api/angular-ui-router.d.ts @@ -0,0 +1,126 @@ +// Type definitions for Angular JS 1.1.5+ (ui.router module) +// Project: https://github.com/angular-ui/ui-router +// Definitions by: Michel Salib +// Definitions: https://github.com/borisyankov/DefinitelyTyped + +declare module ng.ui { + + interface IState { + name?: string; + template?: string; + templateUrl?: any; // string || () => string + templateProvider?: any; // () => string || IPromise + controller?: any; + controllerAs?: string; + controllerProvider?: any; + resolve?: {}; + url?: string; + params?: any; + views?: {}; + abstract?: boolean; + onEnter?: (...args: any[]) => void; + onExit?: (...args: any[]) => void; + data?: any; + reloadOnSearch?: boolean; + } + + interface ITypedState extends IState { + data?: T; + } + + interface IStateProvider extends IServiceProvider { + state(name: string, config: IState): IStateProvider; + state(config: IState): IStateProvider; + decorator(name?: string, decorator?: (state: IState, parent: Function) => any): any; + } + + interface IUrlMatcher { + concat(pattern: string): IUrlMatcher; + exec(path: string, searchParams: {}): {}; + parameters(): string[]; + format(values: {}): string; + } + + interface IUrlMatcherFactory { + compile(pattern: string): IUrlMatcher; + isMatcher(o: any): boolean; + } + + interface IUrlRouterProvider extends IServiceProvider { + when(whenPath: RegExp, handler: Function): IUrlRouterProvider; + when(whenPath: RegExp, handler: any[]): IUrlRouterProvider; + when(whenPath: RegExp, toPath: string): IUrlRouterProvider; + when(whenPath: IUrlMatcher, hanlder: Function): IUrlRouterProvider; + when(whenPath: IUrlMatcher, handler: any[]): IUrlRouterProvider; + when(whenPath: IUrlMatcher, toPath: string): IUrlRouterProvider; + when(whenPath: string, handler: Function): IUrlRouterProvider; + when(whenPath: string, handler: any[]): IUrlRouterProvider; + when(whenPath: string, toPath: string): IUrlRouterProvider; + otherwise(handler: Function): IUrlRouterProvider; + otherwise(handler: any[]): IUrlRouterProvider; + otherwise(path: string): IUrlRouterProvider; + rule(handler: Function): IUrlRouterProvider; + rule(handler: any[]): IUrlRouterProvider; + } + + interface IStateOptions { + location?: any; + inherit?: boolean; + relative?: IState; + notify?: boolean; + reload?: boolean; + } + + interface IHrefOptions { + lossy?: boolean; + inherit?: boolean; + relative?: IState; + absolute?: boolean; + } + + interface IStateService { + go(to: string, params?: {}, options?: IStateOptions): IPromise; + transitionTo(state: string, params?: {}, updateLocation?: boolean): void; + transitionTo(state: string, params?: {}, options?: IStateOptions): void; + includes(state: string, params?: {}): boolean; + is(state:string, params?: {}): boolean; + is(state: IState, params?: {}): boolean; + href(state: IState, params?: {}, options?: IHrefOptions): string; + href(state: string, params?: {}, options?: IHrefOptions): string; + get(state: string): IState; + get(): IState[]; + current: IState; + params: any; + reload(): void; + } + + interface IStateParamsService { + [key: string]: any; + } + + interface IStateParams { + [key: string]: any; + } + + interface IUrlRouterService { + /* + * Triggers an update; the same update that happens when the address bar + * url changes, aka $locationChangeSuccess. + * + * This method is useful when you need to use preventDefault() on the + * $locationChangeSuccess event, perform some custom logic (route protection, + * auth, config, redirection, etc) and then finally proceed with the transition + * by calling $urlRouter.sync(). + * + */ + sync(): void; + } + + interface IUiViewScrollProvider { + /* + * Reverts back to using the core $anchorScroll service for scrolling + * based on the url anchor. + */ + useAnchorScroll(): void; + } +} diff --git a/public/admincp/bower_components/angular-ui-router/bower.json b/public/admincp/bower_components/angular-ui-router/bower.json new file mode 100644 index 000000000..45e802a88 --- /dev/null +++ b/public/admincp/bower_components/angular-ui-router/bower.json @@ -0,0 +1,23 @@ +{ + "name": "angular-ui-router", + "version": "0.2.13", + "main": "./release/angular-ui-router.js", + "dependencies": { + "angular": ">= 1.0.8" + }, + "ignore": [ + "**/.*", + "node_modules", + "bower_components", + "component.json", + "package.json", + "lib", + "config", + "sample", + "test", + "tests", + "ngdoc_assets", + "Gruntfile.js", + "files.js" + ] +} diff --git a/public/admincp/bower_components/angular-ui-router/release/angular-ui-router.js b/public/admincp/bower_components/angular-ui-router/release/angular-ui-router.js new file mode 100644 index 000000000..d2636f8ec --- /dev/null +++ b/public/admincp/bower_components/angular-ui-router/release/angular-ui-router.js @@ -0,0 +1,4232 @@ +/** + * State-based routing for AngularJS + * @version v0.2.13 + * @link http://angular-ui.github.com/ + * @license MIT License, http://www.opensource.org/licenses/MIT + */ + +/* commonjs package manager support (eg componentjs) */ +if (typeof module !== "undefined" && typeof exports !== "undefined" && module.exports === exports){ + module.exports = 'ui.router'; +} + +(function (window, angular, undefined) { +/*jshint globalstrict:true*/ +/*global angular:false*/ +'use strict'; + +var isDefined = angular.isDefined, + isFunction = angular.isFunction, + isString = angular.isString, + isObject = angular.isObject, + isArray = angular.isArray, + forEach = angular.forEach, + extend = angular.extend, + copy = angular.copy; + +function inherit(parent, extra) { + return extend(new (extend(function() {}, { prototype: parent }))(), extra); +} + +function merge(dst) { + forEach(arguments, function(obj) { + if (obj !== dst) { + forEach(obj, function(value, key) { + if (!dst.hasOwnProperty(key)) dst[key] = value; + }); + } + }); + return dst; +} + +/** + * Finds the common ancestor path between two states. + * + * @param {Object} first The first state. + * @param {Object} second The second state. + * @return {Array} Returns an array of state names in descending order, not including the root. + */ +function ancestors(first, second) { + var path = []; + + for (var n in first.path) { + if (first.path[n] !== second.path[n]) break; + path.push(first.path[n]); + } + return path; +} + +/** + * IE8-safe wrapper for `Object.keys()`. + * + * @param {Object} object A JavaScript object. + * @return {Array} Returns the keys of the object as an array. + */ +function objectKeys(object) { + if (Object.keys) { + return Object.keys(object); + } + var result = []; + + angular.forEach(object, function(val, key) { + result.push(key); + }); + return result; +} + +/** + * IE8-safe wrapper for `Array.prototype.indexOf()`. + * + * @param {Array} array A JavaScript array. + * @param {*} value A value to search the array for. + * @return {Number} Returns the array index value of `value`, or `-1` if not present. + */ +function indexOf(array, value) { + if (Array.prototype.indexOf) { + return array.indexOf(value, Number(arguments[2]) || 0); + } + var len = array.length >>> 0, from = Number(arguments[2]) || 0; + from = (from < 0) ? Math.ceil(from) : Math.floor(from); + + if (from < 0) from += len; + + for (; from < len; from++) { + if (from in array && array[from] === value) return from; + } + return -1; +} + +/** + * Merges a set of parameters with all parameters inherited between the common parents of the + * current state and a given destination state. + * + * @param {Object} currentParams The value of the current state parameters ($stateParams). + * @param {Object} newParams The set of parameters which will be composited with inherited params. + * @param {Object} $current Internal definition of object representing the current state. + * @param {Object} $to Internal definition of object representing state to transition to. + */ +function inheritParams(currentParams, newParams, $current, $to) { + var parents = ancestors($current, $to), parentParams, inherited = {}, inheritList = []; + + for (var i in parents) { + if (!parents[i].params) continue; + parentParams = objectKeys(parents[i].params); + if (!parentParams.length) continue; + + for (var j in parentParams) { + if (indexOf(inheritList, parentParams[j]) >= 0) continue; + inheritList.push(parentParams[j]); + inherited[parentParams[j]] = currentParams[parentParams[j]]; + } + } + return extend({}, inherited, newParams); +} + +/** + * Performs a non-strict comparison of the subset of two objects, defined by a list of keys. + * + * @param {Object} a The first object. + * @param {Object} b The second object. + * @param {Array} keys The list of keys within each object to compare. If the list is empty or not specified, + * it defaults to the list of keys in `a`. + * @return {Boolean} Returns `true` if the keys match, otherwise `false`. + */ +function equalForKeys(a, b, keys) { + if (!keys) { + keys = []; + for (var n in a) keys.push(n); // Used instead of Object.keys() for IE8 compatibility + } + + for (var i=0; i + * + * + * + * + * + * + * + * + * + * + * + * + */ +angular.module('ui.router', ['ui.router.state']); + +angular.module('ui.router.compat', ['ui.router']); + +/** + * @ngdoc object + * @name ui.router.util.$resolve + * + * @requires $q + * @requires $injector + * + * @description + * Manages resolution of (acyclic) graphs of promises. + */ +$Resolve.$inject = ['$q', '$injector']; +function $Resolve( $q, $injector) { + + var VISIT_IN_PROGRESS = 1, + VISIT_DONE = 2, + NOTHING = {}, + NO_DEPENDENCIES = [], + NO_LOCALS = NOTHING, + NO_PARENT = extend($q.when(NOTHING), { $$promises: NOTHING, $$values: NOTHING }); + + + /** + * @ngdoc function + * @name ui.router.util.$resolve#study + * @methodOf ui.router.util.$resolve + * + * @description + * Studies a set of invocables that are likely to be used multiple times. + *
      +   * $resolve.study(invocables)(locals, parent, self)
      +   * 
      + * is equivalent to + *
      +   * $resolve.resolve(invocables, locals, parent, self)
      +   * 
      + * but the former is more efficient (in fact `resolve` just calls `study` + * internally). + * + * @param {object} invocables Invocable objects + * @return {function} a function to pass in locals, parent and self + */ + this.study = function (invocables) { + if (!isObject(invocables)) throw new Error("'invocables' must be an object"); + var invocableKeys = objectKeys(invocables || {}); + + // Perform a topological sort of invocables to build an ordered plan + var plan = [], cycle = [], visited = {}; + function visit(value, key) { + if (visited[key] === VISIT_DONE) return; + + cycle.push(key); + if (visited[key] === VISIT_IN_PROGRESS) { + cycle.splice(0, indexOf(cycle, key)); + throw new Error("Cyclic dependency: " + cycle.join(" -> ")); + } + visited[key] = VISIT_IN_PROGRESS; + + if (isString(value)) { + plan.push(key, [ function() { return $injector.get(value); }], NO_DEPENDENCIES); + } else { + var params = $injector.annotate(value); + forEach(params, function (param) { + if (param !== key && invocables.hasOwnProperty(param)) visit(invocables[param], param); + }); + plan.push(key, value, params); + } + + cycle.pop(); + visited[key] = VISIT_DONE; + } + forEach(invocables, visit); + invocables = cycle = visited = null; // plan is all that's required + + function isResolve(value) { + return isObject(value) && value.then && value.$$promises; + } + + return function (locals, parent, self) { + if (isResolve(locals) && self === undefined) { + self = parent; parent = locals; locals = null; + } + if (!locals) locals = NO_LOCALS; + else if (!isObject(locals)) { + throw new Error("'locals' must be an object"); + } + if (!parent) parent = NO_PARENT; + else if (!isResolve(parent)) { + throw new Error("'parent' must be a promise returned by $resolve.resolve()"); + } + + // To complete the overall resolution, we have to wait for the parent + // promise and for the promise for each invokable in our plan. + var resolution = $q.defer(), + result = resolution.promise, + promises = result.$$promises = {}, + values = extend({}, locals), + wait = 1 + plan.length/3, + merged = false; + + function done() { + // Merge parent values we haven't got yet and publish our own $$values + if (!--wait) { + if (!merged) merge(values, parent.$$values); + result.$$values = values; + result.$$promises = result.$$promises || true; // keep for isResolve() + delete result.$$inheritedValues; + resolution.resolve(values); + } + } + + function fail(reason) { + result.$$failure = reason; + resolution.reject(reason); + } + + // Short-circuit if parent has already failed + if (isDefined(parent.$$failure)) { + fail(parent.$$failure); + return result; + } + + if (parent.$$inheritedValues) { + merge(values, omit(parent.$$inheritedValues, invocableKeys)); + } + + // Merge parent values if the parent has already resolved, or merge + // parent promises and wait if the parent resolve is still in progress. + extend(promises, parent.$$promises); + if (parent.$$values) { + merged = merge(values, omit(parent.$$values, invocableKeys)); + result.$$inheritedValues = omit(parent.$$values, invocableKeys); + done(); + } else { + if (parent.$$inheritedValues) { + result.$$inheritedValues = omit(parent.$$inheritedValues, invocableKeys); + } + parent.then(done, fail); + } + + // Process each invocable in the plan, but ignore any where a local of the same name exists. + for (var i=0, ii=plan.length; i} The template html as a string, or a promise + * for that string. + */ + this.fromUrl = function (url, params) { + if (isFunction(url)) url = url(params); + if (url == null) return null; + else return $http + .get(url, { cache: $templateCache, headers: { Accept: 'text/html' }}) + .then(function(response) { return response.data; }); + }; + + /** + * @ngdoc function + * @name ui.router.util.$templateFactory#fromProvider + * @methodOf ui.router.util.$templateFactory + * + * @description + * Creates a template by invoking an injectable provider function. + * + * @param {Function} provider Function to invoke via `$injector.invoke` + * @param {Object} params Parameters for the template. + * @param {Object} locals Locals to pass to `invoke`. Defaults to + * `{ params: params }`. + * @return {string|Promise.} The template html as a string, or a promise + * for that string. + */ + this.fromProvider = function (provider, params, locals) { + return $injector.invoke(provider, null, locals || { params: params }); + }; +} + +angular.module('ui.router.util').service('$templateFactory', $TemplateFactory); + +var $$UMFP; // reference to $UrlMatcherFactoryProvider + +/** + * @ngdoc object + * @name ui.router.util.type:UrlMatcher + * + * @description + * Matches URLs against patterns and extracts named parameters from the path or the search + * part of the URL. A URL pattern consists of a path pattern, optionally followed by '?' and a list + * of search parameters. Multiple search parameter names are separated by '&'. Search parameters + * do not influence whether or not a URL is matched, but their values are passed through into + * the matched parameters returned by {@link ui.router.util.type:UrlMatcher#methods_exec exec}. + * + * Path parameter placeholders can be specified using simple colon/catch-all syntax or curly brace + * syntax, which optionally allows a regular expression for the parameter to be specified: + * + * * `':'` name - colon placeholder + * * `'*'` name - catch-all placeholder + * * `'{' name '}'` - curly placeholder + * * `'{' name ':' regexp|type '}'` - curly placeholder with regexp or type name. Should the + * regexp itself contain curly braces, they must be in matched pairs or escaped with a backslash. + * + * Parameter names may contain only word characters (latin letters, digits, and underscore) and + * must be unique within the pattern (across both path and search parameters). For colon + * placeholders or curly placeholders without an explicit regexp, a path parameter matches any + * number of characters other than '/'. For catch-all placeholders the path parameter matches + * any number of characters. + * + * Examples: + * + * * `'/hello/'` - Matches only if the path is exactly '/hello/'. There is no special treatment for + * trailing slashes, and patterns have to match the entire path, not just a prefix. + * * `'/user/:id'` - Matches '/user/bob' or '/user/1234!!!' or even '/user/' but not '/user' or + * '/user/bob/details'. The second path segment will be captured as the parameter 'id'. + * * `'/user/{id}'` - Same as the previous example, but using curly brace syntax. + * * `'/user/{id:[^/]*}'` - Same as the previous example. + * * `'/user/{id:[0-9a-fA-F]{1,8}}'` - Similar to the previous example, but only matches if the id + * parameter consists of 1 to 8 hex digits. + * * `'/files/{path:.*}'` - Matches any URL starting with '/files/' and captures the rest of the + * path into the parameter 'path'. + * * `'/files/*path'` - ditto. + * * `'/calendar/{start:date}'` - Matches "/calendar/2014-11-12" (because the pattern defined + * in the built-in `date` Type matches `2014-11-12`) and provides a Date object in $stateParams.start + * + * @param {string} pattern The pattern to compile into a matcher. + * @param {Object} config A configuration object hash: + * @param {Object=} parentMatcher Used to concatenate the pattern/config onto + * an existing UrlMatcher + * + * * `caseInsensitive` - `true` if URL matching should be case insensitive, otherwise `false`, the default value (for backward compatibility) is `false`. + * * `strict` - `false` if matching against a URL with a trailing slash should be treated as equivalent to a URL without a trailing slash, the default value is `true`. + * + * @property {string} prefix A static prefix of this pattern. The matcher guarantees that any + * URL matching this matcher (i.e. any string for which {@link ui.router.util.type:UrlMatcher#methods_exec exec()} returns + * non-null) will start with this prefix. + * + * @property {string} source The pattern that was passed into the constructor + * + * @property {string} sourcePath The path portion of the source property + * + * @property {string} sourceSearch The search portion of the source property + * + * @property {string} regex The constructed regex that will be used to match against the url when + * it is time to determine which url will match. + * + * @returns {Object} New `UrlMatcher` object + */ +function UrlMatcher(pattern, config, parentMatcher) { + config = extend({ params: {} }, isObject(config) ? config : {}); + + // Find all placeholders and create a compiled pattern, using either classic or curly syntax: + // '*' name + // ':' name + // '{' name '}' + // '{' name ':' regexp '}' + // The regular expression is somewhat complicated due to the need to allow curly braces + // inside the regular expression. The placeholder regexp breaks down as follows: + // ([:*])([\w\[\]]+) - classic placeholder ($1 / $2) (search version has - for snake-case) + // \{([\w\[\]]+)(?:\:( ... ))?\} - curly brace placeholder ($3) with optional regexp/type ... ($4) (search version has - for snake-case + // (?: ... | ... | ... )+ - the regexp consists of any number of atoms, an atom being either + // [^{}\\]+ - anything other than curly braces or backslash + // \\. - a backslash escape + // \{(?:[^{}\\]+|\\.)*\} - a matched set of curly braces containing other atoms + var placeholder = /([:*])([\w\[\]]+)|\{([\w\[\]]+)(?:\:((?:[^{}\\]+|\\.|\{(?:[^{}\\]+|\\.)*\})+))?\}/g, + searchPlaceholder = /([:]?)([\w\[\]-]+)|\{([\w\[\]-]+)(?:\:((?:[^{}\\]+|\\.|\{(?:[^{}\\]+|\\.)*\})+))?\}/g, + compiled = '^', last = 0, m, + segments = this.segments = [], + parentParams = parentMatcher ? parentMatcher.params : {}, + params = this.params = parentMatcher ? parentMatcher.params.$$new() : new $$UMFP.ParamSet(), + paramNames = []; + + function addParameter(id, type, config, location) { + paramNames.push(id); + if (parentParams[id]) return parentParams[id]; + if (!/^\w+(-+\w+)*(?:\[\])?$/.test(id)) throw new Error("Invalid parameter name '" + id + "' in pattern '" + pattern + "'"); + if (params[id]) throw new Error("Duplicate parameter name '" + id + "' in pattern '" + pattern + "'"); + params[id] = new $$UMFP.Param(id, type, config, location); + return params[id]; + } + + function quoteRegExp(string, pattern, squash) { + var surroundPattern = ['',''], result = string.replace(/[\\\[\]\^$*+?.()|{}]/g, "\\$&"); + if (!pattern) return result; + switch(squash) { + case false: surroundPattern = ['(', ')']; break; + case true: surroundPattern = ['?(', ')?']; break; + default: surroundPattern = ['(' + squash + "|", ')?']; break; + } + return result + surroundPattern[0] + pattern + surroundPattern[1]; + } + + this.source = pattern; + + // Split into static segments separated by path parameter placeholders. + // The number of segments is always 1 more than the number of parameters. + function matchDetails(m, isSearch) { + var id, regexp, segment, type, cfg, arrayMode; + id = m[2] || m[3]; // IE[78] returns '' for unmatched groups instead of null + cfg = config.params[id]; + segment = pattern.substring(last, m.index); + regexp = isSearch ? m[4] : m[4] || (m[1] == '*' ? '.*' : null); + type = $$UMFP.type(regexp || "string") || inherit($$UMFP.type("string"), { pattern: new RegExp(regexp) }); + return { + id: id, regexp: regexp, segment: segment, type: type, cfg: cfg + }; + } + + var p, param, segment; + while ((m = placeholder.exec(pattern))) { + p = matchDetails(m, false); + if (p.segment.indexOf('?') >= 0) break; // we're into the search part + + param = addParameter(p.id, p.type, p.cfg, "path"); + compiled += quoteRegExp(p.segment, param.type.pattern.source, param.squash); + segments.push(p.segment); + last = placeholder.lastIndex; + } + segment = pattern.substring(last); + + // Find any search parameter names and remove them from the last segment + var i = segment.indexOf('?'); + + if (i >= 0) { + var search = this.sourceSearch = segment.substring(i); + segment = segment.substring(0, i); + this.sourcePath = pattern.substring(0, last + i); + + if (search.length > 0) { + last = 0; + while ((m = searchPlaceholder.exec(search))) { + p = matchDetails(m, true); + param = addParameter(p.id, p.type, p.cfg, "search"); + last = placeholder.lastIndex; + // check if ?& + } + } + } else { + this.sourcePath = pattern; + this.sourceSearch = ''; + } + + compiled += quoteRegExp(segment) + (config.strict === false ? '\/?' : '') + '$'; + segments.push(segment); + + this.regexp = new RegExp(compiled, config.caseInsensitive ? 'i' : undefined); + this.prefix = segments[0]; + this.$$paramNames = paramNames; +} + +/** + * @ngdoc function + * @name ui.router.util.type:UrlMatcher#concat + * @methodOf ui.router.util.type:UrlMatcher + * + * @description + * Returns a new matcher for a pattern constructed by appending the path part and adding the + * search parameters of the specified pattern to this pattern. The current pattern is not + * modified. This can be understood as creating a pattern for URLs that are relative to (or + * suffixes of) the current pattern. + * + * @example + * The following two matchers are equivalent: + *
      + * new UrlMatcher('/user/{id}?q').concat('/details?date');
      + * new UrlMatcher('/user/{id}/details?q&date');
      + * 
      + * + * @param {string} pattern The pattern to append. + * @param {Object} config An object hash of the configuration for the matcher. + * @returns {UrlMatcher} A matcher for the concatenated pattern. + */ +UrlMatcher.prototype.concat = function (pattern, config) { + // Because order of search parameters is irrelevant, we can add our own search + // parameters to the end of the new pattern. Parse the new pattern by itself + // and then join the bits together, but it's much easier to do this on a string level. + var defaultConfig = { + caseInsensitive: $$UMFP.caseInsensitive(), + strict: $$UMFP.strictMode(), + squash: $$UMFP.defaultSquashPolicy() + }; + return new UrlMatcher(this.sourcePath + pattern + this.sourceSearch, extend(defaultConfig, config), this); +}; + +UrlMatcher.prototype.toString = function () { + return this.source; +}; + +/** + * @ngdoc function + * @name ui.router.util.type:UrlMatcher#exec + * @methodOf ui.router.util.type:UrlMatcher + * + * @description + * Tests the specified path against this matcher, and returns an object containing the captured + * parameter values, or null if the path does not match. The returned object contains the values + * of any search parameters that are mentioned in the pattern, but their value may be null if + * they are not present in `searchParams`. This means that search parameters are always treated + * as optional. + * + * @example + *
      + * new UrlMatcher('/user/{id}?q&r').exec('/user/bob', {
      + *   x: '1', q: 'hello'
      + * });
      + * // returns { id: 'bob', q: 'hello', r: null }
      + * 
      + * + * @param {string} path The URL path to match, e.g. `$location.path()`. + * @param {Object} searchParams URL search parameters, e.g. `$location.search()`. + * @returns {Object} The captured parameter values. + */ +UrlMatcher.prototype.exec = function (path, searchParams) { + var m = this.regexp.exec(path); + if (!m) return null; + searchParams = searchParams || {}; + + var paramNames = this.parameters(), nTotal = paramNames.length, + nPath = this.segments.length - 1, + values = {}, i, j, cfg, paramName; + + if (nPath !== m.length - 1) throw new Error("Unbalanced capture group in route '" + this.source + "'"); + + function decodePathArray(string) { + function reverseString(str) { return str.split("").reverse().join(""); } + function unquoteDashes(str) { return str.replace(/\\-/, "-"); } + + var split = reverseString(string).split(/-(?!\\)/); + var allReversed = map(split, reverseString); + return map(allReversed, unquoteDashes).reverse(); + } + + for (i = 0; i < nPath; i++) { + paramName = paramNames[i]; + var param = this.params[paramName]; + var paramVal = m[i+1]; + // if the param value matches a pre-replace pair, replace the value before decoding. + for (j = 0; j < param.replace; j++) { + if (param.replace[j].from === paramVal) paramVal = param.replace[j].to; + } + if (paramVal && param.array === true) paramVal = decodePathArray(paramVal); + values[paramName] = param.value(paramVal); + } + for (/**/; i < nTotal; i++) { + paramName = paramNames[i]; + values[paramName] = this.params[paramName].value(searchParams[paramName]); + } + + return values; +}; + +/** + * @ngdoc function + * @name ui.router.util.type:UrlMatcher#parameters + * @methodOf ui.router.util.type:UrlMatcher + * + * @description + * Returns the names of all path and search parameters of this pattern in an unspecified order. + * + * @returns {Array.} An array of parameter names. Must be treated as read-only. If the + * pattern has no parameters, an empty array is returned. + */ +UrlMatcher.prototype.parameters = function (param) { + if (!isDefined(param)) return this.$$paramNames; + return this.params[param] || null; +}; + +/** + * @ngdoc function + * @name ui.router.util.type:UrlMatcher#validate + * @methodOf ui.router.util.type:UrlMatcher + * + * @description + * Checks an object hash of parameters to validate their correctness according to the parameter + * types of this `UrlMatcher`. + * + * @param {Object} params The object hash of parameters to validate. + * @returns {boolean} Returns `true` if `params` validates, otherwise `false`. + */ +UrlMatcher.prototype.validates = function (params) { + return this.params.$$validates(params); +}; + +/** + * @ngdoc function + * @name ui.router.util.type:UrlMatcher#format + * @methodOf ui.router.util.type:UrlMatcher + * + * @description + * Creates a URL that matches this pattern by substituting the specified values + * for the path and search parameters. Null values for path parameters are + * treated as empty strings. + * + * @example + *
      + * new UrlMatcher('/user/{id}?q').format({ id:'bob', q:'yes' });
      + * // returns '/user/bob?q=yes'
      + * 
      + * + * @param {Object} values the values to substitute for the parameters in this pattern. + * @returns {string} the formatted URL (path and optionally search part). + */ +UrlMatcher.prototype.format = function (values) { + values = values || {}; + var segments = this.segments, params = this.parameters(), paramset = this.params; + if (!this.validates(values)) return null; + + var i, search = false, nPath = segments.length - 1, nTotal = params.length, result = segments[0]; + + function encodeDashes(str) { // Replace dashes with encoded "\-" + return encodeURIComponent(str).replace(/-/g, function(c) { return '%5C%' + c.charCodeAt(0).toString(16).toUpperCase(); }); + } + + for (i = 0; i < nTotal; i++) { + var isPathParam = i < nPath; + var name = params[i], param = paramset[name], value = param.value(values[name]); + var isDefaultValue = param.isOptional && param.type.equals(param.value(), value); + var squash = isDefaultValue ? param.squash : false; + var encoded = param.type.encode(value); + + if (isPathParam) { + var nextSegment = segments[i + 1]; + if (squash === false) { + if (encoded != null) { + if (isArray(encoded)) { + result += map(encoded, encodeDashes).join("-"); + } else { + result += encodeURIComponent(encoded); + } + } + result += nextSegment; + } else if (squash === true) { + var capture = result.match(/\/$/) ? /\/?(.*)/ : /(.*)/; + result += nextSegment.match(capture)[1]; + } else if (isString(squash)) { + result += squash + nextSegment; + } + } else { + if (encoded == null || (isDefaultValue && squash !== false)) continue; + if (!isArray(encoded)) encoded = [ encoded ]; + encoded = map(encoded, encodeURIComponent).join('&' + name + '='); + result += (search ? '&' : '?') + (name + '=' + encoded); + search = true; + } + } + + return result; +}; + +/** + * @ngdoc object + * @name ui.router.util.type:Type + * + * @description + * Implements an interface to define custom parameter types that can be decoded from and encoded to + * string parameters matched in a URL. Used by {@link ui.router.util.type:UrlMatcher `UrlMatcher`} + * objects when matching or formatting URLs, or comparing or validating parameter values. + * + * See {@link ui.router.util.$urlMatcherFactory#methods_type `$urlMatcherFactory#type()`} for more + * information on registering custom types. + * + * @param {Object} config A configuration object which contains the custom type definition. The object's + * properties will override the default methods and/or pattern in `Type`'s public interface. + * @example + *
      + * {
      + *   decode: function(val) { return parseInt(val, 10); },
      + *   encode: function(val) { return val && val.toString(); },
      + *   equals: function(a, b) { return this.is(a) && a === b; },
      + *   is: function(val) { return angular.isNumber(val) isFinite(val) && val % 1 === 0; },
      + *   pattern: /\d+/
      + * }
      + * 
      + * + * @property {RegExp} pattern The regular expression pattern used to match values of this type when + * coming from a substring of a URL. + * + * @returns {Object} Returns a new `Type` object. + */ +function Type(config) { + extend(this, config); +} + +/** + * @ngdoc function + * @name ui.router.util.type:Type#is + * @methodOf ui.router.util.type:Type + * + * @description + * Detects whether a value is of a particular type. Accepts a native (decoded) value + * and determines whether it matches the current `Type` object. + * + * @param {*} val The value to check. + * @param {string} key Optional. If the type check is happening in the context of a specific + * {@link ui.router.util.type:UrlMatcher `UrlMatcher`} object, this is the name of the + * parameter in which `val` is stored. Can be used for meta-programming of `Type` objects. + * @returns {Boolean} Returns `true` if the value matches the type, otherwise `false`. + */ +Type.prototype.is = function(val, key) { + return true; +}; + +/** + * @ngdoc function + * @name ui.router.util.type:Type#encode + * @methodOf ui.router.util.type:Type + * + * @description + * Encodes a custom/native type value to a string that can be embedded in a URL. Note that the + * return value does *not* need to be URL-safe (i.e. passed through `encodeURIComponent()`), it + * only needs to be a representation of `val` that has been coerced to a string. + * + * @param {*} val The value to encode. + * @param {string} key The name of the parameter in which `val` is stored. Can be used for + * meta-programming of `Type` objects. + * @returns {string} Returns a string representation of `val` that can be encoded in a URL. + */ +Type.prototype.encode = function(val, key) { + return val; +}; + +/** + * @ngdoc function + * @name ui.router.util.type:Type#decode + * @methodOf ui.router.util.type:Type + * + * @description + * Converts a parameter value (from URL string or transition param) to a custom/native value. + * + * @param {string} val The URL parameter value to decode. + * @param {string} key The name of the parameter in which `val` is stored. Can be used for + * meta-programming of `Type` objects. + * @returns {*} Returns a custom representation of the URL parameter value. + */ +Type.prototype.decode = function(val, key) { + return val; +}; + +/** + * @ngdoc function + * @name ui.router.util.type:Type#equals + * @methodOf ui.router.util.type:Type + * + * @description + * Determines whether two decoded values are equivalent. + * + * @param {*} a A value to compare against. + * @param {*} b A value to compare against. + * @returns {Boolean} Returns `true` if the values are equivalent/equal, otherwise `false`. + */ +Type.prototype.equals = function(a, b) { + return a == b; +}; + +Type.prototype.$subPattern = function() { + var sub = this.pattern.toString(); + return sub.substr(1, sub.length - 2); +}; + +Type.prototype.pattern = /.*/; + +Type.prototype.toString = function() { return "{Type:" + this.name + "}"; }; + +/* + * Wraps an existing custom Type as an array of Type, depending on 'mode'. + * e.g.: + * - urlmatcher pattern "/path?{queryParam[]:int}" + * - url: "/path?queryParam=1&queryParam=2 + * - $stateParams.queryParam will be [1, 2] + * if `mode` is "auto", then + * - url: "/path?queryParam=1 will create $stateParams.queryParam: 1 + * - url: "/path?queryParam=1&queryParam=2 will create $stateParams.queryParam: [1, 2] + */ +Type.prototype.$asArray = function(mode, isSearch) { + if (!mode) return this; + if (mode === "auto" && !isSearch) throw new Error("'auto' array mode is for query parameters only"); + return new ArrayType(this, mode); + + function ArrayType(type, mode) { + function bindTo(type, callbackName) { + return function() { + return type[callbackName].apply(type, arguments); + }; + } + + // Wrap non-array value as array + function arrayWrap(val) { return isArray(val) ? val : (isDefined(val) ? [ val ] : []); } + // Unwrap array value for "auto" mode. Return undefined for empty array. + function arrayUnwrap(val) { + switch(val.length) { + case 0: return undefined; + case 1: return mode === "auto" ? val[0] : val; + default: return val; + } + } + function falsey(val) { return !val; } + + // Wraps type (.is/.encode/.decode) functions to operate on each value of an array + function arrayHandler(callback, allTruthyMode) { + return function handleArray(val) { + val = arrayWrap(val); + var result = map(val, callback); + if (allTruthyMode === true) + return filter(result, falsey).length === 0; + return arrayUnwrap(result); + }; + } + + // Wraps type (.equals) functions to operate on each value of an array + function arrayEqualsHandler(callback) { + return function handleArray(val1, val2) { + var left = arrayWrap(val1), right = arrayWrap(val2); + if (left.length !== right.length) return false; + for (var i = 0; i < left.length; i++) { + if (!callback(left[i], right[i])) return false; + } + return true; + }; + } + + this.encode = arrayHandler(bindTo(type, 'encode')); + this.decode = arrayHandler(bindTo(type, 'decode')); + this.is = arrayHandler(bindTo(type, 'is'), true); + this.equals = arrayEqualsHandler(bindTo(type, 'equals')); + this.pattern = type.pattern; + this.$arrayMode = mode; + } +}; + + + +/** + * @ngdoc object + * @name ui.router.util.$urlMatcherFactory + * + * @description + * Factory for {@link ui.router.util.type:UrlMatcher `UrlMatcher`} instances. The factory + * is also available to providers under the name `$urlMatcherFactoryProvider`. + */ +function $UrlMatcherFactory() { + $$UMFP = this; + + var isCaseInsensitive = false, isStrictMode = true, defaultSquashPolicy = false; + + function valToString(val) { return val != null ? val.toString().replace(/\//g, "%2F") : val; } + function valFromString(val) { return val != null ? val.toString().replace(/%2F/g, "/") : val; } +// TODO: in 1.0, make string .is() return false if value is undefined by default. +// function regexpMatches(val) { /*jshint validthis:true */ return isDefined(val) && this.pattern.test(val); } + function regexpMatches(val) { /*jshint validthis:true */ return this.pattern.test(val); } + + var $types = {}, enqueue = true, typeQueue = [], injector, defaultTypes = { + string: { + encode: valToString, + decode: valFromString, + is: regexpMatches, + pattern: /[^/]*/ + }, + int: { + encode: valToString, + decode: function(val) { return parseInt(val, 10); }, + is: function(val) { return isDefined(val) && this.decode(val.toString()) === val; }, + pattern: /\d+/ + }, + bool: { + encode: function(val) { return val ? 1 : 0; }, + decode: function(val) { return parseInt(val, 10) !== 0; }, + is: function(val) { return val === true || val === false; }, + pattern: /0|1/ + }, + date: { + encode: function (val) { + if (!this.is(val)) + return undefined; + return [ val.getFullYear(), + ('0' + (val.getMonth() + 1)).slice(-2), + ('0' + val.getDate()).slice(-2) + ].join("-"); + }, + decode: function (val) { + if (this.is(val)) return val; + var match = this.capture.exec(val); + return match ? new Date(match[1], match[2] - 1, match[3]) : undefined; + }, + is: function(val) { return val instanceof Date && !isNaN(val.valueOf()); }, + equals: function (a, b) { return this.is(a) && this.is(b) && a.toISOString() === b.toISOString(); }, + pattern: /[0-9]{4}-(?:0[1-9]|1[0-2])-(?:0[1-9]|[1-2][0-9]|3[0-1])/, + capture: /([0-9]{4})-(0[1-9]|1[0-2])-(0[1-9]|[1-2][0-9]|3[0-1])/ + }, + json: { + encode: angular.toJson, + decode: angular.fromJson, + is: angular.isObject, + equals: angular.equals, + pattern: /[^/]*/ + }, + any: { // does not encode/decode + encode: angular.identity, + decode: angular.identity, + is: angular.identity, + equals: angular.equals, + pattern: /.*/ + } + }; + + function getDefaultConfig() { + return { + strict: isStrictMode, + caseInsensitive: isCaseInsensitive + }; + } + + function isInjectable(value) { + return (isFunction(value) || (isArray(value) && isFunction(value[value.length - 1]))); + } + + /** + * [Internal] Get the default value of a parameter, which may be an injectable function. + */ + $UrlMatcherFactory.$$getDefaultValue = function(config) { + if (!isInjectable(config.value)) return config.value; + if (!injector) throw new Error("Injectable functions cannot be called at configuration time"); + return injector.invoke(config.value); + }; + + /** + * @ngdoc function + * @name ui.router.util.$urlMatcherFactory#caseInsensitive + * @methodOf ui.router.util.$urlMatcherFactory + * + * @description + * Defines whether URL matching should be case sensitive (the default behavior), or not. + * + * @param {boolean} value `false` to match URL in a case sensitive manner; otherwise `true`; + * @returns {boolean} the current value of caseInsensitive + */ + this.caseInsensitive = function(value) { + if (isDefined(value)) + isCaseInsensitive = value; + return isCaseInsensitive; + }; + + /** + * @ngdoc function + * @name ui.router.util.$urlMatcherFactory#strictMode + * @methodOf ui.router.util.$urlMatcherFactory + * + * @description + * Defines whether URLs should match trailing slashes, or not (the default behavior). + * + * @param {boolean=} value `false` to match trailing slashes in URLs, otherwise `true`. + * @returns {boolean} the current value of strictMode + */ + this.strictMode = function(value) { + if (isDefined(value)) + isStrictMode = value; + return isStrictMode; + }; + + /** + * @ngdoc function + * @name ui.router.util.$urlMatcherFactory#defaultSquashPolicy + * @methodOf ui.router.util.$urlMatcherFactory + * + * @description + * Sets the default behavior when generating or matching URLs with default parameter values. + * + * @param {string} value A string that defines the default parameter URL squashing behavior. + * `nosquash`: When generating an href with a default parameter value, do not squash the parameter value from the URL + * `slash`: When generating an href with a default parameter value, squash (remove) the parameter value, and, if the + * parameter is surrounded by slashes, squash (remove) one slash from the URL + * any other string, e.g. "~": When generating an href with a default parameter value, squash (remove) + * the parameter value from the URL and replace it with this string. + */ + this.defaultSquashPolicy = function(value) { + if (!isDefined(value)) return defaultSquashPolicy; + if (value !== true && value !== false && !isString(value)) + throw new Error("Invalid squash policy: " + value + ". Valid policies: false, true, arbitrary-string"); + defaultSquashPolicy = value; + return value; + }; + + /** + * @ngdoc function + * @name ui.router.util.$urlMatcherFactory#compile + * @methodOf ui.router.util.$urlMatcherFactory + * + * @description + * Creates a {@link ui.router.util.type:UrlMatcher `UrlMatcher`} for the specified pattern. + * + * @param {string} pattern The URL pattern. + * @param {Object} config The config object hash. + * @returns {UrlMatcher} The UrlMatcher. + */ + this.compile = function (pattern, config) { + return new UrlMatcher(pattern, extend(getDefaultConfig(), config)); + }; + + /** + * @ngdoc function + * @name ui.router.util.$urlMatcherFactory#isMatcher + * @methodOf ui.router.util.$urlMatcherFactory + * + * @description + * Returns true if the specified object is a `UrlMatcher`, or false otherwise. + * + * @param {Object} object The object to perform the type check against. + * @returns {Boolean} Returns `true` if the object matches the `UrlMatcher` interface, by + * implementing all the same methods. + */ + this.isMatcher = function (o) { + if (!isObject(o)) return false; + var result = true; + + forEach(UrlMatcher.prototype, function(val, name) { + if (isFunction(val)) { + result = result && (isDefined(o[name]) && isFunction(o[name])); + } + }); + return result; + }; + + /** + * @ngdoc function + * @name ui.router.util.$urlMatcherFactory#type + * @methodOf ui.router.util.$urlMatcherFactory + * + * @description + * Registers a custom {@link ui.router.util.type:Type `Type`} object that can be used to + * generate URLs with typed parameters. + * + * @param {string} name The type name. + * @param {Object|Function} definition The type definition. See + * {@link ui.router.util.type:Type `Type`} for information on the values accepted. + * @param {Object|Function} definitionFn (optional) A function that is injected before the app + * runtime starts. The result of this function is merged into the existing `definition`. + * See {@link ui.router.util.type:Type `Type`} for information on the values accepted. + * + * @returns {Object} Returns `$urlMatcherFactoryProvider`. + * + * @example + * This is a simple example of a custom type that encodes and decodes items from an + * array, using the array index as the URL-encoded value: + * + *
      +   * var list = ['John', 'Paul', 'George', 'Ringo'];
      +   *
      +   * $urlMatcherFactoryProvider.type('listItem', {
      +   *   encode: function(item) {
      +   *     // Represent the list item in the URL using its corresponding index
      +   *     return list.indexOf(item);
      +   *   },
      +   *   decode: function(item) {
      +   *     // Look up the list item by index
      +   *     return list[parseInt(item, 10)];
      +   *   },
      +   *   is: function(item) {
      +   *     // Ensure the item is valid by checking to see that it appears
      +   *     // in the list
      +   *     return list.indexOf(item) > -1;
      +   *   }
      +   * });
      +   *
      +   * $stateProvider.state('list', {
      +   *   url: "/list/{item:listItem}",
      +   *   controller: function($scope, $stateParams) {
      +   *     console.log($stateParams.item);
      +   *   }
      +   * });
      +   *
      +   * // ...
      +   *
      +   * // Changes URL to '/list/3', logs "Ringo" to the console
      +   * $state.go('list', { item: "Ringo" });
      +   * 
      + * + * This is a more complex example of a type that relies on dependency injection to + * interact with services, and uses the parameter name from the URL to infer how to + * handle encoding and decoding parameter values: + * + *
      +   * // Defines a custom type that gets a value from a service,
      +   * // where each service gets different types of values from
      +   * // a backend API:
      +   * $urlMatcherFactoryProvider.type('dbObject', {}, function(Users, Posts) {
      +   *
      +   *   // Matches up services to URL parameter names
      +   *   var services = {
      +   *     user: Users,
      +   *     post: Posts
      +   *   };
      +   *
      +   *   return {
      +   *     encode: function(object) {
      +   *       // Represent the object in the URL using its unique ID
      +   *       return object.id;
      +   *     },
      +   *     decode: function(value, key) {
      +   *       // Look up the object by ID, using the parameter
      +   *       // name (key) to call the correct service
      +   *       return services[key].findById(value);
      +   *     },
      +   *     is: function(object, key) {
      +   *       // Check that object is a valid dbObject
      +   *       return angular.isObject(object) && object.id && services[key];
      +   *     }
      +   *     equals: function(a, b) {
      +   *       // Check the equality of decoded objects by comparing
      +   *       // their unique IDs
      +   *       return a.id === b.id;
      +   *     }
      +   *   };
      +   * });
      +   *
      +   * // In a config() block, you can then attach URLs with
      +   * // type-annotated parameters:
      +   * $stateProvider.state('users', {
      +   *   url: "/users",
      +   *   // ...
      +   * }).state('users.item', {
      +   *   url: "/{user:dbObject}",
      +   *   controller: function($scope, $stateParams) {
      +   *     // $stateParams.user will now be an object returned from
      +   *     // the Users service
      +   *   },
      +   *   // ...
      +   * });
      +   * 
      + */ + this.type = function (name, definition, definitionFn) { + if (!isDefined(definition)) return $types[name]; + if ($types.hasOwnProperty(name)) throw new Error("A type named '" + name + "' has already been defined."); + + $types[name] = new Type(extend({ name: name }, definition)); + if (definitionFn) { + typeQueue.push({ name: name, def: definitionFn }); + if (!enqueue) flushTypeQueue(); + } + return this; + }; + + // `flushTypeQueue()` waits until `$urlMatcherFactory` is injected before invoking the queued `definitionFn`s + function flushTypeQueue() { + while(typeQueue.length) { + var type = typeQueue.shift(); + if (type.pattern) throw new Error("You cannot override a type's .pattern at runtime."); + angular.extend($types[type.name], injector.invoke(type.def)); + } + } + + // Register default types. Store them in the prototype of $types. + forEach(defaultTypes, function(type, name) { $types[name] = new Type(extend({name: name}, type)); }); + $types = inherit($types, {}); + + /* No need to document $get, since it returns this */ + this.$get = ['$injector', function ($injector) { + injector = $injector; + enqueue = false; + flushTypeQueue(); + + forEach(defaultTypes, function(type, name) { + if (!$types[name]) $types[name] = new Type(type); + }); + return this; + }]; + + this.Param = function Param(id, type, config, location) { + var self = this; + config = unwrapShorthand(config); + type = getType(config, type, location); + var arrayMode = getArrayMode(); + type = arrayMode ? type.$asArray(arrayMode, location === "search") : type; + if (type.name === "string" && !arrayMode && location === "path" && config.value === undefined) + config.value = ""; // for 0.2.x; in 0.3.0+ do not automatically default to "" + var isOptional = config.value !== undefined; + var squash = getSquashPolicy(config, isOptional); + var replace = getReplace(config, arrayMode, isOptional, squash); + + function unwrapShorthand(config) { + var keys = isObject(config) ? objectKeys(config) : []; + var isShorthand = indexOf(keys, "value") === -1 && indexOf(keys, "type") === -1 && + indexOf(keys, "squash") === -1 && indexOf(keys, "array") === -1; + if (isShorthand) config = { value: config }; + config.$$fn = isInjectable(config.value) ? config.value : function () { return config.value; }; + return config; + } + + function getType(config, urlType, location) { + if (config.type && urlType) throw new Error("Param '"+id+"' has two type configurations."); + if (urlType) return urlType; + if (!config.type) return (location === "config" ? $types.any : $types.string); + return config.type instanceof Type ? config.type : new Type(config.type); + } + + // array config: param name (param[]) overrides default settings. explicit config overrides param name. + function getArrayMode() { + var arrayDefaults = { array: (location === "search" ? "auto" : false) }; + var arrayParamNomenclature = id.match(/\[\]$/) ? { array: true } : {}; + return extend(arrayDefaults, arrayParamNomenclature, config).array; + } + + /** + * returns false, true, or the squash value to indicate the "default parameter url squash policy". + */ + function getSquashPolicy(config, isOptional) { + var squash = config.squash; + if (!isOptional || squash === false) return false; + if (!isDefined(squash) || squash == null) return defaultSquashPolicy; + if (squash === true || isString(squash)) return squash; + throw new Error("Invalid squash policy: '" + squash + "'. Valid policies: false, true, or arbitrary string"); + } + + function getReplace(config, arrayMode, isOptional, squash) { + var replace, configuredKeys, defaultPolicy = [ + { from: "", to: (isOptional || arrayMode ? undefined : "") }, + { from: null, to: (isOptional || arrayMode ? undefined : "") } + ]; + replace = isArray(config.replace) ? config.replace : []; + if (isString(squash)) + replace.push({ from: squash, to: undefined }); + configuredKeys = map(replace, function(item) { return item.from; } ); + return filter(defaultPolicy, function(item) { return indexOf(configuredKeys, item.from) === -1; }).concat(replace); + } + + /** + * [Internal] Get the default value of a parameter, which may be an injectable function. + */ + function $$getDefaultValue() { + if (!injector) throw new Error("Injectable functions cannot be called at configuration time"); + return injector.invoke(config.$$fn); + } + + /** + * [Internal] Gets the decoded representation of a value if the value is defined, otherwise, returns the + * default value, which may be the result of an injectable function. + */ + function $value(value) { + function hasReplaceVal(val) { return function(obj) { return obj.from === val; }; } + function $replace(value) { + var replacement = map(filter(self.replace, hasReplaceVal(value)), function(obj) { return obj.to; }); + return replacement.length ? replacement[0] : value; + } + value = $replace(value); + return isDefined(value) ? self.type.decode(value) : $$getDefaultValue(); + } + + function toString() { return "{Param:" + id + " " + type + " squash: '" + squash + "' optional: " + isOptional + "}"; } + + extend(this, { + id: id, + type: type, + location: location, + array: arrayMode, + squash: squash, + replace: replace, + isOptional: isOptional, + value: $value, + dynamic: undefined, + config: config, + toString: toString + }); + }; + + function ParamSet(params) { + extend(this, params || {}); + } + + ParamSet.prototype = { + $$new: function() { + return inherit(this, extend(new ParamSet(), { $$parent: this})); + }, + $$keys: function () { + var keys = [], chain = [], parent = this, + ignore = objectKeys(ParamSet.prototype); + while (parent) { chain.push(parent); parent = parent.$$parent; } + chain.reverse(); + forEach(chain, function(paramset) { + forEach(objectKeys(paramset), function(key) { + if (indexOf(keys, key) === -1 && indexOf(ignore, key) === -1) keys.push(key); + }); + }); + return keys; + }, + $$values: function(paramValues) { + var values = {}, self = this; + forEach(self.$$keys(), function(key) { + values[key] = self[key].value(paramValues && paramValues[key]); + }); + return values; + }, + $$equals: function(paramValues1, paramValues2) { + var equal = true, self = this; + forEach(self.$$keys(), function(key) { + var left = paramValues1 && paramValues1[key], right = paramValues2 && paramValues2[key]; + if (!self[key].type.equals(left, right)) equal = false; + }); + return equal; + }, + $$validates: function $$validate(paramValues) { + var result = true, isOptional, val, param, self = this; + + forEach(this.$$keys(), function(key) { + param = self[key]; + val = paramValues[key]; + isOptional = !val && param.isOptional; + result = result && (isOptional || !!param.type.is(val)); + }); + return result; + }, + $$parent: undefined + }; + + this.ParamSet = ParamSet; +} + +// Register as a provider so it's available to other providers +angular.module('ui.router.util').provider('$urlMatcherFactory', $UrlMatcherFactory); +angular.module('ui.router.util').run(['$urlMatcherFactory', function($urlMatcherFactory) { }]); + +/** + * @ngdoc object + * @name ui.router.router.$urlRouterProvider + * + * @requires ui.router.util.$urlMatcherFactoryProvider + * @requires $locationProvider + * + * @description + * `$urlRouterProvider` has the responsibility of watching `$location`. + * When `$location` changes it runs through a list of rules one by one until a + * match is found. `$urlRouterProvider` is used behind the scenes anytime you specify + * a url in a state configuration. All urls are compiled into a UrlMatcher object. + * + * There are several methods on `$urlRouterProvider` that make it useful to use directly + * in your module config. + */ +$UrlRouterProvider.$inject = ['$locationProvider', '$urlMatcherFactoryProvider']; +function $UrlRouterProvider( $locationProvider, $urlMatcherFactory) { + var rules = [], otherwise = null, interceptDeferred = false, listener; + + // Returns a string that is a prefix of all strings matching the RegExp + function regExpPrefix(re) { + var prefix = /^\^((?:\\[^a-zA-Z0-9]|[^\\\[\]\^$*+?.()|{}]+)*)/.exec(re.source); + return (prefix != null) ? prefix[1].replace(/\\(.)/g, "$1") : ''; + } + + // Interpolates matched values into a String.replace()-style pattern + function interpolate(pattern, match) { + return pattern.replace(/\$(\$|\d{1,2})/, function (m, what) { + return match[what === '$' ? 0 : Number(what)]; + }); + } + + /** + * @ngdoc function + * @name ui.router.router.$urlRouterProvider#rule + * @methodOf ui.router.router.$urlRouterProvider + * + * @description + * Defines rules that are used by `$urlRouterProvider` to find matches for + * specific URLs. + * + * @example + *
      +   * var app = angular.module('app', ['ui.router.router']);
      +   *
      +   * app.config(function ($urlRouterProvider) {
      +   *   // Here's an example of how you might allow case insensitive urls
      +   *   $urlRouterProvider.rule(function ($injector, $location) {
      +   *     var path = $location.path(),
      +   *         normalized = path.toLowerCase();
      +   *
      +   *     if (path !== normalized) {
      +   *       return normalized;
      +   *     }
      +   *   });
      +   * });
      +   * 
      + * + * @param {object} rule Handler function that takes `$injector` and `$location` + * services as arguments. You can use them to return a valid path as a string. + * + * @return {object} `$urlRouterProvider` - `$urlRouterProvider` instance + */ + this.rule = function (rule) { + if (!isFunction(rule)) throw new Error("'rule' must be a function"); + rules.push(rule); + return this; + }; + + /** + * @ngdoc object + * @name ui.router.router.$urlRouterProvider#otherwise + * @methodOf ui.router.router.$urlRouterProvider + * + * @description + * Defines a path that is used when an invalid route is requested. + * + * @example + *
      +   * var app = angular.module('app', ['ui.router.router']);
      +   *
      +   * app.config(function ($urlRouterProvider) {
      +   *   // if the path doesn't match any of the urls you configured
      +   *   // otherwise will take care of routing the user to the
      +   *   // specified url
      +   *   $urlRouterProvider.otherwise('/index');
      +   *
      +   *   // Example of using function rule as param
      +   *   $urlRouterProvider.otherwise(function ($injector, $location) {
      +   *     return '/a/valid/url';
      +   *   });
      +   * });
      +   * 
      + * + * @param {string|object} rule The url path you want to redirect to or a function + * rule that returns the url path. The function version is passed two params: + * `$injector` and `$location` services, and must return a url string. + * + * @return {object} `$urlRouterProvider` - `$urlRouterProvider` instance + */ + this.otherwise = function (rule) { + if (isString(rule)) { + var redirect = rule; + rule = function () { return redirect; }; + } + else if (!isFunction(rule)) throw new Error("'rule' must be a function"); + otherwise = rule; + return this; + }; + + + function handleIfMatch($injector, handler, match) { + if (!match) return false; + var result = $injector.invoke(handler, handler, { $match: match }); + return isDefined(result) ? result : true; + } + + /** + * @ngdoc function + * @name ui.router.router.$urlRouterProvider#when + * @methodOf ui.router.router.$urlRouterProvider + * + * @description + * Registers a handler for a given url matching. if handle is a string, it is + * treated as a redirect, and is interpolated according to the syntax of match + * (i.e. like `String.replace()` for `RegExp`, or like a `UrlMatcher` pattern otherwise). + * + * If the handler is a function, it is injectable. It gets invoked if `$location` + * matches. You have the option of inject the match object as `$match`. + * + * The handler can return + * + * - **falsy** to indicate that the rule didn't match after all, then `$urlRouter` + * will continue trying to find another one that matches. + * - **string** which is treated as a redirect and passed to `$location.url()` + * - **void** or any **truthy** value tells `$urlRouter` that the url was handled. + * + * @example + *
      +   * var app = angular.module('app', ['ui.router.router']);
      +   *
      +   * app.config(function ($urlRouterProvider) {
      +   *   $urlRouterProvider.when($state.url, function ($match, $stateParams) {
      +   *     if ($state.$current.navigable !== state ||
      +   *         !equalForKeys($match, $stateParams) {
      +   *      $state.transitionTo(state, $match, false);
      +   *     }
      +   *   });
      +   * });
      +   * 
      + * + * @param {string|object} what The incoming path that you want to redirect. + * @param {string|object} handler The path you want to redirect your user to. + */ + this.when = function (what, handler) { + var redirect, handlerIsString = isString(handler); + if (isString(what)) what = $urlMatcherFactory.compile(what); + + if (!handlerIsString && !isFunction(handler) && !isArray(handler)) + throw new Error("invalid 'handler' in when()"); + + var strategies = { + matcher: function (what, handler) { + if (handlerIsString) { + redirect = $urlMatcherFactory.compile(handler); + handler = ['$match', function ($match) { return redirect.format($match); }]; + } + return extend(function ($injector, $location) { + return handleIfMatch($injector, handler, what.exec($location.path(), $location.search())); + }, { + prefix: isString(what.prefix) ? what.prefix : '' + }); + }, + regex: function (what, handler) { + if (what.global || what.sticky) throw new Error("when() RegExp must not be global or sticky"); + + if (handlerIsString) { + redirect = handler; + handler = ['$match', function ($match) { return interpolate(redirect, $match); }]; + } + return extend(function ($injector, $location) { + return handleIfMatch($injector, handler, what.exec($location.path())); + }, { + prefix: regExpPrefix(what) + }); + } + }; + + var check = { matcher: $urlMatcherFactory.isMatcher(what), regex: what instanceof RegExp }; + + for (var n in check) { + if (check[n]) return this.rule(strategies[n](what, handler)); + } + + throw new Error("invalid 'what' in when()"); + }; + + /** + * @ngdoc function + * @name ui.router.router.$urlRouterProvider#deferIntercept + * @methodOf ui.router.router.$urlRouterProvider + * + * @description + * Disables (or enables) deferring location change interception. + * + * If you wish to customize the behavior of syncing the URL (for example, if you wish to + * defer a transition but maintain the current URL), call this method at configuration time. + * Then, at run time, call `$urlRouter.listen()` after you have configured your own + * `$locationChangeSuccess` event handler. + * + * @example + *
      +   * var app = angular.module('app', ['ui.router.router']);
      +   *
      +   * app.config(function ($urlRouterProvider) {
      +   *
      +   *   // Prevent $urlRouter from automatically intercepting URL changes;
      +   *   // this allows you to configure custom behavior in between
      +   *   // location changes and route synchronization:
      +   *   $urlRouterProvider.deferIntercept();
      +   *
      +   * }).run(function ($rootScope, $urlRouter, UserService) {
      +   *
      +   *   $rootScope.$on('$locationChangeSuccess', function(e) {
      +   *     // UserService is an example service for managing user state
      +   *     if (UserService.isLoggedIn()) return;
      +   *
      +   *     // Prevent $urlRouter's default handler from firing
      +   *     e.preventDefault();
      +   *
      +   *     UserService.handleLogin().then(function() {
      +   *       // Once the user has logged in, sync the current URL
      +   *       // to the router:
      +   *       $urlRouter.sync();
      +   *     });
      +   *   });
      +   *
      +   *   // Configures $urlRouter's listener *after* your custom listener
      +   *   $urlRouter.listen();
      +   * });
      +   * 
      + * + * @param {boolean} defer Indicates whether to defer location change interception. Passing + no parameter is equivalent to `true`. + */ + this.deferIntercept = function (defer) { + if (defer === undefined) defer = true; + interceptDeferred = defer; + }; + + /** + * @ngdoc object + * @name ui.router.router.$urlRouter + * + * @requires $location + * @requires $rootScope + * @requires $injector + * @requires $browser + * + * @description + * + */ + this.$get = $get; + $get.$inject = ['$location', '$rootScope', '$injector', '$browser']; + function $get( $location, $rootScope, $injector, $browser) { + + var baseHref = $browser.baseHref(), location = $location.url(), lastPushedUrl; + + function appendBasePath(url, isHtml5, absolute) { + if (baseHref === '/') return url; + if (isHtml5) return baseHref.slice(0, -1) + url; + if (absolute) return baseHref.slice(1) + url; + return url; + } + + // TODO: Optimize groups of rules with non-empty prefix into some sort of decision tree + function update(evt) { + if (evt && evt.defaultPrevented) return; + var ignoreUpdate = lastPushedUrl && $location.url() === lastPushedUrl; + lastPushedUrl = undefined; + if (ignoreUpdate) return true; + + function check(rule) { + var handled = rule($injector, $location); + + if (!handled) return false; + if (isString(handled)) $location.replace().url(handled); + return true; + } + var n = rules.length, i; + + for (i = 0; i < n; i++) { + if (check(rules[i])) return; + } + // always check otherwise last to allow dynamic updates to the set of rules + if (otherwise) check(otherwise); + } + + function listen() { + listener = listener || $rootScope.$on('$locationChangeSuccess', update); + return listener; + } + + if (!interceptDeferred) listen(); + + return { + /** + * @ngdoc function + * @name ui.router.router.$urlRouter#sync + * @methodOf ui.router.router.$urlRouter + * + * @description + * Triggers an update; the same update that happens when the address bar url changes, aka `$locationChangeSuccess`. + * This method is useful when you need to use `preventDefault()` on the `$locationChangeSuccess` event, + * perform some custom logic (route protection, auth, config, redirection, etc) and then finally proceed + * with the transition by calling `$urlRouter.sync()`. + * + * @example + *
      +       * angular.module('app', ['ui.router'])
      +       *   .run(function($rootScope, $urlRouter) {
      +       *     $rootScope.$on('$locationChangeSuccess', function(evt) {
      +       *       // Halt state change from even starting
      +       *       evt.preventDefault();
      +       *       // Perform custom logic
      +       *       var meetsRequirement = ...
      +       *       // Continue with the update and state transition if logic allows
      +       *       if (meetsRequirement) $urlRouter.sync();
      +       *     });
      +       * });
      +       * 
      + */ + sync: function() { + update(); + }, + + listen: function() { + return listen(); + }, + + update: function(read) { + if (read) { + location = $location.url(); + return; + } + if ($location.url() === location) return; + + $location.url(location); + $location.replace(); + }, + + push: function(urlMatcher, params, options) { + $location.url(urlMatcher.format(params || {})); + lastPushedUrl = options && options.$$avoidResync ? $location.url() : undefined; + if (options && options.replace) $location.replace(); + }, + + /** + * @ngdoc function + * @name ui.router.router.$urlRouter#href + * @methodOf ui.router.router.$urlRouter + * + * @description + * A URL generation method that returns the compiled URL for a given + * {@link ui.router.util.type:UrlMatcher `UrlMatcher`}, populated with the provided parameters. + * + * @example + *
      +       * $bob = $urlRouter.href(new UrlMatcher("/about/:person"), {
      +       *   person: "bob"
      +       * });
      +       * // $bob == "/about/bob";
      +       * 
      + * + * @param {UrlMatcher} urlMatcher The `UrlMatcher` object which is used as the template of the URL to generate. + * @param {object=} params An object of parameter values to fill the matcher's required parameters. + * @param {object=} options Options object. The options are: + * + * - **`absolute`** - {boolean=false}, If true will generate an absolute url, e.g. "http://www.example.com/fullurl". + * + * @returns {string} Returns the fully compiled URL, or `null` if `params` fail validation against `urlMatcher` + */ + href: function(urlMatcher, params, options) { + if (!urlMatcher.validates(params)) return null; + + var isHtml5 = $locationProvider.html5Mode(); + if (angular.isObject(isHtml5)) { + isHtml5 = isHtml5.enabled; + } + + var url = urlMatcher.format(params); + options = options || {}; + + if (!isHtml5 && url !== null) { + url = "#" + $locationProvider.hashPrefix() + url; + } + url = appendBasePath(url, isHtml5, options.absolute); + + if (!options.absolute || !url) { + return url; + } + + var slash = (!isHtml5 && url ? '/' : ''), port = $location.port(); + port = (port === 80 || port === 443 ? '' : ':' + port); + + return [$location.protocol(), '://', $location.host(), port, slash, url].join(''); + } + }; + } +} + +angular.module('ui.router.router').provider('$urlRouter', $UrlRouterProvider); + +/** + * @ngdoc object + * @name ui.router.state.$stateProvider + * + * @requires ui.router.router.$urlRouterProvider + * @requires ui.router.util.$urlMatcherFactoryProvider + * + * @description + * The new `$stateProvider` works similar to Angular's v1 router, but it focuses purely + * on state. + * + * A state corresponds to a "place" in the application in terms of the overall UI and + * navigation. A state describes (via the controller / template / view properties) what + * the UI looks like and does at that place. + * + * States often have things in common, and the primary way of factoring out these + * commonalities in this model is via the state hierarchy, i.e. parent/child states aka + * nested states. + * + * The `$stateProvider` provides interfaces to declare these states for your app. + */ +$StateProvider.$inject = ['$urlRouterProvider', '$urlMatcherFactoryProvider']; +function $StateProvider( $urlRouterProvider, $urlMatcherFactory) { + + var root, states = {}, $state, queue = {}, abstractKey = 'abstract'; + + // Builds state properties from definition passed to registerState() + var stateBuilder = { + + // Derive parent state from a hierarchical name only if 'parent' is not explicitly defined. + // state.children = []; + // if (parent) parent.children.push(state); + parent: function(state) { + if (isDefined(state.parent) && state.parent) return findState(state.parent); + // regex matches any valid composite state name + // would match "contact.list" but not "contacts" + var compositeName = /^(.+)\.[^.]+$/.exec(state.name); + return compositeName ? findState(compositeName[1]) : root; + }, + + // inherit 'data' from parent and override by own values (if any) + data: function(state) { + if (state.parent && state.parent.data) { + state.data = state.self.data = extend({}, state.parent.data, state.data); + } + return state.data; + }, + + // Build a URLMatcher if necessary, either via a relative or absolute URL + url: function(state) { + var url = state.url, config = { params: state.params || {} }; + + if (isString(url)) { + if (url.charAt(0) == '^') return $urlMatcherFactory.compile(url.substring(1), config); + return (state.parent.navigable || root).url.concat(url, config); + } + + if (!url || $urlMatcherFactory.isMatcher(url)) return url; + throw new Error("Invalid url '" + url + "' in state '" + state + "'"); + }, + + // Keep track of the closest ancestor state that has a URL (i.e. is navigable) + navigable: function(state) { + return state.url ? state : (state.parent ? state.parent.navigable : null); + }, + + // Own parameters for this state. state.url.params is already built at this point. Create and add non-url params + ownParams: function(state) { + var params = state.url && state.url.params || new $$UMFP.ParamSet(); + forEach(state.params || {}, function(config, id) { + if (!params[id]) params[id] = new $$UMFP.Param(id, null, config, "config"); + }); + return params; + }, + + // Derive parameters for this state and ensure they're a super-set of parent's parameters + params: function(state) { + return state.parent && state.parent.params ? extend(state.parent.params.$$new(), state.ownParams) : new $$UMFP.ParamSet(); + }, + + // If there is no explicit multi-view configuration, make one up so we don't have + // to handle both cases in the view directive later. Note that having an explicit + // 'views' property will mean the default unnamed view properties are ignored. This + // is also a good time to resolve view names to absolute names, so everything is a + // straight lookup at link time. + views: function(state) { + var views = {}; + + forEach(isDefined(state.views) ? state.views : { '': state }, function (view, name) { + if (name.indexOf('@') < 0) name += '@' + state.parent.name; + views[name] = view; + }); + return views; + }, + + // Keep a full path from the root down to this state as this is needed for state activation. + path: function(state) { + return state.parent ? state.parent.path.concat(state) : []; // exclude root from path + }, + + // Speed up $state.contains() as it's used a lot + includes: function(state) { + var includes = state.parent ? extend({}, state.parent.includes) : {}; + includes[state.name] = true; + return includes; + }, + + $delegates: {} + }; + + function isRelative(stateName) { + return stateName.indexOf(".") === 0 || stateName.indexOf("^") === 0; + } + + function findState(stateOrName, base) { + if (!stateOrName) return undefined; + + var isStr = isString(stateOrName), + name = isStr ? stateOrName : stateOrName.name, + path = isRelative(name); + + if (path) { + if (!base) throw new Error("No reference point given for path '" + name + "'"); + base = findState(base); + + var rel = name.split("."), i = 0, pathLength = rel.length, current = base; + + for (; i < pathLength; i++) { + if (rel[i] === "" && i === 0) { + current = base; + continue; + } + if (rel[i] === "^") { + if (!current.parent) throw new Error("Path '" + name + "' not valid for state '" + base.name + "'"); + current = current.parent; + continue; + } + break; + } + rel = rel.slice(i).join("."); + name = current.name + (current.name && rel ? "." : "") + rel; + } + var state = states[name]; + + if (state && (isStr || (!isStr && (state === stateOrName || state.self === stateOrName)))) { + return state; + } + return undefined; + } + + function queueState(parentName, state) { + if (!queue[parentName]) { + queue[parentName] = []; + } + queue[parentName].push(state); + } + + function flushQueuedChildren(parentName) { + var queued = queue[parentName] || []; + while(queued.length) { + registerState(queued.shift()); + } + } + + function registerState(state) { + // Wrap a new object around the state so we can store our private details easily. + state = inherit(state, { + self: state, + resolve: state.resolve || {}, + toString: function() { return this.name; } + }); + + var name = state.name; + if (!isString(name) || name.indexOf('@') >= 0) throw new Error("State must have a valid name"); + if (states.hasOwnProperty(name)) throw new Error("State '" + name + "'' is already defined"); + + // Get parent name + var parentName = (name.indexOf('.') !== -1) ? name.substring(0, name.lastIndexOf('.')) + : (isString(state.parent)) ? state.parent + : (isObject(state.parent) && isString(state.parent.name)) ? state.parent.name + : ''; + + // If parent is not registered yet, add state to queue and register later + if (parentName && !states[parentName]) { + return queueState(parentName, state.self); + } + + for (var key in stateBuilder) { + if (isFunction(stateBuilder[key])) state[key] = stateBuilder[key](state, stateBuilder.$delegates[key]); + } + states[name] = state; + + // Register the state in the global state list and with $urlRouter if necessary. + if (!state[abstractKey] && state.url) { + $urlRouterProvider.when(state.url, ['$match', '$stateParams', function ($match, $stateParams) { + if ($state.$current.navigable != state || !equalForKeys($match, $stateParams)) { + $state.transitionTo(state, $match, { inherit: true, location: false }); + } + }]); + } + + // Register any queued children + flushQueuedChildren(name); + + return state; + } + + // Checks text to see if it looks like a glob. + function isGlob (text) { + return text.indexOf('*') > -1; + } + + // Returns true if glob matches current $state name. + function doesStateMatchGlob (glob) { + var globSegments = glob.split('.'), + segments = $state.$current.name.split('.'); + + //match greedy starts + if (globSegments[0] === '**') { + segments = segments.slice(indexOf(segments, globSegments[1])); + segments.unshift('**'); + } + //match greedy ends + if (globSegments[globSegments.length - 1] === '**') { + segments.splice(indexOf(segments, globSegments[globSegments.length - 2]) + 1, Number.MAX_VALUE); + segments.push('**'); + } + + if (globSegments.length != segments.length) { + return false; + } + + //match single stars + for (var i = 0, l = globSegments.length; i < l; i++) { + if (globSegments[i] === '*') { + segments[i] = '*'; + } + } + + return segments.join('') === globSegments.join(''); + } + + + // Implicit root state that is always active + root = registerState({ + name: '', + url: '^', + views: null, + 'abstract': true + }); + root.navigable = null; + + + /** + * @ngdoc function + * @name ui.router.state.$stateProvider#decorator + * @methodOf ui.router.state.$stateProvider + * + * @description + * Allows you to extend (carefully) or override (at your own peril) the + * `stateBuilder` object used internally by `$stateProvider`. This can be used + * to add custom functionality to ui-router, for example inferring templateUrl + * based on the state name. + * + * When passing only a name, it returns the current (original or decorated) builder + * function that matches `name`. + * + * The builder functions that can be decorated are listed below. Though not all + * necessarily have a good use case for decoration, that is up to you to decide. + * + * In addition, users can attach custom decorators, which will generate new + * properties within the state's internal definition. There is currently no clear + * use-case for this beyond accessing internal states (i.e. $state.$current), + * however, expect this to become increasingly relevant as we introduce additional + * meta-programming features. + * + * **Warning**: Decorators should not be interdependent because the order of + * execution of the builder functions in non-deterministic. Builder functions + * should only be dependent on the state definition object and super function. + * + * + * Existing builder functions and current return values: + * + * - **parent** `{object}` - returns the parent state object. + * - **data** `{object}` - returns state data, including any inherited data that is not + * overridden by own values (if any). + * - **url** `{object}` - returns a {@link ui.router.util.type:UrlMatcher UrlMatcher} + * or `null`. + * - **navigable** `{object}` - returns closest ancestor state that has a URL (aka is + * navigable). + * - **params** `{object}` - returns an array of state params that are ensured to + * be a super-set of parent's params. + * - **views** `{object}` - returns a views object where each key is an absolute view + * name (i.e. "viewName@stateName") and each value is the config object + * (template, controller) for the view. Even when you don't use the views object + * explicitly on a state config, one is still created for you internally. + * So by decorating this builder function you have access to decorating template + * and controller properties. + * - **ownParams** `{object}` - returns an array of params that belong to the state, + * not including any params defined by ancestor states. + * - **path** `{string}` - returns the full path from the root down to this state. + * Needed for state activation. + * - **includes** `{object}` - returns an object that includes every state that + * would pass a `$state.includes()` test. + * + * @example + *
      +   * // Override the internal 'views' builder with a function that takes the state
      +   * // definition, and a reference to the internal function being overridden:
      +   * $stateProvider.decorator('views', function (state, parent) {
      +   *   var result = {},
      +   *       views = parent(state);
      +   *
      +   *   angular.forEach(views, function (config, name) {
      +   *     var autoName = (state.name + '.' + name).replace('.', '/');
      +   *     config.templateUrl = config.templateUrl || '/partials/' + autoName + '.html';
      +   *     result[name] = config;
      +   *   });
      +   *   return result;
      +   * });
      +   *
      +   * $stateProvider.state('home', {
      +   *   views: {
      +   *     'contact.list': { controller: 'ListController' },
      +   *     'contact.item': { controller: 'ItemController' }
      +   *   }
      +   * });
      +   *
      +   * // ...
      +   *
      +   * $state.go('home');
      +   * // Auto-populates list and item views with /partials/home/contact/list.html,
      +   * // and /partials/home/contact/item.html, respectively.
      +   * 
      + * + * @param {string} name The name of the builder function to decorate. + * @param {object} func A function that is responsible for decorating the original + * builder function. The function receives two parameters: + * + * - `{object}` - state - The state config object. + * - `{object}` - super - The original builder function. + * + * @return {object} $stateProvider - $stateProvider instance + */ + this.decorator = decorator; + function decorator(name, func) { + /*jshint validthis: true */ + if (isString(name) && !isDefined(func)) { + return stateBuilder[name]; + } + if (!isFunction(func) || !isString(name)) { + return this; + } + if (stateBuilder[name] && !stateBuilder.$delegates[name]) { + stateBuilder.$delegates[name] = stateBuilder[name]; + } + stateBuilder[name] = func; + return this; + } + + /** + * @ngdoc function + * @name ui.router.state.$stateProvider#state + * @methodOf ui.router.state.$stateProvider + * + * @description + * Registers a state configuration under a given state name. The stateConfig object + * has the following acceptable properties. + * + * @param {string} name A unique state name, e.g. "home", "about", "contacts". + * To create a parent/child state use a dot, e.g. "about.sales", "home.newest". + * @param {object} stateConfig State configuration object. + * @param {string|function=} stateConfig.template + * + * html template as a string or a function that returns + * an html template as a string which should be used by the uiView directives. This property + * takes precedence over templateUrl. + * + * If `template` is a function, it will be called with the following parameters: + * + * - {array.<object>} - state parameters extracted from the current $location.path() by + * applying the current state + * + *
      template:
      +   *   "

      inline template definition

      " + + * "
      "
      + *
      template: function(params) {
      +   *       return "

      generated template

      "; }
      + *
      + * + * @param {string|function=} stateConfig.templateUrl + * + * + * path or function that returns a path to an html + * template that should be used by uiView. + * + * If `templateUrl` is a function, it will be called with the following parameters: + * + * - {array.<object>} - state parameters extracted from the current $location.path() by + * applying the current state + * + *
      templateUrl: "home.html"
      + *
      templateUrl: function(params) {
      +   *     return myTemplates[params.pageId]; }
      + * + * @param {function=} stateConfig.templateProvider + * + * Provider function that returns HTML content string. + *
       templateProvider:
      +   *       function(MyTemplateService, params) {
      +   *         return MyTemplateService.getTemplate(params.pageId);
      +   *       }
      + * + * @param {string|function=} stateConfig.controller + * + * + * Controller fn that should be associated with newly + * related scope or the name of a registered controller if passed as a string. + * Optionally, the ControllerAs may be declared here. + *
      controller: "MyRegisteredController"
      + *
      controller:
      +   *     "MyRegisteredController as fooCtrl"}
      + *
      controller: function($scope, MyService) {
      +   *     $scope.data = MyService.getData(); }
      + * + * @param {function=} stateConfig.controllerProvider + * + * + * Injectable provider function that returns the actual controller or string. + *
      controllerProvider:
      +   *   function(MyResolveData) {
      +   *     if (MyResolveData.foo)
      +   *       return "FooCtrl"
      +   *     else if (MyResolveData.bar)
      +   *       return "BarCtrl";
      +   *     else return function($scope) {
      +   *       $scope.baz = "Qux";
      +   *     }
      +   *   }
      + * + * @param {string=} stateConfig.controllerAs + * + * + * A controller alias name. If present the controller will be + * published to scope under the controllerAs name. + *
      controllerAs: "myCtrl"
      + * + * @param {object=} stateConfig.resolve + * + * + * An optional map<string, function> of dependencies which + * should be injected into the controller. If any of these dependencies are promises, + * the router will wait for them all to be resolved before the controller is instantiated. + * If all the promises are resolved successfully, the $stateChangeSuccess event is fired + * and the values of the resolved promises are injected into any controllers that reference them. + * If any of the promises are rejected the $stateChangeError event is fired. + * + * The map object is: + * + * - key - {string}: name of dependency to be injected into controller + * - factory - {string|function}: If string then it is alias for service. Otherwise if function, + * it is injected and return value it treated as dependency. If result is a promise, it is + * resolved before its value is injected into controller. + * + *
      resolve: {
      +   *     myResolve1:
      +   *       function($http, $stateParams) {
      +   *         return $http.get("/api/foos/"+stateParams.fooID);
      +   *       }
      +   *     }
      + * + * @param {string=} stateConfig.url + * + * + * A url fragment with optional parameters. When a state is navigated or + * transitioned to, the `$stateParams` service will be populated with any + * parameters that were passed. + * + * examples: + *
      url: "/home"
      +   * url: "/users/:userid"
      +   * url: "/books/{bookid:[a-zA-Z_-]}"
      +   * url: "/books/{categoryid:int}"
      +   * url: "/books/{publishername:string}/{categoryid:int}"
      +   * url: "/messages?before&after"
      +   * url: "/messages?{before:date}&{after:date}"
      + * url: "/messages/:mailboxid?{before:date}&{after:date}" + * + * @param {object=} stateConfig.views + * + * an optional map<string, object> which defined multiple views, or targets views + * manually/explicitly. + * + * Examples: + * + * Targets three named `ui-view`s in the parent state's template + *
      views: {
      +   *     header: {
      +   *       controller: "headerCtrl",
      +   *       templateUrl: "header.html"
      +   *     }, body: {
      +   *       controller: "bodyCtrl",
      +   *       templateUrl: "body.html"
      +   *     }, footer: {
      +   *       controller: "footCtrl",
      +   *       templateUrl: "footer.html"
      +   *     }
      +   *   }
      + * + * Targets named `ui-view="header"` from grandparent state 'top''s template, and named `ui-view="body" from parent state's template. + *
      views: {
      +   *     'header@top': {
      +   *       controller: "msgHeaderCtrl",
      +   *       templateUrl: "msgHeader.html"
      +   *     }, 'body': {
      +   *       controller: "messagesCtrl",
      +   *       templateUrl: "messages.html"
      +   *     }
      +   *   }
      + * + * @param {boolean=} [stateConfig.abstract=false] + * + * An abstract state will never be directly activated, + * but can provide inherited properties to its common children states. + *
      abstract: true
      + * + * @param {function=} stateConfig.onEnter + * + * + * Callback function for when a state is entered. Good way + * to trigger an action or dispatch an event, such as opening a dialog. + * If minifying your scripts, make sure to explictly annotate this function, + * because it won't be automatically annotated by your build tools. + * + *
      onEnter: function(MyService, $stateParams) {
      +   *     MyService.foo($stateParams.myParam);
      +   * }
      + * + * @param {function=} stateConfig.onExit + * + * + * Callback function for when a state is exited. Good way to + * trigger an action or dispatch an event, such as opening a dialog. + * If minifying your scripts, make sure to explictly annotate this function, + * because it won't be automatically annotated by your build tools. + * + *
      onExit: function(MyService, $stateParams) {
      +   *     MyService.cleanup($stateParams.myParam);
      +   * }
      + * + * @param {boolean=} [stateConfig.reloadOnSearch=true] + * + * + * If `false`, will not retrigger the same state + * just because a search/query parameter has changed (via $location.search() or $location.hash()). + * Useful for when you'd like to modify $location.search() without triggering a reload. + *
      reloadOnSearch: false
      + * + * @param {object=} stateConfig.data + * + * + * Arbitrary data object, useful for custom configuration. The parent state's `data` is + * prototypally inherited. In other words, adding a data property to a state adds it to + * the entire subtree via prototypal inheritance. + * + *
      data: {
      +   *     requiredRole: 'foo'
      +   * } 
      + * + * @param {object=} stateConfig.params + * + * + * A map which optionally configures parameters declared in the `url`, or + * defines additional non-url parameters. For each parameter being + * configured, add a configuration object keyed to the name of the parameter. + * + * Each parameter configuration object may contain the following properties: + * + * - ** value ** - {object|function=}: specifies the default value for this + * parameter. This implicitly sets this parameter as optional. + * + * When UI-Router routes to a state and no value is + * specified for this parameter in the URL or transition, the + * default value will be used instead. If `value` is a function, + * it will be injected and invoked, and the return value used. + * + * *Note*: `undefined` is treated as "no default value" while `null` + * is treated as "the default value is `null`". + * + * *Shorthand*: If you only need to configure the default value of the + * parameter, you may use a shorthand syntax. In the **`params`** + * map, instead mapping the param name to a full parameter configuration + * object, simply set map it to the default parameter value, e.g.: + * + *
      // define a parameter's default value
      +   * params: {
      +   *     param1: { value: "defaultValue" }
      +   * }
      +   * // shorthand default values
      +   * params: {
      +   *     param1: "defaultValue",
      +   *     param2: "param2Default"
      +   * }
      + * + * - ** array ** - {boolean=}: *(default: false)* If true, the param value will be + * treated as an array of values. If you specified a Type, the value will be + * treated as an array of the specified Type. Note: query parameter values + * default to a special `"auto"` mode. + * + * For query parameters in `"auto"` mode, if multiple values for a single parameter + * are present in the URL (e.g.: `/foo?bar=1&bar=2&bar=3`) then the values + * are mapped to an array (e.g.: `{ foo: [ '1', '2', '3' ] }`). However, if + * only one value is present (e.g.: `/foo?bar=1`) then the value is treated as single + * value (e.g.: `{ foo: '1' }`). + * + *
      params: {
      +   *     param1: { array: true }
      +   * }
      + * + * - ** squash ** - {bool|string=}: `squash` configures how a default parameter value is represented in the URL when + * the current parameter value is the same as the default value. If `squash` is not set, it uses the + * configured default squash policy. + * (See {@link ui.router.util.$urlMatcherFactory#methods_defaultSquashPolicy `defaultSquashPolicy()`}) + * + * There are three squash settings: + * + * - false: The parameter's default value is not squashed. It is encoded and included in the URL + * - true: The parameter's default value is omitted from the URL. If the parameter is preceeded and followed + * by slashes in the state's `url` declaration, then one of those slashes are omitted. + * This can allow for cleaner looking URLs. + * - `""`: The parameter's default value is replaced with an arbitrary placeholder of your choice. + * + *
      params: {
      +   *     param1: {
      +   *       value: "defaultId",
      +   *       squash: true
      +   * } }
      +   * // squash "defaultValue" to "~"
      +   * params: {
      +   *     param1: {
      +   *       value: "defaultValue",
      +   *       squash: "~"
      +   * } }
      +   * 
      + * + * + * @example + *
      +   * // Some state name examples
      +   *
      +   * // stateName can be a single top-level name (must be unique).
      +   * $stateProvider.state("home", {});
      +   *
      +   * // Or it can be a nested state name. This state is a child of the
      +   * // above "home" state.
      +   * $stateProvider.state("home.newest", {});
      +   *
      +   * // Nest states as deeply as needed.
      +   * $stateProvider.state("home.newest.abc.xyz.inception", {});
      +   *
      +   * // state() returns $stateProvider, so you can chain state declarations.
      +   * $stateProvider
      +   *   .state("home", {})
      +   *   .state("about", {})
      +   *   .state("contacts", {});
      +   * 
      + * + */ + this.state = state; + function state(name, definition) { + /*jshint validthis: true */ + if (isObject(name)) definition = name; + else definition.name = name; + registerState(definition); + return this; + } + + /** + * @ngdoc object + * @name ui.router.state.$state + * + * @requires $rootScope + * @requires $q + * @requires ui.router.state.$view + * @requires $injector + * @requires ui.router.util.$resolve + * @requires ui.router.state.$stateParams + * @requires ui.router.router.$urlRouter + * + * @property {object} params A param object, e.g. {sectionId: section.id)}, that + * you'd like to test against the current active state. + * @property {object} current A reference to the state's config object. However + * you passed it in. Useful for accessing custom data. + * @property {object} transition Currently pending transition. A promise that'll + * resolve or reject. + * + * @description + * `$state` service is responsible for representing states as well as transitioning + * between them. It also provides interfaces to ask for current state or even states + * you're coming from. + */ + this.$get = $get; + $get.$inject = ['$rootScope', '$q', '$view', '$injector', '$resolve', '$stateParams', '$urlRouter', '$location', '$urlMatcherFactory']; + function $get( $rootScope, $q, $view, $injector, $resolve, $stateParams, $urlRouter, $location, $urlMatcherFactory) { + + var TransitionSuperseded = $q.reject(new Error('transition superseded')); + var TransitionPrevented = $q.reject(new Error('transition prevented')); + var TransitionAborted = $q.reject(new Error('transition aborted')); + var TransitionFailed = $q.reject(new Error('transition failed')); + + // Handles the case where a state which is the target of a transition is not found, and the user + // can optionally retry or defer the transition + function handleRedirect(redirect, state, params, options) { + /** + * @ngdoc event + * @name ui.router.state.$state#$stateNotFound + * @eventOf ui.router.state.$state + * @eventType broadcast on root scope + * @description + * Fired when a requested state **cannot be found** using the provided state name during transition. + * The event is broadcast allowing any handlers a single chance to deal with the error (usually by + * lazy-loading the unfound state). A special `unfoundState` object is passed to the listener handler, + * you can see its three properties in the example. You can use `event.preventDefault()` to abort the + * transition and the promise returned from `go` will be rejected with a `'transition aborted'` value. + * + * @param {Object} event Event object. + * @param {Object} unfoundState Unfound State information. Contains: `to, toParams, options` properties. + * @param {State} fromState Current state object. + * @param {Object} fromParams Current state params. + * + * @example + * + *
      +       * // somewhere, assume lazy.state has not been defined
      +       * $state.go("lazy.state", {a:1, b:2}, {inherit:false});
      +       *
      +       * // somewhere else
      +       * $scope.$on('$stateNotFound',
      +       * function(event, unfoundState, fromState, fromParams){
      +       *     console.log(unfoundState.to); // "lazy.state"
      +       *     console.log(unfoundState.toParams); // {a:1, b:2}
      +       *     console.log(unfoundState.options); // {inherit:false} + default options
      +       * })
      +       * 
      + */ + var evt = $rootScope.$broadcast('$stateNotFound', redirect, state, params); + + if (evt.defaultPrevented) { + $urlRouter.update(); + return TransitionAborted; + } + + if (!evt.retry) { + return null; + } + + // Allow the handler to return a promise to defer state lookup retry + if (options.$retry) { + $urlRouter.update(); + return TransitionFailed; + } + var retryTransition = $state.transition = $q.when(evt.retry); + + retryTransition.then(function() { + if (retryTransition !== $state.transition) return TransitionSuperseded; + redirect.options.$retry = true; + return $state.transitionTo(redirect.to, redirect.toParams, redirect.options); + }, function() { + return TransitionAborted; + }); + $urlRouter.update(); + + return retryTransition; + } + + root.locals = { resolve: null, globals: { $stateParams: {} } }; + + $state = { + params: {}, + current: root.self, + $current: root, + transition: null + }; + + /** + * @ngdoc function + * @name ui.router.state.$state#reload + * @methodOf ui.router.state.$state + * + * @description + * A method that force reloads the current state. All resolves are re-resolved, events are not re-fired, + * and controllers reinstantiated (bug with controllers reinstantiating right now, fixing soon). + * + * @example + *
      +     * var app angular.module('app', ['ui.router']);
      +     *
      +     * app.controller('ctrl', function ($scope, $state) {
      +     *   $scope.reload = function(){
      +     *     $state.reload();
      +     *   }
      +     * });
      +     * 
      + * + * `reload()` is just an alias for: + *
      +     * $state.transitionTo($state.current, $stateParams, { 
      +     *   reload: true, inherit: false, notify: true
      +     * });
      +     * 
      + * + * @returns {promise} A promise representing the state of the new transition. See + * {@link ui.router.state.$state#methods_go $state.go}. + */ + $state.reload = function reload() { + return $state.transitionTo($state.current, $stateParams, { reload: true, inherit: false, notify: true }); + }; + + /** + * @ngdoc function + * @name ui.router.state.$state#go + * @methodOf ui.router.state.$state + * + * @description + * Convenience method for transitioning to a new state. `$state.go` calls + * `$state.transitionTo` internally but automatically sets options to + * `{ location: true, inherit: true, relative: $state.$current, notify: true }`. + * This allows you to easily use an absolute or relative to path and specify + * only the parameters you'd like to update (while letting unspecified parameters + * inherit from the currently active ancestor states). + * + * @example + *
      +     * var app = angular.module('app', ['ui.router']);
      +     *
      +     * app.controller('ctrl', function ($scope, $state) {
      +     *   $scope.changeState = function () {
      +     *     $state.go('contact.detail');
      +     *   };
      +     * });
      +     * 
      + * + * + * @param {string} to Absolute state name or relative state path. Some examples: + * + * - `$state.go('contact.detail')` - will go to the `contact.detail` state + * - `$state.go('^')` - will go to a parent state + * - `$state.go('^.sibling')` - will go to a sibling state + * - `$state.go('.child.grandchild')` - will go to grandchild state + * + * @param {object=} params A map of the parameters that will be sent to the state, + * will populate $stateParams. Any parameters that are not specified will be inherited from currently + * defined parameters. This allows, for example, going to a sibling state that shares parameters + * specified in a parent state. Parameter inheritance only works between common ancestor states, I.e. + * transitioning to a sibling will get you the parameters for all parents, transitioning to a child + * will get you all current parameters, etc. + * @param {object=} options Options object. The options are: + * + * - **`location`** - {boolean=true|string=} - If `true` will update the url in the location bar, if `false` + * will not. If string, must be `"replace"`, which will update url and also replace last history record. + * - **`inherit`** - {boolean=true}, If `true` will inherit url parameters from current url. + * - **`relative`** - {object=$state.$current}, When transitioning with relative path (e.g '^'), + * defines which state to be relative from. + * - **`notify`** - {boolean=true}, If `true` will broadcast $stateChangeStart and $stateChangeSuccess events. + * - **`reload`** (v0.2.5) - {boolean=false}, If `true` will force transition even if the state or params + * have not changed, aka a reload of the same state. It differs from reloadOnSearch because you'd + * use this when you want to force a reload when *everything* is the same, including search params. + * + * @returns {promise} A promise representing the state of the new transition. + * + * Possible success values: + * + * - $state.current + * + *
      Possible rejection values: + * + * - 'transition superseded' - when a newer transition has been started after this one + * - 'transition prevented' - when `event.preventDefault()` has been called in a `$stateChangeStart` listener + * - 'transition aborted' - when `event.preventDefault()` has been called in a `$stateNotFound` listener or + * when a `$stateNotFound` `event.retry` promise errors. + * - 'transition failed' - when a state has been unsuccessfully found after 2 tries. + * - *resolve error* - when an error has occurred with a `resolve` + * + */ + $state.go = function go(to, params, options) { + return $state.transitionTo(to, params, extend({ inherit: true, relative: $state.$current }, options)); + }; + + /** + * @ngdoc function + * @name ui.router.state.$state#transitionTo + * @methodOf ui.router.state.$state + * + * @description + * Low-level method for transitioning to a new state. {@link ui.router.state.$state#methods_go $state.go} + * uses `transitionTo` internally. `$state.go` is recommended in most situations. + * + * @example + *
      +     * var app = angular.module('app', ['ui.router']);
      +     *
      +     * app.controller('ctrl', function ($scope, $state) {
      +     *   $scope.changeState = function () {
      +     *     $state.transitionTo('contact.detail');
      +     *   };
      +     * });
      +     * 
      + * + * @param {string} to State name. + * @param {object=} toParams A map of the parameters that will be sent to the state, + * will populate $stateParams. + * @param {object=} options Options object. The options are: + * + * - **`location`** - {boolean=true|string=} - If `true` will update the url in the location bar, if `false` + * will not. If string, must be `"replace"`, which will update url and also replace last history record. + * - **`inherit`** - {boolean=false}, If `true` will inherit url parameters from current url. + * - **`relative`** - {object=}, When transitioning with relative path (e.g '^'), + * defines which state to be relative from. + * - **`notify`** - {boolean=true}, If `true` will broadcast $stateChangeStart and $stateChangeSuccess events. + * - **`reload`** (v0.2.5) - {boolean=false}, If `true` will force transition even if the state or params + * have not changed, aka a reload of the same state. It differs from reloadOnSearch because you'd + * use this when you want to force a reload when *everything* is the same, including search params. + * + * @returns {promise} A promise representing the state of the new transition. See + * {@link ui.router.state.$state#methods_go $state.go}. + */ + $state.transitionTo = function transitionTo(to, toParams, options) { + toParams = toParams || {}; + options = extend({ + location: true, inherit: false, relative: null, notify: true, reload: false, $retry: false + }, options || {}); + + var from = $state.$current, fromParams = $state.params, fromPath = from.path; + var evt, toState = findState(to, options.relative); + + if (!isDefined(toState)) { + var redirect = { to: to, toParams: toParams, options: options }; + var redirectResult = handleRedirect(redirect, from.self, fromParams, options); + + if (redirectResult) { + return redirectResult; + } + + // Always retry once if the $stateNotFound was not prevented + // (handles either redirect changed or state lazy-definition) + to = redirect.to; + toParams = redirect.toParams; + options = redirect.options; + toState = findState(to, options.relative); + + if (!isDefined(toState)) { + if (!options.relative) throw new Error("No such state '" + to + "'"); + throw new Error("Could not resolve '" + to + "' from state '" + options.relative + "'"); + } + } + if (toState[abstractKey]) throw new Error("Cannot transition to abstract state '" + to + "'"); + if (options.inherit) toParams = inheritParams($stateParams, toParams || {}, $state.$current, toState); + if (!toState.params.$$validates(toParams)) return TransitionFailed; + + toParams = toState.params.$$values(toParams); + to = toState; + + var toPath = to.path; + + // Starting from the root of the path, keep all levels that haven't changed + var keep = 0, state = toPath[keep], locals = root.locals, toLocals = []; + + if (!options.reload) { + while (state && state === fromPath[keep] && state.ownParams.$$equals(toParams, fromParams)) { + locals = toLocals[keep] = state.locals; + keep++; + state = toPath[keep]; + } + } + + // If we're going to the same state and all locals are kept, we've got nothing to do. + // But clear 'transition', as we still want to cancel any other pending transitions. + // TODO: We may not want to bump 'transition' if we're called from a location change + // that we've initiated ourselves, because we might accidentally abort a legitimate + // transition initiated from code? + if (shouldTriggerReload(to, from, locals, options)) { + if (to.self.reloadOnSearch !== false) $urlRouter.update(); + $state.transition = null; + return $q.when($state.current); + } + + // Filter parameters before we pass them to event handlers etc. + toParams = filterByKeys(to.params.$$keys(), toParams || {}); + + // Broadcast start event and cancel the transition if requested + if (options.notify) { + /** + * @ngdoc event + * @name ui.router.state.$state#$stateChangeStart + * @eventOf ui.router.state.$state + * @eventType broadcast on root scope + * @description + * Fired when the state transition **begins**. You can use `event.preventDefault()` + * to prevent the transition from happening and then the transition promise will be + * rejected with a `'transition prevented'` value. + * + * @param {Object} event Event object. + * @param {State} toState The state being transitioned to. + * @param {Object} toParams The params supplied to the `toState`. + * @param {State} fromState The current state, pre-transition. + * @param {Object} fromParams The params supplied to the `fromState`. + * + * @example + * + *
      +         * $rootScope.$on('$stateChangeStart',
      +         * function(event, toState, toParams, fromState, fromParams){
      +         *     event.preventDefault();
      +         *     // transitionTo() promise will be rejected with
      +         *     // a 'transition prevented' error
      +         * })
      +         * 
      + */ + if ($rootScope.$broadcast('$stateChangeStart', to.self, toParams, from.self, fromParams).defaultPrevented) { + $urlRouter.update(); + return TransitionPrevented; + } + } + + // Resolve locals for the remaining states, but don't update any global state just + // yet -- if anything fails to resolve the current state needs to remain untouched. + // We also set up an inheritance chain for the locals here. This allows the view directive + // to quickly look up the correct definition for each view in the current state. Even + // though we create the locals object itself outside resolveState(), it is initially + // empty and gets filled asynchronously. We need to keep track of the promise for the + // (fully resolved) current locals, and pass this down the chain. + var resolved = $q.when(locals); + + for (var l = keep; l < toPath.length; l++, state = toPath[l]) { + locals = toLocals[l] = inherit(locals); + resolved = resolveState(state, toParams, state === to, resolved, locals, options); + } + + // Once everything is resolved, we are ready to perform the actual transition + // and return a promise for the new state. We also keep track of what the + // current promise is, so that we can detect overlapping transitions and + // keep only the outcome of the last transition. + var transition = $state.transition = resolved.then(function () { + var l, entering, exiting; + + if ($state.transition !== transition) return TransitionSuperseded; + + // Exit 'from' states not kept + for (l = fromPath.length - 1; l >= keep; l--) { + exiting = fromPath[l]; + if (exiting.self.onExit) { + $injector.invoke(exiting.self.onExit, exiting.self, exiting.locals.globals); + } + exiting.locals = null; + } + + // Enter 'to' states not kept + for (l = keep; l < toPath.length; l++) { + entering = toPath[l]; + entering.locals = toLocals[l]; + if (entering.self.onEnter) { + $injector.invoke(entering.self.onEnter, entering.self, entering.locals.globals); + } + } + + // Run it again, to catch any transitions in callbacks + if ($state.transition !== transition) return TransitionSuperseded; + + // Update globals in $state + $state.$current = to; + $state.current = to.self; + $state.params = toParams; + copy($state.params, $stateParams); + $state.transition = null; + + if (options.location && to.navigable) { + $urlRouter.push(to.navigable.url, to.navigable.locals.globals.$stateParams, { + $$avoidResync: true, replace: options.location === 'replace' + }); + } + + if (options.notify) { + /** + * @ngdoc event + * @name ui.router.state.$state#$stateChangeSuccess + * @eventOf ui.router.state.$state + * @eventType broadcast on root scope + * @description + * Fired once the state transition is **complete**. + * + * @param {Object} event Event object. + * @param {State} toState The state being transitioned to. + * @param {Object} toParams The params supplied to the `toState`. + * @param {State} fromState The current state, pre-transition. + * @param {Object} fromParams The params supplied to the `fromState`. + */ + $rootScope.$broadcast('$stateChangeSuccess', to.self, toParams, from.self, fromParams); + } + $urlRouter.update(true); + + return $state.current; + }, function (error) { + if ($state.transition !== transition) return TransitionSuperseded; + + $state.transition = null; + /** + * @ngdoc event + * @name ui.router.state.$state#$stateChangeError + * @eventOf ui.router.state.$state + * @eventType broadcast on root scope + * @description + * Fired when an **error occurs** during transition. It's important to note that if you + * have any errors in your resolve functions (javascript errors, non-existent services, etc) + * they will not throw traditionally. You must listen for this $stateChangeError event to + * catch **ALL** errors. + * + * @param {Object} event Event object. + * @param {State} toState The state being transitioned to. + * @param {Object} toParams The params supplied to the `toState`. + * @param {State} fromState The current state, pre-transition. + * @param {Object} fromParams The params supplied to the `fromState`. + * @param {Error} error The resolve error object. + */ + evt = $rootScope.$broadcast('$stateChangeError', to.self, toParams, from.self, fromParams, error); + + if (!evt.defaultPrevented) { + $urlRouter.update(); + } + + return $q.reject(error); + }); + + return transition; + }; + + /** + * @ngdoc function + * @name ui.router.state.$state#is + * @methodOf ui.router.state.$state + * + * @description + * Similar to {@link ui.router.state.$state#methods_includes $state.includes}, + * but only checks for the full state name. If params is supplied then it will be + * tested for strict equality against the current active params object, so all params + * must match with none missing and no extras. + * + * @example + *
      +     * $state.$current.name = 'contacts.details.item';
      +     *
      +     * // absolute name
      +     * $state.is('contact.details.item'); // returns true
      +     * $state.is(contactDetailItemStateObject); // returns true
      +     *
      +     * // relative name (. and ^), typically from a template
      +     * // E.g. from the 'contacts.details' template
      +     * 
      Item
      + *
      + * + * @param {string|object} stateOrName The state name (absolute or relative) or state object you'd like to check. + * @param {object=} params A param object, e.g. `{sectionId: section.id}`, that you'd like + * to test against the current active state. + * @param {object=} options An options object. The options are: + * + * - **`relative`** - {string|object} - If `stateOrName` is a relative state name and `options.relative` is set, .is will + * test relative to `options.relative` state (or name). + * + * @returns {boolean} Returns true if it is the state. + */ + $state.is = function is(stateOrName, params, options) { + options = extend({ relative: $state.$current }, options || {}); + var state = findState(stateOrName, options.relative); + + if (!isDefined(state)) { return undefined; } + if ($state.$current !== state) { return false; } + return params ? equalForKeys(state.params.$$values(params), $stateParams) : true; + }; + + /** + * @ngdoc function + * @name ui.router.state.$state#includes + * @methodOf ui.router.state.$state + * + * @description + * A method to determine if the current active state is equal to or is the child of the + * state stateName. If any params are passed then they will be tested for a match as well. + * Not all the parameters need to be passed, just the ones you'd like to test for equality. + * + * @example + * Partial and relative names + *
      +     * $state.$current.name = 'contacts.details.item';
      +     *
      +     * // Using partial names
      +     * $state.includes("contacts"); // returns true
      +     * $state.includes("contacts.details"); // returns true
      +     * $state.includes("contacts.details.item"); // returns true
      +     * $state.includes("contacts.list"); // returns false
      +     * $state.includes("about"); // returns false
      +     *
      +     * // Using relative names (. and ^), typically from a template
      +     * // E.g. from the 'contacts.details' template
      +     * 
      Item
      + *
      + * + * Basic globbing patterns + *
      +     * $state.$current.name = 'contacts.details.item.url';
      +     *
      +     * $state.includes("*.details.*.*"); // returns true
      +     * $state.includes("*.details.**"); // returns true
      +     * $state.includes("**.item.**"); // returns true
      +     * $state.includes("*.details.item.url"); // returns true
      +     * $state.includes("*.details.*.url"); // returns true
      +     * $state.includes("*.details.*"); // returns false
      +     * $state.includes("item.**"); // returns false
      +     * 
      + * + * @param {string} stateOrName A partial name, relative name, or glob pattern + * to be searched for within the current state name. + * @param {object=} params A param object, e.g. `{sectionId: section.id}`, + * that you'd like to test against the current active state. + * @param {object=} options An options object. The options are: + * + * - **`relative`** - {string|object=} - If `stateOrName` is a relative state reference and `options.relative` is set, + * .includes will test relative to `options.relative` state (or name). + * + * @returns {boolean} Returns true if it does include the state + */ + $state.includes = function includes(stateOrName, params, options) { + options = extend({ relative: $state.$current }, options || {}); + if (isString(stateOrName) && isGlob(stateOrName)) { + if (!doesStateMatchGlob(stateOrName)) { + return false; + } + stateOrName = $state.$current.name; + } + + var state = findState(stateOrName, options.relative); + if (!isDefined(state)) { return undefined; } + if (!isDefined($state.$current.includes[state.name])) { return false; } + return params ? equalForKeys(state.params.$$values(params), $stateParams, objectKeys(params)) : true; + }; + + + /** + * @ngdoc function + * @name ui.router.state.$state#href + * @methodOf ui.router.state.$state + * + * @description + * A url generation method that returns the compiled url for the given state populated with the given params. + * + * @example + *
      +     * expect($state.href("about.person", { person: "bob" })).toEqual("/about/bob");
      +     * 
      + * + * @param {string|object} stateOrName The state name or state object you'd like to generate a url from. + * @param {object=} params An object of parameter values to fill the state's required parameters. + * @param {object=} options Options object. The options are: + * + * - **`lossy`** - {boolean=true} - If true, and if there is no url associated with the state provided in the + * first parameter, then the constructed href url will be built from the first navigable ancestor (aka + * ancestor with a valid url). + * - **`inherit`** - {boolean=true}, If `true` will inherit url parameters from current url. + * - **`relative`** - {object=$state.$current}, When transitioning with relative path (e.g '^'), + * defines which state to be relative from. + * - **`absolute`** - {boolean=false}, If true will generate an absolute url, e.g. "http://www.example.com/fullurl". + * + * @returns {string} compiled state url + */ + $state.href = function href(stateOrName, params, options) { + options = extend({ + lossy: true, + inherit: true, + absolute: false, + relative: $state.$current + }, options || {}); + + var state = findState(stateOrName, options.relative); + + if (!isDefined(state)) return null; + if (options.inherit) params = inheritParams($stateParams, params || {}, $state.$current, state); + + var nav = (state && options.lossy) ? state.navigable : state; + + if (!nav || nav.url === undefined || nav.url === null) { + return null; + } + return $urlRouter.href(nav.url, filterByKeys(state.params.$$keys(), params || {}), { + absolute: options.absolute + }); + }; + + /** + * @ngdoc function + * @name ui.router.state.$state#get + * @methodOf ui.router.state.$state + * + * @description + * Returns the state configuration object for any specific state or all states. + * + * @param {string|object=} stateOrName (absolute or relative) If provided, will only get the config for + * the requested state. If not provided, returns an array of ALL state configs. + * @param {string|object=} context When stateOrName is a relative state reference, the state will be retrieved relative to context. + * @returns {Object|Array} State configuration object or array of all objects. + */ + $state.get = function (stateOrName, context) { + if (arguments.length === 0) return map(objectKeys(states), function(name) { return states[name].self; }); + var state = findState(stateOrName, context || $state.$current); + return (state && state.self) ? state.self : null; + }; + + function resolveState(state, params, paramsAreFiltered, inherited, dst, options) { + // Make a restricted $stateParams with only the parameters that apply to this state if + // necessary. In addition to being available to the controller and onEnter/onExit callbacks, + // we also need $stateParams to be available for any $injector calls we make during the + // dependency resolution process. + var $stateParams = (paramsAreFiltered) ? params : filterByKeys(state.params.$$keys(), params); + var locals = { $stateParams: $stateParams }; + + // Resolve 'global' dependencies for the state, i.e. those not specific to a view. + // We're also including $stateParams in this; that way the parameters are restricted + // to the set that should be visible to the state, and are independent of when we update + // the global $state and $stateParams values. + dst.resolve = $resolve.resolve(state.resolve, locals, dst.resolve, state); + var promises = [dst.resolve.then(function (globals) { + dst.globals = globals; + })]; + if (inherited) promises.push(inherited); + + // Resolve template and dependencies for all views. + forEach(state.views, function (view, name) { + var injectables = (view.resolve && view.resolve !== state.resolve ? view.resolve : {}); + injectables.$template = [ function () { + return $view.load(name, { view: view, locals: locals, params: $stateParams, notify: options.notify }) || ''; + }]; + + promises.push($resolve.resolve(injectables, locals, dst.resolve, state).then(function (result) { + // References to the controller (only instantiated at link time) + if (isFunction(view.controllerProvider) || isArray(view.controllerProvider)) { + var injectLocals = angular.extend({}, injectables, locals); + result.$$controller = $injector.invoke(view.controllerProvider, null, injectLocals); + } else { + result.$$controller = view.controller; + } + // Provide access to the state itself for internal use + result.$$state = state; + result.$$controllerAs = view.controllerAs; + dst[name] = result; + })); + }); + + // Wait for all the promises and then return the activation object + return $q.all(promises).then(function (values) { + return dst; + }); + } + + return $state; + } + + function shouldTriggerReload(to, from, locals, options) { + if (to === from && ((locals === from.locals && !options.reload) || (to.self.reloadOnSearch === false))) { + return true; + } + } +} + +angular.module('ui.router.state') + .value('$stateParams', {}) + .provider('$state', $StateProvider); + + +$ViewProvider.$inject = []; +function $ViewProvider() { + + this.$get = $get; + /** + * @ngdoc object + * @name ui.router.state.$view + * + * @requires ui.router.util.$templateFactory + * @requires $rootScope + * + * @description + * + */ + $get.$inject = ['$rootScope', '$templateFactory']; + function $get( $rootScope, $templateFactory) { + return { + // $view.load('full.viewName', { template: ..., controller: ..., resolve: ..., async: false, params: ... }) + /** + * @ngdoc function + * @name ui.router.state.$view#load + * @methodOf ui.router.state.$view + * + * @description + * + * @param {string} name name + * @param {object} options option object. + */ + load: function load(name, options) { + var result, defaults = { + template: null, controller: null, view: null, locals: null, notify: true, async: true, params: {} + }; + options = extend(defaults, options); + + if (options.view) { + result = $templateFactory.fromConfig(options.view, options.params, options.locals); + } + if (result && options.notify) { + /** + * @ngdoc event + * @name ui.router.state.$state#$viewContentLoading + * @eventOf ui.router.state.$view + * @eventType broadcast on root scope + * @description + * + * Fired once the view **begins loading**, *before* the DOM is rendered. + * + * @param {Object} event Event object. + * @param {Object} viewConfig The view config properties (template, controller, etc). + * + * @example + * + *
      +         * $scope.$on('$viewContentLoading',
      +         * function(event, viewConfig){
      +         *     // Access to all the view config properties.
      +         *     // and one special property 'targetView'
      +         *     // viewConfig.targetView
      +         * });
      +         * 
      + */ + $rootScope.$broadcast('$viewContentLoading', options); + } + return result; + } + }; + } +} + +angular.module('ui.router.state').provider('$view', $ViewProvider); + +/** + * @ngdoc object + * @name ui.router.state.$uiViewScrollProvider + * + * @description + * Provider that returns the {@link ui.router.state.$uiViewScroll} service function. + */ +function $ViewScrollProvider() { + + var useAnchorScroll = false; + + /** + * @ngdoc function + * @name ui.router.state.$uiViewScrollProvider#useAnchorScroll + * @methodOf ui.router.state.$uiViewScrollProvider + * + * @description + * Reverts back to using the core [`$anchorScroll`](http://docs.angularjs.org/api/ng.$anchorScroll) service for + * scrolling based on the url anchor. + */ + this.useAnchorScroll = function () { + useAnchorScroll = true; + }; + + /** + * @ngdoc object + * @name ui.router.state.$uiViewScroll + * + * @requires $anchorScroll + * @requires $timeout + * + * @description + * When called with a jqLite element, it scrolls the element into view (after a + * `$timeout` so the DOM has time to refresh). + * + * If you prefer to rely on `$anchorScroll` to scroll the view to the anchor, + * this can be enabled by calling {@link ui.router.state.$uiViewScrollProvider#methods_useAnchorScroll `$uiViewScrollProvider.useAnchorScroll()`}. + */ + this.$get = ['$anchorScroll', '$timeout', function ($anchorScroll, $timeout) { + if (useAnchorScroll) { + return $anchorScroll; + } + + return function ($element) { + $timeout(function () { + $element[0].scrollIntoView(); + }, 0, false); + }; + }]; +} + +angular.module('ui.router.state').provider('$uiViewScroll', $ViewScrollProvider); + +/** + * @ngdoc directive + * @name ui.router.state.directive:ui-view + * + * @requires ui.router.state.$state + * @requires $compile + * @requires $controller + * @requires $injector + * @requires ui.router.state.$uiViewScroll + * @requires $document + * + * @restrict ECA + * + * @description + * The ui-view directive tells $state where to place your templates. + * + * @param {string=} name A view name. The name should be unique amongst the other views in the + * same state. You can have views of the same name that live in different states. + * + * @param {string=} autoscroll It allows you to set the scroll behavior of the browser window + * when a view is populated. By default, $anchorScroll is overridden by ui-router's custom scroll + * service, {@link ui.router.state.$uiViewScroll}. This custom service let's you + * scroll ui-view elements into view when they are populated during a state activation. + * + * *Note: To revert back to old [`$anchorScroll`](http://docs.angularjs.org/api/ng.$anchorScroll) + * functionality, call `$uiViewScrollProvider.useAnchorScroll()`.* + * + * @param {string=} onload Expression to evaluate whenever the view updates. + * + * @example + * A view can be unnamed or named. + *
      + * 
      + * 
      + * + * + *
      + *
      + * + * You can only have one unnamed view within any template (or root html). If you are only using a + * single view and it is unnamed then you can populate it like so: + *
      + * 
      + * $stateProvider.state("home", { + * template: "

      HELLO!

      " + * }) + *
      + * + * The above is a convenient shortcut equivalent to specifying your view explicitly with the {@link ui.router.state.$stateProvider#views `views`} + * config property, by name, in this case an empty name: + *
      + * $stateProvider.state("home", {
      + *   views: {
      + *     "": {
      + *       template: "

      HELLO!

      " + * } + * } + * }) + *
      + * + * But typically you'll only use the views property if you name your view or have more than one view + * in the same template. There's not really a compelling reason to name a view if its the only one, + * but you could if you wanted, like so: + *
      + * 
      + *
      + *
      + * $stateProvider.state("home", {
      + *   views: {
      + *     "main": {
      + *       template: "

      HELLO!

      " + * } + * } + * }) + *
      + * + * Really though, you'll use views to set up multiple views: + *
      + * 
      + *
      + *
      + *
      + * + *
      + * $stateProvider.state("home", {
      + *   views: {
      + *     "": {
      + *       template: "

      HELLO!

      " + * }, + * "chart": { + * template: "" + * }, + * "data": { + * template: "" + * } + * } + * }) + *
      + * + * Examples for `autoscroll`: + * + *
      + * 
      + * 
      + *
      + * 
      + * 
      + * 
      + * 
      + * 
      + */ +$ViewDirective.$inject = ['$state', '$injector', '$uiViewScroll', '$interpolate']; +function $ViewDirective( $state, $injector, $uiViewScroll, $interpolate) { + + function getService() { + return ($injector.has) ? function(service) { + return $injector.has(service) ? $injector.get(service) : null; + } : function(service) { + try { + return $injector.get(service); + } catch (e) { + return null; + } + }; + } + + var service = getService(), + $animator = service('$animator'), + $animate = service('$animate'); + + // Returns a set of DOM manipulation functions based on which Angular version + // it should use + function getRenderer(attrs, scope) { + var statics = function() { + return { + enter: function (element, target, cb) { target.after(element); cb(); }, + leave: function (element, cb) { element.remove(); cb(); } + }; + }; + + if ($animate) { + return { + enter: function(element, target, cb) { + var promise = $animate.enter(element, null, target, cb); + if (promise && promise.then) promise.then(cb); + }, + leave: function(element, cb) { + var promise = $animate.leave(element, cb); + if (promise && promise.then) promise.then(cb); + } + }; + } + + if ($animator) { + var animate = $animator && $animator(scope, attrs); + + return { + enter: function(element, target, cb) {animate.enter(element, null, target); cb(); }, + leave: function(element, cb) { animate.leave(element); cb(); } + }; + } + + return statics(); + } + + var directive = { + restrict: 'ECA', + terminal: true, + priority: 400, + transclude: 'element', + compile: function (tElement, tAttrs, $transclude) { + return function (scope, $element, attrs) { + var previousEl, currentEl, currentScope, latestLocals, + onloadExp = attrs.onload || '', + autoScrollExp = attrs.autoscroll, + renderer = getRenderer(attrs, scope); + + scope.$on('$stateChangeSuccess', function() { + updateView(false); + }); + scope.$on('$viewContentLoading', function() { + updateView(false); + }); + + updateView(true); + + function cleanupLastView() { + if (previousEl) { + previousEl.remove(); + previousEl = null; + } + + if (currentScope) { + currentScope.$destroy(); + currentScope = null; + } + + if (currentEl) { + renderer.leave(currentEl, function() { + previousEl = null; + }); + + previousEl = currentEl; + currentEl = null; + } + } + + function updateView(firstTime) { + var newScope, + name = getUiViewName(scope, attrs, $element, $interpolate), + previousLocals = name && $state.$current && $state.$current.locals[name]; + + if (!firstTime && previousLocals === latestLocals) return; // nothing to do + newScope = scope.$new(); + latestLocals = $state.$current.locals[name]; + + var clone = $transclude(newScope, function(clone) { + renderer.enter(clone, $element, function onUiViewEnter() { + if(currentScope) { + currentScope.$emit('$viewContentAnimationEnded'); + } + + if (angular.isDefined(autoScrollExp) && !autoScrollExp || scope.$eval(autoScrollExp)) { + $uiViewScroll(clone); + } + }); + cleanupLastView(); + }); + + currentEl = clone; + currentScope = newScope; + /** + * @ngdoc event + * @name ui.router.state.directive:ui-view#$viewContentLoaded + * @eventOf ui.router.state.directive:ui-view + * @eventType emits on ui-view directive scope + * @description * + * Fired once the view is **loaded**, *after* the DOM is rendered. + * + * @param {Object} event Event object. + */ + currentScope.$emit('$viewContentLoaded'); + currentScope.$eval(onloadExp); + } + }; + } + }; + + return directive; +} + +$ViewDirectiveFill.$inject = ['$compile', '$controller', '$state', '$interpolate']; +function $ViewDirectiveFill ( $compile, $controller, $state, $interpolate) { + return { + restrict: 'ECA', + priority: -400, + compile: function (tElement) { + var initial = tElement.html(); + return function (scope, $element, attrs) { + var current = $state.$current, + name = getUiViewName(scope, attrs, $element, $interpolate), + locals = current && current.locals[name]; + + if (! locals) { + return; + } + + $element.data('$uiView', { name: name, state: locals.$$state }); + $element.html(locals.$template ? locals.$template : initial); + + var link = $compile($element.contents()); + + if (locals.$$controller) { + locals.$scope = scope; + var controller = $controller(locals.$$controller, locals); + if (locals.$$controllerAs) { + scope[locals.$$controllerAs] = controller; + } + $element.data('$ngControllerController', controller); + $element.children().data('$ngControllerController', controller); + } + + link(scope); + }; + } + }; +} + +/** + * Shared ui-view code for both directives: + * Given scope, element, and its attributes, return the view's name + */ +function getUiViewName(scope, attrs, element, $interpolate) { + var name = $interpolate(attrs.uiView || attrs.name || '')(scope); + var inherited = element.inheritedData('$uiView'); + return name.indexOf('@') >= 0 ? name : (name + '@' + (inherited ? inherited.state.name : '')); +} + +angular.module('ui.router.state').directive('uiView', $ViewDirective); +angular.module('ui.router.state').directive('uiView', $ViewDirectiveFill); + +function parseStateRef(ref, current) { + var preparsed = ref.match(/^\s*({[^}]*})\s*$/), parsed; + if (preparsed) ref = current + '(' + preparsed[1] + ')'; + parsed = ref.replace(/\n/g, " ").match(/^([^(]+?)\s*(\((.*)\))?$/); + if (!parsed || parsed.length !== 4) throw new Error("Invalid state ref '" + ref + "'"); + return { state: parsed[1], paramExpr: parsed[3] || null }; +} + +function stateContext(el) { + var stateData = el.parent().inheritedData('$uiView'); + + if (stateData && stateData.state && stateData.state.name) { + return stateData.state; + } +} + +/** + * @ngdoc directive + * @name ui.router.state.directive:ui-sref + * + * @requires ui.router.state.$state + * @requires $timeout + * + * @restrict A + * + * @description + * A directive that binds a link (`` tag) to a state. If the state has an associated + * URL, the directive will automatically generate & update the `href` attribute via + * the {@link ui.router.state.$state#methods_href $state.href()} method. Clicking + * the link will trigger a state transition with optional parameters. + * + * Also middle-clicking, right-clicking, and ctrl-clicking on the link will be + * handled natively by the browser. + * + * You can also use relative state paths within ui-sref, just like the relative + * paths passed to `$state.go()`. You just need to be aware that the path is relative + * to the state that the link lives in, in other words the state that loaded the + * template containing the link. + * + * You can specify options to pass to {@link ui.router.state.$state#go $state.go()} + * using the `ui-sref-opts` attribute. Options are restricted to `location`, `inherit`, + * and `reload`. + * + * @example + * Here's an example of how you'd use ui-sref and how it would compile. If you have the + * following template: + *
      + * Home | About | Next page
      + * 
      + * 
      + * 
      + * + * Then the compiled html would be (assuming Html5Mode is off and current state is contacts): + *
      + * Home | About | Next page
      + * 
      + * 
        + *
      • + * Joe + *
      • + *
      • + * Alice + *
      • + *
      • + * Bob + *
      • + *
      + * + * Home + *
      + * + * @param {string} ui-sref 'stateName' can be any valid absolute or relative state + * @param {Object} ui-sref-opts options to pass to {@link ui.router.state.$state#go $state.go()} + */ +$StateRefDirective.$inject = ['$state', '$timeout']; +function $StateRefDirective($state, $timeout) { + var allowedOptions = ['location', 'inherit', 'reload']; + + return { + restrict: 'A', + require: ['?^uiSrefActive', '?^uiSrefActiveEq'], + link: function(scope, element, attrs, uiSrefActive) { + var ref = parseStateRef(attrs.uiSref, $state.current.name); + var params = null, url = null, base = stateContext(element) || $state.$current; + var newHref = null, isAnchor = element.prop("tagName") === "A"; + var isForm = element[0].nodeName === "FORM"; + var attr = isForm ? "action" : "href", nav = true; + + var options = { relative: base, inherit: true }; + var optionsOverride = scope.$eval(attrs.uiSrefOpts) || {}; + + angular.forEach(allowedOptions, function(option) { + if (option in optionsOverride) { + options[option] = optionsOverride[option]; + } + }); + + var update = function(newVal) { + if (newVal) params = angular.copy(newVal); + if (!nav) return; + + newHref = $state.href(ref.state, params, options); + + var activeDirective = uiSrefActive[1] || uiSrefActive[0]; + if (activeDirective) { + activeDirective.$$setStateInfo(ref.state, params); + } + if (newHref === null) { + nav = false; + return false; + } + attrs.$set(attr, newHref); + }; + + if (ref.paramExpr) { + scope.$watch(ref.paramExpr, function(newVal, oldVal) { + if (newVal !== params) update(newVal); + }, true); + params = angular.copy(scope.$eval(ref.paramExpr)); + } + update(); + + if (isForm) return; + + element.bind("click", function(e) { + var button = e.which || e.button; + if ( !(button > 1 || e.ctrlKey || e.metaKey || e.shiftKey || element.attr('target')) ) { + // HACK: This is to allow ng-clicks to be processed before the transition is initiated: + var transition = $timeout(function() { + $state.go(ref.state, params, options); + }); + e.preventDefault(); + + // if the state has no URL, ignore one preventDefault from the directive. + var ignorePreventDefaultCount = isAnchor && !newHref ? 1: 0; + e.preventDefault = function() { + if (ignorePreventDefaultCount-- <= 0) + $timeout.cancel(transition); + }; + } + }); + } + }; +} + +/** + * @ngdoc directive + * @name ui.router.state.directive:ui-sref-active + * + * @requires ui.router.state.$state + * @requires ui.router.state.$stateParams + * @requires $interpolate + * + * @restrict A + * + * @description + * A directive working alongside ui-sref to add classes to an element when the + * related ui-sref directive's state is active, and removing them when it is inactive. + * The primary use-case is to simplify the special appearance of navigation menus + * relying on `ui-sref`, by having the "active" state's menu button appear different, + * distinguishing it from the inactive menu items. + * + * ui-sref-active can live on the same element as ui-sref or on a parent element. The first + * ui-sref-active found at the same level or above the ui-sref will be used. + * + * Will activate when the ui-sref's target state or any child state is active. If you + * need to activate only when the ui-sref target state is active and *not* any of + * it's children, then you will use + * {@link ui.router.state.directive:ui-sref-active-eq ui-sref-active-eq} + * + * @example + * Given the following template: + *
      + * 
      + * 
      + * + * + * When the app state is "app.user" (or any children states), and contains the state parameter "user" with value "bilbobaggins", + * the resulting HTML will appear as (note the 'active' class): + *
      + * 
      + * 
      + * + * The class name is interpolated **once** during the directives link time (any further changes to the + * interpolated value are ignored). + * + * Multiple classes may be specified in a space-separated format: + *
      + * 
        + *
      • + * link + *
      • + *
      + *
      + */ + +/** + * @ngdoc directive + * @name ui.router.state.directive:ui-sref-active-eq + * + * @requires ui.router.state.$state + * @requires ui.router.state.$stateParams + * @requires $interpolate + * + * @restrict A + * + * @description + * The same as {@link ui.router.state.directive:ui-sref-active ui-sref-active} but will only activate + * when the exact target state used in the `ui-sref` is active; no child states. + * + */ +$StateRefActiveDirective.$inject = ['$state', '$stateParams', '$interpolate']; +function $StateRefActiveDirective($state, $stateParams, $interpolate) { + return { + restrict: "A", + controller: ['$scope', '$element', '$attrs', function ($scope, $element, $attrs) { + var state, params, activeClass; + + // There probably isn't much point in $observing this + // uiSrefActive and uiSrefActiveEq share the same directive object with some + // slight difference in logic routing + activeClass = $interpolate($attrs.uiSrefActiveEq || $attrs.uiSrefActive || '', false)($scope); + + // Allow uiSref to communicate with uiSrefActive[Equals] + this.$$setStateInfo = function (newState, newParams) { + state = $state.get(newState, stateContext($element)); + params = newParams; + update(); + }; + + $scope.$on('$stateChangeSuccess', update); + + // Update route state + function update() { + if (isMatch()) { + $element.addClass(activeClass); + } else { + $element.removeClass(activeClass); + } + } + + function isMatch() { + if (typeof $attrs.uiSrefActiveEq !== 'undefined') { + return state && $state.is(state.name, params); + } else { + return state && $state.includes(state.name, params); + } + } + }] + }; +} + +angular.module('ui.router.state') + .directive('uiSref', $StateRefDirective) + .directive('uiSrefActive', $StateRefActiveDirective) + .directive('uiSrefActiveEq', $StateRefActiveDirective); + +/** + * @ngdoc filter + * @name ui.router.state.filter:isState + * + * @requires ui.router.state.$state + * + * @description + * Translates to {@link ui.router.state.$state#methods_is $state.is("stateName")}. + */ +$IsStateFilter.$inject = ['$state']; +function $IsStateFilter($state) { + var isFilter = function (state) { + return $state.is(state); + }; + isFilter.$stateful = true; + return isFilter; +} + +/** + * @ngdoc filter + * @name ui.router.state.filter:includedByState + * + * @requires ui.router.state.$state + * + * @description + * Translates to {@link ui.router.state.$state#methods_includes $state.includes('fullOrPartialStateName')}. + */ +$IncludedByStateFilter.$inject = ['$state']; +function $IncludedByStateFilter($state) { + var includesFilter = function (state) { + return $state.includes(state); + }; + includesFilter.$stateful = true; + return includesFilter; +} + +angular.module('ui.router.state') + .filter('isState', $IsStateFilter) + .filter('includedByState', $IncludedByStateFilter); +})(window, window.angular); \ No newline at end of file diff --git a/public/admincp/bower_components/angular-ui-router/release/angular-ui-router.min.js b/public/admincp/bower_components/angular-ui-router/release/angular-ui-router.min.js new file mode 100644 index 000000000..be06fb5b0 --- /dev/null +++ b/public/admincp/bower_components/angular-ui-router/release/angular-ui-router.min.js @@ -0,0 +1,7 @@ +/** + * State-based routing for AngularJS + * @version v0.2.13 + * @link http://angular-ui.github.com/ + * @license MIT License, http://www.opensource.org/licenses/MIT + */ +"undefined"!=typeof module&&"undefined"!=typeof exports&&module.exports===exports&&(module.exports="ui.router"),function(a,b,c){"use strict";function d(a,b){return M(new(M(function(){},{prototype:a})),b)}function e(a){return L(arguments,function(b){b!==a&&L(b,function(b,c){a.hasOwnProperty(c)||(a[c]=b)})}),a}function f(a,b){var c=[];for(var d in a.path){if(a.path[d]!==b.path[d])break;c.push(a.path[d])}return c}function g(a){if(Object.keys)return Object.keys(a);var c=[];return b.forEach(a,function(a,b){c.push(b)}),c}function h(a,b){if(Array.prototype.indexOf)return a.indexOf(b,Number(arguments[2])||0);var c=a.length>>>0,d=Number(arguments[2])||0;for(d=0>d?Math.ceil(d):Math.floor(d),0>d&&(d+=c);c>d;d++)if(d in a&&a[d]===b)return d;return-1}function i(a,b,c,d){var e,i=f(c,d),j={},k=[];for(var l in i)if(i[l].params&&(e=g(i[l].params),e.length))for(var m in e)h(k,e[m])>=0||(k.push(e[m]),j[e[m]]=a[e[m]]);return M({},j,b)}function j(a,b,c){if(!c){c=[];for(var d in a)c.push(d)}for(var e=0;e "));if(s[c]=d,I(a))q.push(c,[function(){return b.get(a)}],j);else{var e=b.annotate(a);L(e,function(a){a!==c&&i.hasOwnProperty(a)&&n(i[a],a)}),q.push(c,a,e)}r.pop(),s[c]=f}}function o(a){return J(a)&&a.then&&a.$$promises}if(!J(i))throw new Error("'invocables' must be an object");var p=g(i||{}),q=[],r=[],s={};return L(i,n),i=r=s=null,function(d,f,g){function h(){--u||(v||e(t,f.$$values),r.$$values=t,r.$$promises=r.$$promises||!0,delete r.$$inheritedValues,n.resolve(t))}function i(a){r.$$failure=a,n.reject(a)}function j(c,e,f){function j(a){l.reject(a),i(a)}function k(){if(!G(r.$$failure))try{l.resolve(b.invoke(e,g,t)),l.promise.then(function(a){t[c]=a,h()},j)}catch(a){j(a)}}var l=a.defer(),m=0;L(f,function(a){s.hasOwnProperty(a)&&!d.hasOwnProperty(a)&&(m++,s[a].then(function(b){t[a]=b,--m||k()},j))}),m||k(),s[c]=l.promise}if(o(d)&&g===c&&(g=f,f=d,d=null),d){if(!J(d))throw new Error("'locals' must be an object")}else d=k;if(f){if(!o(f))throw new Error("'parent' must be a promise returned by $resolve.resolve()")}else f=m;var n=a.defer(),r=n.promise,s=r.$$promises={},t=M({},d),u=1+q.length/3,v=!1;if(G(f.$$failure))return i(f.$$failure),r;f.$$inheritedValues&&e(t,l(f.$$inheritedValues,p)),M(s,f.$$promises),f.$$values?(v=e(t,l(f.$$values,p)),r.$$inheritedValues=l(f.$$values,p),h()):(f.$$inheritedValues&&(r.$$inheritedValues=l(f.$$inheritedValues,p)),f.then(h,i));for(var w=0,x=q.length;x>w;w+=3)d.hasOwnProperty(q[w])?h():j(q[w],q[w+1],q[w+2]);return r}},this.resolve=function(a,b,c,d){return this.study(a)(b,c,d)}}function p(a,b,c){this.fromConfig=function(a,b,c){return G(a.template)?this.fromString(a.template,b):G(a.templateUrl)?this.fromUrl(a.templateUrl,b):G(a.templateProvider)?this.fromProvider(a.templateProvider,b,c):null},this.fromString=function(a,b){return H(a)?a(b):a},this.fromUrl=function(c,d){return H(c)&&(c=c(d)),null==c?null:a.get(c,{cache:b,headers:{Accept:"text/html"}}).then(function(a){return a.data})},this.fromProvider=function(a,b,d){return c.invoke(a,null,d||{params:b})}}function q(a,b,e){function f(b,c,d,e){if(q.push(b),o[b])return o[b];if(!/^\w+(-+\w+)*(?:\[\])?$/.test(b))throw new Error("Invalid parameter name '"+b+"' in pattern '"+a+"'");if(p[b])throw new Error("Duplicate parameter name '"+b+"' in pattern '"+a+"'");return p[b]=new O.Param(b,c,d,e),p[b]}function g(a,b,c){var d=["",""],e=a.replace(/[\\\[\]\^$*+?.()|{}]/g,"\\$&");if(!b)return e;switch(c){case!1:d=["(",")"];break;case!0:d=["?(",")?"];break;default:d=["("+c+"|",")?"]}return e+d[0]+b+d[1]}function h(c,e){var f,g,h,i,j;return f=c[2]||c[3],j=b.params[f],h=a.substring(m,c.index),g=e?c[4]:c[4]||("*"==c[1]?".*":null),i=O.type(g||"string")||d(O.type("string"),{pattern:new RegExp(g)}),{id:f,regexp:g,segment:h,type:i,cfg:j}}b=M({params:{}},J(b)?b:{});var i,j=/([:*])([\w\[\]]+)|\{([\w\[\]]+)(?:\:((?:[^{}\\]+|\\.|\{(?:[^{}\\]+|\\.)*\})+))?\}/g,k=/([:]?)([\w\[\]-]+)|\{([\w\[\]-]+)(?:\:((?:[^{}\\]+|\\.|\{(?:[^{}\\]+|\\.)*\})+))?\}/g,l="^",m=0,n=this.segments=[],o=e?e.params:{},p=this.params=e?e.params.$$new():new O.ParamSet,q=[];this.source=a;for(var r,s,t;(i=j.exec(a))&&(r=h(i,!1),!(r.segment.indexOf("?")>=0));)s=f(r.id,r.type,r.cfg,"path"),l+=g(r.segment,s.type.pattern.source,s.squash),n.push(r.segment),m=j.lastIndex;t=a.substring(m);var u=t.indexOf("?");if(u>=0){var v=this.sourceSearch=t.substring(u);if(t=t.substring(0,u),this.sourcePath=a.substring(0,m+u),v.length>0)for(m=0;i=k.exec(v);)r=h(i,!0),s=f(r.id,r.type,r.cfg,"search"),m=j.lastIndex}else this.sourcePath=a,this.sourceSearch="";l+=g(t)+(b.strict===!1?"/?":"")+"$",n.push(t),this.regexp=new RegExp(l,b.caseInsensitive?"i":c),this.prefix=n[0],this.$$paramNames=q}function r(a){M(this,a)}function s(){function a(a){return null!=a?a.toString().replace(/\//g,"%2F"):a}function e(a){return null!=a?a.toString().replace(/%2F/g,"/"):a}function f(a){return this.pattern.test(a)}function i(){return{strict:t,caseInsensitive:p}}function j(a){return H(a)||K(a)&&H(a[a.length-1])}function k(){for(;x.length;){var a=x.shift();if(a.pattern)throw new Error("You cannot override a type's .pattern at runtime.");b.extend(v[a.name],o.invoke(a.def))}}function l(a){M(this,a||{})}O=this;var o,p=!1,t=!0,u=!1,v={},w=!0,x=[],y={string:{encode:a,decode:e,is:f,pattern:/[^/]*/},"int":{encode:a,decode:function(a){return parseInt(a,10)},is:function(a){return G(a)&&this.decode(a.toString())===a},pattern:/\d+/},bool:{encode:function(a){return a?1:0},decode:function(a){return 0!==parseInt(a,10)},is:function(a){return a===!0||a===!1},pattern:/0|1/},date:{encode:function(a){return this.is(a)?[a.getFullYear(),("0"+(a.getMonth()+1)).slice(-2),("0"+a.getDate()).slice(-2)].join("-"):c},decode:function(a){if(this.is(a))return a;var b=this.capture.exec(a);return b?new Date(b[1],b[2]-1,b[3]):c},is:function(a){return a instanceof Date&&!isNaN(a.valueOf())},equals:function(a,b){return this.is(a)&&this.is(b)&&a.toISOString()===b.toISOString()},pattern:/[0-9]{4}-(?:0[1-9]|1[0-2])-(?:0[1-9]|[1-2][0-9]|3[0-1])/,capture:/([0-9]{4})-(0[1-9]|1[0-2])-(0[1-9]|[1-2][0-9]|3[0-1])/},json:{encode:b.toJson,decode:b.fromJson,is:b.isObject,equals:b.equals,pattern:/[^/]*/},any:{encode:b.identity,decode:b.identity,is:b.identity,equals:b.equals,pattern:/.*/}};s.$$getDefaultValue=function(a){if(!j(a.value))return a.value;if(!o)throw new Error("Injectable functions cannot be called at configuration time");return o.invoke(a.value)},this.caseInsensitive=function(a){return G(a)&&(p=a),p},this.strictMode=function(a){return G(a)&&(t=a),t},this.defaultSquashPolicy=function(a){if(!G(a))return u;if(a!==!0&&a!==!1&&!I(a))throw new Error("Invalid squash policy: "+a+". Valid policies: false, true, arbitrary-string");return u=a,a},this.compile=function(a,b){return new q(a,M(i(),b))},this.isMatcher=function(a){if(!J(a))return!1;var b=!0;return L(q.prototype,function(c,d){H(c)&&(b=b&&G(a[d])&&H(a[d]))}),b},this.type=function(a,b,c){if(!G(b))return v[a];if(v.hasOwnProperty(a))throw new Error("A type named '"+a+"' has already been defined.");return v[a]=new r(M({name:a},b)),c&&(x.push({name:a,def:c}),w||k()),this},L(y,function(a,b){v[b]=new r(M({name:b},a))}),v=d(v,{}),this.$get=["$injector",function(a){return o=a,w=!1,k(),L(y,function(a,b){v[b]||(v[b]=new r(a))}),this}],this.Param=function(a,b,d,e){function f(a){var b=J(a)?g(a):[],c=-1===h(b,"value")&&-1===h(b,"type")&&-1===h(b,"squash")&&-1===h(b,"array");return c&&(a={value:a}),a.$$fn=j(a.value)?a.value:function(){return a.value},a}function i(b,c,d){if(b.type&&c)throw new Error("Param '"+a+"' has two type configurations.");return c?c:b.type?b.type instanceof r?b.type:new r(b.type):"config"===d?v.any:v.string}function k(){var b={array:"search"===e?"auto":!1},c=a.match(/\[\]$/)?{array:!0}:{};return M(b,c,d).array}function l(a,b){var c=a.squash;if(!b||c===!1)return!1;if(!G(c)||null==c)return u;if(c===!0||I(c))return c;throw new Error("Invalid squash policy: '"+c+"'. Valid policies: false, true, or arbitrary string")}function p(a,b,d,e){var f,g,i=[{from:"",to:d||b?c:""},{from:null,to:d||b?c:""}];return f=K(a.replace)?a.replace:[],I(e)&&f.push({from:e,to:c}),g=n(f,function(a){return a.from}),m(i,function(a){return-1===h(g,a.from)}).concat(f)}function q(){if(!o)throw new Error("Injectable functions cannot be called at configuration time");return o.invoke(d.$$fn)}function s(a){function b(a){return function(b){return b.from===a}}function c(a){var c=n(m(w.replace,b(a)),function(a){return a.to});return c.length?c[0]:a}return a=c(a),G(a)?w.type.decode(a):q()}function t(){return"{Param:"+a+" "+b+" squash: '"+z+"' optional: "+y+"}"}var w=this;d=f(d),b=i(d,b,e);var x=k();b=x?b.$asArray(x,"search"===e):b,"string"!==b.name||x||"path"!==e||d.value!==c||(d.value="");var y=d.value!==c,z=l(d,y),A=p(d,x,y,z);M(this,{id:a,type:b,location:e,array:x,squash:z,replace:A,isOptional:y,value:s,dynamic:c,config:d,toString:t})},l.prototype={$$new:function(){return d(this,M(new l,{$$parent:this}))},$$keys:function(){for(var a=[],b=[],c=this,d=g(l.prototype);c;)b.push(c),c=c.$$parent;return b.reverse(),L(b,function(b){L(g(b),function(b){-1===h(a,b)&&-1===h(d,b)&&a.push(b)})}),a},$$values:function(a){var b={},c=this;return L(c.$$keys(),function(d){b[d]=c[d].value(a&&a[d])}),b},$$equals:function(a,b){var c=!0,d=this;return L(d.$$keys(),function(e){var f=a&&a[e],g=b&&b[e];d[e].type.equals(f,g)||(c=!1)}),c},$$validates:function(a){var b,c,d,e=!0,f=this;return L(this.$$keys(),function(g){d=f[g],c=a[g],b=!c&&d.isOptional,e=e&&(b||!!d.type.is(c))}),e},$$parent:c},this.ParamSet=l}function t(a,d){function e(a){var b=/^\^((?:\\[^a-zA-Z0-9]|[^\\\[\]\^$*+?.()|{}]+)*)/.exec(a.source);return null!=b?b[1].replace(/\\(.)/g,"$1"):""}function f(a,b){return a.replace(/\$(\$|\d{1,2})/,function(a,c){return b["$"===c?0:Number(c)]})}function g(a,b,c){if(!c)return!1;var d=a.invoke(b,b,{$match:c});return G(d)?d:!0}function h(d,e,f,g){function h(a,b,c){return"/"===p?a:b?p.slice(0,-1)+a:c?p.slice(1)+a:a}function m(a){function b(a){var b=a(f,d);return b?(I(b)&&d.replace().url(b),!0):!1}if(!a||!a.defaultPrevented){var e=o&&d.url()===o;if(o=c,e)return!0;var g,h=j.length;for(g=0;h>g;g++)if(b(j[g]))return;k&&b(k)}}function n(){return i=i||e.$on("$locationChangeSuccess",m)}var o,p=g.baseHref(),q=d.url();return l||n(),{sync:function(){m()},listen:function(){return n()},update:function(a){return a?void(q=d.url()):void(d.url()!==q&&(d.url(q),d.replace()))},push:function(a,b,e){d.url(a.format(b||{})),o=e&&e.$$avoidResync?d.url():c,e&&e.replace&&d.replace()},href:function(c,e,f){if(!c.validates(e))return null;var g=a.html5Mode();b.isObject(g)&&(g=g.enabled);var i=c.format(e);if(f=f||{},g||null===i||(i="#"+a.hashPrefix()+i),i=h(i,g,f.absolute),!f.absolute||!i)return i;var j=!g&&i?"/":"",k=d.port();return k=80===k||443===k?"":":"+k,[d.protocol(),"://",d.host(),k,j,i].join("")}}}var i,j=[],k=null,l=!1;this.rule=function(a){if(!H(a))throw new Error("'rule' must be a function");return j.push(a),this},this.otherwise=function(a){if(I(a)){var b=a;a=function(){return b}}else if(!H(a))throw new Error("'rule' must be a function");return k=a,this},this.when=function(a,b){var c,h=I(b);if(I(a)&&(a=d.compile(a)),!h&&!H(b)&&!K(b))throw new Error("invalid 'handler' in when()");var i={matcher:function(a,b){return h&&(c=d.compile(b),b=["$match",function(a){return c.format(a)}]),M(function(c,d){return g(c,b,a.exec(d.path(),d.search()))},{prefix:I(a.prefix)?a.prefix:""})},regex:function(a,b){if(a.global||a.sticky)throw new Error("when() RegExp must not be global or sticky");return h&&(c=b,b=["$match",function(a){return f(c,a)}]),M(function(c,d){return g(c,b,a.exec(d.path()))},{prefix:e(a)})}},j={matcher:d.isMatcher(a),regex:a instanceof RegExp};for(var k in j)if(j[k])return this.rule(i[k](a,b));throw new Error("invalid 'what' in when()")},this.deferIntercept=function(a){a===c&&(a=!0),l=a},this.$get=h,h.$inject=["$location","$rootScope","$injector","$browser"]}function u(a,e){function f(a){return 0===a.indexOf(".")||0===a.indexOf("^")}function l(a,b){if(!a)return c;var d=I(a),e=d?a:a.name,g=f(e);if(g){if(!b)throw new Error("No reference point given for path '"+e+"'");b=l(b);for(var h=e.split("."),i=0,j=h.length,k=b;j>i;i++)if(""!==h[i]||0!==i){if("^"!==h[i])break;if(!k.parent)throw new Error("Path '"+e+"' not valid for state '"+b.name+"'");k=k.parent}else k=b;h=h.slice(i).join("."),e=k.name+(k.name&&h?".":"")+h}var m=y[e];return!m||!d&&(d||m!==a&&m.self!==a)?c:m}function m(a,b){z[a]||(z[a]=[]),z[a].push(b)}function o(a){for(var b=z[a]||[];b.length;)p(b.shift())}function p(b){b=d(b,{self:b,resolve:b.resolve||{},toString:function(){return this.name}});var c=b.name;if(!I(c)||c.indexOf("@")>=0)throw new Error("State must have a valid name");if(y.hasOwnProperty(c))throw new Error("State '"+c+"'' is already defined");var e=-1!==c.indexOf(".")?c.substring(0,c.lastIndexOf(".")):I(b.parent)?b.parent:J(b.parent)&&I(b.parent.name)?b.parent.name:"";if(e&&!y[e])return m(e,b.self);for(var f in B)H(B[f])&&(b[f]=B[f](b,B.$delegates[f]));return y[c]=b,!b[A]&&b.url&&a.when(b.url,["$match","$stateParams",function(a,c){x.$current.navigable==b&&j(a,c)||x.transitionTo(b,a,{inherit:!0,location:!1})}]),o(c),b}function q(a){return a.indexOf("*")>-1}function r(a){var b=a.split("."),c=x.$current.name.split(".");if("**"===b[0]&&(c=c.slice(h(c,b[1])),c.unshift("**")),"**"===b[b.length-1]&&(c.splice(h(c,b[b.length-2])+1,Number.MAX_VALUE),c.push("**")),b.length!=c.length)return!1;for(var d=0,e=b.length;e>d;d++)"*"===b[d]&&(c[d]="*");return c.join("")===b.join("")}function s(a,b){return I(a)&&!G(b)?B[a]:H(b)&&I(a)?(B[a]&&!B.$delegates[a]&&(B.$delegates[a]=B[a]),B[a]=b,this):this}function t(a,b){return J(a)?b=a:b.name=a,p(b),this}function u(a,e,f,h,m,o,p){function s(b,c,d,f){var g=a.$broadcast("$stateNotFound",b,c,d);if(g.defaultPrevented)return p.update(),B;if(!g.retry)return null;if(f.$retry)return p.update(),C;var h=x.transition=e.when(g.retry);return h.then(function(){return h!==x.transition?u:(b.options.$retry=!0,x.transitionTo(b.to,b.toParams,b.options))},function(){return B}),p.update(),h}function t(a,c,d,g,i,j){var l=d?c:k(a.params.$$keys(),c),n={$stateParams:l};i.resolve=m.resolve(a.resolve,n,i.resolve,a);var o=[i.resolve.then(function(a){i.globals=a})];return g&&o.push(g),L(a.views,function(c,d){var e=c.resolve&&c.resolve!==a.resolve?c.resolve:{};e.$template=[function(){return f.load(d,{view:c,locals:n,params:l,notify:j.notify})||""}],o.push(m.resolve(e,n,i.resolve,a).then(function(f){if(H(c.controllerProvider)||K(c.controllerProvider)){var g=b.extend({},e,n);f.$$controller=h.invoke(c.controllerProvider,null,g)}else f.$$controller=c.controller;f.$$state=a,f.$$controllerAs=c.controllerAs,i[d]=f}))}),e.all(o).then(function(){return i})}var u=e.reject(new Error("transition superseded")),z=e.reject(new Error("transition prevented")),B=e.reject(new Error("transition aborted")),C=e.reject(new Error("transition failed"));return w.locals={resolve:null,globals:{$stateParams:{}}},x={params:{},current:w.self,$current:w,transition:null},x.reload=function(){return x.transitionTo(x.current,o,{reload:!0,inherit:!1,notify:!0})},x.go=function(a,b,c){return x.transitionTo(a,b,M({inherit:!0,relative:x.$current},c))},x.transitionTo=function(b,c,f){c=c||{},f=M({location:!0,inherit:!1,relative:null,notify:!0,reload:!1,$retry:!1},f||{});var g,j=x.$current,m=x.params,n=j.path,q=l(b,f.relative);if(!G(q)){var r={to:b,toParams:c,options:f},y=s(r,j.self,m,f);if(y)return y;if(b=r.to,c=r.toParams,f=r.options,q=l(b,f.relative),!G(q)){if(!f.relative)throw new Error("No such state '"+b+"'");throw new Error("Could not resolve '"+b+"' from state '"+f.relative+"'")}}if(q[A])throw new Error("Cannot transition to abstract state '"+b+"'");if(f.inherit&&(c=i(o,c||{},x.$current,q)),!q.params.$$validates(c))return C;c=q.params.$$values(c),b=q;var B=b.path,D=0,E=B[D],F=w.locals,H=[];if(!f.reload)for(;E&&E===n[D]&&E.ownParams.$$equals(c,m);)F=H[D]=E.locals,D++,E=B[D];if(v(b,j,F,f))return b.self.reloadOnSearch!==!1&&p.update(),x.transition=null,e.when(x.current);if(c=k(b.params.$$keys(),c||{}),f.notify&&a.$broadcast("$stateChangeStart",b.self,c,j.self,m).defaultPrevented)return p.update(),z;for(var I=e.when(F),J=D;J=D;d--)g=n[d],g.self.onExit&&h.invoke(g.self.onExit,g.self,g.locals.globals),g.locals=null;for(d=D;d=0?e:e+"@"+(f?f.state.name:"")}function A(a,b){var c,d=a.match(/^\s*({[^}]*})\s*$/);if(d&&(a=b+"("+d[1]+")"),c=a.replace(/\n/g," ").match(/^([^(]+?)\s*(\((.*)\))?$/),!c||4!==c.length)throw new Error("Invalid state ref '"+a+"'");return{state:c[1],paramExpr:c[3]||null}}function B(a){var b=a.parent().inheritedData("$uiView");return b&&b.state&&b.state.name?b.state:void 0}function C(a,c){var d=["location","inherit","reload"];return{restrict:"A",require:["?^uiSrefActive","?^uiSrefActiveEq"],link:function(e,f,g,h){var i=A(g.uiSref,a.current.name),j=null,k=B(f)||a.$current,l=null,m="A"===f.prop("tagName"),n="FORM"===f[0].nodeName,o=n?"action":"href",p=!0,q={relative:k,inherit:!0},r=e.$eval(g.uiSrefOpts)||{};b.forEach(d,function(a){a in r&&(q[a]=r[a])});var s=function(c){if(c&&(j=b.copy(c)),p){l=a.href(i.state,j,q);var d=h[1]||h[0];return d&&d.$$setStateInfo(i.state,j),null===l?(p=!1,!1):void g.$set(o,l)}};i.paramExpr&&(e.$watch(i.paramExpr,function(a){a!==j&&s(a)},!0),j=b.copy(e.$eval(i.paramExpr))),s(),n||f.bind("click",function(b){var d=b.which||b.button;if(!(d>1||b.ctrlKey||b.metaKey||b.shiftKey||f.attr("target"))){var e=c(function(){a.go(i.state,j,q)});b.preventDefault();var g=m&&!l?1:0;b.preventDefault=function(){g--<=0&&c.cancel(e)}}})}}}function D(a,b,c){return{restrict:"A",controller:["$scope","$element","$attrs",function(b,d,e){function f(){g()?d.addClass(j):d.removeClass(j)}function g(){return"undefined"!=typeof e.uiSrefActiveEq?h&&a.is(h.name,i):h&&a.includes(h.name,i)}var h,i,j;j=c(e.uiSrefActiveEq||e.uiSrefActive||"",!1)(b),this.$$setStateInfo=function(b,c){h=a.get(b,B(d)),i=c,f()},b.$on("$stateChangeSuccess",f)}]}}function E(a){var b=function(b){return a.is(b)};return b.$stateful=!0,b}function F(a){var b=function(b){return a.includes(b)};return b.$stateful=!0,b}var G=b.isDefined,H=b.isFunction,I=b.isString,J=b.isObject,K=b.isArray,L=b.forEach,M=b.extend,N=b.copy;b.module("ui.router.util",["ng"]),b.module("ui.router.router",["ui.router.util"]),b.module("ui.router.state",["ui.router.router","ui.router.util"]),b.module("ui.router",["ui.router.state"]),b.module("ui.router.compat",["ui.router"]),o.$inject=["$q","$injector"],b.module("ui.router.util").service("$resolve",o),p.$inject=["$http","$templateCache","$injector"],b.module("ui.router.util").service("$templateFactory",p);var O;q.prototype.concat=function(a,b){var c={caseInsensitive:O.caseInsensitive(),strict:O.strictMode(),squash:O.defaultSquashPolicy()};return new q(this.sourcePath+a+this.sourceSearch,M(c,b),this)},q.prototype.toString=function(){return this.source},q.prototype.exec=function(a,b){function c(a){function b(a){return a.split("").reverse().join("")}function c(a){return a.replace(/\\-/,"-")}var d=b(a).split(/-(?!\\)/),e=n(d,b);return n(e,c).reverse()}var d=this.regexp.exec(a);if(!d)return null;b=b||{};var e,f,g,h=this.parameters(),i=h.length,j=this.segments.length-1,k={};if(j!==d.length-1)throw new Error("Unbalanced capture group in route '"+this.source+"'");for(e=0;j>e;e++){g=h[e];var l=this.params[g],m=d[e+1];for(f=0;fe;e++)g=h[e],k[g]=this.params[g].value(b[g]);return k},q.prototype.parameters=function(a){return G(a)?this.params[a]||null:this.$$paramNames},q.prototype.validates=function(a){return this.params.$$validates(a)},q.prototype.format=function(a){function b(a){return encodeURIComponent(a).replace(/-/g,function(a){return"%5C%"+a.charCodeAt(0).toString(16).toUpperCase()})}a=a||{};var c=this.segments,d=this.parameters(),e=this.params;if(!this.validates(a))return null;var f,g=!1,h=c.length-1,i=d.length,j=c[0];for(f=0;i>f;f++){var k=h>f,l=d[f],m=e[l],o=m.value(a[l]),p=m.isOptional&&m.type.equals(m.value(),o),q=p?m.squash:!1,r=m.type.encode(o);if(k){var s=c[f+1];if(q===!1)null!=r&&(j+=K(r)?n(r,b).join("-"):encodeURIComponent(r)),j+=s;else if(q===!0){var t=j.match(/\/$/)?/\/?(.*)/:/(.*)/;j+=s.match(t)[1]}else I(q)&&(j+=q+s)}else{if(null==r||p&&q!==!1)continue;K(r)||(r=[r]),r=n(r,encodeURIComponent).join("&"+l+"="),j+=(g?"&":"?")+(l+"="+r),g=!0}}return j},r.prototype.is=function(){return!0},r.prototype.encode=function(a){return a},r.prototype.decode=function(a){return a},r.prototype.equals=function(a,b){return a==b},r.prototype.$subPattern=function(){var a=this.pattern.toString();return a.substr(1,a.length-2)},r.prototype.pattern=/.*/,r.prototype.toString=function(){return"{Type:"+this.name+"}"},r.prototype.$asArray=function(a,b){function d(a,b){function d(a,b){return function(){return a[b].apply(a,arguments)}}function e(a){return K(a)?a:G(a)?[a]:[]}function f(a){switch(a.length){case 0:return c;case 1:return"auto"===b?a[0]:a;default:return a}}function g(a){return!a}function h(a,b){return function(c){c=e(c);var d=n(c,a);return b===!0?0===m(d,g).length:f(d)}}function i(a){return function(b,c){var d=e(b),f=e(c);if(d.length!==f.length)return!1;for(var g=0;g>> 0, from = Number(arguments[2]) || 0; + from = (from < 0) ? Math.ceil(from) : Math.floor(from); + + if (from < 0) from += len; + + for (; from < len; from++) { + if (from in array && array[from] === value) return from; + } + return -1; +} + +/** + * Merges a set of parameters with all parameters inherited between the common parents of the + * current state and a given destination state. + * + * @param {Object} currentParams The value of the current state parameters ($stateParams). + * @param {Object} newParams The set of parameters which will be composited with inherited params. + * @param {Object} $current Internal definition of object representing the current state. + * @param {Object} $to Internal definition of object representing state to transition to. + */ +function inheritParams(currentParams, newParams, $current, $to) { + var parents = ancestors($current, $to), parentParams, inherited = {}, inheritList = []; + + for (var i in parents) { + if (!parents[i].params) continue; + parentParams = objectKeys(parents[i].params); + if (!parentParams.length) continue; + + for (var j in parentParams) { + if (indexOf(inheritList, parentParams[j]) >= 0) continue; + inheritList.push(parentParams[j]); + inherited[parentParams[j]] = currentParams[parentParams[j]]; + } + } + return extend({}, inherited, newParams); +} + +/** + * Performs a non-strict comparison of the subset of two objects, defined by a list of keys. + * + * @param {Object} a The first object. + * @param {Object} b The second object. + * @param {Array} keys The list of keys within each object to compare. If the list is empty or not specified, + * it defaults to the list of keys in `a`. + * @return {Boolean} Returns `true` if the keys match, otherwise `false`. + */ +function equalForKeys(a, b, keys) { + if (!keys) { + keys = []; + for (var n in a) keys.push(n); // Used instead of Object.keys() for IE8 compatibility + } + + for (var i=0; i + * + * + * + * + * + * + * + * + * + * + * + * + */ +angular.module('ui.router', ['ui.router.state']); + +angular.module('ui.router.compat', ['ui.router']); diff --git a/public/admincp/bower_components/angular-ui-router/src/resolve.js b/public/admincp/bower_components/angular-ui-router/src/resolve.js new file mode 100644 index 000000000..f1c179009 --- /dev/null +++ b/public/admincp/bower_components/angular-ui-router/src/resolve.js @@ -0,0 +1,252 @@ +/** + * @ngdoc object + * @name ui.router.util.$resolve + * + * @requires $q + * @requires $injector + * + * @description + * Manages resolution of (acyclic) graphs of promises. + */ +$Resolve.$inject = ['$q', '$injector']; +function $Resolve( $q, $injector) { + + var VISIT_IN_PROGRESS = 1, + VISIT_DONE = 2, + NOTHING = {}, + NO_DEPENDENCIES = [], + NO_LOCALS = NOTHING, + NO_PARENT = extend($q.when(NOTHING), { $$promises: NOTHING, $$values: NOTHING }); + + + /** + * @ngdoc function + * @name ui.router.util.$resolve#study + * @methodOf ui.router.util.$resolve + * + * @description + * Studies a set of invocables that are likely to be used multiple times. + *
      +   * $resolve.study(invocables)(locals, parent, self)
      +   * 
      + * is equivalent to + *
      +   * $resolve.resolve(invocables, locals, parent, self)
      +   * 
      + * but the former is more efficient (in fact `resolve` just calls `study` + * internally). + * + * @param {object} invocables Invocable objects + * @return {function} a function to pass in locals, parent and self + */ + this.study = function (invocables) { + if (!isObject(invocables)) throw new Error("'invocables' must be an object"); + var invocableKeys = objectKeys(invocables || {}); + + // Perform a topological sort of invocables to build an ordered plan + var plan = [], cycle = [], visited = {}; + function visit(value, key) { + if (visited[key] === VISIT_DONE) return; + + cycle.push(key); + if (visited[key] === VISIT_IN_PROGRESS) { + cycle.splice(0, indexOf(cycle, key)); + throw new Error("Cyclic dependency: " + cycle.join(" -> ")); + } + visited[key] = VISIT_IN_PROGRESS; + + if (isString(value)) { + plan.push(key, [ function() { return $injector.get(value); }], NO_DEPENDENCIES); + } else { + var params = $injector.annotate(value); + forEach(params, function (param) { + if (param !== key && invocables.hasOwnProperty(param)) visit(invocables[param], param); + }); + plan.push(key, value, params); + } + + cycle.pop(); + visited[key] = VISIT_DONE; + } + forEach(invocables, visit); + invocables = cycle = visited = null; // plan is all that's required + + function isResolve(value) { + return isObject(value) && value.then && value.$$promises; + } + + return function (locals, parent, self) { + if (isResolve(locals) && self === undefined) { + self = parent; parent = locals; locals = null; + } + if (!locals) locals = NO_LOCALS; + else if (!isObject(locals)) { + throw new Error("'locals' must be an object"); + } + if (!parent) parent = NO_PARENT; + else if (!isResolve(parent)) { + throw new Error("'parent' must be a promise returned by $resolve.resolve()"); + } + + // To complete the overall resolution, we have to wait for the parent + // promise and for the promise for each invokable in our plan. + var resolution = $q.defer(), + result = resolution.promise, + promises = result.$$promises = {}, + values = extend({}, locals), + wait = 1 + plan.length/3, + merged = false; + + function done() { + // Merge parent values we haven't got yet and publish our own $$values + if (!--wait) { + if (!merged) merge(values, parent.$$values); + result.$$values = values; + result.$$promises = result.$$promises || true; // keep for isResolve() + delete result.$$inheritedValues; + resolution.resolve(values); + } + } + + function fail(reason) { + result.$$failure = reason; + resolution.reject(reason); + } + + // Short-circuit if parent has already failed + if (isDefined(parent.$$failure)) { + fail(parent.$$failure); + return result; + } + + if (parent.$$inheritedValues) { + merge(values, omit(parent.$$inheritedValues, invocableKeys)); + } + + // Merge parent values if the parent has already resolved, or merge + // parent promises and wait if the parent resolve is still in progress. + extend(promises, parent.$$promises); + if (parent.$$values) { + merged = merge(values, omit(parent.$$values, invocableKeys)); + result.$$inheritedValues = omit(parent.$$values, invocableKeys); + done(); + } else { + if (parent.$$inheritedValues) { + result.$$inheritedValues = omit(parent.$$inheritedValues, invocableKeys); + } + parent.then(done, fail); + } + + // Process each invocable in the plan, but ignore any where a local of the same name exists. + for (var i=0, ii=plan.length; i= 0) throw new Error("State must have a valid name"); + if (states.hasOwnProperty(name)) throw new Error("State '" + name + "'' is already defined"); + + // Get parent name + var parentName = (name.indexOf('.') !== -1) ? name.substring(0, name.lastIndexOf('.')) + : (isString(state.parent)) ? state.parent + : (isObject(state.parent) && isString(state.parent.name)) ? state.parent.name + : ''; + + // If parent is not registered yet, add state to queue and register later + if (parentName && !states[parentName]) { + return queueState(parentName, state.self); + } + + for (var key in stateBuilder) { + if (isFunction(stateBuilder[key])) state[key] = stateBuilder[key](state, stateBuilder.$delegates[key]); + } + states[name] = state; + + // Register the state in the global state list and with $urlRouter if necessary. + if (!state[abstractKey] && state.url) { + $urlRouterProvider.when(state.url, ['$match', '$stateParams', function ($match, $stateParams) { + if ($state.$current.navigable != state || !equalForKeys($match, $stateParams)) { + $state.transitionTo(state, $match, { inherit: true, location: false }); + } + }]); + } + + // Register any queued children + flushQueuedChildren(name); + + return state; + } + + // Checks text to see if it looks like a glob. + function isGlob (text) { + return text.indexOf('*') > -1; + } + + // Returns true if glob matches current $state name. + function doesStateMatchGlob (glob) { + var globSegments = glob.split('.'), + segments = $state.$current.name.split('.'); + + //match greedy starts + if (globSegments[0] === '**') { + segments = segments.slice(indexOf(segments, globSegments[1])); + segments.unshift('**'); + } + //match greedy ends + if (globSegments[globSegments.length - 1] === '**') { + segments.splice(indexOf(segments, globSegments[globSegments.length - 2]) + 1, Number.MAX_VALUE); + segments.push('**'); + } + + if (globSegments.length != segments.length) { + return false; + } + + //match single stars + for (var i = 0, l = globSegments.length; i < l; i++) { + if (globSegments[i] === '*') { + segments[i] = '*'; + } + } + + return segments.join('') === globSegments.join(''); + } + + + // Implicit root state that is always active + root = registerState({ + name: '', + url: '^', + views: null, + 'abstract': true + }); + root.navigable = null; + + + /** + * @ngdoc function + * @name ui.router.state.$stateProvider#decorator + * @methodOf ui.router.state.$stateProvider + * + * @description + * Allows you to extend (carefully) or override (at your own peril) the + * `stateBuilder` object used internally by `$stateProvider`. This can be used + * to add custom functionality to ui-router, for example inferring templateUrl + * based on the state name. + * + * When passing only a name, it returns the current (original or decorated) builder + * function that matches `name`. + * + * The builder functions that can be decorated are listed below. Though not all + * necessarily have a good use case for decoration, that is up to you to decide. + * + * In addition, users can attach custom decorators, which will generate new + * properties within the state's internal definition. There is currently no clear + * use-case for this beyond accessing internal states (i.e. $state.$current), + * however, expect this to become increasingly relevant as we introduce additional + * meta-programming features. + * + * **Warning**: Decorators should not be interdependent because the order of + * execution of the builder functions in non-deterministic. Builder functions + * should only be dependent on the state definition object and super function. + * + * + * Existing builder functions and current return values: + * + * - **parent** `{object}` - returns the parent state object. + * - **data** `{object}` - returns state data, including any inherited data that is not + * overridden by own values (if any). + * - **url** `{object}` - returns a {@link ui.router.util.type:UrlMatcher UrlMatcher} + * or `null`. + * - **navigable** `{object}` - returns closest ancestor state that has a URL (aka is + * navigable). + * - **params** `{object}` - returns an array of state params that are ensured to + * be a super-set of parent's params. + * - **views** `{object}` - returns a views object where each key is an absolute view + * name (i.e. "viewName@stateName") and each value is the config object + * (template, controller) for the view. Even when you don't use the views object + * explicitly on a state config, one is still created for you internally. + * So by decorating this builder function you have access to decorating template + * and controller properties. + * - **ownParams** `{object}` - returns an array of params that belong to the state, + * not including any params defined by ancestor states. + * - **path** `{string}` - returns the full path from the root down to this state. + * Needed for state activation. + * - **includes** `{object}` - returns an object that includes every state that + * would pass a `$state.includes()` test. + * + * @example + *
      +   * // Override the internal 'views' builder with a function that takes the state
      +   * // definition, and a reference to the internal function being overridden:
      +   * $stateProvider.decorator('views', function (state, parent) {
      +   *   var result = {},
      +   *       views = parent(state);
      +   *
      +   *   angular.forEach(views, function (config, name) {
      +   *     var autoName = (state.name + '.' + name).replace('.', '/');
      +   *     config.templateUrl = config.templateUrl || '/partials/' + autoName + '.html';
      +   *     result[name] = config;
      +   *   });
      +   *   return result;
      +   * });
      +   *
      +   * $stateProvider.state('home', {
      +   *   views: {
      +   *     'contact.list': { controller: 'ListController' },
      +   *     'contact.item': { controller: 'ItemController' }
      +   *   }
      +   * });
      +   *
      +   * // ...
      +   *
      +   * $state.go('home');
      +   * // Auto-populates list and item views with /partials/home/contact/list.html,
      +   * // and /partials/home/contact/item.html, respectively.
      +   * 
      + * + * @param {string} name The name of the builder function to decorate. + * @param {object} func A function that is responsible for decorating the original + * builder function. The function receives two parameters: + * + * - `{object}` - state - The state config object. + * - `{object}` - super - The original builder function. + * + * @return {object} $stateProvider - $stateProvider instance + */ + this.decorator = decorator; + function decorator(name, func) { + /*jshint validthis: true */ + if (isString(name) && !isDefined(func)) { + return stateBuilder[name]; + } + if (!isFunction(func) || !isString(name)) { + return this; + } + if (stateBuilder[name] && !stateBuilder.$delegates[name]) { + stateBuilder.$delegates[name] = stateBuilder[name]; + } + stateBuilder[name] = func; + return this; + } + + /** + * @ngdoc function + * @name ui.router.state.$stateProvider#state + * @methodOf ui.router.state.$stateProvider + * + * @description + * Registers a state configuration under a given state name. The stateConfig object + * has the following acceptable properties. + * + * @param {string} name A unique state name, e.g. "home", "about", "contacts". + * To create a parent/child state use a dot, e.g. "about.sales", "home.newest". + * @param {object} stateConfig State configuration object. + * @param {string|function=} stateConfig.template + * + * html template as a string or a function that returns + * an html template as a string which should be used by the uiView directives. This property + * takes precedence over templateUrl. + * + * If `template` is a function, it will be called with the following parameters: + * + * - {array.<object>} - state parameters extracted from the current $location.path() by + * applying the current state + * + *
      template:
      +   *   "

      inline template definition

      " + + * "
      "
      + *
      template: function(params) {
      +   *       return "

      generated template

      "; }
      + * + * + * @param {string|function=} stateConfig.templateUrl + * + * + * path or function that returns a path to an html + * template that should be used by uiView. + * + * If `templateUrl` is a function, it will be called with the following parameters: + * + * - {array.<object>} - state parameters extracted from the current $location.path() by + * applying the current state + * + *
      templateUrl: "home.html"
      + *
      templateUrl: function(params) {
      +   *     return myTemplates[params.pageId]; }
      + * + * @param {function=} stateConfig.templateProvider + * + * Provider function that returns HTML content string. + *
       templateProvider:
      +   *       function(MyTemplateService, params) {
      +   *         return MyTemplateService.getTemplate(params.pageId);
      +   *       }
      + * + * @param {string|function=} stateConfig.controller + * + * + * Controller fn that should be associated with newly + * related scope or the name of a registered controller if passed as a string. + * Optionally, the ControllerAs may be declared here. + *
      controller: "MyRegisteredController"
      + *
      controller:
      +   *     "MyRegisteredController as fooCtrl"}
      + *
      controller: function($scope, MyService) {
      +   *     $scope.data = MyService.getData(); }
      + * + * @param {function=} stateConfig.controllerProvider + * + * + * Injectable provider function that returns the actual controller or string. + *
      controllerProvider:
      +   *   function(MyResolveData) {
      +   *     if (MyResolveData.foo)
      +   *       return "FooCtrl"
      +   *     else if (MyResolveData.bar)
      +   *       return "BarCtrl";
      +   *     else return function($scope) {
      +   *       $scope.baz = "Qux";
      +   *     }
      +   *   }
      + * + * @param {string=} stateConfig.controllerAs + * + * + * A controller alias name. If present the controller will be + * published to scope under the controllerAs name. + *
      controllerAs: "myCtrl"
      + * + * @param {object=} stateConfig.resolve + * + * + * An optional map<string, function> of dependencies which + * should be injected into the controller. If any of these dependencies are promises, + * the router will wait for them all to be resolved before the controller is instantiated. + * If all the promises are resolved successfully, the $stateChangeSuccess event is fired + * and the values of the resolved promises are injected into any controllers that reference them. + * If any of the promises are rejected the $stateChangeError event is fired. + * + * The map object is: + * + * - key - {string}: name of dependency to be injected into controller + * - factory - {string|function}: If string then it is alias for service. Otherwise if function, + * it is injected and return value it treated as dependency. If result is a promise, it is + * resolved before its value is injected into controller. + * + *
      resolve: {
      +   *     myResolve1:
      +   *       function($http, $stateParams) {
      +   *         return $http.get("/api/foos/"+stateParams.fooID);
      +   *       }
      +   *     }
      + * + * @param {string=} stateConfig.url + * + * + * A url fragment with optional parameters. When a state is navigated or + * transitioned to, the `$stateParams` service will be populated with any + * parameters that were passed. + * + * examples: + *
      url: "/home"
      +   * url: "/users/:userid"
      +   * url: "/books/{bookid:[a-zA-Z_-]}"
      +   * url: "/books/{categoryid:int}"
      +   * url: "/books/{publishername:string}/{categoryid:int}"
      +   * url: "/messages?before&after"
      +   * url: "/messages?{before:date}&{after:date}"
      + * url: "/messages/:mailboxid?{before:date}&{after:date}" + * + * @param {object=} stateConfig.views + * + * an optional map<string, object> which defined multiple views, or targets views + * manually/explicitly. + * + * Examples: + * + * Targets three named `ui-view`s in the parent state's template + *
      views: {
      +   *     header: {
      +   *       controller: "headerCtrl",
      +   *       templateUrl: "header.html"
      +   *     }, body: {
      +   *       controller: "bodyCtrl",
      +   *       templateUrl: "body.html"
      +   *     }, footer: {
      +   *       controller: "footCtrl",
      +   *       templateUrl: "footer.html"
      +   *     }
      +   *   }
      + * + * Targets named `ui-view="header"` from grandparent state 'top''s template, and named `ui-view="body" from parent state's template. + *
      views: {
      +   *     'header@top': {
      +   *       controller: "msgHeaderCtrl",
      +   *       templateUrl: "msgHeader.html"
      +   *     }, 'body': {
      +   *       controller: "messagesCtrl",
      +   *       templateUrl: "messages.html"
      +   *     }
      +   *   }
      + * + * @param {boolean=} [stateConfig.abstract=false] + * + * An abstract state will never be directly activated, + * but can provide inherited properties to its common children states. + *
      abstract: true
      + * + * @param {function=} stateConfig.onEnter + * + * + * Callback function for when a state is entered. Good way + * to trigger an action or dispatch an event, such as opening a dialog. + * If minifying your scripts, make sure to explictly annotate this function, + * because it won't be automatically annotated by your build tools. + * + *
      onEnter: function(MyService, $stateParams) {
      +   *     MyService.foo($stateParams.myParam);
      +   * }
      + * + * @param {function=} stateConfig.onExit + * + * + * Callback function for when a state is exited. Good way to + * trigger an action or dispatch an event, such as opening a dialog. + * If minifying your scripts, make sure to explictly annotate this function, + * because it won't be automatically annotated by your build tools. + * + *
      onExit: function(MyService, $stateParams) {
      +   *     MyService.cleanup($stateParams.myParam);
      +   * }
      + * + * @param {boolean=} [stateConfig.reloadOnSearch=true] + * + * + * If `false`, will not retrigger the same state + * just because a search/query parameter has changed (via $location.search() or $location.hash()). + * Useful for when you'd like to modify $location.search() without triggering a reload. + *
      reloadOnSearch: false
      + * + * @param {object=} stateConfig.data + * + * + * Arbitrary data object, useful for custom configuration. The parent state's `data` is + * prototypally inherited. In other words, adding a data property to a state adds it to + * the entire subtree via prototypal inheritance. + * + *
      data: {
      +   *     requiredRole: 'foo'
      +   * } 
      + * + * @param {object=} stateConfig.params + * + * + * A map which optionally configures parameters declared in the `url`, or + * defines additional non-url parameters. For each parameter being + * configured, add a configuration object keyed to the name of the parameter. + * + * Each parameter configuration object may contain the following properties: + * + * - ** value ** - {object|function=}: specifies the default value for this + * parameter. This implicitly sets this parameter as optional. + * + * When UI-Router routes to a state and no value is + * specified for this parameter in the URL or transition, the + * default value will be used instead. If `value` is a function, + * it will be injected and invoked, and the return value used. + * + * *Note*: `undefined` is treated as "no default value" while `null` + * is treated as "the default value is `null`". + * + * *Shorthand*: If you only need to configure the default value of the + * parameter, you may use a shorthand syntax. In the **`params`** + * map, instead mapping the param name to a full parameter configuration + * object, simply set map it to the default parameter value, e.g.: + * + *
      // define a parameter's default value
      +   * params: {
      +   *     param1: { value: "defaultValue" }
      +   * }
      +   * // shorthand default values
      +   * params: {
      +   *     param1: "defaultValue",
      +   *     param2: "param2Default"
      +   * }
      + * + * - ** array ** - {boolean=}: *(default: false)* If true, the param value will be + * treated as an array of values. If you specified a Type, the value will be + * treated as an array of the specified Type. Note: query parameter values + * default to a special `"auto"` mode. + * + * For query parameters in `"auto"` mode, if multiple values for a single parameter + * are present in the URL (e.g.: `/foo?bar=1&bar=2&bar=3`) then the values + * are mapped to an array (e.g.: `{ foo: [ '1', '2', '3' ] }`). However, if + * only one value is present (e.g.: `/foo?bar=1`) then the value is treated as single + * value (e.g.: `{ foo: '1' }`). + * + *
      params: {
      +   *     param1: { array: true }
      +   * }
      + * + * - ** squash ** - {bool|string=}: `squash` configures how a default parameter value is represented in the URL when + * the current parameter value is the same as the default value. If `squash` is not set, it uses the + * configured default squash policy. + * (See {@link ui.router.util.$urlMatcherFactory#methods_defaultSquashPolicy `defaultSquashPolicy()`}) + * + * There are three squash settings: + * + * - false: The parameter's default value is not squashed. It is encoded and included in the URL + * - true: The parameter's default value is omitted from the URL. If the parameter is preceeded and followed + * by slashes in the state's `url` declaration, then one of those slashes are omitted. + * This can allow for cleaner looking URLs. + * - `""`: The parameter's default value is replaced with an arbitrary placeholder of your choice. + * + *
      params: {
      +   *     param1: {
      +   *       value: "defaultId",
      +   *       squash: true
      +   * } }
      +   * // squash "defaultValue" to "~"
      +   * params: {
      +   *     param1: {
      +   *       value: "defaultValue",
      +   *       squash: "~"
      +   * } }
      +   * 
      + * + * + * @example + *
      +   * // Some state name examples
      +   *
      +   * // stateName can be a single top-level name (must be unique).
      +   * $stateProvider.state("home", {});
      +   *
      +   * // Or it can be a nested state name. This state is a child of the
      +   * // above "home" state.
      +   * $stateProvider.state("home.newest", {});
      +   *
      +   * // Nest states as deeply as needed.
      +   * $stateProvider.state("home.newest.abc.xyz.inception", {});
      +   *
      +   * // state() returns $stateProvider, so you can chain state declarations.
      +   * $stateProvider
      +   *   .state("home", {})
      +   *   .state("about", {})
      +   *   .state("contacts", {});
      +   * 
      + * + */ + this.state = state; + function state(name, definition) { + /*jshint validthis: true */ + if (isObject(name)) definition = name; + else definition.name = name; + registerState(definition); + return this; + } + + /** + * @ngdoc object + * @name ui.router.state.$state + * + * @requires $rootScope + * @requires $q + * @requires ui.router.state.$view + * @requires $injector + * @requires ui.router.util.$resolve + * @requires ui.router.state.$stateParams + * @requires ui.router.router.$urlRouter + * + * @property {object} params A param object, e.g. {sectionId: section.id)}, that + * you'd like to test against the current active state. + * @property {object} current A reference to the state's config object. However + * you passed it in. Useful for accessing custom data. + * @property {object} transition Currently pending transition. A promise that'll + * resolve or reject. + * + * @description + * `$state` service is responsible for representing states as well as transitioning + * between them. It also provides interfaces to ask for current state or even states + * you're coming from. + */ + this.$get = $get; + $get.$inject = ['$rootScope', '$q', '$view', '$injector', '$resolve', '$stateParams', '$urlRouter', '$location', '$urlMatcherFactory']; + function $get( $rootScope, $q, $view, $injector, $resolve, $stateParams, $urlRouter, $location, $urlMatcherFactory) { + + var TransitionSuperseded = $q.reject(new Error('transition superseded')); + var TransitionPrevented = $q.reject(new Error('transition prevented')); + var TransitionAborted = $q.reject(new Error('transition aborted')); + var TransitionFailed = $q.reject(new Error('transition failed')); + + // Handles the case where a state which is the target of a transition is not found, and the user + // can optionally retry or defer the transition + function handleRedirect(redirect, state, params, options) { + /** + * @ngdoc event + * @name ui.router.state.$state#$stateNotFound + * @eventOf ui.router.state.$state + * @eventType broadcast on root scope + * @description + * Fired when a requested state **cannot be found** using the provided state name during transition. + * The event is broadcast allowing any handlers a single chance to deal with the error (usually by + * lazy-loading the unfound state). A special `unfoundState` object is passed to the listener handler, + * you can see its three properties in the example. You can use `event.preventDefault()` to abort the + * transition and the promise returned from `go` will be rejected with a `'transition aborted'` value. + * + * @param {Object} event Event object. + * @param {Object} unfoundState Unfound State information. Contains: `to, toParams, options` properties. + * @param {State} fromState Current state object. + * @param {Object} fromParams Current state params. + * + * @example + * + *
      +       * // somewhere, assume lazy.state has not been defined
      +       * $state.go("lazy.state", {a:1, b:2}, {inherit:false});
      +       *
      +       * // somewhere else
      +       * $scope.$on('$stateNotFound',
      +       * function(event, unfoundState, fromState, fromParams){
      +       *     console.log(unfoundState.to); // "lazy.state"
      +       *     console.log(unfoundState.toParams); // {a:1, b:2}
      +       *     console.log(unfoundState.options); // {inherit:false} + default options
      +       * })
      +       * 
      + */ + var evt = $rootScope.$broadcast('$stateNotFound', redirect, state, params); + + if (evt.defaultPrevented) { + $urlRouter.update(); + return TransitionAborted; + } + + if (!evt.retry) { + return null; + } + + // Allow the handler to return a promise to defer state lookup retry + if (options.$retry) { + $urlRouter.update(); + return TransitionFailed; + } + var retryTransition = $state.transition = $q.when(evt.retry); + + retryTransition.then(function() { + if (retryTransition !== $state.transition) return TransitionSuperseded; + redirect.options.$retry = true; + return $state.transitionTo(redirect.to, redirect.toParams, redirect.options); + }, function() { + return TransitionAborted; + }); + $urlRouter.update(); + + return retryTransition; + } + + root.locals = { resolve: null, globals: { $stateParams: {} } }; + + $state = { + params: {}, + current: root.self, + $current: root, + transition: null + }; + + /** + * @ngdoc function + * @name ui.router.state.$state#reload + * @methodOf ui.router.state.$state + * + * @description + * A method that force reloads the current state. All resolves are re-resolved, events are not re-fired, + * and controllers reinstantiated (bug with controllers reinstantiating right now, fixing soon). + * + * @example + *
      +     * var app angular.module('app', ['ui.router']);
      +     *
      +     * app.controller('ctrl', function ($scope, $state) {
      +     *   $scope.reload = function(){
      +     *     $state.reload();
      +     *   }
      +     * });
      +     * 
      + * + * `reload()` is just an alias for: + *
      +     * $state.transitionTo($state.current, $stateParams, { 
      +     *   reload: true, inherit: false, notify: true
      +     * });
      +     * 
      + * + * @returns {promise} A promise representing the state of the new transition. See + * {@link ui.router.state.$state#methods_go $state.go}. + */ + $state.reload = function reload() { + return $state.transitionTo($state.current, $stateParams, { reload: true, inherit: false, notify: true }); + }; + + /** + * @ngdoc function + * @name ui.router.state.$state#go + * @methodOf ui.router.state.$state + * + * @description + * Convenience method for transitioning to a new state. `$state.go` calls + * `$state.transitionTo` internally but automatically sets options to + * `{ location: true, inherit: true, relative: $state.$current, notify: true }`. + * This allows you to easily use an absolute or relative to path and specify + * only the parameters you'd like to update (while letting unspecified parameters + * inherit from the currently active ancestor states). + * + * @example + *
      +     * var app = angular.module('app', ['ui.router']);
      +     *
      +     * app.controller('ctrl', function ($scope, $state) {
      +     *   $scope.changeState = function () {
      +     *     $state.go('contact.detail');
      +     *   };
      +     * });
      +     * 
      + * + * + * @param {string} to Absolute state name or relative state path. Some examples: + * + * - `$state.go('contact.detail')` - will go to the `contact.detail` state + * - `$state.go('^')` - will go to a parent state + * - `$state.go('^.sibling')` - will go to a sibling state + * - `$state.go('.child.grandchild')` - will go to grandchild state + * + * @param {object=} params A map of the parameters that will be sent to the state, + * will populate $stateParams. Any parameters that are not specified will be inherited from currently + * defined parameters. This allows, for example, going to a sibling state that shares parameters + * specified in a parent state. Parameter inheritance only works between common ancestor states, I.e. + * transitioning to a sibling will get you the parameters for all parents, transitioning to a child + * will get you all current parameters, etc. + * @param {object=} options Options object. The options are: + * + * - **`location`** - {boolean=true|string=} - If `true` will update the url in the location bar, if `false` + * will not. If string, must be `"replace"`, which will update url and also replace last history record. + * - **`inherit`** - {boolean=true}, If `true` will inherit url parameters from current url. + * - **`relative`** - {object=$state.$current}, When transitioning with relative path (e.g '^'), + * defines which state to be relative from. + * - **`notify`** - {boolean=true}, If `true` will broadcast $stateChangeStart and $stateChangeSuccess events. + * - **`reload`** (v0.2.5) - {boolean=false}, If `true` will force transition even if the state or params + * have not changed, aka a reload of the same state. It differs from reloadOnSearch because you'd + * use this when you want to force a reload when *everything* is the same, including search params. + * + * @returns {promise} A promise representing the state of the new transition. + * + * Possible success values: + * + * - $state.current + * + *
      Possible rejection values: + * + * - 'transition superseded' - when a newer transition has been started after this one + * - 'transition prevented' - when `event.preventDefault()` has been called in a `$stateChangeStart` listener + * - 'transition aborted' - when `event.preventDefault()` has been called in a `$stateNotFound` listener or + * when a `$stateNotFound` `event.retry` promise errors. + * - 'transition failed' - when a state has been unsuccessfully found after 2 tries. + * - *resolve error* - when an error has occurred with a `resolve` + * + */ + $state.go = function go(to, params, options) { + return $state.transitionTo(to, params, extend({ inherit: true, relative: $state.$current }, options)); + }; + + /** + * @ngdoc function + * @name ui.router.state.$state#transitionTo + * @methodOf ui.router.state.$state + * + * @description + * Low-level method for transitioning to a new state. {@link ui.router.state.$state#methods_go $state.go} + * uses `transitionTo` internally. `$state.go` is recommended in most situations. + * + * @example + *
      +     * var app = angular.module('app', ['ui.router']);
      +     *
      +     * app.controller('ctrl', function ($scope, $state) {
      +     *   $scope.changeState = function () {
      +     *     $state.transitionTo('contact.detail');
      +     *   };
      +     * });
      +     * 
      + * + * @param {string} to State name. + * @param {object=} toParams A map of the parameters that will be sent to the state, + * will populate $stateParams. + * @param {object=} options Options object. The options are: + * + * - **`location`** - {boolean=true|string=} - If `true` will update the url in the location bar, if `false` + * will not. If string, must be `"replace"`, which will update url and also replace last history record. + * - **`inherit`** - {boolean=false}, If `true` will inherit url parameters from current url. + * - **`relative`** - {object=}, When transitioning with relative path (e.g '^'), + * defines which state to be relative from. + * - **`notify`** - {boolean=true}, If `true` will broadcast $stateChangeStart and $stateChangeSuccess events. + * - **`reload`** (v0.2.5) - {boolean=false}, If `true` will force transition even if the state or params + * have not changed, aka a reload of the same state. It differs from reloadOnSearch because you'd + * use this when you want to force a reload when *everything* is the same, including search params. + * + * @returns {promise} A promise representing the state of the new transition. See + * {@link ui.router.state.$state#methods_go $state.go}. + */ + $state.transitionTo = function transitionTo(to, toParams, options) { + toParams = toParams || {}; + options = extend({ + location: true, inherit: false, relative: null, notify: true, reload: false, $retry: false + }, options || {}); + + var from = $state.$current, fromParams = $state.params, fromPath = from.path; + var evt, toState = findState(to, options.relative); + + if (!isDefined(toState)) { + var redirect = { to: to, toParams: toParams, options: options }; + var redirectResult = handleRedirect(redirect, from.self, fromParams, options); + + if (redirectResult) { + return redirectResult; + } + + // Always retry once if the $stateNotFound was not prevented + // (handles either redirect changed or state lazy-definition) + to = redirect.to; + toParams = redirect.toParams; + options = redirect.options; + toState = findState(to, options.relative); + + if (!isDefined(toState)) { + if (!options.relative) throw new Error("No such state '" + to + "'"); + throw new Error("Could not resolve '" + to + "' from state '" + options.relative + "'"); + } + } + if (toState[abstractKey]) throw new Error("Cannot transition to abstract state '" + to + "'"); + if (options.inherit) toParams = inheritParams($stateParams, toParams || {}, $state.$current, toState); + if (!toState.params.$$validates(toParams)) return TransitionFailed; + + toParams = toState.params.$$values(toParams); + to = toState; + + var toPath = to.path; + + // Starting from the root of the path, keep all levels that haven't changed + var keep = 0, state = toPath[keep], locals = root.locals, toLocals = []; + + if (!options.reload) { + while (state && state === fromPath[keep] && state.ownParams.$$equals(toParams, fromParams)) { + locals = toLocals[keep] = state.locals; + keep++; + state = toPath[keep]; + } + } + + // If we're going to the same state and all locals are kept, we've got nothing to do. + // But clear 'transition', as we still want to cancel any other pending transitions. + // TODO: We may not want to bump 'transition' if we're called from a location change + // that we've initiated ourselves, because we might accidentally abort a legitimate + // transition initiated from code? + if (shouldTriggerReload(to, from, locals, options)) { + if (to.self.reloadOnSearch !== false) $urlRouter.update(); + $state.transition = null; + return $q.when($state.current); + } + + // Filter parameters before we pass them to event handlers etc. + toParams = filterByKeys(to.params.$$keys(), toParams || {}); + + // Broadcast start event and cancel the transition if requested + if (options.notify) { + /** + * @ngdoc event + * @name ui.router.state.$state#$stateChangeStart + * @eventOf ui.router.state.$state + * @eventType broadcast on root scope + * @description + * Fired when the state transition **begins**. You can use `event.preventDefault()` + * to prevent the transition from happening and then the transition promise will be + * rejected with a `'transition prevented'` value. + * + * @param {Object} event Event object. + * @param {State} toState The state being transitioned to. + * @param {Object} toParams The params supplied to the `toState`. + * @param {State} fromState The current state, pre-transition. + * @param {Object} fromParams The params supplied to the `fromState`. + * + * @example + * + *
      +         * $rootScope.$on('$stateChangeStart',
      +         * function(event, toState, toParams, fromState, fromParams){
      +         *     event.preventDefault();
      +         *     // transitionTo() promise will be rejected with
      +         *     // a 'transition prevented' error
      +         * })
      +         * 
      + */ + if ($rootScope.$broadcast('$stateChangeStart', to.self, toParams, from.self, fromParams).defaultPrevented) { + $urlRouter.update(); + return TransitionPrevented; + } + } + + // Resolve locals for the remaining states, but don't update any global state just + // yet -- if anything fails to resolve the current state needs to remain untouched. + // We also set up an inheritance chain for the locals here. This allows the view directive + // to quickly look up the correct definition for each view in the current state. Even + // though we create the locals object itself outside resolveState(), it is initially + // empty and gets filled asynchronously. We need to keep track of the promise for the + // (fully resolved) current locals, and pass this down the chain. + var resolved = $q.when(locals); + + for (var l = keep; l < toPath.length; l++, state = toPath[l]) { + locals = toLocals[l] = inherit(locals); + resolved = resolveState(state, toParams, state === to, resolved, locals, options); + } + + // Once everything is resolved, we are ready to perform the actual transition + // and return a promise for the new state. We also keep track of what the + // current promise is, so that we can detect overlapping transitions and + // keep only the outcome of the last transition. + var transition = $state.transition = resolved.then(function () { + var l, entering, exiting; + + if ($state.transition !== transition) return TransitionSuperseded; + + // Exit 'from' states not kept + for (l = fromPath.length - 1; l >= keep; l--) { + exiting = fromPath[l]; + if (exiting.self.onExit) { + $injector.invoke(exiting.self.onExit, exiting.self, exiting.locals.globals); + } + exiting.locals = null; + } + + // Enter 'to' states not kept + for (l = keep; l < toPath.length; l++) { + entering = toPath[l]; + entering.locals = toLocals[l]; + if (entering.self.onEnter) { + $injector.invoke(entering.self.onEnter, entering.self, entering.locals.globals); + } + } + + // Run it again, to catch any transitions in callbacks + if ($state.transition !== transition) return TransitionSuperseded; + + // Update globals in $state + $state.$current = to; + $state.current = to.self; + $state.params = toParams; + copy($state.params, $stateParams); + $state.transition = null; + + if (options.location && to.navigable) { + $urlRouter.push(to.navigable.url, to.navigable.locals.globals.$stateParams, { + $$avoidResync: true, replace: options.location === 'replace' + }); + } + + if (options.notify) { + /** + * @ngdoc event + * @name ui.router.state.$state#$stateChangeSuccess + * @eventOf ui.router.state.$state + * @eventType broadcast on root scope + * @description + * Fired once the state transition is **complete**. + * + * @param {Object} event Event object. + * @param {State} toState The state being transitioned to. + * @param {Object} toParams The params supplied to the `toState`. + * @param {State} fromState The current state, pre-transition. + * @param {Object} fromParams The params supplied to the `fromState`. + */ + $rootScope.$broadcast('$stateChangeSuccess', to.self, toParams, from.self, fromParams); + } + $urlRouter.update(true); + + return $state.current; + }, function (error) { + if ($state.transition !== transition) return TransitionSuperseded; + + $state.transition = null; + /** + * @ngdoc event + * @name ui.router.state.$state#$stateChangeError + * @eventOf ui.router.state.$state + * @eventType broadcast on root scope + * @description + * Fired when an **error occurs** during transition. It's important to note that if you + * have any errors in your resolve functions (javascript errors, non-existent services, etc) + * they will not throw traditionally. You must listen for this $stateChangeError event to + * catch **ALL** errors. + * + * @param {Object} event Event object. + * @param {State} toState The state being transitioned to. + * @param {Object} toParams The params supplied to the `toState`. + * @param {State} fromState The current state, pre-transition. + * @param {Object} fromParams The params supplied to the `fromState`. + * @param {Error} error The resolve error object. + */ + evt = $rootScope.$broadcast('$stateChangeError', to.self, toParams, from.self, fromParams, error); + + if (!evt.defaultPrevented) { + $urlRouter.update(); + } + + return $q.reject(error); + }); + + return transition; + }; + + /** + * @ngdoc function + * @name ui.router.state.$state#is + * @methodOf ui.router.state.$state + * + * @description + * Similar to {@link ui.router.state.$state#methods_includes $state.includes}, + * but only checks for the full state name. If params is supplied then it will be + * tested for strict equality against the current active params object, so all params + * must match with none missing and no extras. + * + * @example + *
      +     * $state.$current.name = 'contacts.details.item';
      +     *
      +     * // absolute name
      +     * $state.is('contact.details.item'); // returns true
      +     * $state.is(contactDetailItemStateObject); // returns true
      +     *
      +     * // relative name (. and ^), typically from a template
      +     * // E.g. from the 'contacts.details' template
      +     * 
      Item
      + *
      + * + * @param {string|object} stateOrName The state name (absolute or relative) or state object you'd like to check. + * @param {object=} params A param object, e.g. `{sectionId: section.id}`, that you'd like + * to test against the current active state. + * @param {object=} options An options object. The options are: + * + * - **`relative`** - {string|object} - If `stateOrName` is a relative state name and `options.relative` is set, .is will + * test relative to `options.relative` state (or name). + * + * @returns {boolean} Returns true if it is the state. + */ + $state.is = function is(stateOrName, params, options) { + options = extend({ relative: $state.$current }, options || {}); + var state = findState(stateOrName, options.relative); + + if (!isDefined(state)) { return undefined; } + if ($state.$current !== state) { return false; } + return params ? equalForKeys(state.params.$$values(params), $stateParams) : true; + }; + + /** + * @ngdoc function + * @name ui.router.state.$state#includes + * @methodOf ui.router.state.$state + * + * @description + * A method to determine if the current active state is equal to or is the child of the + * state stateName. If any params are passed then they will be tested for a match as well. + * Not all the parameters need to be passed, just the ones you'd like to test for equality. + * + * @example + * Partial and relative names + *
      +     * $state.$current.name = 'contacts.details.item';
      +     *
      +     * // Using partial names
      +     * $state.includes("contacts"); // returns true
      +     * $state.includes("contacts.details"); // returns true
      +     * $state.includes("contacts.details.item"); // returns true
      +     * $state.includes("contacts.list"); // returns false
      +     * $state.includes("about"); // returns false
      +     *
      +     * // Using relative names (. and ^), typically from a template
      +     * // E.g. from the 'contacts.details' template
      +     * 
      Item
      + *
      + * + * Basic globbing patterns + *
      +     * $state.$current.name = 'contacts.details.item.url';
      +     *
      +     * $state.includes("*.details.*.*"); // returns true
      +     * $state.includes("*.details.**"); // returns true
      +     * $state.includes("**.item.**"); // returns true
      +     * $state.includes("*.details.item.url"); // returns true
      +     * $state.includes("*.details.*.url"); // returns true
      +     * $state.includes("*.details.*"); // returns false
      +     * $state.includes("item.**"); // returns false
      +     * 
      + * + * @param {string} stateOrName A partial name, relative name, or glob pattern + * to be searched for within the current state name. + * @param {object=} params A param object, e.g. `{sectionId: section.id}`, + * that you'd like to test against the current active state. + * @param {object=} options An options object. The options are: + * + * - **`relative`** - {string|object=} - If `stateOrName` is a relative state reference and `options.relative` is set, + * .includes will test relative to `options.relative` state (or name). + * + * @returns {boolean} Returns true if it does include the state + */ + $state.includes = function includes(stateOrName, params, options) { + options = extend({ relative: $state.$current }, options || {}); + if (isString(stateOrName) && isGlob(stateOrName)) { + if (!doesStateMatchGlob(stateOrName)) { + return false; + } + stateOrName = $state.$current.name; + } + + var state = findState(stateOrName, options.relative); + if (!isDefined(state)) { return undefined; } + if (!isDefined($state.$current.includes[state.name])) { return false; } + return params ? equalForKeys(state.params.$$values(params), $stateParams, objectKeys(params)) : true; + }; + + + /** + * @ngdoc function + * @name ui.router.state.$state#href + * @methodOf ui.router.state.$state + * + * @description + * A url generation method that returns the compiled url for the given state populated with the given params. + * + * @example + *
      +     * expect($state.href("about.person", { person: "bob" })).toEqual("/about/bob");
      +     * 
      + * + * @param {string|object} stateOrName The state name or state object you'd like to generate a url from. + * @param {object=} params An object of parameter values to fill the state's required parameters. + * @param {object=} options Options object. The options are: + * + * - **`lossy`** - {boolean=true} - If true, and if there is no url associated with the state provided in the + * first parameter, then the constructed href url will be built from the first navigable ancestor (aka + * ancestor with a valid url). + * - **`inherit`** - {boolean=true}, If `true` will inherit url parameters from current url. + * - **`relative`** - {object=$state.$current}, When transitioning with relative path (e.g '^'), + * defines which state to be relative from. + * - **`absolute`** - {boolean=false}, If true will generate an absolute url, e.g. "http://www.example.com/fullurl". + * + * @returns {string} compiled state url + */ + $state.href = function href(stateOrName, params, options) { + options = extend({ + lossy: true, + inherit: true, + absolute: false, + relative: $state.$current + }, options || {}); + + var state = findState(stateOrName, options.relative); + + if (!isDefined(state)) return null; + if (options.inherit) params = inheritParams($stateParams, params || {}, $state.$current, state); + + var nav = (state && options.lossy) ? state.navigable : state; + + if (!nav || nav.url === undefined || nav.url === null) { + return null; + } + return $urlRouter.href(nav.url, filterByKeys(state.params.$$keys(), params || {}), { + absolute: options.absolute + }); + }; + + /** + * @ngdoc function + * @name ui.router.state.$state#get + * @methodOf ui.router.state.$state + * + * @description + * Returns the state configuration object for any specific state or all states. + * + * @param {string|object=} stateOrName (absolute or relative) If provided, will only get the config for + * the requested state. If not provided, returns an array of ALL state configs. + * @param {string|object=} context When stateOrName is a relative state reference, the state will be retrieved relative to context. + * @returns {Object|Array} State configuration object or array of all objects. + */ + $state.get = function (stateOrName, context) { + if (arguments.length === 0) return map(objectKeys(states), function(name) { return states[name].self; }); + var state = findState(stateOrName, context || $state.$current); + return (state && state.self) ? state.self : null; + }; + + function resolveState(state, params, paramsAreFiltered, inherited, dst, options) { + // Make a restricted $stateParams with only the parameters that apply to this state if + // necessary. In addition to being available to the controller and onEnter/onExit callbacks, + // we also need $stateParams to be available for any $injector calls we make during the + // dependency resolution process. + var $stateParams = (paramsAreFiltered) ? params : filterByKeys(state.params.$$keys(), params); + var locals = { $stateParams: $stateParams }; + + // Resolve 'global' dependencies for the state, i.e. those not specific to a view. + // We're also including $stateParams in this; that way the parameters are restricted + // to the set that should be visible to the state, and are independent of when we update + // the global $state and $stateParams values. + dst.resolve = $resolve.resolve(state.resolve, locals, dst.resolve, state); + var promises = [dst.resolve.then(function (globals) { + dst.globals = globals; + })]; + if (inherited) promises.push(inherited); + + // Resolve template and dependencies for all views. + forEach(state.views, function (view, name) { + var injectables = (view.resolve && view.resolve !== state.resolve ? view.resolve : {}); + injectables.$template = [ function () { + return $view.load(name, { view: view, locals: locals, params: $stateParams, notify: options.notify }) || ''; + }]; + + promises.push($resolve.resolve(injectables, locals, dst.resolve, state).then(function (result) { + // References to the controller (only instantiated at link time) + if (isFunction(view.controllerProvider) || isArray(view.controllerProvider)) { + var injectLocals = angular.extend({}, injectables, locals); + result.$$controller = $injector.invoke(view.controllerProvider, null, injectLocals); + } else { + result.$$controller = view.controller; + } + // Provide access to the state itself for internal use + result.$$state = state; + result.$$controllerAs = view.controllerAs; + dst[name] = result; + })); + }); + + // Wait for all the promises and then return the activation object + return $q.all(promises).then(function (values) { + return dst; + }); + } + + return $state; + } + + function shouldTriggerReload(to, from, locals, options) { + if (to === from && ((locals === from.locals && !options.reload) || (to.self.reloadOnSearch === false))) { + return true; + } + } +} + +angular.module('ui.router.state') + .value('$stateParams', {}) + .provider('$state', $StateProvider); diff --git a/public/admincp/bower_components/angular-ui-router/src/stateDirectives.js b/public/admincp/bower_components/angular-ui-router/src/stateDirectives.js new file mode 100644 index 000000000..4d9d527dd --- /dev/null +++ b/public/admincp/bower_components/angular-ui-router/src/stateDirectives.js @@ -0,0 +1,268 @@ +function parseStateRef(ref, current) { + var preparsed = ref.match(/^\s*({[^}]*})\s*$/), parsed; + if (preparsed) ref = current + '(' + preparsed[1] + ')'; + parsed = ref.replace(/\n/g, " ").match(/^([^(]+?)\s*(\((.*)\))?$/); + if (!parsed || parsed.length !== 4) throw new Error("Invalid state ref '" + ref + "'"); + return { state: parsed[1], paramExpr: parsed[3] || null }; +} + +function stateContext(el) { + var stateData = el.parent().inheritedData('$uiView'); + + if (stateData && stateData.state && stateData.state.name) { + return stateData.state; + } +} + +/** + * @ngdoc directive + * @name ui.router.state.directive:ui-sref + * + * @requires ui.router.state.$state + * @requires $timeout + * + * @restrict A + * + * @description + * A directive that binds a link (`` tag) to a state. If the state has an associated + * URL, the directive will automatically generate & update the `href` attribute via + * the {@link ui.router.state.$state#methods_href $state.href()} method. Clicking + * the link will trigger a state transition with optional parameters. + * + * Also middle-clicking, right-clicking, and ctrl-clicking on the link will be + * handled natively by the browser. + * + * You can also use relative state paths within ui-sref, just like the relative + * paths passed to `$state.go()`. You just need to be aware that the path is relative + * to the state that the link lives in, in other words the state that loaded the + * template containing the link. + * + * You can specify options to pass to {@link ui.router.state.$state#go $state.go()} + * using the `ui-sref-opts` attribute. Options are restricted to `location`, `inherit`, + * and `reload`. + * + * @example + * Here's an example of how you'd use ui-sref and how it would compile. If you have the + * following template: + *
      + * Home | About | Next page
      + * 
      + * 
      + * 
      + * + * Then the compiled html would be (assuming Html5Mode is off and current state is contacts): + *
      + * Home | About | Next page
      + * 
      + * 
        + *
      • + * Joe + *
      • + *
      • + * Alice + *
      • + *
      • + * Bob + *
      • + *
      + * + * Home + *
      + * + * @param {string} ui-sref 'stateName' can be any valid absolute or relative state + * @param {Object} ui-sref-opts options to pass to {@link ui.router.state.$state#go $state.go()} + */ +$StateRefDirective.$inject = ['$state', '$timeout']; +function $StateRefDirective($state, $timeout) { + var allowedOptions = ['location', 'inherit', 'reload']; + + return { + restrict: 'A', + require: ['?^uiSrefActive', '?^uiSrefActiveEq'], + link: function(scope, element, attrs, uiSrefActive) { + var ref = parseStateRef(attrs.uiSref, $state.current.name); + var params = null, url = null, base = stateContext(element) || $state.$current; + var newHref = null, isAnchor = element.prop("tagName") === "A"; + var isForm = element[0].nodeName === "FORM"; + var attr = isForm ? "action" : "href", nav = true; + + var options = { relative: base, inherit: true }; + var optionsOverride = scope.$eval(attrs.uiSrefOpts) || {}; + + angular.forEach(allowedOptions, function(option) { + if (option in optionsOverride) { + options[option] = optionsOverride[option]; + } + }); + + var update = function(newVal) { + if (newVal) params = angular.copy(newVal); + if (!nav) return; + + newHref = $state.href(ref.state, params, options); + + var activeDirective = uiSrefActive[1] || uiSrefActive[0]; + if (activeDirective) { + activeDirective.$$setStateInfo(ref.state, params); + } + if (newHref === null) { + nav = false; + return false; + } + attrs.$set(attr, newHref); + }; + + if (ref.paramExpr) { + scope.$watch(ref.paramExpr, function(newVal, oldVal) { + if (newVal !== params) update(newVal); + }, true); + params = angular.copy(scope.$eval(ref.paramExpr)); + } + update(); + + if (isForm) return; + + element.bind("click", function(e) { + var button = e.which || e.button; + if ( !(button > 1 || e.ctrlKey || e.metaKey || e.shiftKey || element.attr('target')) ) { + // HACK: This is to allow ng-clicks to be processed before the transition is initiated: + var transition = $timeout(function() { + $state.go(ref.state, params, options); + }); + e.preventDefault(); + + // if the state has no URL, ignore one preventDefault from the directive. + var ignorePreventDefaultCount = isAnchor && !newHref ? 1: 0; + e.preventDefault = function() { + if (ignorePreventDefaultCount-- <= 0) + $timeout.cancel(transition); + }; + } + }); + } + }; +} + +/** + * @ngdoc directive + * @name ui.router.state.directive:ui-sref-active + * + * @requires ui.router.state.$state + * @requires ui.router.state.$stateParams + * @requires $interpolate + * + * @restrict A + * + * @description + * A directive working alongside ui-sref to add classes to an element when the + * related ui-sref directive's state is active, and removing them when it is inactive. + * The primary use-case is to simplify the special appearance of navigation menus + * relying on `ui-sref`, by having the "active" state's menu button appear different, + * distinguishing it from the inactive menu items. + * + * ui-sref-active can live on the same element as ui-sref or on a parent element. The first + * ui-sref-active found at the same level or above the ui-sref will be used. + * + * Will activate when the ui-sref's target state or any child state is active. If you + * need to activate only when the ui-sref target state is active and *not* any of + * it's children, then you will use + * {@link ui.router.state.directive:ui-sref-active-eq ui-sref-active-eq} + * + * @example + * Given the following template: + *
      + * 
      + * 
      + * + * + * When the app state is "app.user" (or any children states), and contains the state parameter "user" with value "bilbobaggins", + * the resulting HTML will appear as (note the 'active' class): + *
      + * 
      + * 
      + * + * The class name is interpolated **once** during the directives link time (any further changes to the + * interpolated value are ignored). + * + * Multiple classes may be specified in a space-separated format: + *
      + * 
        + *
      • + * link + *
      • + *
      + *
      + */ + +/** + * @ngdoc directive + * @name ui.router.state.directive:ui-sref-active-eq + * + * @requires ui.router.state.$state + * @requires ui.router.state.$stateParams + * @requires $interpolate + * + * @restrict A + * + * @description + * The same as {@link ui.router.state.directive:ui-sref-active ui-sref-active} but will only activate + * when the exact target state used in the `ui-sref` is active; no child states. + * + */ +$StateRefActiveDirective.$inject = ['$state', '$stateParams', '$interpolate']; +function $StateRefActiveDirective($state, $stateParams, $interpolate) { + return { + restrict: "A", + controller: ['$scope', '$element', '$attrs', function ($scope, $element, $attrs) { + var state, params, activeClass; + + // There probably isn't much point in $observing this + // uiSrefActive and uiSrefActiveEq share the same directive object with some + // slight difference in logic routing + activeClass = $interpolate($attrs.uiSrefActiveEq || $attrs.uiSrefActive || '', false)($scope); + + // Allow uiSref to communicate with uiSrefActive[Equals] + this.$$setStateInfo = function (newState, newParams) { + state = $state.get(newState, stateContext($element)); + params = newParams; + update(); + }; + + $scope.$on('$stateChangeSuccess', update); + + // Update route state + function update() { + if (isMatch()) { + $element.addClass(activeClass); + } else { + $element.removeClass(activeClass); + } + } + + function isMatch() { + if (typeof $attrs.uiSrefActiveEq !== 'undefined') { + return state && $state.is(state.name, params); + } else { + return state && $state.includes(state.name, params); + } + } + }] + }; +} + +angular.module('ui.router.state') + .directive('uiSref', $StateRefDirective) + .directive('uiSrefActive', $StateRefActiveDirective) + .directive('uiSrefActiveEq', $StateRefActiveDirective); diff --git a/public/admincp/bower_components/angular-ui-router/src/stateFilters.js b/public/admincp/bower_components/angular-ui-router/src/stateFilters.js new file mode 100644 index 000000000..e0a117580 --- /dev/null +++ b/public/admincp/bower_components/angular-ui-router/src/stateFilters.js @@ -0,0 +1,39 @@ +/** + * @ngdoc filter + * @name ui.router.state.filter:isState + * + * @requires ui.router.state.$state + * + * @description + * Translates to {@link ui.router.state.$state#methods_is $state.is("stateName")}. + */ +$IsStateFilter.$inject = ['$state']; +function $IsStateFilter($state) { + var isFilter = function (state) { + return $state.is(state); + }; + isFilter.$stateful = true; + return isFilter; +} + +/** + * @ngdoc filter + * @name ui.router.state.filter:includedByState + * + * @requires ui.router.state.$state + * + * @description + * Translates to {@link ui.router.state.$state#methods_includes $state.includes('fullOrPartialStateName')}. + */ +$IncludedByStateFilter.$inject = ['$state']; +function $IncludedByStateFilter($state) { + var includesFilter = function (state) { + return $state.includes(state); + }; + includesFilter.$stateful = true; + return includesFilter; +} + +angular.module('ui.router.state') + .filter('isState', $IsStateFilter) + .filter('includedByState', $IncludedByStateFilter); diff --git a/public/admincp/bower_components/angular-ui-router/src/templateFactory.js b/public/admincp/bower_components/angular-ui-router/src/templateFactory.js new file mode 100644 index 000000000..ca491a987 --- /dev/null +++ b/public/admincp/bower_components/angular-ui-router/src/templateFactory.js @@ -0,0 +1,110 @@ +/** + * @ngdoc object + * @name ui.router.util.$templateFactory + * + * @requires $http + * @requires $templateCache + * @requires $injector + * + * @description + * Service. Manages loading of templates. + */ +$TemplateFactory.$inject = ['$http', '$templateCache', '$injector']; +function $TemplateFactory( $http, $templateCache, $injector) { + + /** + * @ngdoc function + * @name ui.router.util.$templateFactory#fromConfig + * @methodOf ui.router.util.$templateFactory + * + * @description + * Creates a template from a configuration object. + * + * @param {object} config Configuration object for which to load a template. + * The following properties are search in the specified order, and the first one + * that is defined is used to create the template: + * + * @param {string|object} config.template html string template or function to + * load via {@link ui.router.util.$templateFactory#fromString fromString}. + * @param {string|object} config.templateUrl url to load or a function returning + * the url to load via {@link ui.router.util.$templateFactory#fromUrl fromUrl}. + * @param {Function} config.templateProvider function to invoke via + * {@link ui.router.util.$templateFactory#fromProvider fromProvider}. + * @param {object} params Parameters to pass to the template function. + * @param {object} locals Locals to pass to `invoke` if the template is loaded + * via a `templateProvider`. Defaults to `{ params: params }`. + * + * @return {string|object} The template html as a string, or a promise for + * that string,or `null` if no template is configured. + */ + this.fromConfig = function (config, params, locals) { + return ( + isDefined(config.template) ? this.fromString(config.template, params) : + isDefined(config.templateUrl) ? this.fromUrl(config.templateUrl, params) : + isDefined(config.templateProvider) ? this.fromProvider(config.templateProvider, params, locals) : + null + ); + }; + + /** + * @ngdoc function + * @name ui.router.util.$templateFactory#fromString + * @methodOf ui.router.util.$templateFactory + * + * @description + * Creates a template from a string or a function returning a string. + * + * @param {string|object} template html template as a string or function that + * returns an html template as a string. + * @param {object} params Parameters to pass to the template function. + * + * @return {string|object} The template html as a string, or a promise for that + * string. + */ + this.fromString = function (template, params) { + return isFunction(template) ? template(params) : template; + }; + + /** + * @ngdoc function + * @name ui.router.util.$templateFactory#fromUrl + * @methodOf ui.router.util.$templateFactory + * + * @description + * Loads a template from the a URL via `$http` and `$templateCache`. + * + * @param {string|Function} url url of the template to load, or a function + * that returns a url. + * @param {Object} params Parameters to pass to the url function. + * @return {string|Promise.} The template html as a string, or a promise + * for that string. + */ + this.fromUrl = function (url, params) { + if (isFunction(url)) url = url(params); + if (url == null) return null; + else return $http + .get(url, { cache: $templateCache, headers: { Accept: 'text/html' }}) + .then(function(response) { return response.data; }); + }; + + /** + * @ngdoc function + * @name ui.router.util.$templateFactory#fromProvider + * @methodOf ui.router.util.$templateFactory + * + * @description + * Creates a template by invoking an injectable provider function. + * + * @param {Function} provider Function to invoke via `$injector.invoke` + * @param {Object} params Parameters for the template. + * @param {Object} locals Locals to pass to `invoke`. Defaults to + * `{ params: params }`. + * @return {string|Promise.} The template html as a string, or a promise + * for that string. + */ + this.fromProvider = function (provider, params, locals) { + return $injector.invoke(provider, null, locals || { params: params }); + }; +} + +angular.module('ui.router.util').service('$templateFactory', $TemplateFactory); diff --git a/public/admincp/bower_components/angular-ui-router/src/urlMatcherFactory.js b/public/admincp/bower_components/angular-ui-router/src/urlMatcherFactory.js new file mode 100644 index 000000000..a16e728c5 --- /dev/null +++ b/public/admincp/bower_components/angular-ui-router/src/urlMatcherFactory.js @@ -0,0 +1,1036 @@ +var $$UMFP; // reference to $UrlMatcherFactoryProvider + +/** + * @ngdoc object + * @name ui.router.util.type:UrlMatcher + * + * @description + * Matches URLs against patterns and extracts named parameters from the path or the search + * part of the URL. A URL pattern consists of a path pattern, optionally followed by '?' and a list + * of search parameters. Multiple search parameter names are separated by '&'. Search parameters + * do not influence whether or not a URL is matched, but their values are passed through into + * the matched parameters returned by {@link ui.router.util.type:UrlMatcher#methods_exec exec}. + * + * Path parameter placeholders can be specified using simple colon/catch-all syntax or curly brace + * syntax, which optionally allows a regular expression for the parameter to be specified: + * + * * `':'` name - colon placeholder + * * `'*'` name - catch-all placeholder + * * `'{' name '}'` - curly placeholder + * * `'{' name ':' regexp|type '}'` - curly placeholder with regexp or type name. Should the + * regexp itself contain curly braces, they must be in matched pairs or escaped with a backslash. + * + * Parameter names may contain only word characters (latin letters, digits, and underscore) and + * must be unique within the pattern (across both path and search parameters). For colon + * placeholders or curly placeholders without an explicit regexp, a path parameter matches any + * number of characters other than '/'. For catch-all placeholders the path parameter matches + * any number of characters. + * + * Examples: + * + * * `'/hello/'` - Matches only if the path is exactly '/hello/'. There is no special treatment for + * trailing slashes, and patterns have to match the entire path, not just a prefix. + * * `'/user/:id'` - Matches '/user/bob' or '/user/1234!!!' or even '/user/' but not '/user' or + * '/user/bob/details'. The second path segment will be captured as the parameter 'id'. + * * `'/user/{id}'` - Same as the previous example, but using curly brace syntax. + * * `'/user/{id:[^/]*}'` - Same as the previous example. + * * `'/user/{id:[0-9a-fA-F]{1,8}}'` - Similar to the previous example, but only matches if the id + * parameter consists of 1 to 8 hex digits. + * * `'/files/{path:.*}'` - Matches any URL starting with '/files/' and captures the rest of the + * path into the parameter 'path'. + * * `'/files/*path'` - ditto. + * * `'/calendar/{start:date}'` - Matches "/calendar/2014-11-12" (because the pattern defined + * in the built-in `date` Type matches `2014-11-12`) and provides a Date object in $stateParams.start + * + * @param {string} pattern The pattern to compile into a matcher. + * @param {Object} config A configuration object hash: + * @param {Object=} parentMatcher Used to concatenate the pattern/config onto + * an existing UrlMatcher + * + * * `caseInsensitive` - `true` if URL matching should be case insensitive, otherwise `false`, the default value (for backward compatibility) is `false`. + * * `strict` - `false` if matching against a URL with a trailing slash should be treated as equivalent to a URL without a trailing slash, the default value is `true`. + * + * @property {string} prefix A static prefix of this pattern. The matcher guarantees that any + * URL matching this matcher (i.e. any string for which {@link ui.router.util.type:UrlMatcher#methods_exec exec()} returns + * non-null) will start with this prefix. + * + * @property {string} source The pattern that was passed into the constructor + * + * @property {string} sourcePath The path portion of the source property + * + * @property {string} sourceSearch The search portion of the source property + * + * @property {string} regex The constructed regex that will be used to match against the url when + * it is time to determine which url will match. + * + * @returns {Object} New `UrlMatcher` object + */ +function UrlMatcher(pattern, config, parentMatcher) { + config = extend({ params: {} }, isObject(config) ? config : {}); + + // Find all placeholders and create a compiled pattern, using either classic or curly syntax: + // '*' name + // ':' name + // '{' name '}' + // '{' name ':' regexp '}' + // The regular expression is somewhat complicated due to the need to allow curly braces + // inside the regular expression. The placeholder regexp breaks down as follows: + // ([:*])([\w\[\]]+) - classic placeholder ($1 / $2) (search version has - for snake-case) + // \{([\w\[\]]+)(?:\:( ... ))?\} - curly brace placeholder ($3) with optional regexp/type ... ($4) (search version has - for snake-case + // (?: ... | ... | ... )+ - the regexp consists of any number of atoms, an atom being either + // [^{}\\]+ - anything other than curly braces or backslash + // \\. - a backslash escape + // \{(?:[^{}\\]+|\\.)*\} - a matched set of curly braces containing other atoms + var placeholder = /([:*])([\w\[\]]+)|\{([\w\[\]]+)(?:\:((?:[^{}\\]+|\\.|\{(?:[^{}\\]+|\\.)*\})+))?\}/g, + searchPlaceholder = /([:]?)([\w\[\]-]+)|\{([\w\[\]-]+)(?:\:((?:[^{}\\]+|\\.|\{(?:[^{}\\]+|\\.)*\})+))?\}/g, + compiled = '^', last = 0, m, + segments = this.segments = [], + parentParams = parentMatcher ? parentMatcher.params : {}, + params = this.params = parentMatcher ? parentMatcher.params.$$new() : new $$UMFP.ParamSet(), + paramNames = []; + + function addParameter(id, type, config, location) { + paramNames.push(id); + if (parentParams[id]) return parentParams[id]; + if (!/^\w+(-+\w+)*(?:\[\])?$/.test(id)) throw new Error("Invalid parameter name '" + id + "' in pattern '" + pattern + "'"); + if (params[id]) throw new Error("Duplicate parameter name '" + id + "' in pattern '" + pattern + "'"); + params[id] = new $$UMFP.Param(id, type, config, location); + return params[id]; + } + + function quoteRegExp(string, pattern, squash) { + var surroundPattern = ['',''], result = string.replace(/[\\\[\]\^$*+?.()|{}]/g, "\\$&"); + if (!pattern) return result; + switch(squash) { + case false: surroundPattern = ['(', ')']; break; + case true: surroundPattern = ['?(', ')?']; break; + default: surroundPattern = ['(' + squash + "|", ')?']; break; + } + return result + surroundPattern[0] + pattern + surroundPattern[1]; + } + + this.source = pattern; + + // Split into static segments separated by path parameter placeholders. + // The number of segments is always 1 more than the number of parameters. + function matchDetails(m, isSearch) { + var id, regexp, segment, type, cfg, arrayMode; + id = m[2] || m[3]; // IE[78] returns '' for unmatched groups instead of null + cfg = config.params[id]; + segment = pattern.substring(last, m.index); + regexp = isSearch ? m[4] : m[4] || (m[1] == '*' ? '.*' : null); + type = $$UMFP.type(regexp || "string") || inherit($$UMFP.type("string"), { pattern: new RegExp(regexp) }); + return { + id: id, regexp: regexp, segment: segment, type: type, cfg: cfg + }; + } + + var p, param, segment; + while ((m = placeholder.exec(pattern))) { + p = matchDetails(m, false); + if (p.segment.indexOf('?') >= 0) break; // we're into the search part + + param = addParameter(p.id, p.type, p.cfg, "path"); + compiled += quoteRegExp(p.segment, param.type.pattern.source, param.squash); + segments.push(p.segment); + last = placeholder.lastIndex; + } + segment = pattern.substring(last); + + // Find any search parameter names and remove them from the last segment + var i = segment.indexOf('?'); + + if (i >= 0) { + var search = this.sourceSearch = segment.substring(i); + segment = segment.substring(0, i); + this.sourcePath = pattern.substring(0, last + i); + + if (search.length > 0) { + last = 0; + while ((m = searchPlaceholder.exec(search))) { + p = matchDetails(m, true); + param = addParameter(p.id, p.type, p.cfg, "search"); + last = placeholder.lastIndex; + // check if ?& + } + } + } else { + this.sourcePath = pattern; + this.sourceSearch = ''; + } + + compiled += quoteRegExp(segment) + (config.strict === false ? '\/?' : '') + '$'; + segments.push(segment); + + this.regexp = new RegExp(compiled, config.caseInsensitive ? 'i' : undefined); + this.prefix = segments[0]; + this.$$paramNames = paramNames; +} + +/** + * @ngdoc function + * @name ui.router.util.type:UrlMatcher#concat + * @methodOf ui.router.util.type:UrlMatcher + * + * @description + * Returns a new matcher for a pattern constructed by appending the path part and adding the + * search parameters of the specified pattern to this pattern. The current pattern is not + * modified. This can be understood as creating a pattern for URLs that are relative to (or + * suffixes of) the current pattern. + * + * @example + * The following two matchers are equivalent: + *
      + * new UrlMatcher('/user/{id}?q').concat('/details?date');
      + * new UrlMatcher('/user/{id}/details?q&date');
      + * 
      + * + * @param {string} pattern The pattern to append. + * @param {Object} config An object hash of the configuration for the matcher. + * @returns {UrlMatcher} A matcher for the concatenated pattern. + */ +UrlMatcher.prototype.concat = function (pattern, config) { + // Because order of search parameters is irrelevant, we can add our own search + // parameters to the end of the new pattern. Parse the new pattern by itself + // and then join the bits together, but it's much easier to do this on a string level. + var defaultConfig = { + caseInsensitive: $$UMFP.caseInsensitive(), + strict: $$UMFP.strictMode(), + squash: $$UMFP.defaultSquashPolicy() + }; + return new UrlMatcher(this.sourcePath + pattern + this.sourceSearch, extend(defaultConfig, config), this); +}; + +UrlMatcher.prototype.toString = function () { + return this.source; +}; + +/** + * @ngdoc function + * @name ui.router.util.type:UrlMatcher#exec + * @methodOf ui.router.util.type:UrlMatcher + * + * @description + * Tests the specified path against this matcher, and returns an object containing the captured + * parameter values, or null if the path does not match. The returned object contains the values + * of any search parameters that are mentioned in the pattern, but their value may be null if + * they are not present in `searchParams`. This means that search parameters are always treated + * as optional. + * + * @example + *
      + * new UrlMatcher('/user/{id}?q&r').exec('/user/bob', {
      + *   x: '1', q: 'hello'
      + * });
      + * // returns { id: 'bob', q: 'hello', r: null }
      + * 
      + * + * @param {string} path The URL path to match, e.g. `$location.path()`. + * @param {Object} searchParams URL search parameters, e.g. `$location.search()`. + * @returns {Object} The captured parameter values. + */ +UrlMatcher.prototype.exec = function (path, searchParams) { + var m = this.regexp.exec(path); + if (!m) return null; + searchParams = searchParams || {}; + + var paramNames = this.parameters(), nTotal = paramNames.length, + nPath = this.segments.length - 1, + values = {}, i, j, cfg, paramName; + + if (nPath !== m.length - 1) throw new Error("Unbalanced capture group in route '" + this.source + "'"); + + function decodePathArray(string) { + function reverseString(str) { return str.split("").reverse().join(""); } + function unquoteDashes(str) { return str.replace(/\\-/, "-"); } + + var split = reverseString(string).split(/-(?!\\)/); + var allReversed = map(split, reverseString); + return map(allReversed, unquoteDashes).reverse(); + } + + for (i = 0; i < nPath; i++) { + paramName = paramNames[i]; + var param = this.params[paramName]; + var paramVal = m[i+1]; + // if the param value matches a pre-replace pair, replace the value before decoding. + for (j = 0; j < param.replace; j++) { + if (param.replace[j].from === paramVal) paramVal = param.replace[j].to; + } + if (paramVal && param.array === true) paramVal = decodePathArray(paramVal); + values[paramName] = param.value(paramVal); + } + for (/**/; i < nTotal; i++) { + paramName = paramNames[i]; + values[paramName] = this.params[paramName].value(searchParams[paramName]); + } + + return values; +}; + +/** + * @ngdoc function + * @name ui.router.util.type:UrlMatcher#parameters + * @methodOf ui.router.util.type:UrlMatcher + * + * @description + * Returns the names of all path and search parameters of this pattern in an unspecified order. + * + * @returns {Array.} An array of parameter names. Must be treated as read-only. If the + * pattern has no parameters, an empty array is returned. + */ +UrlMatcher.prototype.parameters = function (param) { + if (!isDefined(param)) return this.$$paramNames; + return this.params[param] || null; +}; + +/** + * @ngdoc function + * @name ui.router.util.type:UrlMatcher#validate + * @methodOf ui.router.util.type:UrlMatcher + * + * @description + * Checks an object hash of parameters to validate their correctness according to the parameter + * types of this `UrlMatcher`. + * + * @param {Object} params The object hash of parameters to validate. + * @returns {boolean} Returns `true` if `params` validates, otherwise `false`. + */ +UrlMatcher.prototype.validates = function (params) { + return this.params.$$validates(params); +}; + +/** + * @ngdoc function + * @name ui.router.util.type:UrlMatcher#format + * @methodOf ui.router.util.type:UrlMatcher + * + * @description + * Creates a URL that matches this pattern by substituting the specified values + * for the path and search parameters. Null values for path parameters are + * treated as empty strings. + * + * @example + *
      + * new UrlMatcher('/user/{id}?q').format({ id:'bob', q:'yes' });
      + * // returns '/user/bob?q=yes'
      + * 
      + * + * @param {Object} values the values to substitute for the parameters in this pattern. + * @returns {string} the formatted URL (path and optionally search part). + */ +UrlMatcher.prototype.format = function (values) { + values = values || {}; + var segments = this.segments, params = this.parameters(), paramset = this.params; + if (!this.validates(values)) return null; + + var i, search = false, nPath = segments.length - 1, nTotal = params.length, result = segments[0]; + + function encodeDashes(str) { // Replace dashes with encoded "\-" + return encodeURIComponent(str).replace(/-/g, function(c) { return '%5C%' + c.charCodeAt(0).toString(16).toUpperCase(); }); + } + + for (i = 0; i < nTotal; i++) { + var isPathParam = i < nPath; + var name = params[i], param = paramset[name], value = param.value(values[name]); + var isDefaultValue = param.isOptional && param.type.equals(param.value(), value); + var squash = isDefaultValue ? param.squash : false; + var encoded = param.type.encode(value); + + if (isPathParam) { + var nextSegment = segments[i + 1]; + if (squash === false) { + if (encoded != null) { + if (isArray(encoded)) { + result += map(encoded, encodeDashes).join("-"); + } else { + result += encodeURIComponent(encoded); + } + } + result += nextSegment; + } else if (squash === true) { + var capture = result.match(/\/$/) ? /\/?(.*)/ : /(.*)/; + result += nextSegment.match(capture)[1]; + } else if (isString(squash)) { + result += squash + nextSegment; + } + } else { + if (encoded == null || (isDefaultValue && squash !== false)) continue; + if (!isArray(encoded)) encoded = [ encoded ]; + encoded = map(encoded, encodeURIComponent).join('&' + name + '='); + result += (search ? '&' : '?') + (name + '=' + encoded); + search = true; + } + } + + return result; +}; + +/** + * @ngdoc object + * @name ui.router.util.type:Type + * + * @description + * Implements an interface to define custom parameter types that can be decoded from and encoded to + * string parameters matched in a URL. Used by {@link ui.router.util.type:UrlMatcher `UrlMatcher`} + * objects when matching or formatting URLs, or comparing or validating parameter values. + * + * See {@link ui.router.util.$urlMatcherFactory#methods_type `$urlMatcherFactory#type()`} for more + * information on registering custom types. + * + * @param {Object} config A configuration object which contains the custom type definition. The object's + * properties will override the default methods and/or pattern in `Type`'s public interface. + * @example + *
      + * {
      + *   decode: function(val) { return parseInt(val, 10); },
      + *   encode: function(val) { return val && val.toString(); },
      + *   equals: function(a, b) { return this.is(a) && a === b; },
      + *   is: function(val) { return angular.isNumber(val) isFinite(val) && val % 1 === 0; },
      + *   pattern: /\d+/
      + * }
      + * 
      + * + * @property {RegExp} pattern The regular expression pattern used to match values of this type when + * coming from a substring of a URL. + * + * @returns {Object} Returns a new `Type` object. + */ +function Type(config) { + extend(this, config); +} + +/** + * @ngdoc function + * @name ui.router.util.type:Type#is + * @methodOf ui.router.util.type:Type + * + * @description + * Detects whether a value is of a particular type. Accepts a native (decoded) value + * and determines whether it matches the current `Type` object. + * + * @param {*} val The value to check. + * @param {string} key Optional. If the type check is happening in the context of a specific + * {@link ui.router.util.type:UrlMatcher `UrlMatcher`} object, this is the name of the + * parameter in which `val` is stored. Can be used for meta-programming of `Type` objects. + * @returns {Boolean} Returns `true` if the value matches the type, otherwise `false`. + */ +Type.prototype.is = function(val, key) { + return true; +}; + +/** + * @ngdoc function + * @name ui.router.util.type:Type#encode + * @methodOf ui.router.util.type:Type + * + * @description + * Encodes a custom/native type value to a string that can be embedded in a URL. Note that the + * return value does *not* need to be URL-safe (i.e. passed through `encodeURIComponent()`), it + * only needs to be a representation of `val` that has been coerced to a string. + * + * @param {*} val The value to encode. + * @param {string} key The name of the parameter in which `val` is stored. Can be used for + * meta-programming of `Type` objects. + * @returns {string} Returns a string representation of `val` that can be encoded in a URL. + */ +Type.prototype.encode = function(val, key) { + return val; +}; + +/** + * @ngdoc function + * @name ui.router.util.type:Type#decode + * @methodOf ui.router.util.type:Type + * + * @description + * Converts a parameter value (from URL string or transition param) to a custom/native value. + * + * @param {string} val The URL parameter value to decode. + * @param {string} key The name of the parameter in which `val` is stored. Can be used for + * meta-programming of `Type` objects. + * @returns {*} Returns a custom representation of the URL parameter value. + */ +Type.prototype.decode = function(val, key) { + return val; +}; + +/** + * @ngdoc function + * @name ui.router.util.type:Type#equals + * @methodOf ui.router.util.type:Type + * + * @description + * Determines whether two decoded values are equivalent. + * + * @param {*} a A value to compare against. + * @param {*} b A value to compare against. + * @returns {Boolean} Returns `true` if the values are equivalent/equal, otherwise `false`. + */ +Type.prototype.equals = function(a, b) { + return a == b; +}; + +Type.prototype.$subPattern = function() { + var sub = this.pattern.toString(); + return sub.substr(1, sub.length - 2); +}; + +Type.prototype.pattern = /.*/; + +Type.prototype.toString = function() { return "{Type:" + this.name + "}"; }; + +/* + * Wraps an existing custom Type as an array of Type, depending on 'mode'. + * e.g.: + * - urlmatcher pattern "/path?{queryParam[]:int}" + * - url: "/path?queryParam=1&queryParam=2 + * - $stateParams.queryParam will be [1, 2] + * if `mode` is "auto", then + * - url: "/path?queryParam=1 will create $stateParams.queryParam: 1 + * - url: "/path?queryParam=1&queryParam=2 will create $stateParams.queryParam: [1, 2] + */ +Type.prototype.$asArray = function(mode, isSearch) { + if (!mode) return this; + if (mode === "auto" && !isSearch) throw new Error("'auto' array mode is for query parameters only"); + return new ArrayType(this, mode); + + function ArrayType(type, mode) { + function bindTo(type, callbackName) { + return function() { + return type[callbackName].apply(type, arguments); + }; + } + + // Wrap non-array value as array + function arrayWrap(val) { return isArray(val) ? val : (isDefined(val) ? [ val ] : []); } + // Unwrap array value for "auto" mode. Return undefined for empty array. + function arrayUnwrap(val) { + switch(val.length) { + case 0: return undefined; + case 1: return mode === "auto" ? val[0] : val; + default: return val; + } + } + function falsey(val) { return !val; } + + // Wraps type (.is/.encode/.decode) functions to operate on each value of an array + function arrayHandler(callback, allTruthyMode) { + return function handleArray(val) { + val = arrayWrap(val); + var result = map(val, callback); + if (allTruthyMode === true) + return filter(result, falsey).length === 0; + return arrayUnwrap(result); + }; + } + + // Wraps type (.equals) functions to operate on each value of an array + function arrayEqualsHandler(callback) { + return function handleArray(val1, val2) { + var left = arrayWrap(val1), right = arrayWrap(val2); + if (left.length !== right.length) return false; + for (var i = 0; i < left.length; i++) { + if (!callback(left[i], right[i])) return false; + } + return true; + }; + } + + this.encode = arrayHandler(bindTo(type, 'encode')); + this.decode = arrayHandler(bindTo(type, 'decode')); + this.is = arrayHandler(bindTo(type, 'is'), true); + this.equals = arrayEqualsHandler(bindTo(type, 'equals')); + this.pattern = type.pattern; + this.$arrayMode = mode; + } +}; + + + +/** + * @ngdoc object + * @name ui.router.util.$urlMatcherFactory + * + * @description + * Factory for {@link ui.router.util.type:UrlMatcher `UrlMatcher`} instances. The factory + * is also available to providers under the name `$urlMatcherFactoryProvider`. + */ +function $UrlMatcherFactory() { + $$UMFP = this; + + var isCaseInsensitive = false, isStrictMode = true, defaultSquashPolicy = false; + + function valToString(val) { return val != null ? val.toString().replace(/\//g, "%2F") : val; } + function valFromString(val) { return val != null ? val.toString().replace(/%2F/g, "/") : val; } +// TODO: in 1.0, make string .is() return false if value is undefined by default. +// function regexpMatches(val) { /*jshint validthis:true */ return isDefined(val) && this.pattern.test(val); } + function regexpMatches(val) { /*jshint validthis:true */ return this.pattern.test(val); } + + var $types = {}, enqueue = true, typeQueue = [], injector, defaultTypes = { + string: { + encode: valToString, + decode: valFromString, + is: regexpMatches, + pattern: /[^/]*/ + }, + int: { + encode: valToString, + decode: function(val) { return parseInt(val, 10); }, + is: function(val) { return isDefined(val) && this.decode(val.toString()) === val; }, + pattern: /\d+/ + }, + bool: { + encode: function(val) { return val ? 1 : 0; }, + decode: function(val) { return parseInt(val, 10) !== 0; }, + is: function(val) { return val === true || val === false; }, + pattern: /0|1/ + }, + date: { + encode: function (val) { + if (!this.is(val)) + return undefined; + return [ val.getFullYear(), + ('0' + (val.getMonth() + 1)).slice(-2), + ('0' + val.getDate()).slice(-2) + ].join("-"); + }, + decode: function (val) { + if (this.is(val)) return val; + var match = this.capture.exec(val); + return match ? new Date(match[1], match[2] - 1, match[3]) : undefined; + }, + is: function(val) { return val instanceof Date && !isNaN(val.valueOf()); }, + equals: function (a, b) { return this.is(a) && this.is(b) && a.toISOString() === b.toISOString(); }, + pattern: /[0-9]{4}-(?:0[1-9]|1[0-2])-(?:0[1-9]|[1-2][0-9]|3[0-1])/, + capture: /([0-9]{4})-(0[1-9]|1[0-2])-(0[1-9]|[1-2][0-9]|3[0-1])/ + }, + json: { + encode: angular.toJson, + decode: angular.fromJson, + is: angular.isObject, + equals: angular.equals, + pattern: /[^/]*/ + }, + any: { // does not encode/decode + encode: angular.identity, + decode: angular.identity, + is: angular.identity, + equals: angular.equals, + pattern: /.*/ + } + }; + + function getDefaultConfig() { + return { + strict: isStrictMode, + caseInsensitive: isCaseInsensitive + }; + } + + function isInjectable(value) { + return (isFunction(value) || (isArray(value) && isFunction(value[value.length - 1]))); + } + + /** + * [Internal] Get the default value of a parameter, which may be an injectable function. + */ + $UrlMatcherFactory.$$getDefaultValue = function(config) { + if (!isInjectable(config.value)) return config.value; + if (!injector) throw new Error("Injectable functions cannot be called at configuration time"); + return injector.invoke(config.value); + }; + + /** + * @ngdoc function + * @name ui.router.util.$urlMatcherFactory#caseInsensitive + * @methodOf ui.router.util.$urlMatcherFactory + * + * @description + * Defines whether URL matching should be case sensitive (the default behavior), or not. + * + * @param {boolean} value `false` to match URL in a case sensitive manner; otherwise `true`; + * @returns {boolean} the current value of caseInsensitive + */ + this.caseInsensitive = function(value) { + if (isDefined(value)) + isCaseInsensitive = value; + return isCaseInsensitive; + }; + + /** + * @ngdoc function + * @name ui.router.util.$urlMatcherFactory#strictMode + * @methodOf ui.router.util.$urlMatcherFactory + * + * @description + * Defines whether URLs should match trailing slashes, or not (the default behavior). + * + * @param {boolean=} value `false` to match trailing slashes in URLs, otherwise `true`. + * @returns {boolean} the current value of strictMode + */ + this.strictMode = function(value) { + if (isDefined(value)) + isStrictMode = value; + return isStrictMode; + }; + + /** + * @ngdoc function + * @name ui.router.util.$urlMatcherFactory#defaultSquashPolicy + * @methodOf ui.router.util.$urlMatcherFactory + * + * @description + * Sets the default behavior when generating or matching URLs with default parameter values. + * + * @param {string} value A string that defines the default parameter URL squashing behavior. + * `nosquash`: When generating an href with a default parameter value, do not squash the parameter value from the URL + * `slash`: When generating an href with a default parameter value, squash (remove) the parameter value, and, if the + * parameter is surrounded by slashes, squash (remove) one slash from the URL + * any other string, e.g. "~": When generating an href with a default parameter value, squash (remove) + * the parameter value from the URL and replace it with this string. + */ + this.defaultSquashPolicy = function(value) { + if (!isDefined(value)) return defaultSquashPolicy; + if (value !== true && value !== false && !isString(value)) + throw new Error("Invalid squash policy: " + value + ". Valid policies: false, true, arbitrary-string"); + defaultSquashPolicy = value; + return value; + }; + + /** + * @ngdoc function + * @name ui.router.util.$urlMatcherFactory#compile + * @methodOf ui.router.util.$urlMatcherFactory + * + * @description + * Creates a {@link ui.router.util.type:UrlMatcher `UrlMatcher`} for the specified pattern. + * + * @param {string} pattern The URL pattern. + * @param {Object} config The config object hash. + * @returns {UrlMatcher} The UrlMatcher. + */ + this.compile = function (pattern, config) { + return new UrlMatcher(pattern, extend(getDefaultConfig(), config)); + }; + + /** + * @ngdoc function + * @name ui.router.util.$urlMatcherFactory#isMatcher + * @methodOf ui.router.util.$urlMatcherFactory + * + * @description + * Returns true if the specified object is a `UrlMatcher`, or false otherwise. + * + * @param {Object} object The object to perform the type check against. + * @returns {Boolean} Returns `true` if the object matches the `UrlMatcher` interface, by + * implementing all the same methods. + */ + this.isMatcher = function (o) { + if (!isObject(o)) return false; + var result = true; + + forEach(UrlMatcher.prototype, function(val, name) { + if (isFunction(val)) { + result = result && (isDefined(o[name]) && isFunction(o[name])); + } + }); + return result; + }; + + /** + * @ngdoc function + * @name ui.router.util.$urlMatcherFactory#type + * @methodOf ui.router.util.$urlMatcherFactory + * + * @description + * Registers a custom {@link ui.router.util.type:Type `Type`} object that can be used to + * generate URLs with typed parameters. + * + * @param {string} name The type name. + * @param {Object|Function} definition The type definition. See + * {@link ui.router.util.type:Type `Type`} for information on the values accepted. + * @param {Object|Function} definitionFn (optional) A function that is injected before the app + * runtime starts. The result of this function is merged into the existing `definition`. + * See {@link ui.router.util.type:Type `Type`} for information on the values accepted. + * + * @returns {Object} Returns `$urlMatcherFactoryProvider`. + * + * @example + * This is a simple example of a custom type that encodes and decodes items from an + * array, using the array index as the URL-encoded value: + * + *
      +   * var list = ['John', 'Paul', 'George', 'Ringo'];
      +   *
      +   * $urlMatcherFactoryProvider.type('listItem', {
      +   *   encode: function(item) {
      +   *     // Represent the list item in the URL using its corresponding index
      +   *     return list.indexOf(item);
      +   *   },
      +   *   decode: function(item) {
      +   *     // Look up the list item by index
      +   *     return list[parseInt(item, 10)];
      +   *   },
      +   *   is: function(item) {
      +   *     // Ensure the item is valid by checking to see that it appears
      +   *     // in the list
      +   *     return list.indexOf(item) > -1;
      +   *   }
      +   * });
      +   *
      +   * $stateProvider.state('list', {
      +   *   url: "/list/{item:listItem}",
      +   *   controller: function($scope, $stateParams) {
      +   *     console.log($stateParams.item);
      +   *   }
      +   * });
      +   *
      +   * // ...
      +   *
      +   * // Changes URL to '/list/3', logs "Ringo" to the console
      +   * $state.go('list', { item: "Ringo" });
      +   * 
      + * + * This is a more complex example of a type that relies on dependency injection to + * interact with services, and uses the parameter name from the URL to infer how to + * handle encoding and decoding parameter values: + * + *
      +   * // Defines a custom type that gets a value from a service,
      +   * // where each service gets different types of values from
      +   * // a backend API:
      +   * $urlMatcherFactoryProvider.type('dbObject', {}, function(Users, Posts) {
      +   *
      +   *   // Matches up services to URL parameter names
      +   *   var services = {
      +   *     user: Users,
      +   *     post: Posts
      +   *   };
      +   *
      +   *   return {
      +   *     encode: function(object) {
      +   *       // Represent the object in the URL using its unique ID
      +   *       return object.id;
      +   *     },
      +   *     decode: function(value, key) {
      +   *       // Look up the object by ID, using the parameter
      +   *       // name (key) to call the correct service
      +   *       return services[key].findById(value);
      +   *     },
      +   *     is: function(object, key) {
      +   *       // Check that object is a valid dbObject
      +   *       return angular.isObject(object) && object.id && services[key];
      +   *     }
      +   *     equals: function(a, b) {
      +   *       // Check the equality of decoded objects by comparing
      +   *       // their unique IDs
      +   *       return a.id === b.id;
      +   *     }
      +   *   };
      +   * });
      +   *
      +   * // In a config() block, you can then attach URLs with
      +   * // type-annotated parameters:
      +   * $stateProvider.state('users', {
      +   *   url: "/users",
      +   *   // ...
      +   * }).state('users.item', {
      +   *   url: "/{user:dbObject}",
      +   *   controller: function($scope, $stateParams) {
      +   *     // $stateParams.user will now be an object returned from
      +   *     // the Users service
      +   *   },
      +   *   // ...
      +   * });
      +   * 
      + */ + this.type = function (name, definition, definitionFn) { + if (!isDefined(definition)) return $types[name]; + if ($types.hasOwnProperty(name)) throw new Error("A type named '" + name + "' has already been defined."); + + $types[name] = new Type(extend({ name: name }, definition)); + if (definitionFn) { + typeQueue.push({ name: name, def: definitionFn }); + if (!enqueue) flushTypeQueue(); + } + return this; + }; + + // `flushTypeQueue()` waits until `$urlMatcherFactory` is injected before invoking the queued `definitionFn`s + function flushTypeQueue() { + while(typeQueue.length) { + var type = typeQueue.shift(); + if (type.pattern) throw new Error("You cannot override a type's .pattern at runtime."); + angular.extend($types[type.name], injector.invoke(type.def)); + } + } + + // Register default types. Store them in the prototype of $types. + forEach(defaultTypes, function(type, name) { $types[name] = new Type(extend({name: name}, type)); }); + $types = inherit($types, {}); + + /* No need to document $get, since it returns this */ + this.$get = ['$injector', function ($injector) { + injector = $injector; + enqueue = false; + flushTypeQueue(); + + forEach(defaultTypes, function(type, name) { + if (!$types[name]) $types[name] = new Type(type); + }); + return this; + }]; + + this.Param = function Param(id, type, config, location) { + var self = this; + config = unwrapShorthand(config); + type = getType(config, type, location); + var arrayMode = getArrayMode(); + type = arrayMode ? type.$asArray(arrayMode, location === "search") : type; + if (type.name === "string" && !arrayMode && location === "path" && config.value === undefined) + config.value = ""; // for 0.2.x; in 0.3.0+ do not automatically default to "" + var isOptional = config.value !== undefined; + var squash = getSquashPolicy(config, isOptional); + var replace = getReplace(config, arrayMode, isOptional, squash); + + function unwrapShorthand(config) { + var keys = isObject(config) ? objectKeys(config) : []; + var isShorthand = indexOf(keys, "value") === -1 && indexOf(keys, "type") === -1 && + indexOf(keys, "squash") === -1 && indexOf(keys, "array") === -1; + if (isShorthand) config = { value: config }; + config.$$fn = isInjectable(config.value) ? config.value : function () { return config.value; }; + return config; + } + + function getType(config, urlType, location) { + if (config.type && urlType) throw new Error("Param '"+id+"' has two type configurations."); + if (urlType) return urlType; + if (!config.type) return (location === "config" ? $types.any : $types.string); + return config.type instanceof Type ? config.type : new Type(config.type); + } + + // array config: param name (param[]) overrides default settings. explicit config overrides param name. + function getArrayMode() { + var arrayDefaults = { array: (location === "search" ? "auto" : false) }; + var arrayParamNomenclature = id.match(/\[\]$/) ? { array: true } : {}; + return extend(arrayDefaults, arrayParamNomenclature, config).array; + } + + /** + * returns false, true, or the squash value to indicate the "default parameter url squash policy". + */ + function getSquashPolicy(config, isOptional) { + var squash = config.squash; + if (!isOptional || squash === false) return false; + if (!isDefined(squash) || squash == null) return defaultSquashPolicy; + if (squash === true || isString(squash)) return squash; + throw new Error("Invalid squash policy: '" + squash + "'. Valid policies: false, true, or arbitrary string"); + } + + function getReplace(config, arrayMode, isOptional, squash) { + var replace, configuredKeys, defaultPolicy = [ + { from: "", to: (isOptional || arrayMode ? undefined : "") }, + { from: null, to: (isOptional || arrayMode ? undefined : "") } + ]; + replace = isArray(config.replace) ? config.replace : []; + if (isString(squash)) + replace.push({ from: squash, to: undefined }); + configuredKeys = map(replace, function(item) { return item.from; } ); + return filter(defaultPolicy, function(item) { return indexOf(configuredKeys, item.from) === -1; }).concat(replace); + } + + /** + * [Internal] Get the default value of a parameter, which may be an injectable function. + */ + function $$getDefaultValue() { + if (!injector) throw new Error("Injectable functions cannot be called at configuration time"); + return injector.invoke(config.$$fn); + } + + /** + * [Internal] Gets the decoded representation of a value if the value is defined, otherwise, returns the + * default value, which may be the result of an injectable function. + */ + function $value(value) { + function hasReplaceVal(val) { return function(obj) { return obj.from === val; }; } + function $replace(value) { + var replacement = map(filter(self.replace, hasReplaceVal(value)), function(obj) { return obj.to; }); + return replacement.length ? replacement[0] : value; + } + value = $replace(value); + return isDefined(value) ? self.type.decode(value) : $$getDefaultValue(); + } + + function toString() { return "{Param:" + id + " " + type + " squash: '" + squash + "' optional: " + isOptional + "}"; } + + extend(this, { + id: id, + type: type, + location: location, + array: arrayMode, + squash: squash, + replace: replace, + isOptional: isOptional, + value: $value, + dynamic: undefined, + config: config, + toString: toString + }); + }; + + function ParamSet(params) { + extend(this, params || {}); + } + + ParamSet.prototype = { + $$new: function() { + return inherit(this, extend(new ParamSet(), { $$parent: this})); + }, + $$keys: function () { + var keys = [], chain = [], parent = this, + ignore = objectKeys(ParamSet.prototype); + while (parent) { chain.push(parent); parent = parent.$$parent; } + chain.reverse(); + forEach(chain, function(paramset) { + forEach(objectKeys(paramset), function(key) { + if (indexOf(keys, key) === -1 && indexOf(ignore, key) === -1) keys.push(key); + }); + }); + return keys; + }, + $$values: function(paramValues) { + var values = {}, self = this; + forEach(self.$$keys(), function(key) { + values[key] = self[key].value(paramValues && paramValues[key]); + }); + return values; + }, + $$equals: function(paramValues1, paramValues2) { + var equal = true, self = this; + forEach(self.$$keys(), function(key) { + var left = paramValues1 && paramValues1[key], right = paramValues2 && paramValues2[key]; + if (!self[key].type.equals(left, right)) equal = false; + }); + return equal; + }, + $$validates: function $$validate(paramValues) { + var result = true, isOptional, val, param, self = this; + + forEach(this.$$keys(), function(key) { + param = self[key]; + val = paramValues[key]; + isOptional = !val && param.isOptional; + result = result && (isOptional || !!param.type.is(val)); + }); + return result; + }, + $$parent: undefined + }; + + this.ParamSet = ParamSet; +} + +// Register as a provider so it's available to other providers +angular.module('ui.router.util').provider('$urlMatcherFactory', $UrlMatcherFactory); +angular.module('ui.router.util').run(['$urlMatcherFactory', function($urlMatcherFactory) { }]); diff --git a/public/admincp/bower_components/angular-ui-router/src/urlRouter.js b/public/admincp/bower_components/angular-ui-router/src/urlRouter.js new file mode 100644 index 000000000..2b2293762 --- /dev/null +++ b/public/admincp/bower_components/angular-ui-router/src/urlRouter.js @@ -0,0 +1,413 @@ +/** + * @ngdoc object + * @name ui.router.router.$urlRouterProvider + * + * @requires ui.router.util.$urlMatcherFactoryProvider + * @requires $locationProvider + * + * @description + * `$urlRouterProvider` has the responsibility of watching `$location`. + * When `$location` changes it runs through a list of rules one by one until a + * match is found. `$urlRouterProvider` is used behind the scenes anytime you specify + * a url in a state configuration. All urls are compiled into a UrlMatcher object. + * + * There are several methods on `$urlRouterProvider` that make it useful to use directly + * in your module config. + */ +$UrlRouterProvider.$inject = ['$locationProvider', '$urlMatcherFactoryProvider']; +function $UrlRouterProvider( $locationProvider, $urlMatcherFactory) { + var rules = [], otherwise = null, interceptDeferred = false, listener; + + // Returns a string that is a prefix of all strings matching the RegExp + function regExpPrefix(re) { + var prefix = /^\^((?:\\[^a-zA-Z0-9]|[^\\\[\]\^$*+?.()|{}]+)*)/.exec(re.source); + return (prefix != null) ? prefix[1].replace(/\\(.)/g, "$1") : ''; + } + + // Interpolates matched values into a String.replace()-style pattern + function interpolate(pattern, match) { + return pattern.replace(/\$(\$|\d{1,2})/, function (m, what) { + return match[what === '$' ? 0 : Number(what)]; + }); + } + + /** + * @ngdoc function + * @name ui.router.router.$urlRouterProvider#rule + * @methodOf ui.router.router.$urlRouterProvider + * + * @description + * Defines rules that are used by `$urlRouterProvider` to find matches for + * specific URLs. + * + * @example + *
      +   * var app = angular.module('app', ['ui.router.router']);
      +   *
      +   * app.config(function ($urlRouterProvider) {
      +   *   // Here's an example of how you might allow case insensitive urls
      +   *   $urlRouterProvider.rule(function ($injector, $location) {
      +   *     var path = $location.path(),
      +   *         normalized = path.toLowerCase();
      +   *
      +   *     if (path !== normalized) {
      +   *       return normalized;
      +   *     }
      +   *   });
      +   * });
      +   * 
      + * + * @param {object} rule Handler function that takes `$injector` and `$location` + * services as arguments. You can use them to return a valid path as a string. + * + * @return {object} `$urlRouterProvider` - `$urlRouterProvider` instance + */ + this.rule = function (rule) { + if (!isFunction(rule)) throw new Error("'rule' must be a function"); + rules.push(rule); + return this; + }; + + /** + * @ngdoc object + * @name ui.router.router.$urlRouterProvider#otherwise + * @methodOf ui.router.router.$urlRouterProvider + * + * @description + * Defines a path that is used when an invalid route is requested. + * + * @example + *
      +   * var app = angular.module('app', ['ui.router.router']);
      +   *
      +   * app.config(function ($urlRouterProvider) {
      +   *   // if the path doesn't match any of the urls you configured
      +   *   // otherwise will take care of routing the user to the
      +   *   // specified url
      +   *   $urlRouterProvider.otherwise('/index');
      +   *
      +   *   // Example of using function rule as param
      +   *   $urlRouterProvider.otherwise(function ($injector, $location) {
      +   *     return '/a/valid/url';
      +   *   });
      +   * });
      +   * 
      + * + * @param {string|object} rule The url path you want to redirect to or a function + * rule that returns the url path. The function version is passed two params: + * `$injector` and `$location` services, and must return a url string. + * + * @return {object} `$urlRouterProvider` - `$urlRouterProvider` instance + */ + this.otherwise = function (rule) { + if (isString(rule)) { + var redirect = rule; + rule = function () { return redirect; }; + } + else if (!isFunction(rule)) throw new Error("'rule' must be a function"); + otherwise = rule; + return this; + }; + + + function handleIfMatch($injector, handler, match) { + if (!match) return false; + var result = $injector.invoke(handler, handler, { $match: match }); + return isDefined(result) ? result : true; + } + + /** + * @ngdoc function + * @name ui.router.router.$urlRouterProvider#when + * @methodOf ui.router.router.$urlRouterProvider + * + * @description + * Registers a handler for a given url matching. if handle is a string, it is + * treated as a redirect, and is interpolated according to the syntax of match + * (i.e. like `String.replace()` for `RegExp`, or like a `UrlMatcher` pattern otherwise). + * + * If the handler is a function, it is injectable. It gets invoked if `$location` + * matches. You have the option of inject the match object as `$match`. + * + * The handler can return + * + * - **falsy** to indicate that the rule didn't match after all, then `$urlRouter` + * will continue trying to find another one that matches. + * - **string** which is treated as a redirect and passed to `$location.url()` + * - **void** or any **truthy** value tells `$urlRouter` that the url was handled. + * + * @example + *
      +   * var app = angular.module('app', ['ui.router.router']);
      +   *
      +   * app.config(function ($urlRouterProvider) {
      +   *   $urlRouterProvider.when($state.url, function ($match, $stateParams) {
      +   *     if ($state.$current.navigable !== state ||
      +   *         !equalForKeys($match, $stateParams) {
      +   *      $state.transitionTo(state, $match, false);
      +   *     }
      +   *   });
      +   * });
      +   * 
      + * + * @param {string|object} what The incoming path that you want to redirect. + * @param {string|object} handler The path you want to redirect your user to. + */ + this.when = function (what, handler) { + var redirect, handlerIsString = isString(handler); + if (isString(what)) what = $urlMatcherFactory.compile(what); + + if (!handlerIsString && !isFunction(handler) && !isArray(handler)) + throw new Error("invalid 'handler' in when()"); + + var strategies = { + matcher: function (what, handler) { + if (handlerIsString) { + redirect = $urlMatcherFactory.compile(handler); + handler = ['$match', function ($match) { return redirect.format($match); }]; + } + return extend(function ($injector, $location) { + return handleIfMatch($injector, handler, what.exec($location.path(), $location.search())); + }, { + prefix: isString(what.prefix) ? what.prefix : '' + }); + }, + regex: function (what, handler) { + if (what.global || what.sticky) throw new Error("when() RegExp must not be global or sticky"); + + if (handlerIsString) { + redirect = handler; + handler = ['$match', function ($match) { return interpolate(redirect, $match); }]; + } + return extend(function ($injector, $location) { + return handleIfMatch($injector, handler, what.exec($location.path())); + }, { + prefix: regExpPrefix(what) + }); + } + }; + + var check = { matcher: $urlMatcherFactory.isMatcher(what), regex: what instanceof RegExp }; + + for (var n in check) { + if (check[n]) return this.rule(strategies[n](what, handler)); + } + + throw new Error("invalid 'what' in when()"); + }; + + /** + * @ngdoc function + * @name ui.router.router.$urlRouterProvider#deferIntercept + * @methodOf ui.router.router.$urlRouterProvider + * + * @description + * Disables (or enables) deferring location change interception. + * + * If you wish to customize the behavior of syncing the URL (for example, if you wish to + * defer a transition but maintain the current URL), call this method at configuration time. + * Then, at run time, call `$urlRouter.listen()` after you have configured your own + * `$locationChangeSuccess` event handler. + * + * @example + *
      +   * var app = angular.module('app', ['ui.router.router']);
      +   *
      +   * app.config(function ($urlRouterProvider) {
      +   *
      +   *   // Prevent $urlRouter from automatically intercepting URL changes;
      +   *   // this allows you to configure custom behavior in between
      +   *   // location changes and route synchronization:
      +   *   $urlRouterProvider.deferIntercept();
      +   *
      +   * }).run(function ($rootScope, $urlRouter, UserService) {
      +   *
      +   *   $rootScope.$on('$locationChangeSuccess', function(e) {
      +   *     // UserService is an example service for managing user state
      +   *     if (UserService.isLoggedIn()) return;
      +   *
      +   *     // Prevent $urlRouter's default handler from firing
      +   *     e.preventDefault();
      +   *
      +   *     UserService.handleLogin().then(function() {
      +   *       // Once the user has logged in, sync the current URL
      +   *       // to the router:
      +   *       $urlRouter.sync();
      +   *     });
      +   *   });
      +   *
      +   *   // Configures $urlRouter's listener *after* your custom listener
      +   *   $urlRouter.listen();
      +   * });
      +   * 
      + * + * @param {boolean} defer Indicates whether to defer location change interception. Passing + no parameter is equivalent to `true`. + */ + this.deferIntercept = function (defer) { + if (defer === undefined) defer = true; + interceptDeferred = defer; + }; + + /** + * @ngdoc object + * @name ui.router.router.$urlRouter + * + * @requires $location + * @requires $rootScope + * @requires $injector + * @requires $browser + * + * @description + * + */ + this.$get = $get; + $get.$inject = ['$location', '$rootScope', '$injector', '$browser']; + function $get( $location, $rootScope, $injector, $browser) { + + var baseHref = $browser.baseHref(), location = $location.url(), lastPushedUrl; + + function appendBasePath(url, isHtml5, absolute) { + if (baseHref === '/') return url; + if (isHtml5) return baseHref.slice(0, -1) + url; + if (absolute) return baseHref.slice(1) + url; + return url; + } + + // TODO: Optimize groups of rules with non-empty prefix into some sort of decision tree + function update(evt) { + if (evt && evt.defaultPrevented) return; + var ignoreUpdate = lastPushedUrl && $location.url() === lastPushedUrl; + lastPushedUrl = undefined; + if (ignoreUpdate) return true; + + function check(rule) { + var handled = rule($injector, $location); + + if (!handled) return false; + if (isString(handled)) $location.replace().url(handled); + return true; + } + var n = rules.length, i; + + for (i = 0; i < n; i++) { + if (check(rules[i])) return; + } + // always check otherwise last to allow dynamic updates to the set of rules + if (otherwise) check(otherwise); + } + + function listen() { + listener = listener || $rootScope.$on('$locationChangeSuccess', update); + return listener; + } + + if (!interceptDeferred) listen(); + + return { + /** + * @ngdoc function + * @name ui.router.router.$urlRouter#sync + * @methodOf ui.router.router.$urlRouter + * + * @description + * Triggers an update; the same update that happens when the address bar url changes, aka `$locationChangeSuccess`. + * This method is useful when you need to use `preventDefault()` on the `$locationChangeSuccess` event, + * perform some custom logic (route protection, auth, config, redirection, etc) and then finally proceed + * with the transition by calling `$urlRouter.sync()`. + * + * @example + *
      +       * angular.module('app', ['ui.router'])
      +       *   .run(function($rootScope, $urlRouter) {
      +       *     $rootScope.$on('$locationChangeSuccess', function(evt) {
      +       *       // Halt state change from even starting
      +       *       evt.preventDefault();
      +       *       // Perform custom logic
      +       *       var meetsRequirement = ...
      +       *       // Continue with the update and state transition if logic allows
      +       *       if (meetsRequirement) $urlRouter.sync();
      +       *     });
      +       * });
      +       * 
      + */ + sync: function() { + update(); + }, + + listen: function() { + return listen(); + }, + + update: function(read) { + if (read) { + location = $location.url(); + return; + } + if ($location.url() === location) return; + + $location.url(location); + $location.replace(); + }, + + push: function(urlMatcher, params, options) { + $location.url(urlMatcher.format(params || {})); + lastPushedUrl = options && options.$$avoidResync ? $location.url() : undefined; + if (options && options.replace) $location.replace(); + }, + + /** + * @ngdoc function + * @name ui.router.router.$urlRouter#href + * @methodOf ui.router.router.$urlRouter + * + * @description + * A URL generation method that returns the compiled URL for a given + * {@link ui.router.util.type:UrlMatcher `UrlMatcher`}, populated with the provided parameters. + * + * @example + *
      +       * $bob = $urlRouter.href(new UrlMatcher("/about/:person"), {
      +       *   person: "bob"
      +       * });
      +       * // $bob == "/about/bob";
      +       * 
      + * + * @param {UrlMatcher} urlMatcher The `UrlMatcher` object which is used as the template of the URL to generate. + * @param {object=} params An object of parameter values to fill the matcher's required parameters. + * @param {object=} options Options object. The options are: + * + * - **`absolute`** - {boolean=false}, If true will generate an absolute url, e.g. "http://www.example.com/fullurl". + * + * @returns {string} Returns the fully compiled URL, or `null` if `params` fail validation against `urlMatcher` + */ + href: function(urlMatcher, params, options) { + if (!urlMatcher.validates(params)) return null; + + var isHtml5 = $locationProvider.html5Mode(); + if (angular.isObject(isHtml5)) { + isHtml5 = isHtml5.enabled; + } + + var url = urlMatcher.format(params); + options = options || {}; + + if (!isHtml5 && url !== null) { + url = "#" + $locationProvider.hashPrefix() + url; + } + url = appendBasePath(url, isHtml5, options.absolute); + + if (!options.absolute || !url) { + return url; + } + + var slash = (!isHtml5 && url ? '/' : ''), port = $location.port(); + port = (port === 80 || port === 443 ? '' : ':' + port); + + return [$location.protocol(), '://', $location.host(), port, slash, url].join(''); + } + }; + } +} + +angular.module('ui.router.router').provider('$urlRouter', $UrlRouterProvider); diff --git a/public/admincp/bower_components/angular-ui-router/src/view.js b/public/admincp/bower_components/angular-ui-router/src/view.js new file mode 100644 index 000000000..f19a3c569 --- /dev/null +++ b/public/admincp/bower_components/angular-ui-router/src/view.js @@ -0,0 +1,71 @@ + +$ViewProvider.$inject = []; +function $ViewProvider() { + + this.$get = $get; + /** + * @ngdoc object + * @name ui.router.state.$view + * + * @requires ui.router.util.$templateFactory + * @requires $rootScope + * + * @description + * + */ + $get.$inject = ['$rootScope', '$templateFactory']; + function $get( $rootScope, $templateFactory) { + return { + // $view.load('full.viewName', { template: ..., controller: ..., resolve: ..., async: false, params: ... }) + /** + * @ngdoc function + * @name ui.router.state.$view#load + * @methodOf ui.router.state.$view + * + * @description + * + * @param {string} name name + * @param {object} options option object. + */ + load: function load(name, options) { + var result, defaults = { + template: null, controller: null, view: null, locals: null, notify: true, async: true, params: {} + }; + options = extend(defaults, options); + + if (options.view) { + result = $templateFactory.fromConfig(options.view, options.params, options.locals); + } + if (result && options.notify) { + /** + * @ngdoc event + * @name ui.router.state.$state#$viewContentLoading + * @eventOf ui.router.state.$view + * @eventType broadcast on root scope + * @description + * + * Fired once the view **begins loading**, *before* the DOM is rendered. + * + * @param {Object} event Event object. + * @param {Object} viewConfig The view config properties (template, controller, etc). + * + * @example + * + *
      +         * $scope.$on('$viewContentLoading',
      +         * function(event, viewConfig){
      +         *     // Access to all the view config properties.
      +         *     // and one special property 'targetView'
      +         *     // viewConfig.targetView
      +         * });
      +         * 
      + */ + $rootScope.$broadcast('$viewContentLoading', options); + } + return result; + } + }; + } +} + +angular.module('ui.router.state').provider('$view', $ViewProvider); diff --git a/public/admincp/bower_components/angular-ui-router/src/viewDirective.js b/public/admincp/bower_components/angular-ui-router/src/viewDirective.js new file mode 100644 index 000000000..d3cf100a2 --- /dev/null +++ b/public/admincp/bower_components/angular-ui-router/src/viewDirective.js @@ -0,0 +1,302 @@ +/** + * @ngdoc directive + * @name ui.router.state.directive:ui-view + * + * @requires ui.router.state.$state + * @requires $compile + * @requires $controller + * @requires $injector + * @requires ui.router.state.$uiViewScroll + * @requires $document + * + * @restrict ECA + * + * @description + * The ui-view directive tells $state where to place your templates. + * + * @param {string=} name A view name. The name should be unique amongst the other views in the + * same state. You can have views of the same name that live in different states. + * + * @param {string=} autoscroll It allows you to set the scroll behavior of the browser window + * when a view is populated. By default, $anchorScroll is overridden by ui-router's custom scroll + * service, {@link ui.router.state.$uiViewScroll}. This custom service let's you + * scroll ui-view elements into view when they are populated during a state activation. + * + * *Note: To revert back to old [`$anchorScroll`](http://docs.angularjs.org/api/ng.$anchorScroll) + * functionality, call `$uiViewScrollProvider.useAnchorScroll()`.* + * + * @param {string=} onload Expression to evaluate whenever the view updates. + * + * @example + * A view can be unnamed or named. + *
      + * 
      + * 
      + * + * + *
      + *
      + * + * You can only have one unnamed view within any template (or root html). If you are only using a + * single view and it is unnamed then you can populate it like so: + *
      + * 
      + * $stateProvider.state("home", { + * template: "

      HELLO!

      " + * }) + *
      + * + * The above is a convenient shortcut equivalent to specifying your view explicitly with the {@link ui.router.state.$stateProvider#views `views`} + * config property, by name, in this case an empty name: + *
      + * $stateProvider.state("home", {
      + *   views: {
      + *     "": {
      + *       template: "

      HELLO!

      " + * } + * } + * }) + *
      + * + * But typically you'll only use the views property if you name your view or have more than one view + * in the same template. There's not really a compelling reason to name a view if its the only one, + * but you could if you wanted, like so: + *
      + * 
      + *
      + *
      + * $stateProvider.state("home", {
      + *   views: {
      + *     "main": {
      + *       template: "

      HELLO!

      " + * } + * } + * }) + *
      + * + * Really though, you'll use views to set up multiple views: + *
      + * 
      + *
      + *
      + *
      + * + *
      + * $stateProvider.state("home", {
      + *   views: {
      + *     "": {
      + *       template: "

      HELLO!

      " + * }, + * "chart": { + * template: "" + * }, + * "data": { + * template: "" + * } + * } + * }) + *
      + * + * Examples for `autoscroll`: + * + *
      + * 
      + * 
      + *
      + * 
      + * 
      + * 
      + * 
      + * 
      + */ +$ViewDirective.$inject = ['$state', '$injector', '$uiViewScroll', '$interpolate']; +function $ViewDirective( $state, $injector, $uiViewScroll, $interpolate) { + + function getService() { + return ($injector.has) ? function(service) { + return $injector.has(service) ? $injector.get(service) : null; + } : function(service) { + try { + return $injector.get(service); + } catch (e) { + return null; + } + }; + } + + var service = getService(), + $animator = service('$animator'), + $animate = service('$animate'); + + // Returns a set of DOM manipulation functions based on which Angular version + // it should use + function getRenderer(attrs, scope) { + var statics = function() { + return { + enter: function (element, target, cb) { target.after(element); cb(); }, + leave: function (element, cb) { element.remove(); cb(); } + }; + }; + + if ($animate) { + return { + enter: function(element, target, cb) { + var promise = $animate.enter(element, null, target, cb); + if (promise && promise.then) promise.then(cb); + }, + leave: function(element, cb) { + var promise = $animate.leave(element, cb); + if (promise && promise.then) promise.then(cb); + } + }; + } + + if ($animator) { + var animate = $animator && $animator(scope, attrs); + + return { + enter: function(element, target, cb) {animate.enter(element, null, target); cb(); }, + leave: function(element, cb) { animate.leave(element); cb(); } + }; + } + + return statics(); + } + + var directive = { + restrict: 'ECA', + terminal: true, + priority: 400, + transclude: 'element', + compile: function (tElement, tAttrs, $transclude) { + return function (scope, $element, attrs) { + var previousEl, currentEl, currentScope, latestLocals, + onloadExp = attrs.onload || '', + autoScrollExp = attrs.autoscroll, + renderer = getRenderer(attrs, scope); + + scope.$on('$stateChangeSuccess', function() { + updateView(false); + }); + scope.$on('$viewContentLoading', function() { + updateView(false); + }); + + updateView(true); + + function cleanupLastView() { + if (previousEl) { + previousEl.remove(); + previousEl = null; + } + + if (currentScope) { + currentScope.$destroy(); + currentScope = null; + } + + if (currentEl) { + renderer.leave(currentEl, function() { + previousEl = null; + }); + + previousEl = currentEl; + currentEl = null; + } + } + + function updateView(firstTime) { + var newScope, + name = getUiViewName(scope, attrs, $element, $interpolate), + previousLocals = name && $state.$current && $state.$current.locals[name]; + + if (!firstTime && previousLocals === latestLocals) return; // nothing to do + newScope = scope.$new(); + latestLocals = $state.$current.locals[name]; + + var clone = $transclude(newScope, function(clone) { + renderer.enter(clone, $element, function onUiViewEnter() { + if(currentScope) { + currentScope.$emit('$viewContentAnimationEnded'); + } + + if (angular.isDefined(autoScrollExp) && !autoScrollExp || scope.$eval(autoScrollExp)) { + $uiViewScroll(clone); + } + }); + cleanupLastView(); + }); + + currentEl = clone; + currentScope = newScope; + /** + * @ngdoc event + * @name ui.router.state.directive:ui-view#$viewContentLoaded + * @eventOf ui.router.state.directive:ui-view + * @eventType emits on ui-view directive scope + * @description * + * Fired once the view is **loaded**, *after* the DOM is rendered. + * + * @param {Object} event Event object. + */ + currentScope.$emit('$viewContentLoaded'); + currentScope.$eval(onloadExp); + } + }; + } + }; + + return directive; +} + +$ViewDirectiveFill.$inject = ['$compile', '$controller', '$state', '$interpolate']; +function $ViewDirectiveFill ( $compile, $controller, $state, $interpolate) { + return { + restrict: 'ECA', + priority: -400, + compile: function (tElement) { + var initial = tElement.html(); + return function (scope, $element, attrs) { + var current = $state.$current, + name = getUiViewName(scope, attrs, $element, $interpolate), + locals = current && current.locals[name]; + + if (! locals) { + return; + } + + $element.data('$uiView', { name: name, state: locals.$$state }); + $element.html(locals.$template ? locals.$template : initial); + + var link = $compile($element.contents()); + + if (locals.$$controller) { + locals.$scope = scope; + var controller = $controller(locals.$$controller, locals); + if (locals.$$controllerAs) { + scope[locals.$$controllerAs] = controller; + } + $element.data('$ngControllerController', controller); + $element.children().data('$ngControllerController', controller); + } + + link(scope); + }; + } + }; +} + +/** + * Shared ui-view code for both directives: + * Given scope, element, and its attributes, return the view's name + */ +function getUiViewName(scope, attrs, element, $interpolate) { + var name = $interpolate(attrs.uiView || attrs.name || '')(scope); + var inherited = element.inheritedData('$uiView'); + return name.indexOf('@') >= 0 ? name : (name + '@' + (inherited ? inherited.state.name : '')); +} + +angular.module('ui.router.state').directive('uiView', $ViewDirective); +angular.module('ui.router.state').directive('uiView', $ViewDirectiveFill); diff --git a/public/admincp/bower_components/angular-ui-router/src/viewScroll.js b/public/admincp/bower_components/angular-ui-router/src/viewScroll.js new file mode 100644 index 000000000..dfe0a030d --- /dev/null +++ b/public/admincp/bower_components/angular-ui-router/src/viewScroll.js @@ -0,0 +1,52 @@ +/** + * @ngdoc object + * @name ui.router.state.$uiViewScrollProvider + * + * @description + * Provider that returns the {@link ui.router.state.$uiViewScroll} service function. + */ +function $ViewScrollProvider() { + + var useAnchorScroll = false; + + /** + * @ngdoc function + * @name ui.router.state.$uiViewScrollProvider#useAnchorScroll + * @methodOf ui.router.state.$uiViewScrollProvider + * + * @description + * Reverts back to using the core [`$anchorScroll`](http://docs.angularjs.org/api/ng.$anchorScroll) service for + * scrolling based on the url anchor. + */ + this.useAnchorScroll = function () { + useAnchorScroll = true; + }; + + /** + * @ngdoc object + * @name ui.router.state.$uiViewScroll + * + * @requires $anchorScroll + * @requires $timeout + * + * @description + * When called with a jqLite element, it scrolls the element into view (after a + * `$timeout` so the DOM has time to refresh). + * + * If you prefer to rely on `$anchorScroll` to scroll the view to the anchor, + * this can be enabled by calling {@link ui.router.state.$uiViewScrollProvider#methods_useAnchorScroll `$uiViewScrollProvider.useAnchorScroll()`}. + */ + this.$get = ['$anchorScroll', '$timeout', function ($anchorScroll, $timeout) { + if (useAnchorScroll) { + return $anchorScroll; + } + + return function ($element) { + $timeout(function () { + $element[0].scrollIntoView(); + }, 0, false); + }; + }]; +} + +angular.module('ui.router.state').provider('$uiViewScroll', $ViewScrollProvider); diff --git a/public/admincp/bower_components/angular/.bower.json b/public/admincp/bower_components/angular/.bower.json new file mode 100644 index 000000000..b73a6cfcf --- /dev/null +++ b/public/admincp/bower_components/angular/.bower.json @@ -0,0 +1,17 @@ +{ + "name": "angular", + "version": "1.3.8", + "main": "./angular.js", + "ignore": [], + "dependencies": {}, + "homepage": "https://github.com/angular/bower-angular", + "_release": "1.3.8", + "_resolution": { + "type": "version", + "tag": "v1.3.8", + "commit": "3c90c24001beb2e69bcadcd785a9b6194cf590c0" + }, + "_source": "git://github.com/angular/bower-angular.git", + "_target": "1.3.8", + "_originalSource": "angular" +} \ No newline at end of file diff --git a/public/admincp/bower_components/angular/README.md b/public/admincp/bower_components/angular/README.md new file mode 100644 index 000000000..897fb7f01 --- /dev/null +++ b/public/admincp/bower_components/angular/README.md @@ -0,0 +1,67 @@ +# packaged angular + +This repo is for distribution on `npm` and `bower`. The source for this module is in the +[main AngularJS repo](https://github.com/angular/angular.js). +Please file issues and pull requests against that repo. + +## Install + +You can install this package either with `npm` or with `bower`. + +### npm + +```shell +npm install angular +``` + +Then add a ` +``` + +Note that this package is not in CommonJS format, so doing `require('angular')` will return `undefined`. +If you're using [Browserify](https://github.com/substack/node-browserify), you can use +[exposify](https://github.com/thlorenz/exposify) to have `require('angular')` return the `angular` +global. + +### bower + +```shell +bower install angular +``` + +Then add a ` +``` + +## Documentation + +Documentation is available on the +[AngularJS docs site](http://docs.angularjs.org/). + +## License + +The MIT License + +Copyright (c) 2010-2012 Google, Inc. http://angularjs.org + +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/public/admincp/bower_components/angular/angular-csp.css b/public/admincp/bower_components/angular/angular-csp.css new file mode 100644 index 000000000..0ce9d864c --- /dev/null +++ b/public/admincp/bower_components/angular/angular-csp.css @@ -0,0 +1,13 @@ +/* Include this file in your html if you are using the CSP mode. */ + +@charset "UTF-8"; + +[ng\:cloak], [ng-cloak], [data-ng-cloak], [x-ng-cloak], +.ng-cloak, .x-ng-cloak, +.ng-hide:not(.ng-hide-animate) { + display: none !important; +} + +ng\:form { + display: block; +} diff --git a/public/admincp/bower_components/angular/angular.js b/public/admincp/bower_components/angular/angular.js new file mode 100644 index 000000000..b740cde01 --- /dev/null +++ b/public/admincp/bower_components/angular/angular.js @@ -0,0 +1,26070 @@ +/** + * @license AngularJS v1.3.8 + * (c) 2010-2014 Google, Inc. http://angularjs.org + * License: MIT + */ +(function(window, document, undefined) {'use strict'; + +/** + * @description + * + * This object provides a utility for producing rich Error messages within + * Angular. It can be called as follows: + * + * var exampleMinErr = minErr('example'); + * throw exampleMinErr('one', 'This {0} is {1}', foo, bar); + * + * The above creates an instance of minErr in the example namespace. The + * resulting error will have a namespaced error code of example.one. The + * resulting error will replace {0} with the value of foo, and {1} with the + * value of bar. The object is not restricted in the number of arguments it can + * take. + * + * If fewer arguments are specified than necessary for interpolation, the extra + * interpolation markers will be preserved in the final string. + * + * Since data will be parsed statically during a build step, some restrictions + * are applied with respect to how minErr instances are created and called. + * Instances should have names of the form namespaceMinErr for a minErr created + * using minErr('namespace') . Error codes, namespaces and template strings + * should all be static strings, not variables or general expressions. + * + * @param {string} module The namespace to use for the new minErr instance. + * @param {function} ErrorConstructor Custom error constructor to be instantiated when returning + * error from returned function, for cases when a particular type of error is useful. + * @returns {function(code:string, template:string, ...templateArgs): Error} minErr instance + */ + +function minErr(module, ErrorConstructor) { + ErrorConstructor = ErrorConstructor || Error; + return function() { + var code = arguments[0], + prefix = '[' + (module ? module + ':' : '') + code + '] ', + template = arguments[1], + templateArgs = arguments, + + message, i; + + message = prefix + template.replace(/\{\d+\}/g, function(match) { + var index = +match.slice(1, -1), arg; + + if (index + 2 < templateArgs.length) { + return toDebugString(templateArgs[index + 2]); + } + return match; + }); + + message = message + '\nhttp://errors.angularjs.org/1.3.8/' + + (module ? module + '/' : '') + code; + for (i = 2; i < arguments.length; i++) { + message = message + (i == 2 ? '?' : '&') + 'p' + (i - 2) + '=' + + encodeURIComponent(toDebugString(arguments[i])); + } + return new ErrorConstructor(message); + }; +} + +/* We need to tell jshint what variables are being exported */ +/* global angular: true, + msie: true, + jqLite: true, + jQuery: true, + slice: true, + splice: true, + push: true, + toString: true, + ngMinErr: true, + angularModule: true, + uid: true, + REGEX_STRING_REGEXP: true, + VALIDITY_STATE_PROPERTY: true, + + lowercase: true, + uppercase: true, + manualLowercase: true, + manualUppercase: true, + nodeName_: true, + isArrayLike: true, + forEach: true, + sortedKeys: true, + forEachSorted: true, + reverseParams: true, + nextUid: true, + setHashKey: true, + extend: true, + int: true, + inherit: true, + noop: true, + identity: true, + valueFn: true, + isUndefined: true, + isDefined: true, + isObject: true, + isString: true, + isNumber: true, + isDate: true, + isArray: true, + isFunction: true, + isRegExp: true, + isWindow: true, + isScope: true, + isFile: true, + isFormData: true, + isBlob: true, + isBoolean: true, + isPromiseLike: true, + trim: true, + escapeForRegexp: true, + isElement: true, + makeMap: true, + includes: true, + arrayRemove: true, + copy: true, + shallowCopy: true, + equals: true, + csp: true, + concat: true, + sliceArgs: true, + bind: true, + toJsonReplacer: true, + toJson: true, + fromJson: true, + startingTag: true, + tryDecodeURIComponent: true, + parseKeyValue: true, + toKeyValue: true, + encodeUriSegment: true, + encodeUriQuery: true, + angularInit: true, + bootstrap: true, + getTestability: true, + snake_case: true, + bindJQuery: true, + assertArg: true, + assertArgFn: true, + assertNotHasOwnProperty: true, + getter: true, + getBlockNodes: true, + hasOwnProperty: true, + createMap: true, + + NODE_TYPE_ELEMENT: true, + NODE_TYPE_TEXT: true, + NODE_TYPE_COMMENT: true, + NODE_TYPE_DOCUMENT: true, + NODE_TYPE_DOCUMENT_FRAGMENT: true, +*/ + +//////////////////////////////////// + +/** + * @ngdoc module + * @name ng + * @module ng + * @description + * + * # ng (core module) + * The ng module is loaded by default when an AngularJS application is started. The module itself + * contains the essential components for an AngularJS application to function. The table below + * lists a high level breakdown of each of the services/factories, filters, directives and testing + * components available within this core module. + * + *
      + */ + +var REGEX_STRING_REGEXP = /^\/(.+)\/([a-z]*)$/; + +// The name of a form control's ValidityState property. +// This is used so that it's possible for internal tests to create mock ValidityStates. +var VALIDITY_STATE_PROPERTY = 'validity'; + +/** + * @ngdoc function + * @name angular.lowercase + * @module ng + * @kind function + * + * @description Converts the specified string to lowercase. + * @param {string} string String to be converted to lowercase. + * @returns {string} Lowercased string. + */ +var lowercase = function(string) {return isString(string) ? string.toLowerCase() : string;}; +var hasOwnProperty = Object.prototype.hasOwnProperty; + +/** + * @ngdoc function + * @name angular.uppercase + * @module ng + * @kind function + * + * @description Converts the specified string to uppercase. + * @param {string} string String to be converted to uppercase. + * @returns {string} Uppercased string. + */ +var uppercase = function(string) {return isString(string) ? string.toUpperCase() : string;}; + + +var manualLowercase = function(s) { + /* jshint bitwise: false */ + return isString(s) + ? s.replace(/[A-Z]/g, function(ch) {return String.fromCharCode(ch.charCodeAt(0) | 32);}) + : s; +}; +var manualUppercase = function(s) { + /* jshint bitwise: false */ + return isString(s) + ? s.replace(/[a-z]/g, function(ch) {return String.fromCharCode(ch.charCodeAt(0) & ~32);}) + : s; +}; + + +// String#toLowerCase and String#toUpperCase don't produce correct results in browsers with Turkish +// locale, for this reason we need to detect this case and redefine lowercase/uppercase methods +// with correct but slower alternatives. +if ('i' !== 'I'.toLowerCase()) { + lowercase = manualLowercase; + uppercase = manualUppercase; +} + + +var + msie, // holds major version number for IE, or NaN if UA is not IE. + jqLite, // delay binding since jQuery could be loaded after us. + jQuery, // delay binding + slice = [].slice, + splice = [].splice, + push = [].push, + toString = Object.prototype.toString, + ngMinErr = minErr('ng'), + + /** @name angular */ + angular = window.angular || (window.angular = {}), + angularModule, + uid = 0; + +/** + * documentMode is an IE-only property + * http://msdn.microsoft.com/en-us/library/ie/cc196988(v=vs.85).aspx + */ +msie = document.documentMode; + + +/** + * @private + * @param {*} obj + * @return {boolean} Returns true if `obj` is an array or array-like object (NodeList, Arguments, + * String ...) + */ +function isArrayLike(obj) { + if (obj == null || isWindow(obj)) { + return false; + } + + var length = obj.length; + + if (obj.nodeType === NODE_TYPE_ELEMENT && length) { + return true; + } + + return isString(obj) || isArray(obj) || length === 0 || + typeof length === 'number' && length > 0 && (length - 1) in obj; +} + +/** + * @ngdoc function + * @name angular.forEach + * @module ng + * @kind function + * + * @description + * Invokes the `iterator` function once for each item in `obj` collection, which can be either an + * object or an array. The `iterator` function is invoked with `iterator(value, key, obj)`, where `value` + * is the value of an object property or an array element, `key` is the object property key or + * array element index and obj is the `obj` itself. Specifying a `context` for the function is optional. + * + * It is worth noting that `.forEach` does not iterate over inherited properties because it filters + * using the `hasOwnProperty` method. + * + * Unlike ES262's + * [Array.prototype.forEach](http://www.ecma-international.org/ecma-262/5.1/#sec-15.4.4.18), + * Providing 'undefined' or 'null' values for `obj` will not throw a TypeError, but rather just + * return the value provided. + * + ```js + var values = {name: 'misko', gender: 'male'}; + var log = []; + angular.forEach(values, function(value, key) { + this.push(key + ': ' + value); + }, log); + expect(log).toEqual(['name: misko', 'gender: male']); + ``` + * + * @param {Object|Array} obj Object to iterate over. + * @param {Function} iterator Iterator function. + * @param {Object=} context Object to become context (`this`) for the iterator function. + * @returns {Object|Array} Reference to `obj`. + */ + +function forEach(obj, iterator, context) { + var key, length; + if (obj) { + if (isFunction(obj)) { + for (key in obj) { + // Need to check if hasOwnProperty exists, + // as on IE8 the result of querySelectorAll is an object without a hasOwnProperty function + if (key != 'prototype' && key != 'length' && key != 'name' && (!obj.hasOwnProperty || obj.hasOwnProperty(key))) { + iterator.call(context, obj[key], key, obj); + } + } + } else if (isArray(obj) || isArrayLike(obj)) { + var isPrimitive = typeof obj !== 'object'; + for (key = 0, length = obj.length; key < length; key++) { + if (isPrimitive || key in obj) { + iterator.call(context, obj[key], key, obj); + } + } + } else if (obj.forEach && obj.forEach !== forEach) { + obj.forEach(iterator, context, obj); + } else { + for (key in obj) { + if (obj.hasOwnProperty(key)) { + iterator.call(context, obj[key], key, obj); + } + } + } + } + return obj; +} + +function sortedKeys(obj) { + return Object.keys(obj).sort(); +} + +function forEachSorted(obj, iterator, context) { + var keys = sortedKeys(obj); + for (var i = 0; i < keys.length; i++) { + iterator.call(context, obj[keys[i]], keys[i]); + } + return keys; +} + + +/** + * when using forEach the params are value, key, but it is often useful to have key, value. + * @param {function(string, *)} iteratorFn + * @returns {function(*, string)} + */ +function reverseParams(iteratorFn) { + return function(value, key) { iteratorFn(key, value); }; +} + +/** + * A consistent way of creating unique IDs in angular. + * + * Using simple numbers allows us to generate 28.6 million unique ids per second for 10 years before + * we hit number precision issues in JavaScript. + * + * Math.pow(2,53) / 60 / 60 / 24 / 365 / 10 = 28.6M + * + * @returns {number} an unique alpha-numeric string + */ +function nextUid() { + return ++uid; +} + + +/** + * Set or clear the hashkey for an object. + * @param obj object + * @param h the hashkey (!truthy to delete the hashkey) + */ +function setHashKey(obj, h) { + if (h) { + obj.$$hashKey = h; + } + else { + delete obj.$$hashKey; + } +} + +/** + * @ngdoc function + * @name angular.extend + * @module ng + * @kind function + * + * @description + * Extends the destination object `dst` by copying own enumerable properties from the `src` object(s) + * to `dst`. You can specify multiple `src` objects. If you want to preserve original objects, you can do so + * by passing an empty object as the target: `var object = angular.extend({}, object1, object2)`. + * Note: Keep in mind that `angular.extend` does not support recursive merge (deep copy). + * + * @param {Object} dst Destination object. + * @param {...Object} src Source object(s). + * @returns {Object} Reference to `dst`. + */ +function extend(dst) { + var h = dst.$$hashKey; + + for (var i = 1, ii = arguments.length; i < ii; i++) { + var obj = arguments[i]; + if (obj) { + var keys = Object.keys(obj); + for (var j = 0, jj = keys.length; j < jj; j++) { + var key = keys[j]; + dst[key] = obj[key]; + } + } + } + + setHashKey(dst, h); + return dst; +} + +function int(str) { + return parseInt(str, 10); +} + + +function inherit(parent, extra) { + return extend(Object.create(parent), extra); +} + +/** + * @ngdoc function + * @name angular.noop + * @module ng + * @kind function + * + * @description + * A function that performs no operations. This function can be useful when writing code in the + * functional style. + ```js + function foo(callback) { + var result = calculateResult(); + (callback || angular.noop)(result); + } + ``` + */ +function noop() {} +noop.$inject = []; + + +/** + * @ngdoc function + * @name angular.identity + * @module ng + * @kind function + * + * @description + * A function that returns its first argument. This function is useful when writing code in the + * functional style. + * + ```js + function transformer(transformationFn, value) { + return (transformationFn || angular.identity)(value); + }; + ``` + * @param {*} value to be returned. + * @returns {*} the value passed in. + */ +function identity($) {return $;} +identity.$inject = []; + + +function valueFn(value) {return function() {return value;};} + +/** + * @ngdoc function + * @name angular.isUndefined + * @module ng + * @kind function + * + * @description + * Determines if a reference is undefined. + * + * @param {*} value Reference to check. + * @returns {boolean} True if `value` is undefined. + */ +function isUndefined(value) {return typeof value === 'undefined';} + + +/** + * @ngdoc function + * @name angular.isDefined + * @module ng + * @kind function + * + * @description + * Determines if a reference is defined. + * + * @param {*} value Reference to check. + * @returns {boolean} True if `value` is defined. + */ +function isDefined(value) {return typeof value !== 'undefined';} + + +/** + * @ngdoc function + * @name angular.isObject + * @module ng + * @kind function + * + * @description + * Determines if a reference is an `Object`. Unlike `typeof` in JavaScript, `null`s are not + * considered to be objects. Note that JavaScript arrays are objects. + * + * @param {*} value Reference to check. + * @returns {boolean} True if `value` is an `Object` but not `null`. + */ +function isObject(value) { + // http://jsperf.com/isobject4 + return value !== null && typeof value === 'object'; +} + + +/** + * @ngdoc function + * @name angular.isString + * @module ng + * @kind function + * + * @description + * Determines if a reference is a `String`. + * + * @param {*} value Reference to check. + * @returns {boolean} True if `value` is a `String`. + */ +function isString(value) {return typeof value === 'string';} + + +/** + * @ngdoc function + * @name angular.isNumber + * @module ng + * @kind function + * + * @description + * Determines if a reference is a `Number`. + * + * @param {*} value Reference to check. + * @returns {boolean} True if `value` is a `Number`. + */ +function isNumber(value) {return typeof value === 'number';} + + +/** + * @ngdoc function + * @name angular.isDate + * @module ng + * @kind function + * + * @description + * Determines if a value is a date. + * + * @param {*} value Reference to check. + * @returns {boolean} True if `value` is a `Date`. + */ +function isDate(value) { + return toString.call(value) === '[object Date]'; +} + + +/** + * @ngdoc function + * @name angular.isArray + * @module ng + * @kind function + * + * @description + * Determines if a reference is an `Array`. + * + * @param {*} value Reference to check. + * @returns {boolean} True if `value` is an `Array`. + */ +var isArray = Array.isArray; + +/** + * @ngdoc function + * @name angular.isFunction + * @module ng + * @kind function + * + * @description + * Determines if a reference is a `Function`. + * + * @param {*} value Reference to check. + * @returns {boolean} True if `value` is a `Function`. + */ +function isFunction(value) {return typeof value === 'function';} + + +/** + * Determines if a value is a regular expression object. + * + * @private + * @param {*} value Reference to check. + * @returns {boolean} True if `value` is a `RegExp`. + */ +function isRegExp(value) { + return toString.call(value) === '[object RegExp]'; +} + + +/** + * Checks if `obj` is a window object. + * + * @private + * @param {*} obj Object to check + * @returns {boolean} True if `obj` is a window obj. + */ +function isWindow(obj) { + return obj && obj.window === obj; +} + + +function isScope(obj) { + return obj && obj.$evalAsync && obj.$watch; +} + + +function isFile(obj) { + return toString.call(obj) === '[object File]'; +} + + +function isFormData(obj) { + return toString.call(obj) === '[object FormData]'; +} + + +function isBlob(obj) { + return toString.call(obj) === '[object Blob]'; +} + + +function isBoolean(value) { + return typeof value === 'boolean'; +} + + +function isPromiseLike(obj) { + return obj && isFunction(obj.then); +} + + +var trim = function(value) { + return isString(value) ? value.trim() : value; +}; + +// Copied from: +// http://docs.closure-library.googlecode.com/git/local_closure_goog_string_string.js.source.html#line1021 +// Prereq: s is a string. +var escapeForRegexp = function(s) { + return s.replace(/([-()\[\]{}+?*.$\^|,:#= 0) + array.splice(index, 1); + return value; +} + +/** + * @ngdoc function + * @name angular.copy + * @module ng + * @kind function + * + * @description + * Creates a deep copy of `source`, which should be an object or an array. + * + * * If no destination is supplied, a copy of the object or array is created. + * * If a destination is provided, all of its elements (for arrays) or properties (for objects) + * are deleted and then all elements/properties from the source are copied to it. + * * If `source` is not an object or array (inc. `null` and `undefined`), `source` is returned. + * * If `source` is identical to 'destination' an exception will be thrown. + * + * @param {*} source The source that will be used to make a copy. + * Can be any type, including primitives, `null`, and `undefined`. + * @param {(Object|Array)=} destination Destination into which the source is copied. If + * provided, must be of the same type as `source`. + * @returns {*} The copy or updated `destination`, if `destination` was specified. + * + * @example + + +
      +
      + Name:
      + E-mail:
      + Gender: male + female
      + + +
      +
      form = {{user | json}}
      +
      master = {{master | json}}
      +
      + + +
      +
      + */ +function copy(source, destination, stackSource, stackDest) { + if (isWindow(source) || isScope(source)) { + throw ngMinErr('cpws', + "Can't copy! Making copies of Window or Scope instances is not supported."); + } + + if (!destination) { + destination = source; + if (source) { + if (isArray(source)) { + destination = copy(source, [], stackSource, stackDest); + } else if (isDate(source)) { + destination = new Date(source.getTime()); + } else if (isRegExp(source)) { + destination = new RegExp(source.source, source.toString().match(/[^\/]*$/)[0]); + destination.lastIndex = source.lastIndex; + } else if (isObject(source)) { + var emptyObject = Object.create(Object.getPrototypeOf(source)); + destination = copy(source, emptyObject, stackSource, stackDest); + } + } + } else { + if (source === destination) throw ngMinErr('cpi', + "Can't copy! Source and destination are identical."); + + stackSource = stackSource || []; + stackDest = stackDest || []; + + if (isObject(source)) { + var index = stackSource.indexOf(source); + if (index !== -1) return stackDest[index]; + + stackSource.push(source); + stackDest.push(destination); + } + + var result; + if (isArray(source)) { + destination.length = 0; + for (var i = 0; i < source.length; i++) { + result = copy(source[i], null, stackSource, stackDest); + if (isObject(source[i])) { + stackSource.push(source[i]); + stackDest.push(result); + } + destination.push(result); + } + } else { + var h = destination.$$hashKey; + if (isArray(destination)) { + destination.length = 0; + } else { + forEach(destination, function(value, key) { + delete destination[key]; + }); + } + for (var key in source) { + if (source.hasOwnProperty(key)) { + result = copy(source[key], null, stackSource, stackDest); + if (isObject(source[key])) { + stackSource.push(source[key]); + stackDest.push(result); + } + destination[key] = result; + } + } + setHashKey(destination,h); + } + + } + return destination; +} + +/** + * Creates a shallow copy of an object, an array or a primitive. + * + * Assumes that there are no proto properties for objects. + */ +function shallowCopy(src, dst) { + if (isArray(src)) { + dst = dst || []; + + for (var i = 0, ii = src.length; i < ii; i++) { + dst[i] = src[i]; + } + } else if (isObject(src)) { + dst = dst || {}; + + for (var key in src) { + if (!(key.charAt(0) === '$' && key.charAt(1) === '$')) { + dst[key] = src[key]; + } + } + } + + return dst || src; +} + + +/** + * @ngdoc function + * @name angular.equals + * @module ng + * @kind function + * + * @description + * Determines if two objects or two values are equivalent. Supports value types, regular + * expressions, arrays and objects. + * + * Two objects or values are considered equivalent if at least one of the following is true: + * + * * Both objects or values pass `===` comparison. + * * Both objects or values are of the same type and all of their properties are equal by + * comparing them with `angular.equals`. + * * Both values are NaN. (In JavaScript, NaN == NaN => false. But we consider two NaN as equal) + * * Both values represent the same regular expression (In JavaScript, + * /abc/ == /abc/ => false. But we consider two regular expressions as equal when their textual + * representation matches). + * + * During a property comparison, properties of `function` type and properties with names + * that begin with `$` are ignored. + * + * Scope and DOMWindow objects are being compared only by identify (`===`). + * + * @param {*} o1 Object or value to compare. + * @param {*} o2 Object or value to compare. + * @returns {boolean} True if arguments are equal. + */ +function equals(o1, o2) { + if (o1 === o2) return true; + if (o1 === null || o2 === null) return false; + if (o1 !== o1 && o2 !== o2) return true; // NaN === NaN + var t1 = typeof o1, t2 = typeof o2, length, key, keySet; + if (t1 == t2) { + if (t1 == 'object') { + if (isArray(o1)) { + if (!isArray(o2)) return false; + if ((length = o1.length) == o2.length) { + for (key = 0; key < length; key++) { + if (!equals(o1[key], o2[key])) return false; + } + return true; + } + } else if (isDate(o1)) { + if (!isDate(o2)) return false; + return equals(o1.getTime(), o2.getTime()); + } else if (isRegExp(o1) && isRegExp(o2)) { + return o1.toString() == o2.toString(); + } else { + if (isScope(o1) || isScope(o2) || isWindow(o1) || isWindow(o2) || isArray(o2)) return false; + keySet = {}; + for (key in o1) { + if (key.charAt(0) === '$' || isFunction(o1[key])) continue; + if (!equals(o1[key], o2[key])) return false; + keySet[key] = true; + } + for (key in o2) { + if (!keySet.hasOwnProperty(key) && + key.charAt(0) !== '$' && + o2[key] !== undefined && + !isFunction(o2[key])) return false; + } + return true; + } + } + } + return false; +} + +var csp = function() { + if (isDefined(csp.isActive_)) return csp.isActive_; + + var active = !!(document.querySelector('[ng-csp]') || + document.querySelector('[data-ng-csp]')); + + if (!active) { + try { + /* jshint -W031, -W054 */ + new Function(''); + /* jshint +W031, +W054 */ + } catch (e) { + active = true; + } + } + + return (csp.isActive_ = active); +}; + + + +function concat(array1, array2, index) { + return array1.concat(slice.call(array2, index)); +} + +function sliceArgs(args, startIndex) { + return slice.call(args, startIndex || 0); +} + + +/* jshint -W101 */ +/** + * @ngdoc function + * @name angular.bind + * @module ng + * @kind function + * + * @description + * Returns a function which calls function `fn` bound to `self` (`self` becomes the `this` for + * `fn`). You can supply optional `args` that are prebound to the function. This feature is also + * known as [partial application](http://en.wikipedia.org/wiki/Partial_application), as + * distinguished from [function currying](http://en.wikipedia.org/wiki/Currying#Contrast_with_partial_function_application). + * + * @param {Object} self Context which `fn` should be evaluated in. + * @param {function()} fn Function to be bound. + * @param {...*} args Optional arguments to be prebound to the `fn` function call. + * @returns {function()} Function that wraps the `fn` with all the specified bindings. + */ +/* jshint +W101 */ +function bind(self, fn) { + var curryArgs = arguments.length > 2 ? sliceArgs(arguments, 2) : []; + if (isFunction(fn) && !(fn instanceof RegExp)) { + return curryArgs.length + ? function() { + return arguments.length + ? fn.apply(self, concat(curryArgs, arguments, 0)) + : fn.apply(self, curryArgs); + } + : function() { + return arguments.length + ? fn.apply(self, arguments) + : fn.call(self); + }; + } else { + // in IE, native methods are not functions so they cannot be bound (note: they don't need to be) + return fn; + } +} + + +function toJsonReplacer(key, value) { + var val = value; + + if (typeof key === 'string' && key.charAt(0) === '$' && key.charAt(1) === '$') { + val = undefined; + } else if (isWindow(value)) { + val = '$WINDOW'; + } else if (value && document === value) { + val = '$DOCUMENT'; + } else if (isScope(value)) { + val = '$SCOPE'; + } + + return val; +} + + +/** + * @ngdoc function + * @name angular.toJson + * @module ng + * @kind function + * + * @description + * Serializes input into a JSON-formatted string. Properties with leading $$ characters will be + * stripped since angular uses this notation internally. + * + * @param {Object|Array|Date|string|number} obj Input to be serialized into JSON. + * @param {boolean|number=} pretty If set to true, the JSON output will contain newlines and whitespace. + * If set to an integer, the JSON output will contain that many spaces per indentation (the default is 2). + * @returns {string|undefined} JSON-ified string representing `obj`. + */ +function toJson(obj, pretty) { + if (typeof obj === 'undefined') return undefined; + if (!isNumber(pretty)) { + pretty = pretty ? 2 : null; + } + return JSON.stringify(obj, toJsonReplacer, pretty); +} + + +/** + * @ngdoc function + * @name angular.fromJson + * @module ng + * @kind function + * + * @description + * Deserializes a JSON string. + * + * @param {string} json JSON string to deserialize. + * @returns {Object|Array|string|number} Deserialized JSON string. + */ +function fromJson(json) { + return isString(json) + ? JSON.parse(json) + : json; +} + + +/** + * @returns {string} Returns the string representation of the element. + */ +function startingTag(element) { + element = jqLite(element).clone(); + try { + // turns out IE does not let you set .html() on elements which + // are not allowed to have children. So we just ignore it. + element.empty(); + } catch (e) {} + var elemHtml = jqLite('
      ').append(element).html(); + try { + return element[0].nodeType === NODE_TYPE_TEXT ? lowercase(elemHtml) : + elemHtml. + match(/^(<[^>]+>)/)[1]. + replace(/^<([\w\-]+)/, function(match, nodeName) { return '<' + lowercase(nodeName); }); + } catch (e) { + return lowercase(elemHtml); + } + +} + + +///////////////////////////////////////////////// + +/** + * Tries to decode the URI component without throwing an exception. + * + * @private + * @param str value potential URI component to check. + * @returns {boolean} True if `value` can be decoded + * with the decodeURIComponent function. + */ +function tryDecodeURIComponent(value) { + try { + return decodeURIComponent(value); + } catch (e) { + // Ignore any invalid uri component + } +} + + +/** + * Parses an escaped url query string into key-value pairs. + * @returns {Object.} + */ +function parseKeyValue(/**string*/keyValue) { + var obj = {}, key_value, key; + forEach((keyValue || "").split('&'), function(keyValue) { + if (keyValue) { + key_value = keyValue.replace(/\+/g,'%20').split('='); + key = tryDecodeURIComponent(key_value[0]); + if (isDefined(key)) { + var val = isDefined(key_value[1]) ? tryDecodeURIComponent(key_value[1]) : true; + if (!hasOwnProperty.call(obj, key)) { + obj[key] = val; + } else if (isArray(obj[key])) { + obj[key].push(val); + } else { + obj[key] = [obj[key],val]; + } + } + } + }); + return obj; +} + +function toKeyValue(obj) { + var parts = []; + forEach(obj, function(value, key) { + if (isArray(value)) { + forEach(value, function(arrayValue) { + parts.push(encodeUriQuery(key, true) + + (arrayValue === true ? '' : '=' + encodeUriQuery(arrayValue, true))); + }); + } else { + parts.push(encodeUriQuery(key, true) + + (value === true ? '' : '=' + encodeUriQuery(value, true))); + } + }); + return parts.length ? parts.join('&') : ''; +} + + +/** + * We need our custom method because encodeURIComponent is too aggressive and doesn't follow + * http://www.ietf.org/rfc/rfc3986.txt with regards to the character set (pchar) allowed in path + * segments: + * segment = *pchar + * pchar = unreserved / pct-encoded / sub-delims / ":" / "@" + * pct-encoded = "%" HEXDIG HEXDIG + * unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~" + * sub-delims = "!" / "$" / "&" / "'" / "(" / ")" + * / "*" / "+" / "," / ";" / "=" + */ +function encodeUriSegment(val) { + return encodeUriQuery(val, true). + replace(/%26/gi, '&'). + replace(/%3D/gi, '='). + replace(/%2B/gi, '+'); +} + + +/** + * This method is intended for encoding *key* or *value* parts of query component. We need a custom + * method because encodeURIComponent is too aggressive and encodes stuff that doesn't have to be + * encoded per http://tools.ietf.org/html/rfc3986: + * query = *( pchar / "/" / "?" ) + * pchar = unreserved / pct-encoded / sub-delims / ":" / "@" + * unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~" + * pct-encoded = "%" HEXDIG HEXDIG + * sub-delims = "!" / "$" / "&" / "'" / "(" / ")" + * / "*" / "+" / "," / ";" / "=" + */ +function encodeUriQuery(val, pctEncodeSpaces) { + return encodeURIComponent(val). + replace(/%40/gi, '@'). + replace(/%3A/gi, ':'). + replace(/%24/g, '$'). + replace(/%2C/gi, ','). + replace(/%3B/gi, ';'). + replace(/%20/g, (pctEncodeSpaces ? '%20' : '+')); +} + +var ngAttrPrefixes = ['ng-', 'data-ng-', 'ng:', 'x-ng-']; + +function getNgAttribute(element, ngAttr) { + var attr, i, ii = ngAttrPrefixes.length; + element = jqLite(element); + for (i = 0; i < ii; ++i) { + attr = ngAttrPrefixes[i] + ngAttr; + if (isString(attr = element.attr(attr))) { + return attr; + } + } + return null; +} + +/** + * @ngdoc directive + * @name ngApp + * @module ng + * + * @element ANY + * @param {angular.Module} ngApp an optional application + * {@link angular.module module} name to load. + * @param {boolean=} ngStrictDi if this attribute is present on the app element, the injector will be + * created in "strict-di" mode. This means that the application will fail to invoke functions which + * do not use explicit function annotation (and are thus unsuitable for minification), as described + * in {@link guide/di the Dependency Injection guide}, and useful debugging info will assist in + * tracking down the root of these bugs. + * + * @description + * + * Use this directive to **auto-bootstrap** an AngularJS application. The `ngApp` directive + * designates the **root element** of the application and is typically placed near the root element + * of the page - e.g. on the `` or `` tags. + * + * Only one AngularJS application can be auto-bootstrapped per HTML document. The first `ngApp` + * found in the document will be used to define the root element to auto-bootstrap as an + * application. To run multiple applications in an HTML document you must manually bootstrap them using + * {@link angular.bootstrap} instead. AngularJS applications cannot be nested within each other. + * + * You can specify an **AngularJS module** to be used as the root module for the application. This + * module will be loaded into the {@link auto.$injector} when the application is bootstrapped. It + * should contain the application code needed or have dependencies on other modules that will + * contain the code. See {@link angular.module} for more information. + * + * In the example below if the `ngApp` directive were not placed on the `html` element then the + * document would not be compiled, the `AppController` would not be instantiated and the `{{ a+b }}` + * would not be resolved to `3`. + * + * `ngApp` is the easiest, and most common way to bootstrap an application. + * + + +
      + I can add: {{a}} + {{b}} = {{ a+b }} +
      +
      + + angular.module('ngAppDemo', []).controller('ngAppDemoController', function($scope) { + $scope.a = 1; + $scope.b = 2; + }); + +
      + * + * Using `ngStrictDi`, you would see something like this: + * + + +
      +
      + I can add: {{a}} + {{b}} = {{ a+b }} + +

      This renders because the controller does not fail to + instantiate, by using explicit annotation style (see + script.js for details) +

      +
      + +
      + Name:
      + Hello, {{name}}! + +

      This renders because the controller does not fail to + instantiate, by using explicit annotation style + (see script.js for details) +

      +
      + +
      + I can add: {{a}} + {{b}} = {{ a+b }} + +

      The controller could not be instantiated, due to relying + on automatic function annotations (which are disabled in + strict mode). As such, the content of this section is not + interpolated, and there should be an error in your web console. +

      +
      +
      +
      + + angular.module('ngAppStrictDemo', []) + // BadController will fail to instantiate, due to relying on automatic function annotation, + // rather than an explicit annotation + .controller('BadController', function($scope) { + $scope.a = 1; + $scope.b = 2; + }) + // Unlike BadController, GoodController1 and GoodController2 will not fail to be instantiated, + // due to using explicit annotations using the array style and $inject property, respectively. + .controller('GoodController1', ['$scope', function($scope) { + $scope.a = 1; + $scope.b = 2; + }]) + .controller('GoodController2', GoodController2); + function GoodController2($scope) { + $scope.name = "World"; + } + GoodController2.$inject = ['$scope']; + + + div[ng-controller] { + margin-bottom: 1em; + -webkit-border-radius: 4px; + border-radius: 4px; + border: 1px solid; + padding: .5em; + } + div[ng-controller^=Good] { + border-color: #d6e9c6; + background-color: #dff0d8; + color: #3c763d; + } + div[ng-controller^=Bad] { + border-color: #ebccd1; + background-color: #f2dede; + color: #a94442; + margin-bottom: 0; + } + +
      + */ +function angularInit(element, bootstrap) { + var appElement, + module, + config = {}; + + // The element `element` has priority over any other element + forEach(ngAttrPrefixes, function(prefix) { + var name = prefix + 'app'; + + if (!appElement && element.hasAttribute && element.hasAttribute(name)) { + appElement = element; + module = element.getAttribute(name); + } + }); + forEach(ngAttrPrefixes, function(prefix) { + var name = prefix + 'app'; + var candidate; + + if (!appElement && (candidate = element.querySelector('[' + name.replace(':', '\\:') + ']'))) { + appElement = candidate; + module = candidate.getAttribute(name); + } + }); + if (appElement) { + config.strictDi = getNgAttribute(appElement, "strict-di") !== null; + bootstrap(appElement, module ? [module] : [], config); + } +} + +/** + * @ngdoc function + * @name angular.bootstrap + * @module ng + * @description + * Use this function to manually start up angular application. + * + * See: {@link guide/bootstrap Bootstrap} + * + * Note that Protractor based end-to-end tests cannot use this function to bootstrap manually. + * They must use {@link ng.directive:ngApp ngApp}. + * + * Angular will detect if it has been loaded into the browser more than once and only allow the + * first loaded script to be bootstrapped and will report a warning to the browser console for + * each of the subsequent scripts. This prevents strange results in applications, where otherwise + * multiple instances of Angular try to work on the DOM. + * + * ```html + * + * + * + *
      + * {{greeting}} + *
      + * + * + * + * + * + * ``` + * + * @param {DOMElement} element DOM element which is the root of angular application. + * @param {Array=} modules an array of modules to load into the application. + * Each item in the array should be the name of a predefined module or a (DI annotated) + * function that will be invoked by the injector as a run block. + * See: {@link angular.module modules} + * @param {Object=} config an object for defining configuration options for the application. The + * following keys are supported: + * + * * `strictDi` - disable automatic function annotation for the application. This is meant to + * assist in finding bugs which break minified code. Defaults to `false`. + * + * @returns {auto.$injector} Returns the newly created injector for this app. + */ +function bootstrap(element, modules, config) { + if (!isObject(config)) config = {}; + var defaultConfig = { + strictDi: false + }; + config = extend(defaultConfig, config); + var doBootstrap = function() { + element = jqLite(element); + + if (element.injector()) { + var tag = (element[0] === document) ? 'document' : startingTag(element); + //Encode angle brackets to prevent input from being sanitized to empty string #8683 + throw ngMinErr( + 'btstrpd', + "App Already Bootstrapped with this Element '{0}'", + tag.replace(//,'>')); + } + + modules = modules || []; + modules.unshift(['$provide', function($provide) { + $provide.value('$rootElement', element); + }]); + + if (config.debugInfoEnabled) { + // Pushing so that this overrides `debugInfoEnabled` setting defined in user's `modules`. + modules.push(['$compileProvider', function($compileProvider) { + $compileProvider.debugInfoEnabled(true); + }]); + } + + modules.unshift('ng'); + var injector = createInjector(modules, config.strictDi); + injector.invoke(['$rootScope', '$rootElement', '$compile', '$injector', + function bootstrapApply(scope, element, compile, injector) { + scope.$apply(function() { + element.data('$injector', injector); + compile(element)(scope); + }); + }] + ); + return injector; + }; + + var NG_ENABLE_DEBUG_INFO = /^NG_ENABLE_DEBUG_INFO!/; + var NG_DEFER_BOOTSTRAP = /^NG_DEFER_BOOTSTRAP!/; + + if (window && NG_ENABLE_DEBUG_INFO.test(window.name)) { + config.debugInfoEnabled = true; + window.name = window.name.replace(NG_ENABLE_DEBUG_INFO, ''); + } + + if (window && !NG_DEFER_BOOTSTRAP.test(window.name)) { + return doBootstrap(); + } + + window.name = window.name.replace(NG_DEFER_BOOTSTRAP, ''); + angular.resumeBootstrap = function(extraModules) { + forEach(extraModules, function(module) { + modules.push(module); + }); + doBootstrap(); + }; +} + +/** + * @ngdoc function + * @name angular.reloadWithDebugInfo + * @module ng + * @description + * Use this function to reload the current application with debug information turned on. + * This takes precedence over a call to `$compileProvider.debugInfoEnabled(false)`. + * + * See {@link ng.$compileProvider#debugInfoEnabled} for more. + */ +function reloadWithDebugInfo() { + window.name = 'NG_ENABLE_DEBUG_INFO!' + window.name; + window.location.reload(); +} + +/** + * @name angular.getTestability + * @module ng + * @description + * Get the testability service for the instance of Angular on the given + * element. + * @param {DOMElement} element DOM element which is the root of angular application. + */ +function getTestability(rootElement) { + var injector = angular.element(rootElement).injector(); + if (!injector) { + throw ngMinErr('test', + 'no injector found for element argument to getTestability'); + } + return injector.get('$$testability'); +} + +var SNAKE_CASE_REGEXP = /[A-Z]/g; +function snake_case(name, separator) { + separator = separator || '_'; + return name.replace(SNAKE_CASE_REGEXP, function(letter, pos) { + return (pos ? separator : '') + letter.toLowerCase(); + }); +} + +var bindJQueryFired = false; +var skipDestroyOnNextJQueryCleanData; +function bindJQuery() { + var originalCleanData; + + if (bindJQueryFired) { + return; + } + + // bind to jQuery if present; + jQuery = window.jQuery; + // Use jQuery if it exists with proper functionality, otherwise default to us. + // Angular 1.2+ requires jQuery 1.7+ for on()/off() support. + // Angular 1.3+ technically requires at least jQuery 2.1+ but it may work with older + // versions. It will not work for sure with jQuery <1.7, though. + if (jQuery && jQuery.fn.on) { + jqLite = jQuery; + extend(jQuery.fn, { + scope: JQLitePrototype.scope, + isolateScope: JQLitePrototype.isolateScope, + controller: JQLitePrototype.controller, + injector: JQLitePrototype.injector, + inheritedData: JQLitePrototype.inheritedData + }); + + // All nodes removed from the DOM via various jQuery APIs like .remove() + // are passed through jQuery.cleanData. Monkey-patch this method to fire + // the $destroy event on all removed nodes. + originalCleanData = jQuery.cleanData; + jQuery.cleanData = function(elems) { + var events; + if (!skipDestroyOnNextJQueryCleanData) { + for (var i = 0, elem; (elem = elems[i]) != null; i++) { + events = jQuery._data(elem, "events"); + if (events && events.$destroy) { + jQuery(elem).triggerHandler('$destroy'); + } + } + } else { + skipDestroyOnNextJQueryCleanData = false; + } + originalCleanData(elems); + }; + } else { + jqLite = JQLite; + } + + angular.element = jqLite; + + // Prevent double-proxying. + bindJQueryFired = true; +} + +/** + * throw error if the argument is falsy. + */ +function assertArg(arg, name, reason) { + if (!arg) { + throw ngMinErr('areq', "Argument '{0}' is {1}", (name || '?'), (reason || "required")); + } + return arg; +} + +function assertArgFn(arg, name, acceptArrayAnnotation) { + if (acceptArrayAnnotation && isArray(arg)) { + arg = arg[arg.length - 1]; + } + + assertArg(isFunction(arg), name, 'not a function, got ' + + (arg && typeof arg === 'object' ? arg.constructor.name || 'Object' : typeof arg)); + return arg; +} + +/** + * throw error if the name given is hasOwnProperty + * @param {String} name the name to test + * @param {String} context the context in which the name is used, such as module or directive + */ +function assertNotHasOwnProperty(name, context) { + if (name === 'hasOwnProperty') { + throw ngMinErr('badname', "hasOwnProperty is not a valid {0} name", context); + } +} + +/** + * Return the value accessible from the object by path. Any undefined traversals are ignored + * @param {Object} obj starting object + * @param {String} path path to traverse + * @param {boolean} [bindFnToScope=true] + * @returns {Object} value as accessible by path + */ +//TODO(misko): this function needs to be removed +function getter(obj, path, bindFnToScope) { + if (!path) return obj; + var keys = path.split('.'); + var key; + var lastInstance = obj; + var len = keys.length; + + for (var i = 0; i < len; i++) { + key = keys[i]; + if (obj) { + obj = (lastInstance = obj)[key]; + } + } + if (!bindFnToScope && isFunction(obj)) { + return bind(lastInstance, obj); + } + return obj; +} + +/** + * Return the DOM siblings between the first and last node in the given array. + * @param {Array} array like object + * @returns {jqLite} jqLite collection containing the nodes + */ +function getBlockNodes(nodes) { + // TODO(perf): just check if all items in `nodes` are siblings and if they are return the original + // collection, otherwise update the original collection. + var node = nodes[0]; + var endNode = nodes[nodes.length - 1]; + var blockNodes = [node]; + + do { + node = node.nextSibling; + if (!node) break; + blockNodes.push(node); + } while (node !== endNode); + + return jqLite(blockNodes); +} + + +/** + * Creates a new object without a prototype. This object is useful for lookup without having to + * guard against prototypically inherited properties via hasOwnProperty. + * + * Related micro-benchmarks: + * - http://jsperf.com/object-create2 + * - http://jsperf.com/proto-map-lookup/2 + * - http://jsperf.com/for-in-vs-object-keys2 + * + * @returns {Object} + */ +function createMap() { + return Object.create(null); +} + +var NODE_TYPE_ELEMENT = 1; +var NODE_TYPE_TEXT = 3; +var NODE_TYPE_COMMENT = 8; +var NODE_TYPE_DOCUMENT = 9; +var NODE_TYPE_DOCUMENT_FRAGMENT = 11; + +/** + * @ngdoc type + * @name angular.Module + * @module ng + * @description + * + * Interface for configuring angular {@link angular.module modules}. + */ + +function setupModuleLoader(window) { + + var $injectorMinErr = minErr('$injector'); + var ngMinErr = minErr('ng'); + + function ensure(obj, name, factory) { + return obj[name] || (obj[name] = factory()); + } + + var angular = ensure(window, 'angular', Object); + + // We need to expose `angular.$$minErr` to modules such as `ngResource` that reference it during bootstrap + angular.$$minErr = angular.$$minErr || minErr; + + return ensure(angular, 'module', function() { + /** @type {Object.} */ + var modules = {}; + + /** + * @ngdoc function + * @name angular.module + * @module ng + * @description + * + * The `angular.module` is a global place for creating, registering and retrieving Angular + * modules. + * All modules (angular core or 3rd party) that should be available to an application must be + * registered using this mechanism. + * + * When passed two or more arguments, a new module is created. If passed only one argument, an + * existing module (the name passed as the first argument to `module`) is retrieved. + * + * + * # Module + * + * A module is a collection of services, directives, controllers, filters, and configuration information. + * `angular.module` is used to configure the {@link auto.$injector $injector}. + * + * ```js + * // Create a new module + * var myModule = angular.module('myModule', []); + * + * // register a new service + * myModule.value('appName', 'MyCoolApp'); + * + * // configure existing services inside initialization blocks. + * myModule.config(['$locationProvider', function($locationProvider) { + * // Configure existing providers + * $locationProvider.hashPrefix('!'); + * }]); + * ``` + * + * Then you can create an injector and load your modules like this: + * + * ```js + * var injector = angular.injector(['ng', 'myModule']) + * ``` + * + * However it's more likely that you'll just use + * {@link ng.directive:ngApp ngApp} or + * {@link angular.bootstrap} to simplify this process for you. + * + * @param {!string} name The name of the module to create or retrieve. + * @param {!Array.=} requires If specified then new module is being created. If + * unspecified then the module is being retrieved for further configuration. + * @param {Function=} configFn Optional configuration function for the module. Same as + * {@link angular.Module#config Module#config()}. + * @returns {module} new module with the {@link angular.Module} api. + */ + return function module(name, requires, configFn) { + var assertNotHasOwnProperty = function(name, context) { + if (name === 'hasOwnProperty') { + throw ngMinErr('badname', 'hasOwnProperty is not a valid {0} name', context); + } + }; + + assertNotHasOwnProperty(name, 'module'); + if (requires && modules.hasOwnProperty(name)) { + modules[name] = null; + } + return ensure(modules, name, function() { + if (!requires) { + throw $injectorMinErr('nomod', "Module '{0}' is not available! You either misspelled " + + "the module name or forgot to load it. If registering a module ensure that you " + + "specify the dependencies as the second argument.", name); + } + + /** @type {!Array.>} */ + var invokeQueue = []; + + /** @type {!Array.} */ + var configBlocks = []; + + /** @type {!Array.} */ + var runBlocks = []; + + var config = invokeLater('$injector', 'invoke', 'push', configBlocks); + + /** @type {angular.Module} */ + var moduleInstance = { + // Private state + _invokeQueue: invokeQueue, + _configBlocks: configBlocks, + _runBlocks: runBlocks, + + /** + * @ngdoc property + * @name angular.Module#requires + * @module ng + * + * @description + * Holds the list of modules which the injector will load before the current module is + * loaded. + */ + requires: requires, + + /** + * @ngdoc property + * @name angular.Module#name + * @module ng + * + * @description + * Name of the module. + */ + name: name, + + + /** + * @ngdoc method + * @name angular.Module#provider + * @module ng + * @param {string} name service name + * @param {Function} providerType Construction function for creating new instance of the + * service. + * @description + * See {@link auto.$provide#provider $provide.provider()}. + */ + provider: invokeLater('$provide', 'provider'), + + /** + * @ngdoc method + * @name angular.Module#factory + * @module ng + * @param {string} name service name + * @param {Function} providerFunction Function for creating new instance of the service. + * @description + * See {@link auto.$provide#factory $provide.factory()}. + */ + factory: invokeLater('$provide', 'factory'), + + /** + * @ngdoc method + * @name angular.Module#service + * @module ng + * @param {string} name service name + * @param {Function} constructor A constructor function that will be instantiated. + * @description + * See {@link auto.$provide#service $provide.service()}. + */ + service: invokeLater('$provide', 'service'), + + /** + * @ngdoc method + * @name angular.Module#value + * @module ng + * @param {string} name service name + * @param {*} object Service instance object. + * @description + * See {@link auto.$provide#value $provide.value()}. + */ + value: invokeLater('$provide', 'value'), + + /** + * @ngdoc method + * @name angular.Module#constant + * @module ng + * @param {string} name constant name + * @param {*} object Constant value. + * @description + * Because the constant are fixed, they get applied before other provide methods. + * See {@link auto.$provide#constant $provide.constant()}. + */ + constant: invokeLater('$provide', 'constant', 'unshift'), + + /** + * @ngdoc method + * @name angular.Module#animation + * @module ng + * @param {string} name animation name + * @param {Function} animationFactory Factory function for creating new instance of an + * animation. + * @description + * + * **NOTE**: animations take effect only if the **ngAnimate** module is loaded. + * + * + * Defines an animation hook that can be later used with + * {@link ngAnimate.$animate $animate} service and directives that use this service. + * + * ```js + * module.animation('.animation-name', function($inject1, $inject2) { + * return { + * eventName : function(element, done) { + * //code to run the animation + * //once complete, then run done() + * return function cancellationFunction(element) { + * //code to cancel the animation + * } + * } + * } + * }) + * ``` + * + * See {@link ng.$animateProvider#register $animateProvider.register()} and + * {@link ngAnimate ngAnimate module} for more information. + */ + animation: invokeLater('$animateProvider', 'register'), + + /** + * @ngdoc method + * @name angular.Module#filter + * @module ng + * @param {string} name Filter name. + * @param {Function} filterFactory Factory function for creating new instance of filter. + * @description + * See {@link ng.$filterProvider#register $filterProvider.register()}. + */ + filter: invokeLater('$filterProvider', 'register'), + + /** + * @ngdoc method + * @name angular.Module#controller + * @module ng + * @param {string|Object} name Controller name, or an object map of controllers where the + * keys are the names and the values are the constructors. + * @param {Function} constructor Controller constructor function. + * @description + * See {@link ng.$controllerProvider#register $controllerProvider.register()}. + */ + controller: invokeLater('$controllerProvider', 'register'), + + /** + * @ngdoc method + * @name angular.Module#directive + * @module ng + * @param {string|Object} name Directive name, or an object map of directives where the + * keys are the names and the values are the factories. + * @param {Function} directiveFactory Factory function for creating new instance of + * directives. + * @description + * See {@link ng.$compileProvider#directive $compileProvider.directive()}. + */ + directive: invokeLater('$compileProvider', 'directive'), + + /** + * @ngdoc method + * @name angular.Module#config + * @module ng + * @param {Function} configFn Execute this function on module load. Useful for service + * configuration. + * @description + * Use this method to register work which needs to be performed on module loading. + * For more about how to configure services, see + * {@link providers#provider-recipe Provider Recipe}. + */ + config: config, + + /** + * @ngdoc method + * @name angular.Module#run + * @module ng + * @param {Function} initializationFn Execute this function after injector creation. + * Useful for application initialization. + * @description + * Use this method to register work which should be performed when the injector is done + * loading all modules. + */ + run: function(block) { + runBlocks.push(block); + return this; + } + }; + + if (configFn) { + config(configFn); + } + + return moduleInstance; + + /** + * @param {string} provider + * @param {string} method + * @param {String=} insertMethod + * @returns {angular.Module} + */ + function invokeLater(provider, method, insertMethod, queue) { + if (!queue) queue = invokeQueue; + return function() { + queue[insertMethod || 'push']([provider, method, arguments]); + return moduleInstance; + }; + } + }); + }; + }); + +} + +/* global: toDebugString: true */ + +function serializeObject(obj) { + var seen = []; + + return JSON.stringify(obj, function(key, val) { + val = toJsonReplacer(key, val); + if (isObject(val)) { + + if (seen.indexOf(val) >= 0) return '<>'; + + seen.push(val); + } + return val; + }); +} + +function toDebugString(obj) { + if (typeof obj === 'function') { + return obj.toString().replace(/ \{[\s\S]*$/, ''); + } else if (typeof obj === 'undefined') { + return 'undefined'; + } else if (typeof obj !== 'string') { + return serializeObject(obj); + } + return obj; +} + +/* global angularModule: true, + version: true, + + $LocaleProvider, + $CompileProvider, + + htmlAnchorDirective, + inputDirective, + inputDirective, + formDirective, + scriptDirective, + selectDirective, + styleDirective, + optionDirective, + ngBindDirective, + ngBindHtmlDirective, + ngBindTemplateDirective, + ngClassDirective, + ngClassEvenDirective, + ngClassOddDirective, + ngCspDirective, + ngCloakDirective, + ngControllerDirective, + ngFormDirective, + ngHideDirective, + ngIfDirective, + ngIncludeDirective, + ngIncludeFillContentDirective, + ngInitDirective, + ngNonBindableDirective, + ngPluralizeDirective, + ngRepeatDirective, + ngShowDirective, + ngStyleDirective, + ngSwitchDirective, + ngSwitchWhenDirective, + ngSwitchDefaultDirective, + ngOptionsDirective, + ngTranscludeDirective, + ngModelDirective, + ngListDirective, + ngChangeDirective, + patternDirective, + patternDirective, + requiredDirective, + requiredDirective, + minlengthDirective, + minlengthDirective, + maxlengthDirective, + maxlengthDirective, + ngValueDirective, + ngModelOptionsDirective, + ngAttributeAliasDirectives, + ngEventDirectives, + + $AnchorScrollProvider, + $AnimateProvider, + $BrowserProvider, + $CacheFactoryProvider, + $ControllerProvider, + $DocumentProvider, + $ExceptionHandlerProvider, + $FilterProvider, + $InterpolateProvider, + $IntervalProvider, + $HttpProvider, + $HttpBackendProvider, + $LocationProvider, + $LogProvider, + $ParseProvider, + $RootScopeProvider, + $QProvider, + $$QProvider, + $$SanitizeUriProvider, + $SceProvider, + $SceDelegateProvider, + $SnifferProvider, + $TemplateCacheProvider, + $TemplateRequestProvider, + $$TestabilityProvider, + $TimeoutProvider, + $$RAFProvider, + $$AsyncCallbackProvider, + $WindowProvider, + $$jqLiteProvider +*/ + + +/** + * @ngdoc object + * @name angular.version + * @module ng + * @description + * An object that contains information about the current AngularJS version. This object has the + * following properties: + * + * - `full` – `{string}` – Full version string, such as "0.9.18". + * - `major` – `{number}` – Major version number, such as "0". + * - `minor` – `{number}` – Minor version number, such as "9". + * - `dot` – `{number}` – Dot version number, such as "18". + * - `codeName` – `{string}` – Code name of the release, such as "jiggling-armfat". + */ +var version = { + full: '1.3.8', // all of these placeholder strings will be replaced by grunt's + major: 1, // package task + minor: 3, + dot: 8, + codeName: 'prophetic-narwhal' +}; + + +function publishExternalAPI(angular) { + extend(angular, { + 'bootstrap': bootstrap, + 'copy': copy, + 'extend': extend, + 'equals': equals, + 'element': jqLite, + 'forEach': forEach, + 'injector': createInjector, + 'noop': noop, + 'bind': bind, + 'toJson': toJson, + 'fromJson': fromJson, + 'identity': identity, + 'isUndefined': isUndefined, + 'isDefined': isDefined, + 'isString': isString, + 'isFunction': isFunction, + 'isObject': isObject, + 'isNumber': isNumber, + 'isElement': isElement, + 'isArray': isArray, + 'version': version, + 'isDate': isDate, + 'lowercase': lowercase, + 'uppercase': uppercase, + 'callbacks': {counter: 0}, + 'getTestability': getTestability, + '$$minErr': minErr, + '$$csp': csp, + 'reloadWithDebugInfo': reloadWithDebugInfo + }); + + angularModule = setupModuleLoader(window); + try { + angularModule('ngLocale'); + } catch (e) { + angularModule('ngLocale', []).provider('$locale', $LocaleProvider); + } + + angularModule('ng', ['ngLocale'], ['$provide', + function ngModule($provide) { + // $$sanitizeUriProvider needs to be before $compileProvider as it is used by it. + $provide.provider({ + $$sanitizeUri: $$SanitizeUriProvider + }); + $provide.provider('$compile', $CompileProvider). + directive({ + a: htmlAnchorDirective, + input: inputDirective, + textarea: inputDirective, + form: formDirective, + script: scriptDirective, + select: selectDirective, + style: styleDirective, + option: optionDirective, + ngBind: ngBindDirective, + ngBindHtml: ngBindHtmlDirective, + ngBindTemplate: ngBindTemplateDirective, + ngClass: ngClassDirective, + ngClassEven: ngClassEvenDirective, + ngClassOdd: ngClassOddDirective, + ngCloak: ngCloakDirective, + ngController: ngControllerDirective, + ngForm: ngFormDirective, + ngHide: ngHideDirective, + ngIf: ngIfDirective, + ngInclude: ngIncludeDirective, + ngInit: ngInitDirective, + ngNonBindable: ngNonBindableDirective, + ngPluralize: ngPluralizeDirective, + ngRepeat: ngRepeatDirective, + ngShow: ngShowDirective, + ngStyle: ngStyleDirective, + ngSwitch: ngSwitchDirective, + ngSwitchWhen: ngSwitchWhenDirective, + ngSwitchDefault: ngSwitchDefaultDirective, + ngOptions: ngOptionsDirective, + ngTransclude: ngTranscludeDirective, + ngModel: ngModelDirective, + ngList: ngListDirective, + ngChange: ngChangeDirective, + pattern: patternDirective, + ngPattern: patternDirective, + required: requiredDirective, + ngRequired: requiredDirective, + minlength: minlengthDirective, + ngMinlength: minlengthDirective, + maxlength: maxlengthDirective, + ngMaxlength: maxlengthDirective, + ngValue: ngValueDirective, + ngModelOptions: ngModelOptionsDirective + }). + directive({ + ngInclude: ngIncludeFillContentDirective + }). + directive(ngAttributeAliasDirectives). + directive(ngEventDirectives); + $provide.provider({ + $anchorScroll: $AnchorScrollProvider, + $animate: $AnimateProvider, + $browser: $BrowserProvider, + $cacheFactory: $CacheFactoryProvider, + $controller: $ControllerProvider, + $document: $DocumentProvider, + $exceptionHandler: $ExceptionHandlerProvider, + $filter: $FilterProvider, + $interpolate: $InterpolateProvider, + $interval: $IntervalProvider, + $http: $HttpProvider, + $httpBackend: $HttpBackendProvider, + $location: $LocationProvider, + $log: $LogProvider, + $parse: $ParseProvider, + $rootScope: $RootScopeProvider, + $q: $QProvider, + $$q: $$QProvider, + $sce: $SceProvider, + $sceDelegate: $SceDelegateProvider, + $sniffer: $SnifferProvider, + $templateCache: $TemplateCacheProvider, + $templateRequest: $TemplateRequestProvider, + $$testability: $$TestabilityProvider, + $timeout: $TimeoutProvider, + $window: $WindowProvider, + $$rAF: $$RAFProvider, + $$asyncCallback: $$AsyncCallbackProvider, + $$jqLite: $$jqLiteProvider + }); + } + ]); +} + +/* global JQLitePrototype: true, + addEventListenerFn: true, + removeEventListenerFn: true, + BOOLEAN_ATTR: true, + ALIASED_ATTR: true, +*/ + +////////////////////////////////// +//JQLite +////////////////////////////////// + +/** + * @ngdoc function + * @name angular.element + * @module ng + * @kind function + * + * @description + * Wraps a raw DOM element or HTML string as a [jQuery](http://jquery.com) element. + * + * If jQuery is available, `angular.element` is an alias for the + * [jQuery](http://api.jquery.com/jQuery/) function. If jQuery is not available, `angular.element` + * delegates to Angular's built-in subset of jQuery, called "jQuery lite" or "jqLite." + * + *
      jqLite is a tiny, API-compatible subset of jQuery that allows + * Angular to manipulate the DOM in a cross-browser compatible way. **jqLite** implements only the most + * commonly needed functionality with the goal of having a very small footprint.
      + * + * To use jQuery, simply load it before `DOMContentLoaded` event fired. + * + *
      **Note:** all element references in Angular are always wrapped with jQuery or + * jqLite; they are never raw DOM references.
      + * + * ## Angular's jqLite + * jqLite provides only the following jQuery methods: + * + * - [`addClass()`](http://api.jquery.com/addClass/) + * - [`after()`](http://api.jquery.com/after/) + * - [`append()`](http://api.jquery.com/append/) + * - [`attr()`](http://api.jquery.com/attr/) - Does not support functions as parameters + * - [`bind()`](http://api.jquery.com/bind/) - Does not support namespaces, selectors or eventData + * - [`children()`](http://api.jquery.com/children/) - Does not support selectors + * - [`clone()`](http://api.jquery.com/clone/) + * - [`contents()`](http://api.jquery.com/contents/) + * - [`css()`](http://api.jquery.com/css/) - Only retrieves inline-styles, does not call `getComputedStyle()` + * - [`data()`](http://api.jquery.com/data/) + * - [`detach()`](http://api.jquery.com/detach/) + * - [`empty()`](http://api.jquery.com/empty/) + * - [`eq()`](http://api.jquery.com/eq/) + * - [`find()`](http://api.jquery.com/find/) - Limited to lookups by tag name + * - [`hasClass()`](http://api.jquery.com/hasClass/) + * - [`html()`](http://api.jquery.com/html/) + * - [`next()`](http://api.jquery.com/next/) - Does not support selectors + * - [`on()`](http://api.jquery.com/on/) - Does not support namespaces, selectors or eventData + * - [`off()`](http://api.jquery.com/off/) - Does not support namespaces or selectors + * - [`one()`](http://api.jquery.com/one/) - Does not support namespaces or selectors + * - [`parent()`](http://api.jquery.com/parent/) - Does not support selectors + * - [`prepend()`](http://api.jquery.com/prepend/) + * - [`prop()`](http://api.jquery.com/prop/) + * - [`ready()`](http://api.jquery.com/ready/) + * - [`remove()`](http://api.jquery.com/remove/) + * - [`removeAttr()`](http://api.jquery.com/removeAttr/) + * - [`removeClass()`](http://api.jquery.com/removeClass/) + * - [`removeData()`](http://api.jquery.com/removeData/) + * - [`replaceWith()`](http://api.jquery.com/replaceWith/) + * - [`text()`](http://api.jquery.com/text/) + * - [`toggleClass()`](http://api.jquery.com/toggleClass/) + * - [`triggerHandler()`](http://api.jquery.com/triggerHandler/) - Passes a dummy event object to handlers. + * - [`unbind()`](http://api.jquery.com/unbind/) - Does not support namespaces + * - [`val()`](http://api.jquery.com/val/) + * - [`wrap()`](http://api.jquery.com/wrap/) + * + * ## jQuery/jqLite Extras + * Angular also provides the following additional methods and events to both jQuery and jqLite: + * + * ### Events + * - `$destroy` - AngularJS intercepts all jqLite/jQuery's DOM destruction apis and fires this event + * on all DOM nodes being removed. This can be used to clean up any 3rd party bindings to the DOM + * element before it is removed. + * + * ### Methods + * - `controller(name)` - retrieves the controller of the current element or its parent. By default + * retrieves controller associated with the `ngController` directive. If `name` is provided as + * camelCase directive name, then the controller for this directive will be retrieved (e.g. + * `'ngModel'`). + * - `injector()` - retrieves the injector of the current element or its parent. + * - `scope()` - retrieves the {@link ng.$rootScope.Scope scope} of the current + * element or its parent. Requires {@link guide/production#disabling-debug-data Debug Data} to + * be enabled. + * - `isolateScope()` - retrieves an isolate {@link ng.$rootScope.Scope scope} if one is attached directly to the + * current element. This getter should be used only on elements that contain a directive which starts a new isolate + * scope. Calling `scope()` on this element always returns the original non-isolate scope. + * Requires {@link guide/production#disabling-debug-data Debug Data} to be enabled. + * - `inheritedData()` - same as `data()`, but walks up the DOM until a value is found or the top + * parent element is reached. + * + * @param {string|DOMElement} element HTML string or DOMElement to be wrapped into jQuery. + * @returns {Object} jQuery object. + */ + +JQLite.expando = 'ng339'; + +var jqCache = JQLite.cache = {}, + jqId = 1, + addEventListenerFn = function(element, type, fn) { + element.addEventListener(type, fn, false); + }, + removeEventListenerFn = function(element, type, fn) { + element.removeEventListener(type, fn, false); + }; + +/* + * !!! This is an undocumented "private" function !!! + */ +JQLite._data = function(node) { + //jQuery always returns an object on cache miss + return this.cache[node[this.expando]] || {}; +}; + +function jqNextId() { return ++jqId; } + + +var SPECIAL_CHARS_REGEXP = /([\:\-\_]+(.))/g; +var MOZ_HACK_REGEXP = /^moz([A-Z])/; +var MOUSE_EVENT_MAP= { mouseleave: "mouseout", mouseenter: "mouseover"}; +var jqLiteMinErr = minErr('jqLite'); + +/** + * Converts snake_case to camelCase. + * Also there is special case for Moz prefix starting with upper case letter. + * @param name Name to normalize + */ +function camelCase(name) { + return name. + replace(SPECIAL_CHARS_REGEXP, function(_, separator, letter, offset) { + return offset ? letter.toUpperCase() : letter; + }). + replace(MOZ_HACK_REGEXP, 'Moz$1'); +} + +var SINGLE_TAG_REGEXP = /^<(\w+)\s*\/?>(?:<\/\1>|)$/; +var HTML_REGEXP = /<|&#?\w+;/; +var TAG_NAME_REGEXP = /<([\w:]+)/; +var XHTML_TAG_REGEXP = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi; + +var wrapMap = { + 'option': [1, ''], + + 'thead': [1, '', '
      '], + 'col': [2, '', '
      '], + 'tr': [2, '', '
      '], + 'td': [3, '', '
      '], + '_default': [0, "", ""] +}; + +wrapMap.optgroup = wrapMap.option; +wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead; +wrapMap.th = wrapMap.td; + + +function jqLiteIsTextNode(html) { + return !HTML_REGEXP.test(html); +} + +function jqLiteAcceptsData(node) { + // The window object can accept data but has no nodeType + // Otherwise we are only interested in elements (1) and documents (9) + var nodeType = node.nodeType; + return nodeType === NODE_TYPE_ELEMENT || !nodeType || nodeType === NODE_TYPE_DOCUMENT; +} + +function jqLiteBuildFragment(html, context) { + var tmp, tag, wrap, + fragment = context.createDocumentFragment(), + nodes = [], i; + + if (jqLiteIsTextNode(html)) { + // Convert non-html into a text node + nodes.push(context.createTextNode(html)); + } else { + // Convert html into DOM nodes + tmp = tmp || fragment.appendChild(context.createElement("div")); + tag = (TAG_NAME_REGEXP.exec(html) || ["", ""])[1].toLowerCase(); + wrap = wrapMap[tag] || wrapMap._default; + tmp.innerHTML = wrap[1] + html.replace(XHTML_TAG_REGEXP, "<$1>") + wrap[2]; + + // Descend through wrappers to the right content + i = wrap[0]; + while (i--) { + tmp = tmp.lastChild; + } + + nodes = concat(nodes, tmp.childNodes); + + tmp = fragment.firstChild; + tmp.textContent = ""; + } + + // Remove wrapper from fragment + fragment.textContent = ""; + fragment.innerHTML = ""; // Clear inner HTML + forEach(nodes, function(node) { + fragment.appendChild(node); + }); + + return fragment; +} + +function jqLiteParseHTML(html, context) { + context = context || document; + var parsed; + + if ((parsed = SINGLE_TAG_REGEXP.exec(html))) { + return [context.createElement(parsed[1])]; + } + + if ((parsed = jqLiteBuildFragment(html, context))) { + return parsed.childNodes; + } + + return []; +} + +///////////////////////////////////////////// +function JQLite(element) { + if (element instanceof JQLite) { + return element; + } + + var argIsString; + + if (isString(element)) { + element = trim(element); + argIsString = true; + } + if (!(this instanceof JQLite)) { + if (argIsString && element.charAt(0) != '<') { + throw jqLiteMinErr('nosel', 'Looking up elements via selectors is not supported by jqLite! See: http://docs.angularjs.org/api/angular.element'); + } + return new JQLite(element); + } + + if (argIsString) { + jqLiteAddNodes(this, jqLiteParseHTML(element)); + } else { + jqLiteAddNodes(this, element); + } +} + +function jqLiteClone(element) { + return element.cloneNode(true); +} + +function jqLiteDealoc(element, onlyDescendants) { + if (!onlyDescendants) jqLiteRemoveData(element); + + if (element.querySelectorAll) { + var descendants = element.querySelectorAll('*'); + for (var i = 0, l = descendants.length; i < l; i++) { + jqLiteRemoveData(descendants[i]); + } + } +} + +function jqLiteOff(element, type, fn, unsupported) { + if (isDefined(unsupported)) throw jqLiteMinErr('offargs', 'jqLite#off() does not support the `selector` argument'); + + var expandoStore = jqLiteExpandoStore(element); + var events = expandoStore && expandoStore.events; + var handle = expandoStore && expandoStore.handle; + + if (!handle) return; //no listeners registered + + if (!type) { + for (type in events) { + if (type !== '$destroy') { + removeEventListenerFn(element, type, handle); + } + delete events[type]; + } + } else { + forEach(type.split(' '), function(type) { + if (isDefined(fn)) { + var listenerFns = events[type]; + arrayRemove(listenerFns || [], fn); + if (listenerFns && listenerFns.length > 0) { + return; + } + } + + removeEventListenerFn(element, type, handle); + delete events[type]; + }); + } +} + +function jqLiteRemoveData(element, name) { + var expandoId = element.ng339; + var expandoStore = expandoId && jqCache[expandoId]; + + if (expandoStore) { + if (name) { + delete expandoStore.data[name]; + return; + } + + if (expandoStore.handle) { + if (expandoStore.events.$destroy) { + expandoStore.handle({}, '$destroy'); + } + jqLiteOff(element); + } + delete jqCache[expandoId]; + element.ng339 = undefined; // don't delete DOM expandos. IE and Chrome don't like it + } +} + + +function jqLiteExpandoStore(element, createIfNecessary) { + var expandoId = element.ng339, + expandoStore = expandoId && jqCache[expandoId]; + + if (createIfNecessary && !expandoStore) { + element.ng339 = expandoId = jqNextId(); + expandoStore = jqCache[expandoId] = {events: {}, data: {}, handle: undefined}; + } + + return expandoStore; +} + + +function jqLiteData(element, key, value) { + if (jqLiteAcceptsData(element)) { + + var isSimpleSetter = isDefined(value); + var isSimpleGetter = !isSimpleSetter && key && !isObject(key); + var massGetter = !key; + var expandoStore = jqLiteExpandoStore(element, !isSimpleGetter); + var data = expandoStore && expandoStore.data; + + if (isSimpleSetter) { // data('key', value) + data[key] = value; + } else { + if (massGetter) { // data() + return data; + } else { + if (isSimpleGetter) { // data('key') + // don't force creation of expandoStore if it doesn't exist yet + return data && data[key]; + } else { // mass-setter: data({key1: val1, key2: val2}) + extend(data, key); + } + } + } + } +} + +function jqLiteHasClass(element, selector) { + if (!element.getAttribute) return false; + return ((" " + (element.getAttribute('class') || '') + " ").replace(/[\n\t]/g, " "). + indexOf(" " + selector + " ") > -1); +} + +function jqLiteRemoveClass(element, cssClasses) { + if (cssClasses && element.setAttribute) { + forEach(cssClasses.split(' '), function(cssClass) { + element.setAttribute('class', trim( + (" " + (element.getAttribute('class') || '') + " ") + .replace(/[\n\t]/g, " ") + .replace(" " + trim(cssClass) + " ", " ")) + ); + }); + } +} + +function jqLiteAddClass(element, cssClasses) { + if (cssClasses && element.setAttribute) { + var existingClasses = (' ' + (element.getAttribute('class') || '') + ' ') + .replace(/[\n\t]/g, " "); + + forEach(cssClasses.split(' '), function(cssClass) { + cssClass = trim(cssClass); + if (existingClasses.indexOf(' ' + cssClass + ' ') === -1) { + existingClasses += cssClass + ' '; + } + }); + + element.setAttribute('class', trim(existingClasses)); + } +} + + +function jqLiteAddNodes(root, elements) { + // THIS CODE IS VERY HOT. Don't make changes without benchmarking. + + if (elements) { + + // if a Node (the most common case) + if (elements.nodeType) { + root[root.length++] = elements; + } else { + var length = elements.length; + + // if an Array or NodeList and not a Window + if (typeof length === 'number' && elements.window !== elements) { + if (length) { + for (var i = 0; i < length; i++) { + root[root.length++] = elements[i]; + } + } + } else { + root[root.length++] = elements; + } + } + } +} + + +function jqLiteController(element, name) { + return jqLiteInheritedData(element, '$' + (name || 'ngController') + 'Controller'); +} + +function jqLiteInheritedData(element, name, value) { + // if element is the document object work with the html element instead + // this makes $(document).scope() possible + if (element.nodeType == NODE_TYPE_DOCUMENT) { + element = element.documentElement; + } + var names = isArray(name) ? name : [name]; + + while (element) { + for (var i = 0, ii = names.length; i < ii; i++) { + if ((value = jqLite.data(element, names[i])) !== undefined) return value; + } + + // If dealing with a document fragment node with a host element, and no parent, use the host + // element as the parent. This enables directives within a Shadow DOM or polyfilled Shadow DOM + // to lookup parent controllers. + element = element.parentNode || (element.nodeType === NODE_TYPE_DOCUMENT_FRAGMENT && element.host); + } +} + +function jqLiteEmpty(element) { + jqLiteDealoc(element, true); + while (element.firstChild) { + element.removeChild(element.firstChild); + } +} + +function jqLiteRemove(element, keepData) { + if (!keepData) jqLiteDealoc(element); + var parent = element.parentNode; + if (parent) parent.removeChild(element); +} + + +function jqLiteDocumentLoaded(action, win) { + win = win || window; + if (win.document.readyState === 'complete') { + // Force the action to be run async for consistent behaviour + // from the action's point of view + // i.e. it will definitely not be in a $apply + win.setTimeout(action); + } else { + // No need to unbind this handler as load is only ever called once + jqLite(win).on('load', action); + } +} + +////////////////////////////////////////// +// Functions which are declared directly. +////////////////////////////////////////// +var JQLitePrototype = JQLite.prototype = { + ready: function(fn) { + var fired = false; + + function trigger() { + if (fired) return; + fired = true; + fn(); + } + + // check if document is already loaded + if (document.readyState === 'complete') { + setTimeout(trigger); + } else { + this.on('DOMContentLoaded', trigger); // works for modern browsers and IE9 + // we can not use jqLite since we are not done loading and jQuery could be loaded later. + // jshint -W064 + JQLite(window).on('load', trigger); // fallback to window.onload for others + // jshint +W064 + } + }, + toString: function() { + var value = []; + forEach(this, function(e) { value.push('' + e);}); + return '[' + value.join(', ') + ']'; + }, + + eq: function(index) { + return (index >= 0) ? jqLite(this[index]) : jqLite(this[this.length + index]); + }, + + length: 0, + push: push, + sort: [].sort, + splice: [].splice +}; + +////////////////////////////////////////// +// Functions iterating getter/setters. +// these functions return self on setter and +// value on get. +////////////////////////////////////////// +var BOOLEAN_ATTR = {}; +forEach('multiple,selected,checked,disabled,readOnly,required,open'.split(','), function(value) { + BOOLEAN_ATTR[lowercase(value)] = value; +}); +var BOOLEAN_ELEMENTS = {}; +forEach('input,select,option,textarea,button,form,details'.split(','), function(value) { + BOOLEAN_ELEMENTS[value] = true; +}); +var ALIASED_ATTR = { + 'ngMinlength': 'minlength', + 'ngMaxlength': 'maxlength', + 'ngMin': 'min', + 'ngMax': 'max', + 'ngPattern': 'pattern' +}; + +function getBooleanAttrName(element, name) { + // check dom last since we will most likely fail on name + var booleanAttr = BOOLEAN_ATTR[name.toLowerCase()]; + + // booleanAttr is here twice to minimize DOM access + return booleanAttr && BOOLEAN_ELEMENTS[nodeName_(element)] && booleanAttr; +} + +function getAliasedAttrName(element, name) { + var nodeName = element.nodeName; + return (nodeName === 'INPUT' || nodeName === 'TEXTAREA') && ALIASED_ATTR[name]; +} + +forEach({ + data: jqLiteData, + removeData: jqLiteRemoveData +}, function(fn, name) { + JQLite[name] = fn; +}); + +forEach({ + data: jqLiteData, + inheritedData: jqLiteInheritedData, + + scope: function(element) { + // Can't use jqLiteData here directly so we stay compatible with jQuery! + return jqLite.data(element, '$scope') || jqLiteInheritedData(element.parentNode || element, ['$isolateScope', '$scope']); + }, + + isolateScope: function(element) { + // Can't use jqLiteData here directly so we stay compatible with jQuery! + return jqLite.data(element, '$isolateScope') || jqLite.data(element, '$isolateScopeNoTemplate'); + }, + + controller: jqLiteController, + + injector: function(element) { + return jqLiteInheritedData(element, '$injector'); + }, + + removeAttr: function(element, name) { + element.removeAttribute(name); + }, + + hasClass: jqLiteHasClass, + + css: function(element, name, value) { + name = camelCase(name); + + if (isDefined(value)) { + element.style[name] = value; + } else { + return element.style[name]; + } + }, + + attr: function(element, name, value) { + var lowercasedName = lowercase(name); + if (BOOLEAN_ATTR[lowercasedName]) { + if (isDefined(value)) { + if (!!value) { + element[name] = true; + element.setAttribute(name, lowercasedName); + } else { + element[name] = false; + element.removeAttribute(lowercasedName); + } + } else { + return (element[name] || + (element.attributes.getNamedItem(name) || noop).specified) + ? lowercasedName + : undefined; + } + } else if (isDefined(value)) { + element.setAttribute(name, value); + } else if (element.getAttribute) { + // the extra argument "2" is to get the right thing for a.href in IE, see jQuery code + // some elements (e.g. Document) don't have get attribute, so return undefined + var ret = element.getAttribute(name, 2); + // normalize non-existing attributes to undefined (as jQuery) + return ret === null ? undefined : ret; + } + }, + + prop: function(element, name, value) { + if (isDefined(value)) { + element[name] = value; + } else { + return element[name]; + } + }, + + text: (function() { + getText.$dv = ''; + return getText; + + function getText(element, value) { + if (isUndefined(value)) { + var nodeType = element.nodeType; + return (nodeType === NODE_TYPE_ELEMENT || nodeType === NODE_TYPE_TEXT) ? element.textContent : ''; + } + element.textContent = value; + } + })(), + + val: function(element, value) { + if (isUndefined(value)) { + if (element.multiple && nodeName_(element) === 'select') { + var result = []; + forEach(element.options, function(option) { + if (option.selected) { + result.push(option.value || option.text); + } + }); + return result.length === 0 ? null : result; + } + return element.value; + } + element.value = value; + }, + + html: function(element, value) { + if (isUndefined(value)) { + return element.innerHTML; + } + jqLiteDealoc(element, true); + element.innerHTML = value; + }, + + empty: jqLiteEmpty +}, function(fn, name) { + /** + * Properties: writes return selection, reads return first value + */ + JQLite.prototype[name] = function(arg1, arg2) { + var i, key; + var nodeCount = this.length; + + // jqLiteHasClass has only two arguments, but is a getter-only fn, so we need to special-case it + // in a way that survives minification. + // jqLiteEmpty takes no arguments but is a setter. + if (fn !== jqLiteEmpty && + (((fn.length == 2 && (fn !== jqLiteHasClass && fn !== jqLiteController)) ? arg1 : arg2) === undefined)) { + if (isObject(arg1)) { + + // we are a write, but the object properties are the key/values + for (i = 0; i < nodeCount; i++) { + if (fn === jqLiteData) { + // data() takes the whole object in jQuery + fn(this[i], arg1); + } else { + for (key in arg1) { + fn(this[i], key, arg1[key]); + } + } + } + // return self for chaining + return this; + } else { + // we are a read, so read the first child. + // TODO: do we still need this? + var value = fn.$dv; + // Only if we have $dv do we iterate over all, otherwise it is just the first element. + var jj = (value === undefined) ? Math.min(nodeCount, 1) : nodeCount; + for (var j = 0; j < jj; j++) { + var nodeValue = fn(this[j], arg1, arg2); + value = value ? value + nodeValue : nodeValue; + } + return value; + } + } else { + // we are a write, so apply to all children + for (i = 0; i < nodeCount; i++) { + fn(this[i], arg1, arg2); + } + // return self for chaining + return this; + } + }; +}); + +function createEventHandler(element, events) { + var eventHandler = function(event, type) { + // jQuery specific api + event.isDefaultPrevented = function() { + return event.defaultPrevented; + }; + + var eventFns = events[type || event.type]; + var eventFnsLength = eventFns ? eventFns.length : 0; + + if (!eventFnsLength) return; + + if (isUndefined(event.immediatePropagationStopped)) { + var originalStopImmediatePropagation = event.stopImmediatePropagation; + event.stopImmediatePropagation = function() { + event.immediatePropagationStopped = true; + + if (event.stopPropagation) { + event.stopPropagation(); + } + + if (originalStopImmediatePropagation) { + originalStopImmediatePropagation.call(event); + } + }; + } + + event.isImmediatePropagationStopped = function() { + return event.immediatePropagationStopped === true; + }; + + // Copy event handlers in case event handlers array is modified during execution. + if ((eventFnsLength > 1)) { + eventFns = shallowCopy(eventFns); + } + + for (var i = 0; i < eventFnsLength; i++) { + if (!event.isImmediatePropagationStopped()) { + eventFns[i].call(element, event); + } + } + }; + + // TODO: this is a hack for angularMocks/clearDataCache that makes it possible to deregister all + // events on `element` + eventHandler.elem = element; + return eventHandler; +} + +////////////////////////////////////////// +// Functions iterating traversal. +// These functions chain results into a single +// selector. +////////////////////////////////////////// +forEach({ + removeData: jqLiteRemoveData, + + on: function jqLiteOn(element, type, fn, unsupported) { + if (isDefined(unsupported)) throw jqLiteMinErr('onargs', 'jqLite#on() does not support the `selector` or `eventData` parameters'); + + // Do not add event handlers to non-elements because they will not be cleaned up. + if (!jqLiteAcceptsData(element)) { + return; + } + + var expandoStore = jqLiteExpandoStore(element, true); + var events = expandoStore.events; + var handle = expandoStore.handle; + + if (!handle) { + handle = expandoStore.handle = createEventHandler(element, events); + } + + // http://jsperf.com/string-indexof-vs-split + var types = type.indexOf(' ') >= 0 ? type.split(' ') : [type]; + var i = types.length; + + while (i--) { + type = types[i]; + var eventFns = events[type]; + + if (!eventFns) { + events[type] = []; + + if (type === 'mouseenter' || type === 'mouseleave') { + // Refer to jQuery's implementation of mouseenter & mouseleave + // Read about mouseenter and mouseleave: + // http://www.quirksmode.org/js/events_mouse.html#link8 + + jqLiteOn(element, MOUSE_EVENT_MAP[type], function(event) { + var target = this, related = event.relatedTarget; + // For mousenter/leave call the handler if related is outside the target. + // NB: No relatedTarget if the mouse left/entered the browser window + if (!related || (related !== target && !target.contains(related))) { + handle(event, type); + } + }); + + } else { + if (type !== '$destroy') { + addEventListenerFn(element, type, handle); + } + } + eventFns = events[type]; + } + eventFns.push(fn); + } + }, + + off: jqLiteOff, + + one: function(element, type, fn) { + element = jqLite(element); + + //add the listener twice so that when it is called + //you can remove the original function and still be + //able to call element.off(ev, fn) normally + element.on(type, function onFn() { + element.off(type, fn); + element.off(type, onFn); + }); + element.on(type, fn); + }, + + replaceWith: function(element, replaceNode) { + var index, parent = element.parentNode; + jqLiteDealoc(element); + forEach(new JQLite(replaceNode), function(node) { + if (index) { + parent.insertBefore(node, index.nextSibling); + } else { + parent.replaceChild(node, element); + } + index = node; + }); + }, + + children: function(element) { + var children = []; + forEach(element.childNodes, function(element) { + if (element.nodeType === NODE_TYPE_ELEMENT) + children.push(element); + }); + return children; + }, + + contents: function(element) { + return element.contentDocument || element.childNodes || []; + }, + + append: function(element, node) { + var nodeType = element.nodeType; + if (nodeType !== NODE_TYPE_ELEMENT && nodeType !== NODE_TYPE_DOCUMENT_FRAGMENT) return; + + node = new JQLite(node); + + for (var i = 0, ii = node.length; i < ii; i++) { + var child = node[i]; + element.appendChild(child); + } + }, + + prepend: function(element, node) { + if (element.nodeType === NODE_TYPE_ELEMENT) { + var index = element.firstChild; + forEach(new JQLite(node), function(child) { + element.insertBefore(child, index); + }); + } + }, + + wrap: function(element, wrapNode) { + wrapNode = jqLite(wrapNode).eq(0).clone()[0]; + var parent = element.parentNode; + if (parent) { + parent.replaceChild(wrapNode, element); + } + wrapNode.appendChild(element); + }, + + remove: jqLiteRemove, + + detach: function(element) { + jqLiteRemove(element, true); + }, + + after: function(element, newElement) { + var index = element, parent = element.parentNode; + newElement = new JQLite(newElement); + + for (var i = 0, ii = newElement.length; i < ii; i++) { + var node = newElement[i]; + parent.insertBefore(node, index.nextSibling); + index = node; + } + }, + + addClass: jqLiteAddClass, + removeClass: jqLiteRemoveClass, + + toggleClass: function(element, selector, condition) { + if (selector) { + forEach(selector.split(' '), function(className) { + var classCondition = condition; + if (isUndefined(classCondition)) { + classCondition = !jqLiteHasClass(element, className); + } + (classCondition ? jqLiteAddClass : jqLiteRemoveClass)(element, className); + }); + } + }, + + parent: function(element) { + var parent = element.parentNode; + return parent && parent.nodeType !== NODE_TYPE_DOCUMENT_FRAGMENT ? parent : null; + }, + + next: function(element) { + return element.nextElementSibling; + }, + + find: function(element, selector) { + if (element.getElementsByTagName) { + return element.getElementsByTagName(selector); + } else { + return []; + } + }, + + clone: jqLiteClone, + + triggerHandler: function(element, event, extraParameters) { + + var dummyEvent, eventFnsCopy, handlerArgs; + var eventName = event.type || event; + var expandoStore = jqLiteExpandoStore(element); + var events = expandoStore && expandoStore.events; + var eventFns = events && events[eventName]; + + if (eventFns) { + // Create a dummy event to pass to the handlers + dummyEvent = { + preventDefault: function() { this.defaultPrevented = true; }, + isDefaultPrevented: function() { return this.defaultPrevented === true; }, + stopImmediatePropagation: function() { this.immediatePropagationStopped = true; }, + isImmediatePropagationStopped: function() { return this.immediatePropagationStopped === true; }, + stopPropagation: noop, + type: eventName, + target: element + }; + + // If a custom event was provided then extend our dummy event with it + if (event.type) { + dummyEvent = extend(dummyEvent, event); + } + + // Copy event handlers in case event handlers array is modified during execution. + eventFnsCopy = shallowCopy(eventFns); + handlerArgs = extraParameters ? [dummyEvent].concat(extraParameters) : [dummyEvent]; + + forEach(eventFnsCopy, function(fn) { + if (!dummyEvent.isImmediatePropagationStopped()) { + fn.apply(element, handlerArgs); + } + }); + } + } +}, function(fn, name) { + /** + * chaining functions + */ + JQLite.prototype[name] = function(arg1, arg2, arg3) { + var value; + + for (var i = 0, ii = this.length; i < ii; i++) { + if (isUndefined(value)) { + value = fn(this[i], arg1, arg2, arg3); + if (isDefined(value)) { + // any function which returns a value needs to be wrapped + value = jqLite(value); + } + } else { + jqLiteAddNodes(value, fn(this[i], arg1, arg2, arg3)); + } + } + return isDefined(value) ? value : this; + }; + + // bind legacy bind/unbind to on/off + JQLite.prototype.bind = JQLite.prototype.on; + JQLite.prototype.unbind = JQLite.prototype.off; +}); + + +// Provider for private $$jqLite service +function $$jqLiteProvider() { + this.$get = function $$jqLite() { + return extend(JQLite, { + hasClass: function(node, classes) { + if (node.attr) node = node[0]; + return jqLiteHasClass(node, classes); + }, + addClass: function(node, classes) { + if (node.attr) node = node[0]; + return jqLiteAddClass(node, classes); + }, + removeClass: function(node, classes) { + if (node.attr) node = node[0]; + return jqLiteRemoveClass(node, classes); + } + }); + }; +} + +/** + * Computes a hash of an 'obj'. + * Hash of a: + * string is string + * number is number as string + * object is either result of calling $$hashKey function on the object or uniquely generated id, + * that is also assigned to the $$hashKey property of the object. + * + * @param obj + * @returns {string} hash string such that the same input will have the same hash string. + * The resulting string key is in 'type:hashKey' format. + */ +function hashKey(obj, nextUidFn) { + var key = obj && obj.$$hashKey; + + if (key) { + if (typeof key === 'function') { + key = obj.$$hashKey(); + } + return key; + } + + var objType = typeof obj; + if (objType == 'function' || (objType == 'object' && obj !== null)) { + key = obj.$$hashKey = objType + ':' + (nextUidFn || nextUid)(); + } else { + key = objType + ':' + obj; + } + + return key; +} + +/** + * HashMap which can use objects as keys + */ +function HashMap(array, isolatedUid) { + if (isolatedUid) { + var uid = 0; + this.nextUid = function() { + return ++uid; + }; + } + forEach(array, this.put, this); +} +HashMap.prototype = { + /** + * Store key value pair + * @param key key to store can be any type + * @param value value to store can be any type + */ + put: function(key, value) { + this[hashKey(key, this.nextUid)] = value; + }, + + /** + * @param key + * @returns {Object} the value for the key + */ + get: function(key) { + return this[hashKey(key, this.nextUid)]; + }, + + /** + * Remove the key/value pair + * @param key + */ + remove: function(key) { + var value = this[key = hashKey(key, this.nextUid)]; + delete this[key]; + return value; + } +}; + +/** + * @ngdoc function + * @module ng + * @name angular.injector + * @kind function + * + * @description + * Creates an injector object that can be used for retrieving services as well as for + * dependency injection (see {@link guide/di dependency injection}). + * + * @param {Array.} modules A list of module functions or their aliases. See + * {@link angular.module}. The `ng` module must be explicitly added. + * @param {boolean=} [strictDi=false] Whether the injector should be in strict mode, which + * disallows argument name annotation inference. + * @returns {injector} Injector object. See {@link auto.$injector $injector}. + * + * @example + * Typical usage + * ```js + * // create an injector + * var $injector = angular.injector(['ng']); + * + * // use the injector to kick off your application + * // use the type inference to auto inject arguments, or use implicit injection + * $injector.invoke(function($rootScope, $compile, $document) { + * $compile($document)($rootScope); + * $rootScope.$digest(); + * }); + * ``` + * + * Sometimes you want to get access to the injector of a currently running Angular app + * from outside Angular. Perhaps, you want to inject and compile some markup after the + * application has been bootstrapped. You can do this using the extra `injector()` added + * to JQuery/jqLite elements. See {@link angular.element}. + * + * *This is fairly rare but could be the case if a third party library is injecting the + * markup.* + * + * In the following example a new block of HTML containing a `ng-controller` + * directive is added to the end of the document body by JQuery. We then compile and link + * it into the current AngularJS scope. + * + * ```js + * var $div = $('
      {{content.label}}
      '); + * $(document.body).append($div); + * + * angular.element(document).injector().invoke(function($compile) { + * var scope = angular.element($div).scope(); + * $compile($div)(scope); + * }); + * ``` + */ + + +/** + * @ngdoc module + * @name auto + * @description + * + * Implicit module which gets automatically added to each {@link auto.$injector $injector}. + */ + +var FN_ARGS = /^function\s*[^\(]*\(\s*([^\)]*)\)/m; +var FN_ARG_SPLIT = /,/; +var FN_ARG = /^\s*(_?)(\S+?)\1\s*$/; +var STRIP_COMMENTS = /((\/\/.*$)|(\/\*[\s\S]*?\*\/))/mg; +var $injectorMinErr = minErr('$injector'); + +function anonFn(fn) { + // For anonymous functions, showing at the very least the function signature can help in + // debugging. + var fnText = fn.toString().replace(STRIP_COMMENTS, ''), + args = fnText.match(FN_ARGS); + if (args) { + return 'function(' + (args[1] || '').replace(/[\s\r\n]+/, ' ') + ')'; + } + return 'fn'; +} + +function annotate(fn, strictDi, name) { + var $inject, + fnText, + argDecl, + last; + + if (typeof fn === 'function') { + if (!($inject = fn.$inject)) { + $inject = []; + if (fn.length) { + if (strictDi) { + if (!isString(name) || !name) { + name = fn.name || anonFn(fn); + } + throw $injectorMinErr('strictdi', + '{0} is not using explicit annotation and cannot be invoked in strict mode', name); + } + fnText = fn.toString().replace(STRIP_COMMENTS, ''); + argDecl = fnText.match(FN_ARGS); + forEach(argDecl[1].split(FN_ARG_SPLIT), function(arg) { + arg.replace(FN_ARG, function(all, underscore, name) { + $inject.push(name); + }); + }); + } + fn.$inject = $inject; + } + } else if (isArray(fn)) { + last = fn.length - 1; + assertArgFn(fn[last], 'fn'); + $inject = fn.slice(0, last); + } else { + assertArgFn(fn, 'fn', true); + } + return $inject; +} + +/////////////////////////////////////// + +/** + * @ngdoc service + * @name $injector + * + * @description + * + * `$injector` is used to retrieve object instances as defined by + * {@link auto.$provide provider}, instantiate types, invoke methods, + * and load modules. + * + * The following always holds true: + * + * ```js + * var $injector = angular.injector(); + * expect($injector.get('$injector')).toBe($injector); + * expect($injector.invoke(function($injector) { + * return $injector; + * })).toBe($injector); + * ``` + * + * # Injection Function Annotation + * + * JavaScript does not have annotations, and annotations are needed for dependency injection. The + * following are all valid ways of annotating function with injection arguments and are equivalent. + * + * ```js + * // inferred (only works if code not minified/obfuscated) + * $injector.invoke(function(serviceA){}); + * + * // annotated + * function explicit(serviceA) {}; + * explicit.$inject = ['serviceA']; + * $injector.invoke(explicit); + * + * // inline + * $injector.invoke(['serviceA', function(serviceA){}]); + * ``` + * + * ## Inference + * + * In JavaScript calling `toString()` on a function returns the function definition. The definition + * can then be parsed and the function arguments can be extracted. This method of discovering + * annotations is disallowed when the injector is in strict mode. + * *NOTE:* This does not work with minification, and obfuscation tools since these tools change the + * argument names. + * + * ## `$inject` Annotation + * By adding an `$inject` property onto a function the injection parameters can be specified. + * + * ## Inline + * As an array of injection names, where the last item in the array is the function to call. + */ + +/** + * @ngdoc method + * @name $injector#get + * + * @description + * Return an instance of the service. + * + * @param {string} name The name of the instance to retrieve. + * @param {string} caller An optional string to provide the origin of the function call for error messages. + * @return {*} The instance. + */ + +/** + * @ngdoc method + * @name $injector#invoke + * + * @description + * Invoke the method and supply the method arguments from the `$injector`. + * + * @param {!Function} fn The function to invoke. Function parameters are injected according to the + * {@link guide/di $inject Annotation} rules. + * @param {Object=} self The `this` for the invoked method. + * @param {Object=} locals Optional object. If preset then any argument names are read from this + * object first, before the `$injector` is consulted. + * @returns {*} the value returned by the invoked `fn` function. + */ + +/** + * @ngdoc method + * @name $injector#has + * + * @description + * Allows the user to query if the particular service exists. + * + * @param {string} name Name of the service to query. + * @returns {boolean} `true` if injector has given service. + */ + +/** + * @ngdoc method + * @name $injector#instantiate + * @description + * Create a new instance of JS type. The method takes a constructor function, invokes the new + * operator, and supplies all of the arguments to the constructor function as specified by the + * constructor annotation. + * + * @param {Function} Type Annotated constructor function. + * @param {Object=} locals Optional object. If preset then any argument names are read from this + * object first, before the `$injector` is consulted. + * @returns {Object} new instance of `Type`. + */ + +/** + * @ngdoc method + * @name $injector#annotate + * + * @description + * Returns an array of service names which the function is requesting for injection. This API is + * used by the injector to determine which services need to be injected into the function when the + * function is invoked. There are three ways in which the function can be annotated with the needed + * dependencies. + * + * # Argument names + * + * The simplest form is to extract the dependencies from the arguments of the function. This is done + * by converting the function into a string using `toString()` method and extracting the argument + * names. + * ```js + * // Given + * function MyController($scope, $route) { + * // ... + * } + * + * // Then + * expect(injector.annotate(MyController)).toEqual(['$scope', '$route']); + * ``` + * + * You can disallow this method by using strict injection mode. + * + * This method does not work with code minification / obfuscation. For this reason the following + * annotation strategies are supported. + * + * # The `$inject` property + * + * If a function has an `$inject` property and its value is an array of strings, then the strings + * represent names of services to be injected into the function. + * ```js + * // Given + * var MyController = function(obfuscatedScope, obfuscatedRoute) { + * // ... + * } + * // Define function dependencies + * MyController['$inject'] = ['$scope', '$route']; + * + * // Then + * expect(injector.annotate(MyController)).toEqual(['$scope', '$route']); + * ``` + * + * # The array notation + * + * It is often desirable to inline Injected functions and that's when setting the `$inject` property + * is very inconvenient. In these situations using the array notation to specify the dependencies in + * a way that survives minification is a better choice: + * + * ```js + * // We wish to write this (not minification / obfuscation safe) + * injector.invoke(function($compile, $rootScope) { + * // ... + * }); + * + * // We are forced to write break inlining + * var tmpFn = function(obfuscatedCompile, obfuscatedRootScope) { + * // ... + * }; + * tmpFn.$inject = ['$compile', '$rootScope']; + * injector.invoke(tmpFn); + * + * // To better support inline function the inline annotation is supported + * injector.invoke(['$compile', '$rootScope', function(obfCompile, obfRootScope) { + * // ... + * }]); + * + * // Therefore + * expect(injector.annotate( + * ['$compile', '$rootScope', function(obfus_$compile, obfus_$rootScope) {}]) + * ).toEqual(['$compile', '$rootScope']); + * ``` + * + * @param {Function|Array.} fn Function for which dependent service names need to + * be retrieved as described above. + * + * @param {boolean=} [strictDi=false] Disallow argument name annotation inference. + * + * @returns {Array.} The names of the services which the function requires. + */ + + + + +/** + * @ngdoc service + * @name $provide + * + * @description + * + * The {@link auto.$provide $provide} service has a number of methods for registering components + * with the {@link auto.$injector $injector}. Many of these functions are also exposed on + * {@link angular.Module}. + * + * An Angular **service** is a singleton object created by a **service factory**. These **service + * factories** are functions which, in turn, are created by a **service provider**. + * The **service providers** are constructor functions. When instantiated they must contain a + * property called `$get`, which holds the **service factory** function. + * + * When you request a service, the {@link auto.$injector $injector} is responsible for finding the + * correct **service provider**, instantiating it and then calling its `$get` **service factory** + * function to get the instance of the **service**. + * + * Often services have no configuration options and there is no need to add methods to the service + * provider. The provider will be no more than a constructor function with a `$get` property. For + * these cases the {@link auto.$provide $provide} service has additional helper methods to register + * services without specifying a provider. + * + * * {@link auto.$provide#provider provider(provider)} - registers a **service provider** with the + * {@link auto.$injector $injector} + * * {@link auto.$provide#constant constant(obj)} - registers a value/object that can be accessed by + * providers and services. + * * {@link auto.$provide#value value(obj)} - registers a value/object that can only be accessed by + * services, not providers. + * * {@link auto.$provide#factory factory(fn)} - registers a service **factory function**, `fn`, + * that will be wrapped in a **service provider** object, whose `$get` property will contain the + * given factory function. + * * {@link auto.$provide#service service(class)} - registers a **constructor function**, `class` + * that will be wrapped in a **service provider** object, whose `$get` property will instantiate + * a new object using the given constructor function. + * + * See the individual methods for more information and examples. + */ + +/** + * @ngdoc method + * @name $provide#provider + * @description + * + * Register a **provider function** with the {@link auto.$injector $injector}. Provider functions + * are constructor functions, whose instances are responsible for "providing" a factory for a + * service. + * + * Service provider names start with the name of the service they provide followed by `Provider`. + * For example, the {@link ng.$log $log} service has a provider called + * {@link ng.$logProvider $logProvider}. + * + * Service provider objects can have additional methods which allow configuration of the provider + * and its service. Importantly, you can configure what kind of service is created by the `$get` + * method, or how that service will act. For example, the {@link ng.$logProvider $logProvider} has a + * method {@link ng.$logProvider#debugEnabled debugEnabled} + * which lets you specify whether the {@link ng.$log $log} service will log debug messages to the + * console or not. + * + * @param {string} name The name of the instance. NOTE: the provider will be available under `name + + 'Provider'` key. + * @param {(Object|function())} provider If the provider is: + * + * - `Object`: then it should have a `$get` method. The `$get` method will be invoked using + * {@link auto.$injector#invoke $injector.invoke()} when an instance needs to be created. + * - `Constructor`: a new instance of the provider will be created using + * {@link auto.$injector#instantiate $injector.instantiate()}, then treated as `object`. + * + * @returns {Object} registered provider instance + + * @example + * + * The following example shows how to create a simple event tracking service and register it using + * {@link auto.$provide#provider $provide.provider()}. + * + * ```js + * // Define the eventTracker provider + * function EventTrackerProvider() { + * var trackingUrl = '/track'; + * + * // A provider method for configuring where the tracked events should been saved + * this.setTrackingUrl = function(url) { + * trackingUrl = url; + * }; + * + * // The service factory function + * this.$get = ['$http', function($http) { + * var trackedEvents = {}; + * return { + * // Call this to track an event + * event: function(event) { + * var count = trackedEvents[event] || 0; + * count += 1; + * trackedEvents[event] = count; + * return count; + * }, + * // Call this to save the tracked events to the trackingUrl + * save: function() { + * $http.post(trackingUrl, trackedEvents); + * } + * }; + * }]; + * } + * + * describe('eventTracker', function() { + * var postSpy; + * + * beforeEach(module(function($provide) { + * // Register the eventTracker provider + * $provide.provider('eventTracker', EventTrackerProvider); + * })); + * + * beforeEach(module(function(eventTrackerProvider) { + * // Configure eventTracker provider + * eventTrackerProvider.setTrackingUrl('/custom-track'); + * })); + * + * it('tracks events', inject(function(eventTracker) { + * expect(eventTracker.event('login')).toEqual(1); + * expect(eventTracker.event('login')).toEqual(2); + * })); + * + * it('saves to the tracking url', inject(function(eventTracker, $http) { + * postSpy = spyOn($http, 'post'); + * eventTracker.event('login'); + * eventTracker.save(); + * expect(postSpy).toHaveBeenCalled(); + * expect(postSpy.mostRecentCall.args[0]).not.toEqual('/track'); + * expect(postSpy.mostRecentCall.args[0]).toEqual('/custom-track'); + * expect(postSpy.mostRecentCall.args[1]).toEqual({ 'login': 1 }); + * })); + * }); + * ``` + */ + +/** + * @ngdoc method + * @name $provide#factory + * @description + * + * Register a **service factory**, which will be called to return the service instance. + * This is short for registering a service where its provider consists of only a `$get` property, + * which is the given service factory function. + * You should use {@link auto.$provide#factory $provide.factory(getFn)} if you do not need to + * configure your service in a provider. + * + * @param {string} name The name of the instance. + * @param {function()} $getFn The $getFn for the instance creation. Internally this is a short hand + * for `$provide.provider(name, {$get: $getFn})`. + * @returns {Object} registered provider instance + * + * @example + * Here is an example of registering a service + * ```js + * $provide.factory('ping', ['$http', function($http) { + * return function ping() { + * return $http.send('/ping'); + * }; + * }]); + * ``` + * You would then inject and use this service like this: + * ```js + * someModule.controller('Ctrl', ['ping', function(ping) { + * ping(); + * }]); + * ``` + */ + + +/** + * @ngdoc method + * @name $provide#service + * @description + * + * Register a **service constructor**, which will be invoked with `new` to create the service + * instance. + * This is short for registering a service where its provider's `$get` property is the service + * constructor function that will be used to instantiate the service instance. + * + * You should use {@link auto.$provide#service $provide.service(class)} if you define your service + * as a type/class. + * + * @param {string} name The name of the instance. + * @param {Function} constructor A class (constructor function) that will be instantiated. + * @returns {Object} registered provider instance + * + * @example + * Here is an example of registering a service using + * {@link auto.$provide#service $provide.service(class)}. + * ```js + * var Ping = function($http) { + * this.$http = $http; + * }; + * + * Ping.$inject = ['$http']; + * + * Ping.prototype.send = function() { + * return this.$http.get('/ping'); + * }; + * $provide.service('ping', Ping); + * ``` + * You would then inject and use this service like this: + * ```js + * someModule.controller('Ctrl', ['ping', function(ping) { + * ping.send(); + * }]); + * ``` + */ + + +/** + * @ngdoc method + * @name $provide#value + * @description + * + * Register a **value service** with the {@link auto.$injector $injector}, such as a string, a + * number, an array, an object or a function. This is short for registering a service where its + * provider's `$get` property is a factory function that takes no arguments and returns the **value + * service**. + * + * Value services are similar to constant services, except that they cannot be injected into a + * module configuration function (see {@link angular.Module#config}) but they can be overridden by + * an Angular + * {@link auto.$provide#decorator decorator}. + * + * @param {string} name The name of the instance. + * @param {*} value The value. + * @returns {Object} registered provider instance + * + * @example + * Here are some examples of creating value services. + * ```js + * $provide.value('ADMIN_USER', 'admin'); + * + * $provide.value('RoleLookup', { admin: 0, writer: 1, reader: 2 }); + * + * $provide.value('halfOf', function(value) { + * return value / 2; + * }); + * ``` + */ + + +/** + * @ngdoc method + * @name $provide#constant + * @description + * + * Register a **constant service**, such as a string, a number, an array, an object or a function, + * with the {@link auto.$injector $injector}. Unlike {@link auto.$provide#value value} it can be + * injected into a module configuration function (see {@link angular.Module#config}) and it cannot + * be overridden by an Angular {@link auto.$provide#decorator decorator}. + * + * @param {string} name The name of the constant. + * @param {*} value The constant value. + * @returns {Object} registered instance + * + * @example + * Here a some examples of creating constants: + * ```js + * $provide.constant('SHARD_HEIGHT', 306); + * + * $provide.constant('MY_COLOURS', ['red', 'blue', 'grey']); + * + * $provide.constant('double', function(value) { + * return value * 2; + * }); + * ``` + */ + + +/** + * @ngdoc method + * @name $provide#decorator + * @description + * + * Register a **service decorator** with the {@link auto.$injector $injector}. A service decorator + * intercepts the creation of a service, allowing it to override or modify the behaviour of the + * service. The object returned by the decorator may be the original service, or a new service + * object which replaces or wraps and delegates to the original service. + * + * @param {string} name The name of the service to decorate. + * @param {function()} decorator This function will be invoked when the service needs to be + * instantiated and should return the decorated service instance. The function is called using + * the {@link auto.$injector#invoke injector.invoke} method and is therefore fully injectable. + * Local injection arguments: + * + * * `$delegate` - The original service instance, which can be monkey patched, configured, + * decorated or delegated to. + * + * @example + * Here we decorate the {@link ng.$log $log} service to convert warnings to errors by intercepting + * calls to {@link ng.$log#error $log.warn()}. + * ```js + * $provide.decorator('$log', ['$delegate', function($delegate) { + * $delegate.warn = $delegate.error; + * return $delegate; + * }]); + * ``` + */ + + +function createInjector(modulesToLoad, strictDi) { + strictDi = (strictDi === true); + var INSTANTIATING = {}, + providerSuffix = 'Provider', + path = [], + loadedModules = new HashMap([], true), + providerCache = { + $provide: { + provider: supportObject(provider), + factory: supportObject(factory), + service: supportObject(service), + value: supportObject(value), + constant: supportObject(constant), + decorator: decorator + } + }, + providerInjector = (providerCache.$injector = + createInternalInjector(providerCache, function(serviceName, caller) { + if (angular.isString(caller)) { + path.push(caller); + } + throw $injectorMinErr('unpr', "Unknown provider: {0}", path.join(' <- ')); + })), + instanceCache = {}, + instanceInjector = (instanceCache.$injector = + createInternalInjector(instanceCache, function(serviceName, caller) { + var provider = providerInjector.get(serviceName + providerSuffix, caller); + return instanceInjector.invoke(provider.$get, provider, undefined, serviceName); + })); + + + forEach(loadModules(modulesToLoad), function(fn) { instanceInjector.invoke(fn || noop); }); + + return instanceInjector; + + //////////////////////////////////// + // $provider + //////////////////////////////////// + + function supportObject(delegate) { + return function(key, value) { + if (isObject(key)) { + forEach(key, reverseParams(delegate)); + } else { + return delegate(key, value); + } + }; + } + + function provider(name, provider_) { + assertNotHasOwnProperty(name, 'service'); + if (isFunction(provider_) || isArray(provider_)) { + provider_ = providerInjector.instantiate(provider_); + } + if (!provider_.$get) { + throw $injectorMinErr('pget', "Provider '{0}' must define $get factory method.", name); + } + return providerCache[name + providerSuffix] = provider_; + } + + function enforceReturnValue(name, factory) { + return function enforcedReturnValue() { + var result = instanceInjector.invoke(factory, this); + if (isUndefined(result)) { + throw $injectorMinErr('undef', "Provider '{0}' must return a value from $get factory method.", name); + } + return result; + }; + } + + function factory(name, factoryFn, enforce) { + return provider(name, { + $get: enforce !== false ? enforceReturnValue(name, factoryFn) : factoryFn + }); + } + + function service(name, constructor) { + return factory(name, ['$injector', function($injector) { + return $injector.instantiate(constructor); + }]); + } + + function value(name, val) { return factory(name, valueFn(val), false); } + + function constant(name, value) { + assertNotHasOwnProperty(name, 'constant'); + providerCache[name] = value; + instanceCache[name] = value; + } + + function decorator(serviceName, decorFn) { + var origProvider = providerInjector.get(serviceName + providerSuffix), + orig$get = origProvider.$get; + + origProvider.$get = function() { + var origInstance = instanceInjector.invoke(orig$get, origProvider); + return instanceInjector.invoke(decorFn, null, {$delegate: origInstance}); + }; + } + + //////////////////////////////////// + // Module Loading + //////////////////////////////////// + function loadModules(modulesToLoad) { + var runBlocks = [], moduleFn; + forEach(modulesToLoad, function(module) { + if (loadedModules.get(module)) return; + loadedModules.put(module, true); + + function runInvokeQueue(queue) { + var i, ii; + for (i = 0, ii = queue.length; i < ii; i++) { + var invokeArgs = queue[i], + provider = providerInjector.get(invokeArgs[0]); + + provider[invokeArgs[1]].apply(provider, invokeArgs[2]); + } + } + + try { + if (isString(module)) { + moduleFn = angularModule(module); + runBlocks = runBlocks.concat(loadModules(moduleFn.requires)).concat(moduleFn._runBlocks); + runInvokeQueue(moduleFn._invokeQueue); + runInvokeQueue(moduleFn._configBlocks); + } else if (isFunction(module)) { + runBlocks.push(providerInjector.invoke(module)); + } else if (isArray(module)) { + runBlocks.push(providerInjector.invoke(module)); + } else { + assertArgFn(module, 'module'); + } + } catch (e) { + if (isArray(module)) { + module = module[module.length - 1]; + } + if (e.message && e.stack && e.stack.indexOf(e.message) == -1) { + // Safari & FF's stack traces don't contain error.message content + // unlike those of Chrome and IE + // So if stack doesn't contain message, we create a new string that contains both. + // Since error.stack is read-only in Safari, I'm overriding e and not e.stack here. + /* jshint -W022 */ + e = e.message + '\n' + e.stack; + } + throw $injectorMinErr('modulerr', "Failed to instantiate module {0} due to:\n{1}", + module, e.stack || e.message || e); + } + }); + return runBlocks; + } + + //////////////////////////////////// + // internal Injector + //////////////////////////////////// + + function createInternalInjector(cache, factory) { + + function getService(serviceName, caller) { + if (cache.hasOwnProperty(serviceName)) { + if (cache[serviceName] === INSTANTIATING) { + throw $injectorMinErr('cdep', 'Circular dependency found: {0}', + serviceName + ' <- ' + path.join(' <- ')); + } + return cache[serviceName]; + } else { + try { + path.unshift(serviceName); + cache[serviceName] = INSTANTIATING; + return cache[serviceName] = factory(serviceName, caller); + } catch (err) { + if (cache[serviceName] === INSTANTIATING) { + delete cache[serviceName]; + } + throw err; + } finally { + path.shift(); + } + } + } + + function invoke(fn, self, locals, serviceName) { + if (typeof locals === 'string') { + serviceName = locals; + locals = null; + } + + var args = [], + $inject = annotate(fn, strictDi, serviceName), + length, i, + key; + + for (i = 0, length = $inject.length; i < length; i++) { + key = $inject[i]; + if (typeof key !== 'string') { + throw $injectorMinErr('itkn', + 'Incorrect injection token! Expected service name as string, got {0}', key); + } + args.push( + locals && locals.hasOwnProperty(key) + ? locals[key] + : getService(key, serviceName) + ); + } + if (isArray(fn)) { + fn = fn[length]; + } + + // http://jsperf.com/angularjs-invoke-apply-vs-switch + // #5388 + return fn.apply(self, args); + } + + function instantiate(Type, locals, serviceName) { + // Check if Type is annotated and use just the given function at n-1 as parameter + // e.g. someModule.factory('greeter', ['$window', function(renamed$window) {}]); + // Object creation: http://jsperf.com/create-constructor/2 + var instance = Object.create((isArray(Type) ? Type[Type.length - 1] : Type).prototype); + var returnedValue = invoke(Type, instance, locals, serviceName); + + return isObject(returnedValue) || isFunction(returnedValue) ? returnedValue : instance; + } + + return { + invoke: invoke, + instantiate: instantiate, + get: getService, + annotate: annotate, + has: function(name) { + return providerCache.hasOwnProperty(name + providerSuffix) || cache.hasOwnProperty(name); + } + }; + } +} + +createInjector.$$annotate = annotate; + +/** + * @ngdoc provider + * @name $anchorScrollProvider + * + * @description + * Use `$anchorScrollProvider` to disable automatic scrolling whenever + * {@link ng.$location#hash $location.hash()} changes. + */ +function $AnchorScrollProvider() { + + var autoScrollingEnabled = true; + + /** + * @ngdoc method + * @name $anchorScrollProvider#disableAutoScrolling + * + * @description + * By default, {@link ng.$anchorScroll $anchorScroll()} will automatically detect changes to + * {@link ng.$location#hash $location.hash()} and scroll to the element matching the new hash.
      + * Use this method to disable automatic scrolling. + * + * If automatic scrolling is disabled, one must explicitly call + * {@link ng.$anchorScroll $anchorScroll()} in order to scroll to the element related to the + * current hash. + */ + this.disableAutoScrolling = function() { + autoScrollingEnabled = false; + }; + + /** + * @ngdoc service + * @name $anchorScroll + * @kind function + * @requires $window + * @requires $location + * @requires $rootScope + * + * @description + * When called, it checks the current value of {@link ng.$location#hash $location.hash()} and + * scrolls to the related element, according to the rules specified in the + * [Html5 spec](http://dev.w3.org/html5/spec/Overview.html#the-indicated-part-of-the-document). + * + * It also watches the {@link ng.$location#hash $location.hash()} and automatically scrolls to + * match any anchor whenever it changes. This can be disabled by calling + * {@link ng.$anchorScrollProvider#disableAutoScrolling $anchorScrollProvider.disableAutoScrolling()}. + * + * Additionally, you can use its {@link ng.$anchorScroll#yOffset yOffset} property to specify a + * vertical scroll-offset (either fixed or dynamic). + * + * @property {(number|function|jqLite)} yOffset + * If set, specifies a vertical scroll-offset. This is often useful when there are fixed + * positioned elements at the top of the page, such as navbars, headers etc. + * + * `yOffset` can be specified in various ways: + * - **number**: A fixed number of pixels to be used as offset.

      + * - **function**: A getter function called everytime `$anchorScroll()` is executed. Must return + * a number representing the offset (in pixels).

      + * - **jqLite**: A jqLite/jQuery element to be used for specifying the offset. The distance from + * the top of the page to the element's bottom will be used as offset.
      + * **Note**: The element will be taken into account only as long as its `position` is set to + * `fixed`. This option is useful, when dealing with responsive navbars/headers that adjust + * their height and/or positioning according to the viewport's size. + * + *
      + *
      + * In order for `yOffset` to work properly, scrolling should take place on the document's root and + * not some child element. + *
      + * + * @example + + +
      + Go to bottom + You're at the bottom! +
      +
      + + angular.module('anchorScrollExample', []) + .controller('ScrollController', ['$scope', '$location', '$anchorScroll', + function ($scope, $location, $anchorScroll) { + $scope.gotoBottom = function() { + // set the location.hash to the id of + // the element you wish to scroll to. + $location.hash('bottom'); + + // call $anchorScroll() + $anchorScroll(); + }; + }]); + + + #scrollArea { + height: 280px; + overflow: auto; + } + + #bottom { + display: block; + margin-top: 2000px; + } + +
      + * + *
      + * The example below illustrates the use of a vertical scroll-offset (specified as a fixed value). + * See {@link ng.$anchorScroll#yOffset $anchorScroll.yOffset} for more details. + * + * @example + + + +
      + Anchor {{x}} of 5 +
      +
      + + angular.module('anchorScrollOffsetExample', []) + .run(['$anchorScroll', function($anchorScroll) { + $anchorScroll.yOffset = 50; // always scroll by 50 extra pixels + }]) + .controller('headerCtrl', ['$anchorScroll', '$location', '$scope', + function ($anchorScroll, $location, $scope) { + $scope.gotoAnchor = function(x) { + var newHash = 'anchor' + x; + if ($location.hash() !== newHash) { + // set the $location.hash to `newHash` and + // $anchorScroll will automatically scroll to it + $location.hash('anchor' + x); + } else { + // call $anchorScroll() explicitly, + // since $location.hash hasn't changed + $anchorScroll(); + } + }; + } + ]); + + + body { + padding-top: 50px; + } + + .anchor { + border: 2px dashed DarkOrchid; + padding: 10px 10px 200px 10px; + } + + .fixed-header { + background-color: rgba(0, 0, 0, 0.2); + height: 50px; + position: fixed; + top: 0; left: 0; right: 0; + } + + .fixed-header > a { + display: inline-block; + margin: 5px 15px; + } + +
      + */ + this.$get = ['$window', '$location', '$rootScope', function($window, $location, $rootScope) { + var document = $window.document; + + // Helper function to get first anchor from a NodeList + // (using `Array#some()` instead of `angular#forEach()` since it's more performant + // and working in all supported browsers.) + function getFirstAnchor(list) { + var result = null; + Array.prototype.some.call(list, function(element) { + if (nodeName_(element) === 'a') { + result = element; + return true; + } + }); + return result; + } + + function getYOffset() { + + var offset = scroll.yOffset; + + if (isFunction(offset)) { + offset = offset(); + } else if (isElement(offset)) { + var elem = offset[0]; + var style = $window.getComputedStyle(elem); + if (style.position !== 'fixed') { + offset = 0; + } else { + offset = elem.getBoundingClientRect().bottom; + } + } else if (!isNumber(offset)) { + offset = 0; + } + + return offset; + } + + function scrollTo(elem) { + if (elem) { + elem.scrollIntoView(); + + var offset = getYOffset(); + + if (offset) { + // `offset` is the number of pixels we should scroll UP in order to align `elem` properly. + // This is true ONLY if the call to `elem.scrollIntoView()` initially aligns `elem` at the + // top of the viewport. + // + // IF the number of pixels from the top of `elem` to the end of the page's content is less + // than the height of the viewport, then `elem.scrollIntoView()` will align the `elem` some + // way down the page. + // + // This is often the case for elements near the bottom of the page. + // + // In such cases we do not need to scroll the whole `offset` up, just the difference between + // the top of the element and the offset, which is enough to align the top of `elem` at the + // desired position. + var elemTop = elem.getBoundingClientRect().top; + $window.scrollBy(0, elemTop - offset); + } + } else { + $window.scrollTo(0, 0); + } + } + + function scroll() { + var hash = $location.hash(), elm; + + // empty hash, scroll to the top of the page + if (!hash) scrollTo(null); + + // element with given id + else if ((elm = document.getElementById(hash))) scrollTo(elm); + + // first anchor with given name :-D + else if ((elm = getFirstAnchor(document.getElementsByName(hash)))) scrollTo(elm); + + // no element and hash == 'top', scroll to the top of the page + else if (hash === 'top') scrollTo(null); + } + + // does not scroll when user clicks on anchor link that is currently on + // (no url change, no $location.hash() change), browser native does scroll + if (autoScrollingEnabled) { + $rootScope.$watch(function autoScrollWatch() {return $location.hash();}, + function autoScrollWatchAction(newVal, oldVal) { + // skip the initial scroll if $location.hash is empty + if (newVal === oldVal && newVal === '') return; + + jqLiteDocumentLoaded(function() { + $rootScope.$evalAsync(scroll); + }); + }); + } + + return scroll; + }]; +} + +var $animateMinErr = minErr('$animate'); + +/** + * @ngdoc provider + * @name $animateProvider + * + * @description + * Default implementation of $animate that doesn't perform any animations, instead just + * synchronously performs DOM + * updates and calls done() callbacks. + * + * In order to enable animations the ngAnimate module has to be loaded. + * + * To see the functional implementation check out src/ngAnimate/animate.js + */ +var $AnimateProvider = ['$provide', function($provide) { + + + this.$$selectors = {}; + + + /** + * @ngdoc method + * @name $animateProvider#register + * + * @description + * Registers a new injectable animation factory function. The factory function produces the + * animation object which contains callback functions for each event that is expected to be + * animated. + * + * * `eventFn`: `function(Element, doneFunction)` The element to animate, the `doneFunction` + * must be called once the element animation is complete. If a function is returned then the + * animation service will use this function to cancel the animation whenever a cancel event is + * triggered. + * + * + * ```js + * return { + * eventFn : function(element, done) { + * //code to run the animation + * //once complete, then run done() + * return function cancellationFunction() { + * //code to cancel the animation + * } + * } + * } + * ``` + * + * @param {string} name The name of the animation. + * @param {Function} factory The factory function that will be executed to return the animation + * object. + */ + this.register = function(name, factory) { + var key = name + '-animation'; + if (name && name.charAt(0) != '.') throw $animateMinErr('notcsel', + "Expecting class selector starting with '.' got '{0}'.", name); + this.$$selectors[name.substr(1)] = key; + $provide.factory(key, factory); + }; + + /** + * @ngdoc method + * @name $animateProvider#classNameFilter + * + * @description + * Sets and/or returns the CSS class regular expression that is checked when performing + * an animation. Upon bootstrap the classNameFilter value is not set at all and will + * therefore enable $animate to attempt to perform an animation on any element. + * When setting the classNameFilter value, animations will only be performed on elements + * that successfully match the filter expression. This in turn can boost performance + * for low-powered devices as well as applications containing a lot of structural operations. + * @param {RegExp=} expression The className expression which will be checked against all animations + * @return {RegExp} The current CSS className expression value. If null then there is no expression value + */ + this.classNameFilter = function(expression) { + if (arguments.length === 1) { + this.$$classNameFilter = (expression instanceof RegExp) ? expression : null; + } + return this.$$classNameFilter; + }; + + this.$get = ['$$q', '$$asyncCallback', '$rootScope', function($$q, $$asyncCallback, $rootScope) { + + var currentDefer; + + function runAnimationPostDigest(fn) { + var cancelFn, defer = $$q.defer(); + defer.promise.$$cancelFn = function ngAnimateMaybeCancel() { + cancelFn && cancelFn(); + }; + + $rootScope.$$postDigest(function ngAnimatePostDigest() { + cancelFn = fn(function ngAnimateNotifyComplete() { + defer.resolve(); + }); + }); + + return defer.promise; + } + + function resolveElementClasses(element, classes) { + var toAdd = [], toRemove = []; + + var hasClasses = createMap(); + forEach((element.attr('class') || '').split(/\s+/), function(className) { + hasClasses[className] = true; + }); + + forEach(classes, function(status, className) { + var hasClass = hasClasses[className]; + + // If the most recent class manipulation (via $animate) was to remove the class, and the + // element currently has the class, the class is scheduled for removal. Otherwise, if + // the most recent class manipulation (via $animate) was to add the class, and the + // element does not currently have the class, the class is scheduled to be added. + if (status === false && hasClass) { + toRemove.push(className); + } else if (status === true && !hasClass) { + toAdd.push(className); + } + }); + + return (toAdd.length + toRemove.length) > 0 && + [toAdd.length ? toAdd : null, toRemove.length ? toRemove : null]; + } + + function cachedClassManipulation(cache, classes, op) { + for (var i=0, ii = classes.length; i < ii; ++i) { + var className = classes[i]; + cache[className] = op; + } + } + + function asyncPromise() { + // only serve one instance of a promise in order to save CPU cycles + if (!currentDefer) { + currentDefer = $$q.defer(); + $$asyncCallback(function() { + currentDefer.resolve(); + currentDefer = null; + }); + } + return currentDefer.promise; + } + + function applyStyles(element, options) { + if (angular.isObject(options)) { + var styles = extend(options.from || {}, options.to || {}); + element.css(styles); + } + } + + /** + * + * @ngdoc service + * @name $animate + * @description The $animate service provides rudimentary DOM manipulation functions to + * insert, remove and move elements within the DOM, as well as adding and removing classes. + * This service is the core service used by the ngAnimate $animator service which provides + * high-level animation hooks for CSS and JavaScript. + * + * $animate is available in the AngularJS core, however, the ngAnimate module must be included + * to enable full out animation support. Otherwise, $animate will only perform simple DOM + * manipulation operations. + * + * To learn more about enabling animation support, click here to visit the {@link ngAnimate + * ngAnimate module page} as well as the {@link ngAnimate.$animate ngAnimate $animate service + * page}. + */ + return { + animate: function(element, from, to) { + applyStyles(element, { from: from, to: to }); + return asyncPromise(); + }, + + /** + * + * @ngdoc method + * @name $animate#enter + * @kind function + * @description Inserts the element into the DOM either after the `after` element or + * as the first child within the `parent` element. When the function is called a promise + * is returned that will be resolved at a later time. + * @param {DOMElement} element the element which will be inserted into the DOM + * @param {DOMElement} parent the parent element which will append the element as + * a child (if the after element is not present) + * @param {DOMElement} after the sibling element which will append the element + * after itself + * @param {object=} options an optional collection of styles that will be applied to the element. + * @return {Promise} the animation callback promise + */ + enter: function(element, parent, after, options) { + applyStyles(element, options); + after ? after.after(element) + : parent.prepend(element); + return asyncPromise(); + }, + + /** + * + * @ngdoc method + * @name $animate#leave + * @kind function + * @description Removes the element from the DOM. When the function is called a promise + * is returned that will be resolved at a later time. + * @param {DOMElement} element the element which will be removed from the DOM + * @param {object=} options an optional collection of options that will be applied to the element. + * @return {Promise} the animation callback promise + */ + leave: function(element, options) { + element.remove(); + return asyncPromise(); + }, + + /** + * + * @ngdoc method + * @name $animate#move + * @kind function + * @description Moves the position of the provided element within the DOM to be placed + * either after the `after` element or inside of the `parent` element. When the function + * is called a promise is returned that will be resolved at a later time. + * + * @param {DOMElement} element the element which will be moved around within the + * DOM + * @param {DOMElement} parent the parent element where the element will be + * inserted into (if the after element is not present) + * @param {DOMElement} after the sibling element where the element will be + * positioned next to + * @param {object=} options an optional collection of options that will be applied to the element. + * @return {Promise} the animation callback promise + */ + move: function(element, parent, after, options) { + // Do not remove element before insert. Removing will cause data associated with the + // element to be dropped. Insert will implicitly do the remove. + return this.enter(element, parent, after, options); + }, + + /** + * + * @ngdoc method + * @name $animate#addClass + * @kind function + * @description Adds the provided className CSS class value to the provided element. + * When the function is called a promise is returned that will be resolved at a later time. + * @param {DOMElement} element the element which will have the className value + * added to it + * @param {string} className the CSS class which will be added to the element + * @param {object=} options an optional collection of options that will be applied to the element. + * @return {Promise} the animation callback promise + */ + addClass: function(element, className, options) { + return this.setClass(element, className, [], options); + }, + + $$addClassImmediately: function(element, className, options) { + element = jqLite(element); + className = !isString(className) + ? (isArray(className) ? className.join(' ') : '') + : className; + forEach(element, function(element) { + jqLiteAddClass(element, className); + }); + applyStyles(element, options); + return asyncPromise(); + }, + + /** + * + * @ngdoc method + * @name $animate#removeClass + * @kind function + * @description Removes the provided className CSS class value from the provided element. + * When the function is called a promise is returned that will be resolved at a later time. + * @param {DOMElement} element the element which will have the className value + * removed from it + * @param {string} className the CSS class which will be removed from the element + * @param {object=} options an optional collection of options that will be applied to the element. + * @return {Promise} the animation callback promise + */ + removeClass: function(element, className, options) { + return this.setClass(element, [], className, options); + }, + + $$removeClassImmediately: function(element, className, options) { + element = jqLite(element); + className = !isString(className) + ? (isArray(className) ? className.join(' ') : '') + : className; + forEach(element, function(element) { + jqLiteRemoveClass(element, className); + }); + applyStyles(element, options); + return asyncPromise(); + }, + + /** + * + * @ngdoc method + * @name $animate#setClass + * @kind function + * @description Adds and/or removes the given CSS classes to and from the element. + * When the function is called a promise is returned that will be resolved at a later time. + * @param {DOMElement} element the element which will have its CSS classes changed + * removed from it + * @param {string} add the CSS classes which will be added to the element + * @param {string} remove the CSS class which will be removed from the element + * @param {object=} options an optional collection of options that will be applied to the element. + * @return {Promise} the animation callback promise + */ + setClass: function(element, add, remove, options) { + var self = this; + var STORAGE_KEY = '$$animateClasses'; + var createdCache = false; + element = jqLite(element); + + var cache = element.data(STORAGE_KEY); + if (!cache) { + cache = { + classes: {}, + options: options + }; + createdCache = true; + } else if (options && cache.options) { + cache.options = angular.extend(cache.options || {}, options); + } + + var classes = cache.classes; + + add = isArray(add) ? add : add.split(' '); + remove = isArray(remove) ? remove : remove.split(' '); + cachedClassManipulation(classes, add, true); + cachedClassManipulation(classes, remove, false); + + if (createdCache) { + cache.promise = runAnimationPostDigest(function(done) { + var cache = element.data(STORAGE_KEY); + element.removeData(STORAGE_KEY); + + // in the event that the element is removed before postDigest + // is run then the cache will be undefined and there will be + // no need anymore to add or remove and of the element classes + if (cache) { + var classes = resolveElementClasses(element, cache.classes); + if (classes) { + self.$$setClassImmediately(element, classes[0], classes[1], cache.options); + } + } + + done(); + }); + element.data(STORAGE_KEY, cache); + } + + return cache.promise; + }, + + $$setClassImmediately: function(element, add, remove, options) { + add && this.$$addClassImmediately(element, add); + remove && this.$$removeClassImmediately(element, remove); + applyStyles(element, options); + return asyncPromise(); + }, + + enabled: noop, + cancel: noop + }; + }]; +}]; + +function $$AsyncCallbackProvider() { + this.$get = ['$$rAF', '$timeout', function($$rAF, $timeout) { + return $$rAF.supported + ? function(fn) { return $$rAF(fn); } + : function(fn) { + return $timeout(fn, 0, false); + }; + }]; +} + +/* global stripHash: true */ + +/** + * ! This is a private undocumented service ! + * + * @name $browser + * @requires $log + * @description + * This object has two goals: + * + * - hide all the global state in the browser caused by the window object + * - abstract away all the browser specific features and inconsistencies + * + * For tests we provide {@link ngMock.$browser mock implementation} of the `$browser` + * service, which can be used for convenient testing of the application without the interaction with + * the real browser apis. + */ +/** + * @param {object} window The global window object. + * @param {object} document jQuery wrapped document. + * @param {object} $log window.console or an object with the same interface. + * @param {object} $sniffer $sniffer service + */ +function Browser(window, document, $log, $sniffer) { + var self = this, + rawDocument = document[0], + location = window.location, + history = window.history, + setTimeout = window.setTimeout, + clearTimeout = window.clearTimeout, + pendingDeferIds = {}; + + self.isMock = false; + + var outstandingRequestCount = 0; + var outstandingRequestCallbacks = []; + + // TODO(vojta): remove this temporary api + self.$$completeOutstandingRequest = completeOutstandingRequest; + self.$$incOutstandingRequestCount = function() { outstandingRequestCount++; }; + + /** + * Executes the `fn` function(supports currying) and decrements the `outstandingRequestCallbacks` + * counter. If the counter reaches 0, all the `outstandingRequestCallbacks` are executed. + */ + function completeOutstandingRequest(fn) { + try { + fn.apply(null, sliceArgs(arguments, 1)); + } finally { + outstandingRequestCount--; + if (outstandingRequestCount === 0) { + while (outstandingRequestCallbacks.length) { + try { + outstandingRequestCallbacks.pop()(); + } catch (e) { + $log.error(e); + } + } + } + } + } + + function getHash(url) { + var index = url.indexOf('#'); + return index === -1 ? '' : url.substr(index + 1); + } + + /** + * @private + * Note: this method is used only by scenario runner + * TODO(vojta): prefix this method with $$ ? + * @param {function()} callback Function that will be called when no outstanding request + */ + self.notifyWhenNoOutstandingRequests = function(callback) { + // force browser to execute all pollFns - this is needed so that cookies and other pollers fire + // at some deterministic time in respect to the test runner's actions. Leaving things up to the + // regular poller would result in flaky tests. + forEach(pollFns, function(pollFn) { pollFn(); }); + + if (outstandingRequestCount === 0) { + callback(); + } else { + outstandingRequestCallbacks.push(callback); + } + }; + + ////////////////////////////////////////////////////////////// + // Poll Watcher API + ////////////////////////////////////////////////////////////// + var pollFns = [], + pollTimeout; + + /** + * @name $browser#addPollFn + * + * @param {function()} fn Poll function to add + * + * @description + * Adds a function to the list of functions that poller periodically executes, + * and starts polling if not started yet. + * + * @returns {function()} the added function + */ + self.addPollFn = function(fn) { + if (isUndefined(pollTimeout)) startPoller(100, setTimeout); + pollFns.push(fn); + return fn; + }; + + /** + * @param {number} interval How often should browser call poll functions (ms) + * @param {function()} setTimeout Reference to a real or fake `setTimeout` function. + * + * @description + * Configures the poller to run in the specified intervals, using the specified + * setTimeout fn and kicks it off. + */ + function startPoller(interval, setTimeout) { + (function check() { + forEach(pollFns, function(pollFn) { pollFn(); }); + pollTimeout = setTimeout(check, interval); + })(); + } + + ////////////////////////////////////////////////////////////// + // URL API + ////////////////////////////////////////////////////////////// + + var cachedState, lastHistoryState, + lastBrowserUrl = location.href, + baseElement = document.find('base'), + reloadLocation = null; + + cacheState(); + lastHistoryState = cachedState; + + /** + * @name $browser#url + * + * @description + * GETTER: + * Without any argument, this method just returns current value of location.href. + * + * SETTER: + * With at least one argument, this method sets url to new value. + * If html5 history api supported, pushState/replaceState is used, otherwise + * location.href/location.replace is used. + * Returns its own instance to allow chaining + * + * NOTE: this api is intended for use only by the $location service. Please use the + * {@link ng.$location $location service} to change url. + * + * @param {string} url New url (when used as setter) + * @param {boolean=} replace Should new url replace current history record? + * @param {object=} state object to use with pushState/replaceState + */ + self.url = function(url, replace, state) { + // In modern browsers `history.state` is `null` by default; treating it separately + // from `undefined` would cause `$browser.url('/foo')` to change `history.state` + // to undefined via `pushState`. Instead, let's change `undefined` to `null` here. + if (isUndefined(state)) { + state = null; + } + + // Android Browser BFCache causes location, history reference to become stale. + if (location !== window.location) location = window.location; + if (history !== window.history) history = window.history; + + // setter + if (url) { + var sameState = lastHistoryState === state; + + // Don't change anything if previous and current URLs and states match. This also prevents + // IE<10 from getting into redirect loop when in LocationHashbangInHtml5Url mode. + // See https://github.com/angular/angular.js/commit/ffb2701 + if (lastBrowserUrl === url && (!$sniffer.history || sameState)) { + return self; + } + var sameBase = lastBrowserUrl && stripHash(lastBrowserUrl) === stripHash(url); + lastBrowserUrl = url; + lastHistoryState = state; + // Don't use history API if only the hash changed + // due to a bug in IE10/IE11 which leads + // to not firing a `hashchange` nor `popstate` event + // in some cases (see #9143). + if ($sniffer.history && (!sameBase || !sameState)) { + history[replace ? 'replaceState' : 'pushState'](state, '', url); + cacheState(); + // Do the assignment again so that those two variables are referentially identical. + lastHistoryState = cachedState; + } else { + if (!sameBase) { + reloadLocation = url; + } + if (replace) { + location.replace(url); + } else if (!sameBase) { + location.href = url; + } else { + location.hash = getHash(url); + } + } + return self; + // getter + } else { + // - reloadLocation is needed as browsers don't allow to read out + // the new location.href if a reload happened. + // - the replacement is a workaround for https://bugzilla.mozilla.org/show_bug.cgi?id=407172 + return reloadLocation || location.href.replace(/%27/g,"'"); + } + }; + + /** + * @name $browser#state + * + * @description + * This method is a getter. + * + * Return history.state or null if history.state is undefined. + * + * @returns {object} state + */ + self.state = function() { + return cachedState; + }; + + var urlChangeListeners = [], + urlChangeInit = false; + + function cacheStateAndFireUrlChange() { + cacheState(); + fireUrlChange(); + } + + // This variable should be used *only* inside the cacheState function. + var lastCachedState = null; + function cacheState() { + // This should be the only place in $browser where `history.state` is read. + cachedState = window.history.state; + cachedState = isUndefined(cachedState) ? null : cachedState; + + // Prevent callbacks fo fire twice if both hashchange & popstate were fired. + if (equals(cachedState, lastCachedState)) { + cachedState = lastCachedState; + } + lastCachedState = cachedState; + } + + function fireUrlChange() { + if (lastBrowserUrl === self.url() && lastHistoryState === cachedState) { + return; + } + + lastBrowserUrl = self.url(); + lastHistoryState = cachedState; + forEach(urlChangeListeners, function(listener) { + listener(self.url(), cachedState); + }); + } + + /** + * @name $browser#onUrlChange + * + * @description + * Register callback function that will be called, when url changes. + * + * It's only called when the url is changed from outside of angular: + * - user types different url into address bar + * - user clicks on history (forward/back) button + * - user clicks on a link + * + * It's not called when url is changed by $browser.url() method + * + * The listener gets called with new url as parameter. + * + * NOTE: this api is intended for use only by the $location service. Please use the + * {@link ng.$location $location service} to monitor url changes in angular apps. + * + * @param {function(string)} listener Listener function to be called when url changes. + * @return {function(string)} Returns the registered listener fn - handy if the fn is anonymous. + */ + self.onUrlChange = function(callback) { + // TODO(vojta): refactor to use node's syntax for events + if (!urlChangeInit) { + // We listen on both (hashchange/popstate) when available, as some browsers (e.g. Opera) + // don't fire popstate when user change the address bar and don't fire hashchange when url + // changed by push/replaceState + + // html5 history api - popstate event + if ($sniffer.history) jqLite(window).on('popstate', cacheStateAndFireUrlChange); + // hashchange event + jqLite(window).on('hashchange', cacheStateAndFireUrlChange); + + urlChangeInit = true; + } + + urlChangeListeners.push(callback); + return callback; + }; + + /** + * Checks whether the url has changed outside of Angular. + * Needs to be exported to be able to check for changes that have been done in sync, + * as hashchange/popstate events fire in async. + */ + self.$$checkUrlChange = fireUrlChange; + + ////////////////////////////////////////////////////////////// + // Misc API + ////////////////////////////////////////////////////////////// + + /** + * @name $browser#baseHref + * + * @description + * Returns current + * (always relative - without domain) + * + * @returns {string} The current base href + */ + self.baseHref = function() { + var href = baseElement.attr('href'); + return href ? href.replace(/^(https?\:)?\/\/[^\/]*/, '') : ''; + }; + + ////////////////////////////////////////////////////////////// + // Cookies API + ////////////////////////////////////////////////////////////// + var lastCookies = {}; + var lastCookieString = ''; + var cookiePath = self.baseHref(); + + function safeDecodeURIComponent(str) { + try { + return decodeURIComponent(str); + } catch (e) { + return str; + } + } + + /** + * @name $browser#cookies + * + * @param {string=} name Cookie name + * @param {string=} value Cookie value + * + * @description + * The cookies method provides a 'private' low level access to browser cookies. + * It is not meant to be used directly, use the $cookie service instead. + * + * The return values vary depending on the arguments that the method was called with as follows: + * + * - cookies() -> hash of all cookies, this is NOT a copy of the internal state, so do not modify + * it + * - cookies(name, value) -> set name to value, if value is undefined delete the cookie + * - cookies(name) -> the same as (name, undefined) == DELETES (no one calls it right now that + * way) + * + * @returns {Object} Hash of all cookies (if called without any parameter) + */ + self.cookies = function(name, value) { + var cookieLength, cookieArray, cookie, i, index; + + if (name) { + if (value === undefined) { + rawDocument.cookie = encodeURIComponent(name) + "=;path=" + cookiePath + + ";expires=Thu, 01 Jan 1970 00:00:00 GMT"; + } else { + if (isString(value)) { + cookieLength = (rawDocument.cookie = encodeURIComponent(name) + '=' + encodeURIComponent(value) + + ';path=' + cookiePath).length + 1; + + // per http://www.ietf.org/rfc/rfc2109.txt browser must allow at minimum: + // - 300 cookies + // - 20 cookies per unique domain + // - 4096 bytes per cookie + if (cookieLength > 4096) { + $log.warn("Cookie '" + name + + "' possibly not set or overflowed because it was too large (" + + cookieLength + " > 4096 bytes)!"); + } + } + } + } else { + if (rawDocument.cookie !== lastCookieString) { + lastCookieString = rawDocument.cookie; + cookieArray = lastCookieString.split("; "); + lastCookies = {}; + + for (i = 0; i < cookieArray.length; i++) { + cookie = cookieArray[i]; + index = cookie.indexOf('='); + if (index > 0) { //ignore nameless cookies + name = safeDecodeURIComponent(cookie.substring(0, index)); + // the first value that is seen for a cookie is the most + // specific one. values for the same cookie name that + // follow are for less specific paths. + if (lastCookies[name] === undefined) { + lastCookies[name] = safeDecodeURIComponent(cookie.substring(index + 1)); + } + } + } + } + return lastCookies; + } + }; + + + /** + * @name $browser#defer + * @param {function()} fn A function, who's execution should be deferred. + * @param {number=} [delay=0] of milliseconds to defer the function execution. + * @returns {*} DeferId that can be used to cancel the task via `$browser.defer.cancel()`. + * + * @description + * Executes a fn asynchronously via `setTimeout(fn, delay)`. + * + * Unlike when calling `setTimeout` directly, in test this function is mocked and instead of using + * `setTimeout` in tests, the fns are queued in an array, which can be programmatically flushed + * via `$browser.defer.flush()`. + * + */ + self.defer = function(fn, delay) { + var timeoutId; + outstandingRequestCount++; + timeoutId = setTimeout(function() { + delete pendingDeferIds[timeoutId]; + completeOutstandingRequest(fn); + }, delay || 0); + pendingDeferIds[timeoutId] = true; + return timeoutId; + }; + + + /** + * @name $browser#defer.cancel + * + * @description + * Cancels a deferred task identified with `deferId`. + * + * @param {*} deferId Token returned by the `$browser.defer` function. + * @returns {boolean} Returns `true` if the task hasn't executed yet and was successfully + * canceled. + */ + self.defer.cancel = function(deferId) { + if (pendingDeferIds[deferId]) { + delete pendingDeferIds[deferId]; + clearTimeout(deferId); + completeOutstandingRequest(noop); + return true; + } + return false; + }; + +} + +function $BrowserProvider() { + this.$get = ['$window', '$log', '$sniffer', '$document', + function($window, $log, $sniffer, $document) { + return new Browser($window, $document, $log, $sniffer); + }]; +} + +/** + * @ngdoc service + * @name $cacheFactory + * + * @description + * Factory that constructs {@link $cacheFactory.Cache Cache} objects and gives access to + * them. + * + * ```js + * + * var cache = $cacheFactory('cacheId'); + * expect($cacheFactory.get('cacheId')).toBe(cache); + * expect($cacheFactory.get('noSuchCacheId')).not.toBeDefined(); + * + * cache.put("key", "value"); + * cache.put("another key", "another value"); + * + * // We've specified no options on creation + * expect(cache.info()).toEqual({id: 'cacheId', size: 2}); + * + * ``` + * + * + * @param {string} cacheId Name or id of the newly created cache. + * @param {object=} options Options object that specifies the cache behavior. Properties: + * + * - `{number=}` `capacity` — turns the cache into LRU cache. + * + * @returns {object} Newly created cache object with the following set of methods: + * + * - `{object}` `info()` — Returns id, size, and options of cache. + * - `{{*}}` `put({string} key, {*} value)` — Puts a new key-value pair into the cache and returns + * it. + * - `{{*}}` `get({string} key)` — Returns cached value for `key` or undefined for cache miss. + * - `{void}` `remove({string} key)` — Removes a key-value pair from the cache. + * - `{void}` `removeAll()` — Removes all cached values. + * - `{void}` `destroy()` — Removes references to this cache from $cacheFactory. + * + * @example + + +
      + + + + +

      Cached Values

      +
      + + : + +
      + +

      Cache Info

      +
      + + : + +
      +
      +
      + + angular.module('cacheExampleApp', []). + controller('CacheController', ['$scope', '$cacheFactory', function($scope, $cacheFactory) { + $scope.keys = []; + $scope.cache = $cacheFactory('cacheId'); + $scope.put = function(key, value) { + if ($scope.cache.get(key) === undefined) { + $scope.keys.push(key); + } + $scope.cache.put(key, value === undefined ? null : value); + }; + }]); + + + p { + margin: 10px 0 3px; + } + +
      + */ +function $CacheFactoryProvider() { + + this.$get = function() { + var caches = {}; + + function cacheFactory(cacheId, options) { + if (cacheId in caches) { + throw minErr('$cacheFactory')('iid', "CacheId '{0}' is already taken!", cacheId); + } + + var size = 0, + stats = extend({}, options, {id: cacheId}), + data = {}, + capacity = (options && options.capacity) || Number.MAX_VALUE, + lruHash = {}, + freshEnd = null, + staleEnd = null; + + /** + * @ngdoc type + * @name $cacheFactory.Cache + * + * @description + * A cache object used to store and retrieve data, primarily used by + * {@link $http $http} and the {@link ng.directive:script script} directive to cache + * templates and other data. + * + * ```js + * angular.module('superCache') + * .factory('superCache', ['$cacheFactory', function($cacheFactory) { + * return $cacheFactory('super-cache'); + * }]); + * ``` + * + * Example test: + * + * ```js + * it('should behave like a cache', inject(function(superCache) { + * superCache.put('key', 'value'); + * superCache.put('another key', 'another value'); + * + * expect(superCache.info()).toEqual({ + * id: 'super-cache', + * size: 2 + * }); + * + * superCache.remove('another key'); + * expect(superCache.get('another key')).toBeUndefined(); + * + * superCache.removeAll(); + * expect(superCache.info()).toEqual({ + * id: 'super-cache', + * size: 0 + * }); + * })); + * ``` + */ + return caches[cacheId] = { + + /** + * @ngdoc method + * @name $cacheFactory.Cache#put + * @kind function + * + * @description + * Inserts a named entry into the {@link $cacheFactory.Cache Cache} object to be + * retrieved later, and incrementing the size of the cache if the key was not already + * present in the cache. If behaving like an LRU cache, it will also remove stale + * entries from the set. + * + * It will not insert undefined values into the cache. + * + * @param {string} key the key under which the cached data is stored. + * @param {*} value the value to store alongside the key. If it is undefined, the key + * will not be stored. + * @returns {*} the value stored. + */ + put: function(key, value) { + if (capacity < Number.MAX_VALUE) { + var lruEntry = lruHash[key] || (lruHash[key] = {key: key}); + + refresh(lruEntry); + } + + if (isUndefined(value)) return; + if (!(key in data)) size++; + data[key] = value; + + if (size > capacity) { + this.remove(staleEnd.key); + } + + return value; + }, + + /** + * @ngdoc method + * @name $cacheFactory.Cache#get + * @kind function + * + * @description + * Retrieves named data stored in the {@link $cacheFactory.Cache Cache} object. + * + * @param {string} key the key of the data to be retrieved + * @returns {*} the value stored. + */ + get: function(key) { + if (capacity < Number.MAX_VALUE) { + var lruEntry = lruHash[key]; + + if (!lruEntry) return; + + refresh(lruEntry); + } + + return data[key]; + }, + + + /** + * @ngdoc method + * @name $cacheFactory.Cache#remove + * @kind function + * + * @description + * Removes an entry from the {@link $cacheFactory.Cache Cache} object. + * + * @param {string} key the key of the entry to be removed + */ + remove: function(key) { + if (capacity < Number.MAX_VALUE) { + var lruEntry = lruHash[key]; + + if (!lruEntry) return; + + if (lruEntry == freshEnd) freshEnd = lruEntry.p; + if (lruEntry == staleEnd) staleEnd = lruEntry.n; + link(lruEntry.n,lruEntry.p); + + delete lruHash[key]; + } + + delete data[key]; + size--; + }, + + + /** + * @ngdoc method + * @name $cacheFactory.Cache#removeAll + * @kind function + * + * @description + * Clears the cache object of any entries. + */ + removeAll: function() { + data = {}; + size = 0; + lruHash = {}; + freshEnd = staleEnd = null; + }, + + + /** + * @ngdoc method + * @name $cacheFactory.Cache#destroy + * @kind function + * + * @description + * Destroys the {@link $cacheFactory.Cache Cache} object entirely, + * removing it from the {@link $cacheFactory $cacheFactory} set. + */ + destroy: function() { + data = null; + stats = null; + lruHash = null; + delete caches[cacheId]; + }, + + + /** + * @ngdoc method + * @name $cacheFactory.Cache#info + * @kind function + * + * @description + * Retrieve information regarding a particular {@link $cacheFactory.Cache Cache}. + * + * @returns {object} an object with the following properties: + *
        + *
      • **id**: the id of the cache instance
      • + *
      • **size**: the number of entries kept in the cache instance
      • + *
      • **...**: any additional properties from the options object when creating the + * cache.
      • + *
      + */ + info: function() { + return extend({}, stats, {size: size}); + } + }; + + + /** + * makes the `entry` the freshEnd of the LRU linked list + */ + function refresh(entry) { + if (entry != freshEnd) { + if (!staleEnd) { + staleEnd = entry; + } else if (staleEnd == entry) { + staleEnd = entry.n; + } + + link(entry.n, entry.p); + link(entry, freshEnd); + freshEnd = entry; + freshEnd.n = null; + } + } + + + /** + * bidirectionally links two entries of the LRU linked list + */ + function link(nextEntry, prevEntry) { + if (nextEntry != prevEntry) { + if (nextEntry) nextEntry.p = prevEntry; //p stands for previous, 'prev' didn't minify + if (prevEntry) prevEntry.n = nextEntry; //n stands for next, 'next' didn't minify + } + } + } + + + /** + * @ngdoc method + * @name $cacheFactory#info + * + * @description + * Get information about all the caches that have been created + * + * @returns {Object} - key-value map of `cacheId` to the result of calling `cache#info` + */ + cacheFactory.info = function() { + var info = {}; + forEach(caches, function(cache, cacheId) { + info[cacheId] = cache.info(); + }); + return info; + }; + + + /** + * @ngdoc method + * @name $cacheFactory#get + * + * @description + * Get access to a cache object by the `cacheId` used when it was created. + * + * @param {string} cacheId Name or id of a cache to access. + * @returns {object} Cache object identified by the cacheId or undefined if no such cache. + */ + cacheFactory.get = function(cacheId) { + return caches[cacheId]; + }; + + + return cacheFactory; + }; +} + +/** + * @ngdoc service + * @name $templateCache + * + * @description + * The first time a template is used, it is loaded in the template cache for quick retrieval. You + * can load templates directly into the cache in a `script` tag, or by consuming the + * `$templateCache` service directly. + * + * Adding via the `script` tag: + * + * ```html + * + * ``` + * + * **Note:** the `script` tag containing the template does not need to be included in the `head` of + * the document, but it must be a descendent of the {@link ng.$rootElement $rootElement} (IE, + * element with ng-app attribute), otherwise the template will be ignored. + * + * Adding via the $templateCache service: + * + * ```js + * var myApp = angular.module('myApp', []); + * myApp.run(function($templateCache) { + * $templateCache.put('templateId.html', 'This is the content of the template'); + * }); + * ``` + * + * To retrieve the template later, simply use it in your HTML: + * ```html + *
      + * ``` + * + * or get it via Javascript: + * ```js + * $templateCache.get('templateId.html') + * ``` + * + * See {@link ng.$cacheFactory $cacheFactory}. + * + */ +function $TemplateCacheProvider() { + this.$get = ['$cacheFactory', function($cacheFactory) { + return $cacheFactory('templates'); + }]; +} + +/* ! VARIABLE/FUNCTION NAMING CONVENTIONS THAT APPLY TO THIS FILE! + * + * DOM-related variables: + * + * - "node" - DOM Node + * - "element" - DOM Element or Node + * - "$node" or "$element" - jqLite-wrapped node or element + * + * + * Compiler related stuff: + * + * - "linkFn" - linking fn of a single directive + * - "nodeLinkFn" - function that aggregates all linking fns for a particular node + * - "childLinkFn" - function that aggregates all linking fns for child nodes of a particular node + * - "compositeLinkFn" - function that aggregates all linking fns for a compilation root (nodeList) + */ + + +/** + * @ngdoc service + * @name $compile + * @kind function + * + * @description + * Compiles an HTML string or DOM into a template and produces a template function, which + * can then be used to link {@link ng.$rootScope.Scope `scope`} and the template together. + * + * The compilation is a process of walking the DOM tree and matching DOM elements to + * {@link ng.$compileProvider#directive directives}. + * + *
      + * **Note:** This document is an in-depth reference of all directive options. + * For a gentle introduction to directives with examples of common use cases, + * see the {@link guide/directive directive guide}. + *
      + * + * ## Comprehensive Directive API + * + * There are many different options for a directive. + * + * The difference resides in the return value of the factory function. + * You can either return a "Directive Definition Object" (see below) that defines the directive properties, + * or just the `postLink` function (all other properties will have the default values). + * + *
      + * **Best Practice:** It's recommended to use the "directive definition object" form. + *
      + * + * Here's an example directive declared with a Directive Definition Object: + * + * ```js + * var myModule = angular.module(...); + * + * myModule.directive('directiveName', function factory(injectables) { + * var directiveDefinitionObject = { + * priority: 0, + * template: '
      ', // or // function(tElement, tAttrs) { ... }, + * // or + * // templateUrl: 'directive.html', // or // function(tElement, tAttrs) { ... }, + * transclude: false, + * restrict: 'A', + * templateNamespace: 'html', + * scope: false, + * controller: function($scope, $element, $attrs, $transclude, otherInjectables) { ... }, + * controllerAs: 'stringAlias', + * require: 'siblingDirectiveName', // or // ['^parentDirectiveName', '?optionalDirectiveName', '?^optionalParent'], + * compile: function compile(tElement, tAttrs, transclude) { + * return { + * pre: function preLink(scope, iElement, iAttrs, controller) { ... }, + * post: function postLink(scope, iElement, iAttrs, controller) { ... } + * } + * // or + * // return function postLink( ... ) { ... } + * }, + * // or + * // link: { + * // pre: function preLink(scope, iElement, iAttrs, controller) { ... }, + * // post: function postLink(scope, iElement, iAttrs, controller) { ... } + * // } + * // or + * // link: function postLink( ... ) { ... } + * }; + * return directiveDefinitionObject; + * }); + * ``` + * + *
      + * **Note:** Any unspecified options will use the default value. You can see the default values below. + *
      + * + * Therefore the above can be simplified as: + * + * ```js + * var myModule = angular.module(...); + * + * myModule.directive('directiveName', function factory(injectables) { + * var directiveDefinitionObject = { + * link: function postLink(scope, iElement, iAttrs) { ... } + * }; + * return directiveDefinitionObject; + * // or + * // return function postLink(scope, iElement, iAttrs) { ... } + * }); + * ``` + * + * + * + * ### Directive Definition Object + * + * The directive definition object provides instructions to the {@link ng.$compile + * compiler}. The attributes are: + * + * #### `multiElement` + * When this property is set to true, the HTML compiler will collect DOM nodes between + * nodes with the attributes `directive-name-start` and `directive-name-end`, and group them + * together as the directive elements. It is recommended that this feature be used on directives + * which are not strictly behavioural (such as {@link ngClick}), and which + * do not manipulate or replace child nodes (such as {@link ngInclude}). + * + * #### `priority` + * When there are multiple directives defined on a single DOM element, sometimes it + * is necessary to specify the order in which the directives are applied. The `priority` is used + * to sort the directives before their `compile` functions get called. Priority is defined as a + * number. Directives with greater numerical `priority` are compiled first. Pre-link functions + * are also run in priority order, but post-link functions are run in reverse order. The order + * of directives with the same priority is undefined. The default priority is `0`. + * + * #### `terminal` + * If set to true then the current `priority` will be the last set of directives + * which will execute (any directives at the current priority will still execute + * as the order of execution on same `priority` is undefined). Note that expressions + * and other directives used in the directive's template will also be excluded from execution. + * + * #### `scope` + * **If set to `true`,** then a new scope will be created for this directive. If multiple directives on the + * same element request a new scope, only one new scope is created. The new scope rule does not + * apply for the root of the template since the root of the template always gets a new scope. + * + * **If set to `{}` (object hash),** then a new "isolate" scope is created. The 'isolate' scope differs from + * normal scope in that it does not prototypically inherit from the parent scope. This is useful + * when creating reusable components, which should not accidentally read or modify data in the + * parent scope. + * + * The 'isolate' scope takes an object hash which defines a set of local scope properties + * derived from the parent scope. These local properties are useful for aliasing values for + * templates. Locals definition is a hash of local scope property to its source: + * + * * `@` or `@attr` - bind a local scope property to the value of DOM attribute. The result is + * always a string since DOM attributes are strings. If no `attr` name is specified then the + * attribute name is assumed to be the same as the local name. + * Given `` and widget definition + * of `scope: { localName:'@myAttr' }`, then widget scope property `localName` will reflect + * the interpolated value of `hello {{name}}`. As the `name` attribute changes so will the + * `localName` property on the widget scope. The `name` is read from the parent scope (not + * component scope). + * + * * `=` or `=attr` - set up bi-directional binding between a local scope property and the + * parent scope property of name defined via the value of the `attr` attribute. If no `attr` + * name is specified then the attribute name is assumed to be the same as the local name. + * Given `` and widget definition of + * `scope: { localModel:'=myAttr' }`, then widget scope property `localModel` will reflect the + * value of `parentModel` on the parent scope. Any changes to `parentModel` will be reflected + * in `localModel` and any changes in `localModel` will reflect in `parentModel`. If the parent + * scope property doesn't exist, it will throw a NON_ASSIGNABLE_MODEL_EXPRESSION exception. You + * can avoid this behavior using `=?` or `=?attr` in order to flag the property as optional. If + * you want to shallow watch for changes (i.e. $watchCollection instead of $watch) you can use + * `=*` or `=*attr` (`=*?` or `=*?attr` if the property is optional). + * + * * `&` or `&attr` - provides a way to execute an expression in the context of the parent scope. + * If no `attr` name is specified then the attribute name is assumed to be the same as the + * local name. Given `` and widget definition of + * `scope: { localFn:'&myAttr' }`, then isolate scope property `localFn` will point to + * a function wrapper for the `count = count + value` expression. Often it's desirable to + * pass data from the isolated scope via an expression to the parent scope, this can be + * done by passing a map of local variable names and values into the expression wrapper fn. + * For example, if the expression is `increment(amount)` then we can specify the amount value + * by calling the `localFn` as `localFn({amount: 22})`. + * + * + * #### `bindToController` + * When an isolate scope is used for a component (see above), and `controllerAs` is used, `bindToController: true` will + * allow a component to have its properties bound to the controller, rather than to scope. When the controller + * is instantiated, the initial values of the isolate scope bindings are already available. + * + * #### `controller` + * Controller constructor function. The controller is instantiated before the + * pre-linking phase and it is shared with other directives (see + * `require` attribute). This allows the directives to communicate with each other and augment + * each other's behavior. The controller is injectable (and supports bracket notation) with the following locals: + * + * * `$scope` - Current scope associated with the element + * * `$element` - Current element + * * `$attrs` - Current attributes object for the element + * * `$transclude` - A transclude linking function pre-bound to the correct transclusion scope: + * `function([scope], cloneLinkingFn, futureParentElement)`. + * * `scope`: optional argument to override the scope. + * * `cloneLinkingFn`: optional argument to create clones of the original transcluded content. + * * `futureParentElement`: + * * defines the parent to which the `cloneLinkingFn` will add the cloned elements. + * * default: `$element.parent()` resp. `$element` for `transclude:'element'` resp. `transclude:true`. + * * only needed for transcludes that are allowed to contain non html elements (e.g. SVG elements) + * and when the `cloneLinkinFn` is passed, + * as those elements need to created and cloned in a special way when they are defined outside their + * usual containers (e.g. like ``). + * * See also the `directive.templateNamespace` property. + * + * + * #### `require` + * Require another directive and inject its controller as the fourth argument to the linking function. The + * `require` takes a string name (or array of strings) of the directive(s) to pass in. If an array is used, the + * injected argument will be an array in corresponding order. If no such directive can be + * found, or if the directive does not have a controller, then an error is raised. The name can be prefixed with: + * + * * (no prefix) - Locate the required controller on the current element. Throw an error if not found. + * * `?` - Attempt to locate the required controller or pass `null` to the `link` fn if not found. + * * `^` - Locate the required controller by searching the element and its parents. Throw an error if not found. + * * `^^` - Locate the required controller by searching the element's parents. Throw an error if not found. + * * `?^` - Attempt to locate the required controller by searching the element and its parents or pass + * `null` to the `link` fn if not found. + * * `?^^` - Attempt to locate the required controller by searching the element's parents, or pass + * `null` to the `link` fn if not found. + * + * + * #### `controllerAs` + * Controller alias at the directive scope. An alias for the controller so it + * can be referenced at the directive template. The directive needs to define a scope for this + * configuration to be used. Useful in the case when directive is used as component. + * + * + * #### `restrict` + * String of subset of `EACM` which restricts the directive to a specific directive + * declaration style. If omitted, the defaults (elements and attributes) are used. + * + * * `E` - Element name (default): `` + * * `A` - Attribute (default): `
      ` + * * `C` - Class: `
      ` + * * `M` - Comment: `` + * + * + * #### `templateNamespace` + * String representing the document type used by the markup in the template. + * AngularJS needs this information as those elements need to be created and cloned + * in a special way when they are defined outside their usual containers like `` and ``. + * + * * `html` - All root nodes in the template are HTML. Root nodes may also be + * top-level elements such as `` or ``. + * * `svg` - The root nodes in the template are SVG elements (excluding ``). + * * `math` - The root nodes in the template are MathML elements (excluding ``). + * + * If no `templateNamespace` is specified, then the namespace is considered to be `html`. + * + * #### `template` + * HTML markup that may: + * * Replace the contents of the directive's element (default). + * * Replace the directive's element itself (if `replace` is true - DEPRECATED). + * * Wrap the contents of the directive's element (if `transclude` is true). + * + * Value may be: + * + * * A string. For example `
      {{delete_str}}
      `. + * * A function which takes two arguments `tElement` and `tAttrs` (described in the `compile` + * function api below) and returns a string value. + * + * + * #### `templateUrl` + * This is similar to `template` but the template is loaded from the specified URL, asynchronously. + * + * Because template loading is asynchronous the compiler will suspend compilation of directives on that element + * for later when the template has been resolved. In the meantime it will continue to compile and link + * sibling and parent elements as though this element had not contained any directives. + * + * The compiler does not suspend the entire compilation to wait for templates to be loaded because this + * would result in the whole app "stalling" until all templates are loaded asynchronously - even in the + * case when only one deeply nested directive has `templateUrl`. + * + * Template loading is asynchronous even if the template has been preloaded into the {@link $templateCache} + * + * You can specify `templateUrl` as a string representing the URL or as a function which takes two + * arguments `tElement` and `tAttrs` (described in the `compile` function api below) and returns + * a string value representing the url. In either case, the template URL is passed through {@link + * $sce#getTrustedResourceUrl $sce.getTrustedResourceUrl}. + * + * + * #### `replace` ([*DEPRECATED*!], will be removed in next major release - i.e. v2.0) + * specify what the template should replace. Defaults to `false`. + * + * * `true` - the template will replace the directive's element. + * * `false` - the template will replace the contents of the directive's element. + * + * The replacement process migrates all of the attributes / classes from the old element to the new + * one. See the {@link guide/directive#template-expanding-directive + * Directives Guide} for an example. + * + * There are very few scenarios where element replacement is required for the application function, + * the main one being reusable custom components that are used within SVG contexts + * (because SVG doesn't work with custom elements in the DOM tree). + * + * #### `transclude` + * Extract the contents of the element where the directive appears and make it available to the directive. + * The contents are compiled and provided to the directive as a **transclusion function**. See the + * {@link $compile#transclusion Transclusion} section below. + * + * There are two kinds of transclusion depending upon whether you want to transclude just the contents of the + * directive's element or the entire element: + * + * * `true` - transclude the content (i.e. the child nodes) of the directive's element. + * * `'element'` - transclude the whole of the directive's element including any directives on this + * element that defined at a lower priority than this directive. When used, the `template` + * property is ignored. + * + * + * #### `compile` + * + * ```js + * function compile(tElement, tAttrs, transclude) { ... } + * ``` + * + * The compile function deals with transforming the template DOM. Since most directives do not do + * template transformation, it is not used often. The compile function takes the following arguments: + * + * * `tElement` - template element - The element where the directive has been declared. It is + * safe to do template transformation on the element and child elements only. + * + * * `tAttrs` - template attributes - Normalized list of attributes declared on this element shared + * between all directive compile functions. + * + * * `transclude` - [*DEPRECATED*!] A transclude linking function: `function(scope, cloneLinkingFn)` + * + *
      + * **Note:** The template instance and the link instance may be different objects if the template has + * been cloned. For this reason it is **not** safe to do anything other than DOM transformations that + * apply to all cloned DOM nodes within the compile function. Specifically, DOM listener registration + * should be done in a linking function rather than in a compile function. + *
      + + *
      + * **Note:** The compile function cannot handle directives that recursively use themselves in their + * own templates or compile functions. Compiling these directives results in an infinite loop and a + * stack overflow errors. + * + * This can be avoided by manually using $compile in the postLink function to imperatively compile + * a directive's template instead of relying on automatic template compilation via `template` or + * `templateUrl` declaration or manual compilation inside the compile function. + *
      + * + *
      + * **Note:** The `transclude` function that is passed to the compile function is deprecated, as it + * e.g. does not know about the right outer scope. Please use the transclude function that is passed + * to the link function instead. + *
      + + * A compile function can have a return value which can be either a function or an object. + * + * * returning a (post-link) function - is equivalent to registering the linking function via the + * `link` property of the config object when the compile function is empty. + * + * * returning an object with function(s) registered via `pre` and `post` properties - allows you to + * control when a linking function should be called during the linking phase. See info about + * pre-linking and post-linking functions below. + * + * + * #### `link` + * This property is used only if the `compile` property is not defined. + * + * ```js + * function link(scope, iElement, iAttrs, controller, transcludeFn) { ... } + * ``` + * + * The link function is responsible for registering DOM listeners as well as updating the DOM. It is + * executed after the template has been cloned. This is where most of the directive logic will be + * put. + * + * * `scope` - {@link ng.$rootScope.Scope Scope} - The scope to be used by the + * directive for registering {@link ng.$rootScope.Scope#$watch watches}. + * + * * `iElement` - instance element - The element where the directive is to be used. It is safe to + * manipulate the children of the element only in `postLink` function since the children have + * already been linked. + * + * * `iAttrs` - instance attributes - Normalized list of attributes declared on this element shared + * between all directive linking functions. + * + * * `controller` - a controller instance - A controller instance if at least one directive on the + * element defines a controller. The controller is shared among all the directives, which allows + * the directives to use the controllers as a communication channel. + * + * * `transcludeFn` - A transclude linking function pre-bound to the correct transclusion scope. + * This is the same as the `$transclude` + * parameter of directive controllers, see there for details. + * `function([scope], cloneLinkingFn, futureParentElement)`. + * + * #### Pre-linking function + * + * Executed before the child elements are linked. Not safe to do DOM transformation since the + * compiler linking function will fail to locate the correct elements for linking. + * + * #### Post-linking function + * + * Executed after the child elements are linked. + * + * Note that child elements that contain `templateUrl` directives will not have been compiled + * and linked since they are waiting for their template to load asynchronously and their own + * compilation and linking has been suspended until that occurs. + * + * It is safe to do DOM transformation in the post-linking function on elements that are not waiting + * for their async templates to be resolved. + * + * + * ### Transclusion + * + * Transclusion is the process of extracting a collection of DOM element from one part of the DOM and + * copying them to another part of the DOM, while maintaining their connection to the original AngularJS + * scope from where they were taken. + * + * Transclusion is used (often with {@link ngTransclude}) to insert the + * original contents of a directive's element into a specified place in the template of the directive. + * The benefit of transclusion, over simply moving the DOM elements manually, is that the transcluded + * content has access to the properties on the scope from which it was taken, even if the directive + * has isolated scope. + * See the {@link guide/directive#creating-a-directive-that-wraps-other-elements Directives Guide}. + * + * This makes it possible for the widget to have private state for its template, while the transcluded + * content has access to its originating scope. + * + *
      + * **Note:** When testing an element transclude directive you must not place the directive at the root of the + * DOM fragment that is being compiled. See {@link guide/unit-testing#testing-transclusion-directives + * Testing Transclusion Directives}. + *
      + * + * #### Transclusion Functions + * + * When a directive requests transclusion, the compiler extracts its contents and provides a **transclusion + * function** to the directive's `link` function and `controller`. This transclusion function is a special + * **linking function** that will return the compiled contents linked to a new transclusion scope. + * + *
      + * If you are just using {@link ngTransclude} then you don't need to worry about this function, since + * ngTransclude will deal with it for us. + *
      + * + * If you want to manually control the insertion and removal of the transcluded content in your directive + * then you must use this transclude function. When you call a transclude function it returns a a jqLite/JQuery + * object that contains the compiled DOM, which is linked to the correct transclusion scope. + * + * When you call a transclusion function you can pass in a **clone attach function**. This function accepts + * two parameters, `function(clone, scope) { ... }`, where the `clone` is a fresh compiled copy of your transcluded + * content and the `scope` is the newly created transclusion scope, to which the clone is bound. + * + *
      + * **Best Practice**: Always provide a `cloneFn` (clone attach function) when you call a translude function + * since you then get a fresh clone of the original DOM and also have access to the new transclusion scope. + *
      + * + * It is normal practice to attach your transcluded content (`clone`) to the DOM inside your **clone + * attach function**: + * + * ```js + * var transcludedContent, transclusionScope; + * + * $transclude(function(clone, scope) { + * element.append(clone); + * transcludedContent = clone; + * transclusionScope = scope; + * }); + * ``` + * + * Later, if you want to remove the transcluded content from your DOM then you should also destroy the + * associated transclusion scope: + * + * ```js + * transcludedContent.remove(); + * transclusionScope.$destroy(); + * ``` + * + *
      + * **Best Practice**: if you intend to add and remove transcluded content manually in your directive + * (by calling the transclude function to get the DOM and and calling `element.remove()` to remove it), + * then you are also responsible for calling `$destroy` on the transclusion scope. + *
      + * + * The built-in DOM manipulation directives, such as {@link ngIf}, {@link ngSwitch} and {@link ngRepeat} + * automatically destroy their transluded clones as necessary so you do not need to worry about this if + * you are simply using {@link ngTransclude} to inject the transclusion into your directive. + * + * + * #### Transclusion Scopes + * + * When you call a transclude function it returns a DOM fragment that is pre-bound to a **transclusion + * scope**. This scope is special, in that it is a child of the directive's scope (and so gets destroyed + * when the directive's scope gets destroyed) but it inherits the properties of the scope from which it + * was taken. + * + * For example consider a directive that uses transclusion and isolated scope. The DOM hierarchy might look + * like this: + * + * ```html + *
      + *
      + *
      + *
      + *
      + *
      + * ``` + * + * The `$parent` scope hierarchy will look like this: + * + * ``` + * - $rootScope + * - isolate + * - transclusion + * ``` + * + * but the scopes will inherit prototypically from different scopes to their `$parent`. + * + * ``` + * - $rootScope + * - transclusion + * - isolate + * ``` + * + * + * ### Attributes + * + * The {@link ng.$compile.directive.Attributes Attributes} object - passed as a parameter in the + * `link()` or `compile()` functions. It has a variety of uses. + * + * accessing *Normalized attribute names:* + * Directives like 'ngBind' can be expressed in many ways: 'ng:bind', `data-ng-bind`, or 'x-ng-bind'. + * the attributes object allows for normalized access to + * the attributes. + * + * * *Directive inter-communication:* All directives share the same instance of the attributes + * object which allows the directives to use the attributes object as inter directive + * communication. + * + * * *Supports interpolation:* Interpolation attributes are assigned to the attribute object + * allowing other directives to read the interpolated value. + * + * * *Observing interpolated attributes:* Use `$observe` to observe the value changes of attributes + * that contain interpolation (e.g. `src="{{bar}}"`). Not only is this very efficient but it's also + * the only way to easily get the actual value because during the linking phase the interpolation + * hasn't been evaluated yet and so the value is at this time set to `undefined`. + * + * ```js + * function linkingFn(scope, elm, attrs, ctrl) { + * // get the attribute value + * console.log(attrs.ngModel); + * + * // change the attribute + * attrs.$set('ngModel', 'new value'); + * + * // observe changes to interpolated attribute + * attrs.$observe('ngModel', function(value) { + * console.log('ngModel has changed value to ' + value); + * }); + * } + * ``` + * + * ## Example + * + *
      + * **Note**: Typically directives are registered with `module.directive`. The example below is + * to illustrate how `$compile` works. + *
      + * + + + +
      +
      +
      +
      +
      +
      + + it('should auto compile', function() { + var textarea = $('textarea'); + var output = $('div[compile]'); + // The initial state reads 'Hello Angular'. + expect(output.getText()).toBe('Hello Angular'); + textarea.clear(); + textarea.sendKeys('{{name}}!'); + expect(output.getText()).toBe('Angular!'); + }); + +
      + + * + * + * @param {string|DOMElement} element Element or HTML string to compile into a template function. + * @param {function(angular.Scope, cloneAttachFn=)} transclude function available to directives - DEPRECATED. + * + *
      + * **Note:** Passing a `transclude` function to the $compile function is deprecated, as it + * e.g. will not use the right outer scope. Please pass the transclude function as a + * `parentBoundTranscludeFn` to the link function instead. + *
      + * + * @param {number} maxPriority only apply directives lower than given priority (Only effects the + * root element(s), not their children) + * @returns {function(scope, cloneAttachFn=, options=)} a link function which is used to bind template + * (a DOM element/tree) to a scope. Where: + * + * * `scope` - A {@link ng.$rootScope.Scope Scope} to bind to. + * * `cloneAttachFn` - If `cloneAttachFn` is provided, then the link function will clone the + * `template` and call the `cloneAttachFn` function allowing the caller to attach the + * cloned elements to the DOM document at the appropriate place. The `cloneAttachFn` is + * called as:
      `cloneAttachFn(clonedElement, scope)` where: + * + * * `clonedElement` - is a clone of the original `element` passed into the compiler. + * * `scope` - is the current scope with which the linking function is working with. + * + * * `options` - An optional object hash with linking options. If `options` is provided, then the following + * keys may be used to control linking behavior: + * + * * `parentBoundTranscludeFn` - the transclude function made available to + * directives; if given, it will be passed through to the link functions of + * directives found in `element` during compilation. + * * `transcludeControllers` - an object hash with keys that map controller names + * to controller instances; if given, it will make the controllers + * available to directives. + * * `futureParentElement` - defines the parent to which the `cloneAttachFn` will add + * the cloned elements; only needed for transcludes that are allowed to contain non html + * elements (e.g. SVG elements). See also the directive.controller property. + * + * Calling the linking function returns the element of the template. It is either the original + * element passed in, or the clone of the element if the `cloneAttachFn` is provided. + * + * After linking the view is not updated until after a call to $digest which typically is done by + * Angular automatically. + * + * If you need access to the bound view, there are two ways to do it: + * + * - If you are not asking the linking function to clone the template, create the DOM element(s) + * before you send them to the compiler and keep this reference around. + * ```js + * var element = $compile('

      {{total}}

      ')(scope); + * ``` + * + * - if on the other hand, you need the element to be cloned, the view reference from the original + * example would not point to the clone, but rather to the original template that was cloned. In + * this case, you can access the clone via the cloneAttachFn: + * ```js + * var templateElement = angular.element('

      {{total}}

      '), + * scope = ....; + * + * var clonedElement = $compile(templateElement)(scope, function(clonedElement, scope) { + * //attach the clone to DOM document at the right place + * }); + * + * //now we have reference to the cloned DOM via `clonedElement` + * ``` + * + * + * For information on how the compiler works, see the + * {@link guide/compiler Angular HTML Compiler} section of the Developer Guide. + */ + +var $compileMinErr = minErr('$compile'); + +/** + * @ngdoc provider + * @name $compileProvider + * + * @description + */ +$CompileProvider.$inject = ['$provide', '$$sanitizeUriProvider']; +function $CompileProvider($provide, $$sanitizeUriProvider) { + var hasDirectives = {}, + Suffix = 'Directive', + COMMENT_DIRECTIVE_REGEXP = /^\s*directive\:\s*([\w\-]+)\s+(.*)$/, + CLASS_DIRECTIVE_REGEXP = /(([\w\-]+)(?:\:([^;]+))?;?)/, + ALL_OR_NOTHING_ATTRS = makeMap('ngSrc,ngSrcset,src,srcset'), + REQUIRE_PREFIX_REGEXP = /^(?:(\^\^?)?(\?)?(\^\^?)?)?/; + + // Ref: http://developers.whatwg.org/webappapis.html#event-handler-idl-attributes + // The assumption is that future DOM event attribute names will begin with + // 'on' and be composed of only English letters. + var EVENT_HANDLER_ATTR_REGEXP = /^(on[a-z]+|formaction)$/; + + function parseIsolateBindings(scope, directiveName) { + var LOCAL_REGEXP = /^\s*([@&]|=(\*?))(\??)\s*(\w*)\s*$/; + + var bindings = {}; + + forEach(scope, function(definition, scopeName) { + var match = definition.match(LOCAL_REGEXP); + + if (!match) { + throw $compileMinErr('iscp', + "Invalid isolate scope definition for directive '{0}'." + + " Definition: {... {1}: '{2}' ...}", + directiveName, scopeName, definition); + } + + bindings[scopeName] = { + mode: match[1][0], + collection: match[2] === '*', + optional: match[3] === '?', + attrName: match[4] || scopeName + }; + }); + + return bindings; + } + + /** + * @ngdoc method + * @name $compileProvider#directive + * @kind function + * + * @description + * Register a new directive with the compiler. + * + * @param {string|Object} name Name of the directive in camel-case (i.e. ngBind which + * will match as ng-bind), or an object map of directives where the keys are the + * names and the values are the factories. + * @param {Function|Array} directiveFactory An injectable directive factory function. See + * {@link guide/directive} for more info. + * @returns {ng.$compileProvider} Self for chaining. + */ + this.directive = function registerDirective(name, directiveFactory) { + assertNotHasOwnProperty(name, 'directive'); + if (isString(name)) { + assertArg(directiveFactory, 'directiveFactory'); + if (!hasDirectives.hasOwnProperty(name)) { + hasDirectives[name] = []; + $provide.factory(name + Suffix, ['$injector', '$exceptionHandler', + function($injector, $exceptionHandler) { + var directives = []; + forEach(hasDirectives[name], function(directiveFactory, index) { + try { + var directive = $injector.invoke(directiveFactory); + if (isFunction(directive)) { + directive = { compile: valueFn(directive) }; + } else if (!directive.compile && directive.link) { + directive.compile = valueFn(directive.link); + } + directive.priority = directive.priority || 0; + directive.index = index; + directive.name = directive.name || name; + directive.require = directive.require || (directive.controller && directive.name); + directive.restrict = directive.restrict || 'EA'; + if (isObject(directive.scope)) { + directive.$$isolateBindings = parseIsolateBindings(directive.scope, directive.name); + } + directives.push(directive); + } catch (e) { + $exceptionHandler(e); + } + }); + return directives; + }]); + } + hasDirectives[name].push(directiveFactory); + } else { + forEach(name, reverseParams(registerDirective)); + } + return this; + }; + + + /** + * @ngdoc method + * @name $compileProvider#aHrefSanitizationWhitelist + * @kind function + * + * @description + * Retrieves or overrides the default regular expression that is used for whitelisting of safe + * urls during a[href] sanitization. + * + * The sanitization is a security measure aimed at preventing XSS attacks via html links. + * + * Any url about to be assigned to a[href] via data-binding is first normalized and turned into + * an absolute url. Afterwards, the url is matched against the `aHrefSanitizationWhitelist` + * regular expression. If a match is found, the original url is written into the dom. Otherwise, + * the absolute url is prefixed with `'unsafe:'` string and only then is it written into the DOM. + * + * @param {RegExp=} regexp New regexp to whitelist urls with. + * @returns {RegExp|ng.$compileProvider} Current RegExp if called without value or self for + * chaining otherwise. + */ + this.aHrefSanitizationWhitelist = function(regexp) { + if (isDefined(regexp)) { + $$sanitizeUriProvider.aHrefSanitizationWhitelist(regexp); + return this; + } else { + return $$sanitizeUriProvider.aHrefSanitizationWhitelist(); + } + }; + + + /** + * @ngdoc method + * @name $compileProvider#imgSrcSanitizationWhitelist + * @kind function + * + * @description + * Retrieves or overrides the default regular expression that is used for whitelisting of safe + * urls during img[src] sanitization. + * + * The sanitization is a security measure aimed at prevent XSS attacks via html links. + * + * Any url about to be assigned to img[src] via data-binding is first normalized and turned into + * an absolute url. Afterwards, the url is matched against the `imgSrcSanitizationWhitelist` + * regular expression. If a match is found, the original url is written into the dom. Otherwise, + * the absolute url is prefixed with `'unsafe:'` string and only then is it written into the DOM. + * + * @param {RegExp=} regexp New regexp to whitelist urls with. + * @returns {RegExp|ng.$compileProvider} Current RegExp if called without value or self for + * chaining otherwise. + */ + this.imgSrcSanitizationWhitelist = function(regexp) { + if (isDefined(regexp)) { + $$sanitizeUriProvider.imgSrcSanitizationWhitelist(regexp); + return this; + } else { + return $$sanitizeUriProvider.imgSrcSanitizationWhitelist(); + } + }; + + /** + * @ngdoc method + * @name $compileProvider#debugInfoEnabled + * + * @param {boolean=} enabled update the debugInfoEnabled state if provided, otherwise just return the + * current debugInfoEnabled state + * @returns {*} current value if used as getter or itself (chaining) if used as setter + * + * @kind function + * + * @description + * Call this method to enable/disable various debug runtime information in the compiler such as adding + * binding information and a reference to the current scope on to DOM elements. + * If enabled, the compiler will add the following to DOM elements that have been bound to the scope + * * `ng-binding` CSS class + * * `$binding` data property containing an array of the binding expressions + * + * You may want to disable this in production for a significant performance boost. See + * {@link guide/production#disabling-debug-data Disabling Debug Data} for more. + * + * The default value is true. + */ + var debugInfoEnabled = true; + this.debugInfoEnabled = function(enabled) { + if (isDefined(enabled)) { + debugInfoEnabled = enabled; + return this; + } + return debugInfoEnabled; + }; + + this.$get = [ + '$injector', '$interpolate', '$exceptionHandler', '$templateRequest', '$parse', + '$controller', '$rootScope', '$document', '$sce', '$animate', '$$sanitizeUri', + function($injector, $interpolate, $exceptionHandler, $templateRequest, $parse, + $controller, $rootScope, $document, $sce, $animate, $$sanitizeUri) { + + var Attributes = function(element, attributesToCopy) { + if (attributesToCopy) { + var keys = Object.keys(attributesToCopy); + var i, l, key; + + for (i = 0, l = keys.length; i < l; i++) { + key = keys[i]; + this[key] = attributesToCopy[key]; + } + } else { + this.$attr = {}; + } + + this.$$element = element; + }; + + Attributes.prototype = { + /** + * @ngdoc method + * @name $compile.directive.Attributes#$normalize + * @kind function + * + * @description + * Converts an attribute name (e.g. dash/colon/underscore-delimited string, optionally prefixed with `x-` or + * `data-`) to its normalized, camelCase form. + * + * Also there is special case for Moz prefix starting with upper case letter. + * + * For further information check out the guide on {@link guide/directive#matching-directives Matching Directives} + * + * @param {string} name Name to normalize + */ + $normalize: directiveNormalize, + + + /** + * @ngdoc method + * @name $compile.directive.Attributes#$addClass + * @kind function + * + * @description + * Adds the CSS class value specified by the classVal parameter to the element. If animations + * are enabled then an animation will be triggered for the class addition. + * + * @param {string} classVal The className value that will be added to the element + */ + $addClass: function(classVal) { + if (classVal && classVal.length > 0) { + $animate.addClass(this.$$element, classVal); + } + }, + + /** + * @ngdoc method + * @name $compile.directive.Attributes#$removeClass + * @kind function + * + * @description + * Removes the CSS class value specified by the classVal parameter from the element. If + * animations are enabled then an animation will be triggered for the class removal. + * + * @param {string} classVal The className value that will be removed from the element + */ + $removeClass: function(classVal) { + if (classVal && classVal.length > 0) { + $animate.removeClass(this.$$element, classVal); + } + }, + + /** + * @ngdoc method + * @name $compile.directive.Attributes#$updateClass + * @kind function + * + * @description + * Adds and removes the appropriate CSS class values to the element based on the difference + * between the new and old CSS class values (specified as newClasses and oldClasses). + * + * @param {string} newClasses The current CSS className value + * @param {string} oldClasses The former CSS className value + */ + $updateClass: function(newClasses, oldClasses) { + var toAdd = tokenDifference(newClasses, oldClasses); + if (toAdd && toAdd.length) { + $animate.addClass(this.$$element, toAdd); + } + + var toRemove = tokenDifference(oldClasses, newClasses); + if (toRemove && toRemove.length) { + $animate.removeClass(this.$$element, toRemove); + } + }, + + /** + * Set a normalized attribute on the element in a way such that all directives + * can share the attribute. This function properly handles boolean attributes. + * @param {string} key Normalized key. (ie ngAttribute) + * @param {string|boolean} value The value to set. If `null` attribute will be deleted. + * @param {boolean=} writeAttr If false, does not write the value to DOM element attribute. + * Defaults to true. + * @param {string=} attrName Optional none normalized name. Defaults to key. + */ + $set: function(key, value, writeAttr, attrName) { + // TODO: decide whether or not to throw an error if "class" + //is set through this function since it may cause $updateClass to + //become unstable. + + var node = this.$$element[0], + booleanKey = getBooleanAttrName(node, key), + aliasedKey = getAliasedAttrName(node, key), + observer = key, + nodeName; + + if (booleanKey) { + this.$$element.prop(key, value); + attrName = booleanKey; + } else if (aliasedKey) { + this[aliasedKey] = value; + observer = aliasedKey; + } + + this[key] = value; + + // translate normalized key to actual key + if (attrName) { + this.$attr[key] = attrName; + } else { + attrName = this.$attr[key]; + if (!attrName) { + this.$attr[key] = attrName = snake_case(key, '-'); + } + } + + nodeName = nodeName_(this.$$element); + + if ((nodeName === 'a' && key === 'href') || + (nodeName === 'img' && key === 'src')) { + // sanitize a[href] and img[src] values + this[key] = value = $$sanitizeUri(value, key === 'src'); + } else if (nodeName === 'img' && key === 'srcset') { + // sanitize img[srcset] values + var result = ""; + + // first check if there are spaces because it's not the same pattern + var trimmedSrcset = trim(value); + // ( 999x ,| 999w ,| ,|, ) + var srcPattern = /(\s+\d+x\s*,|\s+\d+w\s*,|\s+,|,\s+)/; + var pattern = /\s/.test(trimmedSrcset) ? srcPattern : /(,)/; + + // split srcset into tuple of uri and descriptor except for the last item + var rawUris = trimmedSrcset.split(pattern); + + // for each tuples + var nbrUrisWith2parts = Math.floor(rawUris.length / 2); + for (var i = 0; i < nbrUrisWith2parts; i++) { + var innerIdx = i * 2; + // sanitize the uri + result += $$sanitizeUri(trim(rawUris[innerIdx]), true); + // add the descriptor + result += (" " + trim(rawUris[innerIdx + 1])); + } + + // split the last item into uri and descriptor + var lastTuple = trim(rawUris[i * 2]).split(/\s/); + + // sanitize the last uri + result += $$sanitizeUri(trim(lastTuple[0]), true); + + // and add the last descriptor if any + if (lastTuple.length === 2) { + result += (" " + trim(lastTuple[1])); + } + this[key] = value = result; + } + + if (writeAttr !== false) { + if (value === null || value === undefined) { + this.$$element.removeAttr(attrName); + } else { + this.$$element.attr(attrName, value); + } + } + + // fire observers + var $$observers = this.$$observers; + $$observers && forEach($$observers[observer], function(fn) { + try { + fn(value); + } catch (e) { + $exceptionHandler(e); + } + }); + }, + + + /** + * @ngdoc method + * @name $compile.directive.Attributes#$observe + * @kind function + * + * @description + * Observes an interpolated attribute. + * + * The observer function will be invoked once during the next `$digest` following + * compilation. The observer is then invoked whenever the interpolated value + * changes. + * + * @param {string} key Normalized key. (ie ngAttribute) . + * @param {function(interpolatedValue)} fn Function that will be called whenever + the interpolated value of the attribute changes. + * See the {@link guide/directive#text-and-attribute-bindings Directives} guide for more info. + * @returns {function()} Returns a deregistration function for this observer. + */ + $observe: function(key, fn) { + var attrs = this, + $$observers = (attrs.$$observers || (attrs.$$observers = createMap())), + listeners = ($$observers[key] || ($$observers[key] = [])); + + listeners.push(fn); + $rootScope.$evalAsync(function() { + if (!listeners.$$inter && attrs.hasOwnProperty(key)) { + // no one registered attribute interpolation function, so lets call it manually + fn(attrs[key]); + } + }); + + return function() { + arrayRemove(listeners, fn); + }; + } + }; + + + function safeAddClass($element, className) { + try { + $element.addClass(className); + } catch (e) { + // ignore, since it means that we are trying to set class on + // SVG element, where class name is read-only. + } + } + + + var startSymbol = $interpolate.startSymbol(), + endSymbol = $interpolate.endSymbol(), + denormalizeTemplate = (startSymbol == '{{' || endSymbol == '}}') + ? identity + : function denormalizeTemplate(template) { + return template.replace(/\{\{/g, startSymbol).replace(/}}/g, endSymbol); + }, + NG_ATTR_BINDING = /^ngAttr[A-Z]/; + + compile.$$addBindingInfo = debugInfoEnabled ? function $$addBindingInfo($element, binding) { + var bindings = $element.data('$binding') || []; + + if (isArray(binding)) { + bindings = bindings.concat(binding); + } else { + bindings.push(binding); + } + + $element.data('$binding', bindings); + } : noop; + + compile.$$addBindingClass = debugInfoEnabled ? function $$addBindingClass($element) { + safeAddClass($element, 'ng-binding'); + } : noop; + + compile.$$addScopeInfo = debugInfoEnabled ? function $$addScopeInfo($element, scope, isolated, noTemplate) { + var dataName = isolated ? (noTemplate ? '$isolateScopeNoTemplate' : '$isolateScope') : '$scope'; + $element.data(dataName, scope); + } : noop; + + compile.$$addScopeClass = debugInfoEnabled ? function $$addScopeClass($element, isolated) { + safeAddClass($element, isolated ? 'ng-isolate-scope' : 'ng-scope'); + } : noop; + + return compile; + + //================================ + + function compile($compileNodes, transcludeFn, maxPriority, ignoreDirective, + previousCompileContext) { + if (!($compileNodes instanceof jqLite)) { + // jquery always rewraps, whereas we need to preserve the original selector so that we can + // modify it. + $compileNodes = jqLite($compileNodes); + } + // We can not compile top level text elements since text nodes can be merged and we will + // not be able to attach scope data to them, so we will wrap them in + forEach($compileNodes, function(node, index) { + if (node.nodeType == NODE_TYPE_TEXT && node.nodeValue.match(/\S+/) /* non-empty */ ) { + $compileNodes[index] = jqLite(node).wrap('').parent()[0]; + } + }); + var compositeLinkFn = + compileNodes($compileNodes, transcludeFn, $compileNodes, + maxPriority, ignoreDirective, previousCompileContext); + compile.$$addScopeClass($compileNodes); + var namespace = null; + return function publicLinkFn(scope, cloneConnectFn, options) { + assertArg(scope, 'scope'); + + options = options || {}; + var parentBoundTranscludeFn = options.parentBoundTranscludeFn, + transcludeControllers = options.transcludeControllers, + futureParentElement = options.futureParentElement; + + // When `parentBoundTranscludeFn` is passed, it is a + // `controllersBoundTransclude` function (it was previously passed + // as `transclude` to directive.link) so we must unwrap it to get + // its `boundTranscludeFn` + if (parentBoundTranscludeFn && parentBoundTranscludeFn.$$boundTransclude) { + parentBoundTranscludeFn = parentBoundTranscludeFn.$$boundTransclude; + } + + if (!namespace) { + namespace = detectNamespaceForChildElements(futureParentElement); + } + var $linkNode; + if (namespace !== 'html') { + // When using a directive with replace:true and templateUrl the $compileNodes + // (or a child element inside of them) + // might change, so we need to recreate the namespace adapted compileNodes + // for call to the link function. + // Note: This will already clone the nodes... + $linkNode = jqLite( + wrapTemplate(namespace, jqLite('
      ').append($compileNodes).html()) + ); + } else if (cloneConnectFn) { + // important!!: we must call our jqLite.clone() since the jQuery one is trying to be smart + // and sometimes changes the structure of the DOM. + $linkNode = JQLitePrototype.clone.call($compileNodes); + } else { + $linkNode = $compileNodes; + } + + if (transcludeControllers) { + for (var controllerName in transcludeControllers) { + $linkNode.data('$' + controllerName + 'Controller', transcludeControllers[controllerName].instance); + } + } + + compile.$$addScopeInfo($linkNode, scope); + + if (cloneConnectFn) cloneConnectFn($linkNode, scope); + if (compositeLinkFn) compositeLinkFn(scope, $linkNode, $linkNode, parentBoundTranscludeFn); + return $linkNode; + }; + } + + function detectNamespaceForChildElements(parentElement) { + // TODO: Make this detect MathML as well... + var node = parentElement && parentElement[0]; + if (!node) { + return 'html'; + } else { + return nodeName_(node) !== 'foreignobject' && node.toString().match(/SVG/) ? 'svg' : 'html'; + } + } + + /** + * Compile function matches each node in nodeList against the directives. Once all directives + * for a particular node are collected their compile functions are executed. The compile + * functions return values - the linking functions - are combined into a composite linking + * function, which is the a linking function for the node. + * + * @param {NodeList} nodeList an array of nodes or NodeList to compile + * @param {function(angular.Scope, cloneAttachFn=)} transcludeFn A linking function, where the + * scope argument is auto-generated to the new child of the transcluded parent scope. + * @param {DOMElement=} $rootElement If the nodeList is the root of the compilation tree then + * the rootElement must be set the jqLite collection of the compile root. This is + * needed so that the jqLite collection items can be replaced with widgets. + * @param {number=} maxPriority Max directive priority. + * @returns {Function} A composite linking function of all of the matched directives or null. + */ + function compileNodes(nodeList, transcludeFn, $rootElement, maxPriority, ignoreDirective, + previousCompileContext) { + var linkFns = [], + attrs, directives, nodeLinkFn, childNodes, childLinkFn, linkFnFound, nodeLinkFnFound; + + for (var i = 0; i < nodeList.length; i++) { + attrs = new Attributes(); + + // we must always refer to nodeList[i] since the nodes can be replaced underneath us. + directives = collectDirectives(nodeList[i], [], attrs, i === 0 ? maxPriority : undefined, + ignoreDirective); + + nodeLinkFn = (directives.length) + ? applyDirectivesToNode(directives, nodeList[i], attrs, transcludeFn, $rootElement, + null, [], [], previousCompileContext) + : null; + + if (nodeLinkFn && nodeLinkFn.scope) { + compile.$$addScopeClass(attrs.$$element); + } + + childLinkFn = (nodeLinkFn && nodeLinkFn.terminal || + !(childNodes = nodeList[i].childNodes) || + !childNodes.length) + ? null + : compileNodes(childNodes, + nodeLinkFn ? ( + (nodeLinkFn.transcludeOnThisElement || !nodeLinkFn.templateOnThisElement) + && nodeLinkFn.transclude) : transcludeFn); + + if (nodeLinkFn || childLinkFn) { + linkFns.push(i, nodeLinkFn, childLinkFn); + linkFnFound = true; + nodeLinkFnFound = nodeLinkFnFound || nodeLinkFn; + } + + //use the previous context only for the first element in the virtual group + previousCompileContext = null; + } + + // return a linking function if we have found anything, null otherwise + return linkFnFound ? compositeLinkFn : null; + + function compositeLinkFn(scope, nodeList, $rootElement, parentBoundTranscludeFn) { + var nodeLinkFn, childLinkFn, node, childScope, i, ii, idx, childBoundTranscludeFn; + var stableNodeList; + + + if (nodeLinkFnFound) { + // copy nodeList so that if a nodeLinkFn removes or adds an element at this DOM level our + // offsets don't get screwed up + var nodeListLength = nodeList.length; + stableNodeList = new Array(nodeListLength); + + // create a sparse array by only copying the elements which have a linkFn + for (i = 0; i < linkFns.length; i+=3) { + idx = linkFns[i]; + stableNodeList[idx] = nodeList[idx]; + } + } else { + stableNodeList = nodeList; + } + + for (i = 0, ii = linkFns.length; i < ii;) { + node = stableNodeList[linkFns[i++]]; + nodeLinkFn = linkFns[i++]; + childLinkFn = linkFns[i++]; + + if (nodeLinkFn) { + if (nodeLinkFn.scope) { + childScope = scope.$new(); + compile.$$addScopeInfo(jqLite(node), childScope); + } else { + childScope = scope; + } + + if (nodeLinkFn.transcludeOnThisElement) { + childBoundTranscludeFn = createBoundTranscludeFn( + scope, nodeLinkFn.transclude, parentBoundTranscludeFn, + nodeLinkFn.elementTranscludeOnThisElement); + + } else if (!nodeLinkFn.templateOnThisElement && parentBoundTranscludeFn) { + childBoundTranscludeFn = parentBoundTranscludeFn; + + } else if (!parentBoundTranscludeFn && transcludeFn) { + childBoundTranscludeFn = createBoundTranscludeFn(scope, transcludeFn); + + } else { + childBoundTranscludeFn = null; + } + + nodeLinkFn(childLinkFn, childScope, node, $rootElement, childBoundTranscludeFn); + + } else if (childLinkFn) { + childLinkFn(scope, node.childNodes, undefined, parentBoundTranscludeFn); + } + } + } + } + + function createBoundTranscludeFn(scope, transcludeFn, previousBoundTranscludeFn, elementTransclusion) { + + var boundTranscludeFn = function(transcludedScope, cloneFn, controllers, futureParentElement, containingScope) { + + if (!transcludedScope) { + transcludedScope = scope.$new(false, containingScope); + transcludedScope.$$transcluded = true; + } + + return transcludeFn(transcludedScope, cloneFn, { + parentBoundTranscludeFn: previousBoundTranscludeFn, + transcludeControllers: controllers, + futureParentElement: futureParentElement + }); + }; + + return boundTranscludeFn; + } + + /** + * Looks for directives on the given node and adds them to the directive collection which is + * sorted. + * + * @param node Node to search. + * @param directives An array to which the directives are added to. This array is sorted before + * the function returns. + * @param attrs The shared attrs object which is used to populate the normalized attributes. + * @param {number=} maxPriority Max directive priority. + */ + function collectDirectives(node, directives, attrs, maxPriority, ignoreDirective) { + var nodeType = node.nodeType, + attrsMap = attrs.$attr, + match, + className; + + switch (nodeType) { + case NODE_TYPE_ELEMENT: /* Element */ + // use the node name: + addDirective(directives, + directiveNormalize(nodeName_(node)), 'E', maxPriority, ignoreDirective); + + // iterate over the attributes + for (var attr, name, nName, ngAttrName, value, isNgAttr, nAttrs = node.attributes, + j = 0, jj = nAttrs && nAttrs.length; j < jj; j++) { + var attrStartName = false; + var attrEndName = false; + + attr = nAttrs[j]; + name = attr.name; + value = trim(attr.value); + + // support ngAttr attribute binding + ngAttrName = directiveNormalize(name); + if (isNgAttr = NG_ATTR_BINDING.test(ngAttrName)) { + name = name.replace(PREFIX_REGEXP, '') + .substr(8).replace(/_(.)/g, function(match, letter) { + return letter.toUpperCase(); + }); + } + + var directiveNName = ngAttrName.replace(/(Start|End)$/, ''); + if (directiveIsMultiElement(directiveNName)) { + if (ngAttrName === directiveNName + 'Start') { + attrStartName = name; + attrEndName = name.substr(0, name.length - 5) + 'end'; + name = name.substr(0, name.length - 6); + } + } + + nName = directiveNormalize(name.toLowerCase()); + attrsMap[nName] = name; + if (isNgAttr || !attrs.hasOwnProperty(nName)) { + attrs[nName] = value; + if (getBooleanAttrName(node, nName)) { + attrs[nName] = true; // presence means true + } + } + addAttrInterpolateDirective(node, directives, value, nName, isNgAttr); + addDirective(directives, nName, 'A', maxPriority, ignoreDirective, attrStartName, + attrEndName); + } + + // use class as directive + className = node.className; + if (isString(className) && className !== '') { + while (match = CLASS_DIRECTIVE_REGEXP.exec(className)) { + nName = directiveNormalize(match[2]); + if (addDirective(directives, nName, 'C', maxPriority, ignoreDirective)) { + attrs[nName] = trim(match[3]); + } + className = className.substr(match.index + match[0].length); + } + } + break; + case NODE_TYPE_TEXT: /* Text Node */ + addTextInterpolateDirective(directives, node.nodeValue); + break; + case NODE_TYPE_COMMENT: /* Comment */ + try { + match = COMMENT_DIRECTIVE_REGEXP.exec(node.nodeValue); + if (match) { + nName = directiveNormalize(match[1]); + if (addDirective(directives, nName, 'M', maxPriority, ignoreDirective)) { + attrs[nName] = trim(match[2]); + } + } + } catch (e) { + // turns out that under some circumstances IE9 throws errors when one attempts to read + // comment's node value. + // Just ignore it and continue. (Can't seem to reproduce in test case.) + } + break; + } + + directives.sort(byPriority); + return directives; + } + + /** + * Given a node with an directive-start it collects all of the siblings until it finds + * directive-end. + * @param node + * @param attrStart + * @param attrEnd + * @returns {*} + */ + function groupScan(node, attrStart, attrEnd) { + var nodes = []; + var depth = 0; + if (attrStart && node.hasAttribute && node.hasAttribute(attrStart)) { + do { + if (!node) { + throw $compileMinErr('uterdir', + "Unterminated attribute, found '{0}' but no matching '{1}' found.", + attrStart, attrEnd); + } + if (node.nodeType == NODE_TYPE_ELEMENT) { + if (node.hasAttribute(attrStart)) depth++; + if (node.hasAttribute(attrEnd)) depth--; + } + nodes.push(node); + node = node.nextSibling; + } while (depth > 0); + } else { + nodes.push(node); + } + + return jqLite(nodes); + } + + /** + * Wrapper for linking function which converts normal linking function into a grouped + * linking function. + * @param linkFn + * @param attrStart + * @param attrEnd + * @returns {Function} + */ + function groupElementsLinkFnWrapper(linkFn, attrStart, attrEnd) { + return function(scope, element, attrs, controllers, transcludeFn) { + element = groupScan(element[0], attrStart, attrEnd); + return linkFn(scope, element, attrs, controllers, transcludeFn); + }; + } + + /** + * Once the directives have been collected, their compile functions are executed. This method + * is responsible for inlining directive templates as well as terminating the application + * of the directives if the terminal directive has been reached. + * + * @param {Array} directives Array of collected directives to execute their compile function. + * this needs to be pre-sorted by priority order. + * @param {Node} compileNode The raw DOM node to apply the compile functions to + * @param {Object} templateAttrs The shared attribute function + * @param {function(angular.Scope, cloneAttachFn=)} transcludeFn A linking function, where the + * scope argument is auto-generated to the new + * child of the transcluded parent scope. + * @param {JQLite} jqCollection If we are working on the root of the compile tree then this + * argument has the root jqLite array so that we can replace nodes + * on it. + * @param {Object=} originalReplaceDirective An optional directive that will be ignored when + * compiling the transclusion. + * @param {Array.} preLinkFns + * @param {Array.} postLinkFns + * @param {Object} previousCompileContext Context used for previous compilation of the current + * node + * @returns {Function} linkFn + */ + function applyDirectivesToNode(directives, compileNode, templateAttrs, transcludeFn, + jqCollection, originalReplaceDirective, preLinkFns, postLinkFns, + previousCompileContext) { + previousCompileContext = previousCompileContext || {}; + + var terminalPriority = -Number.MAX_VALUE, + newScopeDirective, + controllerDirectives = previousCompileContext.controllerDirectives, + controllers, + newIsolateScopeDirective = previousCompileContext.newIsolateScopeDirective, + templateDirective = previousCompileContext.templateDirective, + nonTlbTranscludeDirective = previousCompileContext.nonTlbTranscludeDirective, + hasTranscludeDirective = false, + hasTemplate = false, + hasElementTranscludeDirective = previousCompileContext.hasElementTranscludeDirective, + $compileNode = templateAttrs.$$element = jqLite(compileNode), + directive, + directiveName, + $template, + replaceDirective = originalReplaceDirective, + childTranscludeFn = transcludeFn, + linkFn, + directiveValue; + + // executes all directives on the current element + for (var i = 0, ii = directives.length; i < ii; i++) { + directive = directives[i]; + var attrStart = directive.$$start; + var attrEnd = directive.$$end; + + // collect multiblock sections + if (attrStart) { + $compileNode = groupScan(compileNode, attrStart, attrEnd); + } + $template = undefined; + + if (terminalPriority > directive.priority) { + break; // prevent further processing of directives + } + + if (directiveValue = directive.scope) { + + // skip the check for directives with async templates, we'll check the derived sync + // directive when the template arrives + if (!directive.templateUrl) { + if (isObject(directiveValue)) { + // This directive is trying to add an isolated scope. + // Check that there is no scope of any kind already + assertNoDuplicate('new/isolated scope', newIsolateScopeDirective || newScopeDirective, + directive, $compileNode); + newIsolateScopeDirective = directive; + } else { + // This directive is trying to add a child scope. + // Check that there is no isolated scope already + assertNoDuplicate('new/isolated scope', newIsolateScopeDirective, directive, + $compileNode); + } + } + + newScopeDirective = newScopeDirective || directive; + } + + directiveName = directive.name; + + if (!directive.templateUrl && directive.controller) { + directiveValue = directive.controller; + controllerDirectives = controllerDirectives || {}; + assertNoDuplicate("'" + directiveName + "' controller", + controllerDirectives[directiveName], directive, $compileNode); + controllerDirectives[directiveName] = directive; + } + + if (directiveValue = directive.transclude) { + hasTranscludeDirective = true; + + // Special case ngIf and ngRepeat so that we don't complain about duplicate transclusion. + // This option should only be used by directives that know how to safely handle element transclusion, + // where the transcluded nodes are added or replaced after linking. + if (!directive.$$tlb) { + assertNoDuplicate('transclusion', nonTlbTranscludeDirective, directive, $compileNode); + nonTlbTranscludeDirective = directive; + } + + if (directiveValue == 'element') { + hasElementTranscludeDirective = true; + terminalPriority = directive.priority; + $template = $compileNode; + $compileNode = templateAttrs.$$element = + jqLite(document.createComment(' ' + directiveName + ': ' + + templateAttrs[directiveName] + ' ')); + compileNode = $compileNode[0]; + replaceWith(jqCollection, sliceArgs($template), compileNode); + + childTranscludeFn = compile($template, transcludeFn, terminalPriority, + replaceDirective && replaceDirective.name, { + // Don't pass in: + // - controllerDirectives - otherwise we'll create duplicates controllers + // - newIsolateScopeDirective or templateDirective - combining templates with + // element transclusion doesn't make sense. + // + // We need only nonTlbTranscludeDirective so that we prevent putting transclusion + // on the same element more than once. + nonTlbTranscludeDirective: nonTlbTranscludeDirective + }); + } else { + $template = jqLite(jqLiteClone(compileNode)).contents(); + $compileNode.empty(); // clear contents + childTranscludeFn = compile($template, transcludeFn); + } + } + + if (directive.template) { + hasTemplate = true; + assertNoDuplicate('template', templateDirective, directive, $compileNode); + templateDirective = directive; + + directiveValue = (isFunction(directive.template)) + ? directive.template($compileNode, templateAttrs) + : directive.template; + + directiveValue = denormalizeTemplate(directiveValue); + + if (directive.replace) { + replaceDirective = directive; + if (jqLiteIsTextNode(directiveValue)) { + $template = []; + } else { + $template = removeComments(wrapTemplate(directive.templateNamespace, trim(directiveValue))); + } + compileNode = $template[0]; + + if ($template.length != 1 || compileNode.nodeType !== NODE_TYPE_ELEMENT) { + throw $compileMinErr('tplrt', + "Template for directive '{0}' must have exactly one root element. {1}", + directiveName, ''); + } + + replaceWith(jqCollection, $compileNode, compileNode); + + var newTemplateAttrs = {$attr: {}}; + + // combine directives from the original node and from the template: + // - take the array of directives for this element + // - split it into two parts, those that already applied (processed) and those that weren't (unprocessed) + // - collect directives from the template and sort them by priority + // - combine directives as: processed + template + unprocessed + var templateDirectives = collectDirectives(compileNode, [], newTemplateAttrs); + var unprocessedDirectives = directives.splice(i + 1, directives.length - (i + 1)); + + if (newIsolateScopeDirective) { + markDirectivesAsIsolate(templateDirectives); + } + directives = directives.concat(templateDirectives).concat(unprocessedDirectives); + mergeTemplateAttributes(templateAttrs, newTemplateAttrs); + + ii = directives.length; + } else { + $compileNode.html(directiveValue); + } + } + + if (directive.templateUrl) { + hasTemplate = true; + assertNoDuplicate('template', templateDirective, directive, $compileNode); + templateDirective = directive; + + if (directive.replace) { + replaceDirective = directive; + } + + nodeLinkFn = compileTemplateUrl(directives.splice(i, directives.length - i), $compileNode, + templateAttrs, jqCollection, hasTranscludeDirective && childTranscludeFn, preLinkFns, postLinkFns, { + controllerDirectives: controllerDirectives, + newIsolateScopeDirective: newIsolateScopeDirective, + templateDirective: templateDirective, + nonTlbTranscludeDirective: nonTlbTranscludeDirective + }); + ii = directives.length; + } else if (directive.compile) { + try { + linkFn = directive.compile($compileNode, templateAttrs, childTranscludeFn); + if (isFunction(linkFn)) { + addLinkFns(null, linkFn, attrStart, attrEnd); + } else if (linkFn) { + addLinkFns(linkFn.pre, linkFn.post, attrStart, attrEnd); + } + } catch (e) { + $exceptionHandler(e, startingTag($compileNode)); + } + } + + if (directive.terminal) { + nodeLinkFn.terminal = true; + terminalPriority = Math.max(terminalPriority, directive.priority); + } + + } + + nodeLinkFn.scope = newScopeDirective && newScopeDirective.scope === true; + nodeLinkFn.transcludeOnThisElement = hasTranscludeDirective; + nodeLinkFn.elementTranscludeOnThisElement = hasElementTranscludeDirective; + nodeLinkFn.templateOnThisElement = hasTemplate; + nodeLinkFn.transclude = childTranscludeFn; + + previousCompileContext.hasElementTranscludeDirective = hasElementTranscludeDirective; + + // might be normal or delayed nodeLinkFn depending on if templateUrl is present + return nodeLinkFn; + + //////////////////// + + function addLinkFns(pre, post, attrStart, attrEnd) { + if (pre) { + if (attrStart) pre = groupElementsLinkFnWrapper(pre, attrStart, attrEnd); + pre.require = directive.require; + pre.directiveName = directiveName; + if (newIsolateScopeDirective === directive || directive.$$isolateScope) { + pre = cloneAndAnnotateFn(pre, {isolateScope: true}); + } + preLinkFns.push(pre); + } + if (post) { + if (attrStart) post = groupElementsLinkFnWrapper(post, attrStart, attrEnd); + post.require = directive.require; + post.directiveName = directiveName; + if (newIsolateScopeDirective === directive || directive.$$isolateScope) { + post = cloneAndAnnotateFn(post, {isolateScope: true}); + } + postLinkFns.push(post); + } + } + + + function getControllers(directiveName, require, $element, elementControllers) { + var value, retrievalMethod = 'data', optional = false; + var $searchElement = $element; + var match; + if (isString(require)) { + match = require.match(REQUIRE_PREFIX_REGEXP); + require = require.substring(match[0].length); + + if (match[3]) { + if (match[1]) match[3] = null; + else match[1] = match[3]; + } + if (match[1] === '^') { + retrievalMethod = 'inheritedData'; + } else if (match[1] === '^^') { + retrievalMethod = 'inheritedData'; + $searchElement = $element.parent(); + } + if (match[2] === '?') { + optional = true; + } + + value = null; + + if (elementControllers && retrievalMethod === 'data') { + if (value = elementControllers[require]) { + value = value.instance; + } + } + value = value || $searchElement[retrievalMethod]('$' + require + 'Controller'); + + if (!value && !optional) { + throw $compileMinErr('ctreq', + "Controller '{0}', required by directive '{1}', can't be found!", + require, directiveName); + } + return value || null; + } else if (isArray(require)) { + value = []; + forEach(require, function(require) { + value.push(getControllers(directiveName, require, $element, elementControllers)); + }); + } + return value; + } + + + function nodeLinkFn(childLinkFn, scope, linkNode, $rootElement, boundTranscludeFn) { + var i, ii, linkFn, controller, isolateScope, elementControllers, transcludeFn, $element, + attrs; + + if (compileNode === linkNode) { + attrs = templateAttrs; + $element = templateAttrs.$$element; + } else { + $element = jqLite(linkNode); + attrs = new Attributes($element, templateAttrs); + } + + if (newIsolateScopeDirective) { + isolateScope = scope.$new(true); + } + + if (boundTranscludeFn) { + // track `boundTranscludeFn` so it can be unwrapped if `transcludeFn` + // is later passed as `parentBoundTranscludeFn` to `publicLinkFn` + transcludeFn = controllersBoundTransclude; + transcludeFn.$$boundTransclude = boundTranscludeFn; + } + + if (controllerDirectives) { + // TODO: merge `controllers` and `elementControllers` into single object. + controllers = {}; + elementControllers = {}; + forEach(controllerDirectives, function(directive) { + var locals = { + $scope: directive === newIsolateScopeDirective || directive.$$isolateScope ? isolateScope : scope, + $element: $element, + $attrs: attrs, + $transclude: transcludeFn + }, controllerInstance; + + controller = directive.controller; + if (controller == '@') { + controller = attrs[directive.name]; + } + + controllerInstance = $controller(controller, locals, true, directive.controllerAs); + + // For directives with element transclusion the element is a comment, + // but jQuery .data doesn't support attaching data to comment nodes as it's hard to + // clean up (http://bugs.jquery.com/ticket/8335). + // Instead, we save the controllers for the element in a local hash and attach to .data + // later, once we have the actual element. + elementControllers[directive.name] = controllerInstance; + if (!hasElementTranscludeDirective) { + $element.data('$' + directive.name + 'Controller', controllerInstance.instance); + } + + controllers[directive.name] = controllerInstance; + }); + } + + if (newIsolateScopeDirective) { + compile.$$addScopeInfo($element, isolateScope, true, !(templateDirective && (templateDirective === newIsolateScopeDirective || + templateDirective === newIsolateScopeDirective.$$originalDirective))); + compile.$$addScopeClass($element, true); + + var isolateScopeController = controllers && controllers[newIsolateScopeDirective.name]; + var isolateBindingContext = isolateScope; + if (isolateScopeController && isolateScopeController.identifier && + newIsolateScopeDirective.bindToController === true) { + isolateBindingContext = isolateScopeController.instance; + } + + forEach(isolateScope.$$isolateBindings = newIsolateScopeDirective.$$isolateBindings, function(definition, scopeName) { + var attrName = definition.attrName, + optional = definition.optional, + mode = definition.mode, // @, =, or & + lastValue, + parentGet, parentSet, compare; + + switch (mode) { + + case '@': + attrs.$observe(attrName, function(value) { + isolateBindingContext[scopeName] = value; + }); + attrs.$$observers[attrName].$$scope = scope; + if (attrs[attrName]) { + // If the attribute has been provided then we trigger an interpolation to ensure + // the value is there for use in the link fn + isolateBindingContext[scopeName] = $interpolate(attrs[attrName])(scope); + } + break; + + case '=': + if (optional && !attrs[attrName]) { + return; + } + parentGet = $parse(attrs[attrName]); + if (parentGet.literal) { + compare = equals; + } else { + compare = function(a, b) { return a === b || (a !== a && b !== b); }; + } + parentSet = parentGet.assign || function() { + // reset the change, or we will throw this exception on every $digest + lastValue = isolateBindingContext[scopeName] = parentGet(scope); + throw $compileMinErr('nonassign', + "Expression '{0}' used with directive '{1}' is non-assignable!", + attrs[attrName], newIsolateScopeDirective.name); + }; + lastValue = isolateBindingContext[scopeName] = parentGet(scope); + var parentValueWatch = function parentValueWatch(parentValue) { + if (!compare(parentValue, isolateBindingContext[scopeName])) { + // we are out of sync and need to copy + if (!compare(parentValue, lastValue)) { + // parent changed and it has precedence + isolateBindingContext[scopeName] = parentValue; + } else { + // if the parent can be assigned then do so + parentSet(scope, parentValue = isolateBindingContext[scopeName]); + } + } + return lastValue = parentValue; + }; + parentValueWatch.$stateful = true; + var unwatch; + if (definition.collection) { + unwatch = scope.$watchCollection(attrs[attrName], parentValueWatch); + } else { + unwatch = scope.$watch($parse(attrs[attrName], parentValueWatch), null, parentGet.literal); + } + isolateScope.$on('$destroy', unwatch); + break; + + case '&': + parentGet = $parse(attrs[attrName]); + isolateBindingContext[scopeName] = function(locals) { + return parentGet(scope, locals); + }; + break; + } + }); + } + if (controllers) { + forEach(controllers, function(controller) { + controller(); + }); + controllers = null; + } + + // PRELINKING + for (i = 0, ii = preLinkFns.length; i < ii; i++) { + linkFn = preLinkFns[i]; + invokeLinkFn(linkFn, + linkFn.isolateScope ? isolateScope : scope, + $element, + attrs, + linkFn.require && getControllers(linkFn.directiveName, linkFn.require, $element, elementControllers), + transcludeFn + ); + } + + // RECURSION + // We only pass the isolate scope, if the isolate directive has a template, + // otherwise the child elements do not belong to the isolate directive. + var scopeToChild = scope; + if (newIsolateScopeDirective && (newIsolateScopeDirective.template || newIsolateScopeDirective.templateUrl === null)) { + scopeToChild = isolateScope; + } + childLinkFn && childLinkFn(scopeToChild, linkNode.childNodes, undefined, boundTranscludeFn); + + // POSTLINKING + for (i = postLinkFns.length - 1; i >= 0; i--) { + linkFn = postLinkFns[i]; + invokeLinkFn(linkFn, + linkFn.isolateScope ? isolateScope : scope, + $element, + attrs, + linkFn.require && getControllers(linkFn.directiveName, linkFn.require, $element, elementControllers), + transcludeFn + ); + } + + // This is the function that is injected as `$transclude`. + // Note: all arguments are optional! + function controllersBoundTransclude(scope, cloneAttachFn, futureParentElement) { + var transcludeControllers; + + // No scope passed in: + if (!isScope(scope)) { + futureParentElement = cloneAttachFn; + cloneAttachFn = scope; + scope = undefined; + } + + if (hasElementTranscludeDirective) { + transcludeControllers = elementControllers; + } + if (!futureParentElement) { + futureParentElement = hasElementTranscludeDirective ? $element.parent() : $element; + } + return boundTranscludeFn(scope, cloneAttachFn, transcludeControllers, futureParentElement, scopeToChild); + } + } + } + + function markDirectivesAsIsolate(directives) { + // mark all directives as needing isolate scope. + for (var j = 0, jj = directives.length; j < jj; j++) { + directives[j] = inherit(directives[j], {$$isolateScope: true}); + } + } + + /** + * looks up the directive and decorates it with exception handling and proper parameters. We + * call this the boundDirective. + * + * @param {string} name name of the directive to look up. + * @param {string} location The directive must be found in specific format. + * String containing any of theses characters: + * + * * `E`: element name + * * `A': attribute + * * `C`: class + * * `M`: comment + * @returns {boolean} true if directive was added. + */ + function addDirective(tDirectives, name, location, maxPriority, ignoreDirective, startAttrName, + endAttrName) { + if (name === ignoreDirective) return null; + var match = null; + if (hasDirectives.hasOwnProperty(name)) { + for (var directive, directives = $injector.get(name + Suffix), + i = 0, ii = directives.length; i < ii; i++) { + try { + directive = directives[i]; + if ((maxPriority === undefined || maxPriority > directive.priority) && + directive.restrict.indexOf(location) != -1) { + if (startAttrName) { + directive = inherit(directive, {$$start: startAttrName, $$end: endAttrName}); + } + tDirectives.push(directive); + match = directive; + } + } catch (e) { $exceptionHandler(e); } + } + } + return match; + } + + + /** + * looks up the directive and returns true if it is a multi-element directive, + * and therefore requires DOM nodes between -start and -end markers to be grouped + * together. + * + * @param {string} name name of the directive to look up. + * @returns true if directive was registered as multi-element. + */ + function directiveIsMultiElement(name) { + if (hasDirectives.hasOwnProperty(name)) { + for (var directive, directives = $injector.get(name + Suffix), + i = 0, ii = directives.length; i < ii; i++) { + directive = directives[i]; + if (directive.multiElement) { + return true; + } + } + } + return false; + } + + /** + * When the element is replaced with HTML template then the new attributes + * on the template need to be merged with the existing attributes in the DOM. + * The desired effect is to have both of the attributes present. + * + * @param {object} dst destination attributes (original DOM) + * @param {object} src source attributes (from the directive template) + */ + function mergeTemplateAttributes(dst, src) { + var srcAttr = src.$attr, + dstAttr = dst.$attr, + $element = dst.$$element; + + // reapply the old attributes to the new element + forEach(dst, function(value, key) { + if (key.charAt(0) != '$') { + if (src[key] && src[key] !== value) { + value += (key === 'style' ? ';' : ' ') + src[key]; + } + dst.$set(key, value, true, srcAttr[key]); + } + }); + + // copy the new attributes on the old attrs object + forEach(src, function(value, key) { + if (key == 'class') { + safeAddClass($element, value); + dst['class'] = (dst['class'] ? dst['class'] + ' ' : '') + value; + } else if (key == 'style') { + $element.attr('style', $element.attr('style') + ';' + value); + dst['style'] = (dst['style'] ? dst['style'] + ';' : '') + value; + // `dst` will never contain hasOwnProperty as DOM parser won't let it. + // You will get an "InvalidCharacterError: DOM Exception 5" error if you + // have an attribute like "has-own-property" or "data-has-own-property", etc. + } else if (key.charAt(0) != '$' && !dst.hasOwnProperty(key)) { + dst[key] = value; + dstAttr[key] = srcAttr[key]; + } + }); + } + + + function compileTemplateUrl(directives, $compileNode, tAttrs, + $rootElement, childTranscludeFn, preLinkFns, postLinkFns, previousCompileContext) { + var linkQueue = [], + afterTemplateNodeLinkFn, + afterTemplateChildLinkFn, + beforeTemplateCompileNode = $compileNode[0], + origAsyncDirective = directives.shift(), + // The fact that we have to copy and patch the directive seems wrong! + derivedSyncDirective = extend({}, origAsyncDirective, { + templateUrl: null, transclude: null, replace: null, $$originalDirective: origAsyncDirective + }), + templateUrl = (isFunction(origAsyncDirective.templateUrl)) + ? origAsyncDirective.templateUrl($compileNode, tAttrs) + : origAsyncDirective.templateUrl, + templateNamespace = origAsyncDirective.templateNamespace; + + $compileNode.empty(); + + $templateRequest($sce.getTrustedResourceUrl(templateUrl)) + .then(function(content) { + var compileNode, tempTemplateAttrs, $template, childBoundTranscludeFn; + + content = denormalizeTemplate(content); + + if (origAsyncDirective.replace) { + if (jqLiteIsTextNode(content)) { + $template = []; + } else { + $template = removeComments(wrapTemplate(templateNamespace, trim(content))); + } + compileNode = $template[0]; + + if ($template.length != 1 || compileNode.nodeType !== NODE_TYPE_ELEMENT) { + throw $compileMinErr('tplrt', + "Template for directive '{0}' must have exactly one root element. {1}", + origAsyncDirective.name, templateUrl); + } + + tempTemplateAttrs = {$attr: {}}; + replaceWith($rootElement, $compileNode, compileNode); + var templateDirectives = collectDirectives(compileNode, [], tempTemplateAttrs); + + if (isObject(origAsyncDirective.scope)) { + markDirectivesAsIsolate(templateDirectives); + } + directives = templateDirectives.concat(directives); + mergeTemplateAttributes(tAttrs, tempTemplateAttrs); + } else { + compileNode = beforeTemplateCompileNode; + $compileNode.html(content); + } + + directives.unshift(derivedSyncDirective); + + afterTemplateNodeLinkFn = applyDirectivesToNode(directives, compileNode, tAttrs, + childTranscludeFn, $compileNode, origAsyncDirective, preLinkFns, postLinkFns, + previousCompileContext); + forEach($rootElement, function(node, i) { + if (node == compileNode) { + $rootElement[i] = $compileNode[0]; + } + }); + afterTemplateChildLinkFn = compileNodes($compileNode[0].childNodes, childTranscludeFn); + + while (linkQueue.length) { + var scope = linkQueue.shift(), + beforeTemplateLinkNode = linkQueue.shift(), + linkRootElement = linkQueue.shift(), + boundTranscludeFn = linkQueue.shift(), + linkNode = $compileNode[0]; + + if (scope.$$destroyed) continue; + + if (beforeTemplateLinkNode !== beforeTemplateCompileNode) { + var oldClasses = beforeTemplateLinkNode.className; + + if (!(previousCompileContext.hasElementTranscludeDirective && + origAsyncDirective.replace)) { + // it was cloned therefore we have to clone as well. + linkNode = jqLiteClone(compileNode); + } + replaceWith(linkRootElement, jqLite(beforeTemplateLinkNode), linkNode); + + // Copy in CSS classes from original node + safeAddClass(jqLite(linkNode), oldClasses); + } + if (afterTemplateNodeLinkFn.transcludeOnThisElement) { + childBoundTranscludeFn = createBoundTranscludeFn(scope, afterTemplateNodeLinkFn.transclude, boundTranscludeFn); + } else { + childBoundTranscludeFn = boundTranscludeFn; + } + afterTemplateNodeLinkFn(afterTemplateChildLinkFn, scope, linkNode, $rootElement, + childBoundTranscludeFn); + } + linkQueue = null; + }); + + return function delayedNodeLinkFn(ignoreChildLinkFn, scope, node, rootElement, boundTranscludeFn) { + var childBoundTranscludeFn = boundTranscludeFn; + if (scope.$$destroyed) return; + if (linkQueue) { + linkQueue.push(scope, + node, + rootElement, + childBoundTranscludeFn); + } else { + if (afterTemplateNodeLinkFn.transcludeOnThisElement) { + childBoundTranscludeFn = createBoundTranscludeFn(scope, afterTemplateNodeLinkFn.transclude, boundTranscludeFn); + } + afterTemplateNodeLinkFn(afterTemplateChildLinkFn, scope, node, rootElement, childBoundTranscludeFn); + } + }; + } + + + /** + * Sorting function for bound directives. + */ + function byPriority(a, b) { + var diff = b.priority - a.priority; + if (diff !== 0) return diff; + if (a.name !== b.name) return (a.name < b.name) ? -1 : 1; + return a.index - b.index; + } + + + function assertNoDuplicate(what, previousDirective, directive, element) { + if (previousDirective) { + throw $compileMinErr('multidir', 'Multiple directives [{0}, {1}] asking for {2} on: {3}', + previousDirective.name, directive.name, what, startingTag(element)); + } + } + + + function addTextInterpolateDirective(directives, text) { + var interpolateFn = $interpolate(text, true); + if (interpolateFn) { + directives.push({ + priority: 0, + compile: function textInterpolateCompileFn(templateNode) { + var templateNodeParent = templateNode.parent(), + hasCompileParent = !!templateNodeParent.length; + + // When transcluding a template that has bindings in the root + // we don't have a parent and thus need to add the class during linking fn. + if (hasCompileParent) compile.$$addBindingClass(templateNodeParent); + + return function textInterpolateLinkFn(scope, node) { + var parent = node.parent(); + if (!hasCompileParent) compile.$$addBindingClass(parent); + compile.$$addBindingInfo(parent, interpolateFn.expressions); + scope.$watch(interpolateFn, function interpolateFnWatchAction(value) { + node[0].nodeValue = value; + }); + }; + } + }); + } + } + + + function wrapTemplate(type, template) { + type = lowercase(type || 'html'); + switch (type) { + case 'svg': + case 'math': + var wrapper = document.createElement('div'); + wrapper.innerHTML = '<' + type + '>' + template + ''; + return wrapper.childNodes[0].childNodes; + default: + return template; + } + } + + + function getTrustedContext(node, attrNormalizedName) { + if (attrNormalizedName == "srcdoc") { + return $sce.HTML; + } + var tag = nodeName_(node); + // maction[xlink:href] can source SVG. It's not limited to . + if (attrNormalizedName == "xlinkHref" || + (tag == "form" && attrNormalizedName == "action") || + (tag != "img" && (attrNormalizedName == "src" || + attrNormalizedName == "ngSrc"))) { + return $sce.RESOURCE_URL; + } + } + + + function addAttrInterpolateDirective(node, directives, value, name, allOrNothing) { + var trustedContext = getTrustedContext(node, name); + allOrNothing = ALL_OR_NOTHING_ATTRS[name] || allOrNothing; + + var interpolateFn = $interpolate(value, true, trustedContext, allOrNothing); + + // no interpolation found -> ignore + if (!interpolateFn) return; + + + if (name === "multiple" && nodeName_(node) === "select") { + throw $compileMinErr("selmulti", + "Binding to the 'multiple' attribute is not supported. Element: {0}", + startingTag(node)); + } + + directives.push({ + priority: 100, + compile: function() { + return { + pre: function attrInterpolatePreLinkFn(scope, element, attr) { + var $$observers = (attr.$$observers || (attr.$$observers = {})); + + if (EVENT_HANDLER_ATTR_REGEXP.test(name)) { + throw $compileMinErr('nodomevents', + "Interpolations for HTML DOM event attributes are disallowed. Please use the " + + "ng- versions (such as ng-click instead of onclick) instead."); + } + + // If the attribute has changed since last $interpolate()ed + var newValue = attr[name]; + if (newValue !== value) { + // we need to interpolate again since the attribute value has been updated + // (e.g. by another directive's compile function) + // ensure unset/empty values make interpolateFn falsy + interpolateFn = newValue && $interpolate(newValue, true, trustedContext, allOrNothing); + value = newValue; + } + + // if attribute was updated so that there is no interpolation going on we don't want to + // register any observers + if (!interpolateFn) return; + + // initialize attr object so that it's ready in case we need the value for isolate + // scope initialization, otherwise the value would not be available from isolate + // directive's linking fn during linking phase + attr[name] = interpolateFn(scope); + + ($$observers[name] || ($$observers[name] = [])).$$inter = true; + (attr.$$observers && attr.$$observers[name].$$scope || scope). + $watch(interpolateFn, function interpolateFnWatchAction(newValue, oldValue) { + //special case for class attribute addition + removal + //so that class changes can tap into the animation + //hooks provided by the $animate service. Be sure to + //skip animations when the first digest occurs (when + //both the new and the old values are the same) since + //the CSS classes are the non-interpolated values + if (name === 'class' && newValue != oldValue) { + attr.$updateClass(newValue, oldValue); + } else { + attr.$set(name, newValue); + } + }); + } + }; + } + }); + } + + + /** + * This is a special jqLite.replaceWith, which can replace items which + * have no parents, provided that the containing jqLite collection is provided. + * + * @param {JqLite=} $rootElement The root of the compile tree. Used so that we can replace nodes + * in the root of the tree. + * @param {JqLite} elementsToRemove The jqLite element which we are going to replace. We keep + * the shell, but replace its DOM node reference. + * @param {Node} newNode The new DOM node. + */ + function replaceWith($rootElement, elementsToRemove, newNode) { + var firstElementToRemove = elementsToRemove[0], + removeCount = elementsToRemove.length, + parent = firstElementToRemove.parentNode, + i, ii; + + if ($rootElement) { + for (i = 0, ii = $rootElement.length; i < ii; i++) { + if ($rootElement[i] == firstElementToRemove) { + $rootElement[i++] = newNode; + for (var j = i, j2 = j + removeCount - 1, + jj = $rootElement.length; + j < jj; j++, j2++) { + if (j2 < jj) { + $rootElement[j] = $rootElement[j2]; + } else { + delete $rootElement[j]; + } + } + $rootElement.length -= removeCount - 1; + + // If the replaced element is also the jQuery .context then replace it + // .context is a deprecated jQuery api, so we should set it only when jQuery set it + // http://api.jquery.com/context/ + if ($rootElement.context === firstElementToRemove) { + $rootElement.context = newNode; + } + break; + } + } + } + + if (parent) { + parent.replaceChild(newNode, firstElementToRemove); + } + + // TODO(perf): what's this document fragment for? is it needed? can we at least reuse it? + var fragment = document.createDocumentFragment(); + fragment.appendChild(firstElementToRemove); + + // Copy over user data (that includes Angular's $scope etc.). Don't copy private + // data here because there's no public interface in jQuery to do that and copying over + // event listeners (which is the main use of private data) wouldn't work anyway. + jqLite(newNode).data(jqLite(firstElementToRemove).data()); + + // Remove data of the replaced element. We cannot just call .remove() + // on the element it since that would deallocate scope that is needed + // for the new node. Instead, remove the data "manually". + if (!jQuery) { + delete jqLite.cache[firstElementToRemove[jqLite.expando]]; + } else { + // jQuery 2.x doesn't expose the data storage. Use jQuery.cleanData to clean up after + // the replaced element. The cleanData version monkey-patched by Angular would cause + // the scope to be trashed and we do need the very same scope to work with the new + // element. However, we cannot just cache the non-patched version and use it here as + // that would break if another library patches the method after Angular does (one + // example is jQuery UI). Instead, set a flag indicating scope destroying should be + // skipped this one time. + skipDestroyOnNextJQueryCleanData = true; + jQuery.cleanData([firstElementToRemove]); + } + + for (var k = 1, kk = elementsToRemove.length; k < kk; k++) { + var element = elementsToRemove[k]; + jqLite(element).remove(); // must do this way to clean up expando + fragment.appendChild(element); + delete elementsToRemove[k]; + } + + elementsToRemove[0] = newNode; + elementsToRemove.length = 1; + } + + + function cloneAndAnnotateFn(fn, annotation) { + return extend(function() { return fn.apply(null, arguments); }, fn, annotation); + } + + + function invokeLinkFn(linkFn, scope, $element, attrs, controllers, transcludeFn) { + try { + linkFn(scope, $element, attrs, controllers, transcludeFn); + } catch (e) { + $exceptionHandler(e, startingTag($element)); + } + } + }]; +} + +var PREFIX_REGEXP = /^((?:x|data)[\:\-_])/i; +/** + * Converts all accepted directives format into proper directive name. + * @param name Name to normalize + */ +function directiveNormalize(name) { + return camelCase(name.replace(PREFIX_REGEXP, '')); +} + +/** + * @ngdoc type + * @name $compile.directive.Attributes + * + * @description + * A shared object between directive compile / linking functions which contains normalized DOM + * element attributes. The values reflect current binding state `{{ }}`. The normalization is + * needed since all of these are treated as equivalent in Angular: + * + * ``` + * + * ``` + */ + +/** + * @ngdoc property + * @name $compile.directive.Attributes#$attr + * + * @description + * A map of DOM element attribute names to the normalized name. This is + * needed to do reverse lookup from normalized name back to actual name. + */ + + +/** + * @ngdoc method + * @name $compile.directive.Attributes#$set + * @kind function + * + * @description + * Set DOM element attribute value. + * + * + * @param {string} name Normalized element attribute name of the property to modify. The name is + * reverse-translated using the {@link ng.$compile.directive.Attributes#$attr $attr} + * property to the original name. + * @param {string} value Value to set the attribute to. The value can be an interpolated string. + */ + + + +/** + * Closure compiler type information + */ + +function nodesetLinkingFn( + /* angular.Scope */ scope, + /* NodeList */ nodeList, + /* Element */ rootElement, + /* function(Function) */ boundTranscludeFn +) {} + +function directiveLinkingFn( + /* nodesetLinkingFn */ nodesetLinkingFn, + /* angular.Scope */ scope, + /* Node */ node, + /* Element */ rootElement, + /* function(Function) */ boundTranscludeFn +) {} + +function tokenDifference(str1, str2) { + var values = '', + tokens1 = str1.split(/\s+/), + tokens2 = str2.split(/\s+/); + + outer: + for (var i = 0; i < tokens1.length; i++) { + var token = tokens1[i]; + for (var j = 0; j < tokens2.length; j++) { + if (token == tokens2[j]) continue outer; + } + values += (values.length > 0 ? ' ' : '') + token; + } + return values; +} + +function removeComments(jqNodes) { + jqNodes = jqLite(jqNodes); + var i = jqNodes.length; + + if (i <= 1) { + return jqNodes; + } + + while (i--) { + var node = jqNodes[i]; + if (node.nodeType === NODE_TYPE_COMMENT) { + splice.call(jqNodes, i, 1); + } + } + return jqNodes; +} + +/** + * @ngdoc provider + * @name $controllerProvider + * @description + * The {@link ng.$controller $controller service} is used by Angular to create new + * controllers. + * + * This provider allows controller registration via the + * {@link ng.$controllerProvider#register register} method. + */ +function $ControllerProvider() { + var controllers = {}, + globals = false, + CNTRL_REG = /^(\S+)(\s+as\s+(\w+))?$/; + + + /** + * @ngdoc method + * @name $controllerProvider#register + * @param {string|Object} name Controller name, or an object map of controllers where the keys are + * the names and the values are the constructors. + * @param {Function|Array} constructor Controller constructor fn (optionally decorated with DI + * annotations in the array notation). + */ + this.register = function(name, constructor) { + assertNotHasOwnProperty(name, 'controller'); + if (isObject(name)) { + extend(controllers, name); + } else { + controllers[name] = constructor; + } + }; + + /** + * @ngdoc method + * @name $controllerProvider#allowGlobals + * @description If called, allows `$controller` to find controller constructors on `window` + */ + this.allowGlobals = function() { + globals = true; + }; + + + this.$get = ['$injector', '$window', function($injector, $window) { + + /** + * @ngdoc service + * @name $controller + * @requires $injector + * + * @param {Function|string} constructor If called with a function then it's considered to be the + * controller constructor function. Otherwise it's considered to be a string which is used + * to retrieve the controller constructor using the following steps: + * + * * check if a controller with given name is registered via `$controllerProvider` + * * check if evaluating the string on the current scope returns a constructor + * * if $controllerProvider#allowGlobals, check `window[constructor]` on the global + * `window` object (not recommended) + * + * The string can use the `controller as property` syntax, where the controller instance is published + * as the specified property on the `scope`; the `scope` must be injected into `locals` param for this + * to work correctly. + * + * @param {Object} locals Injection locals for Controller. + * @return {Object} Instance of given controller. + * + * @description + * `$controller` service is responsible for instantiating controllers. + * + * It's just a simple call to {@link auto.$injector $injector}, but extracted into + * a service, so that one can override this service with [BC version](https://gist.github.com/1649788). + */ + return function(expression, locals, later, ident) { + // PRIVATE API: + // param `later` --- indicates that the controller's constructor is invoked at a later time. + // If true, $controller will allocate the object with the correct + // prototype chain, but will not invoke the controller until a returned + // callback is invoked. + // param `ident` --- An optional label which overrides the label parsed from the controller + // expression, if any. + var instance, match, constructor, identifier; + later = later === true; + if (ident && isString(ident)) { + identifier = ident; + } + + if (isString(expression)) { + match = expression.match(CNTRL_REG), + constructor = match[1], + identifier = identifier || match[3]; + expression = controllers.hasOwnProperty(constructor) + ? controllers[constructor] + : getter(locals.$scope, constructor, true) || + (globals ? getter($window, constructor, true) : undefined); + + assertArgFn(expression, constructor, true); + } + + if (later) { + // Instantiate controller later: + // This machinery is used to create an instance of the object before calling the + // controller's constructor itself. + // + // This allows properties to be added to the controller before the constructor is + // invoked. Primarily, this is used for isolate scope bindings in $compile. + // + // This feature is not intended for use by applications, and is thus not documented + // publicly. + // Object creation: http://jsperf.com/create-constructor/2 + var controllerPrototype = (isArray(expression) ? + expression[expression.length - 1] : expression).prototype; + instance = Object.create(controllerPrototype); + + if (identifier) { + addIdentifier(locals, identifier, instance, constructor || expression.name); + } + + return extend(function() { + $injector.invoke(expression, instance, locals, constructor); + return instance; + }, { + instance: instance, + identifier: identifier + }); + } + + instance = $injector.instantiate(expression, locals, constructor); + + if (identifier) { + addIdentifier(locals, identifier, instance, constructor || expression.name); + } + + return instance; + }; + + function addIdentifier(locals, identifier, instance, name) { + if (!(locals && isObject(locals.$scope))) { + throw minErr('$controller')('noscp', + "Cannot export controller '{0}' as '{1}'! No $scope object provided via `locals`.", + name, identifier); + } + + locals.$scope[identifier] = instance; + } + }]; +} + +/** + * @ngdoc service + * @name $document + * @requires $window + * + * @description + * A {@link angular.element jQuery or jqLite} wrapper for the browser's `window.document` object. + * + * @example + + +
      +

      $document title:

      +

      window.document title:

      +
      +
      + + angular.module('documentExample', []) + .controller('ExampleController', ['$scope', '$document', function($scope, $document) { + $scope.title = $document[0].title; + $scope.windowTitle = angular.element(window.document)[0].title; + }]); + +
      + */ +function $DocumentProvider() { + this.$get = ['$window', function(window) { + return jqLite(window.document); + }]; +} + +/** + * @ngdoc service + * @name $exceptionHandler + * @requires ng.$log + * + * @description + * Any uncaught exception in angular expressions is delegated to this service. + * The default implementation simply delegates to `$log.error` which logs it into + * the browser console. + * + * In unit tests, if `angular-mocks.js` is loaded, this service is overridden by + * {@link ngMock.$exceptionHandler mock $exceptionHandler} which aids in testing. + * + * ## Example: + * + * ```js + * angular.module('exceptionOverride', []).factory('$exceptionHandler', function() { + * return function(exception, cause) { + * exception.message += ' (caused by "' + cause + '")'; + * throw exception; + * }; + * }); + * ``` + * + * This example will override the normal action of `$exceptionHandler`, to make angular + * exceptions fail hard when they happen, instead of just logging to the console. + * + *
      + * Note, that code executed in event-listeners (even those registered using jqLite's `on`/`bind` + * methods) does not delegate exceptions to the {@link ng.$exceptionHandler $exceptionHandler} + * (unless executed during a digest). + * + * If you wish, you can manually delegate exceptions, e.g. + * `try { ... } catch(e) { $exceptionHandler(e); }` + * + * @param {Error} exception Exception associated with the error. + * @param {string=} cause optional information about the context in which + * the error was thrown. + * + */ +function $ExceptionHandlerProvider() { + this.$get = ['$log', function($log) { + return function(exception, cause) { + $log.error.apply($log, arguments); + }; + }]; +} + +var APPLICATION_JSON = 'application/json'; +var CONTENT_TYPE_APPLICATION_JSON = {'Content-Type': APPLICATION_JSON + ';charset=utf-8'}; +var JSON_START = /^\[|^\{(?!\{)/; +var JSON_ENDS = { + '[': /]$/, + '{': /}$/ +}; +var JSON_PROTECTION_PREFIX = /^\)\]\}',?\n/; + +function defaultHttpResponseTransform(data, headers) { + if (isString(data)) { + // Strip json vulnerability protection prefix and trim whitespace + var tempData = data.replace(JSON_PROTECTION_PREFIX, '').trim(); + + if (tempData) { + var contentType = headers('Content-Type'); + if ((contentType && (contentType.indexOf(APPLICATION_JSON) === 0)) || isJsonLike(tempData)) { + data = fromJson(tempData); + } + } + } + + return data; +} + +function isJsonLike(str) { + var jsonStart = str.match(JSON_START); + return jsonStart && JSON_ENDS[jsonStart[0]].test(str); +} + +/** + * Parse headers into key value object + * + * @param {string} headers Raw headers as a string + * @returns {Object} Parsed headers as key value object + */ +function parseHeaders(headers) { + var parsed = createMap(), key, val, i; + + if (!headers) return parsed; + + forEach(headers.split('\n'), function(line) { + i = line.indexOf(':'); + key = lowercase(trim(line.substr(0, i))); + val = trim(line.substr(i + 1)); + + if (key) { + parsed[key] = parsed[key] ? parsed[key] + ', ' + val : val; + } + }); + + return parsed; +} + + +/** + * Returns a function that provides access to parsed headers. + * + * Headers are lazy parsed when first requested. + * @see parseHeaders + * + * @param {(string|Object)} headers Headers to provide access to. + * @returns {function(string=)} Returns a getter function which if called with: + * + * - if called with single an argument returns a single header value or null + * - if called with no arguments returns an object containing all headers. + */ +function headersGetter(headers) { + var headersObj = isObject(headers) ? headers : undefined; + + return function(name) { + if (!headersObj) headersObj = parseHeaders(headers); + + if (name) { + var value = headersObj[lowercase(name)]; + if (value === void 0) { + value = null; + } + return value; + } + + return headersObj; + }; +} + + +/** + * Chain all given functions + * + * This function is used for both request and response transforming + * + * @param {*} data Data to transform. + * @param {function(string=)} headers HTTP headers getter fn. + * @param {number} status HTTP status code of the response. + * @param {(Function|Array.)} fns Function or an array of functions. + * @returns {*} Transformed data. + */ +function transformData(data, headers, status, fns) { + if (isFunction(fns)) + return fns(data, headers, status); + + forEach(fns, function(fn) { + data = fn(data, headers, status); + }); + + return data; +} + + +function isSuccess(status) { + return 200 <= status && status < 300; +} + + +/** + * @ngdoc provider + * @name $httpProvider + * @description + * Use `$httpProvider` to change the default behavior of the {@link ng.$http $http} service. + * */ +function $HttpProvider() { + /** + * @ngdoc property + * @name $httpProvider#defaults + * @description + * + * Object containing default values for all {@link ng.$http $http} requests. + * + * - **`defaults.cache`** - {Object} - an object built with {@link ng.$cacheFactory `$cacheFactory`} + * that will provide the cache for all requests who set their `cache` property to `true`. + * If you set the `default.cache = false` then only requests that specify their own custom + * cache object will be cached. See {@link $http#caching $http Caching} for more information. + * + * - **`defaults.xsrfCookieName`** - {string} - Name of cookie containing the XSRF token. + * Defaults value is `'XSRF-TOKEN'`. + * + * - **`defaults.xsrfHeaderName`** - {string} - Name of HTTP header to populate with the + * XSRF token. Defaults value is `'X-XSRF-TOKEN'`. + * + * - **`defaults.headers`** - {Object} - Default headers for all $http requests. + * Refer to {@link ng.$http#setting-http-headers $http} for documentation on + * setting default headers. + * - **`defaults.headers.common`** + * - **`defaults.headers.post`** + * - **`defaults.headers.put`** + * - **`defaults.headers.patch`** + * + **/ + var defaults = this.defaults = { + // transform incoming response data + transformResponse: [defaultHttpResponseTransform], + + // transform outgoing request data + transformRequest: [function(d) { + return isObject(d) && !isFile(d) && !isBlob(d) && !isFormData(d) ? toJson(d) : d; + }], + + // default headers + headers: { + common: { + 'Accept': 'application/json, text/plain, */*' + }, + post: shallowCopy(CONTENT_TYPE_APPLICATION_JSON), + put: shallowCopy(CONTENT_TYPE_APPLICATION_JSON), + patch: shallowCopy(CONTENT_TYPE_APPLICATION_JSON) + }, + + xsrfCookieName: 'XSRF-TOKEN', + xsrfHeaderName: 'X-XSRF-TOKEN' + }; + + var useApplyAsync = false; + /** + * @ngdoc method + * @name $httpProvider#useApplyAsync + * @description + * + * Configure $http service to combine processing of multiple http responses received at around + * the same time via {@link ng.$rootScope.Scope#$applyAsync $rootScope.$applyAsync}. This can result in + * significant performance improvement for bigger applications that make many HTTP requests + * concurrently (common during application bootstrap). + * + * Defaults to false. If no value is specifed, returns the current configured value. + * + * @param {boolean=} value If true, when requests are loaded, they will schedule a deferred + * "apply" on the next tick, giving time for subsequent requests in a roughly ~10ms window + * to load and share the same digest cycle. + * + * @returns {boolean|Object} If a value is specified, returns the $httpProvider for chaining. + * otherwise, returns the current configured value. + **/ + this.useApplyAsync = function(value) { + if (isDefined(value)) { + useApplyAsync = !!value; + return this; + } + return useApplyAsync; + }; + + /** + * @ngdoc property + * @name $httpProvider#interceptors + * @description + * + * Array containing service factories for all synchronous or asynchronous {@link ng.$http $http} + * pre-processing of request or postprocessing of responses. + * + * These service factories are ordered by request, i.e. they are applied in the same order as the + * array, on request, but reverse order, on response. + * + * {@link ng.$http#interceptors Interceptors detailed info} + **/ + var interceptorFactories = this.interceptors = []; + + this.$get = ['$httpBackend', '$browser', '$cacheFactory', '$rootScope', '$q', '$injector', + function($httpBackend, $browser, $cacheFactory, $rootScope, $q, $injector) { + + var defaultCache = $cacheFactory('$http'); + + /** + * Interceptors stored in reverse order. Inner interceptors before outer interceptors. + * The reversal is needed so that we can build up the interception chain around the + * server request. + */ + var reversedInterceptors = []; + + forEach(interceptorFactories, function(interceptorFactory) { + reversedInterceptors.unshift(isString(interceptorFactory) + ? $injector.get(interceptorFactory) : $injector.invoke(interceptorFactory)); + }); + + /** + * @ngdoc service + * @kind function + * @name $http + * @requires ng.$httpBackend + * @requires $cacheFactory + * @requires $rootScope + * @requires $q + * @requires $injector + * + * @description + * The `$http` service is a core Angular service that facilitates communication with the remote + * HTTP servers via the browser's [XMLHttpRequest](https://developer.mozilla.org/en/xmlhttprequest) + * object or via [JSONP](http://en.wikipedia.org/wiki/JSONP). + * + * For unit testing applications that use `$http` service, see + * {@link ngMock.$httpBackend $httpBackend mock}. + * + * For a higher level of abstraction, please check out the {@link ngResource.$resource + * $resource} service. + * + * The $http API is based on the {@link ng.$q deferred/promise APIs} exposed by + * the $q service. While for simple usage patterns this doesn't matter much, for advanced usage + * it is important to familiarize yourself with these APIs and the guarantees they provide. + * + * + * ## General usage + * The `$http` service is a function which takes a single argument — a configuration object — + * that is used to generate an HTTP request and returns a {@link ng.$q promise} + * with two $http specific methods: `success` and `error`. + * + * ```js + * // Simple GET request example : + * $http.get('/someUrl'). + * success(function(data, status, headers, config) { + * // this callback will be called asynchronously + * // when the response is available + * }). + * error(function(data, status, headers, config) { + * // called asynchronously if an error occurs + * // or server returns response with an error status. + * }); + * ``` + * + * ```js + * // Simple POST request example (passing data) : + * $http.post('/someUrl', {msg:'hello word!'}). + * success(function(data, status, headers, config) { + * // this callback will be called asynchronously + * // when the response is available + * }). + * error(function(data, status, headers, config) { + * // called asynchronously if an error occurs + * // or server returns response with an error status. + * }); + * ``` + * + * + * Since the returned value of calling the $http function is a `promise`, you can also use + * the `then` method to register callbacks, and these callbacks will receive a single argument – + * an object representing the response. See the API signature and type info below for more + * details. + * + * A response status code between 200 and 299 is considered a success status and + * will result in the success callback being called. Note that if the response is a redirect, + * XMLHttpRequest will transparently follow it, meaning that the error callback will not be + * called for such responses. + * + * ## Writing Unit Tests that use $http + * When unit testing (using {@link ngMock ngMock}), it is necessary to call + * {@link ngMock.$httpBackend#flush $httpBackend.flush()} to flush each pending + * request using trained responses. + * + * ``` + * $httpBackend.expectGET(...); + * $http.get(...); + * $httpBackend.flush(); + * ``` + * + * ## Shortcut methods + * + * Shortcut methods are also available. All shortcut methods require passing in the URL, and + * request data must be passed in for POST/PUT requests. + * + * ```js + * $http.get('/someUrl').success(successCallback); + * $http.post('/someUrl', data).success(successCallback); + * ``` + * + * Complete list of shortcut methods: + * + * - {@link ng.$http#get $http.get} + * - {@link ng.$http#head $http.head} + * - {@link ng.$http#post $http.post} + * - {@link ng.$http#put $http.put} + * - {@link ng.$http#delete $http.delete} + * - {@link ng.$http#jsonp $http.jsonp} + * - {@link ng.$http#patch $http.patch} + * + * + * ## Setting HTTP Headers + * + * The $http service will automatically add certain HTTP headers to all requests. These defaults + * can be fully configured by accessing the `$httpProvider.defaults.headers` configuration + * object, which currently contains this default configuration: + * + * - `$httpProvider.defaults.headers.common` (headers that are common for all requests): + * - `Accept: application/json, text/plain, * / *` + * - `$httpProvider.defaults.headers.post`: (header defaults for POST requests) + * - `Content-Type: application/json` + * - `$httpProvider.defaults.headers.put` (header defaults for PUT requests) + * - `Content-Type: application/json` + * + * To add or overwrite these defaults, simply add or remove a property from these configuration + * objects. To add headers for an HTTP method other than POST or PUT, simply add a new object + * with the lowercased HTTP method name as the key, e.g. + * `$httpProvider.defaults.headers.get = { 'My-Header' : 'value' }. + * + * The defaults can also be set at runtime via the `$http.defaults` object in the same + * fashion. For example: + * + * ``` + * module.run(function($http) { + * $http.defaults.headers.common.Authorization = 'Basic YmVlcDpib29w' + * }); + * ``` + * + * In addition, you can supply a `headers` property in the config object passed when + * calling `$http(config)`, which overrides the defaults without changing them globally. + * + * To explicitly remove a header automatically added via $httpProvider.defaults.headers on a per request basis, + * Use the `headers` property, setting the desired header to `undefined`. For example: + * + * ```js + * var req = { + * method: 'POST', + * url: 'http://example.com', + * headers: { + * 'Content-Type': undefined + * }, + * data: { test: 'test' }, + * } + * + * $http(req).success(function(){...}).error(function(){...}); + * ``` + * + * ## Transforming Requests and Responses + * + * Both requests and responses can be transformed using transformation functions: `transformRequest` + * and `transformResponse`. These properties can be a single function that returns + * the transformed value (`{function(data, headersGetter, status)`) or an array of such transformation functions, + * which allows you to `push` or `unshift` a new transformation function into the transformation chain. + * + * ### Default Transformations + * + * The `$httpProvider` provider and `$http` service expose `defaults.transformRequest` and + * `defaults.transformResponse` properties. If a request does not provide its own transformations + * then these will be applied. + * + * You can augment or replace the default transformations by modifying these properties by adding to or + * replacing the array. + * + * Angular provides the following default transformations: + * + * Request transformations (`$httpProvider.defaults.transformRequest` and `$http.defaults.transformRequest`): + * + * - If the `data` property of the request configuration object contains an object, serialize it + * into JSON format. + * + * Response transformations (`$httpProvider.defaults.transformResponse` and `$http.defaults.transformResponse`): + * + * - If XSRF prefix is detected, strip it (see Security Considerations section below). + * - If JSON response is detected, deserialize it using a JSON parser. + * + * + * ### Overriding the Default Transformations Per Request + * + * If you wish override the request/response transformations only for a single request then provide + * `transformRequest` and/or `transformResponse` properties on the configuration object passed + * into `$http`. + * + * Note that if you provide these properties on the config object the default transformations will be + * overwritten. If you wish to augment the default transformations then you must include them in your + * local transformation array. + * + * The following code demonstrates adding a new response transformation to be run after the default response + * transformations have been run. + * + * ```js + * function appendTransform(defaults, transform) { + * + * // We can't guarantee that the default transformation is an array + * defaults = angular.isArray(defaults) ? defaults : [defaults]; + * + * // Append the new transformation to the defaults + * return defaults.concat(transform); + * } + * + * $http({ + * url: '...', + * method: 'GET', + * transformResponse: appendTransform($http.defaults.transformResponse, function(value) { + * return doTransform(value); + * }) + * }); + * ``` + * + * + * ## Caching + * + * To enable caching, set the request configuration `cache` property to `true` (to use default + * cache) or to a custom cache object (built with {@link ng.$cacheFactory `$cacheFactory`}). + * When the cache is enabled, `$http` stores the response from the server in the specified + * cache. The next time the same request is made, the response is served from the cache without + * sending a request to the server. + * + * Note that even if the response is served from cache, delivery of the data is asynchronous in + * the same way that real requests are. + * + * If there are multiple GET requests for the same URL that should be cached using the same + * cache, but the cache is not populated yet, only one request to the server will be made and + * the remaining requests will be fulfilled using the response from the first request. + * + * You can change the default cache to a new object (built with + * {@link ng.$cacheFactory `$cacheFactory`}) by updating the + * {@link ng.$http#defaults `$http.defaults.cache`} property. All requests who set + * their `cache` property to `true` will now use this cache object. + * + * If you set the default cache to `false` then only requests that specify their own custom + * cache object will be cached. + * + * ## Interceptors + * + * Before you start creating interceptors, be sure to understand the + * {@link ng.$q $q and deferred/promise APIs}. + * + * For purposes of global error handling, authentication, or any kind of synchronous or + * asynchronous pre-processing of request or postprocessing of responses, it is desirable to be + * able to intercept requests before they are handed to the server and + * responses before they are handed over to the application code that + * initiated these requests. The interceptors leverage the {@link ng.$q + * promise APIs} to fulfill this need for both synchronous and asynchronous pre-processing. + * + * The interceptors are service factories that are registered with the `$httpProvider` by + * adding them to the `$httpProvider.interceptors` array. The factory is called and + * injected with dependencies (if specified) and returns the interceptor. + * + * There are two kinds of interceptors (and two kinds of rejection interceptors): + * + * * `request`: interceptors get called with a http `config` object. The function is free to + * modify the `config` object or create a new one. The function needs to return the `config` + * object directly, or a promise containing the `config` or a new `config` object. + * * `requestError`: interceptor gets called when a previous interceptor threw an error or + * resolved with a rejection. + * * `response`: interceptors get called with http `response` object. The function is free to + * modify the `response` object or create a new one. The function needs to return the `response` + * object directly, or as a promise containing the `response` or a new `response` object. + * * `responseError`: interceptor gets called when a previous interceptor threw an error or + * resolved with a rejection. + * + * + * ```js + * // register the interceptor as a service + * $provide.factory('myHttpInterceptor', function($q, dependency1, dependency2) { + * return { + * // optional method + * 'request': function(config) { + * // do something on success + * return config; + * }, + * + * // optional method + * 'requestError': function(rejection) { + * // do something on error + * if (canRecover(rejection)) { + * return responseOrNewPromise + * } + * return $q.reject(rejection); + * }, + * + * + * + * // optional method + * 'response': function(response) { + * // do something on success + * return response; + * }, + * + * // optional method + * 'responseError': function(rejection) { + * // do something on error + * if (canRecover(rejection)) { + * return responseOrNewPromise + * } + * return $q.reject(rejection); + * } + * }; + * }); + * + * $httpProvider.interceptors.push('myHttpInterceptor'); + * + * + * // alternatively, register the interceptor via an anonymous factory + * $httpProvider.interceptors.push(function($q, dependency1, dependency2) { + * return { + * 'request': function(config) { + * // same as above + * }, + * + * 'response': function(response) { + * // same as above + * } + * }; + * }); + * ``` + * + * ## Security Considerations + * + * When designing web applications, consider security threats from: + * + * - [JSON vulnerability](http://haacked.com/archive/2008/11/20/anatomy-of-a-subtle-json-vulnerability.aspx) + * - [XSRF](http://en.wikipedia.org/wiki/Cross-site_request_forgery) + * + * Both server and the client must cooperate in order to eliminate these threats. Angular comes + * pre-configured with strategies that address these issues, but for this to work backend server + * cooperation is required. + * + * ### JSON Vulnerability Protection + * + * A [JSON vulnerability](http://haacked.com/archive/2008/11/20/anatomy-of-a-subtle-json-vulnerability.aspx) + * allows third party website to turn your JSON resource URL into + * [JSONP](http://en.wikipedia.org/wiki/JSONP) request under some conditions. To + * counter this your server can prefix all JSON requests with following string `")]}',\n"`. + * Angular will automatically strip the prefix before processing it as JSON. + * + * For example if your server needs to return: + * ```js + * ['one','two'] + * ``` + * + * which is vulnerable to attack, your server can return: + * ```js + * )]}', + * ['one','two'] + * ``` + * + * Angular will strip the prefix, before processing the JSON. + * + * + * ### Cross Site Request Forgery (XSRF) Protection + * + * [XSRF](http://en.wikipedia.org/wiki/Cross-site_request_forgery) is a technique by which + * an unauthorized site can gain your user's private data. Angular provides a mechanism + * to counter XSRF. When performing XHR requests, the $http service reads a token from a cookie + * (by default, `XSRF-TOKEN`) and sets it as an HTTP header (`X-XSRF-TOKEN`). Since only + * JavaScript that runs on your domain could read the cookie, your server can be assured that + * the XHR came from JavaScript running on your domain. The header will not be set for + * cross-domain requests. + * + * To take advantage of this, your server needs to set a token in a JavaScript readable session + * cookie called `XSRF-TOKEN` on the first HTTP GET request. On subsequent XHR requests the + * server can verify that the cookie matches `X-XSRF-TOKEN` HTTP header, and therefore be sure + * that only JavaScript running on your domain could have sent the request. The token must be + * unique for each user and must be verifiable by the server (to prevent the JavaScript from + * making up its own tokens). We recommend that the token is a digest of your site's + * authentication cookie with a [salt](https://en.wikipedia.org/wiki/Salt_(cryptography)) + * for added security. + * + * The name of the headers can be specified using the xsrfHeaderName and xsrfCookieName + * properties of either $httpProvider.defaults at config-time, $http.defaults at run-time, + * or the per-request config object. + * + * + * @param {object} config Object describing the request to be made and how it should be + * processed. The object has following properties: + * + * - **method** – `{string}` – HTTP method (e.g. 'GET', 'POST', etc) + * - **url** – `{string}` – Absolute or relative URL of the resource that is being requested. + * - **params** – `{Object.}` – Map of strings or objects which will be turned + * to `?key1=value1&key2=value2` after the url. If the value is not a string, it will be + * JSONified. + * - **data** – `{string|Object}` – Data to be sent as the request message data. + * - **headers** – `{Object}` – Map of strings or functions which return strings representing + * HTTP headers to send to the server. If the return value of a function is null, the + * header will not be sent. + * - **xsrfHeaderName** – `{string}` – Name of HTTP header to populate with the XSRF token. + * - **xsrfCookieName** – `{string}` – Name of cookie containing the XSRF token. + * - **transformRequest** – + * `{function(data, headersGetter)|Array.}` – + * transform function or an array of such functions. The transform function takes the http + * request body and headers and returns its transformed (typically serialized) version. + * See {@link ng.$http#overriding-the-default-transformations-per-request + * Overriding the Default Transformations} + * - **transformResponse** – + * `{function(data, headersGetter, status)|Array.}` – + * transform function or an array of such functions. The transform function takes the http + * response body, headers and status and returns its transformed (typically deserialized) version. + * See {@link ng.$http#overriding-the-default-transformations-per-request + * Overriding the Default Transformations} + * - **cache** – `{boolean|Cache}` – If true, a default $http cache will be used to cache the + * GET request, otherwise if a cache instance built with + * {@link ng.$cacheFactory $cacheFactory}, this cache will be used for + * caching. + * - **timeout** – `{number|Promise}` – timeout in milliseconds, or {@link ng.$q promise} + * that should abort the request when resolved. + * - **withCredentials** - `{boolean}` - whether to set the `withCredentials` flag on the + * XHR object. See [requests with credentials](https://developer.mozilla.org/docs/Web/HTTP/Access_control_CORS#Requests_with_credentials) + * for more information. + * - **responseType** - `{string}` - see + * [requestType](https://developer.mozilla.org/en-US/docs/DOM/XMLHttpRequest#responseType). + * + * @returns {HttpPromise} Returns a {@link ng.$q promise} object with the + * standard `then` method and two http specific methods: `success` and `error`. The `then` + * method takes two arguments a success and an error callback which will be called with a + * response object. The `success` and `error` methods take a single argument - a function that + * will be called when the request succeeds or fails respectively. The arguments passed into + * these functions are destructured representation of the response object passed into the + * `then` method. The response object has these properties: + * + * - **data** – `{string|Object}` – The response body transformed with the transform + * functions. + * - **status** – `{number}` – HTTP status code of the response. + * - **headers** – `{function([headerName])}` – Header getter function. + * - **config** – `{Object}` – The configuration object that was used to generate the request. + * - **statusText** – `{string}` – HTTP status text of the response. + * + * @property {Array.} pendingRequests Array of config objects for currently pending + * requests. This is primarily meant to be used for debugging purposes. + * + * + * @example + + +
      + + +
      + + + +
      http status code: {{status}}
      +
      http response data: {{data}}
      +
      +
      + + angular.module('httpExample', []) + .controller('FetchController', ['$scope', '$http', '$templateCache', + function($scope, $http, $templateCache) { + $scope.method = 'GET'; + $scope.url = 'http-hello.html'; + + $scope.fetch = function() { + $scope.code = null; + $scope.response = null; + + $http({method: $scope.method, url: $scope.url, cache: $templateCache}). + success(function(data, status) { + $scope.status = status; + $scope.data = data; + }). + error(function(data, status) { + $scope.data = data || "Request failed"; + $scope.status = status; + }); + }; + + $scope.updateModel = function(method, url) { + $scope.method = method; + $scope.url = url; + }; + }]); + + + Hello, $http! + + + var status = element(by.binding('status')); + var data = element(by.binding('data')); + var fetchBtn = element(by.id('fetchbtn')); + var sampleGetBtn = element(by.id('samplegetbtn')); + var sampleJsonpBtn = element(by.id('samplejsonpbtn')); + var invalidJsonpBtn = element(by.id('invalidjsonpbtn')); + + it('should make an xhr GET request', function() { + sampleGetBtn.click(); + fetchBtn.click(); + expect(status.getText()).toMatch('200'); + expect(data.getText()).toMatch(/Hello, \$http!/); + }); + +// Commented out due to flakes. See https://github.com/angular/angular.js/issues/9185 +// it('should make a JSONP request to angularjs.org', function() { +// sampleJsonpBtn.click(); +// fetchBtn.click(); +// expect(status.getText()).toMatch('200'); +// expect(data.getText()).toMatch(/Super Hero!/); +// }); + + it('should make JSONP request to invalid URL and invoke the error handler', + function() { + invalidJsonpBtn.click(); + fetchBtn.click(); + expect(status.getText()).toMatch('0'); + expect(data.getText()).toMatch('Request failed'); + }); + +
      + */ + function $http(requestConfig) { + + if (!angular.isObject(requestConfig)) { + throw minErr('$http')('badreq', 'Http request configuration must be an object. Received: {0}', requestConfig); + } + + var config = extend({ + method: 'get', + transformRequest: defaults.transformRequest, + transformResponse: defaults.transformResponse + }, requestConfig); + + config.headers = mergeHeaders(requestConfig); + config.method = uppercase(config.method); + + var serverRequest = function(config) { + var headers = config.headers; + var reqData = transformData(config.data, headersGetter(headers), undefined, config.transformRequest); + + // strip content-type if data is undefined + if (isUndefined(reqData)) { + forEach(headers, function(value, header) { + if (lowercase(header) === 'content-type') { + delete headers[header]; + } + }); + } + + if (isUndefined(config.withCredentials) && !isUndefined(defaults.withCredentials)) { + config.withCredentials = defaults.withCredentials; + } + + // send request + return sendReq(config, reqData).then(transformResponse, transformResponse); + }; + + var chain = [serverRequest, undefined]; + var promise = $q.when(config); + + // apply interceptors + forEach(reversedInterceptors, function(interceptor) { + if (interceptor.request || interceptor.requestError) { + chain.unshift(interceptor.request, interceptor.requestError); + } + if (interceptor.response || interceptor.responseError) { + chain.push(interceptor.response, interceptor.responseError); + } + }); + + while (chain.length) { + var thenFn = chain.shift(); + var rejectFn = chain.shift(); + + promise = promise.then(thenFn, rejectFn); + } + + promise.success = function(fn) { + promise.then(function(response) { + fn(response.data, response.status, response.headers, config); + }); + return promise; + }; + + promise.error = function(fn) { + promise.then(null, function(response) { + fn(response.data, response.status, response.headers, config); + }); + return promise; + }; + + return promise; + + function transformResponse(response) { + // make a copy since the response must be cacheable + var resp = extend({}, response); + if (!response.data) { + resp.data = response.data; + } else { + resp.data = transformData(response.data, response.headers, response.status, config.transformResponse); + } + return (isSuccess(response.status)) + ? resp + : $q.reject(resp); + } + + function executeHeaderFns(headers) { + var headerContent, processedHeaders = {}; + + forEach(headers, function(headerFn, header) { + if (isFunction(headerFn)) { + headerContent = headerFn(); + if (headerContent != null) { + processedHeaders[header] = headerContent; + } + } else { + processedHeaders[header] = headerFn; + } + }); + + return processedHeaders; + } + + function mergeHeaders(config) { + var defHeaders = defaults.headers, + reqHeaders = extend({}, config.headers), + defHeaderName, lowercaseDefHeaderName, reqHeaderName; + + defHeaders = extend({}, defHeaders.common, defHeaders[lowercase(config.method)]); + + // using for-in instead of forEach to avoid unecessary iteration after header has been found + defaultHeadersIteration: + for (defHeaderName in defHeaders) { + lowercaseDefHeaderName = lowercase(defHeaderName); + + for (reqHeaderName in reqHeaders) { + if (lowercase(reqHeaderName) === lowercaseDefHeaderName) { + continue defaultHeadersIteration; + } + } + + reqHeaders[defHeaderName] = defHeaders[defHeaderName]; + } + + // execute if header value is a function for merged headers + return executeHeaderFns(reqHeaders); + } + } + + $http.pendingRequests = []; + + /** + * @ngdoc method + * @name $http#get + * + * @description + * Shortcut method to perform `GET` request. + * + * @param {string} url Relative or absolute URL specifying the destination of the request + * @param {Object=} config Optional configuration object + * @returns {HttpPromise} Future object + */ + + /** + * @ngdoc method + * @name $http#delete + * + * @description + * Shortcut method to perform `DELETE` request. + * + * @param {string} url Relative or absolute URL specifying the destination of the request + * @param {Object=} config Optional configuration object + * @returns {HttpPromise} Future object + */ + + /** + * @ngdoc method + * @name $http#head + * + * @description + * Shortcut method to perform `HEAD` request. + * + * @param {string} url Relative or absolute URL specifying the destination of the request + * @param {Object=} config Optional configuration object + * @returns {HttpPromise} Future object + */ + + /** + * @ngdoc method + * @name $http#jsonp + * + * @description + * Shortcut method to perform `JSONP` request. + * + * @param {string} url Relative or absolute URL specifying the destination of the request. + * The name of the callback should be the string `JSON_CALLBACK`. + * @param {Object=} config Optional configuration object + * @returns {HttpPromise} Future object + */ + createShortMethods('get', 'delete', 'head', 'jsonp'); + + /** + * @ngdoc method + * @name $http#post + * + * @description + * Shortcut method to perform `POST` request. + * + * @param {string} url Relative or absolute URL specifying the destination of the request + * @param {*} data Request content + * @param {Object=} config Optional configuration object + * @returns {HttpPromise} Future object + */ + + /** + * @ngdoc method + * @name $http#put + * + * @description + * Shortcut method to perform `PUT` request. + * + * @param {string} url Relative or absolute URL specifying the destination of the request + * @param {*} data Request content + * @param {Object=} config Optional configuration object + * @returns {HttpPromise} Future object + */ + + /** + * @ngdoc method + * @name $http#patch + * + * @description + * Shortcut method to perform `PATCH` request. + * + * @param {string} url Relative or absolute URL specifying the destination of the request + * @param {*} data Request content + * @param {Object=} config Optional configuration object + * @returns {HttpPromise} Future object + */ + createShortMethodsWithData('post', 'put', 'patch'); + + /** + * @ngdoc property + * @name $http#defaults + * + * @description + * Runtime equivalent of the `$httpProvider.defaults` property. Allows configuration of + * default headers, withCredentials as well as request and response transformations. + * + * See "Setting HTTP Headers" and "Transforming Requests and Responses" sections above. + */ + $http.defaults = defaults; + + + return $http; + + + function createShortMethods(names) { + forEach(arguments, function(name) { + $http[name] = function(url, config) { + return $http(extend(config || {}, { + method: name, + url: url + })); + }; + }); + } + + + function createShortMethodsWithData(name) { + forEach(arguments, function(name) { + $http[name] = function(url, data, config) { + return $http(extend(config || {}, { + method: name, + url: url, + data: data + })); + }; + }); + } + + + /** + * Makes the request. + * + * !!! ACCESSES CLOSURE VARS: + * $httpBackend, defaults, $log, $rootScope, defaultCache, $http.pendingRequests + */ + function sendReq(config, reqData) { + var deferred = $q.defer(), + promise = deferred.promise, + cache, + cachedResp, + reqHeaders = config.headers, + url = buildUrl(config.url, config.params); + + $http.pendingRequests.push(config); + promise.then(removePendingReq, removePendingReq); + + + if ((config.cache || defaults.cache) && config.cache !== false && + (config.method === 'GET' || config.method === 'JSONP')) { + cache = isObject(config.cache) ? config.cache + : isObject(defaults.cache) ? defaults.cache + : defaultCache; + } + + if (cache) { + cachedResp = cache.get(url); + if (isDefined(cachedResp)) { + if (isPromiseLike(cachedResp)) { + // cached request has already been sent, but there is no response yet + cachedResp.then(resolvePromiseWithResult, resolvePromiseWithResult); + } else { + // serving from cache + if (isArray(cachedResp)) { + resolvePromise(cachedResp[1], cachedResp[0], shallowCopy(cachedResp[2]), cachedResp[3]); + } else { + resolvePromise(cachedResp, 200, {}, 'OK'); + } + } + } else { + // put the promise for the non-transformed response into cache as a placeholder + cache.put(url, promise); + } + } + + + // if we won't have the response in cache, set the xsrf headers and + // send the request to the backend + if (isUndefined(cachedResp)) { + var xsrfValue = urlIsSameOrigin(config.url) + ? $browser.cookies()[config.xsrfCookieName || defaults.xsrfCookieName] + : undefined; + if (xsrfValue) { + reqHeaders[(config.xsrfHeaderName || defaults.xsrfHeaderName)] = xsrfValue; + } + + $httpBackend(config.method, url, reqData, done, reqHeaders, config.timeout, + config.withCredentials, config.responseType); + } + + return promise; + + + /** + * Callback registered to $httpBackend(): + * - caches the response if desired + * - resolves the raw $http promise + * - calls $apply + */ + function done(status, response, headersString, statusText) { + if (cache) { + if (isSuccess(status)) { + cache.put(url, [status, response, parseHeaders(headersString), statusText]); + } else { + // remove promise from the cache + cache.remove(url); + } + } + + function resolveHttpPromise() { + resolvePromise(response, status, headersString, statusText); + } + + if (useApplyAsync) { + $rootScope.$applyAsync(resolveHttpPromise); + } else { + resolveHttpPromise(); + if (!$rootScope.$$phase) $rootScope.$apply(); + } + } + + + /** + * Resolves the raw $http promise. + */ + function resolvePromise(response, status, headers, statusText) { + // normalize internal statuses to 0 + status = Math.max(status, 0); + + (isSuccess(status) ? deferred.resolve : deferred.reject)({ + data: response, + status: status, + headers: headersGetter(headers), + config: config, + statusText: statusText + }); + } + + function resolvePromiseWithResult(result) { + resolvePromise(result.data, result.status, shallowCopy(result.headers()), result.statusText); + } + + function removePendingReq() { + var idx = $http.pendingRequests.indexOf(config); + if (idx !== -1) $http.pendingRequests.splice(idx, 1); + } + } + + + function buildUrl(url, params) { + if (!params) return url; + var parts = []; + forEachSorted(params, function(value, key) { + if (value === null || isUndefined(value)) return; + if (!isArray(value)) value = [value]; + + forEach(value, function(v) { + if (isObject(v)) { + if (isDate(v)) { + v = v.toISOString(); + } else { + v = toJson(v); + } + } + parts.push(encodeUriQuery(key) + '=' + + encodeUriQuery(v)); + }); + }); + if (parts.length > 0) { + url += ((url.indexOf('?') == -1) ? '?' : '&') + parts.join('&'); + } + return url; + } + }]; +} + +function createXhr() { + return new window.XMLHttpRequest(); +} + +/** + * @ngdoc service + * @name $httpBackend + * @requires $window + * @requires $document + * + * @description + * HTTP backend used by the {@link ng.$http service} that delegates to + * XMLHttpRequest object or JSONP and deals with browser incompatibilities. + * + * You should never need to use this service directly, instead use the higher-level abstractions: + * {@link ng.$http $http} or {@link ngResource.$resource $resource}. + * + * During testing this implementation is swapped with {@link ngMock.$httpBackend mock + * $httpBackend} which can be trained with responses. + */ +function $HttpBackendProvider() { + this.$get = ['$browser', '$window', '$document', function($browser, $window, $document) { + return createHttpBackend($browser, createXhr, $browser.defer, $window.angular.callbacks, $document[0]); + }]; +} + +function createHttpBackend($browser, createXhr, $browserDefer, callbacks, rawDocument) { + // TODO(vojta): fix the signature + return function(method, url, post, callback, headers, timeout, withCredentials, responseType) { + $browser.$$incOutstandingRequestCount(); + url = url || $browser.url(); + + if (lowercase(method) == 'jsonp') { + var callbackId = '_' + (callbacks.counter++).toString(36); + callbacks[callbackId] = function(data) { + callbacks[callbackId].data = data; + callbacks[callbackId].called = true; + }; + + var jsonpDone = jsonpReq(url.replace('JSON_CALLBACK', 'angular.callbacks.' + callbackId), + callbackId, function(status, text) { + completeRequest(callback, status, callbacks[callbackId].data, "", text); + callbacks[callbackId] = noop; + }); + } else { + + var xhr = createXhr(); + + xhr.open(method, url, true); + forEach(headers, function(value, key) { + if (isDefined(value)) { + xhr.setRequestHeader(key, value); + } + }); + + xhr.onload = function requestLoaded() { + var statusText = xhr.statusText || ''; + + // responseText is the old-school way of retrieving response (supported by IE8 & 9) + // response/responseType properties were introduced in XHR Level2 spec (supported by IE10) + var response = ('response' in xhr) ? xhr.response : xhr.responseText; + + // normalize IE9 bug (http://bugs.jquery.com/ticket/1450) + var status = xhr.status === 1223 ? 204 : xhr.status; + + // fix status code when it is 0 (0 status is undocumented). + // Occurs when accessing file resources or on Android 4.1 stock browser + // while retrieving files from application cache. + if (status === 0) { + status = response ? 200 : urlResolve(url).protocol == 'file' ? 404 : 0; + } + + completeRequest(callback, + status, + response, + xhr.getAllResponseHeaders(), + statusText); + }; + + var requestError = function() { + // The response is always empty + // See https://xhr.spec.whatwg.org/#request-error-steps and https://fetch.spec.whatwg.org/#concept-network-error + completeRequest(callback, -1, null, null, ''); + }; + + xhr.onerror = requestError; + xhr.onabort = requestError; + + if (withCredentials) { + xhr.withCredentials = true; + } + + if (responseType) { + try { + xhr.responseType = responseType; + } catch (e) { + // WebKit added support for the json responseType value on 09/03/2013 + // https://bugs.webkit.org/show_bug.cgi?id=73648. Versions of Safari prior to 7 are + // known to throw when setting the value "json" as the response type. Other older + // browsers implementing the responseType + // + // The json response type can be ignored if not supported, because JSON payloads are + // parsed on the client-side regardless. + if (responseType !== 'json') { + throw e; + } + } + } + + xhr.send(post || null); + } + + if (timeout > 0) { + var timeoutId = $browserDefer(timeoutRequest, timeout); + } else if (isPromiseLike(timeout)) { + timeout.then(timeoutRequest); + } + + + function timeoutRequest() { + jsonpDone && jsonpDone(); + xhr && xhr.abort(); + } + + function completeRequest(callback, status, response, headersString, statusText) { + // cancel timeout and subsequent timeout promise resolution + if (timeoutId !== undefined) { + $browserDefer.cancel(timeoutId); + } + jsonpDone = xhr = null; + + callback(status, response, headersString, statusText); + $browser.$$completeOutstandingRequest(noop); + } + }; + + function jsonpReq(url, callbackId, done) { + // we can't use jQuery/jqLite here because jQuery does crazy shit with script elements, e.g.: + // - fetches local scripts via XHR and evals them + // - adds and immediately removes script elements from the document + var script = rawDocument.createElement('script'), callback = null; + script.type = "text/javascript"; + script.src = url; + script.async = true; + + callback = function(event) { + removeEventListenerFn(script, "load", callback); + removeEventListenerFn(script, "error", callback); + rawDocument.body.removeChild(script); + script = null; + var status = -1; + var text = "unknown"; + + if (event) { + if (event.type === "load" && !callbacks[callbackId].called) { + event = { type: "error" }; + } + text = event.type; + status = event.type === "error" ? 404 : 200; + } + + if (done) { + done(status, text); + } + }; + + addEventListenerFn(script, "load", callback); + addEventListenerFn(script, "error", callback); + rawDocument.body.appendChild(script); + return callback; + } +} + +var $interpolateMinErr = minErr('$interpolate'); + +/** + * @ngdoc provider + * @name $interpolateProvider + * + * @description + * + * Used for configuring the interpolation markup. Defaults to `{{` and `}}`. + * + * @example + + + +
      + //demo.label// +
      +
      + + it('should interpolate binding with custom symbols', function() { + expect(element(by.binding('demo.label')).getText()).toBe('This binding is brought you by // interpolation symbols.'); + }); + +
      + */ +function $InterpolateProvider() { + var startSymbol = '{{'; + var endSymbol = '}}'; + + /** + * @ngdoc method + * @name $interpolateProvider#startSymbol + * @description + * Symbol to denote start of expression in the interpolated string. Defaults to `{{`. + * + * @param {string=} value new value to set the starting symbol to. + * @returns {string|self} Returns the symbol when used as getter and self if used as setter. + */ + this.startSymbol = function(value) { + if (value) { + startSymbol = value; + return this; + } else { + return startSymbol; + } + }; + + /** + * @ngdoc method + * @name $interpolateProvider#endSymbol + * @description + * Symbol to denote the end of expression in the interpolated string. Defaults to `}}`. + * + * @param {string=} value new value to set the ending symbol to. + * @returns {string|self} Returns the symbol when used as getter and self if used as setter. + */ + this.endSymbol = function(value) { + if (value) { + endSymbol = value; + return this; + } else { + return endSymbol; + } + }; + + + this.$get = ['$parse', '$exceptionHandler', '$sce', function($parse, $exceptionHandler, $sce) { + var startSymbolLength = startSymbol.length, + endSymbolLength = endSymbol.length, + escapedStartRegexp = new RegExp(startSymbol.replace(/./g, escape), 'g'), + escapedEndRegexp = new RegExp(endSymbol.replace(/./g, escape), 'g'); + + function escape(ch) { + return '\\\\\\' + ch; + } + + /** + * @ngdoc service + * @name $interpolate + * @kind function + * + * @requires $parse + * @requires $sce + * + * @description + * + * Compiles a string with markup into an interpolation function. This service is used by the + * HTML {@link ng.$compile $compile} service for data binding. See + * {@link ng.$interpolateProvider $interpolateProvider} for configuring the + * interpolation markup. + * + * + * ```js + * var $interpolate = ...; // injected + * var exp = $interpolate('Hello {{name | uppercase}}!'); + * expect(exp({name:'Angular'}).toEqual('Hello ANGULAR!'); + * ``` + * + * `$interpolate` takes an optional fourth argument, `allOrNothing`. If `allOrNothing` is + * `true`, the interpolation function will return `undefined` unless all embedded expressions + * evaluate to a value other than `undefined`. + * + * ```js + * var $interpolate = ...; // injected + * var context = {greeting: 'Hello', name: undefined }; + * + * // default "forgiving" mode + * var exp = $interpolate('{{greeting}} {{name}}!'); + * expect(exp(context)).toEqual('Hello !'); + * + * // "allOrNothing" mode + * exp = $interpolate('{{greeting}} {{name}}!', false, null, true); + * expect(exp(context)).toBeUndefined(); + * context.name = 'Angular'; + * expect(exp(context)).toEqual('Hello Angular!'); + * ``` + * + * `allOrNothing` is useful for interpolating URLs. `ngSrc` and `ngSrcset` use this behavior. + * + * ####Escaped Interpolation + * $interpolate provides a mechanism for escaping interpolation markers. Start and end markers + * can be escaped by preceding each of their characters with a REVERSE SOLIDUS U+005C (backslash). + * It will be rendered as a regular start/end marker, and will not be interpreted as an expression + * or binding. + * + * This enables web-servers to prevent script injection attacks and defacing attacks, to some + * degree, while also enabling code examples to work without relying on the + * {@link ng.directive:ngNonBindable ngNonBindable} directive. + * + * **For security purposes, it is strongly encouraged that web servers escape user-supplied data, + * replacing angle brackets (<, >) with &lt; and &gt; respectively, and replacing all + * interpolation start/end markers with their escaped counterparts.** + * + * Escaped interpolation markers are only replaced with the actual interpolation markers in rendered + * output when the $interpolate service processes the text. So, for HTML elements interpolated + * by {@link ng.$compile $compile}, or otherwise interpolated with the `mustHaveExpression` parameter + * set to `true`, the interpolated text must contain an unescaped interpolation expression. As such, + * this is typically useful only when user-data is used in rendering a template from the server, or + * when otherwise untrusted data is used by a directive. + * + * + * + *
      + *

      {{apptitle}}: \{\{ username = "defaced value"; \}\} + *

      + *

      {{username}} attempts to inject code which will deface the + * application, but fails to accomplish their task, because the server has correctly + * escaped the interpolation start/end markers with REVERSE SOLIDUS U+005C (backslash) + * characters.

      + *

      Instead, the result of the attempted script injection is visible, and can be removed + * from the database by an administrator.

      + *
      + *
      + *
      + * + * @param {string} text The text with markup to interpolate. + * @param {boolean=} mustHaveExpression if set to true then the interpolation string must have + * embedded expression in order to return an interpolation function. Strings with no + * embedded expression will return null for the interpolation function. + * @param {string=} trustedContext when provided, the returned function passes the interpolated + * result through {@link ng.$sce#getTrusted $sce.getTrusted(interpolatedResult, + * trustedContext)} before returning it. Refer to the {@link ng.$sce $sce} service that + * provides Strict Contextual Escaping for details. + * @param {boolean=} allOrNothing if `true`, then the returned function returns undefined + * unless all embedded expressions evaluate to a value other than `undefined`. + * @returns {function(context)} an interpolation function which is used to compute the + * interpolated string. The function has these parameters: + * + * - `context`: evaluation context for all expressions embedded in the interpolated text + */ + function $interpolate(text, mustHaveExpression, trustedContext, allOrNothing) { + allOrNothing = !!allOrNothing; + var startIndex, + endIndex, + index = 0, + expressions = [], + parseFns = [], + textLength = text.length, + exp, + concat = [], + expressionPositions = []; + + while (index < textLength) { + if (((startIndex = text.indexOf(startSymbol, index)) != -1) && + ((endIndex = text.indexOf(endSymbol, startIndex + startSymbolLength)) != -1)) { + if (index !== startIndex) { + concat.push(unescapeText(text.substring(index, startIndex))); + } + exp = text.substring(startIndex + startSymbolLength, endIndex); + expressions.push(exp); + parseFns.push($parse(exp, parseStringifyInterceptor)); + index = endIndex + endSymbolLength; + expressionPositions.push(concat.length); + concat.push(''); + } else { + // we did not find an interpolation, so we have to add the remainder to the separators array + if (index !== textLength) { + concat.push(unescapeText(text.substring(index))); + } + break; + } + } + + // Concatenating expressions makes it hard to reason about whether some combination of + // concatenated values are unsafe to use and could easily lead to XSS. By requiring that a + // single expression be used for iframe[src], object[src], etc., we ensure that the value + // that's used is assigned or constructed by some JS code somewhere that is more testable or + // make it obvious that you bound the value to some user controlled value. This helps reduce + // the load when auditing for XSS issues. + if (trustedContext && concat.length > 1) { + throw $interpolateMinErr('noconcat', + "Error while interpolating: {0}\nStrict Contextual Escaping disallows " + + "interpolations that concatenate multiple expressions when a trusted value is " + + "required. See http://docs.angularjs.org/api/ng.$sce", text); + } + + if (!mustHaveExpression || expressions.length) { + var compute = function(values) { + for (var i = 0, ii = expressions.length; i < ii; i++) { + if (allOrNothing && isUndefined(values[i])) return; + concat[expressionPositions[i]] = values[i]; + } + return concat.join(''); + }; + + var getValue = function(value) { + return trustedContext ? + $sce.getTrusted(trustedContext, value) : + $sce.valueOf(value); + }; + + var stringify = function(value) { + if (value == null) { // null || undefined + return ''; + } + switch (typeof value) { + case 'string': + break; + case 'number': + value = '' + value; + break; + default: + value = toJson(value); + } + + return value; + }; + + return extend(function interpolationFn(context) { + var i = 0; + var ii = expressions.length; + var values = new Array(ii); + + try { + for (; i < ii; i++) { + values[i] = parseFns[i](context); + } + + return compute(values); + } catch (err) { + var newErr = $interpolateMinErr('interr', "Can't interpolate: {0}\n{1}", text, + err.toString()); + $exceptionHandler(newErr); + } + + }, { + // all of these properties are undocumented for now + exp: text, //just for compatibility with regular watchers created via $watch + expressions: expressions, + $$watchDelegate: function(scope, listener, objectEquality) { + var lastValue; + return scope.$watchGroup(parseFns, function interpolateFnWatcher(values, oldValues) { + var currValue = compute(values); + if (isFunction(listener)) { + listener.call(this, currValue, values !== oldValues ? lastValue : currValue, scope); + } + lastValue = currValue; + }, objectEquality); + } + }); + } + + function unescapeText(text) { + return text.replace(escapedStartRegexp, startSymbol). + replace(escapedEndRegexp, endSymbol); + } + + function parseStringifyInterceptor(value) { + try { + value = getValue(value); + return allOrNothing && !isDefined(value) ? value : stringify(value); + } catch (err) { + var newErr = $interpolateMinErr('interr', "Can't interpolate: {0}\n{1}", text, + err.toString()); + $exceptionHandler(newErr); + } + } + } + + + /** + * @ngdoc method + * @name $interpolate#startSymbol + * @description + * Symbol to denote the start of expression in the interpolated string. Defaults to `{{`. + * + * Use {@link ng.$interpolateProvider#startSymbol `$interpolateProvider.startSymbol`} to change + * the symbol. + * + * @returns {string} start symbol. + */ + $interpolate.startSymbol = function() { + return startSymbol; + }; + + + /** + * @ngdoc method + * @name $interpolate#endSymbol + * @description + * Symbol to denote the end of expression in the interpolated string. Defaults to `}}`. + * + * Use {@link ng.$interpolateProvider#endSymbol `$interpolateProvider.endSymbol`} to change + * the symbol. + * + * @returns {string} end symbol. + */ + $interpolate.endSymbol = function() { + return endSymbol; + }; + + return $interpolate; + }]; +} + +function $IntervalProvider() { + this.$get = ['$rootScope', '$window', '$q', '$$q', + function($rootScope, $window, $q, $$q) { + var intervals = {}; + + + /** + * @ngdoc service + * @name $interval + * + * @description + * Angular's wrapper for `window.setInterval`. The `fn` function is executed every `delay` + * milliseconds. + * + * The return value of registering an interval function is a promise. This promise will be + * notified upon each tick of the interval, and will be resolved after `count` iterations, or + * run indefinitely if `count` is not defined. The value of the notification will be the + * number of iterations that have run. + * To cancel an interval, call `$interval.cancel(promise)`. + * + * In tests you can use {@link ngMock.$interval#flush `$interval.flush(millis)`} to + * move forward by `millis` milliseconds and trigger any functions scheduled to run in that + * time. + * + *
      + * **Note**: Intervals created by this service must be explicitly destroyed when you are finished + * with them. In particular they are not automatically destroyed when a controller's scope or a + * directive's element are destroyed. + * You should take this into consideration and make sure to always cancel the interval at the + * appropriate moment. See the example below for more details on how and when to do this. + *
      + * + * @param {function()} fn A function that should be called repeatedly. + * @param {number} delay Number of milliseconds between each function call. + * @param {number=} [count=0] Number of times to repeat. If not set, or 0, will repeat + * indefinitely. + * @param {boolean=} [invokeApply=true] If set to `false` skips model dirty checking, otherwise + * will invoke `fn` within the {@link ng.$rootScope.Scope#$apply $apply} block. + * @returns {promise} A promise which will be notified on each iteration. + * + * @example + * + * + * + * + *
      + *
      + * Date format:
      + * Current time is: + *
      + * Blood 1 : {{blood_1}} + * Blood 2 : {{blood_2}} + * + * + * + *
      + *
      + * + *
      + *
      + */ + function interval(fn, delay, count, invokeApply) { + var setInterval = $window.setInterval, + clearInterval = $window.clearInterval, + iteration = 0, + skipApply = (isDefined(invokeApply) && !invokeApply), + deferred = (skipApply ? $$q : $q).defer(), + promise = deferred.promise; + + count = isDefined(count) ? count : 0; + + promise.then(null, null, fn); + + promise.$$intervalId = setInterval(function tick() { + deferred.notify(iteration++); + + if (count > 0 && iteration >= count) { + deferred.resolve(iteration); + clearInterval(promise.$$intervalId); + delete intervals[promise.$$intervalId]; + } + + if (!skipApply) $rootScope.$apply(); + + }, delay); + + intervals[promise.$$intervalId] = deferred; + + return promise; + } + + + /** + * @ngdoc method + * @name $interval#cancel + * + * @description + * Cancels a task associated with the `promise`. + * + * @param {promise} promise returned by the `$interval` function. + * @returns {boolean} Returns `true` if the task was successfully canceled. + */ + interval.cancel = function(promise) { + if (promise && promise.$$intervalId in intervals) { + intervals[promise.$$intervalId].reject('canceled'); + $window.clearInterval(promise.$$intervalId); + delete intervals[promise.$$intervalId]; + return true; + } + return false; + }; + + return interval; + }]; +} + +/** + * @ngdoc service + * @name $locale + * + * @description + * $locale service provides localization rules for various Angular components. As of right now the + * only public api is: + * + * * `id` – `{string}` – locale id formatted as `languageId-countryId` (e.g. `en-us`) + */ +function $LocaleProvider() { + this.$get = function() { + return { + id: 'en-us', + + NUMBER_FORMATS: { + DECIMAL_SEP: '.', + GROUP_SEP: ',', + PATTERNS: [ + { // Decimal Pattern + minInt: 1, + minFrac: 0, + maxFrac: 3, + posPre: '', + posSuf: '', + negPre: '-', + negSuf: '', + gSize: 3, + lgSize: 3 + },{ //Currency Pattern + minInt: 1, + minFrac: 2, + maxFrac: 2, + posPre: '\u00A4', + posSuf: '', + negPre: '(\u00A4', + negSuf: ')', + gSize: 3, + lgSize: 3 + } + ], + CURRENCY_SYM: '$' + }, + + DATETIME_FORMATS: { + MONTH: + 'January,February,March,April,May,June,July,August,September,October,November,December' + .split(','), + SHORTMONTH: 'Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec'.split(','), + DAY: 'Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday'.split(','), + SHORTDAY: 'Sun,Mon,Tue,Wed,Thu,Fri,Sat'.split(','), + AMPMS: ['AM','PM'], + medium: 'MMM d, y h:mm:ss a', + 'short': 'M/d/yy h:mm a', + fullDate: 'EEEE, MMMM d, y', + longDate: 'MMMM d, y', + mediumDate: 'MMM d, y', + shortDate: 'M/d/yy', + mediumTime: 'h:mm:ss a', + shortTime: 'h:mm a' + }, + + pluralCat: function(num) { + if (num === 1) { + return 'one'; + } + return 'other'; + } + }; + }; +} + +var PATH_MATCH = /^([^\?#]*)(\?([^#]*))?(#(.*))?$/, + DEFAULT_PORTS = {'http': 80, 'https': 443, 'ftp': 21}; +var $locationMinErr = minErr('$location'); + + +/** + * Encode path using encodeUriSegment, ignoring forward slashes + * + * @param {string} path Path to encode + * @returns {string} + */ +function encodePath(path) { + var segments = path.split('/'), + i = segments.length; + + while (i--) { + segments[i] = encodeUriSegment(segments[i]); + } + + return segments.join('/'); +} + +function parseAbsoluteUrl(absoluteUrl, locationObj) { + var parsedUrl = urlResolve(absoluteUrl); + + locationObj.$$protocol = parsedUrl.protocol; + locationObj.$$host = parsedUrl.hostname; + locationObj.$$port = int(parsedUrl.port) || DEFAULT_PORTS[parsedUrl.protocol] || null; +} + + +function parseAppUrl(relativeUrl, locationObj) { + var prefixed = (relativeUrl.charAt(0) !== '/'); + if (prefixed) { + relativeUrl = '/' + relativeUrl; + } + var match = urlResolve(relativeUrl); + locationObj.$$path = decodeURIComponent(prefixed && match.pathname.charAt(0) === '/' ? + match.pathname.substring(1) : match.pathname); + locationObj.$$search = parseKeyValue(match.search); + locationObj.$$hash = decodeURIComponent(match.hash); + + // make sure path starts with '/'; + if (locationObj.$$path && locationObj.$$path.charAt(0) != '/') { + locationObj.$$path = '/' + locationObj.$$path; + } +} + + +/** + * + * @param {string} begin + * @param {string} whole + * @returns {string} returns text from whole after begin or undefined if it does not begin with + * expected string. + */ +function beginsWith(begin, whole) { + if (whole.indexOf(begin) === 0) { + return whole.substr(begin.length); + } +} + + +function stripHash(url) { + var index = url.indexOf('#'); + return index == -1 ? url : url.substr(0, index); +} + +function trimEmptyHash(url) { + return url.replace(/(#.+)|#$/, '$1'); +} + + +function stripFile(url) { + return url.substr(0, stripHash(url).lastIndexOf('/') + 1); +} + +/* return the server only (scheme://host:port) */ +function serverBase(url) { + return url.substring(0, url.indexOf('/', url.indexOf('//') + 2)); +} + + +/** + * LocationHtml5Url represents an url + * This object is exposed as $location service when HTML5 mode is enabled and supported + * + * @constructor + * @param {string} appBase application base URL + * @param {string} basePrefix url path prefix + */ +function LocationHtml5Url(appBase, basePrefix) { + this.$$html5 = true; + basePrefix = basePrefix || ''; + var appBaseNoFile = stripFile(appBase); + parseAbsoluteUrl(appBase, this); + + + /** + * Parse given html5 (regular) url string into properties + * @param {string} url HTML5 url + * @private + */ + this.$$parse = function(url) { + var pathUrl = beginsWith(appBaseNoFile, url); + if (!isString(pathUrl)) { + throw $locationMinErr('ipthprfx', 'Invalid url "{0}", missing path prefix "{1}".', url, + appBaseNoFile); + } + + parseAppUrl(pathUrl, this); + + if (!this.$$path) { + this.$$path = '/'; + } + + this.$$compose(); + }; + + /** + * Compose url and update `absUrl` property + * @private + */ + this.$$compose = function() { + var search = toKeyValue(this.$$search), + hash = this.$$hash ? '#' + encodeUriSegment(this.$$hash) : ''; + + this.$$url = encodePath(this.$$path) + (search ? '?' + search : '') + hash; + this.$$absUrl = appBaseNoFile + this.$$url.substr(1); // first char is always '/' + }; + + this.$$parseLinkUrl = function(url, relHref) { + if (relHref && relHref[0] === '#') { + // special case for links to hash fragments: + // keep the old url and only replace the hash fragment + this.hash(relHref.slice(1)); + return true; + } + var appUrl, prevAppUrl; + var rewrittenUrl; + + if ((appUrl = beginsWith(appBase, url)) !== undefined) { + prevAppUrl = appUrl; + if ((appUrl = beginsWith(basePrefix, appUrl)) !== undefined) { + rewrittenUrl = appBaseNoFile + (beginsWith('/', appUrl) || appUrl); + } else { + rewrittenUrl = appBase + prevAppUrl; + } + } else if ((appUrl = beginsWith(appBaseNoFile, url)) !== undefined) { + rewrittenUrl = appBaseNoFile + appUrl; + } else if (appBaseNoFile == url + '/') { + rewrittenUrl = appBaseNoFile; + } + if (rewrittenUrl) { + this.$$parse(rewrittenUrl); + } + return !!rewrittenUrl; + }; +} + + +/** + * LocationHashbangUrl represents url + * This object is exposed as $location service when developer doesn't opt into html5 mode. + * It also serves as the base class for html5 mode fallback on legacy browsers. + * + * @constructor + * @param {string} appBase application base URL + * @param {string} hashPrefix hashbang prefix + */ +function LocationHashbangUrl(appBase, hashPrefix) { + var appBaseNoFile = stripFile(appBase); + + parseAbsoluteUrl(appBase, this); + + + /** + * Parse given hashbang url into properties + * @param {string} url Hashbang url + * @private + */ + this.$$parse = function(url) { + var withoutBaseUrl = beginsWith(appBase, url) || beginsWith(appBaseNoFile, url); + var withoutHashUrl; + + if (withoutBaseUrl.charAt(0) === '#') { + + // The rest of the url starts with a hash so we have + // got either a hashbang path or a plain hash fragment + withoutHashUrl = beginsWith(hashPrefix, withoutBaseUrl); + if (isUndefined(withoutHashUrl)) { + // There was no hashbang prefix so we just have a hash fragment + withoutHashUrl = withoutBaseUrl; + } + + } else { + // There was no hashbang path nor hash fragment: + // If we are in HTML5 mode we use what is left as the path; + // Otherwise we ignore what is left + withoutHashUrl = this.$$html5 ? withoutBaseUrl : ''; + } + + parseAppUrl(withoutHashUrl, this); + + this.$$path = removeWindowsDriveName(this.$$path, withoutHashUrl, appBase); + + this.$$compose(); + + /* + * In Windows, on an anchor node on documents loaded from + * the filesystem, the browser will return a pathname + * prefixed with the drive name ('/C:/path') when a + * pathname without a drive is set: + * * a.setAttribute('href', '/foo') + * * a.pathname === '/C:/foo' //true + * + * Inside of Angular, we're always using pathnames that + * do not include drive names for routing. + */ + function removeWindowsDriveName(path, url, base) { + /* + Matches paths for file protocol on windows, + such as /C:/foo/bar, and captures only /foo/bar. + */ + var windowsFilePathExp = /^\/[A-Z]:(\/.*)/; + + var firstPathSegmentMatch; + + //Get the relative path from the input URL. + if (url.indexOf(base) === 0) { + url = url.replace(base, ''); + } + + // The input URL intentionally contains a first path segment that ends with a colon. + if (windowsFilePathExp.exec(url)) { + return path; + } + + firstPathSegmentMatch = windowsFilePathExp.exec(path); + return firstPathSegmentMatch ? firstPathSegmentMatch[1] : path; + } + }; + + /** + * Compose hashbang url and update `absUrl` property + * @private + */ + this.$$compose = function() { + var search = toKeyValue(this.$$search), + hash = this.$$hash ? '#' + encodeUriSegment(this.$$hash) : ''; + + this.$$url = encodePath(this.$$path) + (search ? '?' + search : '') + hash; + this.$$absUrl = appBase + (this.$$url ? hashPrefix + this.$$url : ''); + }; + + this.$$parseLinkUrl = function(url, relHref) { + if (stripHash(appBase) == stripHash(url)) { + this.$$parse(url); + return true; + } + return false; + }; +} + + +/** + * LocationHashbangUrl represents url + * This object is exposed as $location service when html5 history api is enabled but the browser + * does not support it. + * + * @constructor + * @param {string} appBase application base URL + * @param {string} hashPrefix hashbang prefix + */ +function LocationHashbangInHtml5Url(appBase, hashPrefix) { + this.$$html5 = true; + LocationHashbangUrl.apply(this, arguments); + + var appBaseNoFile = stripFile(appBase); + + this.$$parseLinkUrl = function(url, relHref) { + if (relHref && relHref[0] === '#') { + // special case for links to hash fragments: + // keep the old url and only replace the hash fragment + this.hash(relHref.slice(1)); + return true; + } + + var rewrittenUrl; + var appUrl; + + if (appBase == stripHash(url)) { + rewrittenUrl = url; + } else if ((appUrl = beginsWith(appBaseNoFile, url))) { + rewrittenUrl = appBase + hashPrefix + appUrl; + } else if (appBaseNoFile === url + '/') { + rewrittenUrl = appBaseNoFile; + } + if (rewrittenUrl) { + this.$$parse(rewrittenUrl); + } + return !!rewrittenUrl; + }; + + this.$$compose = function() { + var search = toKeyValue(this.$$search), + hash = this.$$hash ? '#' + encodeUriSegment(this.$$hash) : ''; + + this.$$url = encodePath(this.$$path) + (search ? '?' + search : '') + hash; + // include hashPrefix in $$absUrl when $$url is empty so IE8 & 9 do not reload page because of removal of '#' + this.$$absUrl = appBase + hashPrefix + this.$$url; + }; + +} + + +var locationPrototype = { + + /** + * Are we in html5 mode? + * @private + */ + $$html5: false, + + /** + * Has any change been replacing? + * @private + */ + $$replace: false, + + /** + * @ngdoc method + * @name $location#absUrl + * + * @description + * This method is getter only. + * + * Return full url representation with all segments encoded according to rules specified in + * [RFC 3986](http://www.ietf.org/rfc/rfc3986.txt). + * + * + * ```js + * // given url http://example.com/#/some/path?foo=bar&baz=xoxo + * var absUrl = $location.absUrl(); + * // => "http://example.com/#/some/path?foo=bar&baz=xoxo" + * ``` + * + * @return {string} full url + */ + absUrl: locationGetter('$$absUrl'), + + /** + * @ngdoc method + * @name $location#url + * + * @description + * This method is getter / setter. + * + * Return url (e.g. `/path?a=b#hash`) when called without any parameter. + * + * Change path, search and hash, when called with parameter and return `$location`. + * + * + * ```js + * // given url http://example.com/#/some/path?foo=bar&baz=xoxo + * var url = $location.url(); + * // => "/some/path?foo=bar&baz=xoxo" + * ``` + * + * @param {string=} url New url without base prefix (e.g. `/path?a=b#hash`) + * @return {string} url + */ + url: function(url) { + if (isUndefined(url)) + return this.$$url; + + var match = PATH_MATCH.exec(url); + if (match[1] || url === '') this.path(decodeURIComponent(match[1])); + if (match[2] || match[1] || url === '') this.search(match[3] || ''); + this.hash(match[5] || ''); + + return this; + }, + + /** + * @ngdoc method + * @name $location#protocol + * + * @description + * This method is getter only. + * + * Return protocol of current url. + * + * + * ```js + * // given url http://example.com/#/some/path?foo=bar&baz=xoxo + * var protocol = $location.protocol(); + * // => "http" + * ``` + * + * @return {string} protocol of current url + */ + protocol: locationGetter('$$protocol'), + + /** + * @ngdoc method + * @name $location#host + * + * @description + * This method is getter only. + * + * Return host of current url. + * + * + * ```js + * // given url http://example.com/#/some/path?foo=bar&baz=xoxo + * var host = $location.host(); + * // => "example.com" + * ``` + * + * @return {string} host of current url. + */ + host: locationGetter('$$host'), + + /** + * @ngdoc method + * @name $location#port + * + * @description + * This method is getter only. + * + * Return port of current url. + * + * + * ```js + * // given url http://example.com/#/some/path?foo=bar&baz=xoxo + * var port = $location.port(); + * // => 80 + * ``` + * + * @return {Number} port + */ + port: locationGetter('$$port'), + + /** + * @ngdoc method + * @name $location#path + * + * @description + * This method is getter / setter. + * + * Return path of current url when called without any parameter. + * + * Change path when called with parameter and return `$location`. + * + * Note: Path should always begin with forward slash (/), this method will add the forward slash + * if it is missing. + * + * + * ```js + * // given url http://example.com/#/some/path?foo=bar&baz=xoxo + * var path = $location.path(); + * // => "/some/path" + * ``` + * + * @param {(string|number)=} path New path + * @return {string} path + */ + path: locationGetterSetter('$$path', function(path) { + path = path !== null ? path.toString() : ''; + return path.charAt(0) == '/' ? path : '/' + path; + }), + + /** + * @ngdoc method + * @name $location#search + * + * @description + * This method is getter / setter. + * + * Return search part (as object) of current url when called without any parameter. + * + * Change search part when called with parameter and return `$location`. + * + * + * ```js + * // given url http://example.com/#/some/path?foo=bar&baz=xoxo + * var searchObject = $location.search(); + * // => {foo: 'bar', baz: 'xoxo'} + * + * // set foo to 'yipee' + * $location.search('foo', 'yipee'); + * // $location.search() => {foo: 'yipee', baz: 'xoxo'} + * ``` + * + * @param {string|Object.|Object.>} search New search params - string or + * hash object. + * + * When called with a single argument the method acts as a setter, setting the `search` component + * of `$location` to the specified value. + * + * If the argument is a hash object containing an array of values, these values will be encoded + * as duplicate search parameters in the url. + * + * @param {(string|Number|Array|boolean)=} paramValue If `search` is a string or number, then `paramValue` + * will override only a single search property. + * + * If `paramValue` is an array, it will override the property of the `search` component of + * `$location` specified via the first argument. + * + * If `paramValue` is `null`, the property specified via the first argument will be deleted. + * + * If `paramValue` is `true`, the property specified via the first argument will be added with no + * value nor trailing equal sign. + * + * @return {Object} If called with no arguments returns the parsed `search` object. If called with + * one or more arguments returns `$location` object itself. + */ + search: function(search, paramValue) { + switch (arguments.length) { + case 0: + return this.$$search; + case 1: + if (isString(search) || isNumber(search)) { + search = search.toString(); + this.$$search = parseKeyValue(search); + } else if (isObject(search)) { + search = copy(search, {}); + // remove object undefined or null properties + forEach(search, function(value, key) { + if (value == null) delete search[key]; + }); + + this.$$search = search; + } else { + throw $locationMinErr('isrcharg', + 'The first argument of the `$location#search()` call must be a string or an object.'); + } + break; + default: + if (isUndefined(paramValue) || paramValue === null) { + delete this.$$search[search]; + } else { + this.$$search[search] = paramValue; + } + } + + this.$$compose(); + return this; + }, + + /** + * @ngdoc method + * @name $location#hash + * + * @description + * This method is getter / setter. + * + * Return hash fragment when called without any parameter. + * + * Change hash fragment when called with parameter and return `$location`. + * + * + * ```js + * // given url http://example.com/#/some/path?foo=bar&baz=xoxo#hashValue + * var hash = $location.hash(); + * // => "hashValue" + * ``` + * + * @param {(string|number)=} hash New hash fragment + * @return {string} hash + */ + hash: locationGetterSetter('$$hash', function(hash) { + return hash !== null ? hash.toString() : ''; + }), + + /** + * @ngdoc method + * @name $location#replace + * + * @description + * If called, all changes to $location during current `$digest` will be replacing current history + * record, instead of adding new one. + */ + replace: function() { + this.$$replace = true; + return this; + } +}; + +forEach([LocationHashbangInHtml5Url, LocationHashbangUrl, LocationHtml5Url], function(Location) { + Location.prototype = Object.create(locationPrototype); + + /** + * @ngdoc method + * @name $location#state + * + * @description + * This method is getter / setter. + * + * Return the history state object when called without any parameter. + * + * Change the history state object when called with one parameter and return `$location`. + * The state object is later passed to `pushState` or `replaceState`. + * + * NOTE: This method is supported only in HTML5 mode and only in browsers supporting + * the HTML5 History API (i.e. methods `pushState` and `replaceState`). If you need to support + * older browsers (like IE9 or Android < 4.0), don't use this method. + * + * @param {object=} state State object for pushState or replaceState + * @return {object} state + */ + Location.prototype.state = function(state) { + if (!arguments.length) + return this.$$state; + + if (Location !== LocationHtml5Url || !this.$$html5) { + throw $locationMinErr('nostate', 'History API state support is available only ' + + 'in HTML5 mode and only in browsers supporting HTML5 History API'); + } + // The user might modify `stateObject` after invoking `$location.state(stateObject)` + // but we're changing the $$state reference to $browser.state() during the $digest + // so the modification window is narrow. + this.$$state = isUndefined(state) ? null : state; + + return this; + }; +}); + + +function locationGetter(property) { + return function() { + return this[property]; + }; +} + + +function locationGetterSetter(property, preprocess) { + return function(value) { + if (isUndefined(value)) + return this[property]; + + this[property] = preprocess(value); + this.$$compose(); + + return this; + }; +} + + +/** + * @ngdoc service + * @name $location + * + * @requires $rootElement + * + * @description + * The $location service parses the URL in the browser address bar (based on the + * [window.location](https://developer.mozilla.org/en/window.location)) and makes the URL + * available to your application. Changes to the URL in the address bar are reflected into + * $location service and changes to $location are reflected into the browser address bar. + * + * **The $location service:** + * + * - Exposes the current URL in the browser address bar, so you can + * - Watch and observe the URL. + * - Change the URL. + * - Synchronizes the URL with the browser when the user + * - Changes the address bar. + * - Clicks the back or forward button (or clicks a History link). + * - Clicks on a link. + * - Represents the URL object as a set of methods (protocol, host, port, path, search, hash). + * + * For more information see {@link guide/$location Developer Guide: Using $location} + */ + +/** + * @ngdoc provider + * @name $locationProvider + * @description + * Use the `$locationProvider` to configure how the application deep linking paths are stored. + */ +function $LocationProvider() { + var hashPrefix = '', + html5Mode = { + enabled: false, + requireBase: true, + rewriteLinks: true + }; + + /** + * @ngdoc method + * @name $locationProvider#hashPrefix + * @description + * @param {string=} prefix Prefix for hash part (containing path and search) + * @returns {*} current value if used as getter or itself (chaining) if used as setter + */ + this.hashPrefix = function(prefix) { + if (isDefined(prefix)) { + hashPrefix = prefix; + return this; + } else { + return hashPrefix; + } + }; + + /** + * @ngdoc method + * @name $locationProvider#html5Mode + * @description + * @param {(boolean|Object)=} mode If boolean, sets `html5Mode.enabled` to value. + * If object, sets `enabled`, `requireBase` and `rewriteLinks` to respective values. Supported + * properties: + * - **enabled** – `{boolean}` – (default: false) If true, will rely on `history.pushState` to + * change urls where supported. Will fall back to hash-prefixed paths in browsers that do not + * support `pushState`. + * - **requireBase** - `{boolean}` - (default: `true`) When html5Mode is enabled, specifies + * whether or not a tag is required to be present. If `enabled` and `requireBase` are + * true, and a base tag is not present, an error will be thrown when `$location` is injected. + * See the {@link guide/$location $location guide for more information} + * - **rewriteLinks** - `{boolean}` - (default: `true`) When html5Mode is enabled, + * enables/disables url rewriting for relative links. + * + * @returns {Object} html5Mode object if used as getter or itself (chaining) if used as setter + */ + this.html5Mode = function(mode) { + if (isBoolean(mode)) { + html5Mode.enabled = mode; + return this; + } else if (isObject(mode)) { + + if (isBoolean(mode.enabled)) { + html5Mode.enabled = mode.enabled; + } + + if (isBoolean(mode.requireBase)) { + html5Mode.requireBase = mode.requireBase; + } + + if (isBoolean(mode.rewriteLinks)) { + html5Mode.rewriteLinks = mode.rewriteLinks; + } + + return this; + } else { + return html5Mode; + } + }; + + /** + * @ngdoc event + * @name $location#$locationChangeStart + * @eventType broadcast on root scope + * @description + * Broadcasted before a URL will change. + * + * This change can be prevented by calling + * `preventDefault` method of the event. See {@link ng.$rootScope.Scope#$on} for more + * details about event object. Upon successful change + * {@link ng.$location#$locationChangeSuccess $locationChangeSuccess} is fired. + * + * The `newState` and `oldState` parameters may be defined only in HTML5 mode and when + * the browser supports the HTML5 History API. + * + * @param {Object} angularEvent Synthetic event object. + * @param {string} newUrl New URL + * @param {string=} oldUrl URL that was before it was changed. + * @param {string=} newState New history state object + * @param {string=} oldState History state object that was before it was changed. + */ + + /** + * @ngdoc event + * @name $location#$locationChangeSuccess + * @eventType broadcast on root scope + * @description + * Broadcasted after a URL was changed. + * + * The `newState` and `oldState` parameters may be defined only in HTML5 mode and when + * the browser supports the HTML5 History API. + * + * @param {Object} angularEvent Synthetic event object. + * @param {string} newUrl New URL + * @param {string=} oldUrl URL that was before it was changed. + * @param {string=} newState New history state object + * @param {string=} oldState History state object that was before it was changed. + */ + + this.$get = ['$rootScope', '$browser', '$sniffer', '$rootElement', '$window', + function($rootScope, $browser, $sniffer, $rootElement, $window) { + var $location, + LocationMode, + baseHref = $browser.baseHref(), // if base[href] is undefined, it defaults to '' + initialUrl = $browser.url(), + appBase; + + if (html5Mode.enabled) { + if (!baseHref && html5Mode.requireBase) { + throw $locationMinErr('nobase', + "$location in HTML5 mode requires a tag to be present!"); + } + appBase = serverBase(initialUrl) + (baseHref || '/'); + LocationMode = $sniffer.history ? LocationHtml5Url : LocationHashbangInHtml5Url; + } else { + appBase = stripHash(initialUrl); + LocationMode = LocationHashbangUrl; + } + $location = new LocationMode(appBase, '#' + hashPrefix); + $location.$$parseLinkUrl(initialUrl, initialUrl); + + $location.$$state = $browser.state(); + + var IGNORE_URI_REGEXP = /^\s*(javascript|mailto):/i; + + function setBrowserUrlWithFallback(url, replace, state) { + var oldUrl = $location.url(); + var oldState = $location.$$state; + try { + $browser.url(url, replace, state); + + // Make sure $location.state() returns referentially identical (not just deeply equal) + // state object; this makes possible quick checking if the state changed in the digest + // loop. Checking deep equality would be too expensive. + $location.$$state = $browser.state(); + } catch (e) { + // Restore old values if pushState fails + $location.url(oldUrl); + $location.$$state = oldState; + + throw e; + } + } + + $rootElement.on('click', function(event) { + // TODO(vojta): rewrite link when opening in new tab/window (in legacy browser) + // currently we open nice url link and redirect then + + if (!html5Mode.rewriteLinks || event.ctrlKey || event.metaKey || event.which == 2) return; + + var elm = jqLite(event.target); + + // traverse the DOM up to find first A tag + while (nodeName_(elm[0]) !== 'a') { + // ignore rewriting if no A tag (reached root element, or no parent - removed from document) + if (elm[0] === $rootElement[0] || !(elm = elm.parent())[0]) return; + } + + var absHref = elm.prop('href'); + // get the actual href attribute - see + // http://msdn.microsoft.com/en-us/library/ie/dd347148(v=vs.85).aspx + var relHref = elm.attr('href') || elm.attr('xlink:href'); + + if (isObject(absHref) && absHref.toString() === '[object SVGAnimatedString]') { + // SVGAnimatedString.animVal should be identical to SVGAnimatedString.baseVal, unless during + // an animation. + absHref = urlResolve(absHref.animVal).href; + } + + // Ignore when url is started with javascript: or mailto: + if (IGNORE_URI_REGEXP.test(absHref)) return; + + if (absHref && !elm.attr('target') && !event.isDefaultPrevented()) { + if ($location.$$parseLinkUrl(absHref, relHref)) { + // We do a preventDefault for all urls that are part of the angular application, + // in html5mode and also without, so that we are able to abort navigation without + // getting double entries in the location history. + event.preventDefault(); + // update location manually + if ($location.absUrl() != $browser.url()) { + $rootScope.$apply(); + // hack to work around FF6 bug 684208 when scenario runner clicks on links + $window.angular['ff-684208-preventDefault'] = true; + } + } + } + }); + + + // rewrite hashbang url <> html5 url + if ($location.absUrl() != initialUrl) { + $browser.url($location.absUrl(), true); + } + + var initializing = true; + + // update $location when $browser url changes + $browser.onUrlChange(function(newUrl, newState) { + $rootScope.$evalAsync(function() { + var oldUrl = $location.absUrl(); + var oldState = $location.$$state; + var defaultPrevented; + + $location.$$parse(newUrl); + $location.$$state = newState; + + defaultPrevented = $rootScope.$broadcast('$locationChangeStart', newUrl, oldUrl, + newState, oldState).defaultPrevented; + + // if the location was changed by a `$locationChangeStart` handler then stop + // processing this location change + if ($location.absUrl() !== newUrl) return; + + if (defaultPrevented) { + $location.$$parse(oldUrl); + $location.$$state = oldState; + setBrowserUrlWithFallback(oldUrl, false, oldState); + } else { + initializing = false; + afterLocationChange(oldUrl, oldState); + } + }); + if (!$rootScope.$$phase) $rootScope.$digest(); + }); + + // update browser + $rootScope.$watch(function $locationWatch() { + var oldUrl = trimEmptyHash($browser.url()); + var newUrl = trimEmptyHash($location.absUrl()); + var oldState = $browser.state(); + var currentReplace = $location.$$replace; + var urlOrStateChanged = oldUrl !== newUrl || + ($location.$$html5 && $sniffer.history && oldState !== $location.$$state); + + if (initializing || urlOrStateChanged) { + initializing = false; + + $rootScope.$evalAsync(function() { + var newUrl = $location.absUrl(); + var defaultPrevented = $rootScope.$broadcast('$locationChangeStart', newUrl, oldUrl, + $location.$$state, oldState).defaultPrevented; + + // if the location was changed by a `$locationChangeStart` handler then stop + // processing this location change + if ($location.absUrl() !== newUrl) return; + + if (defaultPrevented) { + $location.$$parse(oldUrl); + $location.$$state = oldState; + } else { + if (urlOrStateChanged) { + setBrowserUrlWithFallback(newUrl, currentReplace, + oldState === $location.$$state ? null : $location.$$state); + } + afterLocationChange(oldUrl, oldState); + } + }); + } + + $location.$$replace = false; + + // we don't need to return anything because $evalAsync will make the digest loop dirty when + // there is a change + }); + + return $location; + + function afterLocationChange(oldUrl, oldState) { + $rootScope.$broadcast('$locationChangeSuccess', $location.absUrl(), oldUrl, + $location.$$state, oldState); + } +}]; +} + +/** + * @ngdoc service + * @name $log + * @requires $window + * + * @description + * Simple service for logging. Default implementation safely writes the message + * into the browser's console (if present). + * + * The main purpose of this service is to simplify debugging and troubleshooting. + * + * The default is to log `debug` messages. You can use + * {@link ng.$logProvider ng.$logProvider#debugEnabled} to change this. + * + * @example + + + angular.module('logExample', []) + .controller('LogController', ['$scope', '$log', function($scope, $log) { + $scope.$log = $log; + $scope.message = 'Hello World!'; + }]); + + +
      +

      Reload this page with open console, enter text and hit the log button...

      + Message: + + + + + +
      +
      +
      + */ + +/** + * @ngdoc provider + * @name $logProvider + * @description + * Use the `$logProvider` to configure how the application logs messages + */ +function $LogProvider() { + var debug = true, + self = this; + + /** + * @ngdoc method + * @name $logProvider#debugEnabled + * @description + * @param {boolean=} flag enable or disable debug level messages + * @returns {*} current value if used as getter or itself (chaining) if used as setter + */ + this.debugEnabled = function(flag) { + if (isDefined(flag)) { + debug = flag; + return this; + } else { + return debug; + } + }; + + this.$get = ['$window', function($window) { + return { + /** + * @ngdoc method + * @name $log#log + * + * @description + * Write a log message + */ + log: consoleLog('log'), + + /** + * @ngdoc method + * @name $log#info + * + * @description + * Write an information message + */ + info: consoleLog('info'), + + /** + * @ngdoc method + * @name $log#warn + * + * @description + * Write a warning message + */ + warn: consoleLog('warn'), + + /** + * @ngdoc method + * @name $log#error + * + * @description + * Write an error message + */ + error: consoleLog('error'), + + /** + * @ngdoc method + * @name $log#debug + * + * @description + * Write a debug message + */ + debug: (function() { + var fn = consoleLog('debug'); + + return function() { + if (debug) { + fn.apply(self, arguments); + } + }; + }()) + }; + + function formatError(arg) { + if (arg instanceof Error) { + if (arg.stack) { + arg = (arg.message && arg.stack.indexOf(arg.message) === -1) + ? 'Error: ' + arg.message + '\n' + arg.stack + : arg.stack; + } else if (arg.sourceURL) { + arg = arg.message + '\n' + arg.sourceURL + ':' + arg.line; + } + } + return arg; + } + + function consoleLog(type) { + var console = $window.console || {}, + logFn = console[type] || console.log || noop, + hasApply = false; + + // Note: reading logFn.apply throws an error in IE11 in IE8 document mode. + // The reason behind this is that console.log has type "object" in IE8... + try { + hasApply = !!logFn.apply; + } catch (e) {} + + if (hasApply) { + return function() { + var args = []; + forEach(arguments, function(arg) { + args.push(formatError(arg)); + }); + return logFn.apply(console, args); + }; + } + + // we are IE which either doesn't have window.console => this is noop and we do nothing, + // or we are IE where console.log doesn't have apply so we log at least first 2 args + return function(arg1, arg2) { + logFn(arg1, arg2 == null ? '' : arg2); + }; + } + }]; +} + +var $parseMinErr = minErr('$parse'); + +// Sandboxing Angular Expressions +// ------------------------------ +// Angular expressions are generally considered safe because these expressions only have direct +// access to `$scope` and locals. However, one can obtain the ability to execute arbitrary JS code by +// obtaining a reference to native JS functions such as the Function constructor. +// +// As an example, consider the following Angular expression: +// +// {}.toString.constructor('alert("evil JS code")') +// +// This sandboxing technique is not perfect and doesn't aim to be. The goal is to prevent exploits +// against the expression language, but not to prevent exploits that were enabled by exposing +// sensitive JavaScript or browser APIs on Scope. Exposing such objects on a Scope is never a good +// practice and therefore we are not even trying to protect against interaction with an object +// explicitly exposed in this way. +// +// In general, it is not possible to access a Window object from an angular expression unless a +// window or some DOM object that has a reference to window is published onto a Scope. +// Similarly we prevent invocations of function known to be dangerous, as well as assignments to +// native objects. +// +// See https://docs.angularjs.org/guide/security + + +function ensureSafeMemberName(name, fullExpression) { + if (name === "__defineGetter__" || name === "__defineSetter__" + || name === "__lookupGetter__" || name === "__lookupSetter__" + || name === "__proto__") { + throw $parseMinErr('isecfld', + 'Attempting to access a disallowed field in Angular expressions! ' + + 'Expression: {0}', fullExpression); + } + return name; +} + +function ensureSafeObject(obj, fullExpression) { + // nifty check if obj is Function that is fast and works across iframes and other contexts + if (obj) { + if (obj.constructor === obj) { + throw $parseMinErr('isecfn', + 'Referencing Function in Angular expressions is disallowed! Expression: {0}', + fullExpression); + } else if (// isWindow(obj) + obj.window === obj) { + throw $parseMinErr('isecwindow', + 'Referencing the Window in Angular expressions is disallowed! Expression: {0}', + fullExpression); + } else if (// isElement(obj) + obj.children && (obj.nodeName || (obj.prop && obj.attr && obj.find))) { + throw $parseMinErr('isecdom', + 'Referencing DOM nodes in Angular expressions is disallowed! Expression: {0}', + fullExpression); + } else if (// block Object so that we can't get hold of dangerous Object.* methods + obj === Object) { + throw $parseMinErr('isecobj', + 'Referencing Object in Angular expressions is disallowed! Expression: {0}', + fullExpression); + } + } + return obj; +} + +var CALL = Function.prototype.call; +var APPLY = Function.prototype.apply; +var BIND = Function.prototype.bind; + +function ensureSafeFunction(obj, fullExpression) { + if (obj) { + if (obj.constructor === obj) { + throw $parseMinErr('isecfn', + 'Referencing Function in Angular expressions is disallowed! Expression: {0}', + fullExpression); + } else if (obj === CALL || obj === APPLY || obj === BIND) { + throw $parseMinErr('isecff', + 'Referencing call, apply or bind in Angular expressions is disallowed! Expression: {0}', + fullExpression); + } + } +} + +//Keyword constants +var CONSTANTS = createMap(); +forEach({ + 'null': function() { return null; }, + 'true': function() { return true; }, + 'false': function() { return false; }, + 'undefined': function() {} +}, function(constantGetter, name) { + constantGetter.constant = constantGetter.literal = constantGetter.sharedGetter = true; + CONSTANTS[name] = constantGetter; +}); + +//Not quite a constant, but can be lex/parsed the same +CONSTANTS['this'] = function(self) { return self; }; +CONSTANTS['this'].sharedGetter = true; + + +//Operators - will be wrapped by binaryFn/unaryFn/assignment/filter +var OPERATORS = extend(createMap(), { + '+':function(self, locals, a, b) { + a=a(self, locals); b=b(self, locals); + if (isDefined(a)) { + if (isDefined(b)) { + return a + b; + } + return a; + } + return isDefined(b) ? b : undefined;}, + '-':function(self, locals, a, b) { + a=a(self, locals); b=b(self, locals); + return (isDefined(a) ? a : 0) - (isDefined(b) ? b : 0); + }, + '*':function(self, locals, a, b) {return a(self, locals) * b(self, locals);}, + '/':function(self, locals, a, b) {return a(self, locals) / b(self, locals);}, + '%':function(self, locals, a, b) {return a(self, locals) % b(self, locals);}, + '===':function(self, locals, a, b) {return a(self, locals) === b(self, locals);}, + '!==':function(self, locals, a, b) {return a(self, locals) !== b(self, locals);}, + '==':function(self, locals, a, b) {return a(self, locals) == b(self, locals);}, + '!=':function(self, locals, a, b) {return a(self, locals) != b(self, locals);}, + '<':function(self, locals, a, b) {return a(self, locals) < b(self, locals);}, + '>':function(self, locals, a, b) {return a(self, locals) > b(self, locals);}, + '<=':function(self, locals, a, b) {return a(self, locals) <= b(self, locals);}, + '>=':function(self, locals, a, b) {return a(self, locals) >= b(self, locals);}, + '&&':function(self, locals, a, b) {return a(self, locals) && b(self, locals);}, + '||':function(self, locals, a, b) {return a(self, locals) || b(self, locals);}, + '!':function(self, locals, a) {return !a(self, locals);}, + + //Tokenized as operators but parsed as assignment/filters + '=':true, + '|':true +}); +var ESCAPE = {"n":"\n", "f":"\f", "r":"\r", "t":"\t", "v":"\v", "'":"'", '"':'"'}; + + +///////////////////////////////////////// + + +/** + * @constructor + */ +var Lexer = function(options) { + this.options = options; +}; + +Lexer.prototype = { + constructor: Lexer, + + lex: function(text) { + this.text = text; + this.index = 0; + this.tokens = []; + + while (this.index < this.text.length) { + var ch = this.text.charAt(this.index); + if (ch === '"' || ch === "'") { + this.readString(ch); + } else if (this.isNumber(ch) || ch === '.' && this.isNumber(this.peek())) { + this.readNumber(); + } else if (this.isIdent(ch)) { + this.readIdent(); + } else if (this.is(ch, '(){}[].,;:?')) { + this.tokens.push({index: this.index, text: ch}); + this.index++; + } else if (this.isWhitespace(ch)) { + this.index++; + } else { + var ch2 = ch + this.peek(); + var ch3 = ch2 + this.peek(2); + var op1 = OPERATORS[ch]; + var op2 = OPERATORS[ch2]; + var op3 = OPERATORS[ch3]; + if (op1 || op2 || op3) { + var token = op3 ? ch3 : (op2 ? ch2 : ch); + this.tokens.push({index: this.index, text: token, operator: true}); + this.index += token.length; + } else { + this.throwError('Unexpected next character ', this.index, this.index + 1); + } + } + } + return this.tokens; + }, + + is: function(ch, chars) { + return chars.indexOf(ch) !== -1; + }, + + peek: function(i) { + var num = i || 1; + return (this.index + num < this.text.length) ? this.text.charAt(this.index + num) : false; + }, + + isNumber: function(ch) { + return ('0' <= ch && ch <= '9') && typeof ch === "string"; + }, + + isWhitespace: function(ch) { + // IE treats non-breaking space as \u00A0 + return (ch === ' ' || ch === '\r' || ch === '\t' || + ch === '\n' || ch === '\v' || ch === '\u00A0'); + }, + + isIdent: function(ch) { + return ('a' <= ch && ch <= 'z' || + 'A' <= ch && ch <= 'Z' || + '_' === ch || ch === '$'); + }, + + isExpOperator: function(ch) { + return (ch === '-' || ch === '+' || this.isNumber(ch)); + }, + + throwError: function(error, start, end) { + end = end || this.index; + var colStr = (isDefined(start) + ? 's ' + start + '-' + this.index + ' [' + this.text.substring(start, end) + ']' + : ' ' + end); + throw $parseMinErr('lexerr', 'Lexer Error: {0} at column{1} in expression [{2}].', + error, colStr, this.text); + }, + + readNumber: function() { + var number = ''; + var start = this.index; + while (this.index < this.text.length) { + var ch = lowercase(this.text.charAt(this.index)); + if (ch == '.' || this.isNumber(ch)) { + number += ch; + } else { + var peekCh = this.peek(); + if (ch == 'e' && this.isExpOperator(peekCh)) { + number += ch; + } else if (this.isExpOperator(ch) && + peekCh && this.isNumber(peekCh) && + number.charAt(number.length - 1) == 'e') { + number += ch; + } else if (this.isExpOperator(ch) && + (!peekCh || !this.isNumber(peekCh)) && + number.charAt(number.length - 1) == 'e') { + this.throwError('Invalid exponent'); + } else { + break; + } + } + this.index++; + } + this.tokens.push({ + index: start, + text: number, + constant: true, + value: Number(number) + }); + }, + + readIdent: function() { + var start = this.index; + while (this.index < this.text.length) { + var ch = this.text.charAt(this.index); + if (!(this.isIdent(ch) || this.isNumber(ch))) { + break; + } + this.index++; + } + this.tokens.push({ + index: start, + text: this.text.slice(start, this.index), + identifier: true + }); + }, + + readString: function(quote) { + var start = this.index; + this.index++; + var string = ''; + var rawString = quote; + var escape = false; + while (this.index < this.text.length) { + var ch = this.text.charAt(this.index); + rawString += ch; + if (escape) { + if (ch === 'u') { + var hex = this.text.substring(this.index + 1, this.index + 5); + if (!hex.match(/[\da-f]{4}/i)) + this.throwError('Invalid unicode escape [\\u' + hex + ']'); + this.index += 4; + string += String.fromCharCode(parseInt(hex, 16)); + } else { + var rep = ESCAPE[ch]; + string = string + (rep || ch); + } + escape = false; + } else if (ch === '\\') { + escape = true; + } else if (ch === quote) { + this.index++; + this.tokens.push({ + index: start, + text: rawString, + constant: true, + value: string + }); + return; + } else { + string += ch; + } + this.index++; + } + this.throwError('Unterminated quote', start); + } +}; + + +function isConstant(exp) { + return exp.constant; +} + +/** + * @constructor + */ +var Parser = function(lexer, $filter, options) { + this.lexer = lexer; + this.$filter = $filter; + this.options = options; +}; + +Parser.ZERO = extend(function() { + return 0; +}, { + sharedGetter: true, + constant: true +}); + +Parser.prototype = { + constructor: Parser, + + parse: function(text) { + this.text = text; + this.tokens = this.lexer.lex(text); + + var value = this.statements(); + + if (this.tokens.length !== 0) { + this.throwError('is an unexpected token', this.tokens[0]); + } + + value.literal = !!value.literal; + value.constant = !!value.constant; + + return value; + }, + + primary: function() { + var primary; + if (this.expect('(')) { + primary = this.filterChain(); + this.consume(')'); + } else if (this.expect('[')) { + primary = this.arrayDeclaration(); + } else if (this.expect('{')) { + primary = this.object(); + } else if (this.peek().identifier && this.peek().text in CONSTANTS) { + primary = CONSTANTS[this.consume().text]; + } else if (this.peek().identifier) { + primary = this.identifier(); + } else if (this.peek().constant) { + primary = this.constant(); + } else { + this.throwError('not a primary expression', this.peek()); + } + + var next, context; + while ((next = this.expect('(', '[', '.'))) { + if (next.text === '(') { + primary = this.functionCall(primary, context); + context = null; + } else if (next.text === '[') { + context = primary; + primary = this.objectIndex(primary); + } else if (next.text === '.') { + context = primary; + primary = this.fieldAccess(primary); + } else { + this.throwError('IMPOSSIBLE'); + } + } + return primary; + }, + + throwError: function(msg, token) { + throw $parseMinErr('syntax', + 'Syntax Error: Token \'{0}\' {1} at column {2} of the expression [{3}] starting at [{4}].', + token.text, msg, (token.index + 1), this.text, this.text.substring(token.index)); + }, + + peekToken: function() { + if (this.tokens.length === 0) + throw $parseMinErr('ueoe', 'Unexpected end of expression: {0}', this.text); + return this.tokens[0]; + }, + + peek: function(e1, e2, e3, e4) { + return this.peekAhead(0, e1, e2, e3, e4); + }, + peekAhead: function(i, e1, e2, e3, e4) { + if (this.tokens.length > i) { + var token = this.tokens[i]; + var t = token.text; + if (t === e1 || t === e2 || t === e3 || t === e4 || + (!e1 && !e2 && !e3 && !e4)) { + return token; + } + } + return false; + }, + + expect: function(e1, e2, e3, e4) { + var token = this.peek(e1, e2, e3, e4); + if (token) { + this.tokens.shift(); + return token; + } + return false; + }, + + consume: function(e1) { + if (this.tokens.length === 0) { + throw $parseMinErr('ueoe', 'Unexpected end of expression: {0}', this.text); + } + + var token = this.expect(e1); + if (!token) { + this.throwError('is unexpected, expecting [' + e1 + ']', this.peek()); + } + return token; + }, + + unaryFn: function(op, right) { + var fn = OPERATORS[op]; + return extend(function $parseUnaryFn(self, locals) { + return fn(self, locals, right); + }, { + constant:right.constant, + inputs: [right] + }); + }, + + binaryFn: function(left, op, right, isBranching) { + var fn = OPERATORS[op]; + return extend(function $parseBinaryFn(self, locals) { + return fn(self, locals, left, right); + }, { + constant: left.constant && right.constant, + inputs: !isBranching && [left, right] + }); + }, + + identifier: function() { + var id = this.consume().text; + + //Continue reading each `.identifier` unless it is a method invocation + while (this.peek('.') && this.peekAhead(1).identifier && !this.peekAhead(2, '(')) { + id += this.consume().text + this.consume().text; + } + + return getterFn(id, this.options, this.text); + }, + + constant: function() { + var value = this.consume().value; + + return extend(function $parseConstant() { + return value; + }, { + constant: true, + literal: true + }); + }, + + statements: function() { + var statements = []; + while (true) { + if (this.tokens.length > 0 && !this.peek('}', ')', ';', ']')) + statements.push(this.filterChain()); + if (!this.expect(';')) { + // optimize for the common case where there is only one statement. + // TODO(size): maybe we should not support multiple statements? + return (statements.length === 1) + ? statements[0] + : function $parseStatements(self, locals) { + var value; + for (var i = 0, ii = statements.length; i < ii; i++) { + value = statements[i](self, locals); + } + return value; + }; + } + } + }, + + filterChain: function() { + var left = this.expression(); + var token; + while ((token = this.expect('|'))) { + left = this.filter(left); + } + return left; + }, + + filter: function(inputFn) { + var fn = this.$filter(this.consume().text); + var argsFn; + var args; + + if (this.peek(':')) { + argsFn = []; + args = []; // we can safely reuse the array + while (this.expect(':')) { + argsFn.push(this.expression()); + } + } + + var inputs = [inputFn].concat(argsFn || []); + + return extend(function $parseFilter(self, locals) { + var input = inputFn(self, locals); + if (args) { + args[0] = input; + + var i = argsFn.length; + while (i--) { + args[i + 1] = argsFn[i](self, locals); + } + + return fn.apply(undefined, args); + } + + return fn(input); + }, { + constant: !fn.$stateful && inputs.every(isConstant), + inputs: !fn.$stateful && inputs + }); + }, + + expression: function() { + return this.assignment(); + }, + + assignment: function() { + var left = this.ternary(); + var right; + var token; + if ((token = this.expect('='))) { + if (!left.assign) { + this.throwError('implies assignment but [' + + this.text.substring(0, token.index) + '] can not be assigned to', token); + } + right = this.ternary(); + return extend(function $parseAssignment(scope, locals) { + return left.assign(scope, right(scope, locals), locals); + }, { + inputs: [left, right] + }); + } + return left; + }, + + ternary: function() { + var left = this.logicalOR(); + var middle; + var token; + if ((token = this.expect('?'))) { + middle = this.assignment(); + if (this.consume(':')) { + var right = this.assignment(); + + return extend(function $parseTernary(self, locals) { + return left(self, locals) ? middle(self, locals) : right(self, locals); + }, { + constant: left.constant && middle.constant && right.constant + }); + } + } + + return left; + }, + + logicalOR: function() { + var left = this.logicalAND(); + var token; + while ((token = this.expect('||'))) { + left = this.binaryFn(left, token.text, this.logicalAND(), true); + } + return left; + }, + + logicalAND: function() { + var left = this.equality(); + var token; + while ((token = this.expect('&&'))) { + left = this.binaryFn(left, token.text, this.equality(), true); + } + return left; + }, + + equality: function() { + var left = this.relational(); + var token; + while ((token = this.expect('==','!=','===','!=='))) { + left = this.binaryFn(left, token.text, this.relational()); + } + return left; + }, + + relational: function() { + var left = this.additive(); + var token; + while ((token = this.expect('<', '>', '<=', '>='))) { + left = this.binaryFn(left, token.text, this.additive()); + } + return left; + }, + + additive: function() { + var left = this.multiplicative(); + var token; + while ((token = this.expect('+','-'))) { + left = this.binaryFn(left, token.text, this.multiplicative()); + } + return left; + }, + + multiplicative: function() { + var left = this.unary(); + var token; + while ((token = this.expect('*','/','%'))) { + left = this.binaryFn(left, token.text, this.unary()); + } + return left; + }, + + unary: function() { + var token; + if (this.expect('+')) { + return this.primary(); + } else if ((token = this.expect('-'))) { + return this.binaryFn(Parser.ZERO, token.text, this.unary()); + } else if ((token = this.expect('!'))) { + return this.unaryFn(token.text, this.unary()); + } else { + return this.primary(); + } + }, + + fieldAccess: function(object) { + var getter = this.identifier(); + + return extend(function $parseFieldAccess(scope, locals, self) { + var o = self || object(scope, locals); + return (o == null) ? undefined : getter(o); + }, { + assign: function(scope, value, locals) { + var o = object(scope, locals); + if (!o) object.assign(scope, o = {}); + return getter.assign(o, value); + } + }); + }, + + objectIndex: function(obj) { + var expression = this.text; + + var indexFn = this.expression(); + this.consume(']'); + + return extend(function $parseObjectIndex(self, locals) { + var o = obj(self, locals), + i = indexFn(self, locals), + v; + + ensureSafeMemberName(i, expression); + if (!o) return undefined; + v = ensureSafeObject(o[i], expression); + return v; + }, { + assign: function(self, value, locals) { + var key = ensureSafeMemberName(indexFn(self, locals), expression); + // prevent overwriting of Function.constructor which would break ensureSafeObject check + var o = ensureSafeObject(obj(self, locals), expression); + if (!o) obj.assign(self, o = {}); + return o[key] = value; + } + }); + }, + + functionCall: function(fnGetter, contextGetter) { + var argsFn = []; + if (this.peekToken().text !== ')') { + do { + argsFn.push(this.expression()); + } while (this.expect(',')); + } + this.consume(')'); + + var expressionText = this.text; + // we can safely reuse the array across invocations + var args = argsFn.length ? [] : null; + + return function $parseFunctionCall(scope, locals) { + var context = contextGetter ? contextGetter(scope, locals) : isDefined(contextGetter) ? undefined : scope; + var fn = fnGetter(scope, locals, context) || noop; + + if (args) { + var i = argsFn.length; + while (i--) { + args[i] = ensureSafeObject(argsFn[i](scope, locals), expressionText); + } + } + + ensureSafeObject(context, expressionText); + ensureSafeFunction(fn, expressionText); + + // IE doesn't have apply for some native functions + var v = fn.apply + ? fn.apply(context, args) + : fn(args[0], args[1], args[2], args[3], args[4]); + + return ensureSafeObject(v, expressionText); + }; + }, + + // This is used with json array declaration + arrayDeclaration: function() { + var elementFns = []; + if (this.peekToken().text !== ']') { + do { + if (this.peek(']')) { + // Support trailing commas per ES5.1. + break; + } + elementFns.push(this.expression()); + } while (this.expect(',')); + } + this.consume(']'); + + return extend(function $parseArrayLiteral(self, locals) { + var array = []; + for (var i = 0, ii = elementFns.length; i < ii; i++) { + array.push(elementFns[i](self, locals)); + } + return array; + }, { + literal: true, + constant: elementFns.every(isConstant), + inputs: elementFns + }); + }, + + object: function() { + var keys = [], valueFns = []; + if (this.peekToken().text !== '}') { + do { + if (this.peek('}')) { + // Support trailing commas per ES5.1. + break; + } + var token = this.consume(); + if (token.constant) { + keys.push(token.value); + } else if (token.identifier) { + keys.push(token.text); + } else { + this.throwError("invalid key", token); + } + this.consume(':'); + valueFns.push(this.expression()); + } while (this.expect(',')); + } + this.consume('}'); + + return extend(function $parseObjectLiteral(self, locals) { + var object = {}; + for (var i = 0, ii = valueFns.length; i < ii; i++) { + object[keys[i]] = valueFns[i](self, locals); + } + return object; + }, { + literal: true, + constant: valueFns.every(isConstant), + inputs: valueFns + }); + } +}; + + +////////////////////////////////////////////////// +// Parser helper functions +////////////////////////////////////////////////// + +function setter(obj, path, setValue, fullExp) { + ensureSafeObject(obj, fullExp); + + var element = path.split('.'), key; + for (var i = 0; element.length > 1; i++) { + key = ensureSafeMemberName(element.shift(), fullExp); + var propertyObj = ensureSafeObject(obj[key], fullExp); + if (!propertyObj) { + propertyObj = {}; + obj[key] = propertyObj; + } + obj = propertyObj; + } + key = ensureSafeMemberName(element.shift(), fullExp); + ensureSafeObject(obj[key], fullExp); + obj[key] = setValue; + return setValue; +} + +var getterFnCacheDefault = createMap(); +var getterFnCacheExpensive = createMap(); + +function isPossiblyDangerousMemberName(name) { + return name == 'constructor'; +} + +/** + * Implementation of the "Black Hole" variant from: + * - http://jsperf.com/angularjs-parse-getter/4 + * - http://jsperf.com/path-evaluation-simplified/7 + */ +function cspSafeGetterFn(key0, key1, key2, key3, key4, fullExp, expensiveChecks) { + ensureSafeMemberName(key0, fullExp); + ensureSafeMemberName(key1, fullExp); + ensureSafeMemberName(key2, fullExp); + ensureSafeMemberName(key3, fullExp); + ensureSafeMemberName(key4, fullExp); + var eso = function(o) { + return ensureSafeObject(o, fullExp); + }; + var eso0 = (expensiveChecks || isPossiblyDangerousMemberName(key0)) ? eso : identity; + var eso1 = (expensiveChecks || isPossiblyDangerousMemberName(key1)) ? eso : identity; + var eso2 = (expensiveChecks || isPossiblyDangerousMemberName(key2)) ? eso : identity; + var eso3 = (expensiveChecks || isPossiblyDangerousMemberName(key3)) ? eso : identity; + var eso4 = (expensiveChecks || isPossiblyDangerousMemberName(key4)) ? eso : identity; + + return function cspSafeGetter(scope, locals) { + var pathVal = (locals && locals.hasOwnProperty(key0)) ? locals : scope; + + if (pathVal == null) return pathVal; + pathVal = eso0(pathVal[key0]); + + if (!key1) return pathVal; + if (pathVal == null) return undefined; + pathVal = eso1(pathVal[key1]); + + if (!key2) return pathVal; + if (pathVal == null) return undefined; + pathVal = eso2(pathVal[key2]); + + if (!key3) return pathVal; + if (pathVal == null) return undefined; + pathVal = eso3(pathVal[key3]); + + if (!key4) return pathVal; + if (pathVal == null) return undefined; + pathVal = eso4(pathVal[key4]); + + return pathVal; + }; +} + +function getterFnWithEnsureSafeObject(fn, fullExpression) { + return function(s, l) { + return fn(s, l, ensureSafeObject, fullExpression); + }; +} + +function getterFn(path, options, fullExp) { + var expensiveChecks = options.expensiveChecks; + var getterFnCache = (expensiveChecks ? getterFnCacheExpensive : getterFnCacheDefault); + var fn = getterFnCache[path]; + if (fn) return fn; + + + var pathKeys = path.split('.'), + pathKeysLength = pathKeys.length; + + // http://jsperf.com/angularjs-parse-getter/6 + if (options.csp) { + if (pathKeysLength < 6) { + fn = cspSafeGetterFn(pathKeys[0], pathKeys[1], pathKeys[2], pathKeys[3], pathKeys[4], fullExp, expensiveChecks); + } else { + fn = function cspSafeGetter(scope, locals) { + var i = 0, val; + do { + val = cspSafeGetterFn(pathKeys[i++], pathKeys[i++], pathKeys[i++], pathKeys[i++], + pathKeys[i++], fullExp, expensiveChecks)(scope, locals); + + locals = undefined; // clear after first iteration + scope = val; + } while (i < pathKeysLength); + return val; + }; + } + } else { + var code = ''; + if (expensiveChecks) { + code += 's = eso(s, fe);\nl = eso(l, fe);\n'; + } + var needsEnsureSafeObject = expensiveChecks; + forEach(pathKeys, function(key, index) { + ensureSafeMemberName(key, fullExp); + var lookupJs = (index + // we simply dereference 's' on any .dot notation + ? 's' + // but if we are first then we check locals first, and if so read it first + : '((l&&l.hasOwnProperty("' + key + '"))?l:s)') + '.' + key; + if (expensiveChecks || isPossiblyDangerousMemberName(key)) { + lookupJs = 'eso(' + lookupJs + ', fe)'; + needsEnsureSafeObject = true; + } + code += 'if(s == null) return undefined;\n' + + 's=' + lookupJs + ';\n'; + }); + code += 'return s;'; + + /* jshint -W054 */ + var evaledFnGetter = new Function('s', 'l', 'eso', 'fe', code); // s=scope, l=locals, eso=ensureSafeObject + /* jshint +W054 */ + evaledFnGetter.toString = valueFn(code); + if (needsEnsureSafeObject) { + evaledFnGetter = getterFnWithEnsureSafeObject(evaledFnGetter, fullExp); + } + fn = evaledFnGetter; + } + + fn.sharedGetter = true; + fn.assign = function(self, value) { + return setter(self, path, value, path); + }; + getterFnCache[path] = fn; + return fn; +} + +var objectValueOf = Object.prototype.valueOf; + +function getValueOf(value) { + return isFunction(value.valueOf) ? value.valueOf() : objectValueOf.call(value); +} + +/////////////////////////////////// + +/** + * @ngdoc service + * @name $parse + * @kind function + * + * @description + * + * Converts Angular {@link guide/expression expression} into a function. + * + * ```js + * var getter = $parse('user.name'); + * var setter = getter.assign; + * var context = {user:{name:'angular'}}; + * var locals = {user:{name:'local'}}; + * + * expect(getter(context)).toEqual('angular'); + * setter(context, 'newValue'); + * expect(context.user.name).toEqual('newValue'); + * expect(getter(context, locals)).toEqual('local'); + * ``` + * + * + * @param {string} expression String expression to compile. + * @returns {function(context, locals)} a function which represents the compiled expression: + * + * * `context` – `{object}` – an object against which any expressions embedded in the strings + * are evaluated against (typically a scope object). + * * `locals` – `{object=}` – local variables context object, useful for overriding values in + * `context`. + * + * The returned function also has the following properties: + * * `literal` – `{boolean}` – whether the expression's top-level node is a JavaScript + * literal. + * * `constant` – `{boolean}` – whether the expression is made entirely of JavaScript + * constant literals. + * * `assign` – `{?function(context, value)}` – if the expression is assignable, this will be + * set to a function to change its value on the given context. + * + */ + + +/** + * @ngdoc provider + * @name $parseProvider + * + * @description + * `$parseProvider` can be used for configuring the default behavior of the {@link ng.$parse $parse} + * service. + */ +function $ParseProvider() { + var cacheDefault = createMap(); + var cacheExpensive = createMap(); + + + + this.$get = ['$filter', '$sniffer', function($filter, $sniffer) { + var $parseOptions = { + csp: $sniffer.csp, + expensiveChecks: false + }, + $parseOptionsExpensive = { + csp: $sniffer.csp, + expensiveChecks: true + }; + + function wrapSharedExpression(exp) { + var wrapped = exp; + + if (exp.sharedGetter) { + wrapped = function $parseWrapper(self, locals) { + return exp(self, locals); + }; + wrapped.literal = exp.literal; + wrapped.constant = exp.constant; + wrapped.assign = exp.assign; + } + + return wrapped; + } + + return function $parse(exp, interceptorFn, expensiveChecks) { + var parsedExpression, oneTime, cacheKey; + + switch (typeof exp) { + case 'string': + cacheKey = exp = exp.trim(); + + var cache = (expensiveChecks ? cacheExpensive : cacheDefault); + parsedExpression = cache[cacheKey]; + + if (!parsedExpression) { + if (exp.charAt(0) === ':' && exp.charAt(1) === ':') { + oneTime = true; + exp = exp.substring(2); + } + + var parseOptions = expensiveChecks ? $parseOptionsExpensive : $parseOptions; + var lexer = new Lexer(parseOptions); + var parser = new Parser(lexer, $filter, parseOptions); + parsedExpression = parser.parse(exp); + + if (parsedExpression.constant) { + parsedExpression.$$watchDelegate = constantWatchDelegate; + } else if (oneTime) { + //oneTime is not part of the exp passed to the Parser so we may have to + //wrap the parsedExpression before adding a $$watchDelegate + parsedExpression = wrapSharedExpression(parsedExpression); + parsedExpression.$$watchDelegate = parsedExpression.literal ? + oneTimeLiteralWatchDelegate : oneTimeWatchDelegate; + } else if (parsedExpression.inputs) { + parsedExpression.$$watchDelegate = inputsWatchDelegate; + } + + cache[cacheKey] = parsedExpression; + } + return addInterceptor(parsedExpression, interceptorFn); + + case 'function': + return addInterceptor(exp, interceptorFn); + + default: + return addInterceptor(noop, interceptorFn); + } + }; + + function collectExpressionInputs(inputs, list) { + for (var i = 0, ii = inputs.length; i < ii; i++) { + var input = inputs[i]; + if (!input.constant) { + if (input.inputs) { + collectExpressionInputs(input.inputs, list); + } else if (list.indexOf(input) === -1) { // TODO(perf) can we do better? + list.push(input); + } + } + } + + return list; + } + + function expressionInputDirtyCheck(newValue, oldValueOfValue) { + + if (newValue == null || oldValueOfValue == null) { // null/undefined + return newValue === oldValueOfValue; + } + + if (typeof newValue === 'object') { + + // attempt to convert the value to a primitive type + // TODO(docs): add a note to docs that by implementing valueOf even objects and arrays can + // be cheaply dirty-checked + newValue = getValueOf(newValue); + + if (typeof newValue === 'object') { + // objects/arrays are not supported - deep-watching them would be too expensive + return false; + } + + // fall-through to the primitive equality check + } + + //Primitive or NaN + return newValue === oldValueOfValue || (newValue !== newValue && oldValueOfValue !== oldValueOfValue); + } + + function inputsWatchDelegate(scope, listener, objectEquality, parsedExpression) { + var inputExpressions = parsedExpression.$$inputs || + (parsedExpression.$$inputs = collectExpressionInputs(parsedExpression.inputs, [])); + + var lastResult; + + if (inputExpressions.length === 1) { + var oldInputValue = expressionInputDirtyCheck; // init to something unique so that equals check fails + inputExpressions = inputExpressions[0]; + return scope.$watch(function expressionInputWatch(scope) { + var newInputValue = inputExpressions(scope); + if (!expressionInputDirtyCheck(newInputValue, oldInputValue)) { + lastResult = parsedExpression(scope); + oldInputValue = newInputValue && getValueOf(newInputValue); + } + return lastResult; + }, listener, objectEquality); + } + + var oldInputValueOfValues = []; + for (var i = 0, ii = inputExpressions.length; i < ii; i++) { + oldInputValueOfValues[i] = expressionInputDirtyCheck; // init to something unique so that equals check fails + } + + return scope.$watch(function expressionInputsWatch(scope) { + var changed = false; + + for (var i = 0, ii = inputExpressions.length; i < ii; i++) { + var newInputValue = inputExpressions[i](scope); + if (changed || (changed = !expressionInputDirtyCheck(newInputValue, oldInputValueOfValues[i]))) { + oldInputValueOfValues[i] = newInputValue && getValueOf(newInputValue); + } + } + + if (changed) { + lastResult = parsedExpression(scope); + } + + return lastResult; + }, listener, objectEquality); + } + + function oneTimeWatchDelegate(scope, listener, objectEquality, parsedExpression) { + var unwatch, lastValue; + return unwatch = scope.$watch(function oneTimeWatch(scope) { + return parsedExpression(scope); + }, function oneTimeListener(value, old, scope) { + lastValue = value; + if (isFunction(listener)) { + listener.apply(this, arguments); + } + if (isDefined(value)) { + scope.$$postDigest(function() { + if (isDefined(lastValue)) { + unwatch(); + } + }); + } + }, objectEquality); + } + + function oneTimeLiteralWatchDelegate(scope, listener, objectEquality, parsedExpression) { + var unwatch, lastValue; + return unwatch = scope.$watch(function oneTimeWatch(scope) { + return parsedExpression(scope); + }, function oneTimeListener(value, old, scope) { + lastValue = value; + if (isFunction(listener)) { + listener.call(this, value, old, scope); + } + if (isAllDefined(value)) { + scope.$$postDigest(function() { + if (isAllDefined(lastValue)) unwatch(); + }); + } + }, objectEquality); + + function isAllDefined(value) { + var allDefined = true; + forEach(value, function(val) { + if (!isDefined(val)) allDefined = false; + }); + return allDefined; + } + } + + function constantWatchDelegate(scope, listener, objectEquality, parsedExpression) { + var unwatch; + return unwatch = scope.$watch(function constantWatch(scope) { + return parsedExpression(scope); + }, function constantListener(value, old, scope) { + if (isFunction(listener)) { + listener.apply(this, arguments); + } + unwatch(); + }, objectEquality); + } + + function addInterceptor(parsedExpression, interceptorFn) { + if (!interceptorFn) return parsedExpression; + var watchDelegate = parsedExpression.$$watchDelegate; + + var regularWatch = + watchDelegate !== oneTimeLiteralWatchDelegate && + watchDelegate !== oneTimeWatchDelegate; + + var fn = regularWatch ? function regularInterceptedExpression(scope, locals) { + var value = parsedExpression(scope, locals); + return interceptorFn(value, scope, locals); + } : function oneTimeInterceptedExpression(scope, locals) { + var value = parsedExpression(scope, locals); + var result = interceptorFn(value, scope, locals); + // we only return the interceptor's result if the + // initial value is defined (for bind-once) + return isDefined(value) ? result : value; + }; + + // Propagate $$watchDelegates other then inputsWatchDelegate + if (parsedExpression.$$watchDelegate && + parsedExpression.$$watchDelegate !== inputsWatchDelegate) { + fn.$$watchDelegate = parsedExpression.$$watchDelegate; + } else if (!interceptorFn.$stateful) { + // If there is an interceptor, but no watchDelegate then treat the interceptor like + // we treat filters - it is assumed to be a pure function unless flagged with $stateful + fn.$$watchDelegate = inputsWatchDelegate; + fn.inputs = [parsedExpression]; + } + + return fn; + } + }]; +} + +/** + * @ngdoc service + * @name $q + * @requires $rootScope + * + * @description + * A service that helps you run functions asynchronously, and use their return values (or exceptions) + * when they are done processing. + * + * This is an implementation of promises/deferred objects inspired by + * [Kris Kowal's Q](https://github.com/kriskowal/q). + * + * $q can be used in two fashions --- one which is more similar to Kris Kowal's Q or jQuery's Deferred + * implementations, and the other which resembles ES6 promises to some degree. + * + * # $q constructor + * + * The streamlined ES6 style promise is essentially just using $q as a constructor which takes a `resolver` + * function as the first argument. This is similar to the native Promise implementation from ES6 Harmony, + * see [MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise). + * + * While the constructor-style use is supported, not all of the supporting methods from ES6 Harmony promises are + * available yet. + * + * It can be used like so: + * + * ```js + * // for the purpose of this example let's assume that variables `$q` and `okToGreet` + * // are available in the current lexical scope (they could have been injected or passed in). + * + * function asyncGreet(name) { + * // perform some asynchronous operation, resolve or reject the promise when appropriate. + * return $q(function(resolve, reject) { + * setTimeout(function() { + * if (okToGreet(name)) { + * resolve('Hello, ' + name + '!'); + * } else { + * reject('Greeting ' + name + ' is not allowed.'); + * } + * }, 1000); + * }); + * } + * + * var promise = asyncGreet('Robin Hood'); + * promise.then(function(greeting) { + * alert('Success: ' + greeting); + * }, function(reason) { + * alert('Failed: ' + reason); + * }); + * ``` + * + * Note: progress/notify callbacks are not currently supported via the ES6-style interface. + * + * However, the more traditional CommonJS-style usage is still available, and documented below. + * + * [The CommonJS Promise proposal](http://wiki.commonjs.org/wiki/Promises) describes a promise as an + * interface for interacting with an object that represents the result of an action that is + * performed asynchronously, and may or may not be finished at any given point in time. + * + * From the perspective of dealing with error handling, deferred and promise APIs are to + * asynchronous programming what `try`, `catch` and `throw` keywords are to synchronous programming. + * + * ```js + * // for the purpose of this example let's assume that variables `$q` and `okToGreet` + * // are available in the current lexical scope (they could have been injected or passed in). + * + * function asyncGreet(name) { + * var deferred = $q.defer(); + * + * setTimeout(function() { + * deferred.notify('About to greet ' + name + '.'); + * + * if (okToGreet(name)) { + * deferred.resolve('Hello, ' + name + '!'); + * } else { + * deferred.reject('Greeting ' + name + ' is not allowed.'); + * } + * }, 1000); + * + * return deferred.promise; + * } + * + * var promise = asyncGreet('Robin Hood'); + * promise.then(function(greeting) { + * alert('Success: ' + greeting); + * }, function(reason) { + * alert('Failed: ' + reason); + * }, function(update) { + * alert('Got notification: ' + update); + * }); + * ``` + * + * At first it might not be obvious why this extra complexity is worth the trouble. The payoff + * comes in the way of guarantees that promise and deferred APIs make, see + * https://github.com/kriskowal/uncommonjs/blob/master/promises/specification.md. + * + * Additionally the promise api allows for composition that is very hard to do with the + * traditional callback ([CPS](http://en.wikipedia.org/wiki/Continuation-passing_style)) approach. + * For more on this please see the [Q documentation](https://github.com/kriskowal/q) especially the + * section on serial or parallel joining of promises. + * + * # The Deferred API + * + * A new instance of deferred is constructed by calling `$q.defer()`. + * + * The purpose of the deferred object is to expose the associated Promise instance as well as APIs + * that can be used for signaling the successful or unsuccessful completion, as well as the status + * of the task. + * + * **Methods** + * + * - `resolve(value)` – resolves the derived promise with the `value`. If the value is a rejection + * constructed via `$q.reject`, the promise will be rejected instead. + * - `reject(reason)` – rejects the derived promise with the `reason`. This is equivalent to + * resolving it with a rejection constructed via `$q.reject`. + * - `notify(value)` - provides updates on the status of the promise's execution. This may be called + * multiple times before the promise is either resolved or rejected. + * + * **Properties** + * + * - promise – `{Promise}` – promise object associated with this deferred. + * + * + * # The Promise API + * + * A new promise instance is created when a deferred instance is created and can be retrieved by + * calling `deferred.promise`. + * + * The purpose of the promise object is to allow for interested parties to get access to the result + * of the deferred task when it completes. + * + * **Methods** + * + * - `then(successCallback, errorCallback, notifyCallback)` – regardless of when the promise was or + * will be resolved or rejected, `then` calls one of the success or error callbacks asynchronously + * as soon as the result is available. The callbacks are called with a single argument: the result + * or rejection reason. Additionally, the notify callback may be called zero or more times to + * provide a progress indication, before the promise is resolved or rejected. + * + * This method *returns a new promise* which is resolved or rejected via the return value of the + * `successCallback`, `errorCallback`. It also notifies via the return value of the + * `notifyCallback` method. The promise cannot be resolved or rejected from the notifyCallback + * method. + * + * - `catch(errorCallback)` – shorthand for `promise.then(null, errorCallback)` + * + * - `finally(callback, notifyCallback)` – allows you to observe either the fulfillment or rejection of a promise, + * but to do so without modifying the final value. This is useful to release resources or do some + * clean-up that needs to be done whether the promise was rejected or resolved. See the [full + * specification](https://github.com/kriskowal/q/wiki/API-Reference#promisefinallycallback) for + * more information. + * + * # Chaining promises + * + * Because calling the `then` method of a promise returns a new derived promise, it is easily + * possible to create a chain of promises: + * + * ```js + * promiseB = promiseA.then(function(result) { + * return result + 1; + * }); + * + * // promiseB will be resolved immediately after promiseA is resolved and its value + * // will be the result of promiseA incremented by 1 + * ``` + * + * It is possible to create chains of any length and since a promise can be resolved with another + * promise (which will defer its resolution further), it is possible to pause/defer resolution of + * the promises at any point in the chain. This makes it possible to implement powerful APIs like + * $http's response interceptors. + * + * + * # Differences between Kris Kowal's Q and $q + * + * There are two main differences: + * + * - $q is integrated with the {@link ng.$rootScope.Scope} Scope model observation + * mechanism in angular, which means faster propagation of resolution or rejection into your + * models and avoiding unnecessary browser repaints, which would result in flickering UI. + * - Q has many more features than $q, but that comes at a cost of bytes. $q is tiny, but contains + * all the important functionality needed for common async tasks. + * + * # Testing + * + * ```js + * it('should simulate promise', inject(function($q, $rootScope) { + * var deferred = $q.defer(); + * var promise = deferred.promise; + * var resolvedValue; + * + * promise.then(function(value) { resolvedValue = value; }); + * expect(resolvedValue).toBeUndefined(); + * + * // Simulate resolving of promise + * deferred.resolve(123); + * // Note that the 'then' function does not get called synchronously. + * // This is because we want the promise API to always be async, whether or not + * // it got called synchronously or asynchronously. + * expect(resolvedValue).toBeUndefined(); + * + * // Propagate promise resolution to 'then' functions using $apply(). + * $rootScope.$apply(); + * expect(resolvedValue).toEqual(123); + * })); + * ``` + * + * @param {function(function, function)} resolver Function which is responsible for resolving or + * rejecting the newly created promise. The first parameter is a function which resolves the + * promise, the second parameter is a function which rejects the promise. + * + * @returns {Promise} The newly created promise. + */ +function $QProvider() { + + this.$get = ['$rootScope', '$exceptionHandler', function($rootScope, $exceptionHandler) { + return qFactory(function(callback) { + $rootScope.$evalAsync(callback); + }, $exceptionHandler); + }]; +} + +function $$QProvider() { + this.$get = ['$browser', '$exceptionHandler', function($browser, $exceptionHandler) { + return qFactory(function(callback) { + $browser.defer(callback); + }, $exceptionHandler); + }]; +} + +/** + * Constructs a promise manager. + * + * @param {function(function)} nextTick Function for executing functions in the next turn. + * @param {function(...*)} exceptionHandler Function into which unexpected exceptions are passed for + * debugging purposes. + * @returns {object} Promise manager. + */ +function qFactory(nextTick, exceptionHandler) { + var $qMinErr = minErr('$q', TypeError); + function callOnce(self, resolveFn, rejectFn) { + var called = false; + function wrap(fn) { + return function(value) { + if (called) return; + called = true; + fn.call(self, value); + }; + } + + return [wrap(resolveFn), wrap(rejectFn)]; + } + + /** + * @ngdoc method + * @name ng.$q#defer + * @kind function + * + * @description + * Creates a `Deferred` object which represents a task which will finish in the future. + * + * @returns {Deferred} Returns a new instance of deferred. + */ + var defer = function() { + return new Deferred(); + }; + + function Promise() { + this.$$state = { status: 0 }; + } + + Promise.prototype = { + then: function(onFulfilled, onRejected, progressBack) { + var result = new Deferred(); + + this.$$state.pending = this.$$state.pending || []; + this.$$state.pending.push([result, onFulfilled, onRejected, progressBack]); + if (this.$$state.status > 0) scheduleProcessQueue(this.$$state); + + return result.promise; + }, + + "catch": function(callback) { + return this.then(null, callback); + }, + + "finally": function(callback, progressBack) { + return this.then(function(value) { + return handleCallback(value, true, callback); + }, function(error) { + return handleCallback(error, false, callback); + }, progressBack); + } + }; + + //Faster, more basic than angular.bind http://jsperf.com/angular-bind-vs-custom-vs-native + function simpleBind(context, fn) { + return function(value) { + fn.call(context, value); + }; + } + + function processQueue(state) { + var fn, promise, pending; + + pending = state.pending; + state.processScheduled = false; + state.pending = undefined; + for (var i = 0, ii = pending.length; i < ii; ++i) { + promise = pending[i][0]; + fn = pending[i][state.status]; + try { + if (isFunction(fn)) { + promise.resolve(fn(state.value)); + } else if (state.status === 1) { + promise.resolve(state.value); + } else { + promise.reject(state.value); + } + } catch (e) { + promise.reject(e); + exceptionHandler(e); + } + } + } + + function scheduleProcessQueue(state) { + if (state.processScheduled || !state.pending) return; + state.processScheduled = true; + nextTick(function() { processQueue(state); }); + } + + function Deferred() { + this.promise = new Promise(); + //Necessary to support unbound execution :/ + this.resolve = simpleBind(this, this.resolve); + this.reject = simpleBind(this, this.reject); + this.notify = simpleBind(this, this.notify); + } + + Deferred.prototype = { + resolve: function(val) { + if (this.promise.$$state.status) return; + if (val === this.promise) { + this.$$reject($qMinErr( + 'qcycle', + "Expected promise to be resolved with value other than itself '{0}'", + val)); + } + else { + this.$$resolve(val); + } + + }, + + $$resolve: function(val) { + var then, fns; + + fns = callOnce(this, this.$$resolve, this.$$reject); + try { + if ((isObject(val) || isFunction(val))) then = val && val.then; + if (isFunction(then)) { + this.promise.$$state.status = -1; + then.call(val, fns[0], fns[1], this.notify); + } else { + this.promise.$$state.value = val; + this.promise.$$state.status = 1; + scheduleProcessQueue(this.promise.$$state); + } + } catch (e) { + fns[1](e); + exceptionHandler(e); + } + }, + + reject: function(reason) { + if (this.promise.$$state.status) return; + this.$$reject(reason); + }, + + $$reject: function(reason) { + this.promise.$$state.value = reason; + this.promise.$$state.status = 2; + scheduleProcessQueue(this.promise.$$state); + }, + + notify: function(progress) { + var callbacks = this.promise.$$state.pending; + + if ((this.promise.$$state.status <= 0) && callbacks && callbacks.length) { + nextTick(function() { + var callback, result; + for (var i = 0, ii = callbacks.length; i < ii; i++) { + result = callbacks[i][0]; + callback = callbacks[i][3]; + try { + result.notify(isFunction(callback) ? callback(progress) : progress); + } catch (e) { + exceptionHandler(e); + } + } + }); + } + } + }; + + /** + * @ngdoc method + * @name $q#reject + * @kind function + * + * @description + * Creates a promise that is resolved as rejected with the specified `reason`. This api should be + * used to forward rejection in a chain of promises. If you are dealing with the last promise in + * a promise chain, you don't need to worry about it. + * + * When comparing deferreds/promises to the familiar behavior of try/catch/throw, think of + * `reject` as the `throw` keyword in JavaScript. This also means that if you "catch" an error via + * a promise error callback and you want to forward the error to the promise derived from the + * current promise, you have to "rethrow" the error by returning a rejection constructed via + * `reject`. + * + * ```js + * promiseB = promiseA.then(function(result) { + * // success: do something and resolve promiseB + * // with the old or a new result + * return result; + * }, function(reason) { + * // error: handle the error if possible and + * // resolve promiseB with newPromiseOrValue, + * // otherwise forward the rejection to promiseB + * if (canHandle(reason)) { + * // handle the error and recover + * return newPromiseOrValue; + * } + * return $q.reject(reason); + * }); + * ``` + * + * @param {*} reason Constant, message, exception or an object representing the rejection reason. + * @returns {Promise} Returns a promise that was already resolved as rejected with the `reason`. + */ + var reject = function(reason) { + var result = new Deferred(); + result.reject(reason); + return result.promise; + }; + + var makePromise = function makePromise(value, resolved) { + var result = new Deferred(); + if (resolved) { + result.resolve(value); + } else { + result.reject(value); + } + return result.promise; + }; + + var handleCallback = function handleCallback(value, isResolved, callback) { + var callbackOutput = null; + try { + if (isFunction(callback)) callbackOutput = callback(); + } catch (e) { + return makePromise(e, false); + } + if (isPromiseLike(callbackOutput)) { + return callbackOutput.then(function() { + return makePromise(value, isResolved); + }, function(error) { + return makePromise(error, false); + }); + } else { + return makePromise(value, isResolved); + } + }; + + /** + * @ngdoc method + * @name $q#when + * @kind function + * + * @description + * Wraps an object that might be a value or a (3rd party) then-able promise into a $q promise. + * This is useful when you are dealing with an object that might or might not be a promise, or if + * the promise comes from a source that can't be trusted. + * + * @param {*} value Value or a promise + * @returns {Promise} Returns a promise of the passed value or promise + */ + + + var when = function(value, callback, errback, progressBack) { + var result = new Deferred(); + result.resolve(value); + return result.promise.then(callback, errback, progressBack); + }; + + /** + * @ngdoc method + * @name $q#all + * @kind function + * + * @description + * Combines multiple promises into a single promise that is resolved when all of the input + * promises are resolved. + * + * @param {Array.|Object.} promises An array or hash of promises. + * @returns {Promise} Returns a single promise that will be resolved with an array/hash of values, + * each value corresponding to the promise at the same index/key in the `promises` array/hash. + * If any of the promises is resolved with a rejection, this resulting promise will be rejected + * with the same rejection value. + */ + + function all(promises) { + var deferred = new Deferred(), + counter = 0, + results = isArray(promises) ? [] : {}; + + forEach(promises, function(promise, key) { + counter++; + when(promise).then(function(value) { + if (results.hasOwnProperty(key)) return; + results[key] = value; + if (!(--counter)) deferred.resolve(results); + }, function(reason) { + if (results.hasOwnProperty(key)) return; + deferred.reject(reason); + }); + }); + + if (counter === 0) { + deferred.resolve(results); + } + + return deferred.promise; + } + + var $Q = function Q(resolver) { + if (!isFunction(resolver)) { + throw $qMinErr('norslvr', "Expected resolverFn, got '{0}'", resolver); + } + + if (!(this instanceof Q)) { + // More useful when $Q is the Promise itself. + return new Q(resolver); + } + + var deferred = new Deferred(); + + function resolveFn(value) { + deferred.resolve(value); + } + + function rejectFn(reason) { + deferred.reject(reason); + } + + resolver(resolveFn, rejectFn); + + return deferred.promise; + }; + + $Q.defer = defer; + $Q.reject = reject; + $Q.when = when; + $Q.all = all; + + return $Q; +} + +function $$RAFProvider() { //rAF + this.$get = ['$window', '$timeout', function($window, $timeout) { + var requestAnimationFrame = $window.requestAnimationFrame || + $window.webkitRequestAnimationFrame; + + var cancelAnimationFrame = $window.cancelAnimationFrame || + $window.webkitCancelAnimationFrame || + $window.webkitCancelRequestAnimationFrame; + + var rafSupported = !!requestAnimationFrame; + var raf = rafSupported + ? function(fn) { + var id = requestAnimationFrame(fn); + return function() { + cancelAnimationFrame(id); + }; + } + : function(fn) { + var timer = $timeout(fn, 16.66, false); // 1000 / 60 = 16.666 + return function() { + $timeout.cancel(timer); + }; + }; + + raf.supported = rafSupported; + + return raf; + }]; +} + +/** + * DESIGN NOTES + * + * The design decisions behind the scope are heavily favored for speed and memory consumption. + * + * The typical use of scope is to watch the expressions, which most of the time return the same + * value as last time so we optimize the operation. + * + * Closures construction is expensive in terms of speed as well as memory: + * - No closures, instead use prototypical inheritance for API + * - Internal state needs to be stored on scope directly, which means that private state is + * exposed as $$____ properties + * + * Loop operations are optimized by using while(count--) { ... } + * - this means that in order to keep the same order of execution as addition we have to add + * items to the array at the beginning (unshift) instead of at the end (push) + * + * Child scopes are created and removed often + * - Using an array would be slow since inserts in middle are expensive so we use linked list + * + * There are few watches then a lot of observers. This is why you don't want the observer to be + * implemented in the same way as watch. Watch requires return of initialization function which + * are expensive to construct. + */ + + +/** + * @ngdoc provider + * @name $rootScopeProvider + * @description + * + * Provider for the $rootScope service. + */ + +/** + * @ngdoc method + * @name $rootScopeProvider#digestTtl + * @description + * + * Sets the number of `$digest` iterations the scope should attempt to execute before giving up and + * assuming that the model is unstable. + * + * The current default is 10 iterations. + * + * In complex applications it's possible that the dependencies between `$watch`s will result in + * several digest iterations. However if an application needs more than the default 10 digest + * iterations for its model to stabilize then you should investigate what is causing the model to + * continuously change during the digest. + * + * Increasing the TTL could have performance implications, so you should not change it without + * proper justification. + * + * @param {number} limit The number of digest iterations. + */ + + +/** + * @ngdoc service + * @name $rootScope + * @description + * + * Every application has a single root {@link ng.$rootScope.Scope scope}. + * All other scopes are descendant scopes of the root scope. Scopes provide separation + * between the model and the view, via a mechanism for watching the model for changes. + * They also provide an event emission/broadcast and subscription facility. See the + * {@link guide/scope developer guide on scopes}. + */ +function $RootScopeProvider() { + var TTL = 10; + var $rootScopeMinErr = minErr('$rootScope'); + var lastDirtyWatch = null; + var applyAsyncId = null; + + this.digestTtl = function(value) { + if (arguments.length) { + TTL = value; + } + return TTL; + }; + + this.$get = ['$injector', '$exceptionHandler', '$parse', '$browser', + function($injector, $exceptionHandler, $parse, $browser) { + + /** + * @ngdoc type + * @name $rootScope.Scope + * + * @description + * A root scope can be retrieved using the {@link ng.$rootScope $rootScope} key from the + * {@link auto.$injector $injector}. Child scopes are created using the + * {@link ng.$rootScope.Scope#$new $new()} method. (Most scopes are created automatically when + * compiled HTML template is executed.) + * + * Here is a simple scope snippet to show how you can interact with the scope. + * ```html + * + * ``` + * + * # Inheritance + * A scope can inherit from a parent scope, as in this example: + * ```js + var parent = $rootScope; + var child = parent.$new(); + + parent.salutation = "Hello"; + expect(child.salutation).toEqual('Hello'); + + child.salutation = "Welcome"; + expect(child.salutation).toEqual('Welcome'); + expect(parent.salutation).toEqual('Hello'); + * ``` + * + * When interacting with `Scope` in tests, additional helper methods are available on the + * instances of `Scope` type. See {@link ngMock.$rootScope.Scope ngMock Scope} for additional + * details. + * + * + * @param {Object.=} providers Map of service factory which need to be + * provided for the current scope. Defaults to {@link ng}. + * @param {Object.=} instanceCache Provides pre-instantiated services which should + * append/override services provided by `providers`. This is handy + * when unit-testing and having the need to override a default + * service. + * @returns {Object} Newly created scope. + * + */ + function Scope() { + this.$id = nextUid(); + this.$$phase = this.$parent = this.$$watchers = + this.$$nextSibling = this.$$prevSibling = + this.$$childHead = this.$$childTail = null; + this.$root = this; + this.$$destroyed = false; + this.$$listeners = {}; + this.$$listenerCount = {}; + this.$$isolateBindings = null; + } + + /** + * @ngdoc property + * @name $rootScope.Scope#$id + * + * @description + * Unique scope ID (monotonically increasing) useful for debugging. + */ + + /** + * @ngdoc property + * @name $rootScope.Scope#$parent + * + * @description + * Reference to the parent scope. + */ + + /** + * @ngdoc property + * @name $rootScope.Scope#$root + * + * @description + * Reference to the root scope. + */ + + Scope.prototype = { + constructor: Scope, + /** + * @ngdoc method + * @name $rootScope.Scope#$new + * @kind function + * + * @description + * Creates a new child {@link ng.$rootScope.Scope scope}. + * + * The parent scope will propagate the {@link ng.$rootScope.Scope#$digest $digest()} event. + * The scope can be removed from the scope hierarchy using {@link ng.$rootScope.Scope#$destroy $destroy()}. + * + * {@link ng.$rootScope.Scope#$destroy $destroy()} must be called on a scope when it is + * desired for the scope and its child scopes to be permanently detached from the parent and + * thus stop participating in model change detection and listener notification by invoking. + * + * @param {boolean} isolate If true, then the scope does not prototypically inherit from the + * parent scope. The scope is isolated, as it can not see parent scope properties. + * When creating widgets, it is useful for the widget to not accidentally read parent + * state. + * + * @param {Scope} [parent=this] The {@link ng.$rootScope.Scope `Scope`} that will be the `$parent` + * of the newly created scope. Defaults to `this` scope if not provided. + * This is used when creating a transclude scope to correctly place it + * in the scope hierarchy while maintaining the correct prototypical + * inheritance. + * + * @returns {Object} The newly created child scope. + * + */ + $new: function(isolate, parent) { + var child; + + parent = parent || this; + + if (isolate) { + child = new Scope(); + child.$root = this.$root; + } else { + // Only create a child scope class if somebody asks for one, + // but cache it to allow the VM to optimize lookups. + if (!this.$$ChildScope) { + this.$$ChildScope = function ChildScope() { + this.$$watchers = this.$$nextSibling = + this.$$childHead = this.$$childTail = null; + this.$$listeners = {}; + this.$$listenerCount = {}; + this.$id = nextUid(); + this.$$ChildScope = null; + }; + this.$$ChildScope.prototype = this; + } + child = new this.$$ChildScope(); + } + child.$parent = parent; + child.$$prevSibling = parent.$$childTail; + if (parent.$$childHead) { + parent.$$childTail.$$nextSibling = child; + parent.$$childTail = child; + } else { + parent.$$childHead = parent.$$childTail = child; + } + + // When the new scope is not isolated or we inherit from `this`, and + // the parent scope is destroyed, the property `$$destroyed` is inherited + // prototypically. In all other cases, this property needs to be set + // when the parent scope is destroyed. + // The listener needs to be added after the parent is set + if (isolate || parent != this) child.$on('$destroy', destroyChild); + + return child; + + function destroyChild() { + child.$$destroyed = true; + } + }, + + /** + * @ngdoc method + * @name $rootScope.Scope#$watch + * @kind function + * + * @description + * Registers a `listener` callback to be executed whenever the `watchExpression` changes. + * + * - The `watchExpression` is called on every call to {@link ng.$rootScope.Scope#$digest + * $digest()} and should return the value that will be watched. (Since + * {@link ng.$rootScope.Scope#$digest $digest()} reruns when it detects changes the + * `watchExpression` can execute multiple times per + * {@link ng.$rootScope.Scope#$digest $digest()} and should be idempotent.) + * - The `listener` is called only when the value from the current `watchExpression` and the + * previous call to `watchExpression` are not equal (with the exception of the initial run, + * see below). Inequality is determined according to reference inequality, + * [strict comparison](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Comparison_Operators) + * via the `!==` Javascript operator, unless `objectEquality == true` + * (see next point) + * - When `objectEquality == true`, inequality of the `watchExpression` is determined + * according to the {@link angular.equals} function. To save the value of the object for + * later comparison, the {@link angular.copy} function is used. This therefore means that + * watching complex objects will have adverse memory and performance implications. + * - The watch `listener` may change the model, which may trigger other `listener`s to fire. + * This is achieved by rerunning the watchers until no changes are detected. The rerun + * iteration limit is 10 to prevent an infinite loop deadlock. + * + * + * If you want to be notified whenever {@link ng.$rootScope.Scope#$digest $digest} is called, + * you can register a `watchExpression` function with no `listener`. (Since `watchExpression` + * can execute multiple times per {@link ng.$rootScope.Scope#$digest $digest} cycle when a + * change is detected, be prepared for multiple calls to your listener.) + * + * After a watcher is registered with the scope, the `listener` fn is called asynchronously + * (via {@link ng.$rootScope.Scope#$evalAsync $evalAsync}) to initialize the + * watcher. In rare cases, this is undesirable because the listener is called when the result + * of `watchExpression` didn't change. To detect this scenario within the `listener` fn, you + * can compare the `newVal` and `oldVal`. If these two values are identical (`===`) then the + * listener was called due to initialization. + * + * + * + * # Example + * ```js + // let's assume that scope was dependency injected as the $rootScope + var scope = $rootScope; + scope.name = 'misko'; + scope.counter = 0; + + expect(scope.counter).toEqual(0); + scope.$watch('name', function(newValue, oldValue) { + scope.counter = scope.counter + 1; + }); + expect(scope.counter).toEqual(0); + + scope.$digest(); + // the listener is always called during the first $digest loop after it was registered + expect(scope.counter).toEqual(1); + + scope.$digest(); + // but now it will not be called unless the value changes + expect(scope.counter).toEqual(1); + + scope.name = 'adam'; + scope.$digest(); + expect(scope.counter).toEqual(2); + + + + // Using a function as a watchExpression + var food; + scope.foodCounter = 0; + expect(scope.foodCounter).toEqual(0); + scope.$watch( + // This function returns the value being watched. It is called for each turn of the $digest loop + function() { return food; }, + // This is the change listener, called when the value returned from the above function changes + function(newValue, oldValue) { + if ( newValue !== oldValue ) { + // Only increment the counter if the value changed + scope.foodCounter = scope.foodCounter + 1; + } + } + ); + // No digest has been run so the counter will be zero + expect(scope.foodCounter).toEqual(0); + + // Run the digest but since food has not changed count will still be zero + scope.$digest(); + expect(scope.foodCounter).toEqual(0); + + // Update food and run digest. Now the counter will increment + food = 'cheeseburger'; + scope.$digest(); + expect(scope.foodCounter).toEqual(1); + + * ``` + * + * + * + * @param {(function()|string)} watchExpression Expression that is evaluated on each + * {@link ng.$rootScope.Scope#$digest $digest} cycle. A change in the return value triggers + * a call to the `listener`. + * + * - `string`: Evaluated as {@link guide/expression expression} + * - `function(scope)`: called with current `scope` as a parameter. + * @param {function(newVal, oldVal, scope)} listener Callback called whenever the value + * of `watchExpression` changes. + * + * - `newVal` contains the current value of the `watchExpression` + * - `oldVal` contains the previous value of the `watchExpression` + * - `scope` refers to the current scope + * @param {boolean=} objectEquality Compare for object equality using {@link angular.equals} instead of + * comparing for reference equality. + * @returns {function()} Returns a deregistration function for this listener. + */ + $watch: function(watchExp, listener, objectEquality) { + var get = $parse(watchExp); + + if (get.$$watchDelegate) { + return get.$$watchDelegate(this, listener, objectEquality, get); + } + var scope = this, + array = scope.$$watchers, + watcher = { + fn: listener, + last: initWatchVal, + get: get, + exp: watchExp, + eq: !!objectEquality + }; + + lastDirtyWatch = null; + + if (!isFunction(listener)) { + watcher.fn = noop; + } + + if (!array) { + array = scope.$$watchers = []; + } + // we use unshift since we use a while loop in $digest for speed. + // the while loop reads in reverse order. + array.unshift(watcher); + + return function deregisterWatch() { + arrayRemove(array, watcher); + lastDirtyWatch = null; + }; + }, + + /** + * @ngdoc method + * @name $rootScope.Scope#$watchGroup + * @kind function + * + * @description + * A variant of {@link ng.$rootScope.Scope#$watch $watch()} where it watches an array of `watchExpressions`. + * If any one expression in the collection changes the `listener` is executed. + * + * - The items in the `watchExpressions` array are observed via standard $watch operation and are examined on every + * call to $digest() to see if any items changes. + * - The `listener` is called whenever any expression in the `watchExpressions` array changes. + * + * @param {Array.} watchExpressions Array of expressions that will be individually + * watched using {@link ng.$rootScope.Scope#$watch $watch()} + * + * @param {function(newValues, oldValues, scope)} listener Callback called whenever the return value of any + * expression in `watchExpressions` changes + * The `newValues` array contains the current values of the `watchExpressions`, with the indexes matching + * those of `watchExpression` + * and the `oldValues` array contains the previous values of the `watchExpressions`, with the indexes matching + * those of `watchExpression` + * The `scope` refers to the current scope. + * @returns {function()} Returns a de-registration function for all listeners. + */ + $watchGroup: function(watchExpressions, listener) { + var oldValues = new Array(watchExpressions.length); + var newValues = new Array(watchExpressions.length); + var deregisterFns = []; + var self = this; + var changeReactionScheduled = false; + var firstRun = true; + + if (!watchExpressions.length) { + // No expressions means we call the listener ASAP + var shouldCall = true; + self.$evalAsync(function() { + if (shouldCall) listener(newValues, newValues, self); + }); + return function deregisterWatchGroup() { + shouldCall = false; + }; + } + + if (watchExpressions.length === 1) { + // Special case size of one + return this.$watch(watchExpressions[0], function watchGroupAction(value, oldValue, scope) { + newValues[0] = value; + oldValues[0] = oldValue; + listener(newValues, (value === oldValue) ? newValues : oldValues, scope); + }); + } + + forEach(watchExpressions, function(expr, i) { + var unwatchFn = self.$watch(expr, function watchGroupSubAction(value, oldValue) { + newValues[i] = value; + oldValues[i] = oldValue; + if (!changeReactionScheduled) { + changeReactionScheduled = true; + self.$evalAsync(watchGroupAction); + } + }); + deregisterFns.push(unwatchFn); + }); + + function watchGroupAction() { + changeReactionScheduled = false; + + if (firstRun) { + firstRun = false; + listener(newValues, newValues, self); + } else { + listener(newValues, oldValues, self); + } + } + + return function deregisterWatchGroup() { + while (deregisterFns.length) { + deregisterFns.shift()(); + } + }; + }, + + + /** + * @ngdoc method + * @name $rootScope.Scope#$watchCollection + * @kind function + * + * @description + * Shallow watches the properties of an object and fires whenever any of the properties change + * (for arrays, this implies watching the array items; for object maps, this implies watching + * the properties). If a change is detected, the `listener` callback is fired. + * + * - The `obj` collection is observed via standard $watch operation and is examined on every + * call to $digest() to see if any items have been added, removed, or moved. + * - The `listener` is called whenever anything within the `obj` has changed. Examples include + * adding, removing, and moving items belonging to an object or array. + * + * + * # Example + * ```js + $scope.names = ['igor', 'matias', 'misko', 'james']; + $scope.dataCount = 4; + + $scope.$watchCollection('names', function(newNames, oldNames) { + $scope.dataCount = newNames.length; + }); + + expect($scope.dataCount).toEqual(4); + $scope.$digest(); + + //still at 4 ... no changes + expect($scope.dataCount).toEqual(4); + + $scope.names.pop(); + $scope.$digest(); + + //now there's been a change + expect($scope.dataCount).toEqual(3); + * ``` + * + * + * @param {string|function(scope)} obj Evaluated as {@link guide/expression expression}. The + * expression value should evaluate to an object or an array which is observed on each + * {@link ng.$rootScope.Scope#$digest $digest} cycle. Any shallow change within the + * collection will trigger a call to the `listener`. + * + * @param {function(newCollection, oldCollection, scope)} listener a callback function called + * when a change is detected. + * - The `newCollection` object is the newly modified data obtained from the `obj` expression + * - The `oldCollection` object is a copy of the former collection data. + * Due to performance considerations, the`oldCollection` value is computed only if the + * `listener` function declares two or more arguments. + * - The `scope` argument refers to the current scope. + * + * @returns {function()} Returns a de-registration function for this listener. When the + * de-registration function is executed, the internal watch operation is terminated. + */ + $watchCollection: function(obj, listener) { + $watchCollectionInterceptor.$stateful = true; + + var self = this; + // the current value, updated on each dirty-check run + var newValue; + // a shallow copy of the newValue from the last dirty-check run, + // updated to match newValue during dirty-check run + var oldValue; + // a shallow copy of the newValue from when the last change happened + var veryOldValue; + // only track veryOldValue if the listener is asking for it + var trackVeryOldValue = (listener.length > 1); + var changeDetected = 0; + var changeDetector = $parse(obj, $watchCollectionInterceptor); + var internalArray = []; + var internalObject = {}; + var initRun = true; + var oldLength = 0; + + function $watchCollectionInterceptor(_value) { + newValue = _value; + var newLength, key, bothNaN, newItem, oldItem; + + // If the new value is undefined, then return undefined as the watch may be a one-time watch + if (isUndefined(newValue)) return; + + if (!isObject(newValue)) { // if primitive + if (oldValue !== newValue) { + oldValue = newValue; + changeDetected++; + } + } else if (isArrayLike(newValue)) { + if (oldValue !== internalArray) { + // we are transitioning from something which was not an array into array. + oldValue = internalArray; + oldLength = oldValue.length = 0; + changeDetected++; + } + + newLength = newValue.length; + + if (oldLength !== newLength) { + // if lengths do not match we need to trigger change notification + changeDetected++; + oldValue.length = oldLength = newLength; + } + // copy the items to oldValue and look for changes. + for (var i = 0; i < newLength; i++) { + oldItem = oldValue[i]; + newItem = newValue[i]; + + bothNaN = (oldItem !== oldItem) && (newItem !== newItem); + if (!bothNaN && (oldItem !== newItem)) { + changeDetected++; + oldValue[i] = newItem; + } + } + } else { + if (oldValue !== internalObject) { + // we are transitioning from something which was not an object into object. + oldValue = internalObject = {}; + oldLength = 0; + changeDetected++; + } + // copy the items to oldValue and look for changes. + newLength = 0; + for (key in newValue) { + if (newValue.hasOwnProperty(key)) { + newLength++; + newItem = newValue[key]; + oldItem = oldValue[key]; + + if (key in oldValue) { + bothNaN = (oldItem !== oldItem) && (newItem !== newItem); + if (!bothNaN && (oldItem !== newItem)) { + changeDetected++; + oldValue[key] = newItem; + } + } else { + oldLength++; + oldValue[key] = newItem; + changeDetected++; + } + } + } + if (oldLength > newLength) { + // we used to have more keys, need to find them and destroy them. + changeDetected++; + for (key in oldValue) { + if (!newValue.hasOwnProperty(key)) { + oldLength--; + delete oldValue[key]; + } + } + } + } + return changeDetected; + } + + function $watchCollectionAction() { + if (initRun) { + initRun = false; + listener(newValue, newValue, self); + } else { + listener(newValue, veryOldValue, self); + } + + // make a copy for the next time a collection is changed + if (trackVeryOldValue) { + if (!isObject(newValue)) { + //primitive + veryOldValue = newValue; + } else if (isArrayLike(newValue)) { + veryOldValue = new Array(newValue.length); + for (var i = 0; i < newValue.length; i++) { + veryOldValue[i] = newValue[i]; + } + } else { // if object + veryOldValue = {}; + for (var key in newValue) { + if (hasOwnProperty.call(newValue, key)) { + veryOldValue[key] = newValue[key]; + } + } + } + } + } + + return this.$watch(changeDetector, $watchCollectionAction); + }, + + /** + * @ngdoc method + * @name $rootScope.Scope#$digest + * @kind function + * + * @description + * Processes all of the {@link ng.$rootScope.Scope#$watch watchers} of the current scope and + * its children. Because a {@link ng.$rootScope.Scope#$watch watcher}'s listener can change + * the model, the `$digest()` keeps calling the {@link ng.$rootScope.Scope#$watch watchers} + * until no more listeners are firing. This means that it is possible to get into an infinite + * loop. This function will throw `'Maximum iteration limit exceeded.'` if the number of + * iterations exceeds 10. + * + * Usually, you don't call `$digest()` directly in + * {@link ng.directive:ngController controllers} or in + * {@link ng.$compileProvider#directive directives}. + * Instead, you should call {@link ng.$rootScope.Scope#$apply $apply()} (typically from within + * a {@link ng.$compileProvider#directive directive}), which will force a `$digest()`. + * + * If you want to be notified whenever `$digest()` is called, + * you can register a `watchExpression` function with + * {@link ng.$rootScope.Scope#$watch $watch()} with no `listener`. + * + * In unit tests, you may need to call `$digest()` to simulate the scope life cycle. + * + * # Example + * ```js + var scope = ...; + scope.name = 'misko'; + scope.counter = 0; + + expect(scope.counter).toEqual(0); + scope.$watch('name', function(newValue, oldValue) { + scope.counter = scope.counter + 1; + }); + expect(scope.counter).toEqual(0); + + scope.$digest(); + // the listener is always called during the first $digest loop after it was registered + expect(scope.counter).toEqual(1); + + scope.$digest(); + // but now it will not be called unless the value changes + expect(scope.counter).toEqual(1); + + scope.name = 'adam'; + scope.$digest(); + expect(scope.counter).toEqual(2); + * ``` + * + */ + $digest: function() { + var watch, value, last, + watchers, + length, + dirty, ttl = TTL, + next, current, target = this, + watchLog = [], + logIdx, logMsg, asyncTask; + + beginPhase('$digest'); + // Check for changes to browser url that happened in sync before the call to $digest + $browser.$$checkUrlChange(); + + if (this === $rootScope && applyAsyncId !== null) { + // If this is the root scope, and $applyAsync has scheduled a deferred $apply(), then + // cancel the scheduled $apply and flush the queue of expressions to be evaluated. + $browser.defer.cancel(applyAsyncId); + flushApplyAsync(); + } + + lastDirtyWatch = null; + + do { // "while dirty" loop + dirty = false; + current = target; + + while (asyncQueue.length) { + try { + asyncTask = asyncQueue.shift(); + asyncTask.scope.$eval(asyncTask.expression, asyncTask.locals); + } catch (e) { + $exceptionHandler(e); + } + lastDirtyWatch = null; + } + + traverseScopesLoop: + do { // "traverse the scopes" loop + if ((watchers = current.$$watchers)) { + // process our watches + length = watchers.length; + while (length--) { + try { + watch = watchers[length]; + // Most common watches are on primitives, in which case we can short + // circuit it with === operator, only when === fails do we use .equals + if (watch) { + if ((value = watch.get(current)) !== (last = watch.last) && + !(watch.eq + ? equals(value, last) + : (typeof value === 'number' && typeof last === 'number' + && isNaN(value) && isNaN(last)))) { + dirty = true; + lastDirtyWatch = watch; + watch.last = watch.eq ? copy(value, null) : value; + watch.fn(value, ((last === initWatchVal) ? value : last), current); + if (ttl < 5) { + logIdx = 4 - ttl; + if (!watchLog[logIdx]) watchLog[logIdx] = []; + watchLog[logIdx].push({ + msg: isFunction(watch.exp) ? 'fn: ' + (watch.exp.name || watch.exp.toString()) : watch.exp, + newVal: value, + oldVal: last + }); + } + } else if (watch === lastDirtyWatch) { + // If the most recently dirty watcher is now clean, short circuit since the remaining watchers + // have already been tested. + dirty = false; + break traverseScopesLoop; + } + } + } catch (e) { + $exceptionHandler(e); + } + } + } + + // Insanity Warning: scope depth-first traversal + // yes, this code is a bit crazy, but it works and we have tests to prove it! + // this piece should be kept in sync with the traversal in $broadcast + if (!(next = (current.$$childHead || + (current !== target && current.$$nextSibling)))) { + while (current !== target && !(next = current.$$nextSibling)) { + current = current.$parent; + } + } + } while ((current = next)); + + // `break traverseScopesLoop;` takes us to here + + if ((dirty || asyncQueue.length) && !(ttl--)) { + clearPhase(); + throw $rootScopeMinErr('infdig', + '{0} $digest() iterations reached. Aborting!\n' + + 'Watchers fired in the last 5 iterations: {1}', + TTL, watchLog); + } + + } while (dirty || asyncQueue.length); + + clearPhase(); + + while (postDigestQueue.length) { + try { + postDigestQueue.shift()(); + } catch (e) { + $exceptionHandler(e); + } + } + }, + + + /** + * @ngdoc event + * @name $rootScope.Scope#$destroy + * @eventType broadcast on scope being destroyed + * + * @description + * Broadcasted when a scope and its children are being destroyed. + * + * Note that, in AngularJS, there is also a `$destroy` jQuery event, which can be used to + * clean up DOM bindings before an element is removed from the DOM. + */ + + /** + * @ngdoc method + * @name $rootScope.Scope#$destroy + * @kind function + * + * @description + * Removes the current scope (and all of its children) from the parent scope. Removal implies + * that calls to {@link ng.$rootScope.Scope#$digest $digest()} will no longer + * propagate to the current scope and its children. Removal also implies that the current + * scope is eligible for garbage collection. + * + * The `$destroy()` is usually used by directives such as + * {@link ng.directive:ngRepeat ngRepeat} for managing the + * unrolling of the loop. + * + * Just before a scope is destroyed, a `$destroy` event is broadcasted on this scope. + * Application code can register a `$destroy` event handler that will give it a chance to + * perform any necessary cleanup. + * + * Note that, in AngularJS, there is also a `$destroy` jQuery event, which can be used to + * clean up DOM bindings before an element is removed from the DOM. + */ + $destroy: function() { + // we can't destroy the root scope or a scope that has been already destroyed + if (this.$$destroyed) return; + var parent = this.$parent; + + this.$broadcast('$destroy'); + this.$$destroyed = true; + if (this === $rootScope) return; + + for (var eventName in this.$$listenerCount) { + decrementListenerCount(this, this.$$listenerCount[eventName], eventName); + } + + // sever all the references to parent scopes (after this cleanup, the current scope should + // not be retained by any of our references and should be eligible for garbage collection) + if (parent.$$childHead == this) parent.$$childHead = this.$$nextSibling; + if (parent.$$childTail == this) parent.$$childTail = this.$$prevSibling; + if (this.$$prevSibling) this.$$prevSibling.$$nextSibling = this.$$nextSibling; + if (this.$$nextSibling) this.$$nextSibling.$$prevSibling = this.$$prevSibling; + + // Disable listeners, watchers and apply/digest methods + this.$destroy = this.$digest = this.$apply = this.$evalAsync = this.$applyAsync = noop; + this.$on = this.$watch = this.$watchGroup = function() { return noop; }; + this.$$listeners = {}; + + // All of the code below is bogus code that works around V8's memory leak via optimized code + // and inline caches. + // + // see: + // - https://code.google.com/p/v8/issues/detail?id=2073#c26 + // - https://github.com/angular/angular.js/issues/6794#issuecomment-38648909 + // - https://github.com/angular/angular.js/issues/1313#issuecomment-10378451 + + this.$parent = this.$$nextSibling = this.$$prevSibling = this.$$childHead = + this.$$childTail = this.$root = this.$$watchers = null; + }, + + /** + * @ngdoc method + * @name $rootScope.Scope#$eval + * @kind function + * + * @description + * Executes the `expression` on the current scope and returns the result. Any exceptions in + * the expression are propagated (uncaught). This is useful when evaluating Angular + * expressions. + * + * # Example + * ```js + var scope = ng.$rootScope.Scope(); + scope.a = 1; + scope.b = 2; + + expect(scope.$eval('a+b')).toEqual(3); + expect(scope.$eval(function(scope){ return scope.a + scope.b; })).toEqual(3); + * ``` + * + * @param {(string|function())=} expression An angular expression to be executed. + * + * - `string`: execute using the rules as defined in {@link guide/expression expression}. + * - `function(scope)`: execute the function with the current `scope` parameter. + * + * @param {(object)=} locals Local variables object, useful for overriding values in scope. + * @returns {*} The result of evaluating the expression. + */ + $eval: function(expr, locals) { + return $parse(expr)(this, locals); + }, + + /** + * @ngdoc method + * @name $rootScope.Scope#$evalAsync + * @kind function + * + * @description + * Executes the expression on the current scope at a later point in time. + * + * The `$evalAsync` makes no guarantees as to when the `expression` will be executed, only + * that: + * + * - it will execute after the function that scheduled the evaluation (preferably before DOM + * rendering). + * - at least one {@link ng.$rootScope.Scope#$digest $digest cycle} will be performed after + * `expression` execution. + * + * Any exceptions from the execution of the expression are forwarded to the + * {@link ng.$exceptionHandler $exceptionHandler} service. + * + * __Note:__ if this function is called outside of a `$digest` cycle, a new `$digest` cycle + * will be scheduled. However, it is encouraged to always call code that changes the model + * from within an `$apply` call. That includes code evaluated via `$evalAsync`. + * + * @param {(string|function())=} expression An angular expression to be executed. + * + * - `string`: execute using the rules as defined in {@link guide/expression expression}. + * - `function(scope)`: execute the function with the current `scope` parameter. + * + * @param {(object)=} locals Local variables object, useful for overriding values in scope. + */ + $evalAsync: function(expr, locals) { + // if we are outside of an $digest loop and this is the first time we are scheduling async + // task also schedule async auto-flush + if (!$rootScope.$$phase && !asyncQueue.length) { + $browser.defer(function() { + if (asyncQueue.length) { + $rootScope.$digest(); + } + }); + } + + asyncQueue.push({scope: this, expression: expr, locals: locals}); + }, + + $$postDigest: function(fn) { + postDigestQueue.push(fn); + }, + + /** + * @ngdoc method + * @name $rootScope.Scope#$apply + * @kind function + * + * @description + * `$apply()` is used to execute an expression in angular from outside of the angular + * framework. (For example from browser DOM events, setTimeout, XHR or third party libraries). + * Because we are calling into the angular framework we need to perform proper scope life + * cycle of {@link ng.$exceptionHandler exception handling}, + * {@link ng.$rootScope.Scope#$digest executing watches}. + * + * ## Life cycle + * + * # Pseudo-Code of `$apply()` + * ```js + function $apply(expr) { + try { + return $eval(expr); + } catch (e) { + $exceptionHandler(e); + } finally { + $root.$digest(); + } + } + * ``` + * + * + * Scope's `$apply()` method transitions through the following stages: + * + * 1. The {@link guide/expression expression} is executed using the + * {@link ng.$rootScope.Scope#$eval $eval()} method. + * 2. Any exceptions from the execution of the expression are forwarded to the + * {@link ng.$exceptionHandler $exceptionHandler} service. + * 3. The {@link ng.$rootScope.Scope#$watch watch} listeners are fired immediately after the + * expression was executed using the {@link ng.$rootScope.Scope#$digest $digest()} method. + * + * + * @param {(string|function())=} exp An angular expression to be executed. + * + * - `string`: execute using the rules as defined in {@link guide/expression expression}. + * - `function(scope)`: execute the function with current `scope` parameter. + * + * @returns {*} The result of evaluating the expression. + */ + $apply: function(expr) { + try { + beginPhase('$apply'); + return this.$eval(expr); + } catch (e) { + $exceptionHandler(e); + } finally { + clearPhase(); + try { + $rootScope.$digest(); + } catch (e) { + $exceptionHandler(e); + throw e; + } + } + }, + + /** + * @ngdoc method + * @name $rootScope.Scope#$applyAsync + * @kind function + * + * @description + * Schedule the invokation of $apply to occur at a later time. The actual time difference + * varies across browsers, but is typically around ~10 milliseconds. + * + * This can be used to queue up multiple expressions which need to be evaluated in the same + * digest. + * + * @param {(string|function())=} exp An angular expression to be executed. + * + * - `string`: execute using the rules as defined in {@link guide/expression expression}. + * - `function(scope)`: execute the function with current `scope` parameter. + */ + $applyAsync: function(expr) { + var scope = this; + expr && applyAsyncQueue.push($applyAsyncExpression); + scheduleApplyAsync(); + + function $applyAsyncExpression() { + scope.$eval(expr); + } + }, + + /** + * @ngdoc method + * @name $rootScope.Scope#$on + * @kind function + * + * @description + * Listens on events of a given type. See {@link ng.$rootScope.Scope#$emit $emit} for + * discussion of event life cycle. + * + * The event listener function format is: `function(event, args...)`. The `event` object + * passed into the listener has the following attributes: + * + * - `targetScope` - `{Scope}`: the scope on which the event was `$emit`-ed or + * `$broadcast`-ed. + * - `currentScope` - `{Scope}`: the scope that is currently handling the event. Once the + * event propagates through the scope hierarchy, this property is set to null. + * - `name` - `{string}`: name of the event. + * - `stopPropagation` - `{function=}`: calling `stopPropagation` function will cancel + * further event propagation (available only for events that were `$emit`-ed). + * - `preventDefault` - `{function}`: calling `preventDefault` sets `defaultPrevented` flag + * to true. + * - `defaultPrevented` - `{boolean}`: true if `preventDefault` was called. + * + * @param {string} name Event name to listen on. + * @param {function(event, ...args)} listener Function to call when the event is emitted. + * @returns {function()} Returns a deregistration function for this listener. + */ + $on: function(name, listener) { + var namedListeners = this.$$listeners[name]; + if (!namedListeners) { + this.$$listeners[name] = namedListeners = []; + } + namedListeners.push(listener); + + var current = this; + do { + if (!current.$$listenerCount[name]) { + current.$$listenerCount[name] = 0; + } + current.$$listenerCount[name]++; + } while ((current = current.$parent)); + + var self = this; + return function() { + var indexOfListener = namedListeners.indexOf(listener); + if (indexOfListener !== -1) { + namedListeners[indexOfListener] = null; + decrementListenerCount(self, 1, name); + } + }; + }, + + + /** + * @ngdoc method + * @name $rootScope.Scope#$emit + * @kind function + * + * @description + * Dispatches an event `name` upwards through the scope hierarchy notifying the + * registered {@link ng.$rootScope.Scope#$on} listeners. + * + * The event life cycle starts at the scope on which `$emit` was called. All + * {@link ng.$rootScope.Scope#$on listeners} listening for `name` event on this scope get + * notified. Afterwards, the event traverses upwards toward the root scope and calls all + * registered listeners along the way. The event will stop propagating if one of the listeners + * cancels it. + * + * Any exception emitted from the {@link ng.$rootScope.Scope#$on listeners} will be passed + * onto the {@link ng.$exceptionHandler $exceptionHandler} service. + * + * @param {string} name Event name to emit. + * @param {...*} args Optional one or more arguments which will be passed onto the event listeners. + * @return {Object} Event object (see {@link ng.$rootScope.Scope#$on}). + */ + $emit: function(name, args) { + var empty = [], + namedListeners, + scope = this, + stopPropagation = false, + event = { + name: name, + targetScope: scope, + stopPropagation: function() {stopPropagation = true;}, + preventDefault: function() { + event.defaultPrevented = true; + }, + defaultPrevented: false + }, + listenerArgs = concat([event], arguments, 1), + i, length; + + do { + namedListeners = scope.$$listeners[name] || empty; + event.currentScope = scope; + for (i = 0, length = namedListeners.length; i < length; i++) { + + // if listeners were deregistered, defragment the array + if (!namedListeners[i]) { + namedListeners.splice(i, 1); + i--; + length--; + continue; + } + try { + //allow all listeners attached to the current scope to run + namedListeners[i].apply(null, listenerArgs); + } catch (e) { + $exceptionHandler(e); + } + } + //if any listener on the current scope stops propagation, prevent bubbling + if (stopPropagation) { + event.currentScope = null; + return event; + } + //traverse upwards + scope = scope.$parent; + } while (scope); + + event.currentScope = null; + + return event; + }, + + + /** + * @ngdoc method + * @name $rootScope.Scope#$broadcast + * @kind function + * + * @description + * Dispatches an event `name` downwards to all child scopes (and their children) notifying the + * registered {@link ng.$rootScope.Scope#$on} listeners. + * + * The event life cycle starts at the scope on which `$broadcast` was called. All + * {@link ng.$rootScope.Scope#$on listeners} listening for `name` event on this scope get + * notified. Afterwards, the event propagates to all direct and indirect scopes of the current + * scope and calls all registered listeners along the way. The event cannot be canceled. + * + * Any exception emitted from the {@link ng.$rootScope.Scope#$on listeners} will be passed + * onto the {@link ng.$exceptionHandler $exceptionHandler} service. + * + * @param {string} name Event name to broadcast. + * @param {...*} args Optional one or more arguments which will be passed onto the event listeners. + * @return {Object} Event object, see {@link ng.$rootScope.Scope#$on} + */ + $broadcast: function(name, args) { + var target = this, + current = target, + next = target, + event = { + name: name, + targetScope: target, + preventDefault: function() { + event.defaultPrevented = true; + }, + defaultPrevented: false + }; + + if (!target.$$listenerCount[name]) return event; + + var listenerArgs = concat([event], arguments, 1), + listeners, i, length; + + //down while you can, then up and next sibling or up and next sibling until back at root + while ((current = next)) { + event.currentScope = current; + listeners = current.$$listeners[name] || []; + for (i = 0, length = listeners.length; i < length; i++) { + // if listeners were deregistered, defragment the array + if (!listeners[i]) { + listeners.splice(i, 1); + i--; + length--; + continue; + } + + try { + listeners[i].apply(null, listenerArgs); + } catch (e) { + $exceptionHandler(e); + } + } + + // Insanity Warning: scope depth-first traversal + // yes, this code is a bit crazy, but it works and we have tests to prove it! + // this piece should be kept in sync with the traversal in $digest + // (though it differs due to having the extra check for $$listenerCount) + if (!(next = ((current.$$listenerCount[name] && current.$$childHead) || + (current !== target && current.$$nextSibling)))) { + while (current !== target && !(next = current.$$nextSibling)) { + current = current.$parent; + } + } + } + + event.currentScope = null; + return event; + } + }; + + var $rootScope = new Scope(); + + //The internal queues. Expose them on the $rootScope for debugging/testing purposes. + var asyncQueue = $rootScope.$$asyncQueue = []; + var postDigestQueue = $rootScope.$$postDigestQueue = []; + var applyAsyncQueue = $rootScope.$$applyAsyncQueue = []; + + return $rootScope; + + + function beginPhase(phase) { + if ($rootScope.$$phase) { + throw $rootScopeMinErr('inprog', '{0} already in progress', $rootScope.$$phase); + } + + $rootScope.$$phase = phase; + } + + function clearPhase() { + $rootScope.$$phase = null; + } + + + function decrementListenerCount(current, count, name) { + do { + current.$$listenerCount[name] -= count; + + if (current.$$listenerCount[name] === 0) { + delete current.$$listenerCount[name]; + } + } while ((current = current.$parent)); + } + + /** + * function used as an initial value for watchers. + * because it's unique we can easily tell it apart from other values + */ + function initWatchVal() {} + + function flushApplyAsync() { + while (applyAsyncQueue.length) { + try { + applyAsyncQueue.shift()(); + } catch (e) { + $exceptionHandler(e); + } + } + applyAsyncId = null; + } + + function scheduleApplyAsync() { + if (applyAsyncId === null) { + applyAsyncId = $browser.defer(function() { + $rootScope.$apply(flushApplyAsync); + }); + } + } + }]; +} + +/** + * @description + * Private service to sanitize uris for links and images. Used by $compile and $sanitize. + */ +function $$SanitizeUriProvider() { + var aHrefSanitizationWhitelist = /^\s*(https?|ftp|mailto|tel|file):/, + imgSrcSanitizationWhitelist = /^\s*((https?|ftp|file|blob):|data:image\/)/; + + /** + * @description + * Retrieves or overrides the default regular expression that is used for whitelisting of safe + * urls during a[href] sanitization. + * + * The sanitization is a security measure aimed at prevent XSS attacks via html links. + * + * Any url about to be assigned to a[href] via data-binding is first normalized and turned into + * an absolute url. Afterwards, the url is matched against the `aHrefSanitizationWhitelist` + * regular expression. If a match is found, the original url is written into the dom. Otherwise, + * the absolute url is prefixed with `'unsafe:'` string and only then is it written into the DOM. + * + * @param {RegExp=} regexp New regexp to whitelist urls with. + * @returns {RegExp|ng.$compileProvider} Current RegExp if called without value or self for + * chaining otherwise. + */ + this.aHrefSanitizationWhitelist = function(regexp) { + if (isDefined(regexp)) { + aHrefSanitizationWhitelist = regexp; + return this; + } + return aHrefSanitizationWhitelist; + }; + + + /** + * @description + * Retrieves or overrides the default regular expression that is used for whitelisting of safe + * urls during img[src] sanitization. + * + * The sanitization is a security measure aimed at prevent XSS attacks via html links. + * + * Any url about to be assigned to img[src] via data-binding is first normalized and turned into + * an absolute url. Afterwards, the url is matched against the `imgSrcSanitizationWhitelist` + * regular expression. If a match is found, the original url is written into the dom. Otherwise, + * the absolute url is prefixed with `'unsafe:'` string and only then is it written into the DOM. + * + * @param {RegExp=} regexp New regexp to whitelist urls with. + * @returns {RegExp|ng.$compileProvider} Current RegExp if called without value or self for + * chaining otherwise. + */ + this.imgSrcSanitizationWhitelist = function(regexp) { + if (isDefined(regexp)) { + imgSrcSanitizationWhitelist = regexp; + return this; + } + return imgSrcSanitizationWhitelist; + }; + + this.$get = function() { + return function sanitizeUri(uri, isImage) { + var regex = isImage ? imgSrcSanitizationWhitelist : aHrefSanitizationWhitelist; + var normalizedVal; + normalizedVal = urlResolve(uri).href; + if (normalizedVal !== '' && !normalizedVal.match(regex)) { + return 'unsafe:' + normalizedVal; + } + return uri; + }; + }; +} + +var $sceMinErr = minErr('$sce'); + +var SCE_CONTEXTS = { + HTML: 'html', + CSS: 'css', + URL: 'url', + // RESOURCE_URL is a subtype of URL used in contexts where a privileged resource is sourced from a + // url. (e.g. ng-include, script src, templateUrl) + RESOURCE_URL: 'resourceUrl', + JS: 'js' +}; + +// Helper functions follow. + +function adjustMatcher(matcher) { + if (matcher === 'self') { + return matcher; + } else if (isString(matcher)) { + // Strings match exactly except for 2 wildcards - '*' and '**'. + // '*' matches any character except those from the set ':/.?&'. + // '**' matches any character (like .* in a RegExp). + // More than 2 *'s raises an error as it's ill defined. + if (matcher.indexOf('***') > -1) { + throw $sceMinErr('iwcard', + 'Illegal sequence *** in string matcher. String: {0}', matcher); + } + matcher = escapeForRegexp(matcher). + replace('\\*\\*', '.*'). + replace('\\*', '[^:/.?&;]*'); + return new RegExp('^' + matcher + '$'); + } else if (isRegExp(matcher)) { + // The only other type of matcher allowed is a Regexp. + // Match entire URL / disallow partial matches. + // Flags are reset (i.e. no global, ignoreCase or multiline) + return new RegExp('^' + matcher.source + '$'); + } else { + throw $sceMinErr('imatcher', + 'Matchers may only be "self", string patterns or RegExp objects'); + } +} + + +function adjustMatchers(matchers) { + var adjustedMatchers = []; + if (isDefined(matchers)) { + forEach(matchers, function(matcher) { + adjustedMatchers.push(adjustMatcher(matcher)); + }); + } + return adjustedMatchers; +} + + +/** + * @ngdoc service + * @name $sceDelegate + * @kind function + * + * @description + * + * `$sceDelegate` is a service that is used by the `$sce` service to provide {@link ng.$sce Strict + * Contextual Escaping (SCE)} services to AngularJS. + * + * Typically, you would configure or override the {@link ng.$sceDelegate $sceDelegate} instead of + * the `$sce` service to customize the way Strict Contextual Escaping works in AngularJS. This is + * because, while the `$sce` provides numerous shorthand methods, etc., you really only need to + * override 3 core functions (`trustAs`, `getTrusted` and `valueOf`) to replace the way things + * work because `$sce` delegates to `$sceDelegate` for these operations. + * + * Refer {@link ng.$sceDelegateProvider $sceDelegateProvider} to configure this service. + * + * The default instance of `$sceDelegate` should work out of the box with little pain. While you + * can override it completely to change the behavior of `$sce`, the common case would + * involve configuring the {@link ng.$sceDelegateProvider $sceDelegateProvider} instead by setting + * your own whitelists and blacklists for trusting URLs used for loading AngularJS resources such as + * templates. Refer {@link ng.$sceDelegateProvider#resourceUrlWhitelist + * $sceDelegateProvider.resourceUrlWhitelist} and {@link + * ng.$sceDelegateProvider#resourceUrlBlacklist $sceDelegateProvider.resourceUrlBlacklist} + */ + +/** + * @ngdoc provider + * @name $sceDelegateProvider + * @description + * + * The `$sceDelegateProvider` provider allows developers to configure the {@link ng.$sceDelegate + * $sceDelegate} service. This allows one to get/set the whitelists and blacklists used to ensure + * that the URLs used for sourcing Angular templates are safe. Refer {@link + * ng.$sceDelegateProvider#resourceUrlWhitelist $sceDelegateProvider.resourceUrlWhitelist} and + * {@link ng.$sceDelegateProvider#resourceUrlBlacklist $sceDelegateProvider.resourceUrlBlacklist} + * + * For the general details about this service in Angular, read the main page for {@link ng.$sce + * Strict Contextual Escaping (SCE)}. + * + * **Example**: Consider the following case. + * + * - your app is hosted at url `http://myapp.example.com/` + * - but some of your templates are hosted on other domains you control such as + * `http://srv01.assets.example.com/`,  `http://srv02.assets.example.com/`, etc. + * - and you have an open redirect at `http://myapp.example.com/clickThru?...`. + * + * Here is what a secure configuration for this scenario might look like: + * + * ``` + * angular.module('myApp', []).config(function($sceDelegateProvider) { + * $sceDelegateProvider.resourceUrlWhitelist([ + * // Allow same origin resource loads. + * 'self', + * // Allow loading from our assets domain. Notice the difference between * and **. + * 'http://srv*.assets.example.com/**' + * ]); + * + * // The blacklist overrides the whitelist so the open redirect here is blocked. + * $sceDelegateProvider.resourceUrlBlacklist([ + * 'http://myapp.example.com/clickThru**' + * ]); + * }); + * ``` + */ + +function $SceDelegateProvider() { + this.SCE_CONTEXTS = SCE_CONTEXTS; + + // Resource URLs can also be trusted by policy. + var resourceUrlWhitelist = ['self'], + resourceUrlBlacklist = []; + + /** + * @ngdoc method + * @name $sceDelegateProvider#resourceUrlWhitelist + * @kind function + * + * @param {Array=} whitelist When provided, replaces the resourceUrlWhitelist with the value + * provided. This must be an array or null. A snapshot of this array is used so further + * changes to the array are ignored. + * + * Follow {@link ng.$sce#resourceUrlPatternItem this link} for a description of the items + * allowed in this array. + * + * Note: **an empty whitelist array will block all URLs**! + * + * @return {Array} the currently set whitelist array. + * + * The **default value** when no whitelist has been explicitly set is `['self']` allowing only + * same origin resource requests. + * + * @description + * Sets/Gets the whitelist of trusted resource URLs. + */ + this.resourceUrlWhitelist = function(value) { + if (arguments.length) { + resourceUrlWhitelist = adjustMatchers(value); + } + return resourceUrlWhitelist; + }; + + /** + * @ngdoc method + * @name $sceDelegateProvider#resourceUrlBlacklist + * @kind function + * + * @param {Array=} blacklist When provided, replaces the resourceUrlBlacklist with the value + * provided. This must be an array or null. A snapshot of this array is used so further + * changes to the array are ignored. + * + * Follow {@link ng.$sce#resourceUrlPatternItem this link} for a description of the items + * allowed in this array. + * + * The typical usage for the blacklist is to **block + * [open redirects](http://cwe.mitre.org/data/definitions/601.html)** served by your domain as + * these would otherwise be trusted but actually return content from the redirected domain. + * + * Finally, **the blacklist overrides the whitelist** and has the final say. + * + * @return {Array} the currently set blacklist array. + * + * The **default value** when no whitelist has been explicitly set is the empty array (i.e. there + * is no blacklist.) + * + * @description + * Sets/Gets the blacklist of trusted resource URLs. + */ + + this.resourceUrlBlacklist = function(value) { + if (arguments.length) { + resourceUrlBlacklist = adjustMatchers(value); + } + return resourceUrlBlacklist; + }; + + this.$get = ['$injector', function($injector) { + + var htmlSanitizer = function htmlSanitizer(html) { + throw $sceMinErr('unsafe', 'Attempting to use an unsafe value in a safe context.'); + }; + + if ($injector.has('$sanitize')) { + htmlSanitizer = $injector.get('$sanitize'); + } + + + function matchUrl(matcher, parsedUrl) { + if (matcher === 'self') { + return urlIsSameOrigin(parsedUrl); + } else { + // definitely a regex. See adjustMatchers() + return !!matcher.exec(parsedUrl.href); + } + } + + function isResourceUrlAllowedByPolicy(url) { + var parsedUrl = urlResolve(url.toString()); + var i, n, allowed = false; + // Ensure that at least one item from the whitelist allows this url. + for (i = 0, n = resourceUrlWhitelist.length; i < n; i++) { + if (matchUrl(resourceUrlWhitelist[i], parsedUrl)) { + allowed = true; + break; + } + } + if (allowed) { + // Ensure that no item from the blacklist blocked this url. + for (i = 0, n = resourceUrlBlacklist.length; i < n; i++) { + if (matchUrl(resourceUrlBlacklist[i], parsedUrl)) { + allowed = false; + break; + } + } + } + return allowed; + } + + function generateHolderType(Base) { + var holderType = function TrustedValueHolderType(trustedValue) { + this.$$unwrapTrustedValue = function() { + return trustedValue; + }; + }; + if (Base) { + holderType.prototype = new Base(); + } + holderType.prototype.valueOf = function sceValueOf() { + return this.$$unwrapTrustedValue(); + }; + holderType.prototype.toString = function sceToString() { + return this.$$unwrapTrustedValue().toString(); + }; + return holderType; + } + + var trustedValueHolderBase = generateHolderType(), + byType = {}; + + byType[SCE_CONTEXTS.HTML] = generateHolderType(trustedValueHolderBase); + byType[SCE_CONTEXTS.CSS] = generateHolderType(trustedValueHolderBase); + byType[SCE_CONTEXTS.URL] = generateHolderType(trustedValueHolderBase); + byType[SCE_CONTEXTS.JS] = generateHolderType(trustedValueHolderBase); + byType[SCE_CONTEXTS.RESOURCE_URL] = generateHolderType(byType[SCE_CONTEXTS.URL]); + + /** + * @ngdoc method + * @name $sceDelegate#trustAs + * + * @description + * Returns an object that is trusted by angular for use in specified strict + * contextual escaping contexts (such as ng-bind-html, ng-include, any src + * attribute interpolation, any dom event binding attribute interpolation + * such as for onclick, etc.) that uses the provided value. + * See {@link ng.$sce $sce} for enabling strict contextual escaping. + * + * @param {string} type The kind of context in which this value is safe for use. e.g. url, + * resourceUrl, html, js and css. + * @param {*} value The value that that should be considered trusted/safe. + * @returns {*} A value that can be used to stand in for the provided `value` in places + * where Angular expects a $sce.trustAs() return value. + */ + function trustAs(type, trustedValue) { + var Constructor = (byType.hasOwnProperty(type) ? byType[type] : null); + if (!Constructor) { + throw $sceMinErr('icontext', + 'Attempted to trust a value in invalid context. Context: {0}; Value: {1}', + type, trustedValue); + } + if (trustedValue === null || trustedValue === undefined || trustedValue === '') { + return trustedValue; + } + // All the current contexts in SCE_CONTEXTS happen to be strings. In order to avoid trusting + // mutable objects, we ensure here that the value passed in is actually a string. + if (typeof trustedValue !== 'string') { + throw $sceMinErr('itype', + 'Attempted to trust a non-string value in a content requiring a string: Context: {0}', + type); + } + return new Constructor(trustedValue); + } + + /** + * @ngdoc method + * @name $sceDelegate#valueOf + * + * @description + * If the passed parameter had been returned by a prior call to {@link ng.$sceDelegate#trustAs + * `$sceDelegate.trustAs`}, returns the value that had been passed to {@link + * ng.$sceDelegate#trustAs `$sceDelegate.trustAs`}. + * + * If the passed parameter is not a value that had been returned by {@link + * ng.$sceDelegate#trustAs `$sceDelegate.trustAs`}, returns it as-is. + * + * @param {*} value The result of a prior {@link ng.$sceDelegate#trustAs `$sceDelegate.trustAs`} + * call or anything else. + * @returns {*} The `value` that was originally provided to {@link ng.$sceDelegate#trustAs + * `$sceDelegate.trustAs`} if `value` is the result of such a call. Otherwise, returns + * `value` unchanged. + */ + function valueOf(maybeTrusted) { + if (maybeTrusted instanceof trustedValueHolderBase) { + return maybeTrusted.$$unwrapTrustedValue(); + } else { + return maybeTrusted; + } + } + + /** + * @ngdoc method + * @name $sceDelegate#getTrusted + * + * @description + * Takes the result of a {@link ng.$sceDelegate#trustAs `$sceDelegate.trustAs`} call and + * returns the originally supplied value if the queried context type is a supertype of the + * created type. If this condition isn't satisfied, throws an exception. + * + * @param {string} type The kind of context in which this value is to be used. + * @param {*} maybeTrusted The result of a prior {@link ng.$sceDelegate#trustAs + * `$sceDelegate.trustAs`} call. + * @returns {*} The value the was originally provided to {@link ng.$sceDelegate#trustAs + * `$sceDelegate.trustAs`} if valid in this context. Otherwise, throws an exception. + */ + function getTrusted(type, maybeTrusted) { + if (maybeTrusted === null || maybeTrusted === undefined || maybeTrusted === '') { + return maybeTrusted; + } + var constructor = (byType.hasOwnProperty(type) ? byType[type] : null); + if (constructor && maybeTrusted instanceof constructor) { + return maybeTrusted.$$unwrapTrustedValue(); + } + // If we get here, then we may only take one of two actions. + // 1. sanitize the value for the requested type, or + // 2. throw an exception. + if (type === SCE_CONTEXTS.RESOURCE_URL) { + if (isResourceUrlAllowedByPolicy(maybeTrusted)) { + return maybeTrusted; + } else { + throw $sceMinErr('insecurl', + 'Blocked loading resource from url not allowed by $sceDelegate policy. URL: {0}', + maybeTrusted.toString()); + } + } else if (type === SCE_CONTEXTS.HTML) { + return htmlSanitizer(maybeTrusted); + } + throw $sceMinErr('unsafe', 'Attempting to use an unsafe value in a safe context.'); + } + + return { trustAs: trustAs, + getTrusted: getTrusted, + valueOf: valueOf }; + }]; +} + + +/** + * @ngdoc provider + * @name $sceProvider + * @description + * + * The $sceProvider provider allows developers to configure the {@link ng.$sce $sce} service. + * - enable/disable Strict Contextual Escaping (SCE) in a module + * - override the default implementation with a custom delegate + * + * Read more about {@link ng.$sce Strict Contextual Escaping (SCE)}. + */ + +/* jshint maxlen: false*/ + +/** + * @ngdoc service + * @name $sce + * @kind function + * + * @description + * + * `$sce` is a service that provides Strict Contextual Escaping services to AngularJS. + * + * # Strict Contextual Escaping + * + * Strict Contextual Escaping (SCE) is a mode in which AngularJS requires bindings in certain + * contexts to result in a value that is marked as safe to use for that context. One example of + * such a context is binding arbitrary html controlled by the user via `ng-bind-html`. We refer + * to these contexts as privileged or SCE contexts. + * + * As of version 1.2, Angular ships with SCE enabled by default. + * + * Note: When enabled (the default), IE<11 in quirks mode is not supported. In this mode, IE<11 allow + * one to execute arbitrary javascript by the use of the expression() syntax. Refer + * to learn more about them. + * You can ensure your document is in standards mode and not quirks mode by adding `` + * to the top of your HTML document. + * + * SCE assists in writing code in way that (a) is secure by default and (b) makes auditing for + * security vulnerabilities such as XSS, clickjacking, etc. a lot easier. + * + * Here's an example of a binding in a privileged context: + * + * ``` + * + *
      + * ``` + * + * Notice that `ng-bind-html` is bound to `userHtml` controlled by the user. With SCE + * disabled, this application allows the user to render arbitrary HTML into the DIV. + * In a more realistic example, one may be rendering user comments, blog articles, etc. via + * bindings. (HTML is just one example of a context where rendering user controlled input creates + * security vulnerabilities.) + * + * For the case of HTML, you might use a library, either on the client side, or on the server side, + * to sanitize unsafe HTML before binding to the value and rendering it in the document. + * + * How would you ensure that every place that used these types of bindings was bound to a value that + * was sanitized by your library (or returned as safe for rendering by your server?) How can you + * ensure that you didn't accidentally delete the line that sanitized the value, or renamed some + * properties/fields and forgot to update the binding to the sanitized value? + * + * To be secure by default, you want to ensure that any such bindings are disallowed unless you can + * determine that something explicitly says it's safe to use a value for binding in that + * context. You can then audit your code (a simple grep would do) to ensure that this is only done + * for those values that you can easily tell are safe - because they were received from your server, + * sanitized by your library, etc. You can organize your codebase to help with this - perhaps + * allowing only the files in a specific directory to do this. Ensuring that the internal API + * exposed by that code doesn't markup arbitrary values as safe then becomes a more manageable task. + * + * In the case of AngularJS' SCE service, one uses {@link ng.$sce#trustAs $sce.trustAs} + * (and shorthand methods such as {@link ng.$sce#trustAsHtml $sce.trustAsHtml}, etc.) to + * obtain values that will be accepted by SCE / privileged contexts. + * + * + * ## How does it work? + * + * In privileged contexts, directives and code will bind to the result of {@link ng.$sce#getTrusted + * $sce.getTrusted(context, value)} rather than to the value directly. Directives use {@link + * ng.$sce#parseAs $sce.parseAs} rather than `$parse` to watch attribute bindings, which performs the + * {@link ng.$sce#getTrusted $sce.getTrusted} behind the scenes on non-constant literals. + * + * As an example, {@link ng.directive:ngBindHtml ngBindHtml} uses {@link + * ng.$sce#parseAsHtml $sce.parseAsHtml(binding expression)}. Here's the actual code (slightly + * simplified): + * + * ``` + * var ngBindHtmlDirective = ['$sce', function($sce) { + * return function(scope, element, attr) { + * scope.$watch($sce.parseAsHtml(attr.ngBindHtml), function(value) { + * element.html(value || ''); + * }); + * }; + * }]; + * ``` + * + * ## Impact on loading templates + * + * This applies both to the {@link ng.directive:ngInclude `ng-include`} directive as well as + * `templateUrl`'s specified by {@link guide/directive directives}. + * + * By default, Angular only loads templates from the same domain and protocol as the application + * document. This is done by calling {@link ng.$sce#getTrustedResourceUrl + * $sce.getTrustedResourceUrl} on the template URL. To load templates from other domains and/or + * protocols, you may either either {@link ng.$sceDelegateProvider#resourceUrlWhitelist whitelist + * them} or {@link ng.$sce#trustAsResourceUrl wrap it} into a trusted value. + * + * *Please note*: + * The browser's + * [Same Origin Policy](https://code.google.com/p/browsersec/wiki/Part2#Same-origin_policy_for_XMLHttpRequest) + * and [Cross-Origin Resource Sharing (CORS)](http://www.w3.org/TR/cors/) + * policy apply in addition to this and may further restrict whether the template is successfully + * loaded. This means that without the right CORS policy, loading templates from a different domain + * won't work on all browsers. Also, loading templates from `file://` URL does not work on some + * browsers. + * + * ## This feels like too much overhead + * + * It's important to remember that SCE only applies to interpolation expressions. + * + * If your expressions are constant literals, they're automatically trusted and you don't need to + * call `$sce.trustAs` on them (remember to include the `ngSanitize` module) (e.g. + * `
      `) just works. + * + * Additionally, `a[href]` and `img[src]` automatically sanitize their URLs and do not pass them + * through {@link ng.$sce#getTrusted $sce.getTrusted}. SCE doesn't play a role here. + * + * The included {@link ng.$sceDelegate $sceDelegate} comes with sane defaults to allow you to load + * templates in `ng-include` from your application's domain without having to even know about SCE. + * It blocks loading templates from other domains or loading templates over http from an https + * served document. You can change these by setting your own custom {@link + * ng.$sceDelegateProvider#resourceUrlWhitelist whitelists} and {@link + * ng.$sceDelegateProvider#resourceUrlBlacklist blacklists} for matching such URLs. + * + * This significantly reduces the overhead. It is far easier to pay the small overhead and have an + * application that's secure and can be audited to verify that with much more ease than bolting + * security onto an application later. + * + * + * ## What trusted context types are supported? + * + * | Context | Notes | + * |---------------------|----------------| + * | `$sce.HTML` | For HTML that's safe to source into the application. The {@link ng.directive:ngBindHtml ngBindHtml} directive uses this context for bindings. If an unsafe value is encountered and the {@link ngSanitize $sanitize} module is present this will sanitize the value instead of throwing an error. | + * | `$sce.CSS` | For CSS that's safe to source into the application. Currently unused. Feel free to use it in your own directives. | + * | `$sce.URL` | For URLs that are safe to follow as links. Currently unused (`
      Note that `$sce.RESOURCE_URL` makes a stronger statement about the URL than `$sce.URL` does and therefore contexts requiring values trusted for `$sce.RESOURCE_URL` can be used anywhere that values trusted for `$sce.URL` are required. | + * | `$sce.JS` | For JavaScript that is safe to execute in your application's context. Currently unused. Feel free to use it in your own directives. | + * + * ## Format of items in {@link ng.$sceDelegateProvider#resourceUrlWhitelist resourceUrlWhitelist}/{@link ng.$sceDelegateProvider#resourceUrlBlacklist Blacklist}
      + * + * Each element in these arrays must be one of the following: + * + * - **'self'** + * - The special **string**, `'self'`, can be used to match against all URLs of the **same + * domain** as the application document using the **same protocol**. + * - **String** (except the special value `'self'`) + * - The string is matched against the full *normalized / absolute URL* of the resource + * being tested (substring matches are not good enough.) + * - There are exactly **two wildcard sequences** - `*` and `**`. All other characters + * match themselves. + * - `*`: matches zero or more occurrences of any character other than one of the following 6 + * characters: '`:`', '`/`', '`.`', '`?`', '`&`' and ';'. It's a useful wildcard for use + * in a whitelist. + * - `**`: matches zero or more occurrences of *any* character. As such, it's not + * not appropriate to use in for a scheme, domain, etc. as it would match too much. (e.g. + * http://**.example.com/ would match http://evil.com/?ignore=.example.com/ and that might + * not have been the intention.) Its usage at the very end of the path is ok. (e.g. + * http://foo.example.com/templates/**). + * - **RegExp** (*see caveat below*) + * - *Caveat*: While regular expressions are powerful and offer great flexibility, their syntax + * (and all the inevitable escaping) makes them *harder to maintain*. It's easy to + * accidentally introduce a bug when one updates a complex expression (imho, all regexes should + * have good test coverage.). For instance, the use of `.` in the regex is correct only in a + * small number of cases. A `.` character in the regex used when matching the scheme or a + * subdomain could be matched against a `:` or literal `.` that was likely not intended. It + * is highly recommended to use the string patterns and only fall back to regular expressions + * if they as a last resort. + * - The regular expression must be an instance of RegExp (i.e. not a string.) It is + * matched against the **entire** *normalized / absolute URL* of the resource being tested + * (even when the RegExp did not have the `^` and `$` codes.) In addition, any flags + * present on the RegExp (such as multiline, global, ignoreCase) are ignored. + * - If you are generating your JavaScript from some other templating engine (not + * recommended, e.g. in issue [#4006](https://github.com/angular/angular.js/issues/4006)), + * remember to escape your regular expression (and be aware that you might need more than + * one level of escaping depending on your templating engine and the way you interpolated + * the value.) Do make use of your platform's escaping mechanism as it might be good + * enough before coding your own. e.g. Ruby has + * [Regexp.escape(str)](http://www.ruby-doc.org/core-2.0.0/Regexp.html#method-c-escape) + * and Python has [re.escape](http://docs.python.org/library/re.html#re.escape). + * Javascript lacks a similar built in function for escaping. Take a look at Google + * Closure library's [goog.string.regExpEscape(s)]( + * http://docs.closure-library.googlecode.com/git/closure_goog_string_string.js.source.html#line962). + * + * Refer {@link ng.$sceDelegateProvider $sceDelegateProvider} for an example. + * + * ## Show me an example using SCE. + * + * + * + *
      + *

      + * User comments
      + * By default, HTML that isn't explicitly trusted (e.g. Alice's comment) is sanitized when + * $sanitize is available. If $sanitize isn't available, this results in an error instead of an + * exploit. + *
      + *
      + * {{userComment.name}}: + * + *
      + *
      + *
      + *
      + *
      + * + * + * angular.module('mySceApp', ['ngSanitize']) + * .controller('AppController', ['$http', '$templateCache', '$sce', + * function($http, $templateCache, $sce) { + * var self = this; + * $http.get("test_data.json", {cache: $templateCache}).success(function(userComments) { + * self.userComments = userComments; + * }); + * self.explicitlyTrustedHtml = $sce.trustAsHtml( + * 'Hover over this text.'); + * }]); + * + * + * + * [ + * { "name": "Alice", + * "htmlComment": + * "Is anyone reading this?" + * }, + * { "name": "Bob", + * "htmlComment": "Yes! Am I the only other one?" + * } + * ] + * + * + * + * describe('SCE doc demo', function() { + * it('should sanitize untrusted values', function() { + * expect(element.all(by.css('.htmlComment')).first().getInnerHtml()) + * .toBe('Is anyone reading this?'); + * }); + * + * it('should NOT sanitize explicitly trusted values', function() { + * expect(element(by.id('explicitlyTrustedHtml')).getInnerHtml()).toBe( + * 'Hover over this text.'); + * }); + * }); + * + *
      + * + * + * + * ## Can I disable SCE completely? + * + * Yes, you can. However, this is strongly discouraged. SCE gives you a lot of security benefits + * for little coding overhead. It will be much harder to take an SCE disabled application and + * either secure it on your own or enable SCE at a later stage. It might make sense to disable SCE + * for cases where you have a lot of existing code that was written before SCE was introduced and + * you're migrating them a module at a time. + * + * That said, here's how you can completely disable SCE: + * + * ``` + * angular.module('myAppWithSceDisabledmyApp', []).config(function($sceProvider) { + * // Completely disable SCE. For demonstration purposes only! + * // Do not use in new projects. + * $sceProvider.enabled(false); + * }); + * ``` + * + */ +/* jshint maxlen: 100 */ + +function $SceProvider() { + var enabled = true; + + /** + * @ngdoc method + * @name $sceProvider#enabled + * @kind function + * + * @param {boolean=} value If provided, then enables/disables SCE. + * @return {boolean} true if SCE is enabled, false otherwise. + * + * @description + * Enables/disables SCE and returns the current value. + */ + this.enabled = function(value) { + if (arguments.length) { + enabled = !!value; + } + return enabled; + }; + + + /* Design notes on the default implementation for SCE. + * + * The API contract for the SCE delegate + * ------------------------------------- + * The SCE delegate object must provide the following 3 methods: + * + * - trustAs(contextEnum, value) + * This method is used to tell the SCE service that the provided value is OK to use in the + * contexts specified by contextEnum. It must return an object that will be accepted by + * getTrusted() for a compatible contextEnum and return this value. + * + * - valueOf(value) + * For values that were not produced by trustAs(), return them as is. For values that were + * produced by trustAs(), return the corresponding input value to trustAs. Basically, if + * trustAs is wrapping the given values into some type, this operation unwraps it when given + * such a value. + * + * - getTrusted(contextEnum, value) + * This function should return the a value that is safe to use in the context specified by + * contextEnum or throw and exception otherwise. + * + * NOTE: This contract deliberately does NOT state that values returned by trustAs() must be + * opaque or wrapped in some holder object. That happens to be an implementation detail. For + * instance, an implementation could maintain a registry of all trusted objects by context. In + * such a case, trustAs() would return the same object that was passed in. getTrusted() would + * return the same object passed in if it was found in the registry under a compatible context or + * throw an exception otherwise. An implementation might only wrap values some of the time based + * on some criteria. getTrusted() might return a value and not throw an exception for special + * constants or objects even if not wrapped. All such implementations fulfill this contract. + * + * + * A note on the inheritance model for SCE contexts + * ------------------------------------------------ + * I've used inheritance and made RESOURCE_URL wrapped types a subtype of URL wrapped types. This + * is purely an implementation details. + * + * The contract is simply this: + * + * getTrusted($sce.RESOURCE_URL, value) succeeding implies that getTrusted($sce.URL, value) + * will also succeed. + * + * Inheritance happens to capture this in a natural way. In some future, we + * may not use inheritance anymore. That is OK because no code outside of + * sce.js and sceSpecs.js would need to be aware of this detail. + */ + + this.$get = ['$parse', '$sceDelegate', function( + $parse, $sceDelegate) { + // Prereq: Ensure that we're not running in IE<11 quirks mode. In that mode, IE < 11 allow + // the "expression(javascript expression)" syntax which is insecure. + if (enabled && msie < 8) { + throw $sceMinErr('iequirks', + 'Strict Contextual Escaping does not support Internet Explorer version < 11 in quirks ' + + 'mode. You can fix this by adding the text to the top of your HTML ' + + 'document. See http://docs.angularjs.org/api/ng.$sce for more information.'); + } + + var sce = shallowCopy(SCE_CONTEXTS); + + /** + * @ngdoc method + * @name $sce#isEnabled + * @kind function + * + * @return {Boolean} true if SCE is enabled, false otherwise. If you want to set the value, you + * have to do it at module config time on {@link ng.$sceProvider $sceProvider}. + * + * @description + * Returns a boolean indicating if SCE is enabled. + */ + sce.isEnabled = function() { + return enabled; + }; + sce.trustAs = $sceDelegate.trustAs; + sce.getTrusted = $sceDelegate.getTrusted; + sce.valueOf = $sceDelegate.valueOf; + + if (!enabled) { + sce.trustAs = sce.getTrusted = function(type, value) { return value; }; + sce.valueOf = identity; + } + + /** + * @ngdoc method + * @name $sce#parseAs + * + * @description + * Converts Angular {@link guide/expression expression} into a function. This is like {@link + * ng.$parse $parse} and is identical when the expression is a literal constant. Otherwise, it + * wraps the expression in a call to {@link ng.$sce#getTrusted $sce.getTrusted(*type*, + * *result*)} + * + * @param {string} type The kind of SCE context in which this result will be used. + * @param {string} expression String expression to compile. + * @returns {function(context, locals)} a function which represents the compiled expression: + * + * * `context` – `{object}` – an object against which any expressions embedded in the strings + * are evaluated against (typically a scope object). + * * `locals` – `{object=}` – local variables context object, useful for overriding values in + * `context`. + */ + sce.parseAs = function sceParseAs(type, expr) { + var parsed = $parse(expr); + if (parsed.literal && parsed.constant) { + return parsed; + } else { + return $parse(expr, function(value) { + return sce.getTrusted(type, value); + }); + } + }; + + /** + * @ngdoc method + * @name $sce#trustAs + * + * @description + * Delegates to {@link ng.$sceDelegate#trustAs `$sceDelegate.trustAs`}. As such, + * returns an object that is trusted by angular for use in specified strict contextual + * escaping contexts (such as ng-bind-html, ng-include, any src attribute + * interpolation, any dom event binding attribute interpolation such as for onclick, etc.) + * that uses the provided value. See * {@link ng.$sce $sce} for enabling strict contextual + * escaping. + * + * @param {string} type The kind of context in which this value is safe for use. e.g. url, + * resource_url, html, js and css. + * @param {*} value The value that that should be considered trusted/safe. + * @returns {*} A value that can be used to stand in for the provided `value` in places + * where Angular expects a $sce.trustAs() return value. + */ + + /** + * @ngdoc method + * @name $sce#trustAsHtml + * + * @description + * Shorthand method. `$sce.trustAsHtml(value)` → + * {@link ng.$sceDelegate#trustAs `$sceDelegate.trustAs($sce.HTML, value)`} + * + * @param {*} value The value to trustAs. + * @returns {*} An object that can be passed to {@link ng.$sce#getTrustedHtml + * $sce.getTrustedHtml(value)} to obtain the original value. (privileged directives + * only accept expressions that are either literal constants or are the + * return value of {@link ng.$sce#trustAs $sce.trustAs}.) + */ + + /** + * @ngdoc method + * @name $sce#trustAsUrl + * + * @description + * Shorthand method. `$sce.trustAsUrl(value)` → + * {@link ng.$sceDelegate#trustAs `$sceDelegate.trustAs($sce.URL, value)`} + * + * @param {*} value The value to trustAs. + * @returns {*} An object that can be passed to {@link ng.$sce#getTrustedUrl + * $sce.getTrustedUrl(value)} to obtain the original value. (privileged directives + * only accept expressions that are either literal constants or are the + * return value of {@link ng.$sce#trustAs $sce.trustAs}.) + */ + + /** + * @ngdoc method + * @name $sce#trustAsResourceUrl + * + * @description + * Shorthand method. `$sce.trustAsResourceUrl(value)` → + * {@link ng.$sceDelegate#trustAs `$sceDelegate.trustAs($sce.RESOURCE_URL, value)`} + * + * @param {*} value The value to trustAs. + * @returns {*} An object that can be passed to {@link ng.$sce#getTrustedResourceUrl + * $sce.getTrustedResourceUrl(value)} to obtain the original value. (privileged directives + * only accept expressions that are either literal constants or are the return + * value of {@link ng.$sce#trustAs $sce.trustAs}.) + */ + + /** + * @ngdoc method + * @name $sce#trustAsJs + * + * @description + * Shorthand method. `$sce.trustAsJs(value)` → + * {@link ng.$sceDelegate#trustAs `$sceDelegate.trustAs($sce.JS, value)`} + * + * @param {*} value The value to trustAs. + * @returns {*} An object that can be passed to {@link ng.$sce#getTrustedJs + * $sce.getTrustedJs(value)} to obtain the original value. (privileged directives + * only accept expressions that are either literal constants or are the + * return value of {@link ng.$sce#trustAs $sce.trustAs}.) + */ + + /** + * @ngdoc method + * @name $sce#getTrusted + * + * @description + * Delegates to {@link ng.$sceDelegate#getTrusted `$sceDelegate.getTrusted`}. As such, + * takes the result of a {@link ng.$sce#trustAs `$sce.trustAs`}() call and returns the + * originally supplied value if the queried context type is a supertype of the created type. + * If this condition isn't satisfied, throws an exception. + * + * @param {string} type The kind of context in which this value is to be used. + * @param {*} maybeTrusted The result of a prior {@link ng.$sce#trustAs `$sce.trustAs`} + * call. + * @returns {*} The value the was originally provided to + * {@link ng.$sce#trustAs `$sce.trustAs`} if valid in this context. + * Otherwise, throws an exception. + */ + + /** + * @ngdoc method + * @name $sce#getTrustedHtml + * + * @description + * Shorthand method. `$sce.getTrustedHtml(value)` → + * {@link ng.$sceDelegate#getTrusted `$sceDelegate.getTrusted($sce.HTML, value)`} + * + * @param {*} value The value to pass to `$sce.getTrusted`. + * @returns {*} The return value of `$sce.getTrusted($sce.HTML, value)` + */ + + /** + * @ngdoc method + * @name $sce#getTrustedCss + * + * @description + * Shorthand method. `$sce.getTrustedCss(value)` → + * {@link ng.$sceDelegate#getTrusted `$sceDelegate.getTrusted($sce.CSS, value)`} + * + * @param {*} value The value to pass to `$sce.getTrusted`. + * @returns {*} The return value of `$sce.getTrusted($sce.CSS, value)` + */ + + /** + * @ngdoc method + * @name $sce#getTrustedUrl + * + * @description + * Shorthand method. `$sce.getTrustedUrl(value)` → + * {@link ng.$sceDelegate#getTrusted `$sceDelegate.getTrusted($sce.URL, value)`} + * + * @param {*} value The value to pass to `$sce.getTrusted`. + * @returns {*} The return value of `$sce.getTrusted($sce.URL, value)` + */ + + /** + * @ngdoc method + * @name $sce#getTrustedResourceUrl + * + * @description + * Shorthand method. `$sce.getTrustedResourceUrl(value)` → + * {@link ng.$sceDelegate#getTrusted `$sceDelegate.getTrusted($sce.RESOURCE_URL, value)`} + * + * @param {*} value The value to pass to `$sceDelegate.getTrusted`. + * @returns {*} The return value of `$sce.getTrusted($sce.RESOURCE_URL, value)` + */ + + /** + * @ngdoc method + * @name $sce#getTrustedJs + * + * @description + * Shorthand method. `$sce.getTrustedJs(value)` → + * {@link ng.$sceDelegate#getTrusted `$sceDelegate.getTrusted($sce.JS, value)`} + * + * @param {*} value The value to pass to `$sce.getTrusted`. + * @returns {*} The return value of `$sce.getTrusted($sce.JS, value)` + */ + + /** + * @ngdoc method + * @name $sce#parseAsHtml + * + * @description + * Shorthand method. `$sce.parseAsHtml(expression string)` → + * {@link ng.$sce#parseAs `$sce.parseAs($sce.HTML, value)`} + * + * @param {string} expression String expression to compile. + * @returns {function(context, locals)} a function which represents the compiled expression: + * + * * `context` – `{object}` – an object against which any expressions embedded in the strings + * are evaluated against (typically a scope object). + * * `locals` – `{object=}` – local variables context object, useful for overriding values in + * `context`. + */ + + /** + * @ngdoc method + * @name $sce#parseAsCss + * + * @description + * Shorthand method. `$sce.parseAsCss(value)` → + * {@link ng.$sce#parseAs `$sce.parseAs($sce.CSS, value)`} + * + * @param {string} expression String expression to compile. + * @returns {function(context, locals)} a function which represents the compiled expression: + * + * * `context` – `{object}` – an object against which any expressions embedded in the strings + * are evaluated against (typically a scope object). + * * `locals` – `{object=}` – local variables context object, useful for overriding values in + * `context`. + */ + + /** + * @ngdoc method + * @name $sce#parseAsUrl + * + * @description + * Shorthand method. `$sce.parseAsUrl(value)` → + * {@link ng.$sce#parseAs `$sce.parseAs($sce.URL, value)`} + * + * @param {string} expression String expression to compile. + * @returns {function(context, locals)} a function which represents the compiled expression: + * + * * `context` – `{object}` – an object against which any expressions embedded in the strings + * are evaluated against (typically a scope object). + * * `locals` – `{object=}` – local variables context object, useful for overriding values in + * `context`. + */ + + /** + * @ngdoc method + * @name $sce#parseAsResourceUrl + * + * @description + * Shorthand method. `$sce.parseAsResourceUrl(value)` → + * {@link ng.$sce#parseAs `$sce.parseAs($sce.RESOURCE_URL, value)`} + * + * @param {string} expression String expression to compile. + * @returns {function(context, locals)} a function which represents the compiled expression: + * + * * `context` – `{object}` – an object against which any expressions embedded in the strings + * are evaluated against (typically a scope object). + * * `locals` – `{object=}` – local variables context object, useful for overriding values in + * `context`. + */ + + /** + * @ngdoc method + * @name $sce#parseAsJs + * + * @description + * Shorthand method. `$sce.parseAsJs(value)` → + * {@link ng.$sce#parseAs `$sce.parseAs($sce.JS, value)`} + * + * @param {string} expression String expression to compile. + * @returns {function(context, locals)} a function which represents the compiled expression: + * + * * `context` – `{object}` – an object against which any expressions embedded in the strings + * are evaluated against (typically a scope object). + * * `locals` – `{object=}` – local variables context object, useful for overriding values in + * `context`. + */ + + // Shorthand delegations. + var parse = sce.parseAs, + getTrusted = sce.getTrusted, + trustAs = sce.trustAs; + + forEach(SCE_CONTEXTS, function(enumValue, name) { + var lName = lowercase(name); + sce[camelCase("parse_as_" + lName)] = function(expr) { + return parse(enumValue, expr); + }; + sce[camelCase("get_trusted_" + lName)] = function(value) { + return getTrusted(enumValue, value); + }; + sce[camelCase("trust_as_" + lName)] = function(value) { + return trustAs(enumValue, value); + }; + }); + + return sce; + }]; +} + +/** + * !!! This is an undocumented "private" service !!! + * + * @name $sniffer + * @requires $window + * @requires $document + * + * @property {boolean} history Does the browser support html5 history api ? + * @property {boolean} transitions Does the browser support CSS transition events ? + * @property {boolean} animations Does the browser support CSS animation events ? + * + * @description + * This is very simple implementation of testing browser's features. + */ +function $SnifferProvider() { + this.$get = ['$window', '$document', function($window, $document) { + var eventSupport = {}, + android = + int((/android (\d+)/.exec(lowercase(($window.navigator || {}).userAgent)) || [])[1]), + boxee = /Boxee/i.test(($window.navigator || {}).userAgent), + document = $document[0] || {}, + vendorPrefix, + vendorRegex = /^(Moz|webkit|ms)(?=[A-Z])/, + bodyStyle = document.body && document.body.style, + transitions = false, + animations = false, + match; + + if (bodyStyle) { + for (var prop in bodyStyle) { + if (match = vendorRegex.exec(prop)) { + vendorPrefix = match[0]; + vendorPrefix = vendorPrefix.substr(0, 1).toUpperCase() + vendorPrefix.substr(1); + break; + } + } + + if (!vendorPrefix) { + vendorPrefix = ('WebkitOpacity' in bodyStyle) && 'webkit'; + } + + transitions = !!(('transition' in bodyStyle) || (vendorPrefix + 'Transition' in bodyStyle)); + animations = !!(('animation' in bodyStyle) || (vendorPrefix + 'Animation' in bodyStyle)); + + if (android && (!transitions || !animations)) { + transitions = isString(document.body.style.webkitTransition); + animations = isString(document.body.style.webkitAnimation); + } + } + + + return { + // Android has history.pushState, but it does not update location correctly + // so let's not use the history API at all. + // http://code.google.com/p/android/issues/detail?id=17471 + // https://github.com/angular/angular.js/issues/904 + + // older webkit browser (533.9) on Boxee box has exactly the same problem as Android has + // so let's not use the history API also + // We are purposefully using `!(android < 4)` to cover the case when `android` is undefined + // jshint -W018 + history: !!($window.history && $window.history.pushState && !(android < 4) && !boxee), + // jshint +W018 + hasEvent: function(event) { + // IE9 implements 'input' event it's so fubared that we rather pretend that it doesn't have + // it. In particular the event is not fired when backspace or delete key are pressed or + // when cut operation is performed. + // IE10+ implements 'input' event but it erroneously fires under various situations, + // e.g. when placeholder changes, or a form is focused. + if (event === 'input' && msie <= 11) return false; + + if (isUndefined(eventSupport[event])) { + var divElm = document.createElement('div'); + eventSupport[event] = 'on' + event in divElm; + } + + return eventSupport[event]; + }, + csp: csp(), + vendorPrefix: vendorPrefix, + transitions: transitions, + animations: animations, + android: android + }; + }]; +} + +var $compileMinErr = minErr('$compile'); + +/** + * @ngdoc service + * @name $templateRequest + * + * @description + * The `$templateRequest` service downloads the provided template using `$http` and, upon success, + * stores the contents inside of `$templateCache`. If the HTTP request fails or the response data + * of the HTTP request is empty, a `$compile` error will be thrown (the exception can be thwarted + * by setting the 2nd parameter of the function to true). + * + * @param {string} tpl The HTTP request template URL + * @param {boolean=} ignoreRequestError Whether or not to ignore the exception when the request fails or the template is empty + * + * @return {Promise} the HTTP Promise for the given. + * + * @property {number} totalPendingRequests total amount of pending template requests being downloaded. + */ +function $TemplateRequestProvider() { + this.$get = ['$templateCache', '$http', '$q', function($templateCache, $http, $q) { + function handleRequestFn(tpl, ignoreRequestError) { + var self = handleRequestFn; + self.totalPendingRequests++; + + var transformResponse = $http.defaults && $http.defaults.transformResponse; + + if (isArray(transformResponse)) { + transformResponse = transformResponse.filter(function(transformer) { + return transformer !== defaultHttpResponseTransform; + }); + } else if (transformResponse === defaultHttpResponseTransform) { + transformResponse = null; + } + + var httpOptions = { + cache: $templateCache, + transformResponse: transformResponse + }; + + return $http.get(tpl, httpOptions) + .then(function(response) { + self.totalPendingRequests--; + return response.data; + }, handleError); + + function handleError(resp) { + self.totalPendingRequests--; + if (!ignoreRequestError) { + throw $compileMinErr('tpload', 'Failed to load template: {0}', tpl); + } + return $q.reject(resp); + } + } + + handleRequestFn.totalPendingRequests = 0; + + return handleRequestFn; + }]; +} + +function $$TestabilityProvider() { + this.$get = ['$rootScope', '$browser', '$location', + function($rootScope, $browser, $location) { + + /** + * @name $testability + * + * @description + * The private $$testability service provides a collection of methods for use when debugging + * or by automated test and debugging tools. + */ + var testability = {}; + + /** + * @name $$testability#findBindings + * + * @description + * Returns an array of elements that are bound (via ng-bind or {{}}) + * to expressions matching the input. + * + * @param {Element} element The element root to search from. + * @param {string} expression The binding expression to match. + * @param {boolean} opt_exactMatch If true, only returns exact matches + * for the expression. Filters and whitespace are ignored. + */ + testability.findBindings = function(element, expression, opt_exactMatch) { + var bindings = element.getElementsByClassName('ng-binding'); + var matches = []; + forEach(bindings, function(binding) { + var dataBinding = angular.element(binding).data('$binding'); + if (dataBinding) { + forEach(dataBinding, function(bindingName) { + if (opt_exactMatch) { + var matcher = new RegExp('(^|\\s)' + escapeForRegexp(expression) + '(\\s|\\||$)'); + if (matcher.test(bindingName)) { + matches.push(binding); + } + } else { + if (bindingName.indexOf(expression) != -1) { + matches.push(binding); + } + } + }); + } + }); + return matches; + }; + + /** + * @name $$testability#findModels + * + * @description + * Returns an array of elements that are two-way found via ng-model to + * expressions matching the input. + * + * @param {Element} element The element root to search from. + * @param {string} expression The model expression to match. + * @param {boolean} opt_exactMatch If true, only returns exact matches + * for the expression. + */ + testability.findModels = function(element, expression, opt_exactMatch) { + var prefixes = ['ng-', 'data-ng-', 'ng\\:']; + for (var p = 0; p < prefixes.length; ++p) { + var attributeEquals = opt_exactMatch ? '=' : '*='; + var selector = '[' + prefixes[p] + 'model' + attributeEquals + '"' + expression + '"]'; + var elements = element.querySelectorAll(selector); + if (elements.length) { + return elements; + } + } + }; + + /** + * @name $$testability#getLocation + * + * @description + * Shortcut for getting the location in a browser agnostic way. Returns + * the path, search, and hash. (e.g. /path?a=b#hash) + */ + testability.getLocation = function() { + return $location.url(); + }; + + /** + * @name $$testability#setLocation + * + * @description + * Shortcut for navigating to a location without doing a full page reload. + * + * @param {string} url The location url (path, search and hash, + * e.g. /path?a=b#hash) to go to. + */ + testability.setLocation = function(url) { + if (url !== $location.url()) { + $location.url(url); + $rootScope.$digest(); + } + }; + + /** + * @name $$testability#whenStable + * + * @description + * Calls the callback when $timeout and $http requests are completed. + * + * @param {function} callback + */ + testability.whenStable = function(callback) { + $browser.notifyWhenNoOutstandingRequests(callback); + }; + + return testability; + }]; +} + +function $TimeoutProvider() { + this.$get = ['$rootScope', '$browser', '$q', '$$q', '$exceptionHandler', + function($rootScope, $browser, $q, $$q, $exceptionHandler) { + var deferreds = {}; + + + /** + * @ngdoc service + * @name $timeout + * + * @description + * Angular's wrapper for `window.setTimeout`. The `fn` function is wrapped into a try/catch + * block and delegates any exceptions to + * {@link ng.$exceptionHandler $exceptionHandler} service. + * + * The return value of registering a timeout function is a promise, which will be resolved when + * the timeout is reached and the timeout function is executed. + * + * To cancel a timeout request, call `$timeout.cancel(promise)`. + * + * In tests you can use {@link ngMock.$timeout `$timeout.flush()`} to + * synchronously flush the queue of deferred functions. + * + * @param {function()} fn A function, whose execution should be delayed. + * @param {number=} [delay=0] Delay in milliseconds. + * @param {boolean=} [invokeApply=true] If set to `false` skips model dirty checking, otherwise + * will invoke `fn` within the {@link ng.$rootScope.Scope#$apply $apply} block. + * @returns {Promise} Promise that will be resolved when the timeout is reached. The value this + * promise will be resolved with is the return value of the `fn` function. + * + */ + function timeout(fn, delay, invokeApply) { + var skipApply = (isDefined(invokeApply) && !invokeApply), + deferred = (skipApply ? $$q : $q).defer(), + promise = deferred.promise, + timeoutId; + + timeoutId = $browser.defer(function() { + try { + deferred.resolve(fn()); + } catch (e) { + deferred.reject(e); + $exceptionHandler(e); + } + finally { + delete deferreds[promise.$$timeoutId]; + } + + if (!skipApply) $rootScope.$apply(); + }, delay); + + promise.$$timeoutId = timeoutId; + deferreds[timeoutId] = deferred; + + return promise; + } + + + /** + * @ngdoc method + * @name $timeout#cancel + * + * @description + * Cancels a task associated with the `promise`. As a result of this, the promise will be + * resolved with a rejection. + * + * @param {Promise=} promise Promise returned by the `$timeout` function. + * @returns {boolean} Returns `true` if the task hasn't executed yet and was successfully + * canceled. + */ + timeout.cancel = function(promise) { + if (promise && promise.$$timeoutId in deferreds) { + deferreds[promise.$$timeoutId].reject('canceled'); + delete deferreds[promise.$$timeoutId]; + return $browser.defer.cancel(promise.$$timeoutId); + } + return false; + }; + + return timeout; + }]; +} + +// NOTE: The usage of window and document instead of $window and $document here is +// deliberate. This service depends on the specific behavior of anchor nodes created by the +// browser (resolving and parsing URLs) that is unlikely to be provided by mock objects and +// cause us to break tests. In addition, when the browser resolves a URL for XHR, it +// doesn't know about mocked locations and resolves URLs to the real document - which is +// exactly the behavior needed here. There is little value is mocking these out for this +// service. +var urlParsingNode = document.createElement("a"); +var originUrl = urlResolve(window.location.href); + + +/** + * + * Implementation Notes for non-IE browsers + * ---------------------------------------- + * Assigning a URL to the href property of an anchor DOM node, even one attached to the DOM, + * results both in the normalizing and parsing of the URL. Normalizing means that a relative + * URL will be resolved into an absolute URL in the context of the application document. + * Parsing means that the anchor node's host, hostname, protocol, port, pathname and related + * properties are all populated to reflect the normalized URL. This approach has wide + * compatibility - Safari 1+, Mozilla 1+, Opera 7+,e etc. See + * http://www.aptana.com/reference/html/api/HTMLAnchorElement.html + * + * Implementation Notes for IE + * --------------------------- + * IE >= 8 and <= 10 normalizes the URL when assigned to the anchor node similar to the other + * browsers. However, the parsed components will not be set if the URL assigned did not specify + * them. (e.g. if you assign a.href = "foo", then a.protocol, a.host, etc. will be empty.) We + * work around that by performing the parsing in a 2nd step by taking a previously normalized + * URL (e.g. by assigning to a.href) and assigning it a.href again. This correctly populates the + * properties such as protocol, hostname, port, etc. + * + * IE7 does not normalize the URL when assigned to an anchor node. (Apparently, it does, if one + * uses the inner HTML approach to assign the URL as part of an HTML snippet - + * http://stackoverflow.com/a/472729) However, setting img[src] does normalize the URL. + * Unfortunately, setting img[src] to something like "javascript:foo" on IE throws an exception. + * Since the primary usage for normalizing URLs is to sanitize such URLs, we can't use that + * method and IE < 8 is unsupported. + * + * References: + * http://developer.mozilla.org/en-US/docs/Web/API/HTMLAnchorElement + * http://www.aptana.com/reference/html/api/HTMLAnchorElement.html + * http://url.spec.whatwg.org/#urlutils + * https://github.com/angular/angular.js/pull/2902 + * http://james.padolsey.com/javascript/parsing-urls-with-the-dom/ + * + * @kind function + * @param {string} url The URL to be parsed. + * @description Normalizes and parses a URL. + * @returns {object} Returns the normalized URL as a dictionary. + * + * | member name | Description | + * |---------------|----------------| + * | href | A normalized version of the provided URL if it was not an absolute URL | + * | protocol | The protocol including the trailing colon | + * | host | The host and port (if the port is non-default) of the normalizedUrl | + * | search | The search params, minus the question mark | + * | hash | The hash string, minus the hash symbol + * | hostname | The hostname + * | port | The port, without ":" + * | pathname | The pathname, beginning with "/" + * + */ +function urlResolve(url) { + var href = url; + + if (msie) { + // Normalize before parse. Refer Implementation Notes on why this is + // done in two steps on IE. + urlParsingNode.setAttribute("href", href); + href = urlParsingNode.href; + } + + urlParsingNode.setAttribute('href', href); + + // urlParsingNode provides the UrlUtils interface - http://url.spec.whatwg.org/#urlutils + return { + href: urlParsingNode.href, + protocol: urlParsingNode.protocol ? urlParsingNode.protocol.replace(/:$/, '') : '', + host: urlParsingNode.host, + search: urlParsingNode.search ? urlParsingNode.search.replace(/^\?/, '') : '', + hash: urlParsingNode.hash ? urlParsingNode.hash.replace(/^#/, '') : '', + hostname: urlParsingNode.hostname, + port: urlParsingNode.port, + pathname: (urlParsingNode.pathname.charAt(0) === '/') + ? urlParsingNode.pathname + : '/' + urlParsingNode.pathname + }; +} + +/** + * Parse a request URL and determine whether this is a same-origin request as the application document. + * + * @param {string|object} requestUrl The url of the request as a string that will be resolved + * or a parsed URL object. + * @returns {boolean} Whether the request is for the same origin as the application document. + */ +function urlIsSameOrigin(requestUrl) { + var parsed = (isString(requestUrl)) ? urlResolve(requestUrl) : requestUrl; + return (parsed.protocol === originUrl.protocol && + parsed.host === originUrl.host); +} + +/** + * @ngdoc service + * @name $window + * + * @description + * A reference to the browser's `window` object. While `window` + * is globally available in JavaScript, it causes testability problems, because + * it is a global variable. In angular we always refer to it through the + * `$window` service, so it may be overridden, removed or mocked for testing. + * + * Expressions, like the one defined for the `ngClick` directive in the example + * below, are evaluated with respect to the current scope. Therefore, there is + * no risk of inadvertently coding in a dependency on a global value in such an + * expression. + * + * @example + + + +
      + + +
      +
      + + it('should display the greeting in the input box', function() { + element(by.model('greeting')).sendKeys('Hello, E2E Tests'); + // If we click the button it will block the test runner + // element(':button').click(); + }); + +
      + */ +function $WindowProvider() { + this.$get = valueFn(window); +} + +/* global currencyFilter: true, + dateFilter: true, + filterFilter: true, + jsonFilter: true, + limitToFilter: true, + lowercaseFilter: true, + numberFilter: true, + orderByFilter: true, + uppercaseFilter: true, + */ + +/** + * @ngdoc provider + * @name $filterProvider + * @description + * + * Filters are just functions which transform input to an output. However filters need to be + * Dependency Injected. To achieve this a filter definition consists of a factory function which is + * annotated with dependencies and is responsible for creating a filter function. + * + * ```js + * // Filter registration + * function MyModule($provide, $filterProvider) { + * // create a service to demonstrate injection (not always needed) + * $provide.value('greet', function(name){ + * return 'Hello ' + name + '!'; + * }); + * + * // register a filter factory which uses the + * // greet service to demonstrate DI. + * $filterProvider.register('greet', function(greet){ + * // return the filter function which uses the greet service + * // to generate salutation + * return function(text) { + * // filters need to be forgiving so check input validity + * return text && greet(text) || text; + * }; + * }); + * } + * ``` + * + * The filter function is registered with the `$injector` under the filter name suffix with + * `Filter`. + * + * ```js + * it('should be the same instance', inject( + * function($filterProvider) { + * $filterProvider.register('reverse', function(){ + * return ...; + * }); + * }, + * function($filter, reverseFilter) { + * expect($filter('reverse')).toBe(reverseFilter); + * }); + * ``` + * + * + * For more information about how angular filters work, and how to create your own filters, see + * {@link guide/filter Filters} in the Angular Developer Guide. + */ + +/** + * @ngdoc service + * @name $filter + * @kind function + * @description + * Filters are used for formatting data displayed to the user. + * + * The general syntax in templates is as follows: + * + * {{ expression [| filter_name[:parameter_value] ... ] }} + * + * @param {String} name Name of the filter function to retrieve + * @return {Function} the filter function + * @example + + +
      +

      {{ originalText }}

      +

      {{ filteredText }}

      +
      +
      + + + angular.module('filterExample', []) + .controller('MainCtrl', function($scope, $filter) { + $scope.originalText = 'hello'; + $scope.filteredText = $filter('uppercase')($scope.originalText); + }); + +
      + */ +$FilterProvider.$inject = ['$provide']; +function $FilterProvider($provide) { + var suffix = 'Filter'; + + /** + * @ngdoc method + * @name $filterProvider#register + * @param {string|Object} name Name of the filter function, or an object map of filters where + * the keys are the filter names and the values are the filter factories. + * @returns {Object} Registered filter instance, or if a map of filters was provided then a map + * of the registered filter instances. + */ + function register(name, factory) { + if (isObject(name)) { + var filters = {}; + forEach(name, function(filter, key) { + filters[key] = register(key, filter); + }); + return filters; + } else { + return $provide.factory(name + suffix, factory); + } + } + this.register = register; + + this.$get = ['$injector', function($injector) { + return function(name) { + return $injector.get(name + suffix); + }; + }]; + + //////////////////////////////////////// + + /* global + currencyFilter: false, + dateFilter: false, + filterFilter: false, + jsonFilter: false, + limitToFilter: false, + lowercaseFilter: false, + numberFilter: false, + orderByFilter: false, + uppercaseFilter: false, + */ + + register('currency', currencyFilter); + register('date', dateFilter); + register('filter', filterFilter); + register('json', jsonFilter); + register('limitTo', limitToFilter); + register('lowercase', lowercaseFilter); + register('number', numberFilter); + register('orderBy', orderByFilter); + register('uppercase', uppercaseFilter); +} + +/** + * @ngdoc filter + * @name filter + * @kind function + * + * @description + * Selects a subset of items from `array` and returns it as a new array. + * + * @param {Array} array The source array. + * @param {string|Object|function()} expression The predicate to be used for selecting items from + * `array`. + * + * Can be one of: + * + * - `string`: The string is used for matching against the contents of the `array`. All strings or + * objects with string properties in `array` that match this string will be returned. This also + * applies to nested object properties. + * The predicate can be negated by prefixing the string with `!`. + * + * - `Object`: A pattern object can be used to filter specific properties on objects contained + * by `array`. For example `{name:"M", phone:"1"}` predicate will return an array of items + * which have property `name` containing "M" and property `phone` containing "1". A special + * property name `$` can be used (as in `{$:"text"}`) to accept a match against any + * property of the object or its nested object properties. That's equivalent to the simple + * substring match with a `string` as described above. The predicate can be negated by prefixing + * the string with `!`. + * For example `{name: "!M"}` predicate will return an array of items which have property `name` + * not containing "M". + * + * Note that a named property will match properties on the same level only, while the special + * `$` property will match properties on the same level or deeper. E.g. an array item like + * `{name: {first: 'John', last: 'Doe'}}` will **not** be matched by `{name: 'John'}`, but + * **will** be matched by `{$: 'John'}`. + * + * - `function(value, index)`: A predicate function can be used to write arbitrary filters. The + * function is called for each element of `array`. The final result is an array of those + * elements that the predicate returned true for. + * + * @param {function(actual, expected)|true|undefined} comparator Comparator which is used in + * determining if the expected value (from the filter expression) and actual value (from + * the object in the array) should be considered a match. + * + * Can be one of: + * + * - `function(actual, expected)`: + * The function will be given the object value and the predicate value to compare and + * should return true if both values should be considered equal. + * + * - `true`: A shorthand for `function(actual, expected) { return angular.equals(actual, expected)}`. + * This is essentially strict comparison of expected and actual. + * + * - `false|undefined`: A short hand for a function which will look for a substring match in case + * insensitive way. + * + * @example + + +
      + + Search: + + + + + + +
      NamePhone
      {{friend.name}}{{friend.phone}}
      +
      + Any:
      + Name only
      + Phone only
      + Equality
      + + + + + + +
      NamePhone
      {{friendObj.name}}{{friendObj.phone}}
      +
      + + var expectFriendNames = function(expectedNames, key) { + element.all(by.repeater(key + ' in friends').column(key + '.name')).then(function(arr) { + arr.forEach(function(wd, i) { + expect(wd.getText()).toMatch(expectedNames[i]); + }); + }); + }; + + it('should search across all fields when filtering with a string', function() { + var searchText = element(by.model('searchText')); + searchText.clear(); + searchText.sendKeys('m'); + expectFriendNames(['Mary', 'Mike', 'Adam'], 'friend'); + + searchText.clear(); + searchText.sendKeys('76'); + expectFriendNames(['John', 'Julie'], 'friend'); + }); + + it('should search in specific fields when filtering with a predicate object', function() { + var searchAny = element(by.model('search.$')); + searchAny.clear(); + searchAny.sendKeys('i'); + expectFriendNames(['Mary', 'Mike', 'Julie', 'Juliette'], 'friendObj'); + }); + it('should use a equal comparison when comparator is true', function() { + var searchName = element(by.model('search.name')); + var strict = element(by.model('strict')); + searchName.clear(); + searchName.sendKeys('Julie'); + strict.click(); + expectFriendNames(['Julie'], 'friendObj'); + }); + +
      + */ +function filterFilter() { + return function(array, expression, comparator) { + if (!isArray(array)) return array; + + var predicateFn; + var matchAgainstAnyProp; + + switch (typeof expression) { + case 'function': + predicateFn = expression; + break; + case 'boolean': + case 'number': + case 'string': + matchAgainstAnyProp = true; + //jshint -W086 + case 'object': + //jshint +W086 + predicateFn = createPredicateFn(expression, comparator, matchAgainstAnyProp); + break; + default: + return array; + } + + return array.filter(predicateFn); + }; +} + +// Helper functions for `filterFilter` +function createPredicateFn(expression, comparator, matchAgainstAnyProp) { + var shouldMatchPrimitives = isObject(expression) && ('$' in expression); + var predicateFn; + + if (comparator === true) { + comparator = equals; + } else if (!isFunction(comparator)) { + comparator = function(actual, expected) { + if (isObject(actual) || isObject(expected)) { + // Prevent an object to be considered equal to a string like `'[object'` + return false; + } + + actual = lowercase('' + actual); + expected = lowercase('' + expected); + return actual.indexOf(expected) !== -1; + }; + } + + predicateFn = function(item) { + if (shouldMatchPrimitives && !isObject(item)) { + return deepCompare(item, expression.$, comparator, false); + } + return deepCompare(item, expression, comparator, matchAgainstAnyProp); + }; + + return predicateFn; +} + +function deepCompare(actual, expected, comparator, matchAgainstAnyProp, dontMatchWholeObject) { + var actualType = typeof actual; + var expectedType = typeof expected; + + if ((expectedType === 'string') && (expected.charAt(0) === '!')) { + return !deepCompare(actual, expected.substring(1), comparator, matchAgainstAnyProp); + } else if (actualType === 'array') { + // In case `actual` is an array, consider it a match + // if ANY of it's items matches `expected` + return actual.some(function(item) { + return deepCompare(item, expected, comparator, matchAgainstAnyProp); + }); + } + + switch (actualType) { + case 'object': + var key; + if (matchAgainstAnyProp) { + for (key in actual) { + if ((key.charAt(0) !== '$') && deepCompare(actual[key], expected, comparator, true)) { + return true; + } + } + return dontMatchWholeObject ? false : deepCompare(actual, expected, comparator, false); + } else if (expectedType === 'object') { + for (key in expected) { + var expectedVal = expected[key]; + if (isFunction(expectedVal)) { + continue; + } + + var matchAnyProperty = key === '$'; + var actualVal = matchAnyProperty ? actual : actual[key]; + if (!deepCompare(actualVal, expectedVal, comparator, matchAnyProperty, matchAnyProperty)) { + return false; + } + } + return true; + } else { + return comparator(actual, expected); + } + break; + case 'function': + return false; + default: + return comparator(actual, expected); + } +} + +/** + * @ngdoc filter + * @name currency + * @kind function + * + * @description + * Formats a number as a currency (ie $1,234.56). When no currency symbol is provided, default + * symbol for current locale is used. + * + * @param {number} amount Input to filter. + * @param {string=} symbol Currency symbol or identifier to be displayed. + * @param {number=} fractionSize Number of decimal places to round the amount to, defaults to default max fraction size for current locale + * @returns {string} Formatted number. + * + * + * @example + + + +
      +
      + default currency symbol ($): {{amount | currency}}
      + custom currency identifier (USD$): {{amount | currency:"USD$"}} + no fractions (0): {{amount | currency:"USD$":0}} +
      +
      + + it('should init with 1234.56', function() { + expect(element(by.id('currency-default')).getText()).toBe('$1,234.56'); + expect(element(by.id('currency-custom')).getText()).toBe('USD$1,234.56'); + expect(element(by.id('currency-no-fractions')).getText()).toBe('USD$1,235'); + }); + it('should update', function() { + if (browser.params.browser == 'safari') { + // Safari does not understand the minus key. See + // https://github.com/angular/protractor/issues/481 + return; + } + element(by.model('amount')).clear(); + element(by.model('amount')).sendKeys('-1234'); + expect(element(by.id('currency-default')).getText()).toBe('($1,234.00)'); + expect(element(by.id('currency-custom')).getText()).toBe('(USD$1,234.00)'); + expect(element(by.id('currency-no-fractions')).getText()).toBe('(USD$1,234)'); + }); + +
      + */ +currencyFilter.$inject = ['$locale']; +function currencyFilter($locale) { + var formats = $locale.NUMBER_FORMATS; + return function(amount, currencySymbol, fractionSize) { + if (isUndefined(currencySymbol)) { + currencySymbol = formats.CURRENCY_SYM; + } + + if (isUndefined(fractionSize)) { + fractionSize = formats.PATTERNS[1].maxFrac; + } + + // if null or undefined pass it through + return (amount == null) + ? amount + : formatNumber(amount, formats.PATTERNS[1], formats.GROUP_SEP, formats.DECIMAL_SEP, fractionSize). + replace(/\u00A4/g, currencySymbol); + }; +} + +/** + * @ngdoc filter + * @name number + * @kind function + * + * @description + * Formats a number as text. + * + * If the input is not a number an empty string is returned. + * + * @param {number|string} number Number to format. + * @param {(number|string)=} fractionSize Number of decimal places to round the number to. + * If this is not provided then the fraction size is computed from the current locale's number + * formatting pattern. In the case of the default locale, it will be 3. + * @returns {string} Number rounded to decimalPlaces and places a “,” after each third digit. + * + * @example + + + +
      + Enter number:
      + Default formatting: {{val | number}}
      + No fractions: {{val | number:0}}
      + Negative number: {{-val | number:4}} +
      +
      + + it('should format numbers', function() { + expect(element(by.id('number-default')).getText()).toBe('1,234.568'); + expect(element(by.binding('val | number:0')).getText()).toBe('1,235'); + expect(element(by.binding('-val | number:4')).getText()).toBe('-1,234.5679'); + }); + + it('should update', function() { + element(by.model('val')).clear(); + element(by.model('val')).sendKeys('3374.333'); + expect(element(by.id('number-default')).getText()).toBe('3,374.333'); + expect(element(by.binding('val | number:0')).getText()).toBe('3,374'); + expect(element(by.binding('-val | number:4')).getText()).toBe('-3,374.3330'); + }); + +
      + */ + + +numberFilter.$inject = ['$locale']; +function numberFilter($locale) { + var formats = $locale.NUMBER_FORMATS; + return function(number, fractionSize) { + + // if null or undefined pass it through + return (number == null) + ? number + : formatNumber(number, formats.PATTERNS[0], formats.GROUP_SEP, formats.DECIMAL_SEP, + fractionSize); + }; +} + +var DECIMAL_SEP = '.'; +function formatNumber(number, pattern, groupSep, decimalSep, fractionSize) { + if (!isFinite(number) || isObject(number)) return ''; + + var isNegative = number < 0; + number = Math.abs(number); + var numStr = number + '', + formatedText = '', + parts = []; + + var hasExponent = false; + if (numStr.indexOf('e') !== -1) { + var match = numStr.match(/([\d\.]+)e(-?)(\d+)/); + if (match && match[2] == '-' && match[3] > fractionSize + 1) { + number = 0; + } else { + formatedText = numStr; + hasExponent = true; + } + } + + if (!hasExponent) { + var fractionLen = (numStr.split(DECIMAL_SEP)[1] || '').length; + + // determine fractionSize if it is not specified + if (isUndefined(fractionSize)) { + fractionSize = Math.min(Math.max(pattern.minFrac, fractionLen), pattern.maxFrac); + } + + // safely round numbers in JS without hitting imprecisions of floating-point arithmetics + // inspired by: + // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/round + number = +(Math.round(+(number.toString() + 'e' + fractionSize)).toString() + 'e' + -fractionSize); + + var fraction = ('' + number).split(DECIMAL_SEP); + var whole = fraction[0]; + fraction = fraction[1] || ''; + + var i, pos = 0, + lgroup = pattern.lgSize, + group = pattern.gSize; + + if (whole.length >= (lgroup + group)) { + pos = whole.length - lgroup; + for (i = 0; i < pos; i++) { + if ((pos - i) % group === 0 && i !== 0) { + formatedText += groupSep; + } + formatedText += whole.charAt(i); + } + } + + for (i = pos; i < whole.length; i++) { + if ((whole.length - i) % lgroup === 0 && i !== 0) { + formatedText += groupSep; + } + formatedText += whole.charAt(i); + } + + // format fraction part. + while (fraction.length < fractionSize) { + fraction += '0'; + } + + if (fractionSize && fractionSize !== "0") formatedText += decimalSep + fraction.substr(0, fractionSize); + } else { + if (fractionSize > 0 && number < 1) { + formatedText = number.toFixed(fractionSize); + number = parseFloat(formatedText); + } + } + + if (number === 0) { + isNegative = false; + } + + parts.push(isNegative ? pattern.negPre : pattern.posPre, + formatedText, + isNegative ? pattern.negSuf : pattern.posSuf); + return parts.join(''); +} + +function padNumber(num, digits, trim) { + var neg = ''; + if (num < 0) { + neg = '-'; + num = -num; + } + num = '' + num; + while (num.length < digits) num = '0' + num; + if (trim) + num = num.substr(num.length - digits); + return neg + num; +} + + +function dateGetter(name, size, offset, trim) { + offset = offset || 0; + return function(date) { + var value = date['get' + name](); + if (offset > 0 || value > -offset) + value += offset; + if (value === 0 && offset == -12) value = 12; + return padNumber(value, size, trim); + }; +} + +function dateStrGetter(name, shortForm) { + return function(date, formats) { + var value = date['get' + name](); + var get = uppercase(shortForm ? ('SHORT' + name) : name); + + return formats[get][value]; + }; +} + +function timeZoneGetter(date) { + var zone = -1 * date.getTimezoneOffset(); + var paddedZone = (zone >= 0) ? "+" : ""; + + paddedZone += padNumber(Math[zone > 0 ? 'floor' : 'ceil'](zone / 60), 2) + + padNumber(Math.abs(zone % 60), 2); + + return paddedZone; +} + +function getFirstThursdayOfYear(year) { + // 0 = index of January + var dayOfWeekOnFirst = (new Date(year, 0, 1)).getDay(); + // 4 = index of Thursday (+1 to account for 1st = 5) + // 11 = index of *next* Thursday (+1 account for 1st = 12) + return new Date(year, 0, ((dayOfWeekOnFirst <= 4) ? 5 : 12) - dayOfWeekOnFirst); +} + +function getThursdayThisWeek(datetime) { + return new Date(datetime.getFullYear(), datetime.getMonth(), + // 4 = index of Thursday + datetime.getDate() + (4 - datetime.getDay())); +} + +function weekGetter(size) { + return function(date) { + var firstThurs = getFirstThursdayOfYear(date.getFullYear()), + thisThurs = getThursdayThisWeek(date); + + var diff = +thisThurs - +firstThurs, + result = 1 + Math.round(diff / 6.048e8); // 6.048e8 ms per week + + return padNumber(result, size); + }; +} + +function ampmGetter(date, formats) { + return date.getHours() < 12 ? formats.AMPMS[0] : formats.AMPMS[1]; +} + +var DATE_FORMATS = { + yyyy: dateGetter('FullYear', 4), + yy: dateGetter('FullYear', 2, 0, true), + y: dateGetter('FullYear', 1), + MMMM: dateStrGetter('Month'), + MMM: dateStrGetter('Month', true), + MM: dateGetter('Month', 2, 1), + M: dateGetter('Month', 1, 1), + dd: dateGetter('Date', 2), + d: dateGetter('Date', 1), + HH: dateGetter('Hours', 2), + H: dateGetter('Hours', 1), + hh: dateGetter('Hours', 2, -12), + h: dateGetter('Hours', 1, -12), + mm: dateGetter('Minutes', 2), + m: dateGetter('Minutes', 1), + ss: dateGetter('Seconds', 2), + s: dateGetter('Seconds', 1), + // while ISO 8601 requires fractions to be prefixed with `.` or `,` + // we can be just safely rely on using `sss` since we currently don't support single or two digit fractions + sss: dateGetter('Milliseconds', 3), + EEEE: dateStrGetter('Day'), + EEE: dateStrGetter('Day', true), + a: ampmGetter, + Z: timeZoneGetter, + ww: weekGetter(2), + w: weekGetter(1) +}; + +var DATE_FORMATS_SPLIT = /((?:[^yMdHhmsaZEw']+)|(?:'(?:[^']|'')*')|(?:E+|y+|M+|d+|H+|h+|m+|s+|a|Z|w+))(.*)/, + NUMBER_STRING = /^\-?\d+$/; + +/** + * @ngdoc filter + * @name date + * @kind function + * + * @description + * Formats `date` to a string based on the requested `format`. + * + * `format` string can be composed of the following elements: + * + * * `'yyyy'`: 4 digit representation of year (e.g. AD 1 => 0001, AD 2010 => 2010) + * * `'yy'`: 2 digit representation of year, padded (00-99). (e.g. AD 2001 => 01, AD 2010 => 10) + * * `'y'`: 1 digit representation of year, e.g. (AD 1 => 1, AD 199 => 199) + * * `'MMMM'`: Month in year (January-December) + * * `'MMM'`: Month in year (Jan-Dec) + * * `'MM'`: Month in year, padded (01-12) + * * `'M'`: Month in year (1-12) + * * `'dd'`: Day in month, padded (01-31) + * * `'d'`: Day in month (1-31) + * * `'EEEE'`: Day in Week,(Sunday-Saturday) + * * `'EEE'`: Day in Week, (Sun-Sat) + * * `'HH'`: Hour in day, padded (00-23) + * * `'H'`: Hour in day (0-23) + * * `'hh'`: Hour in AM/PM, padded (01-12) + * * `'h'`: Hour in AM/PM, (1-12) + * * `'mm'`: Minute in hour, padded (00-59) + * * `'m'`: Minute in hour (0-59) + * * `'ss'`: Second in minute, padded (00-59) + * * `'s'`: Second in minute (0-59) + * * `'.sss' or ',sss'`: Millisecond in second, padded (000-999) + * * `'a'`: AM/PM marker + * * `'Z'`: 4 digit (+sign) representation of the timezone offset (-1200-+1200) + * * `'ww'`: Week of year, padded (00-53). Week 01 is the week with the first Thursday of the year + * * `'w'`: Week of year (0-53). Week 1 is the week with the first Thursday of the year + * + * `format` string can also be one of the following predefined + * {@link guide/i18n localizable formats}: + * + * * `'medium'`: equivalent to `'MMM d, y h:mm:ss a'` for en_US locale + * (e.g. Sep 3, 2010 12:05:08 PM) + * * `'short'`: equivalent to `'M/d/yy h:mm a'` for en_US locale (e.g. 9/3/10 12:05 PM) + * * `'fullDate'`: equivalent to `'EEEE, MMMM d, y'` for en_US locale + * (e.g. Friday, September 3, 2010) + * * `'longDate'`: equivalent to `'MMMM d, y'` for en_US locale (e.g. September 3, 2010) + * * `'mediumDate'`: equivalent to `'MMM d, y'` for en_US locale (e.g. Sep 3, 2010) + * * `'shortDate'`: equivalent to `'M/d/yy'` for en_US locale (e.g. 9/3/10) + * * `'mediumTime'`: equivalent to `'h:mm:ss a'` for en_US locale (e.g. 12:05:08 PM) + * * `'shortTime'`: equivalent to `'h:mm a'` for en_US locale (e.g. 12:05 PM) + * + * `format` string can contain literal values. These need to be escaped by surrounding with single quotes (e.g. + * `"h 'in the morning'"`). In order to output a single quote, escape it - i.e., two single quotes in a sequence + * (e.g. `"h 'o''clock'"`). + * + * @param {(Date|number|string)} date Date to format either as Date object, milliseconds (string or + * number) or various ISO 8601 datetime string formats (e.g. yyyy-MM-ddTHH:mm:ss.sssZ and its + * shorter versions like yyyy-MM-ddTHH:mmZ, yyyy-MM-dd or yyyyMMddTHHmmssZ). If no timezone is + * specified in the string input, the time is considered to be in the local timezone. + * @param {string=} format Formatting rules (see Description). If not specified, + * `mediumDate` is used. + * @param {string=} timezone Timezone to be used for formatting. Right now, only `'UTC'` is supported. + * If not specified, the timezone of the browser will be used. + * @returns {string} Formatted string or the input if input is not recognized as date/millis. + * + * @example + + + {{1288323623006 | date:'medium'}}: + {{1288323623006 | date:'medium'}}
      + {{1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'}}: + {{1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'}}
      + {{1288323623006 | date:'MM/dd/yyyy @ h:mma'}}: + {{'1288323623006' | date:'MM/dd/yyyy @ h:mma'}}
      + {{1288323623006 | date:"MM/dd/yyyy 'at' h:mma"}}: + {{'1288323623006' | date:"MM/dd/yyyy 'at' h:mma"}}
      +
      + + it('should format date', function() { + expect(element(by.binding("1288323623006 | date:'medium'")).getText()). + toMatch(/Oct 2\d, 2010 \d{1,2}:\d{2}:\d{2} (AM|PM)/); + expect(element(by.binding("1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'")).getText()). + toMatch(/2010\-10\-2\d \d{2}:\d{2}:\d{2} (\-|\+)?\d{4}/); + expect(element(by.binding("'1288323623006' | date:'MM/dd/yyyy @ h:mma'")).getText()). + toMatch(/10\/2\d\/2010 @ \d{1,2}:\d{2}(AM|PM)/); + expect(element(by.binding("'1288323623006' | date:\"MM/dd/yyyy 'at' h:mma\"")).getText()). + toMatch(/10\/2\d\/2010 at \d{1,2}:\d{2}(AM|PM)/); + }); + +
      + */ +dateFilter.$inject = ['$locale']; +function dateFilter($locale) { + + + var R_ISO8601_STR = /^(\d{4})-?(\d\d)-?(\d\d)(?:T(\d\d)(?::?(\d\d)(?::?(\d\d)(?:\.(\d+))?)?)?(Z|([+-])(\d\d):?(\d\d))?)?$/; + // 1 2 3 4 5 6 7 8 9 10 11 + function jsonStringToDate(string) { + var match; + if (match = string.match(R_ISO8601_STR)) { + var date = new Date(0), + tzHour = 0, + tzMin = 0, + dateSetter = match[8] ? date.setUTCFullYear : date.setFullYear, + timeSetter = match[8] ? date.setUTCHours : date.setHours; + + if (match[9]) { + tzHour = int(match[9] + match[10]); + tzMin = int(match[9] + match[11]); + } + dateSetter.call(date, int(match[1]), int(match[2]) - 1, int(match[3])); + var h = int(match[4] || 0) - tzHour; + var m = int(match[5] || 0) - tzMin; + var s = int(match[6] || 0); + var ms = Math.round(parseFloat('0.' + (match[7] || 0)) * 1000); + timeSetter.call(date, h, m, s, ms); + return date; + } + return string; + } + + + return function(date, format, timezone) { + var text = '', + parts = [], + fn, match; + + format = format || 'mediumDate'; + format = $locale.DATETIME_FORMATS[format] || format; + if (isString(date)) { + date = NUMBER_STRING.test(date) ? int(date) : jsonStringToDate(date); + } + + if (isNumber(date)) { + date = new Date(date); + } + + if (!isDate(date)) { + return date; + } + + while (format) { + match = DATE_FORMATS_SPLIT.exec(format); + if (match) { + parts = concat(parts, match, 1); + format = parts.pop(); + } else { + parts.push(format); + format = null; + } + } + + if (timezone && timezone === 'UTC') { + date = new Date(date.getTime()); + date.setMinutes(date.getMinutes() + date.getTimezoneOffset()); + } + forEach(parts, function(value) { + fn = DATE_FORMATS[value]; + text += fn ? fn(date, $locale.DATETIME_FORMATS) + : value.replace(/(^'|'$)/g, '').replace(/''/g, "'"); + }); + + return text; + }; +} + + +/** + * @ngdoc filter + * @name json + * @kind function + * + * @description + * Allows you to convert a JavaScript object into JSON string. + * + * This filter is mostly useful for debugging. When using the double curly {{value}} notation + * the binding is automatically converted to JSON. + * + * @param {*} object Any JavaScript object (including arrays and primitive types) to filter. + * @param {number=} spacing The number of spaces to use per indentation, defaults to 2. + * @returns {string} JSON string. + * + * + * @example + + +
      {{ {'name':'value'} | json }}
      +
      {{ {'name':'value'} | json:4 }}
      +
      + + it('should jsonify filtered objects', function() { + expect(element(by.id('default-spacing')).getText()).toMatch(/\{\n "name": ?"value"\n}/); + expect(element(by.id('custom-spacing')).getText()).toMatch(/\{\n "name": ?"value"\n}/); + }); + +
      + * + */ +function jsonFilter() { + return function(object, spacing) { + if (isUndefined(spacing)) { + spacing = 2; + } + return toJson(object, spacing); + }; +} + + +/** + * @ngdoc filter + * @name lowercase + * @kind function + * @description + * Converts string to lowercase. + * @see angular.lowercase + */ +var lowercaseFilter = valueFn(lowercase); + + +/** + * @ngdoc filter + * @name uppercase + * @kind function + * @description + * Converts string to uppercase. + * @see angular.uppercase + */ +var uppercaseFilter = valueFn(uppercase); + +/** + * @ngdoc filter + * @name limitTo + * @kind function + * + * @description + * Creates a new array or string containing only a specified number of elements. The elements + * are taken from either the beginning or the end of the source array, string or number, as specified by + * the value and sign (positive or negative) of `limit`. If a number is used as input, it is + * converted to a string. + * + * @param {Array|string|number} input Source array, string or number to be limited. + * @param {string|number} limit The length of the returned array or string. If the `limit` number + * is positive, `limit` number of items from the beginning of the source array/string are copied. + * If the number is negative, `limit` number of items from the end of the source array/string + * are copied. The `limit` will be trimmed if it exceeds `array.length` + * @returns {Array|string} A new sub-array or substring of length `limit` or less if input array + * had less than `limit` elements. + * + * @example + + + +
      + Limit {{numbers}} to: +

      Output numbers: {{ numbers | limitTo:numLimit }}

      + Limit {{letters}} to: +

      Output letters: {{ letters | limitTo:letterLimit }}

      + Limit {{longNumber}} to: +

      Output long number: {{ longNumber | limitTo:longNumberLimit }}

      +
      +
      + + var numLimitInput = element(by.model('numLimit')); + var letterLimitInput = element(by.model('letterLimit')); + var longNumberLimitInput = element(by.model('longNumberLimit')); + var limitedNumbers = element(by.binding('numbers | limitTo:numLimit')); + var limitedLetters = element(by.binding('letters | limitTo:letterLimit')); + var limitedLongNumber = element(by.binding('longNumber | limitTo:longNumberLimit')); + + it('should limit the number array to first three items', function() { + expect(numLimitInput.getAttribute('value')).toBe('3'); + expect(letterLimitInput.getAttribute('value')).toBe('3'); + expect(longNumberLimitInput.getAttribute('value')).toBe('3'); + expect(limitedNumbers.getText()).toEqual('Output numbers: [1,2,3]'); + expect(limitedLetters.getText()).toEqual('Output letters: abc'); + expect(limitedLongNumber.getText()).toEqual('Output long number: 234'); + }); + + // There is a bug in safari and protractor that doesn't like the minus key + // it('should update the output when -3 is entered', function() { + // numLimitInput.clear(); + // numLimitInput.sendKeys('-3'); + // letterLimitInput.clear(); + // letterLimitInput.sendKeys('-3'); + // longNumberLimitInput.clear(); + // longNumberLimitInput.sendKeys('-3'); + // expect(limitedNumbers.getText()).toEqual('Output numbers: [7,8,9]'); + // expect(limitedLetters.getText()).toEqual('Output letters: ghi'); + // expect(limitedLongNumber.getText()).toEqual('Output long number: 342'); + // }); + + it('should not exceed the maximum size of input array', function() { + numLimitInput.clear(); + numLimitInput.sendKeys('100'); + letterLimitInput.clear(); + letterLimitInput.sendKeys('100'); + longNumberLimitInput.clear(); + longNumberLimitInput.sendKeys('100'); + expect(limitedNumbers.getText()).toEqual('Output numbers: [1,2,3,4,5,6,7,8,9]'); + expect(limitedLetters.getText()).toEqual('Output letters: abcdefghi'); + expect(limitedLongNumber.getText()).toEqual('Output long number: 2345432342'); + }); + +
      +*/ +function limitToFilter() { + return function(input, limit) { + if (isNumber(input)) input = input.toString(); + if (!isArray(input) && !isString(input)) return input; + + if (Math.abs(Number(limit)) === Infinity) { + limit = Number(limit); + } else { + limit = int(limit); + } + + if (isString(input)) { + //NaN check on limit + if (limit) { + return limit >= 0 ? input.slice(0, limit) : input.slice(limit, input.length); + } else { + return ""; + } + } + + var i, n; + + // if abs(limit) exceeds maximum length, trim it + if (limit > input.length) + limit = input.length; + else if (limit < -input.length) + limit = -input.length; + + if (limit > 0) { + i = 0; + n = limit; + } else { + // zero and NaN check on limit - return empty array + if (!limit) return []; + + i = input.length + limit; + n = input.length; + } + + return input.slice(i, n); + }; +} + +/** + * @ngdoc filter + * @name orderBy + * @kind function + * + * @description + * Orders a specified `array` by the `expression` predicate. It is ordered alphabetically + * for strings and numerically for numbers. Note: if you notice numbers are not being sorted + * correctly, make sure they are actually being saved as numbers and not strings. + * + * @param {Array} array The array to sort. + * @param {function(*)|string|Array.<(function(*)|string)>=} expression A predicate to be + * used by the comparator to determine the order of elements. + * + * Can be one of: + * + * - `function`: Getter function. The result of this function will be sorted using the + * `<`, `=`, `>` operator. + * - `string`: An Angular expression. The result of this expression is used to compare elements + * (for example `name` to sort by a property called `name` or `name.substr(0, 3)` to sort by + * 3 first characters of a property called `name`). The result of a constant expression + * is interpreted as a property name to be used in comparisons (for example `"special name"` + * to sort object by the value of their `special name` property). An expression can be + * optionally prefixed with `+` or `-` to control ascending or descending sort order + * (for example, `+name` or `-name`). If no property is provided, (e.g. `'+'`) then the array + * element itself is used to compare where sorting. + * - `Array`: An array of function or string predicates. The first predicate in the array + * is used for sorting, but when two items are equivalent, the next predicate is used. + * + * If the predicate is missing or empty then it defaults to `'+'`. + * + * @param {boolean=} reverse Reverse the order of the array. + * @returns {Array} Sorted copy of the source array. + * + * @example + + + +
      +
      Sorting predicate = {{predicate}}; reverse = {{reverse}}
      +
      + [ unsorted ] + + + + + + + + + + + +
      Name + (^)Phone NumberAge
      {{friend.name}}{{friend.phone}}{{friend.age}}
      +
      +
      +
      + * + * It's also possible to call the orderBy filter manually, by injecting `$filter`, retrieving the + * filter routine with `$filter('orderBy')`, and calling the returned filter routine with the + * desired parameters. + * + * Example: + * + * @example + + +
      + + + + + + + + + + + +
      Name + (^)Phone NumberAge
      {{friend.name}}{{friend.phone}}{{friend.age}}
      +
      +
      + + + angular.module('orderByExample', []) + .controller('ExampleController', ['$scope', '$filter', function($scope, $filter) { + var orderBy = $filter('orderBy'); + $scope.friends = [ + { name: 'John', phone: '555-1212', age: 10 }, + { name: 'Mary', phone: '555-9876', age: 19 }, + { name: 'Mike', phone: '555-4321', age: 21 }, + { name: 'Adam', phone: '555-5678', age: 35 }, + { name: 'Julie', phone: '555-8765', age: 29 } + ]; + $scope.order = function(predicate, reverse) { + $scope.friends = orderBy($scope.friends, predicate, reverse); + }; + $scope.order('-age',false); + }]); + +
      + */ +orderByFilter.$inject = ['$parse']; +function orderByFilter($parse) { + return function(array, sortPredicate, reverseOrder) { + if (!(isArrayLike(array))) return array; + sortPredicate = isArray(sortPredicate) ? sortPredicate : [sortPredicate]; + if (sortPredicate.length === 0) { sortPredicate = ['+']; } + sortPredicate = sortPredicate.map(function(predicate) { + var descending = false, get = predicate || identity; + if (isString(predicate)) { + if ((predicate.charAt(0) == '+' || predicate.charAt(0) == '-')) { + descending = predicate.charAt(0) == '-'; + predicate = predicate.substring(1); + } + if (predicate === '') { + // Effectively no predicate was passed so we compare identity + return reverseComparator(compare, descending); + } + get = $parse(predicate); + if (get.constant) { + var key = get(); + return reverseComparator(function(a, b) { + return compare(a[key], b[key]); + }, descending); + } + } + return reverseComparator(function(a, b) { + return compare(get(a),get(b)); + }, descending); + }); + return slice.call(array).sort(reverseComparator(comparator, reverseOrder)); + + function comparator(o1, o2) { + for (var i = 0; i < sortPredicate.length; i++) { + var comp = sortPredicate[i](o1, o2); + if (comp !== 0) return comp; + } + return 0; + } + function reverseComparator(comp, descending) { + return descending + ? function(a, b) {return comp(b,a);} + : comp; + } + + function isPrimitive(value) { + switch (typeof value) { + case 'number': /* falls through */ + case 'boolean': /* falls through */ + case 'string': + return true; + default: + return false; + } + } + + function objectToString(value) { + if (value === null) return 'null'; + if (typeof value.valueOf === 'function') { + value = value.valueOf(); + if (isPrimitive(value)) return value; + } + if (typeof value.toString === 'function') { + value = value.toString(); + if (isPrimitive(value)) return value; + } + return ''; + } + + function compare(v1, v2) { + var t1 = typeof v1; + var t2 = typeof v2; + if (t1 === t2 && t1 === "object") { + v1 = objectToString(v1); + v2 = objectToString(v2); + } + if (t1 === t2) { + if (t1 === "string") { + v1 = v1.toLowerCase(); + v2 = v2.toLowerCase(); + } + if (v1 === v2) return 0; + return v1 < v2 ? -1 : 1; + } else { + return t1 < t2 ? -1 : 1; + } + } + }; +} + +function ngDirective(directive) { + if (isFunction(directive)) { + directive = { + link: directive + }; + } + directive.restrict = directive.restrict || 'AC'; + return valueFn(directive); +} + +/** + * @ngdoc directive + * @name a + * @restrict E + * + * @description + * Modifies the default behavior of the html A tag so that the default action is prevented when + * the href attribute is empty. + * + * This change permits the easy creation of action links with the `ngClick` directive + * without changing the location or causing page reloads, e.g.: + * `Add Item` + */ +var htmlAnchorDirective = valueFn({ + restrict: 'E', + compile: function(element, attr) { + if (!attr.href && !attr.xlinkHref && !attr.name) { + return function(scope, element) { + // SVGAElement does not use the href attribute, but rather the 'xlinkHref' attribute. + var href = toString.call(element.prop('href')) === '[object SVGAnimatedString]' ? + 'xlink:href' : 'href'; + element.on('click', function(event) { + // if we have no href url, then don't navigate anywhere. + if (!element.attr(href)) { + event.preventDefault(); + } + }); + }; + } + } +}); + +/** + * @ngdoc directive + * @name ngHref + * @restrict A + * @priority 99 + * + * @description + * Using Angular markup like `{{hash}}` in an href attribute will + * make the link go to the wrong URL if the user clicks it before + * Angular has a chance to replace the `{{hash}}` markup with its + * value. Until Angular replaces the markup the link will be broken + * and will most likely return a 404 error. The `ngHref` directive + * solves this problem. + * + * The wrong way to write it: + * ```html + * link1 + * ``` + * + * The correct way to write it: + * ```html + * link1 + * ``` + * + * @element A + * @param {template} ngHref any string which can contain `{{}}` markup. + * + * @example + * This example shows various combinations of `href`, `ng-href` and `ng-click` attributes + * in links and their different behaviors: + + +
      + link 1 (link, don't reload)
      + link 2 (link, don't reload)
      + link 3 (link, reload!)
      + anchor (link, don't reload)
      + anchor (no link)
      + link (link, change location) +
      + + it('should execute ng-click but not reload when href without value', function() { + element(by.id('link-1')).click(); + expect(element(by.model('value')).getAttribute('value')).toEqual('1'); + expect(element(by.id('link-1')).getAttribute('href')).toBe(''); + }); + + it('should execute ng-click but not reload when href empty string', function() { + element(by.id('link-2')).click(); + expect(element(by.model('value')).getAttribute('value')).toEqual('2'); + expect(element(by.id('link-2')).getAttribute('href')).toBe(''); + }); + + it('should execute ng-click and change url when ng-href specified', function() { + expect(element(by.id('link-3')).getAttribute('href')).toMatch(/\/123$/); + + element(by.id('link-3')).click(); + + // At this point, we navigate away from an Angular page, so we need + // to use browser.driver to get the base webdriver. + + browser.wait(function() { + return browser.driver.getCurrentUrl().then(function(url) { + return url.match(/\/123$/); + }); + }, 5000, 'page should navigate to /123'); + }); + + xit('should execute ng-click but not reload when href empty string and name specified', function() { + element(by.id('link-4')).click(); + expect(element(by.model('value')).getAttribute('value')).toEqual('4'); + expect(element(by.id('link-4')).getAttribute('href')).toBe(''); + }); + + it('should execute ng-click but not reload when no href but name specified', function() { + element(by.id('link-5')).click(); + expect(element(by.model('value')).getAttribute('value')).toEqual('5'); + expect(element(by.id('link-5')).getAttribute('href')).toBe(null); + }); + + it('should only change url when only ng-href', function() { + element(by.model('value')).clear(); + element(by.model('value')).sendKeys('6'); + expect(element(by.id('link-6')).getAttribute('href')).toMatch(/\/6$/); + + element(by.id('link-6')).click(); + + // At this point, we navigate away from an Angular page, so we need + // to use browser.driver to get the base webdriver. + browser.wait(function() { + return browser.driver.getCurrentUrl().then(function(url) { + return url.match(/\/6$/); + }); + }, 5000, 'page should navigate to /6'); + }); + +
      + */ + +/** + * @ngdoc directive + * @name ngSrc + * @restrict A + * @priority 99 + * + * @description + * Using Angular markup like `{{hash}}` in a `src` attribute doesn't + * work right: The browser will fetch from the URL with the literal + * text `{{hash}}` until Angular replaces the expression inside + * `{{hash}}`. The `ngSrc` directive solves this problem. + * + * The buggy way to write it: + * ```html + * + * ``` + * + * The correct way to write it: + * ```html + * + * ``` + * + * @element IMG + * @param {template} ngSrc any string which can contain `{{}}` markup. + */ + +/** + * @ngdoc directive + * @name ngSrcset + * @restrict A + * @priority 99 + * + * @description + * Using Angular markup like `{{hash}}` in a `srcset` attribute doesn't + * work right: The browser will fetch from the URL with the literal + * text `{{hash}}` until Angular replaces the expression inside + * `{{hash}}`. The `ngSrcset` directive solves this problem. + * + * The buggy way to write it: + * ```html + * + * ``` + * + * The correct way to write it: + * ```html + * + * ``` + * + * @element IMG + * @param {template} ngSrcset any string which can contain `{{}}` markup. + */ + +/** + * @ngdoc directive + * @name ngDisabled + * @restrict A + * @priority 100 + * + * @description + * + * We shouldn't do this, because it will make the button enabled on Chrome/Firefox but not on IE8 and older IEs: + * ```html + *
      + * + *
      + * ``` + * + * The HTML specification does not require browsers to preserve the values of boolean attributes + * such as disabled. (Their presence means true and their absence means false.) + * If we put an Angular interpolation expression into such an attribute then the + * binding information would be lost when the browser removes the attribute. + * The `ngDisabled` directive solves this problem for the `disabled` attribute. + * This complementary directive is not removed by the browser and so provides + * a permanent reliable place to store the binding information. + * + * @example + + + Click me to toggle:
      + +
      + + it('should toggle button', function() { + expect(element(by.css('button')).getAttribute('disabled')).toBeFalsy(); + element(by.model('checked')).click(); + expect(element(by.css('button')).getAttribute('disabled')).toBeTruthy(); + }); + +
      + * + * @element INPUT + * @param {expression} ngDisabled If the {@link guide/expression expression} is truthy, + * then special attribute "disabled" will be set on the element + */ + + +/** + * @ngdoc directive + * @name ngChecked + * @restrict A + * @priority 100 + * + * @description + * The HTML specification does not require browsers to preserve the values of boolean attributes + * such as checked. (Their presence means true and their absence means false.) + * If we put an Angular interpolation expression into such an attribute then the + * binding information would be lost when the browser removes the attribute. + * The `ngChecked` directive solves this problem for the `checked` attribute. + * This complementary directive is not removed by the browser and so provides + * a permanent reliable place to store the binding information. + * @example + + + Check me to check both:
      + +
      + + it('should check both checkBoxes', function() { + expect(element(by.id('checkSlave')).getAttribute('checked')).toBeFalsy(); + element(by.model('master')).click(); + expect(element(by.id('checkSlave')).getAttribute('checked')).toBeTruthy(); + }); + +
      + * + * @element INPUT + * @param {expression} ngChecked If the {@link guide/expression expression} is truthy, + * then special attribute "checked" will be set on the element + */ + + +/** + * @ngdoc directive + * @name ngReadonly + * @restrict A + * @priority 100 + * + * @description + * The HTML specification does not require browsers to preserve the values of boolean attributes + * such as readonly. (Their presence means true and their absence means false.) + * If we put an Angular interpolation expression into such an attribute then the + * binding information would be lost when the browser removes the attribute. + * The `ngReadonly` directive solves this problem for the `readonly` attribute. + * This complementary directive is not removed by the browser and so provides + * a permanent reliable place to store the binding information. + * @example + + + Check me to make text readonly:
      + +
      + + it('should toggle readonly attr', function() { + expect(element(by.css('[type="text"]')).getAttribute('readonly')).toBeFalsy(); + element(by.model('checked')).click(); + expect(element(by.css('[type="text"]')).getAttribute('readonly')).toBeTruthy(); + }); + +
      + * + * @element INPUT + * @param {expression} ngReadonly If the {@link guide/expression expression} is truthy, + * then special attribute "readonly" will be set on the element + */ + + +/** + * @ngdoc directive + * @name ngSelected + * @restrict A + * @priority 100 + * + * @description + * The HTML specification does not require browsers to preserve the values of boolean attributes + * such as selected. (Their presence means true and their absence means false.) + * If we put an Angular interpolation expression into such an attribute then the + * binding information would be lost when the browser removes the attribute. + * The `ngSelected` directive solves this problem for the `selected` attribute. + * This complementary directive is not removed by the browser and so provides + * a permanent reliable place to store the binding information. + * + * @example + + + Check me to select:
      + +
      + + it('should select Greetings!', function() { + expect(element(by.id('greet')).getAttribute('selected')).toBeFalsy(); + element(by.model('selected')).click(); + expect(element(by.id('greet')).getAttribute('selected')).toBeTruthy(); + }); + +
      + * + * @element OPTION + * @param {expression} ngSelected If the {@link guide/expression expression} is truthy, + * then special attribute "selected" will be set on the element + */ + +/** + * @ngdoc directive + * @name ngOpen + * @restrict A + * @priority 100 + * + * @description + * The HTML specification does not require browsers to preserve the values of boolean attributes + * such as open. (Their presence means true and their absence means false.) + * If we put an Angular interpolation expression into such an attribute then the + * binding information would be lost when the browser removes the attribute. + * The `ngOpen` directive solves this problem for the `open` attribute. + * This complementary directive is not removed by the browser and so provides + * a permanent reliable place to store the binding information. + * @example + + + Check me check multiple:
      +
      + Show/Hide me +
      +
      + + it('should toggle open', function() { + expect(element(by.id('details')).getAttribute('open')).toBeFalsy(); + element(by.model('open')).click(); + expect(element(by.id('details')).getAttribute('open')).toBeTruthy(); + }); + +
      + * + * @element DETAILS + * @param {expression} ngOpen If the {@link guide/expression expression} is truthy, + * then special attribute "open" will be set on the element + */ + +var ngAttributeAliasDirectives = {}; + + +// boolean attrs are evaluated +forEach(BOOLEAN_ATTR, function(propName, attrName) { + // binding to multiple is not supported + if (propName == "multiple") return; + + var normalized = directiveNormalize('ng-' + attrName); + ngAttributeAliasDirectives[normalized] = function() { + return { + restrict: 'A', + priority: 100, + link: function(scope, element, attr) { + scope.$watch(attr[normalized], function ngBooleanAttrWatchAction(value) { + attr.$set(attrName, !!value); + }); + } + }; + }; +}); + +// aliased input attrs are evaluated +forEach(ALIASED_ATTR, function(htmlAttr, ngAttr) { + ngAttributeAliasDirectives[ngAttr] = function() { + return { + priority: 100, + link: function(scope, element, attr) { + //special case ngPattern when a literal regular expression value + //is used as the expression (this way we don't have to watch anything). + if (ngAttr === "ngPattern" && attr.ngPattern.charAt(0) == "/") { + var match = attr.ngPattern.match(REGEX_STRING_REGEXP); + if (match) { + attr.$set("ngPattern", new RegExp(match[1], match[2])); + return; + } + } + + scope.$watch(attr[ngAttr], function ngAttrAliasWatchAction(value) { + attr.$set(ngAttr, value); + }); + } + }; + }; +}); + +// ng-src, ng-srcset, ng-href are interpolated +forEach(['src', 'srcset', 'href'], function(attrName) { + var normalized = directiveNormalize('ng-' + attrName); + ngAttributeAliasDirectives[normalized] = function() { + return { + priority: 99, // it needs to run after the attributes are interpolated + link: function(scope, element, attr) { + var propName = attrName, + name = attrName; + + if (attrName === 'href' && + toString.call(element.prop('href')) === '[object SVGAnimatedString]') { + name = 'xlinkHref'; + attr.$attr[name] = 'xlink:href'; + propName = null; + } + + attr.$observe(normalized, function(value) { + if (!value) { + if (attrName === 'href') { + attr.$set(name, null); + } + return; + } + + attr.$set(name, value); + + // on IE, if "ng:src" directive declaration is used and "src" attribute doesn't exist + // then calling element.setAttribute('src', 'foo') doesn't do anything, so we need + // to set the property as well to achieve the desired effect. + // we use attr[attrName] value since $set can sanitize the url. + if (msie && propName) element.prop(propName, attr[name]); + }); + } + }; + }; +}); + +/* global -nullFormCtrl, -SUBMITTED_CLASS, addSetValidityMethod: true + */ +var nullFormCtrl = { + $addControl: noop, + $$renameControl: nullFormRenameControl, + $removeControl: noop, + $setValidity: noop, + $setDirty: noop, + $setPristine: noop, + $setSubmitted: noop +}, +SUBMITTED_CLASS = 'ng-submitted'; + +function nullFormRenameControl(control, name) { + control.$name = name; +} + +/** + * @ngdoc type + * @name form.FormController + * + * @property {boolean} $pristine True if user has not interacted with the form yet. + * @property {boolean} $dirty True if user has already interacted with the form. + * @property {boolean} $valid True if all of the containing forms and controls are valid. + * @property {boolean} $invalid True if at least one containing control or form is invalid. + * @property {boolean} $submitted True if user has submitted the form even if its invalid. + * + * @property {Object} $error Is an object hash, containing references to controls or + * forms with failing validators, where: + * + * - keys are validation tokens (error names), + * - values are arrays of controls or forms that have a failing validator for given error name. + * + * Built-in validation tokens: + * + * - `email` + * - `max` + * - `maxlength` + * - `min` + * - `minlength` + * - `number` + * - `pattern` + * - `required` + * - `url` + * - `date` + * - `datetimelocal` + * - `time` + * - `week` + * - `month` + * + * @description + * `FormController` keeps track of all its controls and nested forms as well as the state of them, + * such as being valid/invalid or dirty/pristine. + * + * Each {@link ng.directive:form form} directive creates an instance + * of `FormController`. + * + */ +//asks for $scope to fool the BC controller module +FormController.$inject = ['$element', '$attrs', '$scope', '$animate', '$interpolate']; +function FormController(element, attrs, $scope, $animate, $interpolate) { + var form = this, + controls = []; + + var parentForm = form.$$parentForm = element.parent().controller('form') || nullFormCtrl; + + // init state + form.$error = {}; + form.$$success = {}; + form.$pending = undefined; + form.$name = $interpolate(attrs.name || attrs.ngForm || '')($scope); + form.$dirty = false; + form.$pristine = true; + form.$valid = true; + form.$invalid = false; + form.$submitted = false; + + parentForm.$addControl(form); + + /** + * @ngdoc method + * @name form.FormController#$rollbackViewValue + * + * @description + * Rollback all form controls pending updates to the `$modelValue`. + * + * Updates may be pending by a debounced event or because the input is waiting for a some future + * event defined in `ng-model-options`. This method is typically needed by the reset button of + * a form that uses `ng-model-options` to pend updates. + */ + form.$rollbackViewValue = function() { + forEach(controls, function(control) { + control.$rollbackViewValue(); + }); + }; + + /** + * @ngdoc method + * @name form.FormController#$commitViewValue + * + * @description + * Commit all form controls pending updates to the `$modelValue`. + * + * Updates may be pending by a debounced event or because the input is waiting for a some future + * event defined in `ng-model-options`. This method is rarely needed as `NgModelController` + * usually handles calling this in response to input events. + */ + form.$commitViewValue = function() { + forEach(controls, function(control) { + control.$commitViewValue(); + }); + }; + + /** + * @ngdoc method + * @name form.FormController#$addControl + * + * @description + * Register a control with the form. + * + * Input elements using ngModelController do this automatically when they are linked. + */ + form.$addControl = function(control) { + // Breaking change - before, inputs whose name was "hasOwnProperty" were quietly ignored + // and not added to the scope. Now we throw an error. + assertNotHasOwnProperty(control.$name, 'input'); + controls.push(control); + + if (control.$name) { + form[control.$name] = control; + } + }; + + // Private API: rename a form control + form.$$renameControl = function(control, newName) { + var oldName = control.$name; + + if (form[oldName] === control) { + delete form[oldName]; + } + form[newName] = control; + control.$name = newName; + }; + + /** + * @ngdoc method + * @name form.FormController#$removeControl + * + * @description + * Deregister a control from the form. + * + * Input elements using ngModelController do this automatically when they are destroyed. + */ + form.$removeControl = function(control) { + if (control.$name && form[control.$name] === control) { + delete form[control.$name]; + } + forEach(form.$pending, function(value, name) { + form.$setValidity(name, null, control); + }); + forEach(form.$error, function(value, name) { + form.$setValidity(name, null, control); + }); + + arrayRemove(controls, control); + }; + + + /** + * @ngdoc method + * @name form.FormController#$setValidity + * + * @description + * Sets the validity of a form control. + * + * This method will also propagate to parent forms. + */ + addSetValidityMethod({ + ctrl: this, + $element: element, + set: function(object, property, control) { + var list = object[property]; + if (!list) { + object[property] = [control]; + } else { + var index = list.indexOf(control); + if (index === -1) { + list.push(control); + } + } + }, + unset: function(object, property, control) { + var list = object[property]; + if (!list) { + return; + } + arrayRemove(list, control); + if (list.length === 0) { + delete object[property]; + } + }, + parentForm: parentForm, + $animate: $animate + }); + + /** + * @ngdoc method + * @name form.FormController#$setDirty + * + * @description + * Sets the form to a dirty state. + * + * This method can be called to add the 'ng-dirty' class and set the form to a dirty + * state (ng-dirty class). This method will also propagate to parent forms. + */ + form.$setDirty = function() { + $animate.removeClass(element, PRISTINE_CLASS); + $animate.addClass(element, DIRTY_CLASS); + form.$dirty = true; + form.$pristine = false; + parentForm.$setDirty(); + }; + + /** + * @ngdoc method + * @name form.FormController#$setPristine + * + * @description + * Sets the form to its pristine state. + * + * This method can be called to remove the 'ng-dirty' class and set the form to its pristine + * state (ng-pristine class). This method will also propagate to all the controls contained + * in this form. + * + * Setting a form back to a pristine state is often useful when we want to 'reuse' a form after + * saving or resetting it. + */ + form.$setPristine = function() { + $animate.setClass(element, PRISTINE_CLASS, DIRTY_CLASS + ' ' + SUBMITTED_CLASS); + form.$dirty = false; + form.$pristine = true; + form.$submitted = false; + forEach(controls, function(control) { + control.$setPristine(); + }); + }; + + /** + * @ngdoc method + * @name form.FormController#$setUntouched + * + * @description + * Sets the form to its untouched state. + * + * This method can be called to remove the 'ng-touched' class and set the form controls to their + * untouched state (ng-untouched class). + * + * Setting a form controls back to their untouched state is often useful when setting the form + * back to its pristine state. + */ + form.$setUntouched = function() { + forEach(controls, function(control) { + control.$setUntouched(); + }); + }; + + /** + * @ngdoc method + * @name form.FormController#$setSubmitted + * + * @description + * Sets the form to its submitted state. + */ + form.$setSubmitted = function() { + $animate.addClass(element, SUBMITTED_CLASS); + form.$submitted = true; + parentForm.$setSubmitted(); + }; +} + +/** + * @ngdoc directive + * @name ngForm + * @restrict EAC + * + * @description + * Nestable alias of {@link ng.directive:form `form`} directive. HTML + * does not allow nesting of form elements. It is useful to nest forms, for example if the validity of a + * sub-group of controls needs to be determined. + * + * Note: the purpose of `ngForm` is to group controls, + * but not to be a replacement for the `
      ` tag with all of its capabilities + * (e.g. posting to the server, ...). + * + * @param {string=} ngForm|name Name of the form. If specified, the form controller will be published into + * related scope, under this name. + * + */ + + /** + * @ngdoc directive + * @name form + * @restrict E + * + * @description + * Directive that instantiates + * {@link form.FormController FormController}. + * + * If the `name` attribute is specified, the form controller is published onto the current scope under + * this name. + * + * # Alias: {@link ng.directive:ngForm `ngForm`} + * + * In Angular forms can be nested. This means that the outer form is valid when all of the child + * forms are valid as well. However, browsers do not allow nesting of `` elements, so + * Angular provides the {@link ng.directive:ngForm `ngForm`} directive which behaves identically to + * `` but can be nested. This allows you to have nested forms, which is very useful when + * using Angular validation directives in forms that are dynamically generated using the + * {@link ng.directive:ngRepeat `ngRepeat`} directive. Since you cannot dynamically generate the `name` + * attribute of input elements using interpolation, you have to wrap each set of repeated inputs in an + * `ngForm` directive and nest these in an outer `form` element. + * + * + * # CSS classes + * - `ng-valid` is set if the form is valid. + * - `ng-invalid` is set if the form is invalid. + * - `ng-pristine` is set if the form is pristine. + * - `ng-dirty` is set if the form is dirty. + * - `ng-submitted` is set if the form was submitted. + * + * Keep in mind that ngAnimate can detect each of these classes when added and removed. + * + * + * # Submitting a form and preventing the default action + * + * Since the role of forms in client-side Angular applications is different than in classical + * roundtrip apps, it is desirable for the browser not to translate the form submission into a full + * page reload that sends the data to the server. Instead some javascript logic should be triggered + * to handle the form submission in an application-specific way. + * + * For this reason, Angular prevents the default action (form submission to the server) unless the + * `` element has an `action` attribute specified. + * + * You can use one of the following two ways to specify what javascript method should be called when + * a form is submitted: + * + * - {@link ng.directive:ngSubmit ngSubmit} directive on the form element + * - {@link ng.directive:ngClick ngClick} directive on the first + * button or input field of type submit (input[type=submit]) + * + * To prevent double execution of the handler, use only one of the {@link ng.directive:ngSubmit ngSubmit} + * or {@link ng.directive:ngClick ngClick} directives. + * This is because of the following form submission rules in the HTML specification: + * + * - If a form has only one input field then hitting enter in this field triggers form submit + * (`ngSubmit`) + * - if a form has 2+ input fields and no buttons or input[type=submit] then hitting enter + * doesn't trigger submit + * - if a form has one or more input fields and one or more buttons or input[type=submit] then + * hitting enter in any of the input fields will trigger the click handler on the *first* button or + * input[type=submit] (`ngClick`) *and* a submit handler on the enclosing form (`ngSubmit`) + * + * Any pending `ngModelOptions` changes will take place immediately when an enclosing form is + * submitted. Note that `ngClick` events will occur before the model is updated. Use `ngSubmit` + * to have access to the updated model. + * + * ## Animation Hooks + * + * Animations in ngForm are triggered when any of the associated CSS classes are added and removed. + * These classes are: `.ng-pristine`, `.ng-dirty`, `.ng-invalid` and `.ng-valid` as well as any + * other validations that are performed within the form. Animations in ngForm are similar to how + * they work in ngClass and animations can be hooked into using CSS transitions, keyframes as well + * as JS animations. + * + * The following example shows a simple way to utilize CSS transitions to style a form element + * that has been rendered as invalid after it has been validated: + * + *
      + * //be sure to include ngAnimate as a module to hook into more
      + * //advanced animations
      + * .my-form {
      + *   transition:0.5s linear all;
      + *   background: white;
      + * }
      + * .my-form.ng-invalid {
      + *   background: red;
      + *   color:white;
      + * }
      + * 
      + * + * @example + + + + + + userType: + Required!
      + userType = {{userType}}
      + myForm.input.$valid = {{myForm.input.$valid}}
      + myForm.input.$error = {{myForm.input.$error}}
      + myForm.$valid = {{myForm.$valid}}
      + myForm.$error.required = {{!!myForm.$error.required}}
      + +
      + + it('should initialize to model', function() { + var userType = element(by.binding('userType')); + var valid = element(by.binding('myForm.input.$valid')); + + expect(userType.getText()).toContain('guest'); + expect(valid.getText()).toContain('true'); + }); + + it('should be invalid if empty', function() { + var userType = element(by.binding('userType')); + var valid = element(by.binding('myForm.input.$valid')); + var userInput = element(by.model('userType')); + + userInput.clear(); + userInput.sendKeys(''); + + expect(userType.getText()).toEqual('userType ='); + expect(valid.getText()).toContain('false'); + }); + +
      + * + * @param {string=} name Name of the form. If specified, the form controller will be published into + * related scope, under this name. + */ +var formDirectiveFactory = function(isNgForm) { + return ['$timeout', function($timeout) { + var formDirective = { + name: 'form', + restrict: isNgForm ? 'EAC' : 'E', + controller: FormController, + compile: function ngFormCompile(formElement) { + // Setup initial state of the control + formElement.addClass(PRISTINE_CLASS).addClass(VALID_CLASS); + + return { + pre: function ngFormPreLink(scope, formElement, attr, controller) { + // if `action` attr is not present on the form, prevent the default action (submission) + if (!('action' in attr)) { + // we can't use jq events because if a form is destroyed during submission the default + // action is not prevented. see #1238 + // + // IE 9 is not affected because it doesn't fire a submit event and try to do a full + // page reload if the form was destroyed by submission of the form via a click handler + // on a button in the form. Looks like an IE9 specific bug. + var handleFormSubmission = function(event) { + scope.$apply(function() { + controller.$commitViewValue(); + controller.$setSubmitted(); + }); + + event.preventDefault(); + }; + + addEventListenerFn(formElement[0], 'submit', handleFormSubmission); + + // unregister the preventDefault listener so that we don't not leak memory but in a + // way that will achieve the prevention of the default action. + formElement.on('$destroy', function() { + $timeout(function() { + removeEventListenerFn(formElement[0], 'submit', handleFormSubmission); + }, 0, false); + }); + } + + var parentFormCtrl = controller.$$parentForm, + alias = controller.$name; + + if (alias) { + setter(scope, alias, controller, alias); + attr.$observe(attr.name ? 'name' : 'ngForm', function(newValue) { + if (alias === newValue) return; + setter(scope, alias, undefined, alias); + alias = newValue; + setter(scope, alias, controller, alias); + parentFormCtrl.$$renameControl(controller, alias); + }); + } + formElement.on('$destroy', function() { + parentFormCtrl.$removeControl(controller); + if (alias) { + setter(scope, alias, undefined, alias); + } + extend(controller, nullFormCtrl); //stop propagating child destruction handlers upwards + }); + } + }; + } + }; + + return formDirective; + }]; +}; + +var formDirective = formDirectiveFactory(); +var ngFormDirective = formDirectiveFactory(true); + +/* global VALID_CLASS: true, + INVALID_CLASS: true, + PRISTINE_CLASS: true, + DIRTY_CLASS: true, + UNTOUCHED_CLASS: true, + TOUCHED_CLASS: true, +*/ + +// Regex code is obtained from SO: https://stackoverflow.com/questions/3143070/javascript-regex-iso-datetime#answer-3143231 +var ISO_DATE_REGEXP = /\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d:[0-5]\d\.\d+([+-][0-2]\d:[0-5]\d|Z)/; +var URL_REGEXP = /^(ftp|http|https):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?$/; +var EMAIL_REGEXP = /^[a-z0-9!#$%&'*+\/=?^_`{|}~.-]+@[a-z0-9]([a-z0-9-]*[a-z0-9])?(\.[a-z0-9]([a-z0-9-]*[a-z0-9])?)*$/i; +var NUMBER_REGEXP = /^\s*(\-|\+)?(\d+|(\d*(\.\d*)))\s*$/; +var DATE_REGEXP = /^(\d{4})-(\d{2})-(\d{2})$/; +var DATETIMELOCAL_REGEXP = /^(\d{4})-(\d\d)-(\d\d)T(\d\d):(\d\d)(?::(\d\d)(\.\d{1,3})?)?$/; +var WEEK_REGEXP = /^(\d{4})-W(\d\d)$/; +var MONTH_REGEXP = /^(\d{4})-(\d\d)$/; +var TIME_REGEXP = /^(\d\d):(\d\d)(?::(\d\d)(\.\d{1,3})?)?$/; +var DEFAULT_REGEXP = /(\s+|^)default(\s+|$)/; + +var $ngModelMinErr = new minErr('ngModel'); + +var inputType = { + + /** + * @ngdoc input + * @name input[text] + * + * @description + * Standard HTML text input with angular data binding, inherited by most of the `input` elements. + * + * + * @param {string} ngModel Assignable angular expression to data-bind to. + * @param {string=} name Property name of the form under which the control is published. + * @param {string=} required Adds `required` validation error key if the value is not entered. + * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to + * the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of + * `required` when you want to data-bind to the `required` attribute. + * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than + * minlength. + * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than + * maxlength. Setting the attribute to a negative or non-numeric value, allows view values of + * any length. + * @param {string=} pattern Similar to `ngPattern` except that the attribute value is the actual string + * that contains the regular expression body that will be converted to a regular expression + * as in the ngPattern directive. + * @param {string=} ngPattern Sets `pattern` validation error key if the ngModel value does not match + * a RegExp found by evaluating the Angular expression given in the attribute value. + * If the expression evaluates to a RegExp object then this is used directly. + * If the expression is a string then it will be converted to a RegExp after wrapping it in `^` and `$` + * characters. For instance, `"abc"` will be converted to `new RegExp('^abc$')`. + * @param {string=} ngChange Angular expression to be executed when input changes due to user + * interaction with the input element. + * @param {boolean=} [ngTrim=true] If set to false Angular will not automatically trim the input. + * This parameter is ignored for input[type=password] controls, which will never trim the + * input. + * + * @example + + + +
      + Single word: + + Required! + + Single word only! + + text = {{text}}
      + myForm.input.$valid = {{myForm.input.$valid}}
      + myForm.input.$error = {{myForm.input.$error}}
      + myForm.$valid = {{myForm.$valid}}
      + myForm.$error.required = {{!!myForm.$error.required}}
      +
      +
      + + var text = element(by.binding('text')); + var valid = element(by.binding('myForm.input.$valid')); + var input = element(by.model('text')); + + it('should initialize to model', function() { + expect(text.getText()).toContain('guest'); + expect(valid.getText()).toContain('true'); + }); + + it('should be invalid if empty', function() { + input.clear(); + input.sendKeys(''); + + expect(text.getText()).toEqual('text ='); + expect(valid.getText()).toContain('false'); + }); + + it('should be invalid if multi word', function() { + input.clear(); + input.sendKeys('hello world'); + + expect(valid.getText()).toContain('false'); + }); + +
      + */ + 'text': textInputType, + + /** + * @ngdoc input + * @name input[date] + * + * @description + * Input with date validation and transformation. In browsers that do not yet support + * the HTML5 date input, a text element will be used. In that case, text must be entered in a valid ISO-8601 + * date format (yyyy-MM-dd), for example: `2009-01-06`. Since many + * modern browsers do not yet support this input type, it is important to provide cues to users on the + * expected input format via a placeholder or label. + * + * The model must always be a Date object, otherwise Angular will throw an error. + * Invalid `Date` objects (dates whose `getTime()` is `NaN`) will be rendered as an empty string. + * + * The timezone to be used to read/write the `Date` instance in the model can be defined using + * {@link ng.directive:ngModelOptions ngModelOptions}. By default, this is the timezone of the browser. + * + * @param {string} ngModel Assignable angular expression to data-bind to. + * @param {string=} name Property name of the form under which the control is published. + * @param {string=} min Sets the `min` validation error key if the value entered is less than `min`. This must be a + * valid ISO date string (yyyy-MM-dd). + * @param {string=} max Sets the `max` validation error key if the value entered is greater than `max`. This must be + * a valid ISO date string (yyyy-MM-dd). + * @param {string=} required Sets `required` validation error key if the value is not entered. + * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to + * the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of + * `required` when you want to data-bind to the `required` attribute. + * @param {string=} ngChange Angular expression to be executed when input changes due to user + * interaction with the input element. + * + * @example + + + +
      + Pick a date in 2013: + + + Required! + + Not a valid date! + value = {{value | date: "yyyy-MM-dd"}}
      + myForm.input.$valid = {{myForm.input.$valid}}
      + myForm.input.$error = {{myForm.input.$error}}
      + myForm.$valid = {{myForm.$valid}}
      + myForm.$error.required = {{!!myForm.$error.required}}
      +
      +
      + + var value = element(by.binding('value | date: "yyyy-MM-dd"')); + var valid = element(by.binding('myForm.input.$valid')); + var input = element(by.model('value')); + + // currently protractor/webdriver does not support + // sending keys to all known HTML5 input controls + // for various browsers (see https://github.com/angular/protractor/issues/562). + function setInput(val) { + // set the value of the element and force validation. + var scr = "var ipt = document.getElementById('exampleInput'); " + + "ipt.value = '" + val + "';" + + "angular.element(ipt).scope().$apply(function(s) { s.myForm[ipt.name].$setViewValue('" + val + "'); });"; + browser.executeScript(scr); + } + + it('should initialize to model', function() { + expect(value.getText()).toContain('2013-10-22'); + expect(valid.getText()).toContain('myForm.input.$valid = true'); + }); + + it('should be invalid if empty', function() { + setInput(''); + expect(value.getText()).toEqual('value ='); + expect(valid.getText()).toContain('myForm.input.$valid = false'); + }); + + it('should be invalid if over max', function() { + setInput('2015-01-01'); + expect(value.getText()).toContain(''); + expect(valid.getText()).toContain('myForm.input.$valid = false'); + }); + +
      + */ + 'date': createDateInputType('date', DATE_REGEXP, + createDateParser(DATE_REGEXP, ['yyyy', 'MM', 'dd']), + 'yyyy-MM-dd'), + + /** + * @ngdoc input + * @name input[datetime-local] + * + * @description + * Input with datetime validation and transformation. In browsers that do not yet support + * the HTML5 date input, a text element will be used. In that case, the text must be entered in a valid ISO-8601 + * local datetime format (yyyy-MM-ddTHH:mm:ss), for example: `2010-12-28T14:57:00`. + * + * The model must always be a Date object, otherwise Angular will throw an error. + * Invalid `Date` objects (dates whose `getTime()` is `NaN`) will be rendered as an empty string. + * + * The timezone to be used to read/write the `Date` instance in the model can be defined using + * {@link ng.directive:ngModelOptions ngModelOptions}. By default, this is the timezone of the browser. + * + * @param {string} ngModel Assignable angular expression to data-bind to. + * @param {string=} name Property name of the form under which the control is published. + * @param {string=} min Sets the `min` validation error key if the value entered is less than `min`. This must be a + * valid ISO datetime format (yyyy-MM-ddTHH:mm:ss). + * @param {string=} max Sets the `max` validation error key if the value entered is greater than `max`. This must be + * a valid ISO datetime format (yyyy-MM-ddTHH:mm:ss). + * @param {string=} required Sets `required` validation error key if the value is not entered. + * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to + * the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of + * `required` when you want to data-bind to the `required` attribute. + * @param {string=} ngChange Angular expression to be executed when input changes due to user + * interaction with the input element. + * + * @example + + + +
      + Pick a date between in 2013: + + + Required! + + Not a valid date! + value = {{value | date: "yyyy-MM-ddTHH:mm:ss"}}
      + myForm.input.$valid = {{myForm.input.$valid}}
      + myForm.input.$error = {{myForm.input.$error}}
      + myForm.$valid = {{myForm.$valid}}
      + myForm.$error.required = {{!!myForm.$error.required}}
      +
      +
      + + var value = element(by.binding('value | date: "yyyy-MM-ddTHH:mm:ss"')); + var valid = element(by.binding('myForm.input.$valid')); + var input = element(by.model('value')); + + // currently protractor/webdriver does not support + // sending keys to all known HTML5 input controls + // for various browsers (https://github.com/angular/protractor/issues/562). + function setInput(val) { + // set the value of the element and force validation. + var scr = "var ipt = document.getElementById('exampleInput'); " + + "ipt.value = '" + val + "';" + + "angular.element(ipt).scope().$apply(function(s) { s.myForm[ipt.name].$setViewValue('" + val + "'); });"; + browser.executeScript(scr); + } + + it('should initialize to model', function() { + expect(value.getText()).toContain('2010-12-28T14:57:00'); + expect(valid.getText()).toContain('myForm.input.$valid = true'); + }); + + it('should be invalid if empty', function() { + setInput(''); + expect(value.getText()).toEqual('value ='); + expect(valid.getText()).toContain('myForm.input.$valid = false'); + }); + + it('should be invalid if over max', function() { + setInput('2015-01-01T23:59:00'); + expect(value.getText()).toContain(''); + expect(valid.getText()).toContain('myForm.input.$valid = false'); + }); + +
      + */ + 'datetime-local': createDateInputType('datetimelocal', DATETIMELOCAL_REGEXP, + createDateParser(DATETIMELOCAL_REGEXP, ['yyyy', 'MM', 'dd', 'HH', 'mm', 'ss', 'sss']), + 'yyyy-MM-ddTHH:mm:ss.sss'), + + /** + * @ngdoc input + * @name input[time] + * + * @description + * Input with time validation and transformation. In browsers that do not yet support + * the HTML5 date input, a text element will be used. In that case, the text must be entered in a valid ISO-8601 + * local time format (HH:mm:ss), for example: `14:57:00`. Model must be a Date object. This binding will always output a + * Date object to the model of January 1, 1970, or local date `new Date(1970, 0, 1, HH, mm, ss)`. + * + * The model must always be a Date object, otherwise Angular will throw an error. + * Invalid `Date` objects (dates whose `getTime()` is `NaN`) will be rendered as an empty string. + * + * The timezone to be used to read/write the `Date` instance in the model can be defined using + * {@link ng.directive:ngModelOptions ngModelOptions}. By default, this is the timezone of the browser. + * + * @param {string} ngModel Assignable angular expression to data-bind to. + * @param {string=} name Property name of the form under which the control is published. + * @param {string=} min Sets the `min` validation error key if the value entered is less than `min`. This must be a + * valid ISO time format (HH:mm:ss). + * @param {string=} max Sets the `max` validation error key if the value entered is greater than `max`. This must be a + * valid ISO time format (HH:mm:ss). + * @param {string=} required Sets `required` validation error key if the value is not entered. + * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to + * the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of + * `required` when you want to data-bind to the `required` attribute. + * @param {string=} ngChange Angular expression to be executed when input changes due to user + * interaction with the input element. + * + * @example + + + +
      + Pick a between 8am and 5pm: + + + Required! + + Not a valid date! + value = {{value | date: "HH:mm:ss"}}
      + myForm.input.$valid = {{myForm.input.$valid}}
      + myForm.input.$error = {{myForm.input.$error}}
      + myForm.$valid = {{myForm.$valid}}
      + myForm.$error.required = {{!!myForm.$error.required}}
      +
      +
      + + var value = element(by.binding('value | date: "HH:mm:ss"')); + var valid = element(by.binding('myForm.input.$valid')); + var input = element(by.model('value')); + + // currently protractor/webdriver does not support + // sending keys to all known HTML5 input controls + // for various browsers (https://github.com/angular/protractor/issues/562). + function setInput(val) { + // set the value of the element and force validation. + var scr = "var ipt = document.getElementById('exampleInput'); " + + "ipt.value = '" + val + "';" + + "angular.element(ipt).scope().$apply(function(s) { s.myForm[ipt.name].$setViewValue('" + val + "'); });"; + browser.executeScript(scr); + } + + it('should initialize to model', function() { + expect(value.getText()).toContain('14:57:00'); + expect(valid.getText()).toContain('myForm.input.$valid = true'); + }); + + it('should be invalid if empty', function() { + setInput(''); + expect(value.getText()).toEqual('value ='); + expect(valid.getText()).toContain('myForm.input.$valid = false'); + }); + + it('should be invalid if over max', function() { + setInput('23:59:00'); + expect(value.getText()).toContain(''); + expect(valid.getText()).toContain('myForm.input.$valid = false'); + }); + +
      + */ + 'time': createDateInputType('time', TIME_REGEXP, + createDateParser(TIME_REGEXP, ['HH', 'mm', 'ss', 'sss']), + 'HH:mm:ss.sss'), + + /** + * @ngdoc input + * @name input[week] + * + * @description + * Input with week-of-the-year validation and transformation to Date. In browsers that do not yet support + * the HTML5 week input, a text element will be used. In that case, the text must be entered in a valid ISO-8601 + * week format (yyyy-W##), for example: `2013-W02`. + * + * The model must always be a Date object, otherwise Angular will throw an error. + * Invalid `Date` objects (dates whose `getTime()` is `NaN`) will be rendered as an empty string. + * + * The timezone to be used to read/write the `Date` instance in the model can be defined using + * {@link ng.directive:ngModelOptions ngModelOptions}. By default, this is the timezone of the browser. + * + * @param {string} ngModel Assignable angular expression to data-bind to. + * @param {string=} name Property name of the form under which the control is published. + * @param {string=} min Sets the `min` validation error key if the value entered is less than `min`. This must be a + * valid ISO week format (yyyy-W##). + * @param {string=} max Sets the `max` validation error key if the value entered is greater than `max`. This must be + * a valid ISO week format (yyyy-W##). + * @param {string=} required Sets `required` validation error key if the value is not entered. + * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to + * the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of + * `required` when you want to data-bind to the `required` attribute. + * @param {string=} ngChange Angular expression to be executed when input changes due to user + * interaction with the input element. + * + * @example + + + +
      + Pick a date between in 2013: + + + Required! + + Not a valid date! + value = {{value | date: "yyyy-Www"}}
      + myForm.input.$valid = {{myForm.input.$valid}}
      + myForm.input.$error = {{myForm.input.$error}}
      + myForm.$valid = {{myForm.$valid}}
      + myForm.$error.required = {{!!myForm.$error.required}}
      +
      +
      + + var value = element(by.binding('value | date: "yyyy-Www"')); + var valid = element(by.binding('myForm.input.$valid')); + var input = element(by.model('value')); + + // currently protractor/webdriver does not support + // sending keys to all known HTML5 input controls + // for various browsers (https://github.com/angular/protractor/issues/562). + function setInput(val) { + // set the value of the element and force validation. + var scr = "var ipt = document.getElementById('exampleInput'); " + + "ipt.value = '" + val + "';" + + "angular.element(ipt).scope().$apply(function(s) { s.myForm[ipt.name].$setViewValue('" + val + "'); });"; + browser.executeScript(scr); + } + + it('should initialize to model', function() { + expect(value.getText()).toContain('2013-W01'); + expect(valid.getText()).toContain('myForm.input.$valid = true'); + }); + + it('should be invalid if empty', function() { + setInput(''); + expect(value.getText()).toEqual('value ='); + expect(valid.getText()).toContain('myForm.input.$valid = false'); + }); + + it('should be invalid if over max', function() { + setInput('2015-W01'); + expect(value.getText()).toContain(''); + expect(valid.getText()).toContain('myForm.input.$valid = false'); + }); + +
      + */ + 'week': createDateInputType('week', WEEK_REGEXP, weekParser, 'yyyy-Www'), + + /** + * @ngdoc input + * @name input[month] + * + * @description + * Input with month validation and transformation. In browsers that do not yet support + * the HTML5 month input, a text element will be used. In that case, the text must be entered in a valid ISO-8601 + * month format (yyyy-MM), for example: `2009-01`. + * + * The model must always be a Date object, otherwise Angular will throw an error. + * Invalid `Date` objects (dates whose `getTime()` is `NaN`) will be rendered as an empty string. + * If the model is not set to the first of the month, the next view to model update will set it + * to the first of the month. + * + * The timezone to be used to read/write the `Date` instance in the model can be defined using + * {@link ng.directive:ngModelOptions ngModelOptions}. By default, this is the timezone of the browser. + * + * @param {string} ngModel Assignable angular expression to data-bind to. + * @param {string=} name Property name of the form under which the control is published. + * @param {string=} min Sets the `min` validation error key if the value entered is less than `min`. This must be + * a valid ISO month format (yyyy-MM). + * @param {string=} max Sets the `max` validation error key if the value entered is greater than `max`. This must + * be a valid ISO month format (yyyy-MM). + * @param {string=} required Sets `required` validation error key if the value is not entered. + * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to + * the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of + * `required` when you want to data-bind to the `required` attribute. + * @param {string=} ngChange Angular expression to be executed when input changes due to user + * interaction with the input element. + * + * @example + + + +
      + Pick a month int 2013: + + + Required! + + Not a valid month! + value = {{value | date: "yyyy-MM"}}
      + myForm.input.$valid = {{myForm.input.$valid}}
      + myForm.input.$error = {{myForm.input.$error}}
      + myForm.$valid = {{myForm.$valid}}
      + myForm.$error.required = {{!!myForm.$error.required}}
      +
      +
      + + var value = element(by.binding('value | date: "yyyy-MM"')); + var valid = element(by.binding('myForm.input.$valid')); + var input = element(by.model('value')); + + // currently protractor/webdriver does not support + // sending keys to all known HTML5 input controls + // for various browsers (https://github.com/angular/protractor/issues/562). + function setInput(val) { + // set the value of the element and force validation. + var scr = "var ipt = document.getElementById('exampleInput'); " + + "ipt.value = '" + val + "';" + + "angular.element(ipt).scope().$apply(function(s) { s.myForm[ipt.name].$setViewValue('" + val + "'); });"; + browser.executeScript(scr); + } + + it('should initialize to model', function() { + expect(value.getText()).toContain('2013-10'); + expect(valid.getText()).toContain('myForm.input.$valid = true'); + }); + + it('should be invalid if empty', function() { + setInput(''); + expect(value.getText()).toEqual('value ='); + expect(valid.getText()).toContain('myForm.input.$valid = false'); + }); + + it('should be invalid if over max', function() { + setInput('2015-01'); + expect(value.getText()).toContain(''); + expect(valid.getText()).toContain('myForm.input.$valid = false'); + }); + +
      + */ + 'month': createDateInputType('month', MONTH_REGEXP, + createDateParser(MONTH_REGEXP, ['yyyy', 'MM']), + 'yyyy-MM'), + + /** + * @ngdoc input + * @name input[number] + * + * @description + * Text input with number validation and transformation. Sets the `number` validation + * error if not a valid number. + * + * The model must always be a number, otherwise Angular will throw an error. + * + * @param {string} ngModel Assignable angular expression to data-bind to. + * @param {string=} name Property name of the form under which the control is published. + * @param {string=} min Sets the `min` validation error key if the value entered is less than `min`. + * @param {string=} max Sets the `max` validation error key if the value entered is greater than `max`. + * @param {string=} required Sets `required` validation error key if the value is not entered. + * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to + * the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of + * `required` when you want to data-bind to the `required` attribute. + * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than + * minlength. + * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than + * maxlength. Setting the attribute to a negative or non-numeric value, allows view values of + * any length. + * @param {string=} pattern Similar to `ngPattern` except that the attribute value is the actual string + * that contains the regular expression body that will be converted to a regular expression + * as in the ngPattern directive. + * @param {string=} ngPattern Sets `pattern` validation error key if the ngModel value does not match + * a RegExp found by evaluating the Angular expression given in the attribute value. + * If the expression evaluates to a RegExp object then this is used directly. + * If the expression is a string then it will be converted to a RegExp after wrapping it in `^` and `$` + * characters. For instance, `"abc"` will be converted to `new RegExp('^abc$')`. + * @param {string=} ngChange Angular expression to be executed when input changes due to user + * interaction with the input element. + * + * @example + + + +
      + Number: + + Required! + + Not valid number! + value = {{value}}
      + myForm.input.$valid = {{myForm.input.$valid}}
      + myForm.input.$error = {{myForm.input.$error}}
      + myForm.$valid = {{myForm.$valid}}
      + myForm.$error.required = {{!!myForm.$error.required}}
      +
      +
      + + var value = element(by.binding('value')); + var valid = element(by.binding('myForm.input.$valid')); + var input = element(by.model('value')); + + it('should initialize to model', function() { + expect(value.getText()).toContain('12'); + expect(valid.getText()).toContain('true'); + }); + + it('should be invalid if empty', function() { + input.clear(); + input.sendKeys(''); + expect(value.getText()).toEqual('value ='); + expect(valid.getText()).toContain('false'); + }); + + it('should be invalid if over max', function() { + input.clear(); + input.sendKeys('123'); + expect(value.getText()).toEqual('value ='); + expect(valid.getText()).toContain('false'); + }); + +
      + */ + 'number': numberInputType, + + + /** + * @ngdoc input + * @name input[url] + * + * @description + * Text input with URL validation. Sets the `url` validation error key if the content is not a + * valid URL. + * + *
      + * **Note:** `input[url]` uses a regex to validate urls that is derived from the regex + * used in Chromium. If you need stricter validation, you can use `ng-pattern` or modify + * the built-in validators (see the {@link guide/forms Forms guide}) + *
      + * + * @param {string} ngModel Assignable angular expression to data-bind to. + * @param {string=} name Property name of the form under which the control is published. + * @param {string=} required Sets `required` validation error key if the value is not entered. + * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to + * the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of + * `required` when you want to data-bind to the `required` attribute. + * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than + * minlength. + * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than + * maxlength. Setting the attribute to a negative or non-numeric value, allows view values of + * any length. + * @param {string=} pattern Similar to `ngPattern` except that the attribute value is the actual string + * that contains the regular expression body that will be converted to a regular expression + * as in the ngPattern directive. + * @param {string=} ngPattern Sets `pattern` validation error key if the ngModel value does not match + * a RegExp found by evaluating the Angular expression given in the attribute value. + * If the expression evaluates to a RegExp object then this is used directly. + * If the expression is a string then it will be converted to a RegExp after wrapping it in `^` and `$` + * characters. For instance, `"abc"` will be converted to `new RegExp('^abc$')`. + * @param {string=} ngChange Angular expression to be executed when input changes due to user + * interaction with the input element. + * + * @example + + + +
      + URL: + + Required! + + Not valid url! + text = {{text}}
      + myForm.input.$valid = {{myForm.input.$valid}}
      + myForm.input.$error = {{myForm.input.$error}}
      + myForm.$valid = {{myForm.$valid}}
      + myForm.$error.required = {{!!myForm.$error.required}}
      + myForm.$error.url = {{!!myForm.$error.url}}
      +
      +
      + + var text = element(by.binding('text')); + var valid = element(by.binding('myForm.input.$valid')); + var input = element(by.model('text')); + + it('should initialize to model', function() { + expect(text.getText()).toContain('http://google.com'); + expect(valid.getText()).toContain('true'); + }); + + it('should be invalid if empty', function() { + input.clear(); + input.sendKeys(''); + + expect(text.getText()).toEqual('text ='); + expect(valid.getText()).toContain('false'); + }); + + it('should be invalid if not url', function() { + input.clear(); + input.sendKeys('box'); + + expect(valid.getText()).toContain('false'); + }); + +
      + */ + 'url': urlInputType, + + + /** + * @ngdoc input + * @name input[email] + * + * @description + * Text input with email validation. Sets the `email` validation error key if not a valid email + * address. + * + *
      + * **Note:** `input[email]` uses a regex to validate email addresses that is derived from the regex + * used in Chromium. If you need stricter validation (e.g. requiring a top-level domain), you can + * use `ng-pattern` or modify the built-in validators (see the {@link guide/forms Forms guide}) + *
      + * + * @param {string} ngModel Assignable angular expression to data-bind to. + * @param {string=} name Property name of the form under which the control is published. + * @param {string=} required Sets `required` validation error key if the value is not entered. + * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to + * the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of + * `required` when you want to data-bind to the `required` attribute. + * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than + * minlength. + * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than + * maxlength. Setting the attribute to a negative or non-numeric value, allows view values of + * any length. + * @param {string=} pattern Similar to `ngPattern` except that the attribute value is the actual string + * that contains the regular expression body that will be converted to a regular expression + * as in the ngPattern directive. + * @param {string=} ngPattern Sets `pattern` validation error key if the ngModel value does not match + * a RegExp found by evaluating the Angular expression given in the attribute value. + * If the expression evaluates to a RegExp object then this is used directly. + * If the expression is a string then it will be converted to a RegExp after wrapping it in `^` and `$` + * characters. For instance, `"abc"` will be converted to `new RegExp('^abc$')`. + * @param {string=} ngChange Angular expression to be executed when input changes due to user + * interaction with the input element. + * + * @example + + + +
      + Email: + + Required! + + Not valid email! + text = {{text}}
      + myForm.input.$valid = {{myForm.input.$valid}}
      + myForm.input.$error = {{myForm.input.$error}}
      + myForm.$valid = {{myForm.$valid}}
      + myForm.$error.required = {{!!myForm.$error.required}}
      + myForm.$error.email = {{!!myForm.$error.email}}
      +
      +
      + + var text = element(by.binding('text')); + var valid = element(by.binding('myForm.input.$valid')); + var input = element(by.model('text')); + + it('should initialize to model', function() { + expect(text.getText()).toContain('me@example.com'); + expect(valid.getText()).toContain('true'); + }); + + it('should be invalid if empty', function() { + input.clear(); + input.sendKeys(''); + expect(text.getText()).toEqual('text ='); + expect(valid.getText()).toContain('false'); + }); + + it('should be invalid if not email', function() { + input.clear(); + input.sendKeys('xxx'); + + expect(valid.getText()).toContain('false'); + }); + +
      + */ + 'email': emailInputType, + + + /** + * @ngdoc input + * @name input[radio] + * + * @description + * HTML radio button. + * + * @param {string} ngModel Assignable angular expression to data-bind to. + * @param {string} value The value to which the expression should be set when selected. + * @param {string=} name Property name of the form under which the control is published. + * @param {string=} ngChange Angular expression to be executed when input changes due to user + * interaction with the input element. + * @param {string} ngValue Angular expression which sets the value to which the expression should + * be set when selected. + * + * @example + + + +
      + Red
      + Green
      + Blue
      + color = {{color | json}}
      +
      + Note that `ng-value="specialValue"` sets radio item's value to be the value of `$scope.specialValue`. +
      + + it('should change state', function() { + var color = element(by.binding('color')); + + expect(color.getText()).toContain('blue'); + + element.all(by.model('color')).get(0).click(); + + expect(color.getText()).toContain('red'); + }); + +
      + */ + 'radio': radioInputType, + + + /** + * @ngdoc input + * @name input[checkbox] + * + * @description + * HTML checkbox. + * + * @param {string} ngModel Assignable angular expression to data-bind to. + * @param {string=} name Property name of the form under which the control is published. + * @param {expression=} ngTrueValue The value to which the expression should be set when selected. + * @param {expression=} ngFalseValue The value to which the expression should be set when not selected. + * @param {string=} ngChange Angular expression to be executed when input changes due to user + * interaction with the input element. + * + * @example + + + +
      + Value1:
      + Value2:
      + value1 = {{value1}}
      + value2 = {{value2}}
      +
      +
      + + it('should change state', function() { + var value1 = element(by.binding('value1')); + var value2 = element(by.binding('value2')); + + expect(value1.getText()).toContain('true'); + expect(value2.getText()).toContain('YES'); + + element(by.model('value1')).click(); + element(by.model('value2')).click(); + + expect(value1.getText()).toContain('false'); + expect(value2.getText()).toContain('NO'); + }); + +
      + */ + 'checkbox': checkboxInputType, + + 'hidden': noop, + 'button': noop, + 'submit': noop, + 'reset': noop, + 'file': noop +}; + +function stringBasedInputType(ctrl) { + ctrl.$formatters.push(function(value) { + return ctrl.$isEmpty(value) ? value : value.toString(); + }); +} + +function textInputType(scope, element, attr, ctrl, $sniffer, $browser) { + baseInputType(scope, element, attr, ctrl, $sniffer, $browser); + stringBasedInputType(ctrl); +} + +function baseInputType(scope, element, attr, ctrl, $sniffer, $browser) { + var type = lowercase(element[0].type); + + // In composition mode, users are still inputing intermediate text buffer, + // hold the listener until composition is done. + // More about composition events: https://developer.mozilla.org/en-US/docs/Web/API/CompositionEvent + if (!$sniffer.android) { + var composing = false; + + element.on('compositionstart', function(data) { + composing = true; + }); + + element.on('compositionend', function() { + composing = false; + listener(); + }); + } + + var listener = function(ev) { + if (timeout) { + $browser.defer.cancel(timeout); + timeout = null; + } + if (composing) return; + var value = element.val(), + event = ev && ev.type; + + // By default we will trim the value + // If the attribute ng-trim exists we will avoid trimming + // If input type is 'password', the value is never trimmed + if (type !== 'password' && (!attr.ngTrim || attr.ngTrim !== 'false')) { + value = trim(value); + } + + // If a control is suffering from bad input (due to native validators), browsers discard its + // value, so it may be necessary to revalidate (by calling $setViewValue again) even if the + // control's value is the same empty value twice in a row. + if (ctrl.$viewValue !== value || (value === '' && ctrl.$$hasNativeValidators)) { + ctrl.$setViewValue(value, event); + } + }; + + // if the browser does support "input" event, we are fine - except on IE9 which doesn't fire the + // input event on backspace, delete or cut + if ($sniffer.hasEvent('input')) { + element.on('input', listener); + } else { + var timeout; + + var deferListener = function(ev, input, origValue) { + if (!timeout) { + timeout = $browser.defer(function() { + timeout = null; + if (!input || input.value !== origValue) { + listener(ev); + } + }); + } + }; + + element.on('keydown', function(event) { + var key = event.keyCode; + + // ignore + // command modifiers arrows + if (key === 91 || (15 < key && key < 19) || (37 <= key && key <= 40)) return; + + deferListener(event, this, this.value); + }); + + // if user modifies input value using context menu in IE, we need "paste" and "cut" events to catch it + if ($sniffer.hasEvent('paste')) { + element.on('paste cut', deferListener); + } + } + + // if user paste into input using mouse on older browser + // or form autocomplete on newer browser, we need "change" event to catch it + element.on('change', listener); + + ctrl.$render = function() { + element.val(ctrl.$isEmpty(ctrl.$viewValue) ? '' : ctrl.$viewValue); + }; +} + +function weekParser(isoWeek, existingDate) { + if (isDate(isoWeek)) { + return isoWeek; + } + + if (isString(isoWeek)) { + WEEK_REGEXP.lastIndex = 0; + var parts = WEEK_REGEXP.exec(isoWeek); + if (parts) { + var year = +parts[1], + week = +parts[2], + hours = 0, + minutes = 0, + seconds = 0, + milliseconds = 0, + firstThurs = getFirstThursdayOfYear(year), + addDays = (week - 1) * 7; + + if (existingDate) { + hours = existingDate.getHours(); + minutes = existingDate.getMinutes(); + seconds = existingDate.getSeconds(); + milliseconds = existingDate.getMilliseconds(); + } + + return new Date(year, 0, firstThurs.getDate() + addDays, hours, minutes, seconds, milliseconds); + } + } + + return NaN; +} + +function createDateParser(regexp, mapping) { + return function(iso, date) { + var parts, map; + + if (isDate(iso)) { + return iso; + } + + if (isString(iso)) { + // When a date is JSON'ified to wraps itself inside of an extra + // set of double quotes. This makes the date parsing code unable + // to match the date string and parse it as a date. + if (iso.charAt(0) == '"' && iso.charAt(iso.length - 1) == '"') { + iso = iso.substring(1, iso.length - 1); + } + if (ISO_DATE_REGEXP.test(iso)) { + return new Date(iso); + } + regexp.lastIndex = 0; + parts = regexp.exec(iso); + + if (parts) { + parts.shift(); + if (date) { + map = { + yyyy: date.getFullYear(), + MM: date.getMonth() + 1, + dd: date.getDate(), + HH: date.getHours(), + mm: date.getMinutes(), + ss: date.getSeconds(), + sss: date.getMilliseconds() / 1000 + }; + } else { + map = { yyyy: 1970, MM: 1, dd: 1, HH: 0, mm: 0, ss: 0, sss: 0 }; + } + + forEach(parts, function(part, index) { + if (index < mapping.length) { + map[mapping[index]] = +part; + } + }); + return new Date(map.yyyy, map.MM - 1, map.dd, map.HH, map.mm, map.ss || 0, map.sss * 1000 || 0); + } + } + + return NaN; + }; +} + +function createDateInputType(type, regexp, parseDate, format) { + return function dynamicDateInputType(scope, element, attr, ctrl, $sniffer, $browser, $filter) { + badInputChecker(scope, element, attr, ctrl); + baseInputType(scope, element, attr, ctrl, $sniffer, $browser); + var timezone = ctrl && ctrl.$options && ctrl.$options.timezone; + var previousDate; + + ctrl.$$parserName = type; + ctrl.$parsers.push(function(value) { + if (ctrl.$isEmpty(value)) return null; + if (regexp.test(value)) { + // Note: We cannot read ctrl.$modelValue, as there might be a different + // parser/formatter in the processing chain so that the model + // contains some different data format! + var parsedDate = parseDate(value, previousDate); + if (timezone === 'UTC') { + parsedDate.setMinutes(parsedDate.getMinutes() - parsedDate.getTimezoneOffset()); + } + return parsedDate; + } + return undefined; + }); + + ctrl.$formatters.push(function(value) { + if (value && !isDate(value)) { + throw $ngModelMinErr('datefmt', 'Expected `{0}` to be a date', value); + } + if (isValidDate(value)) { + previousDate = value; + if (previousDate && timezone === 'UTC') { + var timezoneOffset = 60000 * previousDate.getTimezoneOffset(); + previousDate = new Date(previousDate.getTime() + timezoneOffset); + } + return $filter('date')(value, format, timezone); + } else { + previousDate = null; + return ''; + } + }); + + if (isDefined(attr.min) || attr.ngMin) { + var minVal; + ctrl.$validators.min = function(value) { + return !isValidDate(value) || isUndefined(minVal) || parseDate(value) >= minVal; + }; + attr.$observe('min', function(val) { + minVal = parseObservedDateValue(val); + ctrl.$validate(); + }); + } + + if (isDefined(attr.max) || attr.ngMax) { + var maxVal; + ctrl.$validators.max = function(value) { + return !isValidDate(value) || isUndefined(maxVal) || parseDate(value) <= maxVal; + }; + attr.$observe('max', function(val) { + maxVal = parseObservedDateValue(val); + ctrl.$validate(); + }); + } + + function isValidDate(value) { + // Invalid Date: getTime() returns NaN + return value && !(value.getTime && value.getTime() !== value.getTime()); + } + + function parseObservedDateValue(val) { + return isDefined(val) ? (isDate(val) ? val : parseDate(val)) : undefined; + } + }; +} + +function badInputChecker(scope, element, attr, ctrl) { + var node = element[0]; + var nativeValidation = ctrl.$$hasNativeValidators = isObject(node.validity); + if (nativeValidation) { + ctrl.$parsers.push(function(value) { + var validity = element.prop(VALIDITY_STATE_PROPERTY) || {}; + // Detect bug in FF35 for input[email] (https://bugzilla.mozilla.org/show_bug.cgi?id=1064430): + // - also sets validity.badInput (should only be validity.typeMismatch). + // - see http://www.whatwg.org/specs/web-apps/current-work/multipage/forms.html#e-mail-state-(type=email) + // - can ignore this case as we can still read out the erroneous email... + return validity.badInput && !validity.typeMismatch ? undefined : value; + }); + } +} + +function numberInputType(scope, element, attr, ctrl, $sniffer, $browser) { + badInputChecker(scope, element, attr, ctrl); + baseInputType(scope, element, attr, ctrl, $sniffer, $browser); + + ctrl.$$parserName = 'number'; + ctrl.$parsers.push(function(value) { + if (ctrl.$isEmpty(value)) return null; + if (NUMBER_REGEXP.test(value)) return parseFloat(value); + return undefined; + }); + + ctrl.$formatters.push(function(value) { + if (!ctrl.$isEmpty(value)) { + if (!isNumber(value)) { + throw $ngModelMinErr('numfmt', 'Expected `{0}` to be a number', value); + } + value = value.toString(); + } + return value; + }); + + if (attr.min || attr.ngMin) { + var minVal; + ctrl.$validators.min = function(value) { + return ctrl.$isEmpty(value) || isUndefined(minVal) || value >= minVal; + }; + + attr.$observe('min', function(val) { + if (isDefined(val) && !isNumber(val)) { + val = parseFloat(val, 10); + } + minVal = isNumber(val) && !isNaN(val) ? val : undefined; + // TODO(matsko): implement validateLater to reduce number of validations + ctrl.$validate(); + }); + } + + if (attr.max || attr.ngMax) { + var maxVal; + ctrl.$validators.max = function(value) { + return ctrl.$isEmpty(value) || isUndefined(maxVal) || value <= maxVal; + }; + + attr.$observe('max', function(val) { + if (isDefined(val) && !isNumber(val)) { + val = parseFloat(val, 10); + } + maxVal = isNumber(val) && !isNaN(val) ? val : undefined; + // TODO(matsko): implement validateLater to reduce number of validations + ctrl.$validate(); + }); + } +} + +function urlInputType(scope, element, attr, ctrl, $sniffer, $browser) { + // Note: no badInputChecker here by purpose as `url` is only a validation + // in browsers, i.e. we can always read out input.value even if it is not valid! + baseInputType(scope, element, attr, ctrl, $sniffer, $browser); + stringBasedInputType(ctrl); + + ctrl.$$parserName = 'url'; + ctrl.$validators.url = function(modelValue, viewValue) { + var value = modelValue || viewValue; + return ctrl.$isEmpty(value) || URL_REGEXP.test(value); + }; +} + +function emailInputType(scope, element, attr, ctrl, $sniffer, $browser) { + // Note: no badInputChecker here by purpose as `url` is only a validation + // in browsers, i.e. we can always read out input.value even if it is not valid! + baseInputType(scope, element, attr, ctrl, $sniffer, $browser); + stringBasedInputType(ctrl); + + ctrl.$$parserName = 'email'; + ctrl.$validators.email = function(modelValue, viewValue) { + var value = modelValue || viewValue; + return ctrl.$isEmpty(value) || EMAIL_REGEXP.test(value); + }; +} + +function radioInputType(scope, element, attr, ctrl) { + // make the name unique, if not defined + if (isUndefined(attr.name)) { + element.attr('name', nextUid()); + } + + var listener = function(ev) { + if (element[0].checked) { + ctrl.$setViewValue(attr.value, ev && ev.type); + } + }; + + element.on('click', listener); + + ctrl.$render = function() { + var value = attr.value; + element[0].checked = (value == ctrl.$viewValue); + }; + + attr.$observe('value', ctrl.$render); +} + +function parseConstantExpr($parse, context, name, expression, fallback) { + var parseFn; + if (isDefined(expression)) { + parseFn = $parse(expression); + if (!parseFn.constant) { + throw minErr('ngModel')('constexpr', 'Expected constant expression for `{0}`, but saw ' + + '`{1}`.', name, expression); + } + return parseFn(context); + } + return fallback; +} + +function checkboxInputType(scope, element, attr, ctrl, $sniffer, $browser, $filter, $parse) { + var trueValue = parseConstantExpr($parse, scope, 'ngTrueValue', attr.ngTrueValue, true); + var falseValue = parseConstantExpr($parse, scope, 'ngFalseValue', attr.ngFalseValue, false); + + var listener = function(ev) { + ctrl.$setViewValue(element[0].checked, ev && ev.type); + }; + + element.on('click', listener); + + ctrl.$render = function() { + element[0].checked = ctrl.$viewValue; + }; + + // Override the standard `$isEmpty` because the $viewValue of an empty checkbox is always set to `false` + // This is because of the parser below, which compares the `$modelValue` with `trueValue` to convert + // it to a boolean. + ctrl.$isEmpty = function(value) { + return value === false; + }; + + ctrl.$formatters.push(function(value) { + return equals(value, trueValue); + }); + + ctrl.$parsers.push(function(value) { + return value ? trueValue : falseValue; + }); +} + + +/** + * @ngdoc directive + * @name textarea + * @restrict E + * + * @description + * HTML textarea element control with angular data-binding. The data-binding and validation + * properties of this element are exactly the same as those of the + * {@link ng.directive:input input element}. + * + * @param {string} ngModel Assignable angular expression to data-bind to. + * @param {string=} name Property name of the form under which the control is published. + * @param {string=} required Sets `required` validation error key if the value is not entered. + * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to + * the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of + * `required` when you want to data-bind to the `required` attribute. + * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than + * minlength. + * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than + * maxlength. Setting the attribute to a negative or non-numeric value, allows view values of any + * length. + * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the + * RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for + * patterns defined as scope expressions. + * @param {string=} ngChange Angular expression to be executed when input changes due to user + * interaction with the input element. + * @param {boolean=} [ngTrim=true] If set to false Angular will not automatically trim the input. + */ + + +/** + * @ngdoc directive + * @name input + * @restrict E + * + * @description + * HTML input element control. When used together with {@link ngModel `ngModel`}, it provides data-binding, + * input state control, and validation. + * Input control follows HTML5 input types and polyfills the HTML5 validation behavior for older browsers. + * + *
      + * **Note:** Not every feature offered is available for all input types. + * Specifically, data binding and event handling via `ng-model` is unsupported for `input[file]`. + *
      + * + * @param {string} ngModel Assignable angular expression to data-bind to. + * @param {string=} name Property name of the form under which the control is published. + * @param {string=} required Sets `required` validation error key if the value is not entered. + * @param {boolean=} ngRequired Sets `required` attribute if set to true + * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than + * minlength. + * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than + * maxlength. Setting the attribute to a negative or non-numeric value, allows view values of any + * length. + * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the + * RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for + * patterns defined as scope expressions. + * @param {string=} ngChange Angular expression to be executed when input changes due to user + * interaction with the input element. + * @param {boolean=} [ngTrim=true] If set to false Angular will not automatically trim the input. + * This parameter is ignored for input[type=password] controls, which will never trim the + * input. + * + * @example + + + +
      +
      + User name: + + Required!
      + Last name: + + Too short! + + Too long!
      +
      +
      + user = {{user}}
      + myForm.userName.$valid = {{myForm.userName.$valid}}
      + myForm.userName.$error = {{myForm.userName.$error}}
      + myForm.lastName.$valid = {{myForm.lastName.$valid}}
      + myForm.lastName.$error = {{myForm.lastName.$error}}
      + myForm.$valid = {{myForm.$valid}}
      + myForm.$error.required = {{!!myForm.$error.required}}
      + myForm.$error.minlength = {{!!myForm.$error.minlength}}
      + myForm.$error.maxlength = {{!!myForm.$error.maxlength}}
      +
      +
      + + var user = element(by.exactBinding('user')); + var userNameValid = element(by.binding('myForm.userName.$valid')); + var lastNameValid = element(by.binding('myForm.lastName.$valid')); + var lastNameError = element(by.binding('myForm.lastName.$error')); + var formValid = element(by.binding('myForm.$valid')); + var userNameInput = element(by.model('user.name')); + var userLastInput = element(by.model('user.last')); + + it('should initialize to model', function() { + expect(user.getText()).toContain('{"name":"guest","last":"visitor"}'); + expect(userNameValid.getText()).toContain('true'); + expect(formValid.getText()).toContain('true'); + }); + + it('should be invalid if empty when required', function() { + userNameInput.clear(); + userNameInput.sendKeys(''); + + expect(user.getText()).toContain('{"last":"visitor"}'); + expect(userNameValid.getText()).toContain('false'); + expect(formValid.getText()).toContain('false'); + }); + + it('should be valid if empty when min length is set', function() { + userLastInput.clear(); + userLastInput.sendKeys(''); + + expect(user.getText()).toContain('{"name":"guest","last":""}'); + expect(lastNameValid.getText()).toContain('true'); + expect(formValid.getText()).toContain('true'); + }); + + it('should be invalid if less than required min length', function() { + userLastInput.clear(); + userLastInput.sendKeys('xx'); + + expect(user.getText()).toContain('{"name":"guest"}'); + expect(lastNameValid.getText()).toContain('false'); + expect(lastNameError.getText()).toContain('minlength'); + expect(formValid.getText()).toContain('false'); + }); + + it('should be invalid if longer than max length', function() { + userLastInput.clear(); + userLastInput.sendKeys('some ridiculously long name'); + + expect(user.getText()).toContain('{"name":"guest"}'); + expect(lastNameValid.getText()).toContain('false'); + expect(lastNameError.getText()).toContain('maxlength'); + expect(formValid.getText()).toContain('false'); + }); + +
      + */ +var inputDirective = ['$browser', '$sniffer', '$filter', '$parse', + function($browser, $sniffer, $filter, $parse) { + return { + restrict: 'E', + require: ['?ngModel'], + link: { + pre: function(scope, element, attr, ctrls) { + if (ctrls[0]) { + (inputType[lowercase(attr.type)] || inputType.text)(scope, element, attr, ctrls[0], $sniffer, + $browser, $filter, $parse); + } + } + } + }; +}]; + +var VALID_CLASS = 'ng-valid', + INVALID_CLASS = 'ng-invalid', + PRISTINE_CLASS = 'ng-pristine', + DIRTY_CLASS = 'ng-dirty', + UNTOUCHED_CLASS = 'ng-untouched', + TOUCHED_CLASS = 'ng-touched', + PENDING_CLASS = 'ng-pending'; + +/** + * @ngdoc type + * @name ngModel.NgModelController + * + * @property {string} $viewValue Actual string value in the view. + * @property {*} $modelValue The value in the model that the control is bound to. + * @property {Array.} $parsers Array of functions to execute, as a pipeline, whenever + the control reads value from the DOM. The functions are called in array order, each passing + its return value through to the next. The last return value is forwarded to the + {@link ngModel.NgModelController#$validators `$validators`} collection. + +Parsers are used to sanitize / convert the {@link ngModel.NgModelController#$viewValue +`$viewValue`}. + +Returning `undefined` from a parser means a parse error occurred. In that case, +no {@link ngModel.NgModelController#$validators `$validators`} will run and the `ngModel` +will be set to `undefined` unless {@link ngModelOptions `ngModelOptions.allowInvalid`} +is set to `true`. The parse error is stored in `ngModel.$error.parse`. + + * + * @property {Array.} $formatters Array of functions to execute, as a pipeline, whenever + the model value changes. The functions are called in reverse array order, each passing the value through to the + next. The last return value is used as the actual DOM value. + Used to format / convert values for display in the control. + * ```js + * function formatter(value) { + * if (value) { + * return value.toUpperCase(); + * } + * } + * ngModel.$formatters.push(formatter); + * ``` + * + * @property {Object.} $validators A collection of validators that are applied + * whenever the model value changes. The key value within the object refers to the name of the + * validator while the function refers to the validation operation. The validation operation is + * provided with the model value as an argument and must return a true or false value depending + * on the response of that validation. + * + * ```js + * ngModel.$validators.validCharacters = function(modelValue, viewValue) { + * var value = modelValue || viewValue; + * return /[0-9]+/.test(value) && + * /[a-z]+/.test(value) && + * /[A-Z]+/.test(value) && + * /\W+/.test(value); + * }; + * ``` + * + * @property {Object.} $asyncValidators A collection of validations that are expected to + * perform an asynchronous validation (e.g. a HTTP request). The validation function that is provided + * is expected to return a promise when it is run during the model validation process. Once the promise + * is delivered then the validation status will be set to true when fulfilled and false when rejected. + * When the asynchronous validators are triggered, each of the validators will run in parallel and the model + * value will only be updated once all validators have been fulfilled. As long as an asynchronous validator + * is unfulfilled, its key will be added to the controllers `$pending` property. Also, all asynchronous validators + * will only run once all synchronous validators have passed. + * + * Please note that if $http is used then it is important that the server returns a success HTTP response code + * in order to fulfill the validation and a status level of `4xx` in order to reject the validation. + * + * ```js + * ngModel.$asyncValidators.uniqueUsername = function(modelValue, viewValue) { + * var value = modelValue || viewValue; + * + * // Lookup user by username + * return $http.get('/api/users/' + value). + * then(function resolved() { + * //username exists, this means validation fails + * return $q.reject('exists'); + * }, function rejected() { + * //username does not exist, therefore this validation passes + * return true; + * }); + * }; + * ``` + * + * @property {Array.} $viewChangeListeners Array of functions to execute whenever the + * view value has changed. It is called with no arguments, and its return value is ignored. + * This can be used in place of additional $watches against the model value. + * + * @property {Object} $error An object hash with all failing validator ids as keys. + * @property {Object} $pending An object hash with all pending validator ids as keys. + * + * @property {boolean} $untouched True if control has not lost focus yet. + * @property {boolean} $touched True if control has lost focus. + * @property {boolean} $pristine True if user has not interacted with the control yet. + * @property {boolean} $dirty True if user has already interacted with the control. + * @property {boolean} $valid True if there is no error. + * @property {boolean} $invalid True if at least one error on the control. + * @property {string} $name The name attribute of the control. + * + * @description + * + * `NgModelController` provides API for the {@link ngModel `ngModel`} directive. + * The controller contains services for data-binding, validation, CSS updates, and value formatting + * and parsing. It purposefully does not contain any logic which deals with DOM rendering or + * listening to DOM events. + * Such DOM related logic should be provided by other directives which make use of + * `NgModelController` for data-binding to control elements. + * Angular provides this DOM logic for most {@link input `input`} elements. + * At the end of this page you can find a {@link ngModel.NgModelController#custom-control-example + * custom control example} that uses `ngModelController` to bind to `contenteditable` elements. + * + * @example + * ### Custom Control Example + * This example shows how to use `NgModelController` with a custom control to achieve + * data-binding. Notice how different directives (`contenteditable`, `ng-model`, and `required`) + * collaborate together to achieve the desired result. + * + * Note that `contenteditable` is an HTML5 attribute, which tells the browser to let the element + * contents be edited in place by the user. This will not work on older browsers. + * + * We are using the {@link ng.service:$sce $sce} service here and include the {@link ngSanitize $sanitize} + * module to automatically remove "bad" content like inline event listener (e.g. ``). + * However, as we are using `$sce` the model can still decide to provide unsafe content if it marks + * that content using the `$sce` service. + * + * + + [contenteditable] { + border: 1px solid black; + background-color: white; + min-height: 20px; + } + + .ng-invalid { + border: 1px solid red; + } + + + + angular.module('customControl', ['ngSanitize']). + directive('contenteditable', ['$sce', function($sce) { + return { + restrict: 'A', // only activate on element attribute + require: '?ngModel', // get a hold of NgModelController + link: function(scope, element, attrs, ngModel) { + if (!ngModel) return; // do nothing if no ng-model + + // Specify how UI should be updated + ngModel.$render = function() { + element.html($sce.getTrustedHtml(ngModel.$viewValue || '')); + }; + + // Listen for change events to enable binding + element.on('blur keyup change', function() { + scope.$evalAsync(read); + }); + read(); // initialize + + // Write data to the model + function read() { + var html = element.html(); + // When we clear the content editable the browser leaves a
      behind + // If strip-br attribute is provided then we strip this out + if ( attrs.stripBr && html == '
      ' ) { + html = ''; + } + ngModel.$setViewValue(html); + } + } + }; + }]); +
      + +
      +
      Change me!
      + Required! +
      + +
      +
      + + it('should data-bind and become invalid', function() { + if (browser.params.browser == 'safari' || browser.params.browser == 'firefox') { + // SafariDriver can't handle contenteditable + // and Firefox driver can't clear contenteditables very well + return; + } + var contentEditable = element(by.css('[contenteditable]')); + var content = 'Change me!'; + + expect(contentEditable.getText()).toEqual(content); + + contentEditable.clear(); + contentEditable.sendKeys(protractor.Key.BACK_SPACE); + expect(contentEditable.getText()).toEqual(''); + expect(contentEditable.getAttribute('class')).toMatch(/ng-invalid-required/); + }); + + *
      + * + * + */ +var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$parse', '$animate', '$timeout', '$rootScope', '$q', '$interpolate', + function($scope, $exceptionHandler, $attr, $element, $parse, $animate, $timeout, $rootScope, $q, $interpolate) { + this.$viewValue = Number.NaN; + this.$modelValue = Number.NaN; + this.$$rawModelValue = undefined; // stores the parsed modelValue / model set from scope regardless of validity. + this.$validators = {}; + this.$asyncValidators = {}; + this.$parsers = []; + this.$formatters = []; + this.$viewChangeListeners = []; + this.$untouched = true; + this.$touched = false; + this.$pristine = true; + this.$dirty = false; + this.$valid = true; + this.$invalid = false; + this.$error = {}; // keep invalid keys here + this.$$success = {}; // keep valid keys here + this.$pending = undefined; // keep pending keys here + this.$name = $interpolate($attr.name || '', false)($scope); + + + var parsedNgModel = $parse($attr.ngModel), + parsedNgModelAssign = parsedNgModel.assign, + ngModelGet = parsedNgModel, + ngModelSet = parsedNgModelAssign, + pendingDebounce = null, + ctrl = this; + + this.$$setOptions = function(options) { + ctrl.$options = options; + if (options && options.getterSetter) { + var invokeModelGetter = $parse($attr.ngModel + '()'), + invokeModelSetter = $parse($attr.ngModel + '($$$p)'); + + ngModelGet = function($scope) { + var modelValue = parsedNgModel($scope); + if (isFunction(modelValue)) { + modelValue = invokeModelGetter($scope); + } + return modelValue; + }; + ngModelSet = function($scope, newValue) { + if (isFunction(parsedNgModel($scope))) { + invokeModelSetter($scope, {$$$p: ctrl.$modelValue}); + } else { + parsedNgModelAssign($scope, ctrl.$modelValue); + } + }; + } else if (!parsedNgModel.assign) { + throw $ngModelMinErr('nonassign', "Expression '{0}' is non-assignable. Element: {1}", + $attr.ngModel, startingTag($element)); + } + }; + + /** + * @ngdoc method + * @name ngModel.NgModelController#$render + * + * @description + * Called when the view needs to be updated. It is expected that the user of the ng-model + * directive will implement this method. + * + * The `$render()` method is invoked in the following situations: + * + * * `$rollbackViewValue()` is called. If we are rolling back the view value to the last + * committed value then `$render()` is called to update the input control. + * * The value referenced by `ng-model` is changed programmatically and both the `$modelValue` and + * the `$viewValue` are different to last time. + * + * Since `ng-model` does not do a deep watch, `$render()` is only invoked if the values of + * `$modelValue` and `$viewValue` are actually different to their previous value. If `$modelValue` + * or `$viewValue` are objects (rather than a string or number) then `$render()` will not be + * invoked if you only change a property on the objects. + */ + this.$render = noop; + + /** + * @ngdoc method + * @name ngModel.NgModelController#$isEmpty + * + * @description + * This is called when we need to determine if the value of an input is empty. + * + * For instance, the required directive does this to work out if the input has data or not. + * + * The default `$isEmpty` function checks whether the value is `undefined`, `''`, `null` or `NaN`. + * + * You can override this for input directives whose concept of being empty is different to the + * default. The `checkboxInputType` directive does this because in its case a value of `false` + * implies empty. + * + * @param {*} value The value of the input to check for emptiness. + * @returns {boolean} True if `value` is "empty". + */ + this.$isEmpty = function(value) { + return isUndefined(value) || value === '' || value === null || value !== value; + }; + + var parentForm = $element.inheritedData('$formController') || nullFormCtrl, + currentValidationRunId = 0; + + /** + * @ngdoc method + * @name ngModel.NgModelController#$setValidity + * + * @description + * Change the validity state, and notify the form. + * + * This method can be called within $parsers/$formatters or a custom validation implementation. + * However, in most cases it should be sufficient to use the `ngModel.$validators` and + * `ngModel.$asyncValidators` collections which will call `$setValidity` automatically. + * + * @param {string} validationErrorKey Name of the validator. The `validationErrorKey` will be assigned + * to either `$error[validationErrorKey]` or `$pending[validationErrorKey]` + * (for unfulfilled `$asyncValidators`), so that it is available for data-binding. + * The `validationErrorKey` should be in camelCase and will get converted into dash-case + * for class name. Example: `myError` will result in `ng-valid-my-error` and `ng-invalid-my-error` + * class and can be bound to as `{{someForm.someControl.$error.myError}}` . + * @param {boolean} isValid Whether the current state is valid (true), invalid (false), pending (undefined), + * or skipped (null). Pending is used for unfulfilled `$asyncValidators`. + * Skipped is used by Angular when validators do not run because of parse errors and + * when `$asyncValidators` do not run because any of the `$validators` failed. + */ + addSetValidityMethod({ + ctrl: this, + $element: $element, + set: function(object, property) { + object[property] = true; + }, + unset: function(object, property) { + delete object[property]; + }, + parentForm: parentForm, + $animate: $animate + }); + + /** + * @ngdoc method + * @name ngModel.NgModelController#$setPristine + * + * @description + * Sets the control to its pristine state. + * + * This method can be called to remove the `ng-dirty` class and set the control to its pristine + * state (`ng-pristine` class). A model is considered to be pristine when the control + * has not been changed from when first compiled. + */ + this.$setPristine = function() { + ctrl.$dirty = false; + ctrl.$pristine = true; + $animate.removeClass($element, DIRTY_CLASS); + $animate.addClass($element, PRISTINE_CLASS); + }; + + /** + * @ngdoc method + * @name ngModel.NgModelController#$setDirty + * + * @description + * Sets the control to its dirty state. + * + * This method can be called to remove the `ng-pristine` class and set the control to its dirty + * state (`ng-dirty` class). A model is considered to be dirty when the control has been changed + * from when first compiled. + */ + this.$setDirty = function() { + ctrl.$dirty = true; + ctrl.$pristine = false; + $animate.removeClass($element, PRISTINE_CLASS); + $animate.addClass($element, DIRTY_CLASS); + parentForm.$setDirty(); + }; + + /** + * @ngdoc method + * @name ngModel.NgModelController#$setUntouched + * + * @description + * Sets the control to its untouched state. + * + * This method can be called to remove the `ng-touched` class and set the control to its + * untouched state (`ng-untouched` class). Upon compilation, a model is set as untouched + * by default, however this function can be used to restore that state if the model has + * already been touched by the user. + */ + this.$setUntouched = function() { + ctrl.$touched = false; + ctrl.$untouched = true; + $animate.setClass($element, UNTOUCHED_CLASS, TOUCHED_CLASS); + }; + + /** + * @ngdoc method + * @name ngModel.NgModelController#$setTouched + * + * @description + * Sets the control to its touched state. + * + * This method can be called to remove the `ng-untouched` class and set the control to its + * touched state (`ng-touched` class). A model is considered to be touched when the user has + * first focused the control element and then shifted focus away from the control (blur event). + */ + this.$setTouched = function() { + ctrl.$touched = true; + ctrl.$untouched = false; + $animate.setClass($element, TOUCHED_CLASS, UNTOUCHED_CLASS); + }; + + /** + * @ngdoc method + * @name ngModel.NgModelController#$rollbackViewValue + * + * @description + * Cancel an update and reset the input element's value to prevent an update to the `$modelValue`, + * which may be caused by a pending debounced event or because the input is waiting for a some + * future event. + * + * If you have an input that uses `ng-model-options` to set up debounced events or events such + * as blur you can have a situation where there is a period when the `$viewValue` + * is out of synch with the ngModel's `$modelValue`. + * + * In this case, you can run into difficulties if you try to update the ngModel's `$modelValue` + * programmatically before these debounced/future events have resolved/occurred, because Angular's + * dirty checking mechanism is not able to tell whether the model has actually changed or not. + * + * The `$rollbackViewValue()` method should be called before programmatically changing the model of an + * input which may have such events pending. This is important in order to make sure that the + * input field will be updated with the new model value and any pending operations are cancelled. + * + * + * + * angular.module('cancel-update-example', []) + * + * .controller('CancelUpdateController', ['$scope', function($scope) { + * $scope.resetWithCancel = function(e) { + * if (e.keyCode == 27) { + * $scope.myForm.myInput1.$rollbackViewValue(); + * $scope.myValue = ''; + * } + * }; + * $scope.resetWithoutCancel = function(e) { + * if (e.keyCode == 27) { + * $scope.myValue = ''; + * } + * }; + * }]); + * + * + *
      + *

      Try typing something in each input. See that the model only updates when you + * blur off the input. + *

      + *

      Now see what happens if you start typing then press the Escape key

      + * + *
      + *

      With $rollbackViewValue()

      + *
      + * myValue: "{{ myValue }}" + * + *

      Without $rollbackViewValue()

      + *
      + * myValue: "{{ myValue }}" + *
      + *
      + *
      + *
      + */ + this.$rollbackViewValue = function() { + $timeout.cancel(pendingDebounce); + ctrl.$viewValue = ctrl.$$lastCommittedViewValue; + ctrl.$render(); + }; + + /** + * @ngdoc method + * @name ngModel.NgModelController#$validate + * + * @description + * Runs each of the registered validators (first synchronous validators and then + * asynchronous validators). + * If the validity changes to invalid, the model will be set to `undefined`, + * unless {@link ngModelOptions `ngModelOptions.allowInvalid`} is `true`. + * If the validity changes to valid, it will set the model to the last available valid + * modelValue, i.e. either the last parsed value or the last value set from the scope. + */ + this.$validate = function() { + // ignore $validate before model is initialized + if (isNumber(ctrl.$modelValue) && isNaN(ctrl.$modelValue)) { + return; + } + + var viewValue = ctrl.$$lastCommittedViewValue; + // Note: we use the $$rawModelValue as $modelValue might have been + // set to undefined during a view -> model update that found validation + // errors. We can't parse the view here, since that could change + // the model although neither viewValue nor the model on the scope changed + var modelValue = ctrl.$$rawModelValue; + + // Check if the there's a parse error, so we don't unset it accidentially + var parserName = ctrl.$$parserName || 'parse'; + var parserValid = ctrl.$error[parserName] ? false : undefined; + + var prevValid = ctrl.$valid; + var prevModelValue = ctrl.$modelValue; + + var allowInvalid = ctrl.$options && ctrl.$options.allowInvalid; + + ctrl.$$runValidators(parserValid, modelValue, viewValue, function(allValid) { + // If there was no change in validity, don't update the model + // This prevents changing an invalid modelValue to undefined + if (!allowInvalid && prevValid !== allValid) { + // Note: Don't check ctrl.$valid here, as we could have + // external validators (e.g. calculated on the server), + // that just call $setValidity and need the model value + // to calculate their validity. + ctrl.$modelValue = allValid ? modelValue : undefined; + + if (ctrl.$modelValue !== prevModelValue) { + ctrl.$$writeModelToScope(); + } + } + }); + + }; + + this.$$runValidators = function(parseValid, modelValue, viewValue, doneCallback) { + currentValidationRunId++; + var localValidationRunId = currentValidationRunId; + + // check parser error + if (!processParseErrors(parseValid)) { + validationDone(false); + return; + } + if (!processSyncValidators()) { + validationDone(false); + return; + } + processAsyncValidators(); + + function processParseErrors(parseValid) { + var errorKey = ctrl.$$parserName || 'parse'; + if (parseValid === undefined) { + setValidity(errorKey, null); + } else { + setValidity(errorKey, parseValid); + if (!parseValid) { + forEach(ctrl.$validators, function(v, name) { + setValidity(name, null); + }); + forEach(ctrl.$asyncValidators, function(v, name) { + setValidity(name, null); + }); + return false; + } + } + return true; + } + + function processSyncValidators() { + var syncValidatorsValid = true; + forEach(ctrl.$validators, function(validator, name) { + var result = validator(modelValue, viewValue); + syncValidatorsValid = syncValidatorsValid && result; + setValidity(name, result); + }); + if (!syncValidatorsValid) { + forEach(ctrl.$asyncValidators, function(v, name) { + setValidity(name, null); + }); + return false; + } + return true; + } + + function processAsyncValidators() { + var validatorPromises = []; + var allValid = true; + forEach(ctrl.$asyncValidators, function(validator, name) { + var promise = validator(modelValue, viewValue); + if (!isPromiseLike(promise)) { + throw $ngModelMinErr("$asyncValidators", + "Expected asynchronous validator to return a promise but got '{0}' instead.", promise); + } + setValidity(name, undefined); + validatorPromises.push(promise.then(function() { + setValidity(name, true); + }, function(error) { + allValid = false; + setValidity(name, false); + })); + }); + if (!validatorPromises.length) { + validationDone(true); + } else { + $q.all(validatorPromises).then(function() { + validationDone(allValid); + }, noop); + } + } + + function setValidity(name, isValid) { + if (localValidationRunId === currentValidationRunId) { + ctrl.$setValidity(name, isValid); + } + } + + function validationDone(allValid) { + if (localValidationRunId === currentValidationRunId) { + + doneCallback(allValid); + } + } + }; + + /** + * @ngdoc method + * @name ngModel.NgModelController#$commitViewValue + * + * @description + * Commit a pending update to the `$modelValue`. + * + * Updates may be pending by a debounced event or because the input is waiting for a some future + * event defined in `ng-model-options`. this method is rarely needed as `NgModelController` + * usually handles calling this in response to input events. + */ + this.$commitViewValue = function() { + var viewValue = ctrl.$viewValue; + + $timeout.cancel(pendingDebounce); + + // If the view value has not changed then we should just exit, except in the case where there is + // a native validator on the element. In this case the validation state may have changed even though + // the viewValue has stayed empty. + if (ctrl.$$lastCommittedViewValue === viewValue && (viewValue !== '' || !ctrl.$$hasNativeValidators)) { + return; + } + ctrl.$$lastCommittedViewValue = viewValue; + + // change to dirty + if (ctrl.$pristine) { + this.$setDirty(); + } + this.$$parseAndValidate(); + }; + + this.$$parseAndValidate = function() { + var viewValue = ctrl.$$lastCommittedViewValue; + var modelValue = viewValue; + var parserValid = isUndefined(modelValue) ? undefined : true; + + if (parserValid) { + for (var i = 0; i < ctrl.$parsers.length; i++) { + modelValue = ctrl.$parsers[i](modelValue); + if (isUndefined(modelValue)) { + parserValid = false; + break; + } + } + } + if (isNumber(ctrl.$modelValue) && isNaN(ctrl.$modelValue)) { + // ctrl.$modelValue has not been touched yet... + ctrl.$modelValue = ngModelGet($scope); + } + var prevModelValue = ctrl.$modelValue; + var allowInvalid = ctrl.$options && ctrl.$options.allowInvalid; + ctrl.$$rawModelValue = modelValue; + + if (allowInvalid) { + ctrl.$modelValue = modelValue; + writeToModelIfNeeded(); + } + + // Pass the $$lastCommittedViewValue here, because the cached viewValue might be out of date. + // This can happen if e.g. $setViewValue is called from inside a parser + ctrl.$$runValidators(parserValid, modelValue, ctrl.$$lastCommittedViewValue, function(allValid) { + if (!allowInvalid) { + // Note: Don't check ctrl.$valid here, as we could have + // external validators (e.g. calculated on the server), + // that just call $setValidity and need the model value + // to calculate their validity. + ctrl.$modelValue = allValid ? modelValue : undefined; + writeToModelIfNeeded(); + } + }); + + function writeToModelIfNeeded() { + if (ctrl.$modelValue !== prevModelValue) { + ctrl.$$writeModelToScope(); + } + } + }; + + this.$$writeModelToScope = function() { + ngModelSet($scope, ctrl.$modelValue); + forEach(ctrl.$viewChangeListeners, function(listener) { + try { + listener(); + } catch (e) { + $exceptionHandler(e); + } + }); + }; + + /** + * @ngdoc method + * @name ngModel.NgModelController#$setViewValue + * + * @description + * Update the view value. + * + * This method should be called when an input directive want to change the view value; typically, + * this is done from within a DOM event handler. + * + * For example {@link ng.directive:input input} calls it when the value of the input changes and + * {@link ng.directive:select select} calls it when an option is selected. + * + * If the new `value` is an object (rather than a string or a number), we should make a copy of the + * object before passing it to `$setViewValue`. This is because `ngModel` does not perform a deep + * watch of objects, it only looks for a change of identity. If you only change the property of + * the object then ngModel will not realise that the object has changed and will not invoke the + * `$parsers` and `$validators` pipelines. + * + * For this reason, you should not change properties of the copy once it has been passed to + * `$setViewValue`. Otherwise you may cause the model value on the scope to change incorrectly. + * + * When this method is called, the new `value` will be staged for committing through the `$parsers` + * and `$validators` pipelines. If there are no special {@link ngModelOptions} specified then the staged + * value sent directly for processing, finally to be applied to `$modelValue` and then the + * **expression** specified in the `ng-model` attribute. + * + * Lastly, all the registered change listeners, in the `$viewChangeListeners` list, are called. + * + * In case the {@link ng.directive:ngModelOptions ngModelOptions} directive is used with `updateOn` + * and the `default` trigger is not listed, all those actions will remain pending until one of the + * `updateOn` events is triggered on the DOM element. + * All these actions will be debounced if the {@link ng.directive:ngModelOptions ngModelOptions} + * directive is used with a custom debounce for this particular event. + * + * Note that calling this function does not trigger a `$digest`. + * + * @param {string} value Value from the view. + * @param {string} trigger Event that triggered the update. + */ + this.$setViewValue = function(value, trigger) { + ctrl.$viewValue = value; + if (!ctrl.$options || ctrl.$options.updateOnDefault) { + ctrl.$$debounceViewValueCommit(trigger); + } + }; + + this.$$debounceViewValueCommit = function(trigger) { + var debounceDelay = 0, + options = ctrl.$options, + debounce; + + if (options && isDefined(options.debounce)) { + debounce = options.debounce; + if (isNumber(debounce)) { + debounceDelay = debounce; + } else if (isNumber(debounce[trigger])) { + debounceDelay = debounce[trigger]; + } else if (isNumber(debounce['default'])) { + debounceDelay = debounce['default']; + } + } + + $timeout.cancel(pendingDebounce); + if (debounceDelay) { + pendingDebounce = $timeout(function() { + ctrl.$commitViewValue(); + }, debounceDelay); + } else if ($rootScope.$$phase) { + ctrl.$commitViewValue(); + } else { + $scope.$apply(function() { + ctrl.$commitViewValue(); + }); + } + }; + + // model -> value + // Note: we cannot use a normal scope.$watch as we want to detect the following: + // 1. scope value is 'a' + // 2. user enters 'b' + // 3. ng-change kicks in and reverts scope value to 'a' + // -> scope value did not change since the last digest as + // ng-change executes in apply phase + // 4. view should be changed back to 'a' + $scope.$watch(function ngModelWatch() { + var modelValue = ngModelGet($scope); + + // if scope model value and ngModel value are out of sync + // TODO(perf): why not move this to the action fn? + if (modelValue !== ctrl.$modelValue) { + ctrl.$modelValue = ctrl.$$rawModelValue = modelValue; + + var formatters = ctrl.$formatters, + idx = formatters.length; + + var viewValue = modelValue; + while (idx--) { + viewValue = formatters[idx](viewValue); + } + if (ctrl.$viewValue !== viewValue) { + ctrl.$viewValue = ctrl.$$lastCommittedViewValue = viewValue; + ctrl.$render(); + + ctrl.$$runValidators(undefined, modelValue, viewValue, noop); + } + } + + return modelValue; + }); +}]; + + +/** + * @ngdoc directive + * @name ngModel + * + * @element input + * @priority 1 + * + * @description + * The `ngModel` directive binds an `input`,`select`, `textarea` (or custom form control) to a + * property on the scope using {@link ngModel.NgModelController NgModelController}, + * which is created and exposed by this directive. + * + * `ngModel` is responsible for: + * + * - Binding the view into the model, which other directives such as `input`, `textarea` or `select` + * require. + * - Providing validation behavior (i.e. required, number, email, url). + * - Keeping the state of the control (valid/invalid, dirty/pristine, touched/untouched, validation errors). + * - Setting related css classes on the element (`ng-valid`, `ng-invalid`, `ng-dirty`, `ng-pristine`, `ng-touched`, `ng-untouched`) including animations. + * - Registering the control with its parent {@link ng.directive:form form}. + * + * Note: `ngModel` will try to bind to the property given by evaluating the expression on the + * current scope. If the property doesn't already exist on this scope, it will be created + * implicitly and added to the scope. + * + * For best practices on using `ngModel`, see: + * + * - [Understanding Scopes](https://github.com/angular/angular.js/wiki/Understanding-Scopes) + * + * For basic examples, how to use `ngModel`, see: + * + * - {@link ng.directive:input input} + * - {@link input[text] text} + * - {@link input[checkbox] checkbox} + * - {@link input[radio] radio} + * - {@link input[number] number} + * - {@link input[email] email} + * - {@link input[url] url} + * - {@link input[date] date} + * - {@link input[datetime-local] datetime-local} + * - {@link input[time] time} + * - {@link input[month] month} + * - {@link input[week] week} + * - {@link ng.directive:select select} + * - {@link ng.directive:textarea textarea} + * + * # CSS classes + * The following CSS classes are added and removed on the associated input/select/textarea element + * depending on the validity of the model. + * + * - `ng-valid`: the model is valid + * - `ng-invalid`: the model is invalid + * - `ng-valid-[key]`: for each valid key added by `$setValidity` + * - `ng-invalid-[key]`: for each invalid key added by `$setValidity` + * - `ng-pristine`: the control hasn't been interacted with yet + * - `ng-dirty`: the control has been interacted with + * - `ng-touched`: the control has been blurred + * - `ng-untouched`: the control hasn't been blurred + * - `ng-pending`: any `$asyncValidators` are unfulfilled + * + * Keep in mind that ngAnimate can detect each of these classes when added and removed. + * + * ## Animation Hooks + * + * Animations within models are triggered when any of the associated CSS classes are added and removed + * on the input element which is attached to the model. These classes are: `.ng-pristine`, `.ng-dirty`, + * `.ng-invalid` and `.ng-valid` as well as any other validations that are performed on the model itself. + * The animations that are triggered within ngModel are similar to how they work in ngClass and + * animations can be hooked into using CSS transitions, keyframes as well as JS animations. + * + * The following example shows a simple way to utilize CSS transitions to style an input element + * that has been rendered as invalid after it has been validated: + * + *
      + * //be sure to include ngAnimate as a module to hook into more
      + * //advanced animations
      + * .my-input {
      + *   transition:0.5s linear all;
      + *   background: white;
      + * }
      + * .my-input.ng-invalid {
      + *   background: red;
      + *   color:white;
      + * }
      + * 
      + * + * @example + * + + + + Update input to see transitions when valid/invalid. + Integer is a valid value. +
      + +
      +
      + *
      + * + * ## Binding to a getter/setter + * + * Sometimes it's helpful to bind `ngModel` to a getter/setter function. A getter/setter is a + * function that returns a representation of the model when called with zero arguments, and sets + * the internal state of a model when called with an argument. It's sometimes useful to use this + * for models that have an internal representation that's different than what the model exposes + * to the view. + * + *
      + * **Best Practice:** It's best to keep getters fast because Angular is likely to call them more + * frequently than other parts of your code. + *
      + * + * You use this behavior by adding `ng-model-options="{ getterSetter: true }"` to an element that + * has `ng-model` attached to it. You can also add `ng-model-options="{ getterSetter: true }"` to + * a `
      `, which will enable this behavior for all ``s within it. See + * {@link ng.directive:ngModelOptions `ngModelOptions`} for more. + * + * The following example shows how to use `ngModel` with a getter/setter: + * + * @example + * + +
      + + Name: + + +
      user.name = 
      +
      +
      + + angular.module('getterSetterExample', []) + .controller('ExampleController', ['$scope', function($scope) { + var _name = 'Brian'; + $scope.user = { + name: function(newName) { + if (angular.isDefined(newName)) { + _name = newName; + } + return _name; + } + }; + }]); + + *
      + */ +var ngModelDirective = ['$rootScope', function($rootScope) { + return { + restrict: 'A', + require: ['ngModel', '^?form', '^?ngModelOptions'], + controller: NgModelController, + // Prelink needs to run before any input directive + // so that we can set the NgModelOptions in NgModelController + // before anyone else uses it. + priority: 1, + compile: function ngModelCompile(element) { + // Setup initial state of the control + element.addClass(PRISTINE_CLASS).addClass(UNTOUCHED_CLASS).addClass(VALID_CLASS); + + return { + pre: function ngModelPreLink(scope, element, attr, ctrls) { + var modelCtrl = ctrls[0], + formCtrl = ctrls[1] || nullFormCtrl; + + modelCtrl.$$setOptions(ctrls[2] && ctrls[2].$options); + + // notify others, especially parent forms + formCtrl.$addControl(modelCtrl); + + attr.$observe('name', function(newValue) { + if (modelCtrl.$name !== newValue) { + formCtrl.$$renameControl(modelCtrl, newValue); + } + }); + + scope.$on('$destroy', function() { + formCtrl.$removeControl(modelCtrl); + }); + }, + post: function ngModelPostLink(scope, element, attr, ctrls) { + var modelCtrl = ctrls[0]; + if (modelCtrl.$options && modelCtrl.$options.updateOn) { + element.on(modelCtrl.$options.updateOn, function(ev) { + modelCtrl.$$debounceViewValueCommit(ev && ev.type); + }); + } + + element.on('blur', function(ev) { + if (modelCtrl.$touched) return; + + if ($rootScope.$$phase) { + scope.$evalAsync(modelCtrl.$setTouched); + } else { + scope.$apply(modelCtrl.$setTouched); + } + }); + } + }; + } + }; +}]; + + +/** + * @ngdoc directive + * @name ngChange + * + * @description + * Evaluate the given expression when the user changes the input. + * The expression is evaluated immediately, unlike the JavaScript onchange event + * which only triggers at the end of a change (usually, when the user leaves the + * form element or presses the return key). + * + * The `ngChange` expression is only evaluated when a change in the input value causes + * a new value to be committed to the model. + * + * It will not be evaluated: + * * if the value returned from the `$parsers` transformation pipeline has not changed + * * if the input has continued to be invalid since the model will stay `null` + * * if the model is changed programmatically and not by a change to the input value + * + * + * Note, this directive requires `ngModel` to be present. + * + * @element input + * @param {expression} ngChange {@link guide/expression Expression} to evaluate upon change + * in input value. + * + * @example + * + * + * + *
      + * + * + *
      + * debug = {{confirmed}}
      + * counter = {{counter}}
      + *
      + *
      + * + * var counter = element(by.binding('counter')); + * var debug = element(by.binding('confirmed')); + * + * it('should evaluate the expression if changing from view', function() { + * expect(counter.getText()).toContain('0'); + * + * element(by.id('ng-change-example1')).click(); + * + * expect(counter.getText()).toContain('1'); + * expect(debug.getText()).toContain('true'); + * }); + * + * it('should not evaluate the expression if changing from model', function() { + * element(by.id('ng-change-example2')).click(); + + * expect(counter.getText()).toContain('0'); + * expect(debug.getText()).toContain('true'); + * }); + * + *
      + */ +var ngChangeDirective = valueFn({ + restrict: 'A', + require: 'ngModel', + link: function(scope, element, attr, ctrl) { + ctrl.$viewChangeListeners.push(function() { + scope.$eval(attr.ngChange); + }); + } +}); + + +var requiredDirective = function() { + return { + restrict: 'A', + require: '?ngModel', + link: function(scope, elm, attr, ctrl) { + if (!ctrl) return; + attr.required = true; // force truthy in case we are on non input element + + ctrl.$validators.required = function(modelValue, viewValue) { + return !attr.required || !ctrl.$isEmpty(viewValue); + }; + + attr.$observe('required', function() { + ctrl.$validate(); + }); + } + }; +}; + + +var patternDirective = function() { + return { + restrict: 'A', + require: '?ngModel', + link: function(scope, elm, attr, ctrl) { + if (!ctrl) return; + + var regexp, patternExp = attr.ngPattern || attr.pattern; + attr.$observe('pattern', function(regex) { + if (isString(regex) && regex.length > 0) { + regex = new RegExp('^' + regex + '$'); + } + + if (regex && !regex.test) { + throw minErr('ngPattern')('noregexp', + 'Expected {0} to be a RegExp but was {1}. Element: {2}', patternExp, + regex, startingTag(elm)); + } + + regexp = regex || undefined; + ctrl.$validate(); + }); + + ctrl.$validators.pattern = function(value) { + return ctrl.$isEmpty(value) || isUndefined(regexp) || regexp.test(value); + }; + } + }; +}; + + +var maxlengthDirective = function() { + return { + restrict: 'A', + require: '?ngModel', + link: function(scope, elm, attr, ctrl) { + if (!ctrl) return; + + var maxlength = -1; + attr.$observe('maxlength', function(value) { + var intVal = int(value); + maxlength = isNaN(intVal) ? -1 : intVal; + ctrl.$validate(); + }); + ctrl.$validators.maxlength = function(modelValue, viewValue) { + return (maxlength < 0) || ctrl.$isEmpty(modelValue) || (viewValue.length <= maxlength); + }; + } + }; +}; + +var minlengthDirective = function() { + return { + restrict: 'A', + require: '?ngModel', + link: function(scope, elm, attr, ctrl) { + if (!ctrl) return; + + var minlength = 0; + attr.$observe('minlength', function(value) { + minlength = int(value) || 0; + ctrl.$validate(); + }); + ctrl.$validators.minlength = function(modelValue, viewValue) { + return ctrl.$isEmpty(viewValue) || viewValue.length >= minlength; + }; + } + }; +}; + + +/** + * @ngdoc directive + * @name ngList + * + * @description + * Text input that converts between a delimited string and an array of strings. The default + * delimiter is a comma followed by a space - equivalent to `ng-list=", "`. You can specify a custom + * delimiter as the value of the `ngList` attribute - for example, `ng-list=" | "`. + * + * The behaviour of the directive is affected by the use of the `ngTrim` attribute. + * * If `ngTrim` is set to `"false"` then whitespace around both the separator and each + * list item is respected. This implies that the user of the directive is responsible for + * dealing with whitespace but also allows you to use whitespace as a delimiter, such as a + * tab or newline character. + * * Otherwise whitespace around the delimiter is ignored when splitting (although it is respected + * when joining the list items back together) and whitespace around each list item is stripped + * before it is added to the model. + * + * ### Example with Validation + * + * + * + * angular.module('listExample', []) + * .controller('ExampleController', ['$scope', function($scope) { + * $scope.names = ['morpheus', 'neo', 'trinity']; + * }]); + * + * + *
      + * List: + * + * Required! + *
      + * names = {{names}}
      + * myForm.namesInput.$valid = {{myForm.namesInput.$valid}}
      + * myForm.namesInput.$error = {{myForm.namesInput.$error}}
      + * myForm.$valid = {{myForm.$valid}}
      + * myForm.$error.required = {{!!myForm.$error.required}}
      + *
      + *
      + * + * var listInput = element(by.model('names')); + * var names = element(by.exactBinding('names')); + * var valid = element(by.binding('myForm.namesInput.$valid')); + * var error = element(by.css('span.error')); + * + * it('should initialize to model', function() { + * expect(names.getText()).toContain('["morpheus","neo","trinity"]'); + * expect(valid.getText()).toContain('true'); + * expect(error.getCssValue('display')).toBe('none'); + * }); + * + * it('should be invalid if empty', function() { + * listInput.clear(); + * listInput.sendKeys(''); + * + * expect(names.getText()).toContain(''); + * expect(valid.getText()).toContain('false'); + * expect(error.getCssValue('display')).not.toBe('none'); + * }); + * + *
      + * + * ### Example - splitting on whitespace + * + * + * + *
      {{ list | json }}
      + *
      + * + * it("should split the text by newlines", function() { + * var listInput = element(by.model('list')); + * var output = element(by.binding('list | json')); + * listInput.sendKeys('abc\ndef\nghi'); + * expect(output.getText()).toContain('[\n "abc",\n "def",\n "ghi"\n]'); + * }); + * + *
      + * + * @element input + * @param {string=} ngList optional delimiter that should be used to split the value. + */ +var ngListDirective = function() { + return { + restrict: 'A', + priority: 100, + require: 'ngModel', + link: function(scope, element, attr, ctrl) { + // We want to control whitespace trimming so we use this convoluted approach + // to access the ngList attribute, which doesn't pre-trim the attribute + var ngList = element.attr(attr.$attr.ngList) || ', '; + var trimValues = attr.ngTrim !== 'false'; + var separator = trimValues ? trim(ngList) : ngList; + + var parse = function(viewValue) { + // If the viewValue is invalid (say required but empty) it will be `undefined` + if (isUndefined(viewValue)) return; + + var list = []; + + if (viewValue) { + forEach(viewValue.split(separator), function(value) { + if (value) list.push(trimValues ? trim(value) : value); + }); + } + + return list; + }; + + ctrl.$parsers.push(parse); + ctrl.$formatters.push(function(value) { + if (isArray(value)) { + return value.join(ngList); + } + + return undefined; + }); + + // Override the standard $isEmpty because an empty array means the input is empty. + ctrl.$isEmpty = function(value) { + return !value || !value.length; + }; + } + }; +}; + + +var CONSTANT_VALUE_REGEXP = /^(true|false|\d+)$/; +/** + * @ngdoc directive + * @name ngValue + * + * @description + * Binds the given expression to the value of `
      + + it('should load template defined inside script tag', function() { + element(by.css('#tpl-link')).click(); + expect(element(by.css('#tpl-content')).getText()).toMatch(/Content of the template/); + }); + + + */ +var scriptDirective = ['$templateCache', function($templateCache) { + return { + restrict: 'E', + terminal: true, + compile: function(element, attr) { + if (attr.type == 'text/ng-template') { + var templateUrl = attr.id, + text = element[0].text; + + $templateCache.put(templateUrl, text); + } + } + }; +}]; + +var ngOptionsMinErr = minErr('ngOptions'); +/** + * @ngdoc directive + * @name select + * @restrict E + * + * @description + * HTML `SELECT` element with angular data-binding. + * + * # `ngOptions` + * + * The `ngOptions` attribute can be used to dynamically generate a list of `