From baab0be5af824420b2a916c69efa251c904b53b0 Mon Sep 17 00:00:00 2001 From: Victor Woeltjen Date: Fri, 11 Mar 2016 10:04:33 -0800 Subject: [PATCH 01/27] [Tree] Begin adding mct-tree directive ...to reduce watch counts associated with the tree; #732 and #315 --- .../general/src/directives/MCTTree.js | 39 +++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 platform/commonUI/general/src/directives/MCTTree.js diff --git a/platform/commonUI/general/src/directives/MCTTree.js b/platform/commonUI/general/src/directives/MCTTree.js new file mode 100644 index 0000000000..3266ca3759 --- /dev/null +++ b/platform/commonUI/general/src/directives/MCTTree.js @@ -0,0 +1,39 @@ +/***************************************************************************** + * Open MCT Web, Copyright (c) 2014-2015, United States Government + * as represented by the Administrator of the National Aeronautics and Space + * Administration. All rights reserved. + * + * Open MCT Web is licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + * Open MCT Web includes source code licensed under additional open source + * licenses. See the Open Source Licenses file (LICENSES.md) included with + * this source code distribution or the Licensing information page available + * at runtime from the About dialog for additional information. + *****************************************************************************/ +/*global define*/ + +define([ + 'text!../../res/templates/subtree.html' +], function () { + function MCTTree() { + function link(scope, elem) { + + } + + return { + link: link, + scope: { mctModel: "=" } + }; + } + + return MCTTree; +}); From 3b0a3733b4372b776087d51527c8627bbaff450f Mon Sep 17 00:00:00 2001 From: Victor Woeltjen Date: Fri, 11 Mar 2016 10:23:06 -0800 Subject: [PATCH 02/27] [Tree] Begin adding controller for refactored tree --- .../general/src/directives/MCTTree.js | 46 +++++++++++++++++-- 1 file changed, 41 insertions(+), 5 deletions(-) diff --git a/platform/commonUI/general/src/directives/MCTTree.js b/platform/commonUI/general/src/directives/MCTTree.js index 3266ca3759..4a6e684fcd 100644 --- a/platform/commonUI/general/src/directives/MCTTree.js +++ b/platform/commonUI/general/src/directives/MCTTree.js @@ -23,15 +23,51 @@ define([ 'text!../../res/templates/subtree.html' -], function () { - function MCTTree() { - function link(scope, elem) { +], function (subtreeTemplate) { + function MCTTreeController($scope, $element) { + var ul = elem.filter('ul'), + activeObject, + unlisten; + function addNodes(domainObjects) { + domainObjects.forEach(function (addNode)); } + function loadComposition(domainObject) { + activeObject = domainObject; + ul.empty(); + if (domainObject.hasCapability('composition')) { + // TODO: Add pending indicator + domainObject.useCapability('composition') + .then(addNodes); + } + } + + function changeObject(domainObject) { + if (unlisten) { + unlisten(); + } + + unlisten = domainObject.getCapability('mutation') + .listen(loadComposition); + + loadComposition(domainObject); + } + + scope.$watch('mctObject', changeObject); + } + + function MCTTree() { return { - link: link, - scope: { mctModel: "=" } + restrict: "E", + controller: [ + '$scope', + '$element', + MCTTreeController + ], + require: [ "mctTree" ], + scope: { mctObject: "=" }, + template: subtreeTemplate }; } From ece8f7fded0d385c57e7ef49080939cd26b35f29 Mon Sep 17 00:00:00 2001 From: Victor Woeltjen Date: Fri, 11 Mar 2016 11:12:43 -0800 Subject: [PATCH 03/27] [Tree] Begin separating out TreeView --- .../general/res/templates/tree/node.html | 32 ++++++ .../general/src/directives/MCTTree.js | 37 ++----- .../commonUI/general/src/ui/TreeNodeView.js | 0 platform/commonUI/general/src/ui/TreeView.js | 98 +++++++++++++++++++ 4 files changed, 139 insertions(+), 28 deletions(-) create mode 100644 platform/commonUI/general/res/templates/tree/node.html create mode 100644 platform/commonUI/general/src/ui/TreeNodeView.js create mode 100644 platform/commonUI/general/src/ui/TreeView.js diff --git a/platform/commonUI/general/res/templates/tree/node.html b/platform/commonUI/general/res/templates/tree/node.html new file mode 100644 index 0000000000..ea5e2b3786 --- /dev/null +++ b/platform/commonUI/general/res/templates/tree/node.html @@ -0,0 +1,32 @@ +
  • + + + + + + + + + + +
  • \ No newline at end of file diff --git a/platform/commonUI/general/src/directives/MCTTree.js b/platform/commonUI/general/src/directives/MCTTree.js index 4a6e684fcd..74eb840f51 100644 --- a/platform/commonUI/general/src/directives/MCTTree.js +++ b/platform/commonUI/general/src/directives/MCTTree.js @@ -22,39 +22,19 @@ /*global define*/ define([ - 'text!../../res/templates/subtree.html' -], function (subtreeTemplate) { - function MCTTreeController($scope, $element) { - var ul = elem.filter('ul'), + 'text!../../res/templates/subtree.html', + 'text!../../res/templates/tree/node.html' +], function (subtreeTemplate, nodeTemplate) { + function MCTTreeController($scope, $element, $compile) { + var ul = $element.filter('ul'), + makeNode = $compile(nodeTemplate), activeObject, unlisten; - function addNodes(domainObjects) { - domainObjects.forEach(function (addNode)); - } - function loadComposition(domainObject) { - activeObject = domainObject; - ul.empty(); - if (domainObject.hasCapability('composition')) { - // TODO: Add pending indicator - domainObject.useCapability('composition') - .then(addNodes); - } - } - function changeObject(domainObject) { - if (unlisten) { - unlisten(); - } - unlisten = domainObject.getCapability('mutation') - .listen(loadComposition); - - loadComposition(domainObject); - } - - scope.$watch('mctObject', changeObject); + $scope.$watch('mctObject', changeObject); } function MCTTree() { @@ -63,11 +43,12 @@ define([ controller: [ '$scope', '$element', + '$compile', MCTTreeController ], require: [ "mctTree" ], scope: { mctObject: "=" }, - template: subtreeTemplate + template: "" }; } diff --git a/platform/commonUI/general/src/ui/TreeNodeView.js b/platform/commonUI/general/src/ui/TreeNodeView.js new file mode 100644 index 0000000000..e69de29bb2 diff --git a/platform/commonUI/general/src/ui/TreeView.js b/platform/commonUI/general/src/ui/TreeView.js new file mode 100644 index 0000000000..4032711321 --- /dev/null +++ b/platform/commonUI/general/src/ui/TreeView.js @@ -0,0 +1,98 @@ +/***************************************************************************** + * Open MCT Web, Copyright (c) 2014-2015, United States Government + * as represented by the Administrator of the National Aeronautics and Space + * Administration. All rights reserved. + * + * Open MCT Web is licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + * Open MCT Web includes source code licensed under additional open source + * licenses. See the Open Source Licenses file (LICENSES.md) included with + * this source code distribution or the Licensing information page available + * at runtime from the About dialog for additional information. + *****************************************************************************/ +/*global define*/ + +define([ + 'angular' +], function (angular, TreeNodeView) { + 'use strict'; + + var $ = angular.element.bind(angular); + + function TreeView() { + this.ul = $('
      '); + this.ul.addClass('tree'); + this.nodeViews = []; + } + + TreeView.prototype.setSize = function (sz) { + var nodeView; + + while (this.nodeViews.length < sz) { + nodeView = new TreeNodeView(); + this.nodeViews.push(nodeView); + this.ul.append($(nodeView.elements())); + } + + while (this.nodeViews.length > sz) { + nodeView = this.nodeViews.pop(); + $(nodeView.elements()).remove(); + } + }; + + TreeView.prototype.loadComposition = function (domainObject) { + var self = this; + + function addNode(domainObject, index) { + self.nodeViews[index].model(domainObject); + } + + function addNodes(domainObjects) { + if (domainObject === self.activeObject) { + self.setSize(domainObjects.length); + domainObjects.forEach(addNode); + } + } + + // TODO: Add pending indicator + domainObject.useCapability('composition') + .then(addNodes); + }; + + TreeView.prototype.model = function (domainObject) { + if (this.unlisten) { + this.unlisten(); + } + + this.activeObject = domainObject; + this.ul.empty(); + + if (domainObject && domainObject.hasCapability('composition')) { + this.unlisten = domainObject.getCapability('mutation') + .listen(this.loadComposition.bind(this)); + this.loadComposition(domainObject); + } else { + this.setSize(0); + } + }; + + /** + * + * @returns {HTMLElement[]} + */ + TreeView.prototype.elements = function () { + return this.ul; + }; + + + return TreeView; +}); \ No newline at end of file From 37e6b5a35210fa176373268f381a9326242b1b02 Mon Sep 17 00:00:00 2001 From: Victor Woeltjen Date: Fri, 11 Mar 2016 11:39:10 -0800 Subject: [PATCH 04/27] [Tree] Continue breaking apart tree view --- .../general/res/templates/tree/node.html | 36 ++-------- .../general/res/templates/tree/toggle.html | 2 + .../commonUI/general/src/ui/ToggleView.js | 61 ++++++++++++++++ .../commonUI/general/src/ui/TreeNodeView.js | 70 +++++++++++++++++++ platform/commonUI/general/src/ui/TreeView.js | 9 ++- 5 files changed, 146 insertions(+), 32 deletions(-) create mode 100644 platform/commonUI/general/res/templates/tree/toggle.html create mode 100644 platform/commonUI/general/src/ui/ToggleView.js diff --git a/platform/commonUI/general/res/templates/tree/node.html b/platform/commonUI/general/res/templates/tree/node.html index ea5e2b3786..2041a39cca 100644 --- a/platform/commonUI/general/res/templates/tree/node.html +++ b/platform/commonUI/general/res/templates/tree/node.html @@ -1,32 +1,8 @@ -
    • - - - - - + + - - - + -
    • \ No newline at end of file + + + diff --git a/platform/commonUI/general/res/templates/tree/toggle.html b/platform/commonUI/general/res/templates/tree/toggle.html new file mode 100644 index 0000000000..289f781f95 --- /dev/null +++ b/platform/commonUI/general/res/templates/tree/toggle.html @@ -0,0 +1,2 @@ + + diff --git a/platform/commonUI/general/src/ui/ToggleView.js b/platform/commonUI/general/src/ui/ToggleView.js new file mode 100644 index 0000000000..26e0980944 --- /dev/null +++ b/platform/commonUI/general/src/ui/ToggleView.js @@ -0,0 +1,61 @@ +/***************************************************************************** + * Open MCT Web, Copyright (c) 2014-2015, United States Government + * as represented by the Administrator of the National Aeronautics and Space + * Administration. All rights reserved. + * + * Open MCT Web is licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + * Open MCT Web includes source code licensed under additional open source + * licenses. See the Open Source Licenses file (LICENSES.md) included with + * this source code distribution or the Licensing information page available + * at runtime from the About dialog for additional information. + *****************************************************************************/ +/*global define*/ + +define([ + 'angular', + 'text!../../res/templates/ui/toggle.html' +], function (angular, toggleTemplate) { + function ToggleView(state) { + this.expanded = !!state; + this.callbacks = []; + this.el = angular.element(toggleTemplate); + this.el.on('click', function () { + this.model(!this.expanded); + }.bind(this)); + } + + ToggleView.prototype.model = function (state) { + this.expanded = state; + + if (state) { + this.el.addClass('expanded'); + } else { + this.el.removeClass('expanded'); + } + + this.callbacks.forEach(function (callback) { + callback(state); + }); + }; + + ToggleView.prototype.observe = function (callback) { + this.callbacks.push(callback); + return function () { + this.callbacks = this.callbacks.filter(function (c) { + return c !== callback; + }); + }.bind(this); + }; + + return ToggleView; +}); diff --git a/platform/commonUI/general/src/ui/TreeNodeView.js b/platform/commonUI/general/src/ui/TreeNodeView.js index e69de29bb2..5fe7eab514 100644 --- a/platform/commonUI/general/src/ui/TreeNodeView.js +++ b/platform/commonUI/general/src/ui/TreeNodeView.js @@ -0,0 +1,70 @@ +/***************************************************************************** + * Open MCT Web, Copyright (c) 2014-2015, United States Government + * as represented by the Administrator of the National Aeronautics and Space + * Administration. All rights reserved. + * + * Open MCT Web is licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + * Open MCT Web includes source code licensed under additional open source + * licenses. See the Open Source Licenses file (LICENSES.md) included with + * this source code distribution or the Licensing information page available + * at runtime from the About dialog for additional information. + *****************************************************************************/ +/*global define*/ + +define([ + 'angular', + 'text!../../res/templates/ui/node.html' +], function (angular, nodeTemplate) { + 'use strict'; + + var $ = angular.element.bind(angular); + + function TreeNodeView(subtreeFactory) { + this.factory = subtreeFactory; + this.li = $('
    • '); + this.expanded = false; + } + + TreeNodeView.prototype.populateContents = function (domainObject) { + if (this.li.children().length === 0) { + this.li.append($(nodeTemplate)); + } + + + }; + + TreeNodeView.prototype.model = function (domainObject) { + if (this.unlisten) { + this.unlisten(); + } + + if (domainObject) { + this.unlisten = domainObject.getCapability('mutation') + .listen(this.populateContents.bind(this)); + this.populateContents(domainObject); + } else { + this.li.empty(); + } + }; + + /** + * + * @returns {HTMLElement[]} + */ + TreeNodeView.prototype.elements = function () { + return this.li; + }; + + + return TreeNodeView; +}); \ No newline at end of file diff --git a/platform/commonUI/general/src/ui/TreeView.js b/platform/commonUI/general/src/ui/TreeView.js index 4032711321..5e2f0b0877 100644 --- a/platform/commonUI/general/src/ui/TreeView.js +++ b/platform/commonUI/general/src/ui/TreeView.js @@ -22,7 +22,8 @@ /*global define*/ define([ - 'angular' + 'angular', + './TreeNodeView' ], function (angular, TreeNodeView) { 'use strict'; @@ -34,11 +35,15 @@ define([ this.nodeViews = []; } + function newTreeView() { + return new TreeView(); + } + TreeView.prototype.setSize = function (sz) { var nodeView; while (this.nodeViews.length < sz) { - nodeView = new TreeNodeView(); + nodeView = new TreeNodeView(newTreeView); this.nodeViews.push(nodeView); this.ul.append($(nodeView.elements())); } From cebf9f73dafc8c1451a2390d2eec072991cfbb8e Mon Sep 17 00:00:00 2001 From: Victor Woeltjen Date: Fri, 11 Mar 2016 12:29:24 -0800 Subject: [PATCH 05/27] [Tree] Begin adding tree label --- .../res/templates/tree/tree-label.html | 8 ++++ .../commonUI/general/src/ui/ToggleView.js | 4 ++ .../commonUI/general/src/ui/TreeLabelView.js | 45 +++++++++++++++++++ .../commonUI/general/src/ui/TreeNodeView.js | 28 +++++++++--- 4 files changed, 79 insertions(+), 6 deletions(-) create mode 100644 platform/commonUI/general/res/templates/tree/tree-label.html create mode 100644 platform/commonUI/general/src/ui/TreeLabelView.js diff --git a/platform/commonUI/general/res/templates/tree/tree-label.html b/platform/commonUI/general/res/templates/tree/tree-label.html new file mode 100644 index 0000000000..ae1db92951 --- /dev/null +++ b/platform/commonUI/general/res/templates/tree/tree-label.html @@ -0,0 +1,8 @@ + +
      +
      +
      {{type.getGlyph()}}
      +
      +
      {{model.name}}
      +
      +
      diff --git a/platform/commonUI/general/src/ui/ToggleView.js b/platform/commonUI/general/src/ui/ToggleView.js index 26e0980944..346df43e73 100644 --- a/platform/commonUI/general/src/ui/ToggleView.js +++ b/platform/commonUI/general/src/ui/ToggleView.js @@ -57,5 +57,9 @@ define([ }.bind(this); }; + ToggleView.prototype.elements = function () { + return this.el; + }; + return ToggleView; }); diff --git a/platform/commonUI/general/src/ui/TreeLabelView.js b/platform/commonUI/general/src/ui/TreeLabelView.js new file mode 100644 index 0000000000..239125a706 --- /dev/null +++ b/platform/commonUI/general/src/ui/TreeLabelView.js @@ -0,0 +1,45 @@ +/***************************************************************************** + * Open MCT Web, Copyright (c) 2014-2015, United States Government + * as represented by the Administrator of the National Aeronautics and Space + * Administration. All rights reserved. + * + * Open MCT Web is licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + * Open MCT Web includes source code licensed under additional open source + * licenses. See the Open Source Licenses file (LICENSES.md) included with + * this source code distribution or the Licensing information page available + * at runtime from the About dialog for additional information. + *****************************************************************************/ +/*global define*/ + +define([ + 'angular', + 'text!../../res/templates/ui/tree-label.html' +], function (angular, labelTemplate) { + 'use strict'; + + var $ = angular.element.bind(angular); + + function TreeLabelView() { + this.el = $(labelTemplate); + } + + TreeLabelView.prototype.model = function (domainObject) { + + }; + + TreeLabelView.prototype.elements = function () { + return this.el; + }; + + return TreeLabelView; +}); diff --git a/platform/commonUI/general/src/ui/TreeNodeView.js b/platform/commonUI/general/src/ui/TreeNodeView.js index 5fe7eab514..3867d057c5 100644 --- a/platform/commonUI/general/src/ui/TreeNodeView.js +++ b/platform/commonUI/general/src/ui/TreeNodeView.js @@ -23,24 +23,34 @@ define([ 'angular', - 'text!../../res/templates/ui/node.html' -], function (angular, nodeTemplate) { + 'text!../../res/templates/ui/node.html', + './ToggleView' +], function (angular, nodeTemplate, ToggleView) { 'use strict'; var $ = angular.element.bind(angular); function TreeNodeView(subtreeFactory) { - this.factory = subtreeFactory; this.li = $('
    • '); - this.expanded = false; + + this.toggleView = new ToggleView(false); + this.toggleView.observe(function (state) { + if (state) { + if (!this.subtreeView) { + this.subtreeView = subtreeFactory(); + this.subtreeView.model(this.activeObject); + } + $(this.subtreeView.elements()).removeClass('hidden'); + } else if (this.subtreeView) { + $(this.subtreeView.elements()).addClass('hidden'); + } + }.bind(this)); } TreeNodeView.prototype.populateContents = function (domainObject) { if (this.li.children().length === 0) { this.li.append($(nodeTemplate)); } - - }; TreeNodeView.prototype.model = function (domainObject) { @@ -48,6 +58,8 @@ define([ this.unlisten(); } + this.activeObject = domainObject; + if (domainObject) { this.unlisten = domainObject.getCapability('mutation') .listen(this.populateContents.bind(this)); @@ -55,6 +67,10 @@ define([ } else { this.li.empty(); } + + if (this.subtreeView) { + this.subtreeView.model(domainObject); + } }; /** From 4f293f22a63b52fc34217a481028fc2dbb9eaa90 Mon Sep 17 00:00:00 2001 From: Victor Woeltjen Date: Fri, 11 Mar 2016 12:38:40 -0800 Subject: [PATCH 06/27] [Tree] Add Zepto dependency ...to support implementation of a jQuery-less tree. --- LICENSES.md | 38 +++++++++++++++++++++++++++++ bower.json | 3 ++- main.js | 3 ++- platform/commonUI/general/bundle.js | 10 ++++++++ test-main.js | 3 ++- 5 files changed, 54 insertions(+), 3 deletions(-) diff --git a/LICENSES.md b/LICENSES.md index 6e270d3937..e7ab92507b 100644 --- a/LICENSES.md +++ b/LICENSES.md @@ -476,6 +476,44 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI --- +### Zepto + +#### Info + +* Link: http://zeptojs.com/ + +* Version: 1.1.6 + +* Authors: Thomas Fuchs + +* Description: DOM manipulation + +#### License + +Copyright (c) 2010-2016 Thomas Fuchs +http://zeptojs.com/ + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--- + ### Json.NET #### Info diff --git a/bower.json b/bower.json index b4bf273af2..7285aad9e2 100644 --- a/bower.json +++ b/bower.json @@ -17,6 +17,7 @@ "screenfull": "^3.0.0", "node-uuid": "^1.4.7", "comma-separated-values": "^3.6.4", - "FileSaver.js": "^0.0.2" + "FileSaver.js": "^0.0.2", + "zepto": "^1.1.6" } } diff --git a/main.js b/main.js index 452fe3e823..ec8a2dcb80 100644 --- a/main.js +++ b/main.js @@ -33,7 +33,8 @@ requirejs.config({ "saveAs": "bower_components/FileSaver.js/FileSaver.min", "screenfull": "bower_components/screenfull/dist/screenfull.min", "text": "bower_components/text/text", - "uuid": "bower_components/node-uuid/uuid" + "uuid": "bower_components/node-uuid/uuid", + "zepto": "bower_components/zepto/zepto.min" }, "shim": { "angular": { diff --git a/platform/commonUI/general/bundle.js b/platform/commonUI/general/bundle.js index f3d6d98f61..ecc9f9f8a1 100644 --- a/platform/commonUI/general/bundle.js +++ b/platform/commonUI/general/bundle.js @@ -535,6 +535,16 @@ define([ "copyright": "Copyright (c) Nicolas Gallagher and Jonathan Neal", "license": "license-mit", "link": "https://github.com/necolas/normalize.css/blob/v1.1.2/LICENSE.md" + }, + { + "name": "Zepto", + "version": "1.1.6", + "description": "DOM manipulation", + "author": "Thomas Fuchs", + "website": "http://zeptojs.com/", + "copyright": "Copyright (c) 2010-2016 Thomas Fuchs", + "license": "license-mit", + "link": "https://github.com/madrobby/zepto/blob/master/MIT-LICENSE" } ] } diff --git a/test-main.js b/test-main.js index 13f1bf367d..a12970dd58 100644 --- a/test-main.js +++ b/test-main.js @@ -53,7 +53,8 @@ requirejs.config({ "saveAs": "bower_components/FileSaver.js/FileSaver.min", "screenfull": "bower_components/screenfull/dist/screenfull.min", "text": "bower_components/text/text", - "uuid": "bower_components/node-uuid/uuid" + "uuid": "bower_components/node-uuid/uuid", + "zepto": "bower_components/zepto/zepto.min" }, "shim": { From c5ab6c6c9781486156cb9d4f885f689e176fb31b Mon Sep 17 00:00:00 2001 From: Victor Woeltjen Date: Fri, 11 Mar 2016 14:10:30 -0800 Subject: [PATCH 07/27] [Tree] Implement label for tree --- .../res/templates/tree/tree-label.html | 6 +-- .../commonUI/general/src/ui/TreeLabelView.js | 38 ++++++++++++++++--- 2 files changed, 36 insertions(+), 8 deletions(-) diff --git a/platform/commonUI/general/res/templates/tree/tree-label.html b/platform/commonUI/general/res/templates/tree/tree-label.html index ae1db92951..8c6dcb2e86 100644 --- a/platform/commonUI/general/res/templates/tree/tree-label.html +++ b/platform/commonUI/general/res/templates/tree/tree-label.html @@ -1,8 +1,8 @@
      -
      -
      {{type.getGlyph()}}
      +
      +
      -
      {{model.name}}
      +
      diff --git a/platform/commonUI/general/src/ui/TreeLabelView.js b/platform/commonUI/general/src/ui/TreeLabelView.js index 239125a706..f60aad5369 100644 --- a/platform/commonUI/general/src/ui/TreeLabelView.js +++ b/platform/commonUI/general/src/ui/TreeLabelView.js @@ -22,19 +22,47 @@ /*global define*/ define([ - 'angular', + 'zepto', 'text!../../res/templates/ui/tree-label.html' -], function (angular, labelTemplate) { +], function ($, labelTemplate) { 'use strict'; - var $ = angular.element.bind(angular); - function TreeLabelView() { this.el = $(labelTemplate); } + function getGlyph(domainObject) { + var type = domainObject.getCapability('type'); + return type.getGlyph(); + } + + TreeLabelView.prototype.updateView = function (domainObject) { + var titleEl = this.el.find('.t-title-label'), + glyphEl = this.el.find('.t-item-icon-glyph'), + iconEl = this.el.find('.t-item-icon'); + + titleEl.text(domainObject ? domainObject.getModel().name : ""); + glyphEl.text(domainObject ? getGlyph(domainObject) : ""); + + if (domainObject && isLink(domainObject)) { + iconEl.addClass('l-icon-link'); + } else { + iconEl.removeClass('l-icon-link'); + } + }; + TreeLabelView.prototype.model = function (domainObject) { - + if (this.unlisten) { + this.unlisten(); + delete this.unlisten; + } + + this.updateView(domainObject); + + if (domainObject) { + this.unlisten = domainObject.getCapability('mutation') + .listen(this.updateView.bind(this)); + } }; TreeLabelView.prototype.elements = function () { From cbd950926035ae11081a55acd1594efdb23ccc6a Mon Sep 17 00:00:00 2001 From: Victor Woeltjen Date: Fri, 11 Mar 2016 14:13:14 -0800 Subject: [PATCH 08/27] [Tree] Use TreeView from mct-tree --- .../general/src/directives/MCTTree.js | 33 +++++++------------ 1 file changed, 12 insertions(+), 21 deletions(-) diff --git a/platform/commonUI/general/src/directives/MCTTree.js b/platform/commonUI/general/src/directives/MCTTree.js index 74eb840f51..473511cc96 100644 --- a/platform/commonUI/general/src/directives/MCTTree.js +++ b/platform/commonUI/general/src/directives/MCTTree.js @@ -22,30 +22,21 @@ /*global define*/ define([ - 'text!../../res/templates/subtree.html', - 'text!../../res/templates/tree/node.html' -], function (subtreeTemplate, nodeTemplate) { - function MCTTreeController($scope, $element, $compile) { - var ul = $element.filter('ul'), - makeNode = $compile(nodeTemplate), - activeObject, - unlisten; - - - - - $scope.$watch('mctObject', changeObject); - } - + 'angular', + '../ui/TreeView' +], function (angular, TreeView) { function MCTTree() { + function link(scope, element) { + var treeView = new TreeView(); + + element.append(angular.element(treeView.elements())); + + scope.$watch('mctObject', treeView.model.bind(treeView)); + } + return { restrict: "E", - controller: [ - '$scope', - '$element', - '$compile', - MCTTreeController - ], + link: link, require: [ "mctTree" ], scope: { mctObject: "=" }, template: "" From d4b15525ca58eef3c039f42c20f306c884f6a5a9 Mon Sep 17 00:00:00 2001 From: Victor Woeltjen Date: Fri, 11 Mar 2016 14:23:08 -0800 Subject: [PATCH 09/27] [Tree] Begin using mct-tree for tree representation --- platform/commonUI/general/bundle.js | 6 ++++++ .../general/res/templates/subtree.html | 18 +++--------------- .../commonUI/general/src/directives/MCTTree.js | 4 +--- platform/commonUI/general/src/ui/ToggleView.js | 2 +- .../commonUI/general/src/ui/TreeLabelView.js | 2 +- .../commonUI/general/src/ui/TreeNodeView.js | 2 +- platform/commonUI/general/src/ui/TreeView.js | 3 +-- 7 files changed, 14 insertions(+), 23 deletions(-) diff --git a/platform/commonUI/general/bundle.js b/platform/commonUI/general/bundle.js index ecc9f9f8a1..8e810aec20 100644 --- a/platform/commonUI/general/bundle.js +++ b/platform/commonUI/general/bundle.js @@ -49,6 +49,7 @@ define([ "./src/directives/MCTScroll", "./src/directives/MCTSplitPane", "./src/directives/MCTSplitter", + "./src/directives/MCTTree", "text!./res/templates/bottombar.html", "text!./res/templates/controls/action-button.html", "text!./res/templates/controls/input-filter.html", @@ -97,6 +98,7 @@ define([ MCTScroll, MCTSplitPane, MCTSplitter, + MCTTree, bottombarTemplate, actionButtonTemplate, inputFilterTemplate, @@ -389,6 +391,10 @@ define([ { "key": "mctSplitter", "implementation": MCTSplitter + }, + { + "key": "mctTree", + "implementation": MCTTree } ], "constants": [ diff --git a/platform/commonUI/general/res/templates/subtree.html b/platform/commonUI/general/res/templates/subtree.html index 637b73a8c4..df16327e8c 100644 --- a/platform/commonUI/general/res/templates/subtree.html +++ b/platform/commonUI/general/res/templates/subtree.html @@ -19,18 +19,6 @@ this source code distribution or the Licensing information page available at runtime from the About dialog for additional information. --> -
        -
      • - - - Loading... - -
      • -
      • - - -
      • -
      + + + diff --git a/platform/commonUI/general/src/directives/MCTTree.js b/platform/commonUI/general/src/directives/MCTTree.js index 473511cc96..fb0f63f956 100644 --- a/platform/commonUI/general/src/directives/MCTTree.js +++ b/platform/commonUI/general/src/directives/MCTTree.js @@ -37,9 +37,7 @@ define([ return { restrict: "E", link: link, - require: [ "mctTree" ], - scope: { mctObject: "=" }, - template: "" + scope: { mctObject: "=" } }; } diff --git a/platform/commonUI/general/src/ui/ToggleView.js b/platform/commonUI/general/src/ui/ToggleView.js index 346df43e73..030ac5b416 100644 --- a/platform/commonUI/general/src/ui/ToggleView.js +++ b/platform/commonUI/general/src/ui/ToggleView.js @@ -23,7 +23,7 @@ define([ 'angular', - 'text!../../res/templates/ui/toggle.html' + 'text!../../res/templates/tree/toggle.html' ], function (angular, toggleTemplate) { function ToggleView(state) { this.expanded = !!state; diff --git a/platform/commonUI/general/src/ui/TreeLabelView.js b/platform/commonUI/general/src/ui/TreeLabelView.js index f60aad5369..33db6115f0 100644 --- a/platform/commonUI/general/src/ui/TreeLabelView.js +++ b/platform/commonUI/general/src/ui/TreeLabelView.js @@ -23,7 +23,7 @@ define([ 'zepto', - 'text!../../res/templates/ui/tree-label.html' + 'text!../../res/templates/tree/tree-label.html' ], function ($, labelTemplate) { 'use strict'; diff --git a/platform/commonUI/general/src/ui/TreeNodeView.js b/platform/commonUI/general/src/ui/TreeNodeView.js index 3867d057c5..e84149834f 100644 --- a/platform/commonUI/general/src/ui/TreeNodeView.js +++ b/platform/commonUI/general/src/ui/TreeNodeView.js @@ -23,7 +23,7 @@ define([ 'angular', - 'text!../../res/templates/ui/node.html', + 'text!../../res/templates/tree/node.html', './ToggleView' ], function (angular, nodeTemplate, ToggleView) { 'use strict'; diff --git a/platform/commonUI/general/src/ui/TreeView.js b/platform/commonUI/general/src/ui/TreeView.js index 5e2f0b0877..4e73c45071 100644 --- a/platform/commonUI/general/src/ui/TreeView.js +++ b/platform/commonUI/general/src/ui/TreeView.js @@ -30,8 +30,7 @@ define([ var $ = angular.element.bind(angular); function TreeView() { - this.ul = $('
        '); - this.ul.addClass('tree'); + this.ul = $('
          '); this.nodeViews = []; } From dc2b3e85cc23904acde374b006b47385376936f8 Mon Sep 17 00:00:00 2001 From: Victor Woeltjen Date: Fri, 11 Mar 2016 14:33:05 -0800 Subject: [PATCH 10/27] [Tree] Show tree with toggle --- main.js | 3 ++ .../general/res/templates/tree/node.html | 4 --- .../commonUI/general/src/ui/TreeLabelView.js | 5 ++++ .../commonUI/general/src/ui/TreeNodeView.js | 29 ++++++++++--------- 4 files changed, 24 insertions(+), 17 deletions(-) diff --git a/main.js b/main.js index ec8a2dcb80..8ce58e1ac1 100644 --- a/main.js +++ b/main.js @@ -45,6 +45,9 @@ requirejs.config({ }, "moment-duration-format": { "deps": [ "moment" ] + }, + "zepto": { + "exports": "Zepto" } } }); diff --git a/platform/commonUI/general/res/templates/tree/node.html b/platform/commonUI/general/res/templates/tree/node.html index 2041a39cca..d6012b5ea9 100644 --- a/platform/commonUI/general/res/templates/tree/node.html +++ b/platform/commonUI/general/res/templates/tree/node.html @@ -1,8 +1,4 @@ - - - - diff --git a/platform/commonUI/general/src/ui/TreeLabelView.js b/platform/commonUI/general/src/ui/TreeLabelView.js index 33db6115f0..512e1b49e4 100644 --- a/platform/commonUI/general/src/ui/TreeLabelView.js +++ b/platform/commonUI/general/src/ui/TreeLabelView.js @@ -36,6 +36,11 @@ define([ return type.getGlyph(); } + function isLink(domainObject) { + var location = domainObject.getCapability('location'); + return location.isLink(); + } + TreeLabelView.prototype.updateView = function (domainObject) { var titleEl = this.el.find('.t-title-label'), glyphEl = this.el.find('.t-item-icon-glyph'), diff --git a/platform/commonUI/general/src/ui/TreeNodeView.js b/platform/commonUI/general/src/ui/TreeNodeView.js index e84149834f..ede9bf2a90 100644 --- a/platform/commonUI/general/src/ui/TreeNodeView.js +++ b/platform/commonUI/general/src/ui/TreeNodeView.js @@ -24,8 +24,9 @@ define([ 'angular', 'text!../../res/templates/tree/node.html', - './ToggleView' -], function (angular, nodeTemplate, ToggleView) { + './ToggleView', + './TreeLabelView' +], function (angular, nodeTemplate, ToggleView, TreeLabelView) { 'use strict'; var $ = angular.element.bind(angular); @@ -45,13 +46,16 @@ define([ $(this.subtreeView.elements()).addClass('hidden'); } }.bind(this)); - } - TreeNodeView.prototype.populateContents = function (domainObject) { - if (this.li.children().length === 0) { - this.li.append($(nodeTemplate)); - } - }; + this.labelView = new TreeLabelView(); + + this.li.append($(nodeTemplate)); + this.li.find('span').eq(0) + .append(this.toggleView.elements()) + .append(this.labelView.elements()); + + this.model(undefined); + } TreeNodeView.prototype.model = function (domainObject) { if (this.unlisten) { @@ -60,14 +64,13 @@ define([ this.activeObject = domainObject; - if (domainObject) { - this.unlisten = domainObject.getCapability('mutation') - .listen(this.populateContents.bind(this)); - this.populateContents(domainObject); + if (domainObject && domainObject.hasCapability('composition')) { + $(this.toggleView.elements()).addClass('has-children'); } else { - this.li.empty(); + $(this.toggleView.elements()).removeClass('has-children'); } + this.labelView.model(domainObject); if (this.subtreeView) { this.subtreeView.model(domainObject); } From 7ee8d0a3f738aedf189ee64b507614981088cc7e Mon Sep 17 00:00:00 2001 From: Victor Woeltjen Date: Fri, 11 Mar 2016 14:40:04 -0800 Subject: [PATCH 11/27] [Tree] Display tree correctly --- platform/commonUI/general/src/ui/ToggleView.js | 6 +++--- platform/commonUI/general/src/ui/TreeNodeView.js | 12 ++++++------ platform/commonUI/general/src/ui/TreeView.js | 6 ++---- 3 files changed, 11 insertions(+), 13 deletions(-) diff --git a/platform/commonUI/general/src/ui/ToggleView.js b/platform/commonUI/general/src/ui/ToggleView.js index 030ac5b416..4c8fed722d 100644 --- a/platform/commonUI/general/src/ui/ToggleView.js +++ b/platform/commonUI/general/src/ui/ToggleView.js @@ -22,13 +22,13 @@ /*global define*/ define([ - 'angular', + 'zepto', 'text!../../res/templates/tree/toggle.html' -], function (angular, toggleTemplate) { +], function ($, toggleTemplate) { function ToggleView(state) { this.expanded = !!state; this.callbacks = []; - this.el = angular.element(toggleTemplate); + this.el = $(toggleTemplate); this.el.on('click', function () { this.model(!this.expanded); }.bind(this)); diff --git a/platform/commonUI/general/src/ui/TreeNodeView.js b/platform/commonUI/general/src/ui/TreeNodeView.js index ede9bf2a90..3b54422668 100644 --- a/platform/commonUI/general/src/ui/TreeNodeView.js +++ b/platform/commonUI/general/src/ui/TreeNodeView.js @@ -22,15 +22,13 @@ /*global define*/ define([ - 'angular', + 'zepto', 'text!../../res/templates/tree/node.html', './ToggleView', './TreeLabelView' -], function (angular, nodeTemplate, ToggleView, TreeLabelView) { +], function ($, nodeTemplate, ToggleView, TreeLabelView) { 'use strict'; - var $ = angular.element.bind(angular); - function TreeNodeView(subtreeFactory) { this.li = $('
        • '); @@ -40,6 +38,8 @@ define([ if (!this.subtreeView) { this.subtreeView = subtreeFactory(); this.subtreeView.model(this.activeObject); + this.li.find('.tree-item-subtree').eq(0) + .append($(this.subtreeView.elements())); } $(this.subtreeView.elements()).removeClass('hidden'); } else if (this.subtreeView) { @@ -51,8 +51,8 @@ define([ this.li.append($(nodeTemplate)); this.li.find('span').eq(0) - .append(this.toggleView.elements()) - .append(this.labelView.elements()); + .append($(this.toggleView.elements())) + .append($(this.labelView.elements())); this.model(undefined); } diff --git a/platform/commonUI/general/src/ui/TreeView.js b/platform/commonUI/general/src/ui/TreeView.js index 4e73c45071..5777321a88 100644 --- a/platform/commonUI/general/src/ui/TreeView.js +++ b/platform/commonUI/general/src/ui/TreeView.js @@ -22,13 +22,11 @@ /*global define*/ define([ - 'angular', + 'zepto', './TreeNodeView' -], function (angular, TreeNodeView) { +], function ($, TreeNodeView) { 'use strict'; - var $ = angular.element.bind(angular); - function TreeView() { this.ul = $('
            '); this.nodeViews = []; From 4a8222a15234aa8f01ce8c3989eea1920e48d60c Mon Sep 17 00:00:00 2001 From: Victor Woeltjen Date: Fri, 11 Mar 2016 14:47:50 -0800 Subject: [PATCH 12/27] [Tree] Update labels on mutation --- platform/commonUI/general/src/ui/TreeLabelView.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/commonUI/general/src/ui/TreeLabelView.js b/platform/commonUI/general/src/ui/TreeLabelView.js index 512e1b49e4..0c1144a8bc 100644 --- a/platform/commonUI/general/src/ui/TreeLabelView.js +++ b/platform/commonUI/general/src/ui/TreeLabelView.js @@ -66,7 +66,7 @@ define([ if (domainObject) { this.unlisten = domainObject.getCapability('mutation') - .listen(this.updateView.bind(this)); + .listen(this.updateView.bind(this, domainObject)); } }; From 03ab3bddc47f0af16fca35ed3ce322eb00bd6328 Mon Sep 17 00:00:00 2001 From: Victor Woeltjen Date: Fri, 11 Mar 2016 17:00:55 -0800 Subject: [PATCH 13/27] [Tree] Begin handling selection state --- .../commonUI/general/src/ui/ToggleView.js | 4 +-- .../commonUI/general/src/ui/TreeNodeView.js | 32 ++++++++++++++++++- platform/commonUI/general/src/ui/TreeView.js | 18 ++++++++++- 3 files changed, 50 insertions(+), 4 deletions(-) diff --git a/platform/commonUI/general/src/ui/ToggleView.js b/platform/commonUI/general/src/ui/ToggleView.js index 4c8fed722d..c347ac3837 100644 --- a/platform/commonUI/general/src/ui/ToggleView.js +++ b/platform/commonUI/general/src/ui/ToggleView.js @@ -30,11 +30,11 @@ define([ this.callbacks = []; this.el = $(toggleTemplate); this.el.on('click', function () { - this.model(!this.expanded); + this.value(!this.expanded); }.bind(this)); } - ToggleView.prototype.model = function (state) { + ToggleView.prototype.value = function (state) { this.expanded = state; if (state) { diff --git a/platform/commonUI/general/src/ui/TreeNodeView.js b/platform/commonUI/general/src/ui/TreeNodeView.js index 3b54422668..d6637b6722 100644 --- a/platform/commonUI/general/src/ui/TreeNodeView.js +++ b/platform/commonUI/general/src/ui/TreeNodeView.js @@ -76,6 +76,36 @@ define([ } }; + TreeNodeView.prototype.value = function (domainObject) { + var activeIdPath = getIdPath(this.activeObject), + selectedIdPath = getIdPath(domainObject); + + if (this.onSelectionPath) { + this.li.find('.tree-item').eq(0).removeClass('selected'); + if (this.subtreeView) { + this.subtreeView.value(undefined); + } + } + + this.onSelectionPath = + !!domainObject && + !!this.activeObject && + (activeIdPath.length <= selectedIdPath.length) && + activeIdPath.every(function (id, index) { + return selectedIdPath[index] === id; + }); + + if (this.onSelectionPath) { + if (activeIdPath.length === selectedIdPath.length) { + this.li.find('.tree-item').eq(0).addClass('selected'); + } else { + // Expand to reveal the selection + this.toggleView.value(true); + this.subtreeView.value(domainObject); + } + } + }; + /** * * @returns {HTMLElement[]} @@ -86,4 +116,4 @@ define([ return TreeNodeView; -}); \ No newline at end of file +}); diff --git a/platform/commonUI/general/src/ui/TreeView.js b/platform/commonUI/general/src/ui/TreeView.js index 5777321a88..6a4d7618f4 100644 --- a/platform/commonUI/general/src/ui/TreeView.js +++ b/platform/commonUI/general/src/ui/TreeView.js @@ -30,6 +30,7 @@ define([ function TreeView() { this.ul = $('
              '); this.nodeViews = []; + this.callbacks = []; } function newTreeView() { @@ -62,6 +63,7 @@ define([ if (domainObject === self.activeObject) { self.setSize(domainObjects.length); domainObjects.forEach(addNode); + self.updateNodeViewSelection(); } } @@ -87,6 +89,20 @@ define([ } }; + TreeView.prototype.updateNodeViewSelection = function () { + this.nodeViews.forEach(function (nodeView) { + nodeView.value(this.selectedObject); + }); + }; + + TreeView.prototype.value = function (domainObject) { + this.selectedObject = domainObject; + this.updateNodeViewSelection(); + this.callbacks.forEach(function (callback) { + callback(domainObject); + }); + }; + /** * * @returns {HTMLElement[]} @@ -97,4 +113,4 @@ define([ return TreeView; -}); \ No newline at end of file +}); From 82b61664085f99fe520ed2e2357c71b8aebaa937 Mon Sep 17 00:00:00 2001 From: Victor Woeltjen Date: Fri, 11 Mar 2016 17:09:17 -0800 Subject: [PATCH 14/27] [Tree] Begin wiring in selection --- platform/commonUI/general/res/templates/subtree.html | 2 +- platform/commonUI/general/src/directives/MCTTree.js | 10 +++++++--- platform/commonUI/general/src/ui/TreeView.js | 10 ++++++++++ 3 files changed, 18 insertions(+), 4 deletions(-) diff --git a/platform/commonUI/general/res/templates/subtree.html b/platform/commonUI/general/res/templates/subtree.html index df16327e8c..abc7a0d34a 100644 --- a/platform/commonUI/general/res/templates/subtree.html +++ b/platform/commonUI/general/res/templates/subtree.html @@ -19,6 +19,6 @@ this source code distribution or the Licensing information page available at runtime from the About dialog for additional information. --> - + diff --git a/platform/commonUI/general/src/directives/MCTTree.js b/platform/commonUI/general/src/directives/MCTTree.js index fb0f63f956..29d2e00ba7 100644 --- a/platform/commonUI/general/src/directives/MCTTree.js +++ b/platform/commonUI/general/src/directives/MCTTree.js @@ -25,13 +25,17 @@ define([ 'angular', '../ui/TreeView' ], function (angular, TreeView) { - function MCTTree() { - function link(scope, element) { - var treeView = new TreeView(); + function MCTTree($parse) { + function link(scope, element, attrs) { + var treeView = new TreeView(), + expr = $parse(attrs.mctModel), + unobserve = treeView.observe(expr.assign.bind(expr, scope)); element.append(angular.element(treeView.elements())); + scope.$parent.$watch(attrs.mctModel, treeView.value.bind(treeView)); scope.$watch('mctObject', treeView.model.bind(treeView)); + scope.$on('$destroy', unobserve); } return { diff --git a/platform/commonUI/general/src/ui/TreeView.js b/platform/commonUI/general/src/ui/TreeView.js index 6a4d7618f4..a0c635322e 100644 --- a/platform/commonUI/general/src/ui/TreeView.js +++ b/platform/commonUI/general/src/ui/TreeView.js @@ -103,6 +103,16 @@ define([ }); }; + TreeView.prototype.observe = function (callback) { + callback(this.selectedObject); + this.callbacks.push(callback); + return function () { + this.callbacks = this.callbacks.filter(function (c) { + return c !== callback; + }); + }.bind(this); + }; + /** * * @returns {HTMLElement[]} From 217e697079eb709a3d139a0206f782e04530be67 Mon Sep 17 00:00:00 2001 From: Victor Woeltjen Date: Fri, 11 Mar 2016 17:26:00 -0800 Subject: [PATCH 15/27] [Tree] Display selection state --- platform/commonUI/general/bundle.js | 3 ++- platform/commonUI/general/src/ui/TreeNodeView.js | 10 ++++++++++ platform/commonUI/general/src/ui/TreeView.js | 2 +- 3 files changed, 13 insertions(+), 2 deletions(-) diff --git a/platform/commonUI/general/bundle.js b/platform/commonUI/general/bundle.js index 8e810aec20..d86801e2ea 100644 --- a/platform/commonUI/general/bundle.js +++ b/platform/commonUI/general/bundle.js @@ -394,7 +394,8 @@ define([ }, { "key": "mctTree", - "implementation": MCTTree + "implementation": MCTTree, + "depends": [ '$parse' ] } ], "constants": [ diff --git a/platform/commonUI/general/src/ui/TreeNodeView.js b/platform/commonUI/general/src/ui/TreeNodeView.js index d6637b6722..9481bfdf9e 100644 --- a/platform/commonUI/general/src/ui/TreeNodeView.js +++ b/platform/commonUI/general/src/ui/TreeNodeView.js @@ -76,6 +76,16 @@ define([ } }; + function getIdPath(domainObject) { + function getId(domainObject) { + return domainObject.getId(); + } + + return domainObject ? + domainObject.getCapability('context').getPath().map(getId) : + []; + } + TreeNodeView.prototype.value = function (domainObject) { var activeIdPath = getIdPath(this.activeObject), selectedIdPath = getIdPath(domainObject); diff --git a/platform/commonUI/general/src/ui/TreeView.js b/platform/commonUI/general/src/ui/TreeView.js index a0c635322e..120c3230c8 100644 --- a/platform/commonUI/general/src/ui/TreeView.js +++ b/platform/commonUI/general/src/ui/TreeView.js @@ -92,7 +92,7 @@ define([ TreeView.prototype.updateNodeViewSelection = function () { this.nodeViews.forEach(function (nodeView) { nodeView.value(this.selectedObject); - }); + }.bind(this)); }; TreeView.prototype.value = function (domainObject) { From a3a9393d1bfcf3b27b552ffe2fc65495125c03dc Mon Sep 17 00:00:00 2001 From: Victor Woeltjen Date: Fri, 11 Mar 2016 17:32:57 -0800 Subject: [PATCH 16/27] [Tree] Change selection on click --- platform/commonUI/general/src/directives/MCTTree.js | 3 ++- platform/commonUI/general/src/ui/TreeNodeView.js | 8 ++++++-- platform/commonUI/general/src/ui/TreeView.js | 13 ++++++++----- 3 files changed, 16 insertions(+), 8 deletions(-) diff --git a/platform/commonUI/general/src/directives/MCTTree.js b/platform/commonUI/general/src/directives/MCTTree.js index 29d2e00ba7..c48d1775a7 100644 --- a/platform/commonUI/general/src/directives/MCTTree.js +++ b/platform/commonUI/general/src/directives/MCTTree.js @@ -29,7 +29,8 @@ define([ function link(scope, element, attrs) { var treeView = new TreeView(), expr = $parse(attrs.mctModel), - unobserve = treeView.observe(expr.assign.bind(expr, scope)); + assign = expr.assign.bind(expr, scope.$parent), + unobserve = treeView.observe(assign); element.append(angular.element(treeView.elements())); diff --git a/platform/commonUI/general/src/ui/TreeNodeView.js b/platform/commonUI/general/src/ui/TreeNodeView.js index 9481bfdf9e..b639c024f3 100644 --- a/platform/commonUI/general/src/ui/TreeNodeView.js +++ b/platform/commonUI/general/src/ui/TreeNodeView.js @@ -29,7 +29,7 @@ define([ ], function ($, nodeTemplate, ToggleView, TreeLabelView) { 'use strict'; - function TreeNodeView(subtreeFactory) { + function TreeNodeView(subtreeFactory, selectFn) { this.li = $('
            • '); this.toggleView = new ToggleView(false); @@ -49,6 +49,10 @@ define([ this.labelView = new TreeLabelView(); + $(this.labelView.elements()).on('click', function () { + selectFn(this.activeObject); + }.bind(this)); + this.li.append($(nodeTemplate)); this.li.find('span').eq(0) .append($(this.toggleView.elements())) @@ -80,7 +84,7 @@ define([ function getId(domainObject) { return domainObject.getId(); } - + return domainObject ? domainObject.getCapability('context').getPath().map(getId) : []; diff --git a/platform/commonUI/general/src/ui/TreeView.js b/platform/commonUI/general/src/ui/TreeView.js index 120c3230c8..594fec2894 100644 --- a/platform/commonUI/general/src/ui/TreeView.js +++ b/platform/commonUI/general/src/ui/TreeView.js @@ -27,21 +27,25 @@ define([ ], function ($, TreeNodeView) { 'use strict'; - function TreeView() { + function TreeView(selectFn) { this.ul = $('
                '); this.nodeViews = []; this.callbacks = []; + this.selectFn = selectFn || this.value.bind(this); } - function newTreeView() { - return new TreeView(); + TreeView.prototype.newTreeView = function () { + return new TreeView(this.selectFn); } TreeView.prototype.setSize = function (sz) { var nodeView; while (this.nodeViews.length < sz) { - nodeView = new TreeNodeView(newTreeView); + nodeView = new TreeNodeView( + this.newTreeView.bind(this), + this.selectFn + ); this.nodeViews.push(nodeView); this.ul.append($(nodeView.elements())); } @@ -104,7 +108,6 @@ define([ }; TreeView.prototype.observe = function (callback) { - callback(this.selectedObject); this.callbacks.push(callback); return function () { this.callbacks = this.callbacks.filter(function (c) { From 02ec6db104ea759053c85cc991e984f3b6289ee1 Mon Sep 17 00:00:00 2001 From: Victor Woeltjen Date: Fri, 11 Mar 2016 17:37:11 -0800 Subject: [PATCH 17/27] [Tree] Trigger digest on tree selection change --- platform/commonUI/general/src/directives/MCTTree.js | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/platform/commonUI/general/src/directives/MCTTree.js b/platform/commonUI/general/src/directives/MCTTree.js index c48d1775a7..18641b3941 100644 --- a/platform/commonUI/general/src/directives/MCTTree.js +++ b/platform/commonUI/general/src/directives/MCTTree.js @@ -29,8 +29,12 @@ define([ function link(scope, element, attrs) { var treeView = new TreeView(), expr = $parse(attrs.mctModel), - assign = expr.assign.bind(expr, scope.$parent), - unobserve = treeView.observe(assign); + unobserve = treeView.observe(function (domainObject) { + if (domainObject !== expr(scope.$parent)) { + expr.assign(scope.$parent, domainObject); + scope.$apply(); + } + }); element.append(angular.element(treeView.elements())); From f7ba24c0b6db99f29779c2976ee29c3eebf5cf18 Mon Sep 17 00:00:00 2001 From: Victor Woeltjen Date: Fri, 11 Mar 2016 17:43:18 -0800 Subject: [PATCH 18/27] [Tree] Enable gestures on labels --- platform/commonUI/general/bundle.js | 2 +- .../commonUI/general/src/directives/MCTTree.js | 4 ++-- platform/commonUI/general/src/ui/TreeLabelView.js | 14 +++++++++++++- platform/commonUI/general/src/ui/TreeNodeView.js | 4 ++-- platform/commonUI/general/src/ui/TreeView.js | 8 +++++--- 5 files changed, 23 insertions(+), 9 deletions(-) diff --git a/platform/commonUI/general/bundle.js b/platform/commonUI/general/bundle.js index d86801e2ea..02512fc9fd 100644 --- a/platform/commonUI/general/bundle.js +++ b/platform/commonUI/general/bundle.js @@ -395,7 +395,7 @@ define([ { "key": "mctTree", "implementation": MCTTree, - "depends": [ '$parse' ] + "depends": [ '$parse', 'gestureService' ] } ], "constants": [ diff --git a/platform/commonUI/general/src/directives/MCTTree.js b/platform/commonUI/general/src/directives/MCTTree.js index 18641b3941..47f8eecbc6 100644 --- a/platform/commonUI/general/src/directives/MCTTree.js +++ b/platform/commonUI/general/src/directives/MCTTree.js @@ -25,9 +25,9 @@ define([ 'angular', '../ui/TreeView' ], function (angular, TreeView) { - function MCTTree($parse) { + function MCTTree($parse, gestureService) { function link(scope, element, attrs) { - var treeView = new TreeView(), + var treeView = new TreeView(gestureService), expr = $parse(attrs.mctModel), unobserve = treeView.observe(function (domainObject) { if (domainObject !== expr(scope.$parent)) { diff --git a/platform/commonUI/general/src/ui/TreeLabelView.js b/platform/commonUI/general/src/ui/TreeLabelView.js index 0c1144a8bc..75e8efcc29 100644 --- a/platform/commonUI/general/src/ui/TreeLabelView.js +++ b/platform/commonUI/general/src/ui/TreeLabelView.js @@ -27,8 +27,9 @@ define([ ], function ($, labelTemplate) { 'use strict'; - function TreeLabelView() { + function TreeLabelView(gestureService) { this.el = $(labelTemplate); + this.gestureService = gestureService; } function getGlyph(domainObject) { @@ -62,11 +63,22 @@ define([ delete this.unlisten; } + if (this.activeGestures) { + this.activeGestures.destroy(); + delete this.activeGestures; + } + this.updateView(domainObject); if (domainObject) { this.unlisten = domainObject.getCapability('mutation') .listen(this.updateView.bind(this, domainObject)); + + this.activeGestures = this.gestureService.attachGestures( + this.elements(), + domainObject, + [ 'info', 'menu', 'drag' ] + ); } }; diff --git a/platform/commonUI/general/src/ui/TreeNodeView.js b/platform/commonUI/general/src/ui/TreeNodeView.js index b639c024f3..2b02a2c1f9 100644 --- a/platform/commonUI/general/src/ui/TreeNodeView.js +++ b/platform/commonUI/general/src/ui/TreeNodeView.js @@ -29,7 +29,7 @@ define([ ], function ($, nodeTemplate, ToggleView, TreeLabelView) { 'use strict'; - function TreeNodeView(subtreeFactory, selectFn) { + function TreeNodeView(gestureService, subtreeFactory, selectFn) { this.li = $('
              • '); this.toggleView = new ToggleView(false); @@ -47,7 +47,7 @@ define([ } }.bind(this)); - this.labelView = new TreeLabelView(); + this.labelView = new TreeLabelView(gestureService); $(this.labelView.elements()).on('click', function () { selectFn(this.activeObject); diff --git a/platform/commonUI/general/src/ui/TreeView.js b/platform/commonUI/general/src/ui/TreeView.js index 594fec2894..b1e9e6398e 100644 --- a/platform/commonUI/general/src/ui/TreeView.js +++ b/platform/commonUI/general/src/ui/TreeView.js @@ -27,22 +27,24 @@ define([ ], function ($, TreeNodeView) { 'use strict'; - function TreeView(selectFn) { + function TreeView(gestureService, selectFn) { this.ul = $('
                  '); this.nodeViews = []; this.callbacks = []; this.selectFn = selectFn || this.value.bind(this); + this.gestureService = gestureService; } TreeView.prototype.newTreeView = function () { - return new TreeView(this.selectFn); - } + return new TreeView(this.gestureService, this.selectFn); + }; TreeView.prototype.setSize = function (sz) { var nodeView; while (this.nodeViews.length < sz) { nodeView = new TreeNodeView( + this.gestureService, this.newTreeView.bind(this), this.selectFn ); From d789e91c185a29c57d541c380cd5c63672734ed4 Mon Sep 17 00:00:00 2001 From: Victor Woeltjen Date: Fri, 11 Mar 2016 18:00:58 -0800 Subject: [PATCH 19/27] [Tree] Add wait spinner --- .../general/res/templates/tree/wait-node.html | 27 +++++++++++++++++++ platform/commonUI/general/src/ui/TreeView.js | 15 ++++++++--- 2 files changed, 39 insertions(+), 3 deletions(-) create mode 100644 platform/commonUI/general/res/templates/tree/wait-node.html diff --git a/platform/commonUI/general/res/templates/tree/wait-node.html b/platform/commonUI/general/res/templates/tree/wait-node.html new file mode 100644 index 0000000000..79dffa73b5 --- /dev/null +++ b/platform/commonUI/general/res/templates/tree/wait-node.html @@ -0,0 +1,27 @@ + +
                • + + + Loading... + +
                • diff --git a/platform/commonUI/general/src/ui/TreeView.js b/platform/commonUI/general/src/ui/TreeView.js index b1e9e6398e..b09256388d 100644 --- a/platform/commonUI/general/src/ui/TreeView.js +++ b/platform/commonUI/general/src/ui/TreeView.js @@ -23,8 +23,9 @@ define([ 'zepto', - './TreeNodeView' -], function ($, TreeNodeView) { + './TreeNodeView', + 'text!../../res/templates/tree/wait-node.html' +], function ($, TreeNodeView, spinnerTemplate) { 'use strict'; function TreeView(gestureService, selectFn) { @@ -33,6 +34,7 @@ define([ this.callbacks = []; this.selectFn = selectFn || this.value.bind(this); this.gestureService = gestureService; + this.pending = false; } TreeView.prototype.newTreeView = function () { @@ -66,6 +68,12 @@ define([ } function addNodes(domainObjects) { + if (self.pending) { + self.pending = false; + self.nodeViews = []; + self.ul.empty(); + } + if (domainObject === self.activeObject) { self.setSize(domainObjects.length); domainObjects.forEach(addNode); @@ -73,7 +81,6 @@ define([ } } - // TODO: Add pending indicator domainObject.useCapability('composition') .then(addNodes); }; @@ -87,6 +94,8 @@ define([ this.ul.empty(); if (domainObject && domainObject.hasCapability('composition')) { + this.pending = true; + this.ul.append($(spinnerTemplate)); this.unlisten = domainObject.getCapability('mutation') .listen(this.loadComposition.bind(this)); this.loadComposition(domainObject); From 0e1df444df83ff91ddb2172b497a28423d7299d2 Mon Sep 17 00:00:00 2001 From: Victor Woeltjen Date: Mon, 14 Mar 2016 12:21:58 -0700 Subject: [PATCH 20/27] [Tree] Update test configuration ...to account for new dependency on Zepto (and its necessary shim.) --- test-main.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/test-main.js b/test-main.js index a12970dd58..6e4729f050 100644 --- a/test-main.js +++ b/test-main.js @@ -66,6 +66,9 @@ requirejs.config({ }, "moment-duration-format": { "deps": [ "moment" ] + }, + "zepto": { + "exports": "Zepto" } }, From 43492d31bad0df5ad773e6fb82ef527e086681df Mon Sep 17 00:00:00 2001 From: Victor Woeltjen Date: Mon, 14 Mar 2016 12:22:09 -0700 Subject: [PATCH 21/27] [Tree] Begin writing spec for TreeView --- .../commonUI/general/test/ui/TreeViewSpec.js | 64 +++++++++++++++++++ 1 file changed, 64 insertions(+) create mode 100644 platform/commonUI/general/test/ui/TreeViewSpec.js diff --git a/platform/commonUI/general/test/ui/TreeViewSpec.js b/platform/commonUI/general/test/ui/TreeViewSpec.js new file mode 100644 index 0000000000..4e2db01bb2 --- /dev/null +++ b/platform/commonUI/general/test/ui/TreeViewSpec.js @@ -0,0 +1,64 @@ +/***************************************************************************** + * Open MCT Web, Copyright (c) 2014-2015, United States Government + * as represented by the Administrator of the National Aeronautics and Space + * Administration. All rights reserved. + * + * Open MCT Web is licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + * Open MCT Web includes source code licensed under additional open source + * licenses. See the Open Source Licenses file (LICENSES.md) included with + * this source code distribution or the Licensing information page available + * at runtime from the About dialog for additional information. + *****************************************************************************/ +/*global define,describe,beforeEach,jasmine,it,expect*/ + +define([ + '../../src/ui/TreeView' +], function (TreeView) { + 'use strict'; + + describe("TreeView", function () { + var mockGestureService, + mockSelectFn, + mockGestureHandle, + treeView; + + beforeEach(function () { + mockGestureService = jasmine.createSpyObj( + 'gestureService', + [ 'attachGestures' ] + ); + + mockSelectFn = jasmine.createSpy('select'); + + mockGestureHandle = jasmine.createSpyObj('gestures', ['destroy']); + + mockGestureService.attachGestures.andReturn(mockGestureHandle); + + treeView = new TreeView(mockGestureService, mockSelectFn); + }); + + describe("elements", function () { + var elements; + + beforeEach(function () { + elements = treeView.elements(); + }); + + it("is an unordered list", function () { + expect(elements[0].tagName.toLowerCase()) + .toEqual('ul'); + }); + }); + }); + +}); From ecb37c54bef9e13b398567eb3f26bf07e28da213 Mon Sep 17 00:00:00 2001 From: Victor Woeltjen Date: Mon, 14 Mar 2016 12:52:33 -0700 Subject: [PATCH 22/27] [Tree] Add TreeView test cases --- .../commonUI/general/test/ui/TreeViewSpec.js | 139 +++++++++++++++++- 1 file changed, 135 insertions(+), 4 deletions(-) diff --git a/platform/commonUI/general/test/ui/TreeViewSpec.js b/platform/commonUI/general/test/ui/TreeViewSpec.js index 4e2db01bb2..249c7cf4df 100644 --- a/platform/commonUI/general/test/ui/TreeViewSpec.js +++ b/platform/commonUI/general/test/ui/TreeViewSpec.js @@ -28,8 +28,11 @@ define([ describe("TreeView", function () { var mockGestureService, - mockSelectFn, mockGestureHandle, + mockDomainObject, + mockMutation, + mockUnlisten, + testCapabilities, treeView; beforeEach(function () { @@ -38,13 +41,38 @@ define([ [ 'attachGestures' ] ); - mockSelectFn = jasmine.createSpy('select'); - mockGestureHandle = jasmine.createSpyObj('gestures', ['destroy']); mockGestureService.attachGestures.andReturn(mockGestureHandle); - treeView = new TreeView(mockGestureService, mockSelectFn); + mockDomainObject = jasmine.createSpyObj( + 'domainObject', + [ + 'getId', + 'getModel', + 'getCapability', + 'hasCapability', + 'useCapability' + ] + ); + + mockMutation = jasmine.createSpyObj('mutation', ['listen']); + mockUnlisten = jasmine.createSpy('unlisten'); + mockMutation.listen.andReturn(mockUnlisten); + + testCapabilities = { mutation: mockMutation }; + + mockDomainObject.hasCapability.andCallFake(function (c) { + return !!(testCapabilities[c]); + }); + mockDomainObject.getCapability.andCallFake(function (c) { + return testCapabilities[c]; + }); + mockDomainObject.useCapability.andCallFake(function (c) { + return testCapabilities[c] && testCapabilities[c].invoke(); + }); + + treeView = new TreeView(mockGestureService); }); describe("elements", function () { @@ -59,6 +87,109 @@ define([ .toEqual('ul'); }); }); + + describe("model", function () { + var mockComposition; + + function waitForCompositionCallback() { + var calledBack = false; + testCapabilities.composition.invoke().then(function () { + calledBack = true; + }); + waitsFor(function () { + return calledBack; + }); + } + + beforeEach(function () { + mockComposition = ['a', 'b', 'c'].map(function (id) { + var mockDomainObject = jasmine.createSpyObj( + 'domainObject-' + id, + [ + 'getId', + 'getModel', + 'getCapability', + 'hasCapability', + 'useCapability' + ] + ); + mockDomainObject.getId.andReturn(id); + mockDomainObject.getModel.andReturn({}); + return mockDomainObject; + }); + + testCapabilities.composition = jasmine.createSpyObj( + 'composition', + ['invoke'] + ); + testCapabilities.composition.invoke + .andReturn(Promise.resolve(mockComposition)); + + treeView.model(mockDomainObject); + waitForCompositionCallback(); + }); + + it("adds one node per composition element", function () { + expect(treeView.elements()[0].childElementCount) + .toEqual(mockComposition.length); + }); + + it("listens for mutation", function () { + expect(testCapabilities.mutation.listen) + .toHaveBeenCalledWith(jasmine.any(Function)); + }); + + describe("when mutation occurs", function () { + beforeEach(function () { + mockComposition.pop(); + testCapabilities.mutation.listen + .mostRecentCall.args[0](mockDomainObject); + waitForCompositionCallback(); + }); + + it("continues to show one node per composition element", function () { + expect(treeView.elements()[0].childElementCount) + .toEqual(mockComposition.length); + }); + }); + + describe("when replaced with a non-compositional domain object", function () { + beforeEach(function () { + delete testCapabilities.composition; + treeView.model(mockDomainObject); + }); + + it("stops listening for mutation", function () { + expect(mockUnlisten).toHaveBeenCalled(); + }); + + it("removes all tree nodes", function () { + expect(treeView.elements()[0].childElementCount) + .toEqual(0); + }); + }); + }); + + describe("observe", function () { + var mockCallback, + unobserve; + + beforeEach(function () { + mockCallback = jasmine.createSpy('callback'); + unobserve = treeView.observe(mockCallback); + }); + + it("notifies listeners when value is changed", function () { + treeView.value(mockDomainObject); + expect(mockCallback).toHaveBeenCalledWith(mockDomainObject); + }); + + it("does not notify listeners when deactivated", function () { + unobserve(); + treeView.value(mockDomainObject); + expect(mockCallback).not.toHaveBeenCalled(); + }); + }); }); }); From 8b51ae32d22ee2865453bda9ba27687c7c8dbe33 Mon Sep 17 00:00:00 2001 From: Victor Woeltjen Date: Mon, 14 Mar 2016 13:04:46 -0700 Subject: [PATCH 23/27] [Tree] Begin testing selection change --- .../commonUI/general/test/ui/TreeViewSpec.js | 54 +++++++++++++------ 1 file changed, 39 insertions(+), 15 deletions(-) diff --git a/platform/commonUI/general/test/ui/TreeViewSpec.js b/platform/commonUI/general/test/ui/TreeViewSpec.js index 249c7cf4df..9e58f257bd 100644 --- a/platform/commonUI/general/test/ui/TreeViewSpec.js +++ b/platform/commonUI/general/test/ui/TreeViewSpec.js @@ -22,8 +22,9 @@ /*global define,describe,beforeEach,jasmine,it,expect*/ define([ - '../../src/ui/TreeView' -], function (TreeView) { + '../../src/ui/TreeView', + 'zepto' +], function (TreeView, $) { 'use strict'; describe("TreeView", function () { @@ -62,6 +63,7 @@ define([ testCapabilities = { mutation: mockMutation }; + mockDomainObject.getId.andReturn('parent'); mockDomainObject.hasCapability.andCallFake(function (c) { return !!(testCapabilities[c]); }); @@ -103,19 +105,28 @@ define([ beforeEach(function () { mockComposition = ['a', 'b', 'c'].map(function (id) { - var mockDomainObject = jasmine.createSpyObj( - 'domainObject-' + id, - [ - 'getId', - 'getModel', - 'getCapability', - 'hasCapability', - 'useCapability' - ] - ); - mockDomainObject.getId.andReturn(id); - mockDomainObject.getModel.andReturn({}); - return mockDomainObject; + var mockChild = jasmine.createSpyObj( + 'domainObject-' + id, + [ + 'getId', + 'getModel', + 'getCapability', + 'hasCapability', + 'useCapability' + ] + ), + mockContext = jasmine.createSpyObj( + 'context', + [ 'getPath' ] + ); + mockChild.getId.andReturn(id); + mockChild.getModel.andReturn({}); + mockChild.getCapability.andCallFake(function (c) { + return c === 'context' && mockContext; + }); + mockContext.getPath + .andReturn([mockDomainObject, mockChild]); + return mockChild; }); testCapabilities.composition = jasmine.createSpyObj( @@ -168,6 +179,19 @@ define([ .toEqual(0); }); }); + + describe("when selection state changes", function () { + var selectionIndex = 1; + + beforeEach(function () { + treeView.value(mockComposition[selectionIndex]); + }); + + it("communicates selection state to an appropriate node", function () { + var selected = $(treeView.elements()[0]).find('.selected'); + expect(selected.length).toEqual(1); + }); + }); }); describe("observe", function () { From 8f94751a350326453672ec948461276dcf8e3d77 Mon Sep 17 00:00:00 2001 From: Victor Woeltjen Date: Mon, 14 Mar 2016 14:14:34 -0700 Subject: [PATCH 24/27] [Tree] Add capabilities to child objects for testing --- .../commonUI/general/test/ui/TreeViewSpec.js | 94 ++++++++++--------- 1 file changed, 48 insertions(+), 46 deletions(-) diff --git a/platform/commonUI/general/test/ui/TreeViewSpec.js b/platform/commonUI/general/test/ui/TreeViewSpec.js index 9e58f257bd..8b67248c2a 100644 --- a/platform/commonUI/general/test/ui/TreeViewSpec.js +++ b/platform/commonUI/general/test/ui/TreeViewSpec.js @@ -36,6 +36,31 @@ define([ testCapabilities, treeView; + function makeMockDomainObject(id, model, capabilities) { + var mockDomainObject = jasmine.createSpyObj( + 'domainObject-' + id, + [ + 'getId', + 'getModel', + 'getCapability', + 'hasCapability', + 'useCapability' + ] + ); + mockDomainObject.getId.andReturn(id); + mockDomainObject.getModel.andReturn(model); + mockDomainObject.hasCapability.andCallFake(function (c) { + return !!(capabilities[c]); + }); + mockDomainObject.getCapability.andCallFake(function (c) { + return capabilities[c]; + }); + mockDomainObject.useCapability.andCallFake(function (c) { + return capabilities[c] && capabilities[c].invoke(); + }); + return mockDomainObject; + } + beforeEach(function () { mockGestureService = jasmine.createSpyObj( 'gestureService', @@ -46,33 +71,14 @@ define([ mockGestureService.attachGestures.andReturn(mockGestureHandle); - mockDomainObject = jasmine.createSpyObj( - 'domainObject', - [ - 'getId', - 'getModel', - 'getCapability', - 'hasCapability', - 'useCapability' - ] - ); - mockMutation = jasmine.createSpyObj('mutation', ['listen']); mockUnlisten = jasmine.createSpy('unlisten'); mockMutation.listen.andReturn(mockUnlisten); testCapabilities = { mutation: mockMutation }; - mockDomainObject.getId.andReturn('parent'); - mockDomainObject.hasCapability.andCallFake(function (c) { - return !!(testCapabilities[c]); - }); - mockDomainObject.getCapability.andCallFake(function (c) { - return testCapabilities[c]; - }); - mockDomainObject.useCapability.andCallFake(function (c) { - return testCapabilities[c] && testCapabilities[c].invoke(); - }); + mockDomainObject = + makeMockDomainObject('parent', {}, testCapabilities); treeView = new TreeView(mockGestureService); }); @@ -94,8 +100,9 @@ define([ var mockComposition; function waitForCompositionCallback() { - var calledBack = false; - testCapabilities.composition.invoke().then(function () { + var calledBack = false, + n = Math.random(); + testCapabilities.composition.invoke().then(function (c) { calledBack = true; }); waitsFor(function () { @@ -105,34 +112,29 @@ define([ beforeEach(function () { mockComposition = ['a', 'b', 'c'].map(function (id) { - var mockChild = jasmine.createSpyObj( - 'domainObject-' + id, - [ - 'getId', - 'getModel', - 'getCapability', - 'hasCapability', - 'useCapability' - ] - ), - mockContext = jasmine.createSpyObj( - 'context', - [ 'getPath' ] - ); - mockChild.getId.andReturn(id); - mockChild.getModel.andReturn({}); - mockChild.getCapability.andCallFake(function (c) { - return c === 'context' && mockContext; - }); + var mockContext = + jasmine.createSpyObj('context', [ 'getPath' ]), + mockType = + jasmine.createSpyObj('type', [ 'getGlyph' ]), + mockLocation = + jasmine.createSpyObj('location', [ 'isLink' ]), + mockMutation = + jasmine.createSpyObj('mutation', [ 'listen' ]), + mockChild = makeMockDomainObject(id, {}, { + context: mockContext, + type: mockType, + mutation: mockMutation, + location: mockLocation + }); + mockContext.getPath .andReturn([mockDomainObject, mockChild]); + return mockChild; }); - testCapabilities.composition = jasmine.createSpyObj( - 'composition', - ['invoke'] - ); + testCapabilities.composition = + jasmine.createSpyObj('composition', ['invoke']); testCapabilities.composition.invoke .andReturn(Promise.resolve(mockComposition)); From d72aaf54ca93e72d9f8f5b2752303bf9da131cee Mon Sep 17 00:00:00 2001 From: Victor Woeltjen Date: Mon, 14 Mar 2016 14:40:46 -0700 Subject: [PATCH 25/27] [Tree] Test inner tree creation --- .../commonUI/general/test/ui/TreeViewSpec.js | 87 +++++++++++++++---- 1 file changed, 70 insertions(+), 17 deletions(-) diff --git a/platform/commonUI/general/test/ui/TreeViewSpec.js b/platform/commonUI/general/test/ui/TreeViewSpec.js index 8b67248c2a..370e5c8e10 100644 --- a/platform/commonUI/general/test/ui/TreeViewSpec.js +++ b/platform/commonUI/general/test/ui/TreeViewSpec.js @@ -99,9 +99,25 @@ define([ describe("model", function () { var mockComposition; + function makeGenericCapabilities() { + var mockContext = + jasmine.createSpyObj('context', [ 'getPath' ]), + mockType = + jasmine.createSpyObj('type', [ 'getGlyph' ]), + mockLocation = + jasmine.createSpyObj('location', [ 'isLink' ]), + mockMutation = + jasmine.createSpyObj('mutation', [ 'listen' ]); + return { + context: mockContext, + type: mockType, + mutation: mockMutation, + location: mockLocation + }; + } + function waitForCompositionCallback() { - var calledBack = false, - n = Math.random(); + var calledBack = false; testCapabilities.composition.invoke().then(function (c) { calledBack = true; }); @@ -112,22 +128,11 @@ define([ beforeEach(function () { mockComposition = ['a', 'b', 'c'].map(function (id) { - var mockContext = - jasmine.createSpyObj('context', [ 'getPath' ]), - mockType = - jasmine.createSpyObj('type', [ 'getGlyph' ]), - mockLocation = - jasmine.createSpyObj('location', [ 'isLink' ]), - mockMutation = - jasmine.createSpyObj('mutation', [ 'listen' ]), - mockChild = makeMockDomainObject(id, {}, { - context: mockContext, - type: mockType, - mutation: mockMutation, - location: mockLocation - }); + var testCapabilities = makeGenericCapabilities(), + mockChild = + makeMockDomainObject(id, {}, testCapabilities); - mockContext.getPath + testCapabilities.context.getPath .andReturn([mockDomainObject, mockChild]); return mockChild; @@ -194,6 +199,54 @@ define([ expect(selected.length).toEqual(1); }); }); + + describe("when children contain children", function () { + beforeEach(function () { + var newCapabilities = makeGenericCapabilities(), + gcCapabilities = makeGenericCapabilities(), + mockNewChild = + makeMockDomainObject('d', {}, newCapabilities), + mockGrandchild = + makeMockDomainObject('gc', {}, gcCapabilities), + calledBackInner = false; + + newCapabilities.composition = + jasmine.createSpyObj('composition', [ 'invoke' ]); + newCapabilities.composition.invoke + .andReturn(Promise.resolve([mockGrandchild])); + mockComposition.push(mockNewChild); + + newCapabilities.context.getPath.andReturn([ + mockDomainObject, + mockNewChild + ]); + gcCapabilities.context.getPath.andReturn([ + mockDomainObject, + mockNewChild, + mockGrandchild + ]); + + testCapabilities.mutation.listen + .mostRecentCall.args[0](mockDomainObject); + waitForCompositionCallback(); + runs(function () { + // Select the innermost object to force expansion, + // such that we can verify the subtree is present. + treeView.value(mockGrandchild); + newCapabilities.composition.invoke().then(function () { + calledBackInner = true; + }); + }); + waitsFor(function () { + return calledBackInner; + }); + }); + + it("creates inner trees", function () { + expect($(treeView.elements()[0]).find('ul').length) + .toEqual(1); + }); + }); }); describe("observe", function () { From d522570c0b72da2b7996180a61155f557f8184a2 Mon Sep 17 00:00:00 2001 From: Victor Woeltjen Date: Mon, 14 Mar 2016 14:54:57 -0700 Subject: [PATCH 26/27] [Tree] Add spec for mct-tree --- .../general/test/directives/MCTTreeSpec.js | 92 +++++++++++++++++++ 1 file changed, 92 insertions(+) create mode 100644 platform/commonUI/general/test/directives/MCTTreeSpec.js diff --git a/platform/commonUI/general/test/directives/MCTTreeSpec.js b/platform/commonUI/general/test/directives/MCTTreeSpec.js new file mode 100644 index 0000000000..e8d57e4ac8 --- /dev/null +++ b/platform/commonUI/general/test/directives/MCTTreeSpec.js @@ -0,0 +1,92 @@ +/***************************************************************************** + * Open MCT Web, Copyright (c) 2014-2015, United States Government + * as represented by the Administrator of the National Aeronautics and Space + * Administration. All rights reserved. + * + * Open MCT Web is licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + * Open MCT Web includes source code licensed under additional open source + * licenses. See the Open Source Licenses file (LICENSES.md) included with + * this source code distribution or the Licensing information page available + * at runtime from the About dialog for additional information. + *****************************************************************************/ +/*global define,describe,beforeEach,jasmine,it,expect*/ + +define([ + '../../src/directives/MCTTree' +], function (MCTTree) { + describe("The mct-tree directive", function () { + var mockParse, + mockGestureService, + mockExpr, + mctTree; + + beforeEach(function () { + mockGestureService = jasmine.createSpyObj( + 'gestureService', + [ 'attachGestures' ] + ); + mockParse = jasmine.createSpy('$parse'); + mockExpr = jasmine.createSpy('expr'); + mockExpr.assign = jasmine.createSpy('assign'); + mockParse.andReturn(mockExpr); + + mctTree = new MCTTree(mockParse, mockGestureService); + }); + + it("is applicable as an element", function () { + expect(mctTree.restrict).toEqual("E"); + }); + + it("two-way binds to mctObject", function () { + expect(mctTree.scope).toEqual({ mctObject: "=" }); + }); + + describe("link", function () { + var mockScope, + mockElement, + testAttrs; + + beforeEach(function () { + mockScope = jasmine.createSpyObj('$scope', ['$watch', '$on']); + mockElement = jasmine.createSpyObj('element', ['append']); + testAttrs = { mctModel: "some-expression" }; + mockScope.$parent = + jasmine.createSpyObj('$scope', ['$watch', '$on']); + mctTree.link(mockScope, mockElement, testAttrs); + }); + + it("populates the mct-tree element", function () { + expect(mockElement.append).toHaveBeenCalled(); + }); + + it("watches for mct-model's expression in the parent", function () { + expect(mockScope.$parent.$watch).toHaveBeenCalledWith( + testAttrs.mctModel, + jasmine.any(Function) + ); + }); + + it("watches for changes to mct-object", function () { + expect(mockScope.$watch).toHaveBeenCalledWith("mctObject"); + }); + + it("listens for the $destroy event", function () { + expect(mockScope.$on).toHaveBeenCalledWith( + "$destroy", + jasmine.any(Function) + ); + }); + }); + }); + +}); From 55ae755522e451c06c51fc37405bbaf1853bccec Mon Sep 17 00:00:00 2001 From: Victor Woeltjen Date: Mon, 14 Mar 2016 15:04:50 -0700 Subject: [PATCH 27/27] [Tree] Fix error in test case Correctly expect both arguments to $watch --- platform/commonUI/general/test/directives/MCTTreeSpec.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/platform/commonUI/general/test/directives/MCTTreeSpec.js b/platform/commonUI/general/test/directives/MCTTreeSpec.js index e8d57e4ac8..597c4c55b7 100644 --- a/platform/commonUI/general/test/directives/MCTTreeSpec.js +++ b/platform/commonUI/general/test/directives/MCTTreeSpec.js @@ -77,7 +77,10 @@ define([ }); it("watches for changes to mct-object", function () { - expect(mockScope.$watch).toHaveBeenCalledWith("mctObject"); + expect(mockScope.$watch).toHaveBeenCalledWith( + "mctObject", + jasmine.any(Function) + ); }); it("listens for the $destroy event", function () {