diff --git a/platform/commonUI/general/bundle.js b/platform/commonUI/general/bundle.js index f0454127d4..aeb05762b1 100644 --- a/platform/commonUI/general/bundle.js +++ b/platform/commonUI/general/bundle.js @@ -119,6 +119,12 @@ define([ ] } ], + "filters": [ + { + "implementation": "filters/ReverseFilter.js", + "key": "reverse" + } + ], "stylesheets": [ { "stylesheetUrl": "css/normalize.min.css", diff --git a/platform/commonUI/general/res/sass/plots/_plots-main.scss b/platform/commonUI/general/res/sass/plots/_plots-main.scss index a45bbc13ea..8f4327bb77 100644 --- a/platform/commonUI/general/res/sass/plots/_plots-main.scss +++ b/platform/commonUI/general/res/sass/plots/_plots-main.scss @@ -266,6 +266,8 @@ $plotDisplayArea: ($legendH + $interiorMargin, 0, $xBarH + $interiorMargin, $yBa .gl-plot-tick, .tick-label { + direction: rtl; + unicode-bidi:bidi-override; font-size: 0.7rem; position: absolute; overflow: hidden; diff --git a/platform/commonUI/general/res/templates/controls/datetime-field.html b/platform/commonUI/general/res/templates/controls/datetime-field.html index e9b394c530..18eb9ec46d 100644 --- a/platform/commonUI/general/res/templates/controls/datetime-field.html +++ b/platform/commonUI/general/res/templates/controls/datetime-field.html @@ -24,7 +24,11 @@ + ng-class="{ + error: textInvalid || + (structure.validate && + !structure.validate(ngModel[field])) + }"> C = start + outerMinimumSpan) { + $scope.ngModel = $scope.ngModel || {}; + $scope.ngModel.outer = { start: start, end: end }; + } + } + + function validateStart(startValue) { + return startValue <= $scope.formModel.end - outerMinimumSpan; + } + + function validateEnd(endValue) { + return endValue >= $scope.formModel.start + outerMinimumSpan; } $scope.startLeftDrag = startLeftDrag; @@ -249,6 +244,9 @@ define( $scope.updateBoundsFromForm = updateBoundsFromForm; + $scope.validateStart = validateStart; + $scope.validateEnd = validateEnd; + $scope.ticks = []; // Initialize scope to defaults diff --git a/platform/commonUI/general/src/filters/ReverseFilter.js b/platform/commonUI/general/src/filters/ReverseFilter.js new file mode 100644 index 0000000000..16ab9bc882 --- /dev/null +++ b/platform/commonUI/general/src/filters/ReverseFilter.js @@ -0,0 +1,44 @@ +/***************************************************************************** + * 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'; + + /** + * Implements the `reverse` filter, which reverses text strings. + * Useful in cases where text should be reversed for presentational + * reasons (e.g. in conjunction with CSS tricks involing text direction), + * allowing such behavior to be handled independently from the controller + * layer. + * + * @constructor + * @memberof platform/commonUI/general + */ + function ReverseFilter() { + return function reverse(value) { + return value && value.toString().split('').reverse().join(''); + }; + } + + return ReverseFilter; +}); diff --git a/platform/commonUI/general/test/controllers/TimeRangeControllerSpec.js b/platform/commonUI/general/test/controllers/TimeRangeControllerSpec.js index 861f28ed45..efff87651f 100644 --- a/platform/commonUI/general/test/controllers/TimeRangeControllerSpec.js +++ b/platform/commonUI/general/test/controllers/TimeRangeControllerSpec.js @@ -91,6 +91,24 @@ define( .toHaveBeenCalledWith("ngModel", jasmine.any(Function)); }); + it("exposes start time validator", function () { + var testValue = 42000000; + mockScope.formModel = { end: testValue }; + expect(mockScope.validateStart(testValue + 1)) + .toBe(false); + expect(mockScope.validateStart(testValue - 60 * 60 * 1000 - 1)) + .toBe(true); + }); + + it("exposes end time validator", function () { + var testValue = 42000000; + mockScope.formModel = { start: testValue }; + expect(mockScope.validateEnd(testValue - 1)) + .toBe(false); + expect(mockScope.validateEnd(testValue + 60 * 60 * 1000 + 1)) + .toBe(true); + }); + describe("when changes are made via form entry", function () { beforeEach(function () { mockScope.ngModel = { @@ -194,26 +212,6 @@ define( fireWatchCollection("ngModel", mockScope.ngModel); }); - it("enforces a minimum outer span", function () { - mockScope.ngModel.outer.end = - mockScope.ngModel.outer.start - DAY * 100; - fireWatch( - "ngModel.outer.end", - mockScope.ngModel.outer.end - ); - expect(mockScope.ngModel.outer.end) - .toBeGreaterThan(mockScope.ngModel.outer.start); - - mockScope.ngModel.outer.start = - mockScope.ngModel.outer.end + DAY * 100; - fireWatch( - "ngModel.outer.start", - mockScope.ngModel.outer.start - ); - expect(mockScope.ngModel.outer.end) - .toBeGreaterThan(mockScope.ngModel.outer.start); - }); - it("enforces a minimum inner span when outer span changes", function () { mockScope.ngModel.outer.end = mockScope.ngModel.outer.start - DAY * 100; diff --git a/platform/commonUI/general/test/filters/ReverseFilterSpec.js b/platform/commonUI/general/test/filters/ReverseFilterSpec.js new file mode 100644 index 0000000000..91b770c5a8 --- /dev/null +++ b/platform/commonUI/general/test/filters/ReverseFilterSpec.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,Promise,describe,it,expect,beforeEach,waitsFor,jasmine*/ + +define( + ['../../src/filters/ReverseFilter'], + function (ReverseFilter) { + 'use strict'; + + describe("The reverse filter", function () { + var reverse; + + beforeEach(function () { + reverse = new ReverseFilter(); + }); + + it("reverses text", function () { + expect(reverse('foo')).toEqual('oof'); + }); + + it("returns undefined for undefined inputs", function () { + expect(reverse(undefined)).toBeUndefined(); + }); + }); + } +); diff --git a/platform/commonUI/general/test/suite.json b/platform/commonUI/general/test/suite.json index 5f3cf8bc64..09d0bfd097 100644 --- a/platform/commonUI/general/test/suite.json +++ b/platform/commonUI/general/test/suite.json @@ -20,6 +20,7 @@ "directives/MCTScroll", "directives/MCTSplitPane", "directives/MCTSplitter", + "filters/ReverseFilter", "services/Popup", "services/PopupService", "services/UrlService", diff --git a/platform/commonUI/themes/espresso/res/css/theme-espresso.css b/platform/commonUI/themes/espresso/res/css/theme-espresso.css index 9fea0a877b..f0f0e41445 100644 --- a/platform/commonUI/themes/espresso/res/css/theme-espresso.css +++ b/platform/commonUI/themes/espresso/res/css/theme-espresso.css @@ -4299,10 +4299,10 @@ textarea { .field-hints, .fields { } - - + + .field-hints { - + } */ } /* line 30, ../../../../general/res/sass/forms/_datetime.scss */ @@ -7329,6 +7329,8 @@ table { /* line 267, ../../../../general/res/sass/plots/_plots-main.scss */ .gl-plot-tick, .tick-label { + direction: rtl; + unicode-bidi: bidi-override; font-size: 0.7rem; position: absolute; overflow: hidden; diff --git a/platform/commonUI/themes/snow/res/css/theme-snow.css b/platform/commonUI/themes/snow/res/css/theme-snow.css index 4866a5e379..2d227a1f87 100644 --- a/platform/commonUI/themes/snow/res/css/theme-snow.css +++ b/platform/commonUI/themes/snow/res/css/theme-snow.css @@ -4196,10 +4196,10 @@ textarea { .field-hints, .fields { } - - + + .field-hints { - + } */ } /* line 30, ../../../../general/res/sass/forms/_datetime.scss */ @@ -7202,6 +7202,8 @@ table { /* line 267, ../../../../general/res/sass/plots/_plots-main.scss */ .gl-plot-tick, .tick-label { + direction: rtl; + unicode-bidi: bidi-override; font-size: 0.7rem; position: absolute; overflow: hidden; diff --git a/platform/features/plot/res/templates/plot.html b/platform/features/plot/res/templates/plot.html index 3dc50408ee..12680c2b27 100644 --- a/platform/features/plot/res/templates/plot.html +++ b/platform/features/plot/res/templates/plot.html @@ -47,7 +47,7 @@
- {{tick.label}} + {{tick.label | reverse}}
@@ -125,7 +125,7 @@ class="gl-plot-tick gl-plot-x-tick-label" ng-show="$index > 0 && $index < (subplot.getDomainTicks().length - 1)" ng-style="{ left: (100 * $index / (subplot.getDomainTicks().length - 1)) + '%' }"> - {{tick.label}} + {{tick.label | reverse}}
{{axes[0].active.name}} diff --git a/platform/framework/src/register/CustomRegistrars.js b/platform/framework/src/register/CustomRegistrars.js index 0051105036..e47825e991 100644 --- a/platform/framework/src/register/CustomRegistrars.js +++ b/platform/framework/src/register/CustomRegistrars.js @@ -221,6 +221,13 @@ define( CustomRegistrars.prototype.services = mapUpon(customRegistrar("service")); + /** + * Register Angular filters. + * @param {Array} extensions the resolved extensions + */ + CustomRegistrars.prototype.filters = + mapUpon(customRegistrar("filter")); + /** * Register functions which will run after bootstrapping. * @param {Array} extensions the resolved extensions