- {{folderName}}
+ {{folderName}}
{{ 'click the text to expand the folder' | translate }}{{ 'click the text to collapse the folder' | translate }}
@@ -1055,7 +1055,7 @@
diff --git a/js/ctrls/modal.js b/js/ctrls/modal.js
index b203de9..4fe4446 100644
--- a/js/ctrls/modal.js
+++ b/js/ctrls/modal.js
@@ -118,47 +118,8 @@ angular
this.dirs = {};
this.files = [];
this.show = false;
- this._selected = false;
+ this.selected = true;
}
- OrganizedFolder.prototype.change = function () {
- for (var i = 0; i < this.files.length; i++) {
- this.files[i].selected = this.selected;
- }
- for (var folder in this.dirs) {
- if (this.dirs.hasOwnProperty(folder)) {
- this.dirs[folder].selected = this.selected;
- }
- }
- };
- Object.defineProperty(OrganizedFolder.prototype, "selected", {
- get : function () {
- return this._selected;
- },
- set : function (newValue) {
- this._selected = newValue;
- this.change();
- }
- });
- Object.defineProperty(OrganizedFolder.prototype, "indeterminate", {
- get : function () {
- var allSeleted = true;
- var allNotSelected = true;
- for (var p in this.dirs) {
- if (this.dirs.hasOwnProperty(p)) {
- if (this.dirs[p].indeterminate) {
- return true;
- }
- allSeleted &= this.dirs[p].selected;
- allNotSelected &= !this.dirs[p].selected;
- }
- }
- for (var i = 0; i < this.files.length; i++) {
- allSeleted &= this.files[i].selected;
- allNotSelected &= !this.files[i].selected;
- }
- return !allSeleted && !allNotSelected;// is not determinate when either all selected either all not selected;
- }
- });
var folder = new OrganizedFolder(), tmp;
for (var i = 0; i < files.length; i++) {
tmp = folder;
@@ -172,7 +133,6 @@ angular
}
tmp.files.push(files[i]);
}
- folder.change();
return folder;
};
this.groupedFiles = groupFiles(this.files);
diff --git a/js/directives/fileselect.js b/js/directives/fileselect.js
index b3efbd5..f2b1cdc 100644
--- a/js/directives/fileselect.js
+++ b/js/directives/fileselect.js
@@ -1,57 +1,98 @@
// watches changes in the file upload control (input[file]) and
// puts the files selected in an attribute
-var app = angular.module("webui.directives.fileselect", []);
-app.directive("indeterminate", function () {
- return {
- // Restrict the directive so it can only be used as an attribute
- restrict : "A",
+var app = angular.module("webui.directives.fileselect", ["webui.services.deps"]);
+app.directive("indeterminate", [
+ "$parse", function syncInput (parse) {
+ return {
+ require : "ngModel",
+ // Restrict the directive so it can only be used as an attribute
+ restrict : "A",
- link : function link (scope, elem, attr) {
- // Whenever the bound value of the attribute changes we update
- // the internal 'indeterminate' flag on the attached dom element
- // use upward emit notification for change to prevent the performance penalty bring by $scope.$watch
- elem[0].indeterminate = scope.$eval(attr.indeterminate);
- scope.$on("childSelectedChange", function (event, options) {
- elem[0].indeterminate = scope.$eval(attr.indeterminate);
- });
-
- /* var watcher = scope.$watch(attr.indeterminate, function (value) {
- elem[0].indeterminate = value;
- });
-
- // Remove the watcher when the directive is destroyed
- scope.$on("$destroy", function () {
- watcher();
- }); */
- }
- };
-});
-
-app.directive("monitor", function () {
- return {
- // Restrict the directive so it can only be used as an attribute
- restrict : "A",
-
- link : function link (scope, elem, attr) {
- // Whenever the bound value of the attribute changes we update
- // the internal 'indeterminate' flag on the attached dom element
- elem.change(function () {
- scope.$emit("childSelectedChange");
- });
- }
- };
-});
-
-app.directive("selected", function () {
- return {
- // Restrict the directive so it can only be used as an attribute
- restrict : "A",
-
- link : function link (scope, elem, attr) {
- elem[0].value = scope.$eval(attr.selected);
- scope.$on("childSelectedChange", function (event, options) {
- elem[0].value = scope.$eval(attr.selected);
- });
- }
- };
-});
+ link : function link (scope, elem, attr, ngModelCtrl) {
+ // 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
+ var getter = parse(attr["ngModel"]);
+ var setter = getter.assign;
+ var children = []; // cache children input
+ var get = function () {
+ return getter(scope);
+ };
+ // the internal 'indeterminate' flag on the attached dom element
+ var setIndeterminateState = function (newValue) {
+ elem.prop("indeterminate", newValue);
+ };
+ var setModelValueWithoutSideEffect = function (newVal) {
+ setter(scope, newVal);
+ ngModelCtrl.$modelValue = newVal;
+ ngModelCtrl.$viewValue = newVal;
+ ngModelCtrl.$render();
+ };
+ var setWithSideEffect = function (newVal) {
+ ngModelCtrl.$setViewValue(newVal);
+ ngModelCtrl.$render();
+ };
+ var passIfLeafChild = function (callback) {
+ return function () {
+ if (children.length > 0) {
+ callback.apply(this, arguments);
+ }
+ };
+ };
+ var passIfNotIsLeafChild = function (callback) {
+ return function () {
+ if (children.length === 0) {
+ callback.apply(this, arguments);
+ }
+ };
+ };
+ var passThroughThisScope = function (callback) {
+ return function (event) {
+ if (event.targetScope !== event.currentScope) {
+ return callback.apply(this, arguments);
+ }
+ };
+ };
+ if (attr["indeterminate"] && parse(attr["indeterminate"]).constant && !scope.$eval(attr["indeterminate"])) {
+ // is leaf input, Only receive parent change and emit child change event
+ setIndeterminateState(scope.$eval(attr["indeterminate"]));
+ ngModelCtrl.$viewChangeListeners.push(passIfNotIsLeafChild(function () {
+ scope.$emit("childSelectedChange");
+ }));
+ scope.$on("ParentSelectedChange", passThroughThisScope(
+ function (event, newVal) {
+ setWithSideEffect(newVal);
+ }));
+ scope.$emit("i'm child input", get);
+ setWithSideEffect(get());
+ scope.$emit("childSelectedChange");
+ } else {
+ // init first time and only once
+ // establish parent-child's relation
+ scope.$on("i'm child input", passThroughThisScope(
+ function (event, child) {
+ children.push(child);
+ })
+ );
+ var updateBaseOnChildrenState = function () {
+ var allSelected = children.every(function (child) {
+ return child();
+ });
+ var anySeleted = children.some(function (child) {
+ return child();
+ });
+ setIndeterminateState(allSelected !== anySeleted);
+ setWithSideEffect(allSelected);
+ };
+ // is not leaf input, Only receive child change and parent change event
+ ngModelCtrl.$viewChangeListeners.push(passIfLeafChild(function () {
+ if (!elem.prop("indeterminate")) { // emit when prop indeterminate is set to false
+ scope.$broadcast("ParentSelectedChange", get());
+ }
+ }));
+ // reset input state base on children inputs
+ scope.$on("childSelectedChange", passThroughThisScope(passIfLeafChild(updateBaseOnChildrenState)));
+ }
+ }
+ };
+ }
+]);