├── slides ├── scope.pdf └── binding.pdf ├── fonts ├── glyphicons-halflings-regular.eot ├── glyphicons-halflings-regular.ttf ├── glyphicons-halflings-regular.woff └── glyphicons-halflings-regular.svg ├── partials ├── binding │ ├── style.html │ ├── list.html │ ├── if.html │ ├── switch.html │ ├── watch.html │ ├── sort.html │ ├── wave.html │ ├── simple.html │ ├── region.html │ ├── array.html │ └── employee.html └── scope │ ├── alias.html │ ├── isolate.html │ ├── extend.html │ ├── newscope.html │ ├── assign.html │ ├── eventbus.html │ └── hierarchy.html ├── README.md ├── js ├── scope │ ├── alias.js │ ├── newscope.js │ ├── extend.js │ ├── root.js │ ├── isolate.js │ ├── hierarchy.js │ └── eventbus.js ├── binding │ ├── if.js │ ├── switch.js │ ├── list.js │ ├── simple.js │ ├── array.js │ ├── wave.js │ ├── region.js │ ├── watch.js │ ├── sort.js │ └── employee.js └── app.js ├── binding.html ├── scope.html ├── docs ├── 02.scope.md └── 01.binding.md └── css ├── bootstrap-theme.min.css ├── bootstrap-theme.css.map └── bootstrap-theme.css /slides/scope.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xufei/ng-tutor/HEAD/slides/scope.pdf -------------------------------------------------------------------------------- /slides/binding.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xufei/ng-tutor/HEAD/slides/binding.pdf -------------------------------------------------------------------------------- /fonts/glyphicons-halflings-regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xufei/ng-tutor/HEAD/fonts/glyphicons-halflings-regular.eot -------------------------------------------------------------------------------- /fonts/glyphicons-halflings-regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xufei/ng-tutor/HEAD/fonts/glyphicons-halflings-regular.ttf -------------------------------------------------------------------------------- /fonts/glyphicons-halflings-regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xufei/ng-tutor/HEAD/fonts/glyphicons-halflings-regular.woff -------------------------------------------------------------------------------- /partials/binding/style.html: -------------------------------------------------------------------------------- 1 | 2 |
3 | 测试字体大小 4 |
-------------------------------------------------------------------------------- /partials/scope/alias.html: -------------------------------------------------------------------------------- 1 |
2 |
{{instance.a}}
3 | 4 |
-------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | AngularJS实例教程 —— 跟徐叔叔一起学Angular 2 | ======== 3 | 4 | 现在AngularJS挺火了,但很多新手入门的时候却挺痛苦,很多时候他们没有时间完整看一本书,需要边学边用,很多时候他们学完了,却不知道在业务代码中应该怎样用。作为入门较久,踩坑较多的人,搞这么一个系列教程,希望能让大家快速成长。 5 | -------------------------------------------------------------------------------- /partials/scope/isolate.html: -------------------------------------------------------------------------------- 1 |
2 | 3 | 4 | 5 |
-------------------------------------------------------------------------------- /js/scope/alias.js: -------------------------------------------------------------------------------- 1 | angular.module("tutor") 2 | .controller("AliasCtrl", function() { 3 | this.a = 1; 4 | this.foo = function() { 5 | alert(this.a); 6 | }; 7 | }); -------------------------------------------------------------------------------- /js/binding/if.js: -------------------------------------------------------------------------------- 1 | angular.module("tutor").controller("IfCtrl", ["$scope", function ($scope) { 2 | $scope.condition = 1; 3 | 4 | $scope.change = function() { 5 | $scope.condition = 2; 6 | }; 7 | }]); -------------------------------------------------------------------------------- /js/scope/newscope.js: -------------------------------------------------------------------------------- 1 | angular.module("tutor") 2 | .controller("NewScopeCtrl", ["$scope", function($scope) { 3 | $scope.sum1 = 0; 4 | $scope.sum2 = 0; 5 | $scope.arr = [1, 2, 3]; 6 | }]); -------------------------------------------------------------------------------- /partials/binding/list.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /js/scope/extend.js: -------------------------------------------------------------------------------- 1 | angular.module("tutor").controller("OuterCtrl", ["$scope", function ($scope) { 2 | $scope.a = 1; 3 | 4 | $scope.data = { 5 | a: 1 6 | }; 7 | }]); 8 | 9 | angular.module("tutor").controller("InnerCtrl", ["$scope", function ($scope) { 10 | }]); -------------------------------------------------------------------------------- /js/scope/root.js: -------------------------------------------------------------------------------- 1 | angular.module("tutor").controller("RootCtrl", ["$scope", "$rootScope", function ($scope, $rootScope) { 2 | $scope.log = ""; 3 | 4 | $rootScope.$watch("rootA", function(newVal) { 5 | if (newVal) { 6 | $scope.log += newVal + "\n"; 7 | } 8 | }); 9 | }]); -------------------------------------------------------------------------------- /partials/binding/if.html: -------------------------------------------------------------------------------- 1 |
2 | 9 | 10 | 11 |
-------------------------------------------------------------------------------- /js/scope/isolate.js: -------------------------------------------------------------------------------- 1 | angular.module("tutor").controller("IsolateCtrl", ["$scope", function ($scope) { 2 | $scope.log = ""; 3 | 4 | var child = $scope.$new(); 5 | child.a = 1; 6 | 7 | child.$watch("a", function(newValue) { 8 | $scope.log += newValue + "\n"; 9 | }); 10 | 11 | $scope.change = function() { 12 | child.a++; 13 | }; 14 | }]); -------------------------------------------------------------------------------- /partials/binding/switch.html: -------------------------------------------------------------------------------- 1 |
2 |
3 |
A
4 |
B
5 |
default
6 |
7 | 8 | 9 | 10 |
-------------------------------------------------------------------------------- /js/binding/switch.js: -------------------------------------------------------------------------------- 1 | angular.module("tutor").controller("SwitchCtrl", ["$scope", function ($scope) { 2 | $scope.condition = ""; 3 | 4 | $scope.a = function() { 5 | $scope.condition = "A"; 6 | }; 7 | 8 | $scope.b = function() { 9 | $scope.condition = "B"; 10 | }; 11 | 12 | $scope.c = function() { 13 | $scope.condition = "C"; 14 | }; 15 | }]); -------------------------------------------------------------------------------- /js/binding/list.js: -------------------------------------------------------------------------------- 1 | angular.module("tutor").controller("ListCtrl", ["$scope", function($scope) { 2 | $scope.items = []; 3 | 4 | for (var i=0; i<10; i++) { 5 | $scope.items.push({ 6 | title:i 7 | }); 8 | } 9 | 10 | $scope.selectedItem = $scope.items[0]; 11 | 12 | $scope.select = function(item) { 13 | $scope.selectedItem = item; 14 | }; 15 | }]); -------------------------------------------------------------------------------- /partials/scope/extend.html: -------------------------------------------------------------------------------- 1 |
2 |
3 | outer a1:{{a}} 4 |
5 | inner a1:{{a}} 6 |
7 |
8 | 9 |
10 | outer a2:{{a}} 11 |
12 | 13 |
14 | inner a2:{{a}} 15 |
16 |
-------------------------------------------------------------------------------- /partials/binding/watch.html: -------------------------------------------------------------------------------- 1 |
2 | {{a}} 3 | 4 |
5 | 6 | 7 | 8 | 11 | 12 | 13 |
-------------------------------------------------------------------------------- /js/binding/simple.js: -------------------------------------------------------------------------------- 1 | angular.module("tutor").controller("SimpleCtrl", ["$scope", function ($scope) { 2 | $scope.tom = { 3 | name: "Tom", 4 | gender: 1 5 | }; 6 | 7 | $scope.formatGender = function(gender) { 8 | if (gender == 0) 9 | return "女"; 10 | 11 | if (gender == 1) 12 | return "男"; 13 | }; 14 | 15 | $scope.abs = function(number) { 16 | return Math.abs(number); 17 | }; 18 | }]); -------------------------------------------------------------------------------- /partials/binding/sort.html: -------------------------------------------------------------------------------- 1 |
2 | 10 | 11 |
12 |
13 |
14 |
-------------------------------------------------------------------------------- /partials/binding/wave.html: -------------------------------------------------------------------------------- 1 |
2 | 9 |
10 |
11 |
12 |
13 |
14 |
15 |
-------------------------------------------------------------------------------- /partials/binding/simple.html: -------------------------------------------------------------------------------- 1 |
2 | 3 |
{{a}}
4 |
5 |
6 | 7 | 8 | 9 | 10 |
11 | 12 | 13 | {{price + "(元)"}} 14 | 15 |
16 | 17 | 18 | {{price}}(元) 19 | 20 |
21 | 22 |
{{formatGender(tom.gender)}}
23 | 24 |
25 | 26 |
{{abs(-1)}}
27 |
-------------------------------------------------------------------------------- /partials/scope/newscope.html: -------------------------------------------------------------------------------- 1 |
2 |
outer: {{sum1}}
3 | 10 | 11 |
outer: {{sum2}}
12 | 19 |
-------------------------------------------------------------------------------- /js/binding/array.js: -------------------------------------------------------------------------------- 1 | angular.module("tutor").controller("ArrayCtrl", ["$scope", function ($scope) { 2 | $scope.arr1 = [1, 2, 3]; 3 | $scope.arr2 = [1, 1, 3]; 4 | 5 | $scope.arr3 = [ 6 | [11, 12, 13], 7 | [21, 22, 23], 8 | [31, 32, 33] 9 | ]; 10 | 11 | $scope.arr4 = [{ 12 | name: "Tom", 13 | age: 5 14 | }, { 15 | name: "Jerry", 16 | age: 2 17 | }]; 18 | 19 | $scope.obj = { 20 | a: 1, 21 | b: 1, 22 | c: 3 23 | }; 24 | 25 | $scope.add = function () { 26 | $scope.arr1.push($scope.arr1.length + 1); 27 | }; 28 | }]); -------------------------------------------------------------------------------- /partials/scope/assign.html: -------------------------------------------------------------------------------- 1 |
2 | outer a:{{a}} 3 |
4 | inner a:{{a}} 5 | 6 |
7 |
8 | 9 |
10 | outer data.a:{{data.a}} 11 |
12 | inner data.{{data.a}} 13 | 14 |
15 |
16 | 17 |
18 | outer a:{{a}} 19 |
20 | inner a:{{a}} 21 | 22 |
23 |
-------------------------------------------------------------------------------- /js/binding/wave.js: -------------------------------------------------------------------------------- 1 | angular.module("tutor").controller("WaveCtrl", ["$scope", "$timeout", function ($scope, $timeout) { 2 | $scope.staticItems = []; 3 | $scope.dynamicItems = []; 4 | 5 | for (var i = 0; i < 720; i++) { 6 | $scope.staticItems.push(Math.ceil(100 * (1 + Math.sin(i * Math.PI / 180)))); 7 | } 8 | 9 | var counter = 0; 10 | 11 | function addItem() { 12 | var newItem = Math.ceil(100 * (1 + Math.sin((counter++) * Math.PI / 180))); 13 | 14 | if ($scope.dynamicItems.length > 500) { 15 | $scope.dynamicItems.splice(0, 1); 16 | } 17 | 18 | $scope.dynamicItems.push(newItem); 19 | 20 | $timeout(function () { 21 | addItem(); 22 | }, 10); 23 | } 24 | 25 | addItem(); 26 | }]); -------------------------------------------------------------------------------- /js/binding/region.js: -------------------------------------------------------------------------------- 1 | angular.module("tutor").controller("RegionCtrl", ["$scope", function($scope) { 2 | $scope.provinceArr = ["江苏", "云南"]; 3 | $scope.cityArr = []; 4 | 5 | $scope.$watch("selectedProvince", function(province) { 6 | // 真正有用的代码在这里,实际场景中这里可以是调用后端服务查询的关联数据 7 | switch (province) { 8 | case "江苏": { 9 | $scope.cityArr = ["南京", "苏州"]; 10 | break; 11 | } 12 | case "云南": { 13 | $scope.cityArr = ["昆明", "丽江"]; 14 | break; 15 | } 16 | } 17 | }); 18 | 19 | $scope.selectProvince = function(province) { 20 | $scope.selectedProvince = province; 21 | }; 22 | 23 | $scope.selectCity = function(city) { 24 | $scope.selectedCity = city; 25 | }; 26 | }]); -------------------------------------------------------------------------------- /js/binding/watch.js: -------------------------------------------------------------------------------- 1 | angular.module("tutor").controller("WatchCtrl", ["$scope", function ($scope) { 2 | $scope.log = ""; 3 | 4 | $scope.a = 1; 5 | 6 | $scope.$watch("a", function(newValue, oldValue) { 7 | $scope.log += oldValue + " -> " + newValue + "\n"; 8 | }); 9 | 10 | $scope.changeA = function() { 11 | $scope.a++;; 12 | }; 13 | 14 | $scope.arr = [0]; 15 | 16 | $scope.$watch("arr", function(newValue) { 17 | $scope.log += ("change:" + newValue.join(",")) + "\n"; 18 | }); 19 | 20 | $scope.changeArr = function() { 21 | $scope.arr = [7, 8]; 22 | }; 23 | 24 | $scope.$watch("arr", function(newValue) { 25 | $scope.log += ("deep:" + newValue.join(","))+ "\n"; 26 | }, true); 27 | 28 | $scope.addItem = function() { 29 | $scope.arr.push($scope.arr.length); 30 | }; 31 | }]); -------------------------------------------------------------------------------- /js/binding/sort.js: -------------------------------------------------------------------------------- 1 | angular.module("tutor").controller("SortCtrl", ["$scope", "$timeout", function ($scope, $timeout) { 2 | $scope.arr = [72, 14, 10, 63, 4, 25, 55, 2, 4, 43]; 3 | 4 | $scope.sort = function () { 5 | if (!sort($scope.arr)) { 6 | $timeout(function() { 7 | $scope.sort(); 8 | }, 500); 9 | } 10 | }; 11 | 12 | function sort(array) { 13 | // 喵的,写到这个才发现yield是多么好啊 14 | for (var i = 0; i < array.length; i++) { 15 | for (var j = array.length; j > 0; j--) { 16 | if (array[j] < array[j - 1]) { 17 | var temp = array[j - 1]; 18 | array[j - 1] = array[j]; 19 | array[j] = temp; 20 | 21 | return false; 22 | } 23 | } 24 | } 25 | 26 | return true; 27 | } 28 | }]); -------------------------------------------------------------------------------- /partials/binding/region.html: -------------------------------------------------------------------------------- 1 |
2 | 7 | 12 |
13 |
14 | 15 | 16 |
17 |
18 |
-------------------------------------------------------------------------------- /partials/binding/array.html: -------------------------------------------------------------------------------- 1 |
2 | 3 | 6 | 7 |
8 | 9 | 12 | 13 |
14 | 15 | 23 | 24 |
25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 |
NameAge
{{child.name}}{{child.age}}
40 | 41 |
42 | 43 | 46 |
-------------------------------------------------------------------------------- /partials/scope/eventbus.html: -------------------------------------------------------------------------------- 1 |
2 | 15 | 16 |
Root
17 |
18 |
A
19 |
20 | A1 21 | 22 |
23 |
24 | A2 25 |
26 |
27 |
28 |
B
29 |
30 | B1 31 |
32 |
33 | B2 34 |
35 |
36 |
-------------------------------------------------------------------------------- /partials/scope/hierarchy.html: -------------------------------------------------------------------------------- 1 |
2 | 21 | 22 |
Root
23 |
24 |
A
25 |
26 | A1 27 | 28 |
29 |
30 | A2 31 |
32 |
33 |
34 |
B
35 |
36 | B1 37 |
38 |
39 | B2 40 |
41 |
42 |
-------------------------------------------------------------------------------- /binding.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | angularjs binding 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 34 | 35 |
36 | 37 | 38 | -------------------------------------------------------------------------------- /js/scope/hierarchy.js: -------------------------------------------------------------------------------- 1 | angular.module("tutor") 2 | .controller("Level1Ctrl", ["$scope", "$timeout", function($scope, $timeout) { 3 | $scope.state = "normal"; 4 | 5 | $scope.$on("emit1-0", function(e) { 6 | $scope.state = "emit"; 7 | 8 | $timeout(function() { 9 | $scope.$broadcast("broadcast0-1", 1); 10 | }, 3000); 11 | }); 12 | }]) 13 | .controller("Level2Ctrl", ["$scope", "$timeout", function($scope, $timeout) { 14 | $scope.state = "normal"; 15 | 16 | $scope.$on("broadcast0-1", function(e) { 17 | e.preventDefault(); 18 | 19 | $scope.state = "broadcast"; 20 | 21 | $timeout(function() { 22 | $scope.$broadcast("broadcast1-2", 1); 23 | }, 3000); 24 | }); 25 | 26 | $scope.$on("emit2-1", function(e) { 27 | e.stopPropagation(); 28 | 29 | $scope.state = "emit"; 30 | 31 | $timeout(function() { 32 | $scope.$emit("emit1-0", 1); 33 | }, 3000); 34 | 35 | }); 36 | }]) 37 | 38 | .controller("Level3Ctrl", ["$scope", "$timeout", function($scope, $timeout) { 39 | $scope.state = "normal"; 40 | 41 | $scope.test = function() { 42 | $scope.state = "emit"; 43 | 44 | $timeout(function() { 45 | $scope.$emit("emit2-1", 1); 46 | }, 3000); 47 | }; 48 | 49 | $scope.$on("broadcast0-1", function(e) { 50 | if (e.defaultPrevented) { 51 | console.log("hehe"); 52 | } 53 | }); 54 | 55 | $scope.$on("broadcast1-2", function(e) { 56 | $scope.state = "broadcast"; 57 | }); 58 | }]); -------------------------------------------------------------------------------- /js/scope/eventbus.js: -------------------------------------------------------------------------------- 1 | angular.module("tutor").factory("EventBus", function() { 2 | var eventMap = {}; 3 | 4 | var EventBus = { 5 | on : function(eventType, handler) { 6 | //multiple event listener 7 | if (!eventMap[eventType]) { 8 | eventMap[eventType] = []; 9 | } 10 | eventMap[eventType].push(handler); 11 | }, 12 | 13 | off : function(eventType, handler) { 14 | for (var i = 0; i < eventMap[eventType].length; i++) { 15 | if (eventMap[eventType][i] === handler) { 16 | eventMap[eventType].splice(i, 1); 17 | break; 18 | } 19 | } 20 | }, 21 | 22 | fire : function(event) { 23 | var eventType = event.type; 24 | if (eventMap && eventMap[eventType]) { 25 | for (var i = 0; i < eventMap[eventType].length; i++) { 26 | eventMap[eventType][i](event); 27 | } 28 | } 29 | } 30 | }; 31 | return EventBus; 32 | }); 33 | 34 | angular.module("tutor") 35 | .controller("Level3Ctrl1", ["$scope", "$timeout", "EventBus", function($scope, $timeout, EventBus) { 36 | $scope.state = "normal"; 37 | 38 | $scope.test = function() { 39 | $scope.state = "event"; 40 | 41 | $timeout(function() { 42 | EventBus.fire({type: "notice.from.Lv3ctrl1", data:{}}); 43 | }, 3000); 44 | }; 45 | }]) 46 | .controller("Level3Ctrl2", ["$scope", "$timeout", "EventBus", function($scope, $timeout, EventBus) { 47 | $scope.state = "normal"; 48 | 49 | EventBus.on("notice.from.Lv3ctrl1", function(evt) { 50 | $scope.state = "event"; 51 | }); 52 | }]); -------------------------------------------------------------------------------- /scope.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | angularjs scope 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 |
28 |
29 | 30 | {{rootA}} 31 |
32 | 33 |
34 | 35 |
36 |
37 | 38 |
39 | 45 | 46 |
47 |
48 | 49 | -------------------------------------------------------------------------------- /js/app.js: -------------------------------------------------------------------------------- 1 | angular.module("tutor", []); 2 | 3 | angular.module("tutor").controller("BindingCtrl", ["$scope", function($scope) { 4 | $scope.items = [{ 5 | title: "Simple Binding", 6 | url: "partials/binding/simple.html" 7 | }, { 8 | title: "Array", 9 | url: "partials/binding/array.html" 10 | }, { 11 | title: "Watch", 12 | url: "partials/binding/watch.html" 13 | }, { 14 | title: "List", 15 | url: "partials/binding/list.html" 16 | }, { 17 | title: "Style", 18 | url: "partials/binding/style.html" 19 | }, { 20 | title: "If", 21 | url: "partials/binding/if.html" 22 | }, { 23 | title: "Switch", 24 | url: "partials/binding/switch.html" 25 | }, { 26 | title: "Region", 27 | url: "partials/binding/region.html" 28 | }, { 29 | title: "Employee", 30 | url: "partials/binding/employee.html" 31 | }, { 32 | title: "Wave", 33 | url: "partials/binding/wave.html" 34 | }, { 35 | title: "Sort", 36 | url: "partials/binding/sort.html" 37 | }]; 38 | 39 | $scope.selectedItem = $scope.items[0]; 40 | 41 | $scope.change = function(item) { 42 | $scope.selectedItem = item; 43 | }; 44 | }]); 45 | 46 | angular.module("tutor").controller("ScopeCtrl", ["$scope", function($scope) { 47 | $scope.items = [{ 48 | title: "extend", 49 | url: "partials/scope/extend.html" 50 | }, { 51 | title: "assign", 52 | url: "partials/scope/assign.html" 53 | }, { 54 | title: "alias", 55 | url: "partials/scope/alias.html" 56 | }, { 57 | title: "new scope", 58 | url: "partials/scope/newscope.html" 59 | }, { 60 | title: "isolate", 61 | url: "partials/scope/isolate.html" 62 | }, { 63 | title: "hierarchy", 64 | url: "partials/scope/hierarchy.html" 65 | }, { 66 | title: "event bus", 67 | url: "partials/scope/eventbus.html" 68 | }]; 69 | 70 | $scope.selectedItem = $scope.items[0]; 71 | 72 | $scope.change = function(item) { 73 | $scope.selectedItem = item; 74 | }; 75 | }]); -------------------------------------------------------------------------------- /js/binding/employee.js: -------------------------------------------------------------------------------- 1 | angular.module("tutor").controller("EmployeeCtrl", ["$scope", function ($scope) { 2 | $scope.editing = false; 3 | 4 | $scope.employees = []; 5 | $scope.selectedEmployee = null; 6 | $scope.editingEmployee = {}; 7 | 8 | $scope.provinceArr = ["江苏", "云南"]; 9 | $scope.cityArr = []; 10 | $scope.countyArr = []; 11 | 12 | $scope.formatGender = function (gender) { 13 | if (gender == 0) 14 | return "女"; 15 | 16 | if (gender == 1) 17 | return "男"; 18 | }; 19 | 20 | $scope.$watch("selectedEmployee", function (employee) { 21 | $scope.editingEmployee = employee || {}; 22 | }); 23 | 24 | $scope.$watch("editingEmployee.province", function (province) { 25 | // 真正有用的代码在这里,实际场景中这里可以是调用后端服务查询的关联数据 26 | switch (province) { 27 | case "江苏": 28 | { 29 | $scope.cityArr = ["南京", "苏州"]; 30 | break; 31 | } 32 | case "云南": 33 | { 34 | $scope.cityArr = ["昆明", "丽江"]; 35 | break; 36 | } 37 | } 38 | }); 39 | 40 | $scope.selectEmployee = function (employee) { 41 | $scope.selectedEmployee = employee; 42 | }; 43 | 44 | $scope.create = function () { 45 | $scope.state = "New"; 46 | $scope.editing = true; 47 | 48 | $scope.editingEmployee = {}; 49 | }; 50 | 51 | $scope.modify = function () { 52 | $scope.state = "Modify"; 53 | $scope.editing = true; 54 | 55 | $scope.editingEmployee = angular.extend({}, $scope.selectedEmployee); 56 | }; 57 | 58 | $scope.remove = function () { 59 | if (confirm("确认删除此员工吗?")) { 60 | for (var i = 0; i < $scope.employees.length; i++) { 61 | if ($scope.employees[i] == $scope.selectedEmployee) { 62 | $scope.employees.splice(i, 1); 63 | $scope.selectedEmployee = null; 64 | break; 65 | } 66 | } 67 | } 68 | }; 69 | 70 | $scope.ok = function () { 71 | if ($scope.state === "New") { 72 | $scope.employees.push($scope.editingEmployee); 73 | $scope.selectedEmployee = $scope.editingEmployee; 74 | } 75 | else if ($scope.state === "Modify") { 76 | $scope.selectedEmployee = angular.extend($scope.selectedEmployee, $scope.editingEmployee); 77 | } 78 | $scope.state = "View"; 79 | $scope.editing = false; 80 | }; 81 | 82 | $scope.cancel = function () { 83 | $scope.state = "View"; 84 | $scope.editing = false; 85 | 86 | $scope.editingEmployee = $scope.selectedEmployee; 87 | }; 88 | 89 | $scope.okDisabled = function () { 90 | if ($scope.editing && ($scope.editingEmployee.name) && ($scope.editingEmployee.name.length >= 5)) { 91 | return false; 92 | } 93 | else { 94 | return true; 95 | } 96 | }; 97 | }]); -------------------------------------------------------------------------------- /partials/binding/employee.html: -------------------------------------------------------------------------------- 1 |
2 |
员工列表
3 |
4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 |
姓名年龄性别出生地民族
{{employee.name}}{{employee.age}}{{(employee.gender == "1") ? "男" : "女"}}{{employee.province}}省{{employee.city}}市{{(employee.minority == "yes") ? employee.nation : "汉族"}}
25 | 26 |
27 |
员工详细信息
28 |
29 |
30 |
31 | 32 | 33 |
34 | 36 |
37 |
38 |
39 | 40 | 41 |
42 | 44 |
45 |
46 |
47 | 48 | 49 |
50 | 54 | 58 |
59 |
60 |
61 | 62 | 63 |
64 | 66 |
67 |
68 | 70 |
71 |
72 |
73 | 74 | 75 |
76 | 80 | 84 | 87 |
88 |
89 |
90 |
91 | 92 | 95 | 98 |
99 |
100 | 103 | 104 |
105 |
106 |
107 |
108 |
109 |
110 |
-------------------------------------------------------------------------------- /docs/02.scope.md: -------------------------------------------------------------------------------- 1 | ## 作用域与事件 2 | 3 | 学习Angular,首先要理解其作用域机制。 4 | 5 | Angular应用是分层的,主要有三个层面:视图,模型,视图模型。其中,视图很好理解,就是直接可见的界面,模型就是数据,那么视图模型是什么呢?是一种把数据包装给视图调用的东西。 6 | 7 | 所谓作用域,也就是视图模型中的一个概念。 8 | 9 | ### 根作用域 10 | 11 | 在第一章中,有这么一个很简单的数据绑定例子: 12 | 13 | ```HTML 14 | 15 |
{{rootA}}
16 | ``` 17 | 18 | 当时我们解释过,这个例子能够运行的的原因是,它的rootA变量被创建在根作用域上。每个Angular应用默认有一个根作用域,也就是说,如果用户未指定自己的控制器,变量就是直接挂在这个层级上的。 19 | 20 | 作用域在一个Angular应用中是以树的形状体现的,根作用域位于最顶层,从它往下挂着各级作用域。每一级作用域上面挂着变量和方法,供所属的视图调用。 21 | 22 | 如果想要在代码中显式使用根作用域,可以注入$rootScope。 23 | 24 | 怎么证实刚才的例子中,$rootScope确实存在,而且变量真的在它上面呢?我们来写个代码: 25 | 26 | ```JavaScript 27 | function RootService($rootScope) { 28 | $rootScope.$watch("rootA", function(newVal) { 29 | alert(newVal); 30 | }); 31 | } 32 | ``` 33 | 34 | 这时候我们可以看到,这段代码并未跟界面产生任何关系,但里面的监控表达式确实生效了,也就是说,观测到了根作用域上rootA的变更,说明有人给它赋值了。 35 | 36 | ### 作用域的继承关系 37 | 38 | 在开发过程中,我们可能会出现控制器的嵌套,看下面这段代码: 39 | 40 | ```HTML 41 |
42 | {{a}} 43 |
44 | {{a}} 45 |
46 |
47 | ``` 48 | 49 | ```JavaScript 50 | function OuterCtrl($scope) { 51 | $scope.a = 1; 52 | } 53 | 54 | function InnerCtrl($scope) { 55 | } 56 | ``` 57 | 58 | 注意结果,我们可以看到界面显示了两个1,而我们只在OuterCtrl的作用域里定义了a变量,但界面给我们的结果是,两个a都有值。这里内层的a值显然来自外层,因为当我们对界面作出这样的调整之后,就只有一个了: 59 | 60 | ```HTML 61 |
62 | {{a}} 63 |
64 | 65 |
66 | {{a}} 67 |
68 | ``` 69 | 70 | 这是为什么呢?在Angular中,如果两个控制器所对应的视图存在上下级关系,它们的作用域就自动产生继承关系。什么意思呢? 71 | 72 | 先考虑在纯JavaScript代码中,两个构造函数各自有一个实例: 73 | 74 | ```JavaScript 75 | function Outer() { 76 | this.a = 1; 77 | } 78 | 79 | function Inner() { 80 | } 81 | 82 | var outer = new Outer(); 83 | var inner = new Inner(); 84 | ``` 85 | 86 | 在这里面添加什么代码,能够让inner.a == 1呢? 87 | 88 | 熟悉JavaScript原型的我们,当然毫不犹豫就加了一句:Inner.prototype = outer; 89 | 90 | ```JavaScript 91 | function Outer() { 92 | this.a = 1; 93 | } 94 | 95 | function Inner() { 96 | } 97 | 98 | var outer = new Outer(); 99 | Inner.prototype = outer; 100 | var inner = new Inner(); 101 | ``` 102 | 103 | 于是就得到想要的结果了。 104 | 105 | 再回到我们的例子里,Angular的实现机制其实也就是把这两个控制器中的$scope作了关联,外层的作用域实例成为了内层作用域的原型。 106 | 107 | 以此类推,整个Angular应用的作用域,都存在自顶向下的继承关系,最顶层的是$rootScope,然后一级一级,沿着不同的控制器往下,形成了一棵作用域的树,这也就像封建社会:天子高高在上,分茅裂土,公侯伯子男,一级一级往下,层层从属。 108 | 109 | ### 简单变量的取值与赋值 110 | 111 | 既然作用域是通过原型来继承的,自然也就可以推论出一些特征来。比如说这段代码,点击按钮的结果是什么? 112 | 113 | ```HTML 114 |
115 | {{a}} 116 |
117 | {{a}} 118 | 119 |
120 |
121 | ``` 122 | 123 | ```JavaScript 124 | function OuterCtrl($scope) { 125 | $scope.a = 1; 126 | } 127 | 128 | function InnerCtrl($scope) { 129 | } 130 | ``` 131 | 132 | 点了按钮之后,两个a不一致了,里面的变了,外面的没变,这是为什么?原先两层不是共用一个a吗,怎么会出现两个不同的值?看这句就能明白了,相当于我们之前那个例子里,这样赋值了: 133 | 134 | ```JavaScript 135 | function Outer() { 136 | this.a = 1; 137 | } 138 | 139 | function Inner() { 140 | } 141 | 142 | var outer = new Outer(); 143 | Inner.prototype = outer; 144 | var inner = new Inner(); 145 | 146 | inner.a = inner.a + 1; 147 | ``` 148 | 149 | 最后这句,很有意思,它有两个过程,取值的时候,因为inner自身上面没有,所以沿着原型往上取到了1,然后自增了之后,赋值给自己,这个赋值的时候就不同了,敬爱的林副主席教导我们:有a就赋值,没有a,创造一个a也要赋值。 150 | 151 | 所以这么一来,inner上面就被赋值了一个新的a,outer里面的仍然保持原样,这也就导致了刚才看到的结果。 152 | 153 | 初学者在这个问题上很容易犯错,如果不能随时很明确地认识到这些变量的差异,很容易写出有问题的程序。既然这样,我们可以用一些别的方式来减少变量的歧义。 154 | 155 | ### 对象在上下级作用域之间的共享 156 | 157 | 比如说,我们就是想上下级共享变量,不创建新的,该怎么办呢? 158 | 159 | 考虑下面这个例子: 160 | 161 | ```JavaScript 162 | function Outer() { 163 | this.data = { 164 | a: 1 165 | }; 166 | } 167 | 168 | function Inner() { 169 | } 170 | 171 | var outer = new Outer(); 172 | Inner.prototype = outer; 173 | 174 | var inner = new Inner(); 175 | 176 | console.log(outer.data.a); 177 | console.log(inner.data.a); 178 | 179 | // 注意,这个时候会怎样? 180 | inner.data.a += 1; 181 | 182 | console.log(outer.data.a); 183 | console.log(inner.data.a); 184 | ``` 185 | 186 | 这次的结果就跟上次不同了,原因是什么呢?因为两者的data是同一个引用,对这个对象上面的属性修改,是可以反映到两级对象上的。我们通过引入一个data对象的方式,继续使用了原先的变量。把这个代码移植到AngularJS里,就变成了下面这样: 187 | 188 | ```HTML 189 |
190 | {{data.a}} 191 |
192 | {{data.a}} 193 | 194 |
195 |
196 | ``` 197 | 198 | ```JavaScript 199 | function OuterCtrl($scope) { 200 | $scope.data = { 201 | a: 1 202 | }; 203 | } 204 | 205 | function InnerCtrl($scope) { 206 | } 207 | ``` 208 | 209 | 从这个例子我们就发现了,如果想要避免变量歧义,显式指定所要使用的变量会是比较好的方式,那么如果我们确实就是要在上下级分别存在相同的变量该怎么办呢,比如说下级的点击,想要给上级的a增加1,我们可以使用$parent来指定上级作用域。 210 | 211 | ```HTML 212 |
213 | {{a}} 214 |
215 | {{a}} 216 | 217 |
218 |
219 | ``` 220 | 221 | ```JavaScript 222 | function OuterCtrl($scope) { 223 | $scope.a = 1; 224 | } 225 | 226 | function InnerCtrl($scope) { 227 | } 228 | ``` 229 | 230 | ### 控制器实例别名 231 | 232 | 从Angular 1.2开始,引入了控制器实例的别名机制。在之前,可能都需要向控制器注入$scope,然后,控制器里面定义可绑定属性和方法都是这样: 233 | 234 | ```JavaScript 235 | function CtrlA($scope) { 236 | $scope.a = 1; 237 | $scope.foo = function() { 238 | }; 239 | } 240 | ``` 241 | 242 | ```HTML 243 |
244 |
{{a}}
245 | 246 |
247 | ``` 248 | 249 | 其实$scope的注入是一个比较冗余的概念,没有必要把这种概念过分暴露给用户。在应用中出现的作用域,有的是充当视图模型,而有些则是处于隔离数据的需要,前者如ng-controller,后者如ng-repeat。在最近版本的AngularJS中,已经可以不显式注入$scope了,语法是这样: 250 | 251 | ```JavaScript 252 | function CtrlB() { 253 | this.a = 1; 254 | this.foo = function() { 255 | }; 256 | } 257 | ``` 258 | 259 | 这里面,就完全没有$scope的身影了,那这个控制器怎么使用呢? 260 | 261 | ```HTML 262 |
263 |
{{instanceB.a}}
264 | 265 |
266 | ``` 267 | 268 | 注意我们在引入控制器的时候,加了一个as语法,给CtrlB的实例取了一个别名叫做instanceB,这样,它下属的各级视图都可以显式使用这个名称来调用其属性和方法,不易引起歧义。 269 | 270 | 在开发过程中,为了避免模板中的变量歧义,应当尽可能使用命名限定,比如a.b,出现歧义的可能性就比单独的b要少得多。 271 | 272 | ### 不请自来的新作用域 273 | 274 | 在一个应用中,最常见的会创建作用域的指令是ng-controller,这个很好理解,因为它会实例化一个新的控制器,往里面注入一个$scope,也就是一个新的作用域,所以一般人都会很自然地理解这里面的作用域隔离关系。但是对于另外一些情况,就有些困惑了,比如说,ng-repeat,怎么理解这个东西也会创建新作用域呢? 275 | 276 | 还是看之前的例子: 277 | 278 | ```JavaScript 279 | $scope.arr = [1, 2, 3]; 280 | ``` 281 | 282 | ```HTML 283 | 286 | ``` 287 | 288 | 在ng-repeat的表达式里,有一个item,我们来思考一下,这个item是个什么情况。在这里,数组中有三个元素,在循环的时候,这三个元素都叫做item,这时候就有个问题,如何区分每个不同的item,可能我们这个例子还不够直接,那改一下: 289 | 290 | ```HTML 291 |
outer: {{sum1}}
292 | 299 | ``` 300 | 301 | 这个例子运行一下,我们会发现每个item都会独立改变,说明它们确实是区分开了的。事实上,Angular在这里为ng-repeat的每个子项都创建了单独的作用域,所以,每个item都存在于自己的作用域里,互不影响。有时候,我们是需要在循环内部访问外层变量的,回忆一下,在本章的前面部分中,我们举例说,如果两个控制器,它们的视图有包含关系,内层控制器的作用域可以通过$parent来访问外层控制器作用域上的变量,那么,在这种循环里,是不是也可以如此呢? 302 | 303 | 看这个例子: 304 | 305 | ```HTML 306 |
outer: {{sum2}}
307 | 314 | ``` 315 | 316 | 果然是可以的。很多时候,人们会把$parent误认为是上下两级控制器之间的访问通道,但从这个例子我们可以看到,并非如此,只是两级作用域而已,作用域跟控制器还是不同的,刚才的循环可以说是有两级作用域,但都处于同一个控制器之中。 317 | 318 | 刚才我们已经提到了ng-controller和ng-repeat这两个常用的内置指令,两者都会创建新的作用域,除此之外,还有一些其他指令也会创建新的作用域,很多初学者在使用过程中很容易产生困扰。 319 | 320 | 第一章我们提到用ng-show和ng-hide来控制某个界面块的整体展示和隐藏,但同样的功能其实也可以用ng-if来实现。那么这两者的差异是什么呢,所谓show和hide,大家很好理解,就是某个东西原先有,只是控制是否显式,而if的含义是,如果满足条件,就创建这块DOM,否则不创建。所以,ng-if所控制的界面块,只有条件为真的时候才会存在于DOM树中。 321 | 322 | 除此之外,两者还有个差异,ng-show和ng-hide是不自带作用域的,而ng-if则自己创建了一级作用域。在用的时候,两者就是有差别的,比如说内部元素访问外层定义的变量,就需要使用类似ng-repeat那样的$parent语法了。 323 | 324 | 相似的类型还有ng-switch,ng-include等等,规律可以总结,也就是那些会动态创建一块界面的东西,都是自带一级作用域。 325 | 326 | ### “悬空”的作用域 327 | 328 | 一般而言,在Angular工程中,基本是不需要手动创建作用域的,但真想创建的话,也是可以做到的。在任意一个已有的作用域上调用$new(),就能创建一个新的作用域: 329 | 330 | ```JavaScript 331 | var newScope = scope.$new(); 332 | ``` 333 | 334 | 刚创建出来的作用域是一个“悬空”的作用域,也就是说,它跟任何界面模板都不存在绑定关系,创建它的作用域会成为它的$parent。这种作用域可以经过$compile阶段,与某视图模板进行融合。 335 | 336 | 为了帮助理解,我们可以用DocumentFragment作类比,当作用域被创建的时候,就好比是创建了一个DocumentFragment,它是不在DOM树上的,只有当它被append到DOM树上,才能够被当做普通的DOM来使用。 337 | 338 | 那么,悬空的作用域是不是什么用处都没有呢?也不是,尽管它未与视图关联,但是它的一些方法仍然可以用。 339 | 340 | 我们在第一章里提到了$watch,这就是定义在作用域原型上的。如果我们想要监控一个数据的变化,但这个数据并非绑定到界面上的,比如下面这样,怎么办? 341 | 342 | ```JavaScript 343 | function IsolateCtrl($scope) { 344 | var child = { 345 | a: 1 346 | }; 347 | 348 | child.a++; 349 | } 350 | ``` 351 | 352 | 注意这个child,它并未绑定到$scope上,如果我们想要在a变化的时候做某些事情,是没有办法做的,因为直到最近的某些浏览器中,才实现了Object.observe这样的对象变更观测方法,之前某些浏览器中要做这些,会比较麻烦。 353 | 354 | 但是我们的$watch和$eval之类的方法,其实都是实现在作用域对象上的,也就是说,任何一个作用域,即使没有与界面产生关联,也是能够使用这些方法的。 355 | 356 | ```JavaScript 357 | function IsolateCtrl($scope) { 358 | var child = $scope.$new(); 359 | child.a = 1; 360 | 361 | child.$watch("a", function(newValue) { 362 | alert(newValue); 363 | }); 364 | 365 | $scope.change = function() { 366 | child.a++; 367 | }; 368 | } 369 | ``` 370 | 371 | 这时候child里面a的变更就可以被观测到,并且,这个child只有本作用域可以访问到,相当于是一个增强版的数据模型。如果我们要做一个小型流程引擎之类的东西,作用域对象上提供的这些方法会很有用。 372 | 373 | ### 作用域上的事件 374 | 375 | 我们刚才提到使用$parent来处理上下级的通讯,但其实这不是一种好的方式,尤其是在不同控制器之间,这会增加它们的耦合,对组件复用很不利。那怎样才能更好地解耦呢?我们可以使用事件。 376 | 377 | 提到事件,可能很多人想到的都是DOM事件,其实DOM事件只存在于上层,而且没有业务含义,如果我们想要传递一个明确的业务消息,就需要使用业务事件。这种所谓的业务事件,其实就是一种消息的传递。 378 | 379 | 假设有如图所示的应用: 380 | 381 | ![事件的传递](https://raw.githubusercontent.com/xufei/blog/master/assets/ng/event_flat.png) 382 | 383 | 这张图中有一个应用,下面存在两个视图块A和B,它们分别又有两个子视图。这时候,如果子视图A1想要发出一个业务事件,使得B1和B2能够得到通知,过程就会是: 384 | 385 | - 沿着父作用域一路往上到达双方共同的祖先作用域 386 | - 从祖先作用域一级一级往下进行广播,直到到达需要的地方 387 | 388 | 刚才的图形体现了界面的包含关系,如果把这个图再立体化,就会是下面这样: 389 | 390 | ![事件的传递](https://raw.githubusercontent.com/xufei/blog/master/assets/ng/event.png) 391 | 392 | 对于这种事件的传播方式,可以有个类似的比喻: 393 | 394 | 比如说,某军队中,1营1连1排长想要给1营2连下属的三个排发个警戒通知,他的通知方向是一级一级向上汇报,直到双方共同的上级,也就是1营指挥人员这里,然后再沿着二连这个路线向下去通知。 395 | 396 | - 从作用域往上发送事件,使用scope.$emit 397 | 398 | ```JavaScript 399 | $scope.$emit("someEvent", {}); 400 | ``` 401 | 402 | - 从作用域往下发送事件,使用scope.$broadcast 403 | 404 | ```JavaScript 405 | $scope.$broadcast("someEvent", {}); 406 | ``` 407 | 408 | 这两个方法的第二个参数是要随事件带出的数据。 409 | 410 | 注意,这两种方式传播事件,事件的发送方自己也会收到一份。 411 | 412 | 使用事件的主要作用是消除模块间的耦合,发送方是不需要知道接收方的状况的,接收方也不需要知道发送方的状况,双方只需要传送必要的业务数据即可。 413 | 414 | ### 事件的接收与阻止 415 | 416 | 无论是$emit还是$broadcast发送的事件,都可以被接收,接收这两种事件的方式是一样的: 417 | 418 | ```JavaScript 419 | $scope.$on("someEvent", function(e) { 420 | // 这里从e上可以取到发送过来的数据 421 | }); 422 | ``` 423 | 424 | 注意,事件被接收了,并不代表它就中止了,它仍然会沿着原来的方向继续传播,也就是: 425 | 426 | - $emit的事件将继续向上传播 427 | - $broadcast的事件将继续向下传播 428 | 429 | 有时候,我们希望某一级收到事件之后,就让它停下来,不再传播,可以把事件中止。这时候,两种事件的区别就体现出来了,只有$emit发出的事件是可以被中止的,$broadcast发出的不可以。 430 | 431 | 如果想要阻止$emit事件的继续传播,可以调用事件对象的stopPropagation()方法。 432 | 433 | ```JavaScript 434 | $scope.$on("someEvent", function(e) { 435 | e.stopPropagation(); 436 | }); 437 | ``` 438 | 439 | 但是,想要阻止$broadcast事件的传播,就麻烦了,我们只能通过变通的方式: 440 | 441 | 首先,调用事件对象的preventDefault()方法,然后,在收取这个事件对象的时候,判断它的defaultPrevented属性,如果为true,就忽略此事件。这个过程比较麻烦,其实我们一般是不需要管的,只要不监听对应的事件就可以了。在实际使用过程中,也应当尽量少使用事件的广播,尤其是从较高的层级进行广播。 442 | 443 | *上级作用域* 444 | ```JavaScript 445 | $scope.$on("someEvent", function(e) { 446 | e.preventDefault(); 447 | }); 448 | ``` 449 | 450 | *下级作用域* 451 | ```JavaScript 452 | $scope.$on("someEvent", function(e) { 453 | if (e.defaultPrevented) { 454 | return; 455 | } 456 | }); 457 | ``` 458 | 459 | ### 事件总线 460 | 461 | 在Angular中,不同层级作用域之间的数据通信有多种方式,可以通过原型继承的一些特征,也可以收发事件,还可以使用服务来构造单例对象进行通信。 462 | 463 | 前面提到的这个军队的例子,有些时候沟通效率比较低,特别是层级多的时候。想象一下,刚才这个只有三层,如果更复杂,一个排长的消息都一定要报告到军长那边再下发到其他基层主官,必定贻误军情,更何况有很多下级根本不需要知道这个消息。 464 | 那怎么办呢,难道是直接打电话沟通吗?这个效率高是高,就是容易乱,这也就相当于界面块之间的直接通过id调用。 465 | 466 | Angular的作用域树类似于传统的组织架构树,一个大型企业,一般都会有若干层级,近年来有很多管理的方法论,比如说组织架构的扁平化。 467 | 468 | 我们能不能这样:搞一个专门负责通讯的机构,大家的消息都发给它,然后由它发给相关人员,其他人员在理念上都是平级关系。 469 | 470 | 这就是一个很典型的订阅发布模式,接收方在这里订阅消息,发布方在这里发布消息。这个过程可以用这样的图形来表示: 471 | 472 | ![应用内的事件总线](https://raw.githubusercontent.com/xufei/blog/master/assets/ng/ng_event_bus.png) 473 | 474 | 代码写起来也很简单,把它做成一个公共模块,就可以被各种业务方调用了: 475 | 476 | ```JavaScript 477 | app.factory("EventBus", function() { 478 | var eventMap = {}; 479 | 480 | var EventBus = { 481 | on : function(eventType, handler) { 482 | //multiple event listener 483 | if (!eventMap[eventType]) { 484 | eventMap[eventType] = []; 485 | } 486 | eventMap[eventType].push(handler); 487 | }, 488 | 489 | off : function(eventType, handler) { 490 | for (var i = 0; i < eventMap[eventType].length; i++) { 491 | if (eventMap[eventType][i] === handler) { 492 | eventMap[eventType].splice(i, 1); 493 | break; 494 | } 495 | } 496 | }, 497 | 498 | fire : function(event) { 499 | var eventType = event.type; 500 | if (eventMap && eventMap[eventType]) { 501 | for (var i = 0; i < eventMap[eventType].length; i++) { 502 | eventMap[eventType][i](event); 503 | } 504 | } 505 | } 506 | }; 507 | return EventBus; 508 | }); 509 | ``` 510 | 511 | 事件订阅代码: 512 | 513 | ```JavaScript 514 | EventBus.on("someEvent", function(event) { 515 | // 这里处理事件 516 | var c = event.data.a + event.data.b; 517 | }); 518 | ``` 519 | 520 | 事件发布代码: 521 | 522 | ```JavaScript 523 | EventBus.fire({ 524 | type: "someEvent", 525 | data: { 526 | aaa: 1, 527 | bbb: 2 528 | } 529 | }); 530 | ``` 531 | 532 | 注意,如果在复杂的应用中使用事件总线,需要慎重规划事件名,推荐使用业务路径,比如:"portal.menu.selectedMenuChange",以避免事件冲突。 533 | 534 | ### 小结 535 | 536 | 在本章,我们学习了作用域相关的知识,以及它们之间传递数据的方式。作用域在整个Angular应用中形成了一棵树,以$rootScope为根部,开枝散叶。这棵树独立于DOM而存在,又与DOM相关联。事件在整个树上传播,如蜂飞蝶舞。 537 | 538 | 总体来说,使用AngularJS对JavaScript的基本功是有一定要求的,因为这里面大部分实现都依赖于纯JavaScript语法,比如原型继承的使用。如果对这一块有充分的认识,理解Angular的作用域就会比较容易。 539 | 540 | 一个大型单页应用,需要对部件的整合方式和通信机制作良好的规划,为它们建立良好的秩序,这对于确保整个应用的稳定性是非常必要的。 541 | 542 | > 首要问题不是自由,而是建立合法的公共秩序。人类可以无自由而有秩序,但不能无秩序而有自由。——缪尔·亨廷顿 543 | 544 | 本章所涉及的所有Demo,参见[在线演示地址](https://xufei.github.io/ng-tutor/scope.html) 545 | 546 | [代码库](https://github.com/xufei/ng-tutor) 547 | 548 | 演讲幻灯片下载:点[这里](https://xufei.github.io/ng-tutor/slides/scope.pdf) 549 | 550 | -------------------------------------------------------------------------------- /docs/01.binding.md: -------------------------------------------------------------------------------- 1 | ## 数据绑定与监控 2 | 3 | 在业务开发的过程中,我们可能会大量使用DOM操作,这个过程很繁琐,但是有了AngularJS,基本上就可以解脱了,做到这一点的关键是数据绑定。那什么是数据绑定,怎样绑定呢?本节将从多种角度,选取业务开发过程中的各种场景来举例说明。 4 | 5 | ### 基于单一模型的界面同步 6 | 7 | 有时候,我们会有这样的需求,界面上有个输入框,然后有另外一个地方,要把这个文本原样显示出来,如果没有数据绑定,这个代码可能很麻烦了,比如说,我们要监听输入框的各种事件,键盘按键、复制粘贴等等,然后再把取得的值写入对应位置。但是如果有数据绑定,这个事情就非常简单。 8 | 9 | ```HTML 10 | 11 |
{{a}}
12 | ``` 13 | 14 | 这么小小一段代码,就实现了我们想要的功能,是不是很可爱?这中间的关键是什么呢,就是变量a,在这里,变量a充当了数据模型的角色,输入框的数据变更会同步到模型上,然后再分发给绑定到这个模型的其他UI元素。 15 | 16 | 注意,任意绑定到数据模型的输入元素,它的数据变更都会导致模型变更,比如说,我们有另外一个需求,两个输入框,我们想要在任意一个中输入的时候,另外一个的值始终跟它保持同步。如果用传统的方式,需要在两个输入框上都添加事件,但是有了数据绑定之后,这一切都很简单: 17 | 18 | ```HTML 19 | 20 | 21 | ``` 22 | 23 | 这样的代码就可以了,核心要素还是这个数据模型b。 24 | 25 | 到目前为止的两个例子都很简单,但可能有人有问题要问,因为我们什么js都没有写,这个a跟b是哪里来的,为什么就能起作用呢?对于这个问题,我来作个类比。 26 | 27 | 比如大家写js,都知道变量可以不声明就使用: 28 | 29 | ```JavaScript 30 | a = 1; 31 | ``` 32 | 33 | 这时候a被赋值到哪里了呢,到了全局的window对象上,也就是说其实相当于: 34 | 35 | ```JavaScript 36 | window.a = 1; 37 | ``` 38 | 39 | 在AngularJS里,变量和表达式都附着在一种叫做作用域(scope)的东西上,可以自己声明新的作用域,也可以不声明。每个Angular应用默认会有一个根作用域($rootScope),凡是没有预先声明的东西,都会被创建到它上面去。 40 | 41 | 作用域的相关概念,我们会在下一章里面讲述。在这里,我们只需要知道,如果在界面中绑定了未定义的某变量,当它被赋值的时候,就会自动创建到对应的作用域上去。 42 | 43 | 前面我们在例子中提到的{{}}这种符号,称为插值表达式,这里面的内容将会被动态解析,也可以不使用这种方式来进行绑定,Angular另有一个ng-bind指令用于做这种事情: 44 | 45 | ```HTML 46 | 47 |
{{a}}
48 |
49 | ``` 50 | 51 | ### 对模型的二次计算 52 | 53 | 嗯,有时候,实际情况没有这么简单,比如说,我们可能会需要对数据作一点处理,比如,在每个表示价格的数字后面添加一个单位: 54 | 55 | ```HTML 56 | 57 | {{price + "(元)"}} 58 | ``` 59 | 60 | 当然我们这个例子并不好,因为,其实你可以把无关的数据都放在绑定表达式的外面,就像这样: 61 | 62 | ```HTML 63 | 64 | {{price}}(元) 65 | ``` 66 | 67 | 那么,考虑个稍微复杂一些的。我们经常会遇到,在界面上展示性别,但是数据库里面存的是0或者1,那么,总要对它作个转换。有些比较老土的做法是这样,在模型上添加额外的字段给显示用: 68 | 69 | 这是原始数据: 70 | 71 | ```JavaScript 72 | var tom = { 73 | name: "Tom", 74 | gender: 1 75 | }; 76 | ``` 77 | 78 | 被他转换之后,成了这样: 79 | 80 | ```JavaScript 81 | var tom = { 82 | name: "Tom", 83 | gender: 1, 84 | genderText: "男" 85 | }; 86 | ``` 87 | 88 | 转换函数内容如下: 89 | 90 | ```JavaScript 91 | if (person.gender == 0) 92 | person.genderText = "女"; 93 | 94 | if (person.gender == 1) 95 | person.genderText = "男"; 96 | ``` 97 | 98 | 这样的做法虽然能够达到效果,但破坏了模型的结构,我们可以做些改变: 99 | 100 | ```HTML 101 |
{{formatGender(tom.gender)}}
102 | ``` 103 | 104 | ```JavaScript 105 | $scope.formatGender = function(gender) { 106 | if (gender == 0) 107 | return "女"; 108 | 109 | if (gender == 1) 110 | return "男"; 111 | } 112 | }; 113 | ``` 114 | 115 | 这样我们就达到了目的。这个例子让我们发现,原来,在绑定表达式里面,是可以使用函数的。像我们这里的格式化函数,其实作用只存在于视图层,所以不会影响到真实数据模型。 116 | 117 | 注意:这里有两个注意点。 118 | 119 | 第一,在绑定表达式里面,只能使用自定义函数,不能使用原生函数。举个例子: 120 | 121 | ```HTML 122 |
{{Math.abs(-1)}}
123 | ``` 124 | 125 | 这句就是有问题的,因为Angular的插值表达式机制决定了它不能使用这样的函数,它是直接用自己的解释器去解析这个字符串的,如果确实需要调用原生函数,可以用一个自定义函数作包装,在自定义函数里面可以随意使用各种原生对象,就像这样: 126 | 127 | ```HTML 128 |
{{abs(-1)}}
129 | ``` 130 | 131 | ```JavaScript 132 | $scope.abs = function(number) { 133 | return Math.abs(number); 134 | }; 135 | ``` 136 | 137 | 第二,刚才我们这个例子只是为了说明可以这么用,但不表示这是最佳方案。Angular为这类需求提供了一种叫做filter的方案,可以在插值表达式中使用管道操作符来格式化数据,这个我们后面再细看。 138 | 139 | ### 数组与对象结构的绑定 140 | 141 | 有时候,我们的数据并不总是这么简单,比如说,有可能会需要把一个数组的数据展示出来,这种情况下可以使用Angular的ng-repeat指令来处理,这个东西相当于一个循环,比如我们来看这段例子: 142 | 143 | ```JavaScript 144 | $scope.arr1 = [1, 2, 3]; 145 | 146 | $scope.add = function() { 147 | $scope.arr1.push($scope.arr1.length + 1); 148 | }; 149 | ``` 150 | 151 | ```HTML 152 | 153 | 156 | ``` 157 | 158 | 这样就可以把数组的内容展示到界面上了。数组中的数据产生变化时,也能够实时更新到界面上来。 159 | 160 | 有时候,我们会遇到数组里有重复元素的情况,这时候,ng-repeat代码不能起作用,原因是Angular默认需要在数组中使用唯一索引,那假如我们的数据确实如此,怎么办呢?可以指定它使用序号作索引,就像这样: 161 | 162 | ```JavaScript 163 | $scope.arr2 = [1, 1, 3]; 164 | ``` 165 | 166 | ```HTML 167 | 170 | ``` 171 | 172 | 也可以把多维数组用多层循环的方式迭代出来: 173 | 174 | ```JavaScript 175 | $scope.arr3 = [ 176 | [11, 12, 13], 177 | [21, 22, 23], 178 | [31, 32, 33] 179 | ]; 180 | ``` 181 | 182 | ```HTML 183 | 191 | ``` 192 | 193 | 如果是数组中的元素是对象结构,也不难,我们用个表格来展示这个数组: 194 | 195 | ```JavaScript 196 | $scope.arr4 = [{ 197 | name: "Tom", 198 | age: 5 199 | }, { 200 | name: "Jerry", 201 | age: 2 202 | }]; 203 | ``` 204 | 205 | ```HTML 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 |
NameAge
{{child.name}}{{child.age}}
220 | ``` 221 | 222 | 有时候我们想遍历对象的属性,也可以使用ng-repeat指令: 223 | 224 | ```JavaScript 225 | $scope.obj = { 226 | a: 1, 227 | b: 2, 228 | c: 3 229 | }; 230 | ``` 231 | 232 | ```HTML 233 | 236 | ``` 237 | 238 | 注意,在ng-repeat表达式里,我们使用了一个(key, value)来描述键值关系,如果只想要值,也可以不用这么写,直接按照数组的写法即可。对象值有重复的话,不用像数组那么麻烦需要指定$index做索引,因为它是对象的key做索引,这是不会重复的。 239 | 240 | ### 数据监控 241 | 242 | 有时候,我们不是直接把数据绑定到界面上,而是先要赋值到其他变量上,或者针对数据的变更,作出一些逻辑的处理,这个时候就需要使用监控。 243 | 244 | 最基本的监控很简单: 245 | 246 | ```JavaScript 247 | $scope.a = 1; 248 | 249 | $scope.$watch("a", function(newValue, oldValue) { 250 | alert(oldValue + " -> " + newValue); 251 | }); 252 | 253 | $scope.changeA = function() { 254 | $scope.a++; 255 | }; 256 | ``` 257 | 258 | 对作用域上的变量添加监控之后,就可以在变更时得到通知了。如果说新赋值的变量跟原先的相同,这个监控就不会被执行。比如说刚才例子中,继续对a赋值为1,不会进入监控函数。 259 | 260 | 以上这种方式可以监控到最直接的赋值,包括各种基本类型,以及复杂类型的引用赋值,比如说下面这个数组被重新赋值了,就可以被监控到: 261 | 262 | ```JavaScript 263 | $scope.arr = [0]; 264 | 265 | $scope.$watch("arr", function(newValue) { 266 | alert("change:" + newValue.join(",")); 267 | }); 268 | 269 | $scope.changeArr = function() { 270 | $scope.arr = [7, 8]; 271 | }; 272 | ``` 273 | 274 | 但这种监控方式只能处理引用相等的判断,对于一些更复杂的监控,需要更细致的处理。比如说,我们有可能需要监控一个数组,但并非监控它的整体赋值,而是监控其元素的变更: 275 | 276 | ```JavaScript 277 | $scope.$watch("arr", function(newValue) { 278 | alert("deep:" + newValue.join(",")); 279 | }, true); 280 | 281 | $scope.addItem = function() { 282 | $scope.arr.push($scope.arr.length); 283 | }; 284 | ``` 285 | 286 | 注意,这里我们在$watch函数中,添加了第三个参数,这个参数用于指示对数据的深层监控,包括数组的子元素和对象的属性等等。 287 | 288 | ### 样式的数据绑定 289 | 290 | 刚才我们提到的例子,都是跟数据同步、数据展示相关,但数据绑定的功能是很强大的,其应用场景取决于我们的想象力。 291 | 292 | 不知道大家有没有遇到过这样的场景,有一个数据列表,点中其中某条,这条就改变样式变成加亮,如果用传统的方式,可能要添加一些事件,然后在其中作一些处理,但使用数据绑定,能够大幅简化代码: 293 | 294 | ```JavaScript 295 | function ListCtrl($scope) { 296 | $scope.items = []; 297 | 298 | for (var i=0; i<10; i++) { 299 | $scope.items.push({ 300 | title:i 301 | }); 302 | } 303 | 304 | $scope.selectedItem = $scope.items[0]; 305 | 306 | $scope.select = function(item) { 307 | $scope.selectedItem = item; 308 | }; 309 | } 310 | ``` 311 | 312 | ```HTML 313 | 318 | ``` 319 | 320 | 在本例中,我们使用了一个循环来迭代数组中的元素,并且使用一个变量selectedItem用于标识选中项,然后关键点在于这个ng-class的表达式,它能够根据当前项是否为选中项,作出一个判断,生成对应的样式名。这是绑定的一个典型应用了,基于它,能把一些之前需要依赖于某些控件的功能用特别简单的方式做出来。 321 | 322 | 除了使用ng-class,还可以使用ng-style来对样式作更细致的控制,比如: 323 | 324 | ```HTML 325 | 326 |
327 | 测试字体大小 328 |
329 | ``` 330 | 331 | ### 状态控制 332 | 333 | 有时候,我们除了控制普通的样式,还有可能要控制某个界面元素的显示隐藏。我们用ng-class或者ng-style当然都是可以控制元素的显示隐藏的,但Angular给我们提供了一种快捷方式,那就是ng-show和ng-hide,它们是相反的,其实只要一个就可以了,提供两个是为了写表达式的方便。 334 | 335 | 利用数据绑定,我们可以很容易实现原有的一些显示隐藏功能。比如说,当列表项有选中的时候,某些按钮出现,当什么都没选的时候,不出现这些按钮。 336 | 337 | 主要的代码部分还是借用上面那个列表,只添加一些相关的东西: 338 | 339 | ```HTML 340 | 341 | 342 | ``` 343 | 344 | 把这个代码放在刚才的列表旁边,位于同一个controller下,点击列表元素,就能看到绑定状态了。 345 | 346 | 有时候,我们也想控制按钮的可点击状态,比如刚才的例子,那两个按钮直接显示隐藏,太突兀了,我们来把它们改成启用和禁用。 347 | 348 | ```HTML 349 | 350 | 351 | ``` 352 | 353 | 同理,如果是输入框,可以用同样的方式,使用ng-readonly来控制其只读状态。 354 | 355 | ### 流程控制 356 | 357 | 除了使用ng-show和ng-hide来控制元素的显示隐藏,还可以使用ng-if,但这个的含义与实现机制都大为不同。所谓的show和hide,意味着DOM元素已经存在,只是控制了是否显示,而if则起到了流程控制的作用,只有符合条件的DOM元素才会被创建,否则不创建。 358 | 359 | 比如下面的例子: 360 | 361 | ```JavaScript 362 | function IfCtrl($scope) { 363 | $scope.condition = 1; 364 | 365 | $scope.change = function() { 366 | $scope.condition = 2; 367 | }; 368 | } 369 | ``` 370 | 371 | ```HTML 372 |
373 | 380 | 381 | 382 |
383 | ``` 384 | 385 | 这个例子初始的时候,创建了三个li,其中一个被隐藏(show 2),当点击按钮,condition变成2,仍然是三个li,其中,if 1没有了,if 2创建出来了,show 1隐藏了,show 2显示了。 386 | 387 | 所以,我们现在看到的是,if的节点是动态创建的。与此类似,我们还可以使用ng-switch指令: 388 | 389 | ```JavaScript 390 | function SwitchCtrl($scope) { 391 | $scope.condition = ""; 392 | 393 | $scope.a = function() { 394 | $scope.condition = "A"; 395 | }; 396 | 397 | $scope.b = function() { 398 | $scope.condition = "B"; 399 | }; 400 | 401 | $scope.c = function() { 402 | $scope.condition = "C"; 403 | }; 404 | } 405 | ``` 406 | 407 | ```HTML 408 |
409 |
410 |
A
411 |
B
412 |
default
413 |
414 | 415 | 416 | 417 |
418 | ``` 419 | 420 | 这个例子跟if基本上是一个意思,只是语法更自然些。 421 | 422 | ### 数据联动 423 | 424 | 在做实际业务的过程中,很容易就碰到数据联动的场景,最典型的例子是省市县的三级联动。很多前端教程或者基础面试题以此为例,综合考察其中所运用到的知识点。 425 | 426 | 如果是用Angular做开发,很可能这个就不成其为一个考点了,因为实现起来非常容易。 427 | 428 | 我们刚才已经实现了一个单级列表,可以借用这段代码,做两个列表,第一个的数据变动,对第二个的数据产生过滤。 429 | 430 | ```JavaScript 431 | function RegionCtrl($scope) { 432 | $scope.provinceArr = ["江苏", "云南"]; 433 | $scope.cityArr = []; 434 | 435 | $scope.$watch("selectedProvince", function(province) { 436 | // 真正有用的代码在这里,实际场景中这里可以是调用后端服务查询的关联数据 437 | switch (province) { 438 | case "江苏": { 439 | $scope.cityArr = ["南京", "苏州"]; 440 | break; 441 | } 442 | case "云南": { 443 | $scope.cityArr = ["昆明", "丽江"]; 444 | break; 445 | } 446 | } 447 | }); 448 | 449 | $scope.selectProvince = function(province) { 450 | $scope.selectedProvince = province; 451 | }; 452 | 453 | $scope.selectCity = function(city) { 454 | $scope.selectedCity = city; 455 | }; 456 | } 457 | ``` 458 | 459 | ```HTML 460 |
461 | 466 | 471 |
472 | ``` 473 | 474 | 这段代码看起来比刚才复杂一些,其实有价值的代码就那个$watch里面的东西。这是什么意思呢?意思是,监控selectedProvince这个变量,只要它改变了,就去查询它可能造成的更新数据,然后剩下的事情就不用我们管了。 475 | 476 | 如果是绑定到下拉框上,代码更简单,因为AngularJS专门作了这种考虑,ng-options就是这样的设置: 477 | 478 | ```HTML 479 | 480 | 481 | ``` 482 | 483 | 从这个例子我们看到,相比于传统前端开发方式那种手动监听事件,手动更新DOM的方式,使用数据绑定做数据联动简直太容易了。如果要把这个例子改造成三级联动,只需对selectedCity也做一个监控就行了。 484 | 485 | ### 一个综合的例子 486 | 487 | 了解了这些细节之后,我们可以把它们结合起来做一个比较实际的综合例子。假设我们在为一家小店创建雇员的管理界面,其中包含一个雇员表格,以及一个可用于添加或编辑雇员的表单。 488 | 489 | 雇员包含如下字段:姓名,年龄,性别,出生地,民族。其中,姓名通过输入框输入字符串,年龄通过输入框输入整数,性别通过点选单选按钮来选择,出生地用两个下拉框选择省份和城市,民族可以选择汉族和少数民族,如果选择了少数民族,可以手动输入民族名称。 490 | 491 | 这个例子恰好能把我们刚才讲的绑定全部用到。我们先来看看有哪些绑定关系: 492 | 493 | - 雇员表格可以选中某行,该行样式会高亮 494 | - 如果选中了某行,其详细数据将会同步到表单上 495 | - 如果点击过新增或修改按钮,当前界面处于编辑中,则表单可输入,否则表单只读 496 | - 修改和删除按钮的可点击状态,取决于表格中是否有选中的行 497 | - 出生地点的省市下拉框存在联动关系 498 | - 民族名称的输入框,其可见性取决于选择了汉族还是少数民族的单选按钮 499 | - 新增修改删除、确定取消,这两组按钮互斥,永远不同时出现,其可见性取决于当前是否正在编辑。 500 | - 确定按钮的可点击状态,取决于当前表单数据是否合法 501 | 502 | 如果想做得精细,还有更多可以使用绑定的地方,不过上面这些已经足够我们把所有知识用一遍了。 503 | 504 | 这个例子的代码就不贴了,可以自行查看。 505 | 506 | ### 数据绑定的拓展运用 507 | 508 | 现在我们学会了数据绑定,可以借助这种特性,完成一些很别致的功能。比如说,如果想在页面上用div模拟一个正弦波,只需要把波形数据生成出来,然后一个绑定就可以完成了。 509 | 510 | ```JavaScript 511 | $scope.staticItems = []; 512 | 513 | for (var i=0; i<720; i++) { 514 | $scope.staticItems.push(Math.ceil(100 * (1 + Math.sin(i * Math.PI / 180)))); 515 | } 516 | ``` 517 | 518 | 如果我们想让这个波形动起来,也很容易,只需要结合一个定时器,动态生成这个波形数据就可以了。为了形成滚动效果,当波形采点数目超过某个值的时候,可以把最初的点逐个拿掉,保持总的数组长度。 519 | 520 | ```JavaScript 521 | $scope.dynamicItems = []; 522 | 523 | var counter = 0; 524 | 525 | function addItem() { 526 | var newItem = Math.ceil(100 * (1 + Math.sin((counter++) * Math.PI / 180))); 527 | 528 | if ($scope.dynamicItems.length > 500) { 529 | $scope.dynamicItems.splice(0, 1); 530 | } 531 | 532 | $scope.dynamicItems.push(newItem); 533 | 534 | $timeout(function () { 535 | addItem(); 536 | }, 10); 537 | } 538 | 539 | addItem(); 540 | ``` 541 | 542 | 这个例子对应的HTML代码如下: 543 | 544 | ```HTML 545 |
546 | 553 |
554 |
555 |
556 |
557 |
558 |
559 |
560 | ``` 561 | 562 | 有时候我们经常看到一些算法可视化的项目,比如把排序算法用可视化的方式展现出来,如果使用AngularJS的数据绑定,实现这种效果可谓易如反掌: 563 | 564 | ```HTML 565 |
566 | 574 | 575 |
576 |
577 |
578 |
579 | ``` 580 | 581 | ```JavaScript 582 | $scope.arr = [2, 4, 5, 63, 4, 5, 55, 2, 4, 43]; 583 | 584 | $scope.sort = function () { 585 | if (!sort($scope.arr)) { 586 | $timeout(function() { 587 | $scope.sort(); 588 | }, 500); 589 | } 590 | }; 591 | 592 | function sort(array) { 593 | // 喵的,写到这个才发现yield是多么好啊 594 | for (var i = 0; i < array.length; i++) { 595 | for (var j = array.length; j > 0; j--) { 596 | if (array[j] < array[j - 1]) { 597 | var temp = array[j - 1]; 598 | array[j - 1] = array[j]; 599 | array[j] = temp; 600 | 601 | return false; 602 | } 603 | } 604 | } 605 | 606 | return true; 607 | } 608 | ``` 609 | 610 | 看,就这么简单,一个冒泡排序算法的可视化过程就写好啦。 611 | 612 | 甚至,AngularJS还允许我们在SVG中使用数据绑定,使用它,做一些小游戏也是很容易的,比如我写了个双人对战的象棋,这里有[演示地址](https://xufei.github.io/ng-chess/chess.html),可以查看源码,是不是很简单? 613 | 614 | ### 小结 615 | 616 | 刚才我们已经看到数据绑定的各种使用场景了,这个东西带给我们的最大好处是什么呢?我们回顾一下之前写Web界面,有一部分时间在写HTML和CSS,一部分时间在写纯逻辑的JavaScript,还有很多时间在把这两者结合起来,比如各种创建或选取DOM,设置属性,添加等等,这些事情都是很机械而繁琐的,数据绑定把这个过程简化了,代码也跟着清晰了。 617 | 618 | 数据绑定是一种思维方式,一切的核心就是数据。数据的变更导致界面的更新,如果我们想要更新界面,只需改变数据即可。 619 | 620 | 佛曰:命由己造,相由心生,世间万物皆是化相,心不动,万物皆不动,心不变,万物皆不变。 621 | 622 | 佛曰:种如是因,收如是果,一切唯心造。 623 | 624 | 本章所涉及的所有Demo,参见[在线演示地址](https://xufei.github.io/ng-tutor/binding.html) 625 | 626 | 演讲幻灯片下载:点[这里](https://xufei.github.io/ng-tutor/slides/binding.pdf) 627 | 628 | -------------------------------------------------------------------------------- /css/bootstrap-theme.min.css: -------------------------------------------------------------------------------- 1 | /*! 2 | * Bootstrap v3.2.0 (http://getbootstrap.com) 3 | * Copyright 2011-2014 Twitter, Inc. 4 | * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) 5 | */.btn-default,.btn-primary,.btn-success,.btn-info,.btn-warning,.btn-danger{text-shadow:0 -1px 0 rgba(0,0,0,.2);-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 1px rgba(0,0,0,.075)}.btn-default:active,.btn-primary:active,.btn-success:active,.btn-info:active,.btn-warning:active,.btn-danger:active,.btn-default.active,.btn-primary.active,.btn-success.active,.btn-info.active,.btn-warning.active,.btn-danger.active{-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125);box-shadow:inset 0 3px 5px rgba(0,0,0,.125)}.btn:active,.btn.active{background-image:none}.btn-default{text-shadow:0 1px 0 #fff;background-image:-webkit-linear-gradient(top,#fff 0,#e0e0e0 100%);background-image:-o-linear-gradient(top,#fff 0,#e0e0e0 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#fff),to(#e0e0e0));background-image:linear-gradient(to bottom,#fff 0,#e0e0e0 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe0e0e0', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#dbdbdb;border-color:#ccc}.btn-default:hover,.btn-default:focus{background-color:#e0e0e0;background-position:0 -15px}.btn-default:active,.btn-default.active{background-color:#e0e0e0;border-color:#dbdbdb}.btn-default:disabled,.btn-default[disabled]{background-color:#e0e0e0;background-image:none}.btn-primary{background-image:-webkit-linear-gradient(top,#428bca 0,#2d6ca2 100%);background-image:-o-linear-gradient(top,#428bca 0,#2d6ca2 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#428bca),to(#2d6ca2));background-image:linear-gradient(to bottom,#428bca 0,#2d6ca2 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff2d6ca2', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#2b669a}.btn-primary:hover,.btn-primary:focus{background-color:#2d6ca2;background-position:0 -15px}.btn-primary:active,.btn-primary.active{background-color:#2d6ca2;border-color:#2b669a}.btn-primary:disabled,.btn-primary[disabled]{background-color:#2d6ca2;background-image:none}.btn-success{background-image:-webkit-linear-gradient(top,#5cb85c 0,#419641 100%);background-image:-o-linear-gradient(top,#5cb85c 0,#419641 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#5cb85c),to(#419641));background-image:linear-gradient(to bottom,#5cb85c 0,#419641 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff419641', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#3e8f3e}.btn-success:hover,.btn-success:focus{background-color:#419641;background-position:0 -15px}.btn-success:active,.btn-success.active{background-color:#419641;border-color:#3e8f3e}.btn-success:disabled,.btn-success[disabled]{background-color:#419641;background-image:none}.btn-info{background-image:-webkit-linear-gradient(top,#5bc0de 0,#2aabd2 100%);background-image:-o-linear-gradient(top,#5bc0de 0,#2aabd2 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#5bc0de),to(#2aabd2));background-image:linear-gradient(to bottom,#5bc0de 0,#2aabd2 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff2aabd2', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#28a4c9}.btn-info:hover,.btn-info:focus{background-color:#2aabd2;background-position:0 -15px}.btn-info:active,.btn-info.active{background-color:#2aabd2;border-color:#28a4c9}.btn-info:disabled,.btn-info[disabled]{background-color:#2aabd2;background-image:none}.btn-warning{background-image:-webkit-linear-gradient(top,#f0ad4e 0,#eb9316 100%);background-image:-o-linear-gradient(top,#f0ad4e 0,#eb9316 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f0ad4e),to(#eb9316));background-image:linear-gradient(to bottom,#f0ad4e 0,#eb9316 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffeb9316', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#e38d13}.btn-warning:hover,.btn-warning:focus{background-color:#eb9316;background-position:0 -15px}.btn-warning:active,.btn-warning.active{background-color:#eb9316;border-color:#e38d13}.btn-warning:disabled,.btn-warning[disabled]{background-color:#eb9316;background-image:none}.btn-danger{background-image:-webkit-linear-gradient(top,#d9534f 0,#c12e2a 100%);background-image:-o-linear-gradient(top,#d9534f 0,#c12e2a 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#d9534f),to(#c12e2a));background-image:linear-gradient(to bottom,#d9534f 0,#c12e2a 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc12e2a', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#b92c28}.btn-danger:hover,.btn-danger:focus{background-color:#c12e2a;background-position:0 -15px}.btn-danger:active,.btn-danger.active{background-color:#c12e2a;border-color:#b92c28}.btn-danger:disabled,.btn-danger[disabled]{background-color:#c12e2a;background-image:none}.thumbnail,.img-thumbnail{-webkit-box-shadow:0 1px 2px rgba(0,0,0,.075);box-shadow:0 1px 2px rgba(0,0,0,.075)}.dropdown-menu>li>a:hover,.dropdown-menu>li>a:focus{background-color:#e8e8e8;background-image:-webkit-linear-gradient(top,#f5f5f5 0,#e8e8e8 100%);background-image:-o-linear-gradient(top,#f5f5f5 0,#e8e8e8 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f5f5f5),to(#e8e8e8));background-image:linear-gradient(to bottom,#f5f5f5 0,#e8e8e8 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0);background-repeat:repeat-x}.dropdown-menu>.active>a,.dropdown-menu>.active>a:hover,.dropdown-menu>.active>a:focus{background-color:#357ebd;background-image:-webkit-linear-gradient(top,#428bca 0,#357ebd 100%);background-image:-o-linear-gradient(top,#428bca 0,#357ebd 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#428bca),to(#357ebd));background-image:linear-gradient(to bottom,#428bca 0,#357ebd 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff357ebd', GradientType=0);background-repeat:repeat-x}.navbar-default{background-image:-webkit-linear-gradient(top,#fff 0,#f8f8f8 100%);background-image:-o-linear-gradient(top,#fff 0,#f8f8f8 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#fff),to(#f8f8f8));background-image:linear-gradient(to bottom,#fff 0,#f8f8f8 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff8f8f8', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-radius:4px;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 5px rgba(0,0,0,.075);box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 5px rgba(0,0,0,.075)}.navbar-default .navbar-nav>.active>a{background-image:-webkit-linear-gradient(top,#ebebeb 0,#f3f3f3 100%);background-image:-o-linear-gradient(top,#ebebeb 0,#f3f3f3 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#ebebeb),to(#f3f3f3));background-image:linear-gradient(to bottom,#ebebeb 0,#f3f3f3 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffebebeb', endColorstr='#fff3f3f3', GradientType=0);background-repeat:repeat-x;-webkit-box-shadow:inset 0 3px 9px rgba(0,0,0,.075);box-shadow:inset 0 3px 9px rgba(0,0,0,.075)}.navbar-brand,.navbar-nav>li>a{text-shadow:0 1px 0 rgba(255,255,255,.25)}.navbar-inverse{background-image:-webkit-linear-gradient(top,#3c3c3c 0,#222 100%);background-image:-o-linear-gradient(top,#3c3c3c 0,#222 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#3c3c3c),to(#222));background-image:linear-gradient(to bottom,#3c3c3c 0,#222 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff3c3c3c', endColorstr='#ff222222', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x}.navbar-inverse .navbar-nav>.active>a{background-image:-webkit-linear-gradient(top,#222 0,#282828 100%);background-image:-o-linear-gradient(top,#222 0,#282828 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#222),to(#282828));background-image:linear-gradient(to bottom,#222 0,#282828 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff222222', endColorstr='#ff282828', GradientType=0);background-repeat:repeat-x;-webkit-box-shadow:inset 0 3px 9px rgba(0,0,0,.25);box-shadow:inset 0 3px 9px rgba(0,0,0,.25)}.navbar-inverse .navbar-brand,.navbar-inverse .navbar-nav>li>a{text-shadow:0 -1px 0 rgba(0,0,0,.25)}.navbar-static-top,.navbar-fixed-top,.navbar-fixed-bottom{border-radius:0}.alert{text-shadow:0 1px 0 rgba(255,255,255,.2);-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.25),0 1px 2px rgba(0,0,0,.05);box-shadow:inset 0 1px 0 rgba(255,255,255,.25),0 1px 2px rgba(0,0,0,.05)}.alert-success{background-image:-webkit-linear-gradient(top,#dff0d8 0,#c8e5bc 100%);background-image:-o-linear-gradient(top,#dff0d8 0,#c8e5bc 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#dff0d8),to(#c8e5bc));background-image:linear-gradient(to bottom,#dff0d8 0,#c8e5bc 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffc8e5bc', GradientType=0);background-repeat:repeat-x;border-color:#b2dba1}.alert-info{background-image:-webkit-linear-gradient(top,#d9edf7 0,#b9def0 100%);background-image:-o-linear-gradient(top,#d9edf7 0,#b9def0 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#d9edf7),to(#b9def0));background-image:linear-gradient(to bottom,#d9edf7 0,#b9def0 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffb9def0', GradientType=0);background-repeat:repeat-x;border-color:#9acfea}.alert-warning{background-image:-webkit-linear-gradient(top,#fcf8e3 0,#f8efc0 100%);background-image:-o-linear-gradient(top,#fcf8e3 0,#f8efc0 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#fcf8e3),to(#f8efc0));background-image:linear-gradient(to bottom,#fcf8e3 0,#f8efc0 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fff8efc0', GradientType=0);background-repeat:repeat-x;border-color:#f5e79e}.alert-danger{background-image:-webkit-linear-gradient(top,#f2dede 0,#e7c3c3 100%);background-image:-o-linear-gradient(top,#f2dede 0,#e7c3c3 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f2dede),to(#e7c3c3));background-image:linear-gradient(to bottom,#f2dede 0,#e7c3c3 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffe7c3c3', GradientType=0);background-repeat:repeat-x;border-color:#dca7a7}.progress{background-image:-webkit-linear-gradient(top,#ebebeb 0,#f5f5f5 100%);background-image:-o-linear-gradient(top,#ebebeb 0,#f5f5f5 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#ebebeb),to(#f5f5f5));background-image:linear-gradient(to bottom,#ebebeb 0,#f5f5f5 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffebebeb', endColorstr='#fff5f5f5', GradientType=0);background-repeat:repeat-x}.progress-bar{background-image:-webkit-linear-gradient(top,#428bca 0,#3071a9 100%);background-image:-o-linear-gradient(top,#428bca 0,#3071a9 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#428bca),to(#3071a9));background-image:linear-gradient(to bottom,#428bca 0,#3071a9 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff3071a9', GradientType=0);background-repeat:repeat-x}.progress-bar-success{background-image:-webkit-linear-gradient(top,#5cb85c 0,#449d44 100%);background-image:-o-linear-gradient(top,#5cb85c 0,#449d44 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#5cb85c),to(#449d44));background-image:linear-gradient(to bottom,#5cb85c 0,#449d44 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff449d44', GradientType=0);background-repeat:repeat-x}.progress-bar-info{background-image:-webkit-linear-gradient(top,#5bc0de 0,#31b0d5 100%);background-image:-o-linear-gradient(top,#5bc0de 0,#31b0d5 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#5bc0de),to(#31b0d5));background-image:linear-gradient(to bottom,#5bc0de 0,#31b0d5 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff31b0d5', GradientType=0);background-repeat:repeat-x}.progress-bar-warning{background-image:-webkit-linear-gradient(top,#f0ad4e 0,#ec971f 100%);background-image:-o-linear-gradient(top,#f0ad4e 0,#ec971f 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f0ad4e),to(#ec971f));background-image:linear-gradient(to bottom,#f0ad4e 0,#ec971f 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffec971f', GradientType=0);background-repeat:repeat-x}.progress-bar-danger{background-image:-webkit-linear-gradient(top,#d9534f 0,#c9302c 100%);background-image:-o-linear-gradient(top,#d9534f 0,#c9302c 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#d9534f),to(#c9302c));background-image:linear-gradient(to bottom,#d9534f 0,#c9302c 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc9302c', GradientType=0);background-repeat:repeat-x}.progress-bar-striped{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)}.list-group{border-radius:4px;-webkit-box-shadow:0 1px 2px rgba(0,0,0,.075);box-shadow:0 1px 2px rgba(0,0,0,.075)}.list-group-item.active,.list-group-item.active:hover,.list-group-item.active:focus{text-shadow:0 -1px 0 #3071a9;background-image:-webkit-linear-gradient(top,#428bca 0,#3278b3 100%);background-image:-o-linear-gradient(top,#428bca 0,#3278b3 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#428bca),to(#3278b3));background-image:linear-gradient(to bottom,#428bca 0,#3278b3 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff3278b3', GradientType=0);background-repeat:repeat-x;border-color:#3278b3}.panel{-webkit-box-shadow:0 1px 2px rgba(0,0,0,.05);box-shadow:0 1px 2px rgba(0,0,0,.05)}.panel-default>.panel-heading{background-image:-webkit-linear-gradient(top,#f5f5f5 0,#e8e8e8 100%);background-image:-o-linear-gradient(top,#f5f5f5 0,#e8e8e8 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f5f5f5),to(#e8e8e8));background-image:linear-gradient(to bottom,#f5f5f5 0,#e8e8e8 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0);background-repeat:repeat-x}.panel-primary>.panel-heading{background-image:-webkit-linear-gradient(top,#428bca 0,#357ebd 100%);background-image:-o-linear-gradient(top,#428bca 0,#357ebd 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#428bca),to(#357ebd));background-image:linear-gradient(to bottom,#428bca 0,#357ebd 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff357ebd', GradientType=0);background-repeat:repeat-x}.panel-success>.panel-heading{background-image:-webkit-linear-gradient(top,#dff0d8 0,#d0e9c6 100%);background-image:-o-linear-gradient(top,#dff0d8 0,#d0e9c6 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#dff0d8),to(#d0e9c6));background-image:linear-gradient(to bottom,#dff0d8 0,#d0e9c6 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffd0e9c6', GradientType=0);background-repeat:repeat-x}.panel-info>.panel-heading{background-image:-webkit-linear-gradient(top,#d9edf7 0,#c4e3f3 100%);background-image:-o-linear-gradient(top,#d9edf7 0,#c4e3f3 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#d9edf7),to(#c4e3f3));background-image:linear-gradient(to bottom,#d9edf7 0,#c4e3f3 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffc4e3f3', GradientType=0);background-repeat:repeat-x}.panel-warning>.panel-heading{background-image:-webkit-linear-gradient(top,#fcf8e3 0,#faf2cc 100%);background-image:-o-linear-gradient(top,#fcf8e3 0,#faf2cc 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#fcf8e3),to(#faf2cc));background-image:linear-gradient(to bottom,#fcf8e3 0,#faf2cc 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fffaf2cc', GradientType=0);background-repeat:repeat-x}.panel-danger>.panel-heading{background-image:-webkit-linear-gradient(top,#f2dede 0,#ebcccc 100%);background-image:-o-linear-gradient(top,#f2dede 0,#ebcccc 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f2dede),to(#ebcccc));background-image:linear-gradient(to bottom,#f2dede 0,#ebcccc 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffebcccc', GradientType=0);background-repeat:repeat-x}.well{background-image:-webkit-linear-gradient(top,#e8e8e8 0,#f5f5f5 100%);background-image:-o-linear-gradient(top,#e8e8e8 0,#f5f5f5 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#e8e8e8),to(#f5f5f5));background-image:linear-gradient(to bottom,#e8e8e8 0,#f5f5f5 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffe8e8e8', endColorstr='#fff5f5f5', GradientType=0);background-repeat:repeat-x;border-color:#dcdcdc;-webkit-box-shadow:inset 0 1px 3px rgba(0,0,0,.05),0 1px 0 rgba(255,255,255,.1);box-shadow:inset 0 1px 3px rgba(0,0,0,.05),0 1px 0 rgba(255,255,255,.1)} -------------------------------------------------------------------------------- /css/bootstrap-theme.css.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"bootstrap-theme.css","sources":["less/theme.less","less/mixins/vendor-prefixes.less","bootstrap-theme.css","less/mixins/gradients.less","less/mixins/reset-filter.less"],"names":[],"mappings":"AAeA;;;;;;EAME,0CAAA;EC+CA,6FAAA;EACQ,qFAAA;EC5DT;AFiBC;;;;;;;;;;;;EC0CA,0DAAA;EACQ,kDAAA;EC7CT;AFqCC;;EAEE,wBAAA;EEnCH;AFwCD;EG/CI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EAEA,wHAAA;ECnBF,qEAAA;EJ8BA,6BAAA;EACA,uBAAA;EA+B2C,2BAAA;EAA2B,oBAAA;EE7BvE;AFAC;;EAEE,2BAAA;EACA,8BAAA;EEEH;AFCC;;EAEE,2BAAA;EACA,uBAAA;EECH;AFEC;;EAEE,2BAAA;EACA,wBAAA;EEAH;AFeD;EGhDI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EAEA,wHAAA;ECnBF,qEAAA;EJ8BA,6BAAA;EACA,uBAAA;EE0BD;AFxBC;;EAEE,2BAAA;EACA,8BAAA;EE0BH;AFvBC;;EAEE,2BAAA;EACA,uBAAA;EEyBH;AFtBC;;EAEE,2BAAA;EACA,wBAAA;EEwBH;AFRD;EGjDI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EAEA,wHAAA;ECnBF,qEAAA;EJ8BA,6BAAA;EACA,uBAAA;EEkDD;AFhDC;;EAEE,2BAAA;EACA,8BAAA;EEkDH;AF/CC;;EAEE,2BAAA;EACA,uBAAA;EEiDH;AF9CC;;EAEE,2BAAA;EACA,wBAAA;EEgDH;AF/BD;EGlDI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EAEA,wHAAA;ECnBF,qEAAA;EJ8BA,6BAAA;EACA,uBAAA;EE0ED;AFxEC;;EAEE,2BAAA;EACA,8BAAA;EE0EH;AFvEC;;EAEE,2BAAA;EACA,uBAAA;EEyEH;AFtEC;;EAEE,2BAAA;EACA,wBAAA;EEwEH;AFtDD;EGnDI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EAEA,wHAAA;ECnBF,qEAAA;EJ8BA,6BAAA;EACA,uBAAA;EEkGD;AFhGC;;EAEE,2BAAA;EACA,8BAAA;EEkGH;AF/FC;;EAEE,2BAAA;EACA,uBAAA;EEiGH;AF9FC;;EAEE,2BAAA;EACA,wBAAA;EEgGH;AF7ED;EGpDI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EAEA,wHAAA;ECnBF,qEAAA;EJ8BA,6BAAA;EACA,uBAAA;EE0HD;AFxHC;;EAEE,2BAAA;EACA,8BAAA;EE0HH;AFvHC;;EAEE,2BAAA;EACA,uBAAA;EEyHH;AFtHC;;EAEE,2BAAA;EACA,wBAAA;EEwHH;AF7FD;;ECbE,oDAAA;EACQ,4CAAA;EC8GT;AFvFD;;EGvEI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EACA,6BAAA;EACA,wHAAA;EHsEF,2BAAA;EE6FD;AF3FD;;;EG5EI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EACA,6BAAA;EACA,wHAAA;EH4EF,2BAAA;EEiGD;AFvFD;EG1FI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EACA,6BAAA;EACA,wHAAA;ECnBF,qEAAA;EJ4GA,oBAAA;EC9CA,6FAAA;EACQ,qFAAA;EC4IT;AFlGD;EG1FI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EACA,6BAAA;EACA,wHAAA;EF2CF,0DAAA;EACQ,kDAAA;ECqJT;AF/FD;;EAEE,gDAAA;EEiGD;AF7FD;EG5GI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EACA,6BAAA;EACA,wHAAA;ECnBF,qEAAA;EFgOD;AFrGD;EG5GI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EACA,6BAAA;EACA,wHAAA;EF2CF,yDAAA;EACQ,iDAAA;EC0KT;AF9GD;;EAWI,2CAAA;EEuGH;AFlGD;;;EAGE,kBAAA;EEoGD;AF1FD;EACE,+CAAA;EC3FA,4FAAA;EACQ,oFAAA;ECwLT;AFlFD;EGtJI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EACA,6BAAA;EACA,wHAAA;EH8IF,uBAAA;EE8FD;AFzFD;EGvJI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EACA,6BAAA;EACA,wHAAA;EH8IF,uBAAA;EEsGD;AFhGD;EGxJI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EACA,6BAAA;EACA,wHAAA;EH8IF,uBAAA;EE8GD;AFvGD;EGzJI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EACA,6BAAA;EACA,wHAAA;EH8IF,uBAAA;EEsHD;AFtGD;EGlKI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EACA,6BAAA;EACA,wHAAA;ED2QH;AFnGD;EG5KI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EACA,6BAAA;EACA,wHAAA;EDkRH;AFzGD;EG7KI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EACA,6BAAA;EACA,wHAAA;EDyRH;AF/GD;EG9KI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EACA,6BAAA;EACA,wHAAA;EDgSH;AFrHD;EG/KI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EACA,6BAAA;EACA,wHAAA;EDuSH;AF3HD;EGhLI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EACA,6BAAA;EACA,wHAAA;ED8SH;AF9HD;EGnJI,+MAAA;EACA,0MAAA;EACA,uMAAA;EDoRH;AF1HD;EACE,oBAAA;EC/IA,oDAAA;EACQ,4CAAA;EC4QT;AF3HD;;;EAGE,+BAAA;EGpME,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EACA,6BAAA;EACA,wHAAA;EHkMF,uBAAA;EEiID;AFvHD;ECjKE,mDAAA;EACQ,2CAAA;EC2RT;AFjHD;EG1NI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EACA,6BAAA;EACA,wHAAA;ED8UH;AFvHD;EG3NI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EACA,6BAAA;EACA,wHAAA;EDqVH;AF7HD;EG5NI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EACA,6BAAA;EACA,wHAAA;ED4VH;AFnID;EG7NI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EACA,6BAAA;EACA,wHAAA;EDmWH;AFzID;EG9NI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EACA,6BAAA;EACA,wHAAA;ED0WH;AF/ID;EG/NI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EACA,6BAAA;EACA,wHAAA;EDiXH;AF9ID;EGvOI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EACA,6BAAA;EACA,wHAAA;EHqOF,uBAAA;EC1LA,2FAAA;EACQ,mFAAA;EC+UT","sourcesContent":["\n//\n// Load core variables and mixins\n// --------------------------------------------------\n\n@import \"variables.less\";\n@import \"mixins.less\";\n\n\n\n//\n// Buttons\n// --------------------------------------------------\n\n// Common styles\n.btn-default,\n.btn-primary,\n.btn-success,\n.btn-info,\n.btn-warning,\n.btn-danger {\n text-shadow: 0 -1px 0 rgba(0,0,0,.2);\n @shadow: inset 0 1px 0 rgba(255,255,255,.15), 0 1px 1px rgba(0,0,0,.075);\n .box-shadow(@shadow);\n\n // Reset the shadow\n &:active,\n &.active {\n .box-shadow(inset 0 3px 5px rgba(0,0,0,.125));\n }\n}\n\n// Mixin for generating new styles\n.btn-styles(@btn-color: #555) {\n #gradient > .vertical(@start-color: @btn-color; @end-color: darken(@btn-color, 12%));\n .reset-filter(); // Disable gradients for IE9 because filter bleeds through rounded corners\n background-repeat: repeat-x;\n border-color: darken(@btn-color, 14%);\n\n &:hover,\n &:focus {\n background-color: darken(@btn-color, 12%);\n background-position: 0 -15px;\n }\n\n &:active,\n &.active {\n background-color: darken(@btn-color, 12%);\n border-color: darken(@btn-color, 14%);\n }\n\n &:disabled,\n &[disabled] {\n background-color: darken(@btn-color, 12%);\n background-image: none;\n }\n}\n\n// Common styles\n.btn {\n // Remove the gradient for the pressed/active state\n &:active,\n &.active {\n background-image: none;\n }\n}\n\n// Apply the mixin to the buttons\n.btn-default { .btn-styles(@btn-default-bg); text-shadow: 0 1px 0 #fff; border-color: #ccc; }\n.btn-primary { .btn-styles(@btn-primary-bg); }\n.btn-success { .btn-styles(@btn-success-bg); }\n.btn-info { .btn-styles(@btn-info-bg); }\n.btn-warning { .btn-styles(@btn-warning-bg); }\n.btn-danger { .btn-styles(@btn-danger-bg); }\n\n\n\n//\n// Images\n// --------------------------------------------------\n\n.thumbnail,\n.img-thumbnail {\n .box-shadow(0 1px 2px rgba(0,0,0,.075));\n}\n\n\n\n//\n// Dropdowns\n// --------------------------------------------------\n\n.dropdown-menu > li > a:hover,\n.dropdown-menu > li > a:focus {\n #gradient > .vertical(@start-color: @dropdown-link-hover-bg; @end-color: darken(@dropdown-link-hover-bg, 5%));\n background-color: darken(@dropdown-link-hover-bg, 5%);\n}\n.dropdown-menu > .active > a,\n.dropdown-menu > .active > a:hover,\n.dropdown-menu > .active > a:focus {\n #gradient > .vertical(@start-color: @dropdown-link-active-bg; @end-color: darken(@dropdown-link-active-bg, 5%));\n background-color: darken(@dropdown-link-active-bg, 5%);\n}\n\n\n\n//\n// Navbar\n// --------------------------------------------------\n\n// Default navbar\n.navbar-default {\n #gradient > .vertical(@start-color: lighten(@navbar-default-bg, 10%); @end-color: @navbar-default-bg);\n .reset-filter(); // Remove gradient in IE<10 to fix bug where dropdowns don't get triggered\n border-radius: @navbar-border-radius;\n @shadow: inset 0 1px 0 rgba(255,255,255,.15), 0 1px 5px rgba(0,0,0,.075);\n .box-shadow(@shadow);\n\n .navbar-nav > .active > a {\n #gradient > .vertical(@start-color: darken(@navbar-default-bg, 5%); @end-color: darken(@navbar-default-bg, 2%));\n .box-shadow(inset 0 3px 9px rgba(0,0,0,.075));\n }\n}\n.navbar-brand,\n.navbar-nav > li > a {\n text-shadow: 0 1px 0 rgba(255,255,255,.25);\n}\n\n// Inverted navbar\n.navbar-inverse {\n #gradient > .vertical(@start-color: lighten(@navbar-inverse-bg, 10%); @end-color: @navbar-inverse-bg);\n .reset-filter(); // Remove gradient in IE<10 to fix bug where dropdowns don't get triggered\n\n .navbar-nav > .active > a {\n #gradient > .vertical(@start-color: @navbar-inverse-bg; @end-color: lighten(@navbar-inverse-bg, 2.5%));\n .box-shadow(inset 0 3px 9px rgba(0,0,0,.25));\n }\n\n .navbar-brand,\n .navbar-nav > li > a {\n text-shadow: 0 -1px 0 rgba(0,0,0,.25);\n }\n}\n\n// Undo rounded corners in static and fixed navbars\n.navbar-static-top,\n.navbar-fixed-top,\n.navbar-fixed-bottom {\n border-radius: 0;\n}\n\n\n\n//\n// Alerts\n// --------------------------------------------------\n\n// Common styles\n.alert {\n text-shadow: 0 1px 0 rgba(255,255,255,.2);\n @shadow: inset 0 1px 0 rgba(255,255,255,.25), 0 1px 2px rgba(0,0,0,.05);\n .box-shadow(@shadow);\n}\n\n// Mixin for generating new styles\n.alert-styles(@color) {\n #gradient > .vertical(@start-color: @color; @end-color: darken(@color, 7.5%));\n border-color: darken(@color, 15%);\n}\n\n// Apply the mixin to the alerts\n.alert-success { .alert-styles(@alert-success-bg); }\n.alert-info { .alert-styles(@alert-info-bg); }\n.alert-warning { .alert-styles(@alert-warning-bg); }\n.alert-danger { .alert-styles(@alert-danger-bg); }\n\n\n\n//\n// Progress bars\n// --------------------------------------------------\n\n// Give the progress background some depth\n.progress {\n #gradient > .vertical(@start-color: darken(@progress-bg, 4%); @end-color: @progress-bg)\n}\n\n// Mixin for generating new styles\n.progress-bar-styles(@color) {\n #gradient > .vertical(@start-color: @color; @end-color: darken(@color, 10%));\n}\n\n// Apply the mixin to the progress bars\n.progress-bar { .progress-bar-styles(@progress-bar-bg); }\n.progress-bar-success { .progress-bar-styles(@progress-bar-success-bg); }\n.progress-bar-info { .progress-bar-styles(@progress-bar-info-bg); }\n.progress-bar-warning { .progress-bar-styles(@progress-bar-warning-bg); }\n.progress-bar-danger { .progress-bar-styles(@progress-bar-danger-bg); }\n\n// Reset the striped class because our mixins don't do multiple gradients and\n// the above custom styles override the new `.progress-bar-striped` in v3.2.0.\n.progress-bar-striped {\n #gradient > .striped();\n}\n\n\n//\n// List groups\n// --------------------------------------------------\n\n.list-group {\n border-radius: @border-radius-base;\n .box-shadow(0 1px 2px rgba(0,0,0,.075));\n}\n.list-group-item.active,\n.list-group-item.active:hover,\n.list-group-item.active:focus {\n text-shadow: 0 -1px 0 darken(@list-group-active-bg, 10%);\n #gradient > .vertical(@start-color: @list-group-active-bg; @end-color: darken(@list-group-active-bg, 7.5%));\n border-color: darken(@list-group-active-border, 7.5%);\n}\n\n\n\n//\n// Panels\n// --------------------------------------------------\n\n// Common styles\n.panel {\n .box-shadow(0 1px 2px rgba(0,0,0,.05));\n}\n\n// Mixin for generating new styles\n.panel-heading-styles(@color) {\n #gradient > .vertical(@start-color: @color; @end-color: darken(@color, 5%));\n}\n\n// Apply the mixin to the panel headings only\n.panel-default > .panel-heading { .panel-heading-styles(@panel-default-heading-bg); }\n.panel-primary > .panel-heading { .panel-heading-styles(@panel-primary-heading-bg); }\n.panel-success > .panel-heading { .panel-heading-styles(@panel-success-heading-bg); }\n.panel-info > .panel-heading { .panel-heading-styles(@panel-info-heading-bg); }\n.panel-warning > .panel-heading { .panel-heading-styles(@panel-warning-heading-bg); }\n.panel-danger > .panel-heading { .panel-heading-styles(@panel-danger-heading-bg); }\n\n\n\n//\n// Wells\n// --------------------------------------------------\n\n.well {\n #gradient > .vertical(@start-color: darken(@well-bg, 5%); @end-color: @well-bg);\n border-color: darken(@well-bg, 10%);\n @shadow: inset 0 1px 3px rgba(0,0,0,.05), 0 1px 0 rgba(255,255,255,.1);\n .box-shadow(@shadow);\n}\n","// Vendor Prefixes\n//\n// All vendor mixins are deprecated as of v3.2.0 due to the introduction of\n// Autoprefixer in our Gruntfile. They will be removed in v4.\n\n// - Animations\n// - Backface visibility\n// - Box shadow\n// - Box sizing\n// - Content columns\n// - Hyphens\n// - Placeholder text\n// - Transformations\n// - Transitions\n// - User Select\n\n\n// Animations\n.animation(@animation) {\n -webkit-animation: @animation;\n -o-animation: @animation;\n animation: @animation;\n}\n.animation-name(@name) {\n -webkit-animation-name: @name;\n animation-name: @name;\n}\n.animation-duration(@duration) {\n -webkit-animation-duration: @duration;\n animation-duration: @duration;\n}\n.animation-timing-function(@timing-function) {\n -webkit-animation-timing-function: @timing-function;\n animation-timing-function: @timing-function;\n}\n.animation-delay(@delay) {\n -webkit-animation-delay: @delay;\n animation-delay: @delay;\n}\n.animation-iteration-count(@iteration-count) {\n -webkit-animation-iteration-count: @iteration-count;\n animation-iteration-count: @iteration-count;\n}\n.animation-direction(@direction) {\n -webkit-animation-direction: @direction;\n animation-direction: @direction;\n}\n.animation-fill-mode(@fill-mode) {\n -webkit-animation-fill-mode: @fill-mode;\n animation-fill-mode: @fill-mode;\n}\n\n// Backface visibility\n// Prevent browsers from flickering when using CSS 3D transforms.\n// Default value is `visible`, but can be changed to `hidden`\n\n.backface-visibility(@visibility){\n -webkit-backface-visibility: @visibility;\n -moz-backface-visibility: @visibility;\n backface-visibility: @visibility;\n}\n\n// Drop shadows\n//\n// Note: Deprecated `.box-shadow()` as of v3.1.0 since all of Bootstrap's\n// supported browsers that have box shadow capabilities now support it.\n\n.box-shadow(@shadow) {\n -webkit-box-shadow: @shadow; // iOS <4.3 & Android <4.1\n box-shadow: @shadow;\n}\n\n// Box sizing\n.box-sizing(@boxmodel) {\n -webkit-box-sizing: @boxmodel;\n -moz-box-sizing: @boxmodel;\n box-sizing: @boxmodel;\n}\n\n// CSS3 Content Columns\n.content-columns(@column-count; @column-gap: @grid-gutter-width) {\n -webkit-column-count: @column-count;\n -moz-column-count: @column-count;\n column-count: @column-count;\n -webkit-column-gap: @column-gap;\n -moz-column-gap: @column-gap;\n column-gap: @column-gap;\n}\n\n// Optional hyphenation\n.hyphens(@mode: auto) {\n word-wrap: break-word;\n -webkit-hyphens: @mode;\n -moz-hyphens: @mode;\n -ms-hyphens: @mode; // IE10+\n -o-hyphens: @mode;\n hyphens: @mode;\n}\n\n// Placeholder text\n.placeholder(@color: @input-color-placeholder) {\n &::-moz-placeholder { color: @color; // Firefox\n opacity: 1; } // See https://github.com/twbs/bootstrap/pull/11526\n &:-ms-input-placeholder { color: @color; } // Internet Explorer 10+\n &::-webkit-input-placeholder { color: @color; } // Safari and Chrome\n}\n\n// Transformations\n.scale(@ratio) {\n -webkit-transform: scale(@ratio);\n -ms-transform: scale(@ratio); // IE9 only\n -o-transform: scale(@ratio);\n transform: scale(@ratio);\n}\n.scale(@ratioX; @ratioY) {\n -webkit-transform: scale(@ratioX, @ratioY);\n -ms-transform: scale(@ratioX, @ratioY); // IE9 only\n -o-transform: scale(@ratioX, @ratioY);\n transform: scale(@ratioX, @ratioY);\n}\n.scaleX(@ratio) {\n -webkit-transform: scaleX(@ratio);\n -ms-transform: scaleX(@ratio); // IE9 only\n -o-transform: scaleX(@ratio);\n transform: scaleX(@ratio);\n}\n.scaleY(@ratio) {\n -webkit-transform: scaleY(@ratio);\n -ms-transform: scaleY(@ratio); // IE9 only\n -o-transform: scaleY(@ratio);\n transform: scaleY(@ratio);\n}\n.skew(@x; @y) {\n -webkit-transform: skewX(@x) skewY(@y);\n -ms-transform: skewX(@x) skewY(@y); // See https://github.com/twbs/bootstrap/issues/4885; IE9+\n -o-transform: skewX(@x) skewY(@y);\n transform: skewX(@x) skewY(@y);\n}\n.translate(@x; @y) {\n -webkit-transform: translate(@x, @y);\n -ms-transform: translate(@x, @y); // IE9 only\n -o-transform: translate(@x, @y);\n transform: translate(@x, @y);\n}\n.translate3d(@x; @y; @z) {\n -webkit-transform: translate3d(@x, @y, @z);\n transform: translate3d(@x, @y, @z);\n}\n.rotate(@degrees) {\n -webkit-transform: rotate(@degrees);\n -ms-transform: rotate(@degrees); // IE9 only\n -o-transform: rotate(@degrees);\n transform: rotate(@degrees);\n}\n.rotateX(@degrees) {\n -webkit-transform: rotateX(@degrees);\n -ms-transform: rotateX(@degrees); // IE9 only\n -o-transform: rotateX(@degrees);\n transform: rotateX(@degrees);\n}\n.rotateY(@degrees) {\n -webkit-transform: rotateY(@degrees);\n -ms-transform: rotateY(@degrees); // IE9 only\n -o-transform: rotateY(@degrees);\n transform: rotateY(@degrees);\n}\n.perspective(@perspective) {\n -webkit-perspective: @perspective;\n -moz-perspective: @perspective;\n perspective: @perspective;\n}\n.perspective-origin(@perspective) {\n -webkit-perspective-origin: @perspective;\n -moz-perspective-origin: @perspective;\n perspective-origin: @perspective;\n}\n.transform-origin(@origin) {\n -webkit-transform-origin: @origin;\n -moz-transform-origin: @origin;\n -ms-transform-origin: @origin; // IE9 only\n transform-origin: @origin;\n}\n\n\n// Transitions\n\n.transition(@transition) {\n -webkit-transition: @transition;\n -o-transition: @transition;\n transition: @transition;\n}\n.transition-property(@transition-property) {\n -webkit-transition-property: @transition-property;\n transition-property: @transition-property;\n}\n.transition-delay(@transition-delay) {\n -webkit-transition-delay: @transition-delay;\n transition-delay: @transition-delay;\n}\n.transition-duration(@transition-duration) {\n -webkit-transition-duration: @transition-duration;\n transition-duration: @transition-duration;\n}\n.transition-timing-function(@timing-function) {\n -webkit-transition-timing-function: @timing-function;\n transition-timing-function: @timing-function;\n}\n.transition-transform(@transition) {\n -webkit-transition: -webkit-transform @transition;\n -moz-transition: -moz-transform @transition;\n -o-transition: -o-transform @transition;\n transition: transform @transition;\n}\n\n\n// User select\n// For selecting text on the page\n\n.user-select(@select) {\n -webkit-user-select: @select;\n -moz-user-select: @select;\n -ms-user-select: @select; // IE10+\n user-select: @select;\n}\n",null,"// Gradients\n\n#gradient {\n\n // Horizontal gradient, from left to right\n //\n // Creates two color stops, start and end, by specifying a color and position for each color stop.\n // Color stops are not available in IE9 and below.\n .horizontal(@start-color: #555; @end-color: #333; @start-percent: 0%; @end-percent: 100%) {\n background-image: -webkit-linear-gradient(left, @start-color @start-percent, @end-color @end-percent); // Safari 5.1-6, Chrome 10+\n background-image: -o-linear-gradient(left, @start-color @start-percent, @end-color @end-percent); // Opera 12\n background-image: linear-gradient(to right, @start-color @start-percent, @end-color @end-percent); // Standard, IE10, Firefox 16+, Opera 12.10+, Safari 7+, Chrome 26+\n background-repeat: repeat-x;\n filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=1)\",argb(@start-color),argb(@end-color))); // IE9 and down\n }\n\n // Vertical gradient, from top to bottom\n //\n // Creates two color stops, start and end, by specifying a color and position for each color stop.\n // Color stops are not available in IE9 and below.\n .vertical(@start-color: #555; @end-color: #333; @start-percent: 0%; @end-percent: 100%) {\n background-image: -webkit-linear-gradient(top, @start-color @start-percent, @end-color @end-percent); // Safari 5.1-6, Chrome 10+\n background-image: -o-linear-gradient(top, @start-color @start-percent, @end-color @end-percent); // Opera 12\n background-image: linear-gradient(to bottom, @start-color @start-percent, @end-color @end-percent); // Standard, IE10, Firefox 16+, Opera 12.10+, Safari 7+, Chrome 26+\n background-repeat: repeat-x;\n filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=0)\",argb(@start-color),argb(@end-color))); // IE9 and down\n }\n\n .directional(@start-color: #555; @end-color: #333; @deg: 45deg) {\n background-repeat: repeat-x;\n background-image: -webkit-linear-gradient(@deg, @start-color, @end-color); // Safari 5.1-6, Chrome 10+\n background-image: -o-linear-gradient(@deg, @start-color, @end-color); // Opera 12\n background-image: linear-gradient(@deg, @start-color, @end-color); // Standard, IE10, Firefox 16+, Opera 12.10+, Safari 7+, Chrome 26+\n }\n .horizontal-three-colors(@start-color: #00b3ee; @mid-color: #7a43b6; @color-stop: 50%; @end-color: #c3325f) {\n background-image: -webkit-linear-gradient(left, @start-color, @mid-color @color-stop, @end-color);\n background-image: -o-linear-gradient(left, @start-color, @mid-color @color-stop, @end-color);\n background-image: linear-gradient(to right, @start-color, @mid-color @color-stop, @end-color);\n background-repeat: no-repeat;\n filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=1)\",argb(@start-color),argb(@end-color))); // IE9 and down, gets no color-stop at all for proper fallback\n }\n .vertical-three-colors(@start-color: #00b3ee; @mid-color: #7a43b6; @color-stop: 50%; @end-color: #c3325f) {\n background-image: -webkit-linear-gradient(@start-color, @mid-color @color-stop, @end-color);\n background-image: -o-linear-gradient(@start-color, @mid-color @color-stop, @end-color);\n background-image: linear-gradient(@start-color, @mid-color @color-stop, @end-color);\n background-repeat: no-repeat;\n filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=0)\",argb(@start-color),argb(@end-color))); // IE9 and down, gets no color-stop at all for proper fallback\n }\n .radial(@inner-color: #555; @outer-color: #333) {\n background-image: -webkit-radial-gradient(circle, @inner-color, @outer-color);\n background-image: radial-gradient(circle, @inner-color, @outer-color);\n background-repeat: no-repeat;\n }\n .striped(@color: rgba(255,255,255,.15); @angle: 45deg) {\n background-image: -webkit-linear-gradient(@angle, @color 25%, transparent 25%, transparent 50%, @color 50%, @color 75%, transparent 75%, transparent);\n background-image: -o-linear-gradient(@angle, @color 25%, transparent 25%, transparent 50%, @color 50%, @color 75%, transparent 75%, transparent);\n background-image: linear-gradient(@angle, @color 25%, transparent 25%, transparent 50%, @color 50%, @color 75%, transparent 75%, transparent);\n }\n}\n","// Reset filters for IE\n//\n// When you need to remove a gradient background, do not forget to use this to reset\n// the IE filter for IE9 and below.\n\n.reset-filter() {\n filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(enabled = false)\"));\n}\n"]} -------------------------------------------------------------------------------- /css/bootstrap-theme.css: -------------------------------------------------------------------------------- 1 | /*! 2 | * Bootstrap v3.2.0 (http://getbootstrap.com) 3 | * Copyright 2011-2014 Twitter, Inc. 4 | * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) 5 | */ 6 | 7 | .btn-default, 8 | .btn-primary, 9 | .btn-success, 10 | .btn-info, 11 | .btn-warning, 12 | .btn-danger { 13 | text-shadow: 0 -1px 0 rgba(0, 0, 0, .2); 14 | -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .15), 0 1px 1px rgba(0, 0, 0, .075); 15 | box-shadow: inset 0 1px 0 rgba(255, 255, 255, .15), 0 1px 1px rgba(0, 0, 0, .075); 16 | } 17 | .btn-default:active, 18 | .btn-primary:active, 19 | .btn-success:active, 20 | .btn-info:active, 21 | .btn-warning:active, 22 | .btn-danger:active, 23 | .btn-default.active, 24 | .btn-primary.active, 25 | .btn-success.active, 26 | .btn-info.active, 27 | .btn-warning.active, 28 | .btn-danger.active { 29 | -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125); 30 | box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125); 31 | } 32 | .btn:active, 33 | .btn.active { 34 | background-image: none; 35 | } 36 | .btn-default { 37 | text-shadow: 0 1px 0 #fff; 38 | background-image: -webkit-linear-gradient(top, #fff 0%, #e0e0e0 100%); 39 | background-image: -o-linear-gradient(top, #fff 0%, #e0e0e0 100%); 40 | background-image: -webkit-gradient(linear, left top, left bottom, from(#fff), to(#e0e0e0)); 41 | background-image: linear-gradient(to bottom, #fff 0%, #e0e0e0 100%); 42 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe0e0e0', GradientType=0); 43 | filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); 44 | background-repeat: repeat-x; 45 | border-color: #dbdbdb; 46 | border-color: #ccc; 47 | } 48 | .btn-default:hover, 49 | .btn-default:focus { 50 | background-color: #e0e0e0; 51 | background-position: 0 -15px; 52 | } 53 | .btn-default:active, 54 | .btn-default.active { 55 | background-color: #e0e0e0; 56 | border-color: #dbdbdb; 57 | } 58 | .btn-default:disabled, 59 | .btn-default[disabled] { 60 | background-color: #e0e0e0; 61 | background-image: none; 62 | } 63 | .btn-primary { 64 | background-image: -webkit-linear-gradient(top, #428bca 0%, #2d6ca2 100%); 65 | background-image: -o-linear-gradient(top, #428bca 0%, #2d6ca2 100%); 66 | background-image: -webkit-gradient(linear, left top, left bottom, from(#428bca), to(#2d6ca2)); 67 | background-image: linear-gradient(to bottom, #428bca 0%, #2d6ca2 100%); 68 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff2d6ca2', GradientType=0); 69 | filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); 70 | background-repeat: repeat-x; 71 | border-color: #2b669a; 72 | } 73 | .btn-primary:hover, 74 | .btn-primary:focus { 75 | background-color: #2d6ca2; 76 | background-position: 0 -15px; 77 | } 78 | .btn-primary:active, 79 | .btn-primary.active { 80 | background-color: #2d6ca2; 81 | border-color: #2b669a; 82 | } 83 | .btn-primary:disabled, 84 | .btn-primary[disabled] { 85 | background-color: #2d6ca2; 86 | background-image: none; 87 | } 88 | .btn-success { 89 | background-image: -webkit-linear-gradient(top, #5cb85c 0%, #419641 100%); 90 | background-image: -o-linear-gradient(top, #5cb85c 0%, #419641 100%); 91 | background-image: -webkit-gradient(linear, left top, left bottom, from(#5cb85c), to(#419641)); 92 | background-image: linear-gradient(to bottom, #5cb85c 0%, #419641 100%); 93 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff419641', GradientType=0); 94 | filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); 95 | background-repeat: repeat-x; 96 | border-color: #3e8f3e; 97 | } 98 | .btn-success:hover, 99 | .btn-success:focus { 100 | background-color: #419641; 101 | background-position: 0 -15px; 102 | } 103 | .btn-success:active, 104 | .btn-success.active { 105 | background-color: #419641; 106 | border-color: #3e8f3e; 107 | } 108 | .btn-success:disabled, 109 | .btn-success[disabled] { 110 | background-color: #419641; 111 | background-image: none; 112 | } 113 | .btn-info { 114 | background-image: -webkit-linear-gradient(top, #5bc0de 0%, #2aabd2 100%); 115 | background-image: -o-linear-gradient(top, #5bc0de 0%, #2aabd2 100%); 116 | background-image: -webkit-gradient(linear, left top, left bottom, from(#5bc0de), to(#2aabd2)); 117 | background-image: linear-gradient(to bottom, #5bc0de 0%, #2aabd2 100%); 118 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff2aabd2', GradientType=0); 119 | filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); 120 | background-repeat: repeat-x; 121 | border-color: #28a4c9; 122 | } 123 | .btn-info:hover, 124 | .btn-info:focus { 125 | background-color: #2aabd2; 126 | background-position: 0 -15px; 127 | } 128 | .btn-info:active, 129 | .btn-info.active { 130 | background-color: #2aabd2; 131 | border-color: #28a4c9; 132 | } 133 | .btn-info:disabled, 134 | .btn-info[disabled] { 135 | background-color: #2aabd2; 136 | background-image: none; 137 | } 138 | .btn-warning { 139 | background-image: -webkit-linear-gradient(top, #f0ad4e 0%, #eb9316 100%); 140 | background-image: -o-linear-gradient(top, #f0ad4e 0%, #eb9316 100%); 141 | background-image: -webkit-gradient(linear, left top, left bottom, from(#f0ad4e), to(#eb9316)); 142 | background-image: linear-gradient(to bottom, #f0ad4e 0%, #eb9316 100%); 143 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffeb9316', GradientType=0); 144 | filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); 145 | background-repeat: repeat-x; 146 | border-color: #e38d13; 147 | } 148 | .btn-warning:hover, 149 | .btn-warning:focus { 150 | background-color: #eb9316; 151 | background-position: 0 -15px; 152 | } 153 | .btn-warning:active, 154 | .btn-warning.active { 155 | background-color: #eb9316; 156 | border-color: #e38d13; 157 | } 158 | .btn-warning:disabled, 159 | .btn-warning[disabled] { 160 | background-color: #eb9316; 161 | background-image: none; 162 | } 163 | .btn-danger { 164 | background-image: -webkit-linear-gradient(top, #d9534f 0%, #c12e2a 100%); 165 | background-image: -o-linear-gradient(top, #d9534f 0%, #c12e2a 100%); 166 | background-image: -webkit-gradient(linear, left top, left bottom, from(#d9534f), to(#c12e2a)); 167 | background-image: linear-gradient(to bottom, #d9534f 0%, #c12e2a 100%); 168 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc12e2a', GradientType=0); 169 | filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); 170 | background-repeat: repeat-x; 171 | border-color: #b92c28; 172 | } 173 | .btn-danger:hover, 174 | .btn-danger:focus { 175 | background-color: #c12e2a; 176 | background-position: 0 -15px; 177 | } 178 | .btn-danger:active, 179 | .btn-danger.active { 180 | background-color: #c12e2a; 181 | border-color: #b92c28; 182 | } 183 | .btn-danger:disabled, 184 | .btn-danger[disabled] { 185 | background-color: #c12e2a; 186 | background-image: none; 187 | } 188 | .thumbnail, 189 | .img-thumbnail { 190 | -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, .075); 191 | box-shadow: 0 1px 2px rgba(0, 0, 0, .075); 192 | } 193 | .dropdown-menu > li > a:hover, 194 | .dropdown-menu > li > a:focus { 195 | background-color: #e8e8e8; 196 | background-image: -webkit-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%); 197 | background-image: -o-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%); 198 | background-image: -webkit-gradient(linear, left top, left bottom, from(#f5f5f5), to(#e8e8e8)); 199 | background-image: linear-gradient(to bottom, #f5f5f5 0%, #e8e8e8 100%); 200 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0); 201 | background-repeat: repeat-x; 202 | } 203 | .dropdown-menu > .active > a, 204 | .dropdown-menu > .active > a:hover, 205 | .dropdown-menu > .active > a:focus { 206 | background-color: #357ebd; 207 | background-image: -webkit-linear-gradient(top, #428bca 0%, #357ebd 100%); 208 | background-image: -o-linear-gradient(top, #428bca 0%, #357ebd 100%); 209 | background-image: -webkit-gradient(linear, left top, left bottom, from(#428bca), to(#357ebd)); 210 | background-image: linear-gradient(to bottom, #428bca 0%, #357ebd 100%); 211 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff357ebd', GradientType=0); 212 | background-repeat: repeat-x; 213 | } 214 | .navbar-default { 215 | background-image: -webkit-linear-gradient(top, #fff 0%, #f8f8f8 100%); 216 | background-image: -o-linear-gradient(top, #fff 0%, #f8f8f8 100%); 217 | background-image: -webkit-gradient(linear, left top, left bottom, from(#fff), to(#f8f8f8)); 218 | background-image: linear-gradient(to bottom, #fff 0%, #f8f8f8 100%); 219 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff8f8f8', GradientType=0); 220 | filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); 221 | background-repeat: repeat-x; 222 | border-radius: 4px; 223 | -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .15), 0 1px 5px rgba(0, 0, 0, .075); 224 | box-shadow: inset 0 1px 0 rgba(255, 255, 255, .15), 0 1px 5px rgba(0, 0, 0, .075); 225 | } 226 | .navbar-default .navbar-nav > .active > a { 227 | background-image: -webkit-linear-gradient(top, #ebebeb 0%, #f3f3f3 100%); 228 | background-image: -o-linear-gradient(top, #ebebeb 0%, #f3f3f3 100%); 229 | background-image: -webkit-gradient(linear, left top, left bottom, from(#ebebeb), to(#f3f3f3)); 230 | background-image: linear-gradient(to bottom, #ebebeb 0%, #f3f3f3 100%); 231 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffebebeb', endColorstr='#fff3f3f3', GradientType=0); 232 | background-repeat: repeat-x; 233 | -webkit-box-shadow: inset 0 3px 9px rgba(0, 0, 0, .075); 234 | box-shadow: inset 0 3px 9px rgba(0, 0, 0, .075); 235 | } 236 | .navbar-brand, 237 | .navbar-nav > li > a { 238 | text-shadow: 0 1px 0 rgba(255, 255, 255, .25); 239 | } 240 | .navbar-inverse { 241 | background-image: -webkit-linear-gradient(top, #3c3c3c 0%, #222 100%); 242 | background-image: -o-linear-gradient(top, #3c3c3c 0%, #222 100%); 243 | background-image: -webkit-gradient(linear, left top, left bottom, from(#3c3c3c), to(#222)); 244 | background-image: linear-gradient(to bottom, #3c3c3c 0%, #222 100%); 245 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff3c3c3c', endColorstr='#ff222222', GradientType=0); 246 | filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); 247 | background-repeat: repeat-x; 248 | } 249 | .navbar-inverse .navbar-nav > .active > a { 250 | background-image: -webkit-linear-gradient(top, #222 0%, #282828 100%); 251 | background-image: -o-linear-gradient(top, #222 0%, #282828 100%); 252 | background-image: -webkit-gradient(linear, left top, left bottom, from(#222), to(#282828)); 253 | background-image: linear-gradient(to bottom, #222 0%, #282828 100%); 254 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff222222', endColorstr='#ff282828', GradientType=0); 255 | background-repeat: repeat-x; 256 | -webkit-box-shadow: inset 0 3px 9px rgba(0, 0, 0, .25); 257 | box-shadow: inset 0 3px 9px rgba(0, 0, 0, .25); 258 | } 259 | .navbar-inverse .navbar-brand, 260 | .navbar-inverse .navbar-nav > li > a { 261 | text-shadow: 0 -1px 0 rgba(0, 0, 0, .25); 262 | } 263 | .navbar-static-top, 264 | .navbar-fixed-top, 265 | .navbar-fixed-bottom { 266 | border-radius: 0; 267 | } 268 | .alert { 269 | text-shadow: 0 1px 0 rgba(255, 255, 255, .2); 270 | -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .25), 0 1px 2px rgba(0, 0, 0, .05); 271 | box-shadow: inset 0 1px 0 rgba(255, 255, 255, .25), 0 1px 2px rgba(0, 0, 0, .05); 272 | } 273 | .alert-success { 274 | background-image: -webkit-linear-gradient(top, #dff0d8 0%, #c8e5bc 100%); 275 | background-image: -o-linear-gradient(top, #dff0d8 0%, #c8e5bc 100%); 276 | background-image: -webkit-gradient(linear, left top, left bottom, from(#dff0d8), to(#c8e5bc)); 277 | background-image: linear-gradient(to bottom, #dff0d8 0%, #c8e5bc 100%); 278 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffc8e5bc', GradientType=0); 279 | background-repeat: repeat-x; 280 | border-color: #b2dba1; 281 | } 282 | .alert-info { 283 | background-image: -webkit-linear-gradient(top, #d9edf7 0%, #b9def0 100%); 284 | background-image: -o-linear-gradient(top, #d9edf7 0%, #b9def0 100%); 285 | background-image: -webkit-gradient(linear, left top, left bottom, from(#d9edf7), to(#b9def0)); 286 | background-image: linear-gradient(to bottom, #d9edf7 0%, #b9def0 100%); 287 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffb9def0', GradientType=0); 288 | background-repeat: repeat-x; 289 | border-color: #9acfea; 290 | } 291 | .alert-warning { 292 | background-image: -webkit-linear-gradient(top, #fcf8e3 0%, #f8efc0 100%); 293 | background-image: -o-linear-gradient(top, #fcf8e3 0%, #f8efc0 100%); 294 | background-image: -webkit-gradient(linear, left top, left bottom, from(#fcf8e3), to(#f8efc0)); 295 | background-image: linear-gradient(to bottom, #fcf8e3 0%, #f8efc0 100%); 296 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fff8efc0', GradientType=0); 297 | background-repeat: repeat-x; 298 | border-color: #f5e79e; 299 | } 300 | .alert-danger { 301 | background-image: -webkit-linear-gradient(top, #f2dede 0%, #e7c3c3 100%); 302 | background-image: -o-linear-gradient(top, #f2dede 0%, #e7c3c3 100%); 303 | background-image: -webkit-gradient(linear, left top, left bottom, from(#f2dede), to(#e7c3c3)); 304 | background-image: linear-gradient(to bottom, #f2dede 0%, #e7c3c3 100%); 305 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffe7c3c3', GradientType=0); 306 | background-repeat: repeat-x; 307 | border-color: #dca7a7; 308 | } 309 | .progress { 310 | background-image: -webkit-linear-gradient(top, #ebebeb 0%, #f5f5f5 100%); 311 | background-image: -o-linear-gradient(top, #ebebeb 0%, #f5f5f5 100%); 312 | background-image: -webkit-gradient(linear, left top, left bottom, from(#ebebeb), to(#f5f5f5)); 313 | background-image: linear-gradient(to bottom, #ebebeb 0%, #f5f5f5 100%); 314 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffebebeb', endColorstr='#fff5f5f5', GradientType=0); 315 | background-repeat: repeat-x; 316 | } 317 | .progress-bar { 318 | background-image: -webkit-linear-gradient(top, #428bca 0%, #3071a9 100%); 319 | background-image: -o-linear-gradient(top, #428bca 0%, #3071a9 100%); 320 | background-image: -webkit-gradient(linear, left top, left bottom, from(#428bca), to(#3071a9)); 321 | background-image: linear-gradient(to bottom, #428bca 0%, #3071a9 100%); 322 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff3071a9', GradientType=0); 323 | background-repeat: repeat-x; 324 | } 325 | .progress-bar-success { 326 | background-image: -webkit-linear-gradient(top, #5cb85c 0%, #449d44 100%); 327 | background-image: -o-linear-gradient(top, #5cb85c 0%, #449d44 100%); 328 | background-image: -webkit-gradient(linear, left top, left bottom, from(#5cb85c), to(#449d44)); 329 | background-image: linear-gradient(to bottom, #5cb85c 0%, #449d44 100%); 330 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff449d44', GradientType=0); 331 | background-repeat: repeat-x; 332 | } 333 | .progress-bar-info { 334 | background-image: -webkit-linear-gradient(top, #5bc0de 0%, #31b0d5 100%); 335 | background-image: -o-linear-gradient(top, #5bc0de 0%, #31b0d5 100%); 336 | background-image: -webkit-gradient(linear, left top, left bottom, from(#5bc0de), to(#31b0d5)); 337 | background-image: linear-gradient(to bottom, #5bc0de 0%, #31b0d5 100%); 338 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff31b0d5', GradientType=0); 339 | background-repeat: repeat-x; 340 | } 341 | .progress-bar-warning { 342 | background-image: -webkit-linear-gradient(top, #f0ad4e 0%, #ec971f 100%); 343 | background-image: -o-linear-gradient(top, #f0ad4e 0%, #ec971f 100%); 344 | background-image: -webkit-gradient(linear, left top, left bottom, from(#f0ad4e), to(#ec971f)); 345 | background-image: linear-gradient(to bottom, #f0ad4e 0%, #ec971f 100%); 346 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffec971f', GradientType=0); 347 | background-repeat: repeat-x; 348 | } 349 | .progress-bar-danger { 350 | background-image: -webkit-linear-gradient(top, #d9534f 0%, #c9302c 100%); 351 | background-image: -o-linear-gradient(top, #d9534f 0%, #c9302c 100%); 352 | background-image: -webkit-gradient(linear, left top, left bottom, from(#d9534f), to(#c9302c)); 353 | background-image: linear-gradient(to bottom, #d9534f 0%, #c9302c 100%); 354 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc9302c', GradientType=0); 355 | background-repeat: repeat-x; 356 | } 357 | .progress-bar-striped { 358 | 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); 359 | 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); 360 | 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); 361 | } 362 | .list-group { 363 | border-radius: 4px; 364 | -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, .075); 365 | box-shadow: 0 1px 2px rgba(0, 0, 0, .075); 366 | } 367 | .list-group-item.active, 368 | .list-group-item.active:hover, 369 | .list-group-item.active:focus { 370 | text-shadow: 0 -1px 0 #3071a9; 371 | background-image: -webkit-linear-gradient(top, #428bca 0%, #3278b3 100%); 372 | background-image: -o-linear-gradient(top, #428bca 0%, #3278b3 100%); 373 | background-image: -webkit-gradient(linear, left top, left bottom, from(#428bca), to(#3278b3)); 374 | background-image: linear-gradient(to bottom, #428bca 0%, #3278b3 100%); 375 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff3278b3', GradientType=0); 376 | background-repeat: repeat-x; 377 | border-color: #3278b3; 378 | } 379 | .panel { 380 | -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, .05); 381 | box-shadow: 0 1px 2px rgba(0, 0, 0, .05); 382 | } 383 | .panel-default > .panel-heading { 384 | background-image: -webkit-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%); 385 | background-image: -o-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%); 386 | background-image: -webkit-gradient(linear, left top, left bottom, from(#f5f5f5), to(#e8e8e8)); 387 | background-image: linear-gradient(to bottom, #f5f5f5 0%, #e8e8e8 100%); 388 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0); 389 | background-repeat: repeat-x; 390 | } 391 | .panel-primary > .panel-heading { 392 | background-image: -webkit-linear-gradient(top, #428bca 0%, #357ebd 100%); 393 | background-image: -o-linear-gradient(top, #428bca 0%, #357ebd 100%); 394 | background-image: -webkit-gradient(linear, left top, left bottom, from(#428bca), to(#357ebd)); 395 | background-image: linear-gradient(to bottom, #428bca 0%, #357ebd 100%); 396 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff357ebd', GradientType=0); 397 | background-repeat: repeat-x; 398 | } 399 | .panel-success > .panel-heading { 400 | background-image: -webkit-linear-gradient(top, #dff0d8 0%, #d0e9c6 100%); 401 | background-image: -o-linear-gradient(top, #dff0d8 0%, #d0e9c6 100%); 402 | background-image: -webkit-gradient(linear, left top, left bottom, from(#dff0d8), to(#d0e9c6)); 403 | background-image: linear-gradient(to bottom, #dff0d8 0%, #d0e9c6 100%); 404 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffd0e9c6', GradientType=0); 405 | background-repeat: repeat-x; 406 | } 407 | .panel-info > .panel-heading { 408 | background-image: -webkit-linear-gradient(top, #d9edf7 0%, #c4e3f3 100%); 409 | background-image: -o-linear-gradient(top, #d9edf7 0%, #c4e3f3 100%); 410 | background-image: -webkit-gradient(linear, left top, left bottom, from(#d9edf7), to(#c4e3f3)); 411 | background-image: linear-gradient(to bottom, #d9edf7 0%, #c4e3f3 100%); 412 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffc4e3f3', GradientType=0); 413 | background-repeat: repeat-x; 414 | } 415 | .panel-warning > .panel-heading { 416 | background-image: -webkit-linear-gradient(top, #fcf8e3 0%, #faf2cc 100%); 417 | background-image: -o-linear-gradient(top, #fcf8e3 0%, #faf2cc 100%); 418 | background-image: -webkit-gradient(linear, left top, left bottom, from(#fcf8e3), to(#faf2cc)); 419 | background-image: linear-gradient(to bottom, #fcf8e3 0%, #faf2cc 100%); 420 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fffaf2cc', GradientType=0); 421 | background-repeat: repeat-x; 422 | } 423 | .panel-danger > .panel-heading { 424 | background-image: -webkit-linear-gradient(top, #f2dede 0%, #ebcccc 100%); 425 | background-image: -o-linear-gradient(top, #f2dede 0%, #ebcccc 100%); 426 | background-image: -webkit-gradient(linear, left top, left bottom, from(#f2dede), to(#ebcccc)); 427 | background-image: linear-gradient(to bottom, #f2dede 0%, #ebcccc 100%); 428 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffebcccc', GradientType=0); 429 | background-repeat: repeat-x; 430 | } 431 | .well { 432 | background-image: -webkit-linear-gradient(top, #e8e8e8 0%, #f5f5f5 100%); 433 | background-image: -o-linear-gradient(top, #e8e8e8 0%, #f5f5f5 100%); 434 | background-image: -webkit-gradient(linear, left top, left bottom, from(#e8e8e8), to(#f5f5f5)); 435 | background-image: linear-gradient(to bottom, #e8e8e8 0%, #f5f5f5 100%); 436 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffe8e8e8', endColorstr='#fff5f5f5', GradientType=0); 437 | background-repeat: repeat-x; 438 | border-color: #dcdcdc; 439 | -webkit-box-shadow: inset 0 1px 3px rgba(0, 0, 0, .05), 0 1px 0 rgba(255, 255, 255, .1); 440 | box-shadow: inset 0 1px 3px rgba(0, 0, 0, .05), 0 1px 0 rgba(255, 255, 255, .1); 441 | } 442 | /*# sourceMappingURL=bootstrap-theme.css.map */ 443 | -------------------------------------------------------------------------------- /fonts/glyphicons-halflings-regular.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | --------------------------------------------------------------------------------