Commit 7f909088 by Jeffrey Phillips

Add Guided Tour Service based off Hopscotch

parent a23465c2
...@@ -29,7 +29,7 @@ module.exports = function (grunt) { ...@@ -29,7 +29,7 @@ module.exports = function (grunt) {
separator: ';' separator: ';'
}, },
ui: { ui: {
src: ['src/**/*UI.module.js', 'dist/scripts/templates.js', 'src/components/**/*.js', 'src/filters/**/*.js'], src: ['src/**/*UI.module.js', 'dist/scripts/templates.js', 'src/components/**/*.js', 'src/filters/**/*.js', 'src/ui-services/**/*.js'],
dest: 'dist/origin-web-common-ui.js' dest: 'dist/origin-web-common-ui.js'
}, },
services: { services: {
......
...@@ -33,6 +33,7 @@ ...@@ -33,6 +33,7 @@
"angular-utf8-base64": "~0.0.5", "angular-utf8-base64": "~0.0.5",
"hawtio-core": "~2.0.37", "hawtio-core": "~2.0.37",
"hawtio-extension-service": "~2.0.2", "hawtio-extension-service": "~2.0.2",
"hopscotch": "~0.2.7",
"jquery": "~2.1.4", "jquery": "~2.1.4",
"lodash": "~3.10.1", "lodash": "~3.10.1",
"messenger": "~1.4.1", "messenger": "~1.4.1",
......
...@@ -1097,3 +1097,137 @@ angular.module('openshiftCommonUI') ...@@ -1097,3 +1097,137 @@ angular.module('openshiftCommonUI')
return prefix + randomString; return prefix + randomString;
}; };
}); });
;'use strict';
angular.module('openshiftCommonUI').factory('GuidedTourService', function() {
var hopscotchConfig = {};
var innerConfig;
var bubbleHeight = 175;
var startTour = function(tourConfig, onTourEndCB) {
$('body').append('<div id="guided_tour_backdrop" class="modal-backdrop fade guided-tour-backdrop"></div>');
innerConfig = {
onTourEndCB: onTourEndCB,
bubblePadding: 5,
arrowWidth: 10,
onStart: handleTourStart,
onEnd: handleTourEnd,
onClose: handleTourEnd,
showPrevButton: true,
i18n: {
nextBtn: 'Next >',
prevBtn: '< Back'
}
};
hopscotchConfig = {};
angular.merge(hopscotchConfig, innerConfig, tourConfig);
setupSteps();
makeStepTargetVisible(0);
hopscotch.startTour(hopscotchConfig, 0);
};
var cancelTour = function() {
hopscotch.endTour();
};
function handleTourStart() {
$('#guided_tour_backdrop').click(cancelTour);
}
function handleTourEnd() {
$('#guided_tour_backdrop').remove();
if (angular.isFunction(hopscotchConfig.onTourEndCB)) {
hopscotchConfig.onTourEndCB();
}
}
function setupSteps() {
_.forEach(hopscotchConfig.steps, function(step) {
step.onNextOrig = step.onNext;
step.onPrevOrig = step.onPrev;
step.onNext = onStepNext;
step.onPrev = onStepPrev;
step.fixedElement = true;
// Since we use a title area, move up to get arrow out of title area
if (angular.isUndefined(step.yOffset) && (step.placement === 'right' || step.placement === 'left' )) {
step.yOffset = -45;
}
});
}
function onStepNext() {
var stepNum = hopscotch.getCurrStepNum() - 1;
var stepConfig = hopscotchConfig.steps[stepNum];
if (stepConfig) {
if (stepConfig.onNextOrig) {
stepConfig.onNextOrig();
}
makeStepTargetVisible(stepNum + 1);
}
}
function onStepPrev() {
var stepNum = hopscotch.getCurrStepNum() + 1;
var stepConfig = hopscotchConfig.steps[stepNum];
if (stepConfig) {
if (stepConfig.onPrevOrig) {
stepConfig.onPrevOrig();
}
makeStepTargetVisible(stepNum - 1);
}
}
function makeStepTargetVisible(stepNum) {
var stepConfig = hopscotchConfig.steps[stepNum];
if (!stepConfig) {
return;
}
if (stepConfig.preShow) {
stepConfig.preShow();
}
if (stepConfig.targetScrollElement) {
var scrollElement = $('body').find(stepConfig.targetScrollElement)[0];
var targetElement = $('body').find(stepConfig.target)[0];
if (scrollElement && scrollElement) {
var offsetTop = getOffsetTopFromScrollElement(targetElement, scrollElement);
if (stepConfig.placement === 'top') {
offsetTop -= bubbleHeight;
} else {
offsetTop += bubbleHeight;
}
if (offsetTop > scrollElement.clientHeight) {
scrollElement.scrollTop = offsetTop;
} else {
scrollElement.scrollTop = 0;
}
}
}
}
function getOffsetTopFromScrollElement(targetElement, scrollElement) {
if (!targetElement || targetElement === scrollElement) {
return 0;
} else {
return targetElement.offsetTop + getOffsetTopFromScrollElement(targetElement.offsetParent, scrollElement);
}
}
return {
startTour: startTour,
cancelTour: cancelTour
};
});
...@@ -53,6 +53,124 @@ label.required:before { ...@@ -53,6 +53,124 @@ label.required:before {
left: -3px; left: -3px;
} }
} }
.guided-tour-backdrop {
z-index: 1052;
}
div.hopscotch-bubble {
border-color: #bbb;
border-width: 1px;
box-shadow: 1px 1px 3px rgba(0, 0, 0, 0.3);
}
div.hopscotch-bubble .hopscotch-actions {
background-color: #fff;
margin: -5px;
padding: 20px;
}
div.hopscotch-bubble .hopscotch-bubble-arrow-container .hopscotch-bubble-arrow-border:after {
content: " ";
border-color: transparent;
border-style: solid;
position: absolute;
}
div.hopscotch-bubble .hopscotch-bubble-arrow-container.down .hopscotch-bubble-arrow,
div.hopscotch-bubble .hopscotch-bubble-arrow-container.left .hopscotch-bubble-arrow,
div.hopscotch-bubble .hopscotch-bubble-arrow-container.right .hopscotch-bubble-arrow,
div.hopscotch-bubble .hopscotch-bubble-arrow-container.up .hopscotch-bubble-arrow {
display: none;
}
div.hopscotch-bubble .hopscotch-bubble-arrow-container.down .hopscotch-bubble-arrow-border {
border-top-color: #bbb;
border-width: 10px;
margin-top: -5px;
}
div.hopscotch-bubble .hopscotch-bubble-arrow-container.down .hopscotch-bubble-arrow-border:after {
border-color: #fff transparent transparent;
border-width: 10px 10px 0;
margin-left: -10px;
margin-top: -12px;
}
div.hopscotch-bubble .hopscotch-bubble-arrow-container.left {
top: 48px;
}
div.hopscotch-bubble .hopscotch-bubble-arrow-container.left .hopscotch-bubble-arrow-border {
border-right-color: #bbb;
border-width: 10px;
margin-left: 11px;
}
div.hopscotch-bubble .hopscotch-bubble-arrow-container.left .hopscotch-bubble-arrow-border:after {
border-color: transparent #fff transparent transparent;
border-width: 10px 10px 10px 0;
margin-left: 2px;
margin-top: -10px;
}
div.hopscotch-bubble .hopscotch-bubble-arrow-container.right {
top: 48px;
}
div.hopscotch-bubble .hopscotch-bubble-arrow-container.right .hopscotch-bubble-arrow-border {
border-left-color: #bbb;
border-width: 10px;
margin-left: -5px;
}
div.hopscotch-bubble .hopscotch-bubble-arrow-container.right .hopscotch-bubble-arrow-border:after {
border-color: transparent transparent transparent #fff;
border-width: 10px 0 10px 10px;
margin-left: -12px;
margin-top: -10px;
}
div.hopscotch-bubble .hopscotch-bubble-arrow-container.up .hopscotch-bubble-arrow-border {
border-bottom-color: #bbb;
border-width: 10px;
margin-top: 11px;
}
div.hopscotch-bubble .hopscotch-bubble-arrow-container.up .hopscotch-bubble-arrow-border:after {
border-color: transparent transparent #f5f5f5;
border-width: 0 10px 10px;
margin-left: -10px;
margin-top: 2px;
}
div.hopscotch-bubble .hopscotch-bubble-close {
right: 8px;
top: 7px;
}
div.hopscotch-bubble .hopscotch-bubble-container {
background-color: #f5f5f5;
}
div.hopscotch-bubble .hopscotch-content {
color: #4d5258;
background-color: #fff;
font-family: "Open Sans";
font-size: 12px;
margin: 11px -5px 0 -45px;
padding: 15px 20px 5px;
}
div.hopscotch-bubble h3 {
margin-top: 6px;
color: #4d5258;
font-family: "Open Sans";
padding-left: 10px;
}
div.hopscotch-bubble .hopscotch-bubble-number {
background: none;
background-color: #0088ce;
border-radius: 15px;
font-family: "Open Sans";
font-size: 16px;
margin-left: 10px;
padding: 0;
}
div.hopscotch-bubble .hopscotch-nav-button {
border-radius: 0;
font-family: "Open Sans";
font-size: 12px;
}
div.hopscotch-bubble .hopscotch-nav-button.next {
background-color: #0088ce;
background-image: none;
margin-left: 5px;
}
div.hopscotch-bubble .hopscotch-nav-button.prev {
color: #030303;
}
ul.messenger.messenger-theme-flat { ul.messenger.messenger-theme-flat {
margin: 0; margin: 0;
padding: 0; padding: 0;
......
...@@ -4154,3 +4154,137 @@ angular.module('openshiftCommonServices') ...@@ -4154,3 +4154,137 @@ angular.module('openshiftCommonServices')
return $ws; return $ws;
}]; }];
}]); }]);
;'use strict';
angular.module('openshiftCommonUI').factory('GuidedTourService', function() {
var hopscotchConfig = {};
var innerConfig;
var bubbleHeight = 175;
var startTour = function(tourConfig, onTourEndCB) {
$('body').append('<div id="guided_tour_backdrop" class="modal-backdrop fade guided-tour-backdrop"></div>');
innerConfig = {
onTourEndCB: onTourEndCB,
bubblePadding: 5,
arrowWidth: 10,
onStart: handleTourStart,
onEnd: handleTourEnd,
onClose: handleTourEnd,
showPrevButton: true,
i18n: {
nextBtn: 'Next >',
prevBtn: '< Back'
}
};
hopscotchConfig = {};
angular.merge(hopscotchConfig, innerConfig, tourConfig);
setupSteps();
makeStepTargetVisible(0);
hopscotch.startTour(hopscotchConfig, 0);
};
var cancelTour = function() {
hopscotch.endTour();
};
function handleTourStart() {
$('#guided_tour_backdrop').click(cancelTour);
}
function handleTourEnd() {
$('#guided_tour_backdrop').remove();
if (angular.isFunction(hopscotchConfig.onTourEndCB)) {
hopscotchConfig.onTourEndCB();
}
}
function setupSteps() {
_.forEach(hopscotchConfig.steps, function(step) {
step.onNextOrig = step.onNext;
step.onPrevOrig = step.onPrev;
step.onNext = onStepNext;
step.onPrev = onStepPrev;
step.fixedElement = true;
// Since we use a title area, move up to get arrow out of title area
if (angular.isUndefined(step.yOffset) && (step.placement === 'right' || step.placement === 'left' )) {
step.yOffset = -45;
}
});
}
function onStepNext() {
var stepNum = hopscotch.getCurrStepNum() - 1;
var stepConfig = hopscotchConfig.steps[stepNum];
if (stepConfig) {
if (stepConfig.onNextOrig) {
stepConfig.onNextOrig();
}
makeStepTargetVisible(stepNum + 1);
}
}
function onStepPrev() {
var stepNum = hopscotch.getCurrStepNum() + 1;
var stepConfig = hopscotchConfig.steps[stepNum];
if (stepConfig) {
if (stepConfig.onPrevOrig) {
stepConfig.onPrevOrig();
}
makeStepTargetVisible(stepNum - 1);
}
}
function makeStepTargetVisible(stepNum) {
var stepConfig = hopscotchConfig.steps[stepNum];
if (!stepConfig) {
return;
}
if (stepConfig.preShow) {
stepConfig.preShow();
}
if (stepConfig.targetScrollElement) {
var scrollElement = $('body').find(stepConfig.targetScrollElement)[0];
var targetElement = $('body').find(stepConfig.target)[0];
if (scrollElement && scrollElement) {
var offsetTop = getOffsetTopFromScrollElement(targetElement, scrollElement);
if (stepConfig.placement === 'top') {
offsetTop -= bubbleHeight;
} else {
offsetTop += bubbleHeight;
}
if (offsetTop > scrollElement.clientHeight) {
scrollElement.scrollTop = offsetTop;
} else {
scrollElement.scrollTop = 0;
}
}
}
}
function getOffsetTopFromScrollElement(targetElement, scrollElement) {
if (!targetElement || targetElement === scrollElement) {
return 0;
} else {
return targetElement.offsetTop + getOffsetTopFromScrollElement(targetElement.offsetParent, scrollElement);
}
}
return {
startTour: startTour,
cancelTour: cancelTour
};
});
This source diff could not be displayed because it is too large. You can view the blob instead.
.guided-tour-backdrop {
z-index: @zindex-modal + 2;
}
// Note: variable used for clarity only, changing will require other changes as well due to hopscotch arrow container sizing
@hopscotch-bubble-arrow-width: 10px;
// Overridden hopscotch settings
div.hopscotch-bubble {
border-color: @color-pf-black-400;
border-width: 1px;
box-shadow: 1px 1px 3px rgba(0, 0, 0, .3);
.hopscotch-actions {
background-color: @color-pf-white;
margin: -5px;
padding: @grid-gutter-width / 2;
}
.hopscotch-bubble-arrow-container {
.hopscotch-bubble-arrow-border {
&:after {
content: " ";
border-color: transparent;
border-style: solid;
position: absolute;
}
}
// Use our own arrows
&.down, &.left, &.right, &.up {
.hopscotch-bubble-arrow {
display: none;
}
}
&.down .hopscotch-bubble-arrow-border {
border-top-color: @color-pf-black-400;
border-width: @hopscotch-bubble-arrow-width;
margin-top: -(@hopscotch-bubble-arrow-width / 2);
&:after {
border-color: @color-pf-white transparent transparent;
border-width: @hopscotch-bubble-arrow-width @hopscotch-bubble-arrow-width 0;
margin-left: -@hopscotch-bubble-arrow-width;
margin-top: -(@hopscotch-bubble-arrow-width + 2px);
}
}
&.left {
top: 48px;
.hopscotch-bubble-arrow-border {
border-right-color: @color-pf-black-400;
border-width: @hopscotch-bubble-arrow-width;
margin-left: @hopscotch-bubble-arrow-width + 1px;
&:after {
border-color: transparent @color-pf-white transparent transparent;
border-width: @hopscotch-bubble-arrow-width @hopscotch-bubble-arrow-width @hopscotch-bubble-arrow-width 0;
margin-left: 2px;
margin-top: -@hopscotch-bubble-arrow-width;
}
}
}
&.right {
top: 48px;
.hopscotch-bubble-arrow-border {
border-left-color: @color-pf-black-400;
border-width: @hopscotch-bubble-arrow-width;
margin-left: -5px;
&:after {
border-color: transparent transparent transparent @color-pf-white;
border-width: @hopscotch-bubble-arrow-width 0 @hopscotch-bubble-arrow-width @hopscotch-bubble-arrow-width;
margin-left: -(@hopscotch-bubble-arrow-width + 2px);
margin-top: -@hopscotch-bubble-arrow-width;
}
}
}
&.up .hopscotch-bubble-arrow-border {
border-bottom-color: @color-pf-black-400;
border-width: @hopscotch-bubble-arrow-width;
margin-top: @hopscotch-bubble-arrow-width + 1px;
&:after {
border-color: transparent transparent @color-pf-black-150;
border-width: 0 @hopscotch-bubble-arrow-width @hopscotch-bubble-arrow-width;
margin-left: -@hopscotch-bubble-arrow-width;
margin-top: 2px;
}
}
}
.hopscotch-bubble-close {
right: 8px;
top: 7px;
}
.hopscotch-bubble-container {
background-color: @color-pf-black-150;
}
.hopscotch-content {
color: @color-pf-black-700;
background-color: @color-pf-white;
font-family: "Open Sans";
font-size: 12px;
margin: 11px -5px 0 -45px;
padding: 15px 20px 5px;
}
h3 {
margin-top: 6px;
color: @color-pf-black-700;
font-family: "Open Sans";
padding-left: 10px;
}
.hopscotch-bubble-number {
background: none;
background-color: @color-pf-blue-400;
border-radius: 15px;
font-family: "Open Sans";
font-size: 16px;
margin-left: 10px;
padding: 0;
}
.hopscotch-nav-button {
border-radius: 0;
font-family: "Open Sans";
font-size: 12px;
&.next {
background-color: @color-pf-blue-400;
background-image: none;
margin-left: 5px;
}
&.prev {
color: @color-pf-black;
}
}
}
...@@ -12,5 +12,6 @@ ...@@ -12,5 +12,6 @@
@import "_core.less"; @import "_core.less";
@import "_forms.less"; @import "_forms.less";
@import "_guided-tour.less";
@import "_messages.less"; @import "_messages.less";
@import "_ui-select.less"; @import "_ui-select.less";
'use strict';
angular.module('openshiftCommonUI').factory('GuidedTourService', function() {
var hopscotchConfig = {};
var innerConfig;
var bubbleHeight = 175;
var startTour = function(tourConfig, onTourEndCB) {
$('body').append('<div id="guided_tour_backdrop" class="modal-backdrop fade guided-tour-backdrop"></div>');
innerConfig = {
onTourEndCB: onTourEndCB,
bubblePadding: 5,
arrowWidth: 10,
onStart: handleTourStart,
onEnd: handleTourEnd,
onClose: handleTourEnd,
showPrevButton: true,
i18n: {
nextBtn: 'Next >',
prevBtn: '< Back'
}
};
hopscotchConfig = {};
angular.merge(hopscotchConfig, innerConfig, tourConfig);
setupSteps();
makeStepTargetVisible(0);
hopscotch.startTour(hopscotchConfig, 0);
};
var cancelTour = function() {
hopscotch.endTour();
};
function handleTourStart() {
$('#guided_tour_backdrop').click(cancelTour);
}
function handleTourEnd() {
$('#guided_tour_backdrop').remove();
if (angular.isFunction(hopscotchConfig.onTourEndCB)) {
hopscotchConfig.onTourEndCB();
}
}
function setupSteps() {
_.forEach(hopscotchConfig.steps, function(step) {
step.onNextOrig = step.onNext;
step.onPrevOrig = step.onPrev;
step.onNext = onStepNext;
step.onPrev = onStepPrev;
step.fixedElement = true;
// Since we use a title area, move up to get arrow out of title area
if (angular.isUndefined(step.yOffset) && (step.placement === 'right' || step.placement === 'left' )) {
step.yOffset = -45;
}
});
}
function onStepNext() {
var stepNum = hopscotch.getCurrStepNum() - 1;
var stepConfig = hopscotchConfig.steps[stepNum];
if (stepConfig) {
if (stepConfig.onNextOrig) {
stepConfig.onNextOrig();
}
makeStepTargetVisible(stepNum + 1);
}
}
function onStepPrev() {
var stepNum = hopscotch.getCurrStepNum() + 1;
var stepConfig = hopscotchConfig.steps[stepNum];
if (stepConfig) {
if (stepConfig.onPrevOrig) {
stepConfig.onPrevOrig();
}
makeStepTargetVisible(stepNum - 1);
}
}
function makeStepTargetVisible(stepNum) {
var stepConfig = hopscotchConfig.steps[stepNum];
if (!stepConfig) {
return;
}
if (stepConfig.preShow) {
stepConfig.preShow();
}
if (stepConfig.targetScrollElement) {
var scrollElement = $('body').find(stepConfig.targetScrollElement)[0];
var targetElement = $('body').find(stepConfig.target)[0];
if (scrollElement && scrollElement) {
var offsetTop = getOffsetTopFromScrollElement(targetElement, scrollElement);
if (stepConfig.placement === 'top') {
offsetTop -= bubbleHeight;
} else {
offsetTop += bubbleHeight;
}
if (offsetTop > scrollElement.clientHeight) {
scrollElement.scrollTop = offsetTop;
} else {
scrollElement.scrollTop = 0;
}
}
}
}
function getOffsetTopFromScrollElement(targetElement, scrollElement) {
if (!targetElement || targetElement === scrollElement) {
return 0;
} else {
return targetElement.offsetTop + getOffsetTopFromScrollElement(targetElement.offsetParent, scrollElement);
}
}
return {
startTour: startTour,
cancelTour: cancelTour
};
});
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