<!DOCTYPE html>
<html ng-app="app">
<head>
<title>check all</title>
<script src="http://cdn.bootcss.com/jquery/2.1.2/jquery.js"></script>
<script src="http://cdn.bootcss.com/angular.js/1.3.15/angular.js"></script>
<script src="./checkbox.js"></script>
<link href="http://cdn.bootcss.com/bootstrap/3.3.4/css/bootstrap.css" rel="stylesheet">
<script>
angular.module('app', ['test.checkbox']);
</script>
</head>
<body>
<a checkbox-select-all class="btn btn-default" group="['foodGroup', 'bookGroup']">全都喜欢</a>
<a checkbox-select-all="bookGroup" class="btn btn-default" group="['group1', 'group2', 'group3']">全选所有书籍</a>
<a checkbox-select-all="foodGroup" class="btn btn-default" group="['group4']">全选所有美食</a>
<div class="well">
<label class="label label-info">科幻类</label>
<a checkbox-select-all="group1" class="btn btn-default" group="['checkbox1', 'checkbox2', 'checkbox3']">全选</a>
<div>
<label class="checkbox-inline">
<input type="checkbox" ng-model="checkbox1">三体
</label>
<label class="checkbox-inline">
<input type="checkbox" ng-model="checkbox2">璀璨的银河
</label>
<label class="checkbox-inline">
<input type="checkbox" ng-model="checkbox3">球状闪电
</label>
</div>
<hr />
<label class="label label-info">计算机类</label>
<a checkbox-select-all="group2" class="btn btn-default" group="['checkbox4', 'checkbox5']">全选</a>
<div>
<label class="checkbox-inline">
<input type="checkbox" ng-model="checkbox4">深入浅出NodeJS
</label>
<label class="checkbox-inline">
<input type="checkbox" ng-model="checkbox5">Angularjs权威教程
</label>
</div>
<hr />
<label class="label label-info">人文类</label>
<a checkbox-select-all="group3" class="btn btn-default" group="['checkbox6', 'checkbox7', 'checkbox8']">全选</a>
<div>
<label class="checkbox-inline">
<input type="checkbox" ng-model="checkbox6">黑客与画家
</label>
<label class="checkbox-inline">
<input type="checkbox" ng-model="checkbox7">大教堂与集市
</label>
<label class="checkbox-inline">
<input type="checkbox" ng-model="checkbox8">把时间当朋友
</label>
</div>
</div>
<div class="well">
<label class="label label-info">川菜</label>
<a checkbox-select-all="group4" class="btn btn-default" group="['checkbox9', 'checkbox10', 'checkbox11']">全选</a>
<div>
<label class="checkbox-inline">
<input type="checkbox" ng-model="checkbox9">辣子鸡丁
</label>
<label class="checkbox-inline">
<input type="checkbox" ng-model="checkbox10">红烧茄子
</label>
<label class="checkbox-inline">
<input type="checkbox" ng-model="checkbox11">酸辣土豆丝
</label>
</div>
</div>
</body>
</html>
var checkbtn = angular.module('test.checkbox', []);
checkbtn.factory('checkboxSelectGroupStack', [function(){
var stack = {};
return {
'put': function(grpRef, group){
stack[grpRef] = group;
},
'get': function(grpRef){
return stack[grpRef];
}
};
}]);
checkbtn.directive('checkboxSelectAll', ['$parse', 'checkboxSelectGroupStack', function($parse, groupStack){
return {
'restrict': 'A',
'link': function(scope, element, attrs){
//组引用 (该引用 代表着 group 中所有的成员)
var groupRef = attrs.checkboxSelectAll;
//组成员 (该引用成员既包括 checkbox,也可以是一个groupRef)
var groupItems = $parse(attrs.group || "[]")(scope);
// checkbox-select-all 的属性值代表着其所在元素的 group 引用的组成员。
// group 所引用的成员既可以是 一个 checkbox 成员 也可以是一个 checkbox-select-all 成员
if (typeof groupRef === 'string' && groupRef.length >0 ) {
groupStack.put(groupRef, groupItems);
}
//equals jQuery.merge
var merge = function ( first, second ) {
var len = +second.length,
j = 0,
i = first.length;
for ( ; j < len; j++ ) {
first[ i++ ] = second[ j ];
}
first.length = i;
return first;
};
// 在堆上计算 组成员中的属性值,并将该数组展平成1维数组
var flattenGroupItemsOnGroupStack = function(groupItems){
var flattenGroupItems = [];
groupItems.forEach(function(groupItemOrRef){
// 如果该成员是堆上引用
if ( Array.isArray(groupStack.get(groupItemOrRef)) ) {
// 递归将对堆上的引用全部计算成checkbox级别的组成员
merge(flattenGroupItems, flattenGroupItemsOnGroupStack(groupStack.get(groupItemOrRef)));
}else{
flattenGroupItems.push(groupItemOrRef);
}
});
return flattenGroupItems;
};
var allSelect = function(){
scope.$apply(function(){
flattenGroupItemsOnGroupStack(groupItems).forEach(function(modelName){
scope[modelName] = true; // 全选
});
});
// toggle event
element.unbind('click', allSelect).bind('click', reverseSelect);
};
var reverseSelect = function(){
scope.$apply(function(){
flattenGroupItemsOnGroupStack(groupItems).forEach(function(modelName){
scope[modelName] = !scope[modelName]; //反选
});
});
// toggle event
element.unbind('click', reverseSelect).bind('click', allSelect);
};
element.bind('click', allSelect);
}
}
}]);