remove some es5 feature, decrease recheck times
This commit is contained in:
parent
942dbe6f3f
commit
83ba82d4bc
|
@ -23,7 +23,7 @@
|
||||||
<script src="js/libs/jquery-2.2.4.min.js"></script>
|
<script src="js/libs/jquery-2.2.4.min.js"></script>
|
||||||
<script src="js/libs/lodash-4.17.3.min.js"></script>
|
<script src="js/libs/lodash-4.17.3.min.js"></script>
|
||||||
|
|
||||||
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.5/angular.js"></script>
|
<script src="js/libs/angular.min.js"></script>
|
||||||
|
|
||||||
<script src="js/libs/angularui-bootstrap-tpls.min.js"></script>
|
<script src="js/libs/angularui-bootstrap-tpls.min.js"></script>
|
||||||
<script src="js/libs/bootstrap-filestyle.js"></script>
|
<script src="js/libs/bootstrap-filestyle.js"></script>
|
||||||
|
|
|
@ -12,8 +12,10 @@ app.directive("indeterminate", [
|
||||||
// Whenever the bound value of the attribute changes we update
|
// Whenever the bound value of the attribute changes we update
|
||||||
// use upward emit notification for change to prevent the performance penalty bring by $scope.$watch
|
// use upward emit notification for change to prevent the performance penalty bring by $scope.$watch
|
||||||
var getter = parse(attr["ngModel"]);
|
var getter = parse(attr["ngModel"]);
|
||||||
var setter = getter.assign;
|
// var setter = getter.assign;
|
||||||
var children = []; // cache children input
|
var children = []; // cache children input
|
||||||
|
var cacheSelectedSubInputNumber = 0;
|
||||||
|
var cacheNoSelectedSubInputNumber = 0;
|
||||||
var get = function () {
|
var get = function () {
|
||||||
return getter(scope);
|
return getter(scope);
|
||||||
};
|
};
|
||||||
|
@ -21,18 +23,18 @@ app.directive("indeterminate", [
|
||||||
var setIndeterminateState = function (newValue) {
|
var setIndeterminateState = function (newValue) {
|
||||||
elem.prop("indeterminate", newValue);
|
elem.prop("indeterminate", newValue);
|
||||||
};
|
};
|
||||||
var setWithSideEffect = function (newVal) {
|
var setModelValueWithSideEffect = function (newVal) { // will cause to emit corresponding events
|
||||||
ngModelCtrl.$setViewValue(newVal);
|
ngModelCtrl.$setViewValue(newVal);
|
||||||
ngModelCtrl.$render();
|
ngModelCtrl.$render();
|
||||||
};
|
};
|
||||||
var passIfLeafChild = function (callback) { // ensure to execute callback when this input have one or more subinputs
|
var passIfIsLeafChild = function (callback) { // ensure to execute callback only when this input has one or more subinputs
|
||||||
return function () {
|
return function () {
|
||||||
if (children.length > 0) {
|
if (children.length > 0) {
|
||||||
callback.apply(this, arguments);
|
callback.apply(this, arguments);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
var passIfNotIsLeafChild = function (callback) { // ensure to execute callback when this input havent subinput
|
var passIfNotIsLeafChild = function (callback) { // ensure to execute callback only when this input hasn't subinput
|
||||||
return function () {
|
return function () {
|
||||||
if (children.length === 0) {
|
if (children.length === 0) {
|
||||||
callback.apply(this, arguments);
|
callback.apply(this, arguments);
|
||||||
|
@ -46,19 +48,27 @@ app.directive("indeterminate", [
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
var catchEventOnlyOnce = function (callback) { // only fire once, and stop event's propagation
|
||||||
|
return function (event) {
|
||||||
|
callback.apply(this, arguments);
|
||||||
|
return event.stopPropagation();
|
||||||
|
};
|
||||||
|
};
|
||||||
|
if (attr["indeterminate"] && parse(attr["indeterminate"]).constant) {
|
||||||
|
setIndeterminateState(scope.$eval(attr["indeterminate"])); // set to default value (set in template)
|
||||||
|
}
|
||||||
if (attr["indeterminate"] && parse(attr["indeterminate"]).constant && !scope.$eval(attr["indeterminate"])) {
|
if (attr["indeterminate"] && parse(attr["indeterminate"]).constant && !scope.$eval(attr["indeterminate"])) {
|
||||||
// is leaf input, Only receive parent change and emit child change event
|
// when this input wont have subinput, they will only receive parent change and emit child change event
|
||||||
setIndeterminateState(scope.$eval(attr["indeterminate"]));
|
|
||||||
ngModelCtrl.$viewChangeListeners.push(passIfNotIsLeafChild(function () {
|
ngModelCtrl.$viewChangeListeners.push(passIfNotIsLeafChild(function () {
|
||||||
scope.$emit("childSelectedChange");
|
scope.$emit("childSelectedChange", get());
|
||||||
}));
|
}));
|
||||||
scope.$on("ParentSelectedChange", passThroughThisScope(
|
scope.$on("ParentSelectedChange", passThroughThisScope(passIfNotIsLeafChild(
|
||||||
function (event, newVal) {
|
function (event, newVal) {
|
||||||
setWithSideEffect(newVal); // set value to parent's value; this will cause listener to emit childChange event; this won't be a infinite loop
|
setModelValueWithSideEffect(newVal); // set value to parent's value; this will cause listener to emit childChange event; this won't be a infinite loop
|
||||||
}));
|
})));
|
||||||
// init first time and only once
|
// init first time and only once
|
||||||
scope.$emit("i'm child input", get);
|
scope.$emit("i'm child input", get);
|
||||||
scope.$emit("childSelectedChange"); // force emitted, and force the parent change their state base on children at first time
|
scope.$emit("childSelectedChange", get()); // force emitted, and force the parent change their state base on children at first time
|
||||||
} else {
|
} else {
|
||||||
// establish parent-child's relation
|
// establish parent-child's relation
|
||||||
// listen for the child emitted token
|
// listen for the child emitted token
|
||||||
|
@ -67,25 +77,42 @@ app.directive("indeterminate", [
|
||||||
children.push(child);
|
children.push(child);
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
var updateBaseOnChildrenState = function () {
|
var updateBaseOnChildrenState = function (event, newChildValue) {
|
||||||
var allSelected = children.every(function (child) {
|
if ((cacheSelectedSubInputNumber + cacheNoSelectedSubInputNumber) !== children.length) {
|
||||||
return child();
|
cacheSelectedSubInputNumber = 0;
|
||||||
});
|
cacheNoSelectedSubInputNumber = 0;
|
||||||
var anySeleted = children.some(function (child) {
|
for (var i = 0; i < children.length; i++) {
|
||||||
return child();
|
if (children[i]()) {
|
||||||
});
|
cacheSelectedSubInputNumber += 1;
|
||||||
|
} else {
|
||||||
|
cacheNoSelectedSubInputNumber += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// no need for recalculated children state
|
||||||
|
// just make a few change to cache value
|
||||||
|
if (newChildValue) {
|
||||||
|
cacheSelectedSubInputNumber++;
|
||||||
|
cacheNoSelectedSubInputNumber--;
|
||||||
|
} else {
|
||||||
|
cacheSelectedSubInputNumber--;
|
||||||
|
cacheNoSelectedSubInputNumber++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var allSelected = (cacheNoSelectedSubInputNumber === 0);
|
||||||
|
var anySeleted = (cacheSelectedSubInputNumber > 0);
|
||||||
setIndeterminateState(allSelected !== anySeleted); // if at least one is selected, but not all then set input property indeterminate to true
|
setIndeterminateState(allSelected !== anySeleted); // if at least one is selected, but not all then set input property indeterminate to true
|
||||||
setWithSideEffect(allSelected);
|
setModelValueWithSideEffect(allSelected);
|
||||||
};
|
};
|
||||||
// is not leaf input, Only receive child change and parent change event
|
// is not leaf input, Only receive child change and parent change event
|
||||||
ngModelCtrl.$viewChangeListeners.push(passIfLeafChild(function () {
|
ngModelCtrl.$viewChangeListeners.push(passIfIsLeafChild(function () {
|
||||||
// emit when property indeterminate is set to false, prevent recursively emitting event from parent to children, children to parent
|
// emit when property indeterminate is set to false, prevent recursively emitting event from parent to children, children to parent
|
||||||
if (!elem.prop("indeterminate")) {
|
if (!elem.prop("indeterminate")) {
|
||||||
scope.$broadcast("ParentSelectedChange", get());
|
scope.$broadcast("ParentSelectedChange", get());
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
// reset input state base on children inputs
|
// reset input state base on children inputs
|
||||||
scope.$on("childSelectedChange", passThroughThisScope(passIfLeafChild(updateBaseOnChildrenState)));
|
scope.$on("childSelectedChange", passThroughThisScope(passIfIsLeafChild(updateBaseOnChildrenState)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue
Block a user