diff --git a/platform/commonUI/general/bundle.json b/platform/commonUI/general/bundle.json index 7cc15a48b3..e4e0de3861 100644 --- a/platform/commonUI/general/bundle.json +++ b/platform/commonUI/general/bundle.json @@ -116,10 +116,6 @@ "implementation": "controllers/GetterSetterController.js", "depends": [ "$scope" ] }, - { - "key": "SplitPaneController", - "implementation": "controllers/SplitPaneController.js" - }, { "key": "SelectorController", "implementation": "controllers/SelectorController.js", diff --git a/platform/commonUI/general/res/templates/containers/split-pane.html b/platform/commonUI/general/res/templates/containers/split-pane.html deleted file mode 100644 index 397c22314e..0000000000 --- a/platform/commonUI/general/res/templates/containers/split-pane.html +++ /dev/null @@ -1,30 +0,0 @@ - - -
-
-
-
-
\ No newline at end of file diff --git a/platform/commonUI/general/src/controllers/SplitPaneController.js b/platform/commonUI/general/src/controllers/SplitPaneController.js deleted file mode 100644 index 75dfed28d9..0000000000 --- a/platform/commonUI/general/src/controllers/SplitPaneController.js +++ /dev/null @@ -1,89 +0,0 @@ -/***************************************************************************** - * 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( - [], - function () { - "use strict"; - - var DEFAULT_MAXIMUM = 1000, - DEFAULT_MINIMUM = 120; - - /** - * Controller for the splitter in Browse mode. Current implementation - * uses many hard-coded constants; this could be generalized. - * @memberof platform/commonUI/general - * @constructor - */ - function SplitPaneController() { - this.current = 200; - this.start = 200; - this.assigned = false; - } - - /** - * Get the current position of the splitter, in pixels - * from the left edge. - * @returns {number} position of the splitter, in pixels - */ - SplitPaneController.prototype.state = function (defaultState) { - // Set the state to the desired default, if we don't have a - // "real" current state yet. - if (arguments.length > 0 && !this.assigned) { - this.current = defaultState; - this.assigned = true; - } - return this.current; - }; - - /** - * Begin moving the splitter; this will note the splitter's - * current position, which is necessary for correct - * interpretation of deltas provided by mct-drag. - */ - SplitPaneController.prototype.startMove = function () { - this.start = this.current; - }; - - /** - * Move the splitter a number of pixels to the right - * (negative numbers move the splitter to the left.) - * This movement is relative to the position of the - * splitter when startMove was last invoked. - * @param {number} delta number of pixels to move - */ - SplitPaneController.prototype.move = function (delta, minimum, maximum) { - // Ensure defaults for minimum/maximum - maximum = isNaN(maximum) ? DEFAULT_MAXIMUM : maximum; - minimum = isNaN(minimum) ? DEFAULT_MINIMUM : minimum; - - // Update current splitter state - this.current = Math.min( - maximum, - Math.max(minimum, this.start + delta) - ); - }; - - return SplitPaneController; - } -); diff --git a/platform/commonUI/general/test/controllers/SplitPaneControllerSpec.js b/platform/commonUI/general/test/controllers/SplitPaneControllerSpec.js deleted file mode 100644 index ee502e2e4e..0000000000 --- a/platform/commonUI/general/test/controllers/SplitPaneControllerSpec.js +++ /dev/null @@ -1,74 +0,0 @@ -/***************************************************************************** - * 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,Promise,describe,it,expect,beforeEach,waitsFor,jasmine*/ - -define( - ["../../src/controllers/SplitPaneController"], - function (SplitPaneController) { - "use strict"; - - describe("The split pane controller", function () { - var controller; - - beforeEach(function () { - controller = new SplitPaneController(); - }); - - it("has an initial position", function () { - expect(controller.state() > 0).toBeTruthy(); - }); - - it("can be moved", function () { - var initialState = controller.state(); - controller.startMove(); - controller.move(50); - expect(controller.state()).toEqual(initialState + 50); - }); - - it("clamps its position", function () { - var initialState = controller.state(); - controller.startMove(); - // Move some really extreme number - controller.move(-100000); - // Shouldn't have moved below 0... - expect(controller.state() > 0).toBeTruthy(); - // ...but should have moved left somewhere - expect(controller.state() < initialState).toBeTruthy(); - - // Then do the same to the right - controller.move(100000); - // Shouldn't have moved below 0... - expect(controller.state() < 100000).toBeTruthy(); - // ...but should have moved left somewhere - expect(controller.state() > initialState).toBeTruthy(); - }); - - it("accepts a default state", function () { - // Should use default state the first time... - expect(controller.state(12321)).toEqual(12321); - // ...but not after it's been initialized - expect(controller.state(42)).toEqual(12321); - }); - - }); - } -); \ No newline at end of file diff --git a/platform/commonUI/general/test/directives/MCTSplitPaneSpec.js b/platform/commonUI/general/test/directives/MCTSplitPaneSpec.js index 2d5d5ac5a0..0743f1a584 100644 --- a/platform/commonUI/general/test/directives/MCTSplitPaneSpec.js +++ b/platform/commonUI/general/test/directives/MCTSplitPaneSpec.js @@ -30,13 +30,16 @@ define( 'on', 'addClass', 'children', - 'eq' + 'eq', + 'toggleClass', + 'css' ]; describe("The mct-split-pane directive", function () { var mockParse, mockLog, mockInterval, + mockParsed, mctSplitPane; beforeEach(function () { @@ -45,6 +48,11 @@ define( jasmine.createSpyObj('$log', ['warn', 'info', 'debug']); mockInterval = jasmine.createSpy('$interval'); mockInterval.cancel = jasmine.createSpy('mockCancel'); + mockParsed = jasmine.createSpy('parsed'); + mockParsed.assign = jasmine.createSpy('assign'); + + mockParse.andReturn(mockParsed); + mctSplitPane = new MCTSplitPane( mockParse, mockLog, @@ -61,8 +69,19 @@ define( mockElement, testAttrs, mockChildren, + mockFirstPane, + mockSplitter, + mockSecondPane, controller; + function fireOn(eventType) { + mockScope.$on.calls.forEach(function (call) { + if (call.args[0] === eventType) { + call.args[1](); + } + }); + } + beforeEach(function () { mockScope = jasmine.createSpyObj('$scope', ['$apply', '$watch', '$on']); @@ -71,10 +90,33 @@ define( testAttrs = {}; mockChildren = jasmine.createSpyObj('children', JQLITE_METHODS); + mockFirstPane = + jasmine.createSpyObj('firstPane', JQLITE_METHODS); + mockSplitter = + jasmine.createSpyObj('splitter', JQLITE_METHODS); + mockSecondPane = + jasmine.createSpyObj('secondPane', JQLITE_METHODS); mockElement.children.andReturn(mockChildren); - mockChildren.eq.andReturn(mockChildren); - mockChildren[0] = {}; + mockElement[0] = { + offsetWidth: 12321, + offsetHeight: 45654 + }; + mockChildren.eq.andCallFake(function (i) { + return [mockFirstPane, mockSplitter, mockSecondPane][i]; + }); + mockFirstPane[0] = { offsetWidth: 123, offsetHeight: 456 }; + mockSplitter[0] = { + nodeName: 'mct-splitter', + offsetWidth: 10, + offsetHeight: 456 + }; + mockSecondPane[0] = { offsetWidth: 10, offsetHeight: 456 }; + + mockChildren[0] = mockFirstPane[0]; + mockChildren[1] = mockSplitter[0]; + mockChildren[3] = mockSecondPane[0]; + mockChildren.length = 3; controller = mctSplitPane.controller[3]( mockScope, @@ -87,6 +129,77 @@ define( expect(mockInterval.mostRecentCall.args[3]).toBe(false); }); + it("exposes its splitter's initial position", function () { + expect(controller.position()).toEqual( + mockFirstPane[0].offsetWidth + mockSplitter[0].offsetWidth + ); + }); + + it("exposes the current anchoring mode", function () { + expect(controller.anchor()).toEqual({ + edge : 'left', + opposite : 'right', + dimension : 'width', + orientation : 'vertical' + }); + }); + + it("allows classes to be toggled on contained elements", function () { + controller.toggleClass('resizing'); + expect(mockChildren.toggleClass) + .toHaveBeenCalledWith('resizing'); + }); + + it("allows positions to be set", function () { + var testValue = mockChildren[0].offsetWidth + 50; + controller.position(testValue); + expect(mockFirstPane.css).toHaveBeenCalledWith( + 'width', + (testValue - mockSplitter[0].offsetWidth) + 'px' + ); + }); + + it("issues no warnings under nominal usage", function () { + expect(mockLog.warn).not.toHaveBeenCalled(); + }); + + it("warns if no mct-splitter is present", function () { + mockSplitter[0].nodeName = "not-mct-splitter"; + controller = mctSplitPane.controller[3]( + mockScope, + mockElement, + testAttrs + ); + expect(mockLog.warn).toHaveBeenCalled(); + }); + + it("warns if an unknown anchor key is given", function () { + testAttrs.anchor = "middle"; + controller = mctSplitPane.controller[3]( + mockScope, + mockElement, + testAttrs + ); + expect(mockLog.warn).toHaveBeenCalled(); + }); + + it("updates positions on a timer", function () { + mockFirstPane[0].offsetWidth += 100; + // Should not reflect the change yet + expect(controller.position()).not.toEqual( + mockFirstPane[0].offsetWidth + mockSplitter[0].offsetWidth + ); + mockInterval.mostRecentCall.args[0](); + expect(controller.position()).toEqual( + mockFirstPane[0].offsetWidth + mockSplitter[0].offsetWidth + ); + }); + + it("cancels the active interval when scope is destroyed", function () { + expect(mockInterval.cancel).not.toHaveBeenCalled(); + fireOn('$destroy'); + expect(mockInterval.cancel).toHaveBeenCalled(); + }); }); }); diff --git a/platform/commonUI/general/test/directives/MCTSplitterSpec.js b/platform/commonUI/general/test/directives/MCTSplitterSpec.js new file mode 100644 index 0000000000..3aae62ccc2 --- /dev/null +++ b/platform/commonUI/general/test/directives/MCTSplitterSpec.js @@ -0,0 +1,113 @@ +/***************************************************************************** + * 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,Promise,describe,it,expect,beforeEach,waitsFor,jasmine*/ + +define( + ["../../src/directives/MCTSplitter"], + function (MCTSplitter) { + 'use strict'; + + describe("The mct-splitter directive", function () { + var mctSplitter; + + beforeEach(function () { + mctSplitter = new MCTSplitter(); + }); + + it("is applicable to elements", function () { + expect(mctSplitter.restrict).toEqual("E"); + }); + + it("depends on the mct-split-pane controller", function () { + expect(mctSplitter.require).toEqual("^mctSplitPane"); + }); + + describe("when linked", function () { + var mockScope, + mockElement, + testAttrs, + mockSplitPane; + + beforeEach(function () { + mockScope = jasmine.createSpyObj( + '$scope', + [ '$on', '$watch' ] + ); + mockElement = jasmine.createSpyObj( + 'element', + [ 'addClass' ] + ); + testAttrs = {}; + mockSplitPane = jasmine.createSpyObj( + 'mctSplitPane', + [ 'position', 'toggleClass', 'anchor' ] + ); + + mctSplitter.link( + mockScope, + mockElement, + testAttrs, + mockSplitPane + ); + }); + + it("adds a splitter class", function () { + expect(mockElement.addClass) + .toHaveBeenCalledWith('splitter'); + }); + + describe("and then manipulated", function () { + var testPosition; + + beforeEach(function () { + testPosition = 12321; + mockSplitPane.position.andReturn(testPosition); + mockSplitPane.anchor.andReturn({ + orientation: 'vertical', + reversed: false + }); + mockScope.splitter.startMove(); + }); + + it("adds a 'resizing' class", function () { + expect(mockSplitPane.toggleClass) + .toHaveBeenCalledWith('resizing'); + }); + + it("repositions during drag", function () { + mockScope.splitter.move([ 10, 0 ]); + expect(mockSplitPane.position) + .toHaveBeenCalledWith(testPosition + 10); + }); + + it("removes the 'resizing' class when finished", function () { + mockSplitPane.toggleClass.reset(); + mockScope.splitter.endMove(); + expect(mockSplitPane.toggleClass) + .toHaveBeenCalledWith('resizing'); + }); + + }); + }); + }); + } +); diff --git a/platform/commonUI/general/test/suite.json b/platform/commonUI/general/test/suite.json index 777001174a..5f3cf8bc64 100644 --- a/platform/commonUI/general/test/suite.json +++ b/platform/commonUI/general/test/suite.json @@ -8,7 +8,6 @@ "controllers/GetterSetterController", "controllers/ObjectInspectorController", "controllers/SelectorController", - "controllers/SplitPaneController", "controllers/TimeRangeController", "controllers/ToggleController", "controllers/TreeNodeController", @@ -20,6 +19,7 @@ "directives/MCTResize", "directives/MCTScroll", "directives/MCTSplitPane", + "directives/MCTSplitter", "services/Popup", "services/PopupService", "services/UrlService",