diff --git a/NEWS b/NEWS
index 47b1f034e..793b8bcbc 100644
--- a/NEWS
+++ b/NEWS
@@ -7,6 +7,7 @@ New features
Enhancements
- [core] now possible to {un}subscribe to folders using sogo-tool
- [web] AngularJS optimizations in Mail module
+ - [web] AngularJS optimization of color picker
- [web] improve display of tasks status
Bug fixes
diff --git a/UI/WebServerResources/js/Common/sgColorPicker.directive.js b/UI/WebServerResources/js/Common/sgColorPicker.directive.js
index a855bc092..f5bc50d06 100644
--- a/UI/WebServerResources/js/Common/sgColorPicker.directive.js
+++ b/UI/WebServerResources/js/Common/sgColorPicker.directive.js
@@ -7,71 +7,127 @@
/*
* sgColorPicker - Color picker widget
* @restrict element
- * @param {function} sgOnSelect - the function to call when clicking on a color.
- * One variable is available: color.
* @ngInject
* @example:
-
+
*/
function sgColorPicker() {
return {
restrict: 'E',
require: 'ngModel',
template: [
- '',
' ',
- ' color_lens',
- ' ',
- ' ',
- ' ',
- ' ',
- ' check_box',
- ' ',
- ' ',
- ' ',
- ''
+ ' ng-click="$ctrl.showPicker($event)">',
+ ' format_color_fill',
+ ' '
].join(''),
- replace: true,
controller: sgColorPickerController,
- link: link
+ controllerAs: '$ctrl'
};
-
- function link(scope, iElement, iAttr, ngModelController) {
- // Expose ng-model value to scope
- ngModelController.$render = function() {
- scope.sgColor = ngModelController.$viewValue;
- scope.sgIconColor = contrast(ngModelController.$viewValue);
- };
- }
}
-
+
/**
* @ngInject
*/
- sgColorPickerController.$inject = ['$scope', '$element', 'sgColors'];
- function sgColorPickerController($scope, $element, sgColors) {
- var ngModelController = $element.controller('ngModel');
+ sgColorPickerController.$inject = ['$scope', '$element', '$mdPanel', 'sgColors'];
+ function sgColorPickerController($scope, $element, $mdPanel, sgColors) {
+ var $ctrl, ngModelController, color;
- $scope.sgColors = sgColors.selection;
- $scope.setColor = function(event, color) {
- if (event) {
- _.forEach(event.currentTarget.parentElement.children, function(tile) {
- tile.classList.remove('selected');
- });
- event.currentTarget.classList.add('selected');
+ this.$onInit = function() {
+ $ctrl = this;
+ ngModelController = $element.controller('ngModel');
+ };
+
+ this.$postLink = function() {
+ this.buttonIcon = $element.find('md-icon');
+ ngModelController.$render = function() {
+ updateColor(ngModelController.$viewValue);
+ };
+ };
+
+ function updateColor(newColor) {
+ color = newColor;
+ $ctrl.buttonIcon.css('color', color);
+ }
+
+ this.showPicker = function($event) {
+ var panelPosition = $mdPanel.newPanelPosition()
+ .relativeTo($ctrl.buttonIcon)
+ .addPanelPosition(
+ $mdPanel.xPosition.ALIGN_START,
+ $mdPanel.yPosition.ALIGN_TOPS
+ );
+
+ var panelAnimation = $mdPanel.newPanelAnimation()
+ .openFrom($ctrl.buttonIcon)
+ .duration(100)
+ .withAnimation($mdPanel.animation.FADE);
+
+ // Build grid with 7 colors per row
+ var columns = [];
+ var column = '';
+ for (var i = 0; i < sgColors.selection.length; i++) {
+ var currentColor = sgColors.selection[i];
+ var currentContrastColor = contrast(currentColor);
+ var selected = (currentColor == color);
+ if (i % 7 === 0) {
+ if (column.length) columns.push(column);
+ column = '';
+ }
+ column += '';
+ if (selected)
+ column += '';
+ column += '';
+ }
+
+ var config = {
+ attachTo: angular.element(document.body),
+ bindToController: true,
+ controller: MenuController,
+ controllerAs: '$menuCtrl',
+ position: panelPosition,
+ animation: panelAnimation,
+ targetEvent: $event,
+ template: [
+ '
',
+ '
' + columns.join('
') + '
',
+ '
'
+ ].join(''),
+ trapFocus: true,
+ clickOutsideToClose: true,
+ escapeToClose: true,
+ focusOnOpen: true
+ };
+
+ $mdPanel.open(config)
+ .then(function(panelRef) {
+ // Automatically close panel when clicking inside of it
+ panelRef.panelEl.one('click', function() {
+ panelRef.close();
+ });
+ });
+
+ MenuController.$inject = ['mdPanelRef', '$state', '$mdDialog', 'User'];
+ function MenuController(mdPanelRef, $state, $mdDialog, User) {
+ var $menuCtrl = this;
+
+ this.setColor = function(event, color) {
+ if (event) {
+ _.forEach(event.currentTarget.parentElement.children, function(tile) {
+ tile.classList.remove('selected');
+ });
+ event.currentTarget.classList.add('selected');
+ }
+ // Update scope value and ng-model
+ updateColor(color);
+ ngModelController.$setViewValue(color);
+ };
}
- // Update scope value and ng-model
- $scope.sgColor = color;
- $scope.sgIconColor = contrast(color);
- ngModelController.$setViewValue(color);
};
}
diff --git a/UI/WebServerResources/scss/components/colorpicker/colorpicker.scss b/UI/WebServerResources/scss/components/colorpicker/colorpicker.scss
new file mode 100644
index 000000000..b55b0f8cc
--- /dev/null
+++ b/UI/WebServerResources/scss/components/colorpicker/colorpicker.scss
@@ -0,0 +1,30 @@
+/// colorpicker.scss -*- Mode: scss; indent-tabs-mode: nil; basic-offset: 2 -*-
+
+$colorpicker-size: 25px;
+
+.sg-color-picker-panel {
+
+ div {
+ line-height: 0;
+ cursor: pointer;
+ }
+
+ span {
+ display: inline-block;
+ height: $colorpicker-size;
+ transition: transform .2s;
+ width: $colorpicker-size;
+ z-index: $z-index-menu;
+
+ &:not(.selected):hover {
+ outline: 0;
+ transform: scale(1.3, 1.3);
+ z-index: $z-index-menu + 1;
+ }
+
+ md-icon {
+ float: left;
+ }
+ }
+
+}
diff --git a/UI/WebServerResources/scss/styles.scss b/UI/WebServerResources/scss/styles.scss
index a05dada96..0d2533c51 100755
--- a/UI/WebServerResources/scss/styles.scss
+++ b/UI/WebServerResources/scss/styles.scss
@@ -65,6 +65,7 @@
// Inverse components
@import 'components/avatarImage/avatarImage';
+@import 'components/colorpicker/colorpicker';
@import 'components/draggable-droppable/draggable';
@import 'components/draggable-droppable/droppable';
@import 'components/hotkeys/hotkeys';