From 985680d60dd4a203ebdcfeb9f8b798c72da21f2e Mon Sep 17 00:00:00 2001 From: Aaron Sahlin Date: Tue, 2 Jun 2015 15:26:00 -0500 Subject: [PATCH] JSCS cleanup - Angular framework widgets (partial2) We need to do cleanup before we can enable JSCS globally (https://review.openstack.org/#/c/185725/). Widgets included: modal, modal-wait-spinner, table, toast, transfer-table, wizard Change-Id: Ifa53fde6e0c4119a092e657fc07627ffb68dd248 Partially-Implements: blueprint jscs-cleanup --- .../modal-wait-spinner/modal-wait-spinner.js | 123 +++++++++--------- .../static/framework/widgets/modal/modal.js | 6 +- .../framework/widgets/table/basic-table.js | 51 ++++---- .../widgets/table/basic-table.spec.js | 2 +- .../static/framework/widgets/table/table.js | 73 ++++++----- .../framework/widgets/table/table.spec.js | 56 ++++---- .../static/framework/widgets/toast/toast.js | 22 ++-- .../framework/widgets/toast/toast.spec.js | 6 +- .../widgets/transfer-table/transfer-table.js | 2 +- .../transfer-table/transfer-table.spec.js | 6 +- .../static/framework/widgets/wizard/wizard.js | 14 +- .../framework/widgets/wizard/wizard.spec.js | 2 +- 12 files changed, 188 insertions(+), 175 deletions(-) diff --git a/horizon/static/framework/widgets/modal-wait-spinner/modal-wait-spinner.js b/horizon/static/framework/widgets/modal-wait-spinner/modal-wait-spinner.js index ba4f6f34ed..010b9feae7 100644 --- a/horizon/static/framework/widgets/modal-wait-spinner/modal-wait-spinner.js +++ b/horizon/static/framework/widgets/modal-wait-spinner/modal-wait-spinner.js @@ -17,44 +17,45 @@ (function () { 'use strict'; -/** - @ngdoc overview - @name horizon.framework.widgets.modal-wait-spinner - @description - A "global" wait spinner that displays a line of text followed by "...". - - Requires {@link http://angular-ui.github.io/bootstrap/ `Angular-bootstrap`} - - Used when the user must wait before any additional action is possible. Can be launched from modal dialogs. - - @example - -
-    .controller('MyController', [
-      '$scope',
-      'horizon.framework.widgets.modal.modal-wait-spinner.service',
-      function (modalWaitSpinnerService) {
-        $scope.showSpinner = function () {
-          modalWaitSpinnerService.showModalSpinner(gettext("Loading"));
-        }
-        $scope.hideSpinner = function () {
-          modalWaitSpinnerService.hideModalSpinner();
-         }
-      }
-    ])
-   
-
- - In order to provide a seamless transition to a Horizon that uses more Angular - based pages, the service is currently implemented using the existing - Spin.js library and the corresponding JQuery plugin (jquery.spin.js). This widget looks and feels - the same as the existing spinner we are familiar with in Horizon. Over time, uses of the existing - Horizon spinner ( horizon.modals.modal_spinner() ) can be phased out, or refactored to use this - component. - */ + /* + * @ngdoc overview + * @name horizon.framework.widgets.modal-wait-spinner + * @description + * A "global" wait spinner that displays a line of text followed by "...". + * + * Requires {@link http://angular-ui.github.io/bootstrap/ `Angular-bootstrap`} + * + * Used when the user must wait before any additional action is possible. Can be + * launched from modal dialogs. + * + * @example + * + *
+   *    .controller('MyController', [
+   *      '$scope',
+   *      'horizon.framework.widgets.modal.modal-wait-spinner.service',
+   *      function (modalWaitSpinnerService) {
+   *        $scope.showSpinner = function () {
+   *          modalWaitSpinnerService.showModalSpinner(gettext("Loading"));
+   *        }
+   *        $scope.hideSpinner = function () {
+   *          modalWaitSpinnerService.hideModalSpinner();
+   *        }
+   *      }
+   *    ])
+   *   
+ *
+ * + * In order to provide a seamless transition to a Horizon that uses more Angular + * based pages, the service is currently implemented using the existing + * Spin.js library and the corresponding JQuery plugin (jquery.spin.js). This widget + * looks and feels the same as the existing spinner we are familiar with in Horizon. + * Over time, uses of the existing Horizon spinner ( horizon.modals.modal_spinner() ) + * can be phased out, or refactored to use this component. + */ angular.module('horizon.framework.widgets.modal-wait-spinner', [ - 'ui.bootstrap', + 'ui.bootstrap' ]) .factory('horizon.framework.widgets.modal-wait-spinner.service', [ '$modal', @@ -63,13 +64,13 @@ var service = { showModalSpinner: function (spinnerText) { var modalOptions = { - backdrop: 'static', + backdrop: 'static', /* - Using
for wait-spinner instead of a wait-spinner element - because the existing Horizon spinner CSS styling expects a div - for the modal-body + * Using
for wait-spinner instead of a wait-spinner element + * because the existing Horizon spinner CSS styling expects a div + * for the modal-body */ - template: '', + template: '', windowClass: 'modal-wait-spinner modal_wrapper loading' }; this.modalInstance = $modal.open(modalOptions); @@ -89,26 +90,26 @@ .directive('waitSpinner', [ 'horizon.framework.conf.spinner_options', - function (spinner_options) { + function (spinnerOptions) { - return { - scope: { - text: '@text' // One-direction binding (reads from parent) - }, - restrict: 'A', - link: link, - template: '

{$text$}…

' - }; + return { + scope: { + text: '@text' // One-direction binding (reads from parent) + }, + restrict: 'A', + link: link, + template: '

{$text$}…

' + }; - function link($scope, element) { - element.spin(spinner_options.modal); - /* - At the time link is executed, element may not have been sized by the browser. - Spin.js may mistakenly places the spinner at 50% of 0 (left:0, top:0). To work around - this, explicitly set 50% left and top to center the spinner in the parent - container - */ - element.find('.spinner').css({'left': '50%', 'top': '50%'}); - } - }]); + function link($scope, element) { + element.spin(spinnerOptions.modal); + /* + * At the time link is executed, element may not have been sized by the browser. + * Spin.js may mistakenly places the spinner at 50% of 0 (left:0, top:0). To work around + * this, explicitly set 50% left and top to center the spinner in the parent + * container + */ + element.find('.spinner').css({'left': '50%', 'top': '50%'}); + } + }]); })(); diff --git a/horizon/static/framework/widgets/modal/modal.js b/horizon/static/framework/widgets/modal/modal.js index 1384f6ce96..b6223882cd 100644 --- a/horizon/static/framework/widgets/modal/modal.js +++ b/horizon/static/framework/widgets/modal/modal.js @@ -37,8 +37,8 @@ .controller('simpleModalCtrl', [ '$scope', '$modalInstance', 'context', function($scope, $modalInstance, context) { $scope.context = context; - $scope.submit = function(){ $modalInstance.close(); }; - $scope.cancel = function(){ $modalInstance.dismiss('cancel'); }; + $scope.submit = function() { $modalInstance.close(); }; + $scope.cancel = function() { $modalInstance.dismiss('cancel'); }; } // end of function ]) // end of controller @@ -74,7 +74,7 @@ 'horizon.framework.util.i18n.gettext', function($modal, path, gettext) { return function(params) { - if (params && params.title && params.body){ + if (params && params.title && params.body) { var options = { controller: 'simpleModalCtrl', templateUrl: path + 'modal/simple-modal.html', diff --git a/horizon/static/framework/widgets/table/basic-table.js b/horizon/static/framework/widgets/table/basic-table.js index 526d25f2a2..35c0f4ea1b 100644 --- a/horizon/static/framework/widgets/table/basic-table.js +++ b/horizon/static/framework/widgets/table/basic-table.js @@ -30,32 +30,33 @@ * * ``` */ - .directive('searchBar', [ 'horizon.framework.widgets.table.filterPlaceholderText', 'horizon.framework.widgets.basePath', + .directive('searchBar', ['horizon.framework.widgets.table.filterPlaceholderText', + 'horizon.framework.widgets.basePath', function(FILTER_PLACEHOLDER_TEXT, path) { - return { - restrict: 'E', - templateUrl: path + 'table/search-bar.html', - transclude: true, - link: function (scope, element, attrs, ctrl, transclude) { - if (angular.isDefined(attrs.groupClasses)) { - element.find('.input-group').addClass(attrs.groupClasses); - } - if (angular.isDefined(attrs.iconClasses)) { - element.find('.fa').addClass(attrs.iconClasses); - } - var searchInput = element.find('[st-search]'); + return { + restrict: 'E', + templateUrl: path + 'table/search-bar.html', + transclude: true, + link: function (scope, element, attrs, ctrl, transclude) { + if (angular.isDefined(attrs.groupClasses)) { + element.find('.input-group').addClass(attrs.groupClasses); + } + if (angular.isDefined(attrs.iconClasses)) { + element.find('.fa').addClass(attrs.iconClasses); + } + var searchInput = element.find('[st-search]'); - if (angular.isDefined(attrs.inputClasses)) { - searchInput.addClass(attrs.inputClasses); + if (angular.isDefined(attrs.inputClasses)) { + searchInput.addClass(attrs.inputClasses); + } + var placeholderText = attrs.placeholder || FILTER_PLACEHOLDER_TEXT; + searchInput.attr('placeholder', placeholderText); + + transclude(scope, function(clone) { + element.find('.input-group').append(clone); + }); } - var placeholderText = attrs.placeholder || FILTER_PLACEHOLDER_TEXT; - searchInput.attr('placeholder', placeholderText); + }; + }]); - transclude(scope, function(clone){ - element.find('.input-group').append(clone); - }); - } - }; - }]); - -}()); \ No newline at end of file +}()); diff --git a/horizon/static/framework/widgets/table/basic-table.spec.js b/horizon/static/framework/widgets/table/basic-table.spec.js index b64f54566a..378ef2b6be 100644 --- a/horizon/static/framework/widgets/table/basic-table.spec.js +++ b/horizon/static/framework/widgets/table/basic-table.spec.js @@ -57,4 +57,4 @@ }); -})(); \ No newline at end of file +})(); diff --git a/horizon/static/framework/widgets/table/table.js b/horizon/static/framework/widgets/table/table.js index 49dfa43d7b..a01b7e9e42 100644 --- a/horizon/static/framework/widgets/table/table.js +++ b/horizon/static/framework/widgets/table/table.js @@ -295,46 +295,47 @@ * ``` * */ - app.directive('hzExpandDetail', ['horizon.framework.widgets.table.expandSettings', function(settings) { - return { - restrict: 'A', - scope: { - icons: '@hzExpandDetail', - duration: '@' - }, - link: function(scope, element) { - element.on('click', function() { - var iconClasses = scope.icons || settings.expandIconClasses; - element.toggleClass(iconClasses); + app.directive('hzExpandDetail', ['horizon.framework.widgets.table.expandSettings', + function(settings) { + return { + restrict: 'A', + scope: { + icons: '@hzExpandDetail', + duration: '@' + }, + link: function(scope, element) { + element.on('click', function() { + var iconClasses = scope.icons || settings.expandIconClasses; + element.toggleClass(iconClasses); - var summaryRow = element.closest('tr'); - var detailCell = summaryRow.next('tr').find('.detail'); - var duration = scope.duration ? parseInt(scope.duration) : settings.duration; + var summaryRow = element.closest('tr'); + var detailCell = summaryRow.next('tr').find('.detail'); + var duration = scope.duration ? parseInt(scope.duration) : settings.duration; - if (summaryRow.hasClass('expanded')) { - var options = { - duration: duration, - complete: function() { - // Hide the row after the slide animation finishes - summaryRow.toggleClass('expanded'); + if (summaryRow.hasClass('expanded')) { + var options = { + duration: duration, + complete: function() { + // Hide the row after the slide animation finishes + summaryRow.toggleClass('expanded'); + } + }; + + detailCell.find('.detail-expanded').slideUp(options); + } else { + summaryRow.toggleClass('expanded'); + + if (detailCell.find('.detail-expanded').length === 0) { + // Slide down animation doesn't work on table cells + // so a
wrapper needs to be added + detailCell.wrapInner('
'); } - }; - detailCell.find('.detail-expanded').slideUp(options); - } else { - summaryRow.toggleClass('expanded'); - - if (detailCell.find('.detail-expanded').length === 0) { - // Slide down animation doesn't work on table cells - // so a
wrapper needs to be added - detailCell.wrapInner('
'); + detailCell.find('.detail-expanded').slideDown(duration); } - - detailCell.find('.detail-expanded').slideDown(duration); - } - }); - } - }; - }]); + }); + } + }; + }]); })(); diff --git a/horizon/static/framework/widgets/table/table.spec.js b/horizon/static/framework/widgets/table/table.spec.js index cecb05e3ba..2c7a655b20 100644 --- a/horizon/static/framework/widgets/table/table.spec.js +++ b/horizon/static/framework/widgets/table/table.spec.js @@ -107,18 +107,20 @@ expect($element.scope().numSelected).toBe(1); }); - it('should have numSelected === 0 when first checkbox is clicked, then unclicked', function() { - var checkbox = checkboxes.first(); - checkbox[0].checked = true; - checkbox.triggerHandler('click'); + it('should have numSelected === 0 when first checkbox is clicked, then unclicked', + function() { + var checkbox = checkboxes.first(); + checkbox[0].checked = true; + checkbox.triggerHandler('click'); - expect($element.scope().numSelected).toBe(1); + expect($element.scope().numSelected).toBe(1); - checkbox[0].checked = false; - checkbox.triggerHandler('click'); + checkbox[0].checked = false; + checkbox.triggerHandler('click'); - expect($element.scope().numSelected).toBe(0); - }); + expect($element.scope().numSelected).toBe(0); + } + ); it('should have numSelected === 3 and select-all checked when all rows selected', function() { angular.forEach(checkboxes, function(checkbox) { @@ -130,25 +132,27 @@ expect($element.find('input[hz-select-all]')[0].checked).toBe(true); }); - it('should have select-all unchecked when all rows selected, then one deselected', function() { - angular.forEach(checkboxes, function(checkbox) { - checkbox.checked = true; - angular.element(checkbox).triggerHandler('click'); - }); + it('should have select-all unchecked when all rows selected, then one deselected', + function() { + angular.forEach(checkboxes, function(checkbox) { + checkbox.checked = true; + angular.element(checkbox).triggerHandler('click'); + }); - // all checkboxes selected so check-all should be checked - expect($element.scope().numSelected).toBe(3); - expect($element.find('input[hz-select-all]')[0].checked).toBe(true); + // all checkboxes selected so check-all should be checked + expect($element.scope().numSelected).toBe(3); + expect($element.find('input[hz-select-all]')[0].checked).toBe(true); - // deselect one checkbox - var firstCheckbox = checkboxes.first(); - firstCheckbox[0].checked = false; - firstCheckbox.triggerHandler('click'); + // deselect one checkbox + var firstCheckbox = checkboxes.first(); + firstCheckbox[0].checked = false; + firstCheckbox.triggerHandler('click'); - // check-all should be unchecked - expect($element.scope().numSelected).toBe(2); - expect($element.find('input[hz-select-all]')[0].checked).toBe(false); - }); + // check-all should be unchecked + expect($element.scope().numSelected).toBe(2); + expect($element.find('input[hz-select-all]')[0].checked).toBe(false); + } + ); }); @@ -244,4 +248,4 @@ }); }); -}()); \ No newline at end of file +}()); diff --git a/horizon/static/framework/widgets/toast/toast.js b/horizon/static/framework/widgets/toast/toast.js index 32f18b62c9..89398fddb7 100644 --- a/horizon/static/framework/widgets/toast/toast.js +++ b/horizon/static/framework/widgets/toast/toast.js @@ -147,15 +147,17 @@ * @scope true * */ - .directive('toast', ['horizon.framework.widgets.toast.service', 'horizon.framework.widgets.basePath', function(toastService, path) { - return { - restrict: 'EA', - templateUrl: path + 'toast/toast.html', - scope: {}, - link: function(scope) { - scope.toast = toastService; - } - }; - }]); + .directive('toast', ['horizon.framework.widgets.toast.service', + 'horizon.framework.widgets.basePath', + function(toastService, path) { + return { + restrict: 'EA', + templateUrl: path + 'toast/toast.html', + scope: {}, + link: function(scope) { + scope.toast = toastService; + } + }; + }]); })(); diff --git a/horizon/static/framework/widgets/toast/toast.spec.js b/horizon/static/framework/widgets/toast/toast.spec.js index f9b5ee7ad3..3b4b214446 100644 --- a/horizon/static/framework/widgets/toast/toast.spec.js +++ b/horizon/static/framework/widgets/toast/toast.spec.js @@ -13,13 +13,13 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -(function(){ +(function() { 'use strict'; describe('horizon.framework.widgets.toast module', function() { it('should have been defined', function () { expect(angular.module('horizon.framework.widgets.toast')).toBeDefined(); - }); + }); }); describe('toast factory', function() { @@ -147,4 +147,4 @@ expect(toasts().length).toBe(0); }); }); -})(); \ No newline at end of file +})(); diff --git a/horizon/static/framework/widgets/transfer-table/transfer-table.js b/horizon/static/framework/widgets/transfer-table/transfer-table.js index c57761694d..4fd0eca2fe 100644 --- a/horizon/static/framework/widgets/transfer-table/transfer-table.js +++ b/horizon/static/framework/widgets/transfer-table/transfer-table.js @@ -414,4 +414,4 @@ } ]); -})(); \ No newline at end of file +})(); diff --git a/horizon/static/framework/widgets/transfer-table/transfer-table.spec.js b/horizon/static/framework/widgets/transfer-table/transfer-table.spec.js index 37ba9756f9..6a2cc038d2 100644 --- a/horizon/static/framework/widgets/transfer-table/transfer-table.spec.js +++ b/horizon/static/framework/widgets/transfer-table/transfer-table.spec.js @@ -72,7 +72,7 @@ })); it('returns expected text', function() { - var items = [1,2,3]; + var items = [1, 2, 3]; expect(filter(items, 6)).toBe('Found 3 of 6'); }); @@ -112,6 +112,7 @@ displayedAllocated: [] }; + // jscs:disable maximumLineLength var markup = '' + '' + '' + @@ -138,6 +139,7 @@ '
' + '' + '
'; + // jscs:enable maximumLineLength $element = angular.element(markup); $compile($element)($scope); @@ -209,6 +211,7 @@ maxAllocation: 2 }; + // jscs:disable maximumLineLength var markup = '' + '' + '' + @@ -235,6 +238,7 @@ '
' + '' + '
'; + // jscs:enable maximumLineLength $element = angular.element(markup); $compile($element)($scope); diff --git a/horizon/static/framework/widgets/wizard/wizard.js b/horizon/static/framework/widgets/wizard/wizard.js index b725f81707..72e3064af8 100644 --- a/horizon/static/framework/widgets/wizard/wizard.js +++ b/horizon/static/framework/widgets/wizard/wizard.js @@ -1,8 +1,8 @@ (function () { 'use strict'; - var extend = angular.extend, - forEach = angular.forEach; + var extend = angular.extend; + var forEach = angular.forEach; angular.module('horizon.framework.widgets.wizard', ['ui.bootstrap']) @@ -29,8 +29,8 @@ 'horizon.framework.widgets.wizard.labels', 'horizon.framework.widgets.wizard.events', function ($scope, $q, wizardLabels, wizardEvents) { - var viewModel = $scope.viewModel = {}, - initTask = $q.defer(); + var viewModel = $scope.viewModel = {}; + var initTask = $q.defer(); $scope.initPromise = initTask.promise; $scope.currentIndex = -1; @@ -176,9 +176,9 @@ checkAllReadiness().then(always, always); }], - templateUrl: path + 'wizard/wizard.html' - }; - } + templateUrl: path + 'wizard/wizard.html' + }; + } ]) .controller('ModalContainerCtrl', ['$scope', '$modalInstance', 'launchContext', diff --git a/horizon/static/framework/widgets/wizard/wizard.spec.js b/horizon/static/framework/widgets/wizard/wizard.spec.js index 9cb05c7bfc..c672a7b741 100644 --- a/horizon/static/framework/widgets/wizard/wizard.spec.js +++ b/horizon/static/framework/widgets/wizard/wizard.spec.js @@ -172,7 +172,7 @@ steps: [{}, checkedStep, {}] }; - spyOn(checkedStep, 'checkReadiness').and.returnValue({then: function(){}}); + spyOn(checkedStep, 'checkReadiness').and.returnValue({then: function() {}}); $scope.$digest(); expect(checkedStep.checkReadiness).toHaveBeenCalled(); });