Commit 8df84483 by Jeffrey Phillips

Add origin common modal popup component.

parent 49b4c625
.origin-modal-popup {
background-color: @color-pf-white;
bottom: 0;
color: @text-color;
left: 0;
position: fixed;
padding: 0 (@grid-gutter-width / 2) (@grid-gutter-width / 2);
right: 0;
top: 0;
z-index: @zindex-modal;
@media (min-width: @screen-sm-min) {
border: 1px solid @dropdown-border;
bottom: auto;
box-shadow: 0 6px 12px rgba(0,0,0,.175);
left: auto;
margin-top: 15px;
right: auto;
top: auto;
&:after {
border: solid 7px transparent;
border-bottom-color: @dropdown-border;
content: "";
position: absolute;
right: (@grid-gutter-width / 4);
top: -15px;
}
&:before {
border: solid 7px transparent;
border-bottom-color: @color-pf-black-150;
content: "";
position: absolute;
right: (@grid-gutter-width / 4);
top: -14px;
z-index: 1;
}
&.position-above {
margin-top: -15px;
&:after {
border-bottom-color:transparent;
border-top-color: @color-pf-white;
bottom: -15px;
top: auto;
}
&:before {
border-bottom-color:transparent;
border-top-color: @color-pf-white;
bottom: -14px;
top: auto;
}
}
&.position-left {
&:after {
left: (@grid-gutter-width / 4);
right: auto;
}
&:before {
left: (@grid-gutter-width / 4);
right: auto;
}
}
}
.origin-modal-popup-close {
color: @color-pf-black-600;
font-size: 14px;
line-height: 1;
position: absolute;
right: (@grid-gutter-width / 2);
top: (@grid-gutter-width / 4) + 1;
&:hover {
color: @color-pf-black-800;
}
}
.origin-modal-popup-title {
background: @color-pf-black-150;
margin-left: -(@grid-gutter-width / 2);
margin-right: -(@grid-gutter-width / 2);
margin-top: 0;
padding: 10px @grid-gutter-width 10px (@grid-gutter-width / 2);
}
}
.origin-modal-popup-backdrop.modal-backdrop {
background-color: transparent;
cursor: not-allowed;
z-index: @zindex-navbar-fixed + 1;
}
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
@import "_forms.less"; @import "_forms.less";
@import "_guided-tour.less"; @import "_guided-tour.less";
@import "_mixins.less"; @import "_mixins.less";
@import "_modal-popup.less";
@import "_notifications.less"; @import "_notifications.less";
@import "_tile-click.less"; @import "_tile-click.less";
@import "_ui-select.less"; @import "_ui-select.less";
......
...@@ -393,6 +393,20 @@ hawtioPluginLoader.addModule('openshiftCommonUI'); ...@@ -393,6 +393,20 @@ hawtioPluginLoader.addModule('openshiftCommonUI');
); );
$templateCache.put('src/components/origin-modal-popup/origin-modal-popup.html',
"<div class=\"origin-modal-popup tile-click-prevent\" ng-if=\"$ctrl.shown\" ng-style=\"$ctrl.positionStyle\"\n" +
" ng-class=\"{'position-above': $ctrl.showAbove, 'position-left': $ctrl.showLeft}\">\n" +
" <h4 class=\"origin-modal-popup-title\">\n" +
" {{$ctrl.modalTitle}}\n" +
" </h4>\n" +
" <div ng-transclude></div>\n" +
" <a href=\"\" class=\"origin-modal-popup-close\" ng-click=\"$ctrl.onClose()\">\n" +
" <span class=\"pficon pficon-close\"></span>\n" +
" </a>\n" +
"</div>\n"
);
$templateCache.put('src/components/toast-notifications/toast-notifications.html', $templateCache.put('src/components/toast-notifications/toast-notifications.html',
"<div class=\"toast-notifications-list-pf\">\n" + "<div class=\"toast-notifications-list-pf\">\n" +
" <div ng-repeat=\"(notificationID, notification) in notifications track by (notificationID + (notification.message || notification.details))\" ng-if=\"!notification.hidden || notification.isHover\"\n" + " <div ng-repeat=\"(notificationID, notification) in notifications track by (notificationID + (notification.message || notification.details))\" ng-if=\"!notification.hidden || notification.isHover\"\n" +
...@@ -848,6 +862,115 @@ angular.module("openshiftCommonUI") ...@@ -848,6 +862,115 @@ angular.module("openshiftCommonUI")
}, },
}; };
}); });
;"use strict";
angular.module("openshiftCommonUI").component("originModalPopup", {
transclude: true,
bindings: {
modalTitle: '@',
shown: '<',
position: '@', // 'top-left', 'top-right', 'bottom-left', or 'bottom-right' (default is 'bottom-right')
referenceElement: '<?', // Optional reference element, default is parent element. Used to position popup based on screen position
onClose: '<'
},
templateUrl: 'src/components/origin-modal-popup/origin-modal-popup.html',
controller: function($scope, HTMLService, $element, $window) {
var ctrl = this;
var debounceResize;
function updatePosition() {
var positionElement = ctrl.referenceElement || $element[0].parentNode;
if (positionElement && HTMLService.isWindowAboveBreakpoint(HTMLService.WINDOW_SIZE_SM)) {
var posAbove = ctrl.position && ctrl.position.indexOf('top') > -1;
var posLeft = ctrl.position && ctrl.position.indexOf('left') > -1;
var topPos;
var leftPos;
var elementRect = positionElement.getBoundingClientRect();
var windowHeight = $window.innerHeight;
var modalElement = $element[0].children[0];
var modalHeight = _.get(modalElement, 'offsetHeight', 0);
var modalWidth = _.get(modalElement, 'offsetWidth', 0);
// auto-adjust vertical position based on showing in the viewport
if (elementRect.top < modalHeight) {
posAbove = false;
} else if (elementRect.bottom + modalHeight > windowHeight) {
posAbove = true;
}
if (posAbove) {
topPos = (elementRect.top - modalHeight) + 'px';
} else {
topPos = elementRect.bottom + 'px';
}
if (posLeft) {
leftPos = elementRect.left + 'px';
} else {
leftPos = (elementRect.right - modalWidth) + 'px';
}
ctrl.showAbove = posAbove;
ctrl.showLeft = posLeft;
ctrl.positionStyle = {
left: leftPos,
top: topPos
};
} else {
ctrl.positionStyle = {};
}
}
function showModalBackdrop() {
var backdropElement = '<div class="origin-modal-popup-backdrop modal-backdrop fade in tile-click-prevent"></div>';
var parentNode = ctrl.referenceElement ? ctrl.referenceElement.parentNode : $element[0].parentNode;
$(parentNode).append(backdropElement);
}
function hideModalBackdrop() {
$('.origin-modal-popup-backdrop').remove();
}
function onWindowResize() {
$scope.$evalAsync(updatePosition);
}
function onShow() {
showModalBackdrop();
debounceResize = _.debounce(onWindowResize, 50, { maxWait: 250 });
angular.element($window).on('resize', debounceResize);
}
function onHide() {
hideModalBackdrop();
angular.element($window).off('resize', debounceResize);
}
ctrl.$onChanges = function (changeObj) {
if (changeObj.shown) {
if (ctrl.shown) {
onShow();
} else {
onHide();
}
}
if (changeObj.shown || changeObj.referenceElement) {
if (ctrl.shown) {
updatePosition();
}
}
};
ctrl.$onDestroy = function() {
if (ctrl.shown) {
onHide();
}
}
}
});
;'use strict'; ;'use strict';
// oscUnique is a validation directive // oscUnique is a validation directive
// use: // use:
......
...@@ -272,6 +272,91 @@ div.hopscotch-bubble .hopscotch-nav-button.prev { ...@@ -272,6 +272,91 @@ div.hopscotch-bubble .hopscotch-nav-button.prev {
word-break: break-word; word-break: break-word;
overflow-wrap: break-word; overflow-wrap: break-word;
} }
.origin-modal-popup {
background-color: #fff;
bottom: 0;
color: #363636;
left: 0;
position: fixed;
padding: 0 20px 20px;
right: 0;
top: 0;
z-index: 1050;
}
@media (min-width: 768px) {
.origin-modal-popup {
border: 1px solid #bbb;
bottom: auto;
box-shadow: 0 6px 12px rgba(0, 0, 0, 0.175);
left: auto;
margin-top: 15px;
right: auto;
top: auto;
}
.origin-modal-popup:after {
border: solid 7px transparent;
border-bottom-color: #bbb;
content: "";
position: absolute;
right: 10px;
top: -15px;
}
.origin-modal-popup:before {
border: solid 7px transparent;
border-bottom-color: #f5f5f5;
content: "";
position: absolute;
right: 10px;
top: -14px;
z-index: 1;
}
.origin-modal-popup.position-above {
margin-top: -15px;
}
.origin-modal-popup.position-above:after {
border-bottom-color: transparent;
border-top-color: #fff;
bottom: -15px;
top: auto;
}
.origin-modal-popup.position-above:before {
border-bottom-color: transparent;
border-top-color: #fff;
bottom: -14px;
top: auto;
}
.origin-modal-popup.position-left:after {
left: 10px;
right: auto;
}
.origin-modal-popup.position-left:before {
left: 10px;
right: auto;
}
}
.origin-modal-popup .origin-modal-popup-close {
color: #72767b;
font-size: 14px;
line-height: 1;
position: absolute;
right: 20px;
top: 11px;
}
.origin-modal-popup .origin-modal-popup-close:hover {
color: #393f44;
}
.origin-modal-popup .origin-modal-popup-title {
background: #f5f5f5;
margin-left: -20px;
margin-right: -20px;
margin-top: 0;
padding: 10px 40px 10px 20px;
}
.origin-modal-popup-backdrop.modal-backdrop {
background-color: transparent;
cursor: not-allowed;
z-index: 1031;
}
.toast-action-divider { .toast-action-divider {
color: #9c9c9c; color: #9c9c9c;
} }
......
...@@ -564,6 +564,20 @@ hawtioPluginLoader.addModule('openshiftCommonUI'); ...@@ -564,6 +564,20 @@ hawtioPluginLoader.addModule('openshiftCommonUI');
); );
$templateCache.put('src/components/origin-modal-popup/origin-modal-popup.html',
"<div class=\"origin-modal-popup tile-click-prevent\" ng-if=\"$ctrl.shown\" ng-style=\"$ctrl.positionStyle\"\n" +
" ng-class=\"{'position-above': $ctrl.showAbove, 'position-left': $ctrl.showLeft}\">\n" +
" <h4 class=\"origin-modal-popup-title\">\n" +
" {{$ctrl.modalTitle}}\n" +
" </h4>\n" +
" <div ng-transclude></div>\n" +
" <a href=\"\" class=\"origin-modal-popup-close\" ng-click=\"$ctrl.onClose()\">\n" +
" <span class=\"pficon pficon-close\"></span>\n" +
" </a>\n" +
"</div>\n"
);
$templateCache.put('src/components/toast-notifications/toast-notifications.html', $templateCache.put('src/components/toast-notifications/toast-notifications.html',
"<div class=\"toast-notifications-list-pf\">\n" + "<div class=\"toast-notifications-list-pf\">\n" +
" <div ng-repeat=\"(notificationID, notification) in notifications track by (notificationID + (notification.message || notification.details))\" ng-if=\"!notification.hidden || notification.isHover\"\n" + " <div ng-repeat=\"(notificationID, notification) in notifications track by (notificationID + (notification.message || notification.details))\" ng-if=\"!notification.hidden || notification.isHover\"\n" +
...@@ -1019,6 +1033,115 @@ angular.module("openshiftCommonUI") ...@@ -1019,6 +1033,115 @@ angular.module("openshiftCommonUI")
}], }],
}; };
}]); }]);
;"use strict";
angular.module("openshiftCommonUI").component("originModalPopup", {
transclude: true,
bindings: {
modalTitle: '@',
shown: '<',
position: '@', // 'top-left', 'top-right', 'bottom-left', or 'bottom-right' (default is 'bottom-right')
referenceElement: '<?', // Optional reference element, default is parent element. Used to position popup based on screen position
onClose: '<'
},
templateUrl: 'src/components/origin-modal-popup/origin-modal-popup.html',
controller: ["$scope", "HTMLService", "$element", "$window", function($scope, HTMLService, $element, $window) {
var ctrl = this;
var debounceResize;
function updatePosition() {
var positionElement = ctrl.referenceElement || $element[0].parentNode;
if (positionElement && HTMLService.isWindowAboveBreakpoint(HTMLService.WINDOW_SIZE_SM)) {
var posAbove = ctrl.position && ctrl.position.indexOf('top') > -1;
var posLeft = ctrl.position && ctrl.position.indexOf('left') > -1;
var topPos;
var leftPos;
var elementRect = positionElement.getBoundingClientRect();
var windowHeight = $window.innerHeight;
var modalElement = $element[0].children[0];
var modalHeight = _.get(modalElement, 'offsetHeight', 0);
var modalWidth = _.get(modalElement, 'offsetWidth', 0);
// auto-adjust vertical position based on showing in the viewport
if (elementRect.top < modalHeight) {
posAbove = false;
} else if (elementRect.bottom + modalHeight > windowHeight) {
posAbove = true;
}
if (posAbove) {
topPos = (elementRect.top - modalHeight) + 'px';
} else {
topPos = elementRect.bottom + 'px';
}
if (posLeft) {
leftPos = elementRect.left + 'px';
} else {
leftPos = (elementRect.right - modalWidth) + 'px';
}
ctrl.showAbove = posAbove;
ctrl.showLeft = posLeft;
ctrl.positionStyle = {
left: leftPos,
top: topPos
};
} else {
ctrl.positionStyle = {};
}
}
function showModalBackdrop() {
var backdropElement = '<div class="origin-modal-popup-backdrop modal-backdrop fade in tile-click-prevent"></div>';
var parentNode = ctrl.referenceElement ? ctrl.referenceElement.parentNode : $element[0].parentNode;
$(parentNode).append(backdropElement);
}
function hideModalBackdrop() {
$('.origin-modal-popup-backdrop').remove();
}
function onWindowResize() {
$scope.$evalAsync(updatePosition);
}
function onShow() {
showModalBackdrop();
debounceResize = _.debounce(onWindowResize, 50, { maxWait: 250 });
angular.element($window).on('resize', debounceResize);
}
function onHide() {
hideModalBackdrop();
angular.element($window).off('resize', debounceResize);
}
ctrl.$onChanges = function (changeObj) {
if (changeObj.shown) {
if (ctrl.shown) {
onShow();
} else {
onHide();
}
}
if (changeObj.shown || changeObj.referenceElement) {
if (ctrl.shown) {
updatePosition();
}
}
};
ctrl.$onDestroy = function() {
if (ctrl.shown) {
onHide();
}
}
}]
});
;'use strict'; ;'use strict';
// oscUnique is a validation directive // oscUnique is a validation directive
// use: // use:
......
...@@ -364,6 +364,20 @@ angular.module('openshiftCommonUI').run(['$templateCache', function($templateCac ...@@ -364,6 +364,20 @@ angular.module('openshiftCommonUI').run(['$templateCache', function($templateCac
); );
$templateCache.put('src/components/origin-modal-popup/origin-modal-popup.html',
"<div class=\"origin-modal-popup tile-click-prevent\" ng-if=\"$ctrl.shown\" ng-style=\"$ctrl.positionStyle\"\n" +
" ng-class=\"{'position-above': $ctrl.showAbove, 'position-left': $ctrl.showLeft}\">\n" +
" <h4 class=\"origin-modal-popup-title\">\n" +
" {{$ctrl.modalTitle}}\n" +
" </h4>\n" +
" <div ng-transclude></div>\n" +
" <a href=\"\" class=\"origin-modal-popup-close\" ng-click=\"$ctrl.onClose()\">\n" +
" <span class=\"pficon pficon-close\"></span>\n" +
" </a>\n" +
"</div>\n"
);
$templateCache.put('src/components/toast-notifications/toast-notifications.html', $templateCache.put('src/components/toast-notifications/toast-notifications.html',
"<div class=\"toast-notifications-list-pf\">\n" + "<div class=\"toast-notifications-list-pf\">\n" +
" <div ng-repeat=\"(notificationID, notification) in notifications track by (notificationID + (notification.message || notification.details))\" ng-if=\"!notification.hidden || notification.isHover\"\n" + " <div ng-repeat=\"(notificationID, notification) in notifications track by (notificationID + (notification.message || notification.details))\" ng-if=\"!notification.hidden || notification.isHover\"\n" +
......
<div class="origin-modal-popup tile-click-prevent" ng-if="$ctrl.shown" ng-style="$ctrl.positionStyle"
ng-class="{'position-above': $ctrl.showAbove, 'position-left': $ctrl.showLeft}">
<h4 class="origin-modal-popup-title">
{{$ctrl.modalTitle}}
</h4>
<div ng-transclude></div>
<a href="" class="origin-modal-popup-close" ng-click="$ctrl.onClose()">
<span class="pficon pficon-close"></span>
</a>
</div>
"use strict";
angular.module("openshiftCommonUI").component("originModalPopup", {
transclude: true,
bindings: {
modalTitle: '@',
shown: '<',
position: '@', // 'top-left', 'top-right', 'bottom-left', or 'bottom-right' (default is 'bottom-right')
referenceElement: '<?', // Optional reference element, default is parent element. Used to position popup based on screen position
onClose: '<'
},
templateUrl: 'src/components/origin-modal-popup/origin-modal-popup.html',
controller: function($scope, HTMLService, $element, $window) {
var ctrl = this;
var debounceResize;
function updatePosition() {
var positionElement = ctrl.referenceElement || $element[0].parentNode;
if (positionElement && HTMLService.isWindowAboveBreakpoint(HTMLService.WINDOW_SIZE_SM)) {
var posAbove = ctrl.position && ctrl.position.indexOf('top') > -1;
var posLeft = ctrl.position && ctrl.position.indexOf('left') > -1;
var topPos;
var leftPos;
var elementRect = positionElement.getBoundingClientRect();
var windowHeight = $window.innerHeight;
var modalElement = $element[0].children[0];
var modalHeight = _.get(modalElement, 'offsetHeight', 0);
var modalWidth = _.get(modalElement, 'offsetWidth', 0);
// auto-adjust vertical position based on showing in the viewport
if (elementRect.top < modalHeight) {
posAbove = false;
} else if (elementRect.bottom + modalHeight > windowHeight) {
posAbove = true;
}
if (posAbove) {
topPos = (elementRect.top - modalHeight) + 'px';
} else {
topPos = elementRect.bottom + 'px';
}
if (posLeft) {
leftPos = elementRect.left + 'px';
} else {
leftPos = (elementRect.right - modalWidth) + 'px';
}
ctrl.showAbove = posAbove;
ctrl.showLeft = posLeft;
ctrl.positionStyle = {
left: leftPos,
top: topPos
};
} else {
ctrl.positionStyle = {};
}
}
function showModalBackdrop() {
var backdropElement = '<div class="origin-modal-popup-backdrop modal-backdrop fade in tile-click-prevent"></div>';
var parentNode = ctrl.referenceElement ? ctrl.referenceElement.parentNode : $element[0].parentNode;
$(parentNode).append(backdropElement);
}
function hideModalBackdrop() {
$('.origin-modal-popup-backdrop').remove();
}
function onWindowResize() {
$scope.$evalAsync(updatePosition);
}
function onShow() {
showModalBackdrop();
debounceResize = _.debounce(onWindowResize, 50, { maxWait: 250 });
angular.element($window).on('resize', debounceResize);
}
function onHide() {
hideModalBackdrop();
angular.element($window).off('resize', debounceResize);
}
ctrl.$onChanges = function (changeObj) {
if (changeObj.shown) {
if (ctrl.shown) {
onShow();
} else {
onHide();
}
}
if (changeObj.shown || changeObj.referenceElement) {
if (ctrl.shown) {
updatePosition();
}
}
};
ctrl.$onDestroy = function() {
if (ctrl.shown) {
onHide();
}
}
}
});
.origin-modal-popup {
background-color: @color-pf-white;
bottom: 0;
color: @text-color;
left: 0;
position: fixed;
padding: 0 (@grid-gutter-width / 2) (@grid-gutter-width / 2);
right: 0;
top: 0;
z-index: @zindex-modal;
@media (min-width: @screen-sm-min) {
border: 1px solid @dropdown-border;
bottom: auto;
box-shadow: 0 6px 12px rgba(0,0,0,.175);
left: auto;
margin-top: 15px;
right: auto;
top: auto;
&:after {
border: solid 7px transparent;
border-bottom-color: @dropdown-border;
content: "";
position: absolute;
right: (@grid-gutter-width / 4);
top: -15px;
}
&:before {
border: solid 7px transparent;
border-bottom-color: @color-pf-black-150;
content: "";
position: absolute;
right: (@grid-gutter-width / 4);
top: -14px;
z-index: 1;
}
&.position-above {
margin-top: -15px;
&:after {
border-bottom-color:transparent;
border-top-color: @color-pf-white;
bottom: -15px;
top: auto;
}
&:before {
border-bottom-color:transparent;
border-top-color: @color-pf-white;
bottom: -14px;
top: auto;
}
}
&.position-left {
&:after {
left: (@grid-gutter-width / 4);
right: auto;
}
&:before {
left: (@grid-gutter-width / 4);
right: auto;
}
}
}
.origin-modal-popup-close {
color: @color-pf-black-600;
font-size: 14px;
line-height: 1;
position: absolute;
right: (@grid-gutter-width / 2);
top: (@grid-gutter-width / 4) + 1;
&:hover {
color: @color-pf-black-800;
}
}
.origin-modal-popup-title {
background: @color-pf-black-150;
margin-left: -(@grid-gutter-width / 2);
margin-right: -(@grid-gutter-width / 2);
margin-top: 0;
padding: 10px @grid-gutter-width 10px (@grid-gutter-width / 2);
}
}
.origin-modal-popup-backdrop.modal-backdrop {
background-color: transparent;
cursor: not-allowed;
z-index: @zindex-navbar-fixed + 1;
}
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
@import "_forms.less"; @import "_forms.less";
@import "_guided-tour.less"; @import "_guided-tour.less";
@import "_mixins.less"; @import "_mixins.less";
@import "_modal-popup.less";
@import "_notifications.less"; @import "_notifications.less";
@import "_tile-click.less"; @import "_tile-click.less";
@import "_ui-select.less"; @import "_ui-select.less";
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment