react-joyride
Advanced tools
Comparing version 0.6.4 to 0.6.5
@@ -8,3 +8,3 @@ var React = require('react/addons'); | ||
cssPosition: React.PropTypes.string.isRequired, | ||
handleClick: React.PropTypes.func.isRequired, | ||
onClick: React.PropTypes.func.isRequired, | ||
xPos: React.PropTypes.oneOfType([ | ||
@@ -40,3 +40,3 @@ React.PropTypes.number, | ||
style: styles, | ||
onClick: this.props.handleClick | ||
onClick: this.props.onClick | ||
}, | ||
@@ -43,0 +43,0 @@ React.createElement('span', { className: 'inner' }), |
@@ -9,26 +9,37 @@ var React = require('react/addons'), | ||
initialized: false, | ||
mixin: false, | ||
steps: [], | ||
/** | ||
* Returns the current browser | ||
* @returns {String} | ||
*/ | ||
getBrowser: function () { | ||
// Return cached result if avalible, else get result then cache it. | ||
if (this.browser) { | ||
return this.browser; | ||
} | ||
// Return cached result if avalible, else get result then cache it. | ||
if (this.browser) { | ||
return this.browser; | ||
} | ||
var isOpera = Boolean(window.opera) || navigator.userAgent.indexOf(' OPR/') >= 0; | ||
// Opera 8.0+ (UA detection to detect Blink/v8-powered Opera) | ||
var isFirefox = typeof InstallTrigger !== 'undefined';// Firefox 1.0+ | ||
var isSafari = Object.prototype.toString.call(window.HTMLElement).indexOf('Constructor') > 0; | ||
// At least Safari 3+: "[object HTMLElementConstructor]" | ||
var isChrome = Boolean(window.chrome) && !isOpera;// Chrome 1+ | ||
var isIE = /*@cc_on!@*/false || Boolean(document.documentMode); // At least IE6 | ||
var isOpera = Boolean(window.opera) || navigator.userAgent.indexOf(' OPR/') >= 0; | ||
// Opera 8.0+ (UA detection to detect Blink/v8-powered Opera) | ||
var isFirefox = typeof InstallTrigger !== 'undefined';// Firefox 1.0+ | ||
var isSafari = Object.prototype.toString.call(window.HTMLElement).indexOf('Constructor') > 0; | ||
// At least Safari 3+: "[object HTMLElementConstructor]" | ||
var isChrome = Boolean(window.chrome) && !isOpera;// Chrome 1+ | ||
var isIE = /*@cc_on!@*/false || Boolean(document.documentMode); // At least IE6 | ||
return (this.browser = | ||
isOpera ? 'opera' : | ||
isFirefox ? 'firefox' : | ||
isSafari ? 'safari' : | ||
isChrome ? 'chrome' : | ||
isIE ? 'ie' : | ||
''); | ||
return (this.browser = | ||
isOpera ? 'opera' : | ||
isFirefox ? 'firefox' : | ||
isSafari ? 'safari' : | ||
isChrome ? 'chrome' : | ||
isIE ? 'ie' : | ||
''); | ||
}, | ||
/** | ||
* Get an element actual dimensions with margin | ||
* @param el {String|@type {HTMLElement}} - Element node or selector | ||
* @returns {{height: number, width: number}} | ||
*/ | ||
getElementDimensions: function (el) { | ||
@@ -47,2 +58,156 @@ // Get the DOM Node if you pass in a string | ||
}, | ||
/** | ||
* Get the scrollTop position | ||
* @returns {number} | ||
*/ | ||
getScrollTop: function () { | ||
var state = this.mixin.state, | ||
step = joyride.steps[state.joyrideCurrentIndex], | ||
position = state.joyrideOverridePosition || step.position, | ||
target = document.querySelector(step.selector), | ||
targetTop = target.getBoundingClientRect().top + document.body.scrollTop, | ||
scrollTop = 0; | ||
if (/^top/.test(position)) { | ||
scrollTop = Math.floor(state.joyrideYPos - state.joyrideScrollOffset); | ||
} | ||
else if (/^bottom|^left|^right/.test(position)) { | ||
scrollTop = Math.floor(targetTop - state.joyrideScrollOffset); | ||
} | ||
return scrollTop; | ||
}, | ||
/** | ||
* Keydown event listener | ||
* @this {Mixin} | ||
* @param e {Event} - Keyboard event | ||
*/ | ||
keyboardNavigation: function (e) { | ||
var intKey = (window.Event) ? e.which : e.keyCode, | ||
hasSteps; | ||
if (this.state.joyrideShowTooltip) { | ||
if ([32, 38, 40].indexOf(intKey) > -1) { | ||
e.preventDefault(); | ||
} | ||
if (intKey === 27) { | ||
joyride.toggleTooltip(false, this.state.joyrideCurrentIndex + 1); | ||
} | ||
else if ([13, 32].indexOf(intKey) > -1) { | ||
hasSteps = Boolean(joyride.steps[this.state.joyrideCurrentIndex + 1]); | ||
joyride.toggleTooltip(hasSteps, this.state.joyrideCurrentIndex + 1); | ||
} | ||
} | ||
}, | ||
/** | ||
* Beacon click event listener | ||
* @this {Mixin} | ||
* @param e {Event} - Keyboard event | ||
*/ | ||
onClickBeacon: function (e) { | ||
e.preventDefault(); | ||
joyride.toggleTooltip(true, this.state.joyrideCurrentIndex); | ||
}, | ||
/** | ||
* Tooltip click event listener | ||
* @this {Mixin} | ||
* @param e {Event} - Keyboard event | ||
*/ | ||
onClickTooltip: function (e) { | ||
e.preventDefault(); | ||
e.stopPropagation(); | ||
var state = this.state, | ||
type = e.currentTarget.getAttribute('data-type'), | ||
newIndex = state.joyrideCurrentIndex + (type === 'back' ? -1 : 1); | ||
if (e.target === e.currentTarget) { | ||
joyride.toggleTooltip(state.joyrideType === 'guided' && type !== 'close' && Boolean(joyride.steps[newIndex]), newIndex); | ||
} | ||
}, | ||
/** | ||
* Position absolute elements next to its target based on | ||
* the step position and window size | ||
* @this {Mixin|this} | ||
*/ | ||
calcPlacement: function () { | ||
var mixin = this.mixin || this, | ||
state = mixin.state, | ||
step = joyride.steps[state.joyrideCurrentIndex], | ||
component = document.querySelector((state.joyrideShowTooltip ? '.joyride-tooltip' : '.joyride-beacon')), | ||
position, | ||
body, | ||
target, | ||
placement = { | ||
x: -1000, | ||
y: -1000 | ||
}; | ||
if (step && (!/animate/.test(component.className) || state.joyrideXPos < 0)) { | ||
position = step.position; | ||
body = document.body.getBoundingClientRect(); | ||
target = document.querySelector(step.selector).getBoundingClientRect(); | ||
component = joyride.getElementDimensions((state.joyrideShowTooltip ? '.joyride-tooltip' : '.joyride-beacon')); | ||
// Change the step position in the tooltip won't fit in the window | ||
if (/^left/.test(position) && target.left - (component.width + state.joyrideTooltipOffset) < 0) { | ||
position = 'top'; | ||
} | ||
else if (/^right/.test(position) && target.left + target.width + (component.width + state.joyrideTooltipOffset) > body.width) { | ||
position = 'bottom'; | ||
} | ||
// Calculate x position | ||
if (/^left/.test(position)) { | ||
placement.x = target.left - (state.joyrideShowTooltip ? component.width + state.joyrideTooltipOffset : component.width / 2); | ||
} | ||
else if (/^right/.test(position)) { | ||
placement.x = target.left + target.width - (state.joyrideShowTooltip ? -state.joyrideTooltipOffset : component.width / 2); | ||
} | ||
else { | ||
placement.x = target.left + target.width / 2 - component.width / 2; | ||
} | ||
// Calculate y position | ||
if (/^top/.test(position)) { | ||
placement.y = (target.top - body.top) - (state.joyrideShowTooltip ? component.height + state.joyrideTooltipOffset : component.height / 2); | ||
} | ||
else if (/^bottom/.test(position)) { | ||
placement.y = (target.top - body.top) + target.height - (state.joyrideShowTooltip ? -state.joyrideTooltipOffset : component.height / 2); | ||
} | ||
else { | ||
placement.y = (target.top - body.top) + target.height / 2 - component.height / 2 + (state.joyrideShowTooltip ? state.joyrideTooltipOffset : 0); | ||
} | ||
if (/^bottom|^top/.test(position)) { | ||
if (/left/.test(position)) { | ||
placement.x = target.left - (state.joyrideShowTooltip ? state.joyrideTooltipOffset : component.width / 2); | ||
} | ||
else if (/right/.test(position)) { | ||
placement.x = target.left + target.width - (state.joyrideShowTooltip ? component.width - state.joyrideTooltipOffset : component.width / 2); | ||
} | ||
} | ||
mixin.setState({ | ||
joyrideXPos: joyride.preventWindowOverflow(Math.ceil(placement.x), 'x', component.width, component.height), | ||
joyrideYPos: joyride.preventWindowOverflow(Math.ceil(placement.y), 'y', component.width, component.height), | ||
joyrideOverridePosition: step.position !== position ? position : false | ||
}); | ||
} | ||
}, | ||
/** | ||
* Prevent tooltip to render outside the window | ||
* @param value {Number} - The axis position | ||
* @param axis {String} - The Axis X or Y | ||
* @param elWidth {Number} - The target element width | ||
* @param elHeight {Number} - The target element height | ||
* @returns {Number} | ||
*/ | ||
preventWindowOverflow: function (value, axis, elWidth, elHeight) { | ||
@@ -71,2 +236,16 @@ var winWidth = window.innerWidth, | ||
return newValue; | ||
}, | ||
/** | ||
* | ||
* @param show {Boolean} Render the tooltip directly or the beacon | ||
* @param index {Number} The tour's new index | ||
*/ | ||
toggleTooltip: function (show, index) { | ||
this.mixin.setState({ | ||
joyrideShowTooltip: show, | ||
joyrideCurrentIndex: index, | ||
joyrideXPos: -1000, | ||
joyrideYPos: -1000 | ||
}); | ||
} | ||
@@ -79,2 +258,3 @@ }; | ||
joyrideCurrentIndex: 0, | ||
joyrideKeyboardNavigation: true, | ||
joyrideLocale: { | ||
@@ -111,11 +291,21 @@ back: 'Back', | ||
if (state.joyridePlay && joyride.steps[state.joyrideCurrentIndex]) { | ||
this._renderLayer(); | ||
this._joyrideRenderLayer(); | ||
} | ||
window.addEventListener('resize', this._calculatePlacement); | ||
joyride.mixin = this; | ||
window.addEventListener('resize', joyride.calcPlacement.bind(this)); | ||
if (this.state.joyrideKeyboardNavigation) { | ||
document.body.addEventListener('keydown', joyride.keyboardNavigation.bind(this)); | ||
} | ||
}, | ||
componentWillUnmount: function () { | ||
this._unrenderLayer(); | ||
this._joyrideUnrenderLayer(); | ||
document.body.removeChild(this._target); | ||
window.removeEventListener('resize', this._calculatePlacement); | ||
window.removeEventListener('resize', joyride.calcPlacement.bind(this)); | ||
if (this.state.joyrideKeyboardNavigation) { | ||
document.body.removeEventListener('keydown', joyride.keyboardNavigation.bind(this)); | ||
} | ||
}, | ||
@@ -135,3 +325,3 @@ | ||
if ((opt.shouldRun || opt.toggleTooltip || opt.newX || opt.newY) && opt.hasStep) { | ||
this._renderLayer(); | ||
this._joyrideRenderLayer(); | ||
} | ||
@@ -142,3 +332,3 @@ else if (opt.shouldRun && opt.hasSteps && !opt.hasStep) { | ||
} | ||
this._unrenderLayer(); | ||
this._joyrideUnrenderLayer(); | ||
} | ||
@@ -210,124 +400,4 @@ }, | ||
_onClickBeacon: function (e) { | ||
e.preventDefault(); | ||
this.setState({ | ||
joyrideShowTooltip: true, | ||
joyrideXPos: -1000, | ||
joyrideYPos: -1000 | ||
}); | ||
}, | ||
_onClickTooltip: function (e) { | ||
e.preventDefault(); | ||
e.stopPropagation(); | ||
var state = this.state, | ||
type = e.currentTarget.getAttribute('data-type'), | ||
newIndex = state.joyrideCurrentIndex + (type === 'back' ? -1 : 1); | ||
if (e.target === e.currentTarget) { | ||
if (typeof state.joyrideStepCallback === 'function') { | ||
state.joyrideStepCallback(joyride.steps[state.joyrideCurrentIndex]); | ||
} | ||
this.setState({ | ||
joyrideShowTooltip: state.joyrideType === 'guided' && type !== 'close' && Boolean(joyride.steps[newIndex]), | ||
joyrideCurrentIndex: newIndex, | ||
joyrideXPos: -1000, | ||
joyrideYPos: -1000 | ||
}); | ||
} | ||
}, | ||
_calculatePlacement: function () { | ||
var state = this.state, | ||
step = joyride.steps[state.joyrideCurrentIndex], | ||
component = document.querySelector((state.joyrideShowTooltip ? '.joyride-tooltip' : '.joyride-beacon')), | ||
position, | ||
body, | ||
target, | ||
placement = { | ||
x: -1000, | ||
y: -1000 | ||
}; | ||
if (step && (!/animate/.test(component.className) || state.joyrideXPos < 0)) { | ||
position = step.position; | ||
body = document.body.getBoundingClientRect(); | ||
target = document.querySelector(step.selector).getBoundingClientRect(); | ||
component = joyride.getElementDimensions((state.joyrideShowTooltip ? '.joyride-tooltip' : '.joyride-beacon')); | ||
// Change the step position in the tooltip won't fit in the window | ||
if (/^left/.test(position) && target.left - (component.width + state.joyrideTooltipOffset) < 0) { | ||
position = 'top'; | ||
} | ||
else if (/^right/.test(position) && target.left + target.width + (component.width + state.joyrideTooltipOffset) > body.width) { | ||
position = 'bottom'; | ||
} | ||
// Calculate x position | ||
if (/^left/.test(position)) { | ||
placement.x = target.left - (state.joyrideShowTooltip ? component.width + state.joyrideTooltipOffset : component.width / 2); | ||
} | ||
else if (/^right/.test(position)) { | ||
placement.x = target.left + target.width - (state.joyrideShowTooltip ? -state.joyrideTooltipOffset : component.width / 2); | ||
} | ||
else { | ||
placement.x = target.left + target.width / 2 - component.width / 2; | ||
} | ||
// Calculate y position | ||
if (/^top/.test(position)) { | ||
placement.y = (target.top - body.top) - (state.joyrideShowTooltip ? component.height + state.joyrideTooltipOffset : component.height / 2); | ||
} | ||
else if (/^bottom/.test(position)) { | ||
placement.y = (target.top - body.top) + target.height - (state.joyrideShowTooltip ? -state.joyrideTooltipOffset : component.height / 2); | ||
} | ||
else { | ||
placement.y = (target.top - body.top) + target.height / 2 - component.height / 2 + (state.joyrideShowTooltip ? state.joyrideTooltipOffset : 0); | ||
} | ||
if (/^bottom|^top/.test(position)) { | ||
if (/left/.test(position)) { | ||
placement.x = target.left - (state.joyrideShowTooltip ? state.joyrideTooltipOffset : component.width / 2); | ||
} | ||
else if (/right/.test(position)) { | ||
placement.x = target.left + target.width - (state.joyrideShowTooltip ? component.width - state.joyrideTooltipOffset : component.width / 2); | ||
} | ||
} | ||
this.setState({ | ||
joyrideXPos: joyride.preventWindowOverflow(Math.ceil(placement.x), 'x', component.width, component.height), | ||
joyrideYPos: joyride.preventWindowOverflow(Math.ceil(placement.y), 'y', component.width, component.height), | ||
joyrideOverridePosition: step.position !== position ? position : false | ||
}); | ||
} | ||
}, | ||
_getScrollTop: function () { | ||
var step = joyride.steps[this.state.joyrideCurrentIndex], | ||
position = this.state.joyrideOverridePosition || step.position, | ||
target = document.querySelector(step.selector), | ||
targetTop = target.getBoundingClientRect().top + document.body.scrollTop, | ||
scrollTop = 0; | ||
if (/^top/.test(position)) { | ||
scrollTop = Math.floor(this.state.joyrideYPos - this.state.joyrideScrollOffset); | ||
} | ||
else if (/^bottom|^left|^right/.test(position)) { | ||
scrollTop = Math.floor(targetTop - this.state.joyrideScrollOffset); | ||
} | ||
return scrollTop; | ||
}, | ||
_scrollToNextStep: function (cb) { | ||
if (joyride.steps[this.state.joyrideCurrentIndex] && this.state.joyrideScrollToSteps) { | ||
scroll.top(document.body, this._getScrollTop(), cb); | ||
} | ||
}, | ||
_renderLayer: function () { | ||
var component = this._renderCurrentStep(); | ||
_joyrideRenderLayer: function () { | ||
var component = this._joyrideRenderStep(); | ||
if (!joyride.initialized) { | ||
@@ -339,12 +409,14 @@ joyride.initialized = true; | ||
React.render(component, this._target, function () { | ||
this._calculatePlacement(); | ||
this._scrollToNextStep(); | ||
joyride.calcPlacement(); | ||
if (joyride.steps[this.state.joyrideCurrentIndex] && this.state.joyrideScrollToSteps) { | ||
scroll.top(document.body, joyride.getScrollTop()); | ||
} | ||
}.bind(this)); | ||
}, | ||
_unrenderLayer: function () { | ||
_joyrideUnrenderLayer: function () { | ||
React.unmountComponentAtNode(this._target); | ||
}, | ||
_renderCurrentStep: function () { | ||
_joyrideRenderStep: function () { | ||
var state = this.state, | ||
@@ -387,3 +459,3 @@ component, | ||
yPos: state.joyrideYPos, | ||
onClick: this._onClickTooltip | ||
onClick: joyride.onClickTooltip.bind(this) | ||
}); | ||
@@ -396,3 +468,3 @@ } | ||
yPos: state.joyrideYPos, | ||
handleClick: this._onClickBeacon | ||
onClick: joyride.onClickBeacon.bind(this) | ||
}); | ||
@@ -399,0 +471,0 @@ } |
{ | ||
"name": "react-joyride", | ||
"version": "0.6.4", | ||
"version": "0.6.5", | ||
"description": "Create walkthroughs and guided tours for your apps", | ||
@@ -31,7 +31,7 @@ "author": "Gil Barbara <gilbarbara@gmail.com>", | ||
"devDependencies": { | ||
"del": "^1.2", | ||
"del": "^2.0", | ||
"eslint": "^1.2", | ||
"eslint-plugin-react": "^3.3", | ||
"gulp": "^3.9", | ||
"gulp-autoprefixer": "^2.3", | ||
"gulp-autoprefixer": "^3.0", | ||
"gulp-eslint": "^1.0", | ||
@@ -38,0 +38,0 @@ "gulp-load-plugins": "^0.10", |
@@ -61,22 +61,24 @@ React Joyride | ||
`joyrideLocale` {object}: The strings used in the tooltip. Defaults to `{ back: 'Back', close: 'Close', last: 'Last', next: 'Next' }` | ||
**joyrideKeyboardNavigation** {bool}: Toggle keyboard navigation (esc, space bar, return). Defaults to `true` | ||
`joyrideScrollOffset` {number}: The scrollTop offset used in `joyrideScrollToSteps`. Defaults to `20` | ||
**joyrideLocale** {object}: The strings used in the tooltip. Defaults to `{ back: 'Back', close: 'Close', last: 'Last', next: 'Next' }` | ||
`joyrideScrollToSteps` {bool}: Scroll the page to the next step if needed. Defaults to `true` | ||
**joyrideScrollOffset** {number}: The scrollTop offset used in `joyrideScrollToSteps`. Defaults to `20` | ||
`joyrideShowBackButton` {bool}: Display a back button. Defaults to `true` | ||
**joyrideScrollToSteps** {bool}: Scroll the page to the next step if needed. Defaults to `true` | ||
`joyrideShowOverlay` {bool}: Display an overlay with holes above your steps. Defaults to `true` | ||
**joyrideShowBackButton** {bool}: Display a back button. Defaults to `true` | ||
`joyrideShowStepsProgress` {bool}: Display the tour progress in the next button (1/5) in `guided` tours. Defaults to `false` | ||
**joyrideShowOverlay** {bool}: Display an overlay with holes above your steps. Defaults to `true` | ||
`joyrideTooltipOffset` {number}: The tooltip offset from the target. Defaults to `30` | ||
**joyrideShowStepsProgress** {bool}: Display the tour progress in the next button (1/5) in `guided` tours. Defaults to `false` | ||
`joyrideType` {string}: The type of your presentation. It can be `guided` (played sequencially with the Next button) or `single`. Defaults to `guided` | ||
**joyrideTooltipOffset** {number}: The tooltip offset from the target. Defaults to `30` | ||
`joyrideCompleteCallback` {function}: It will be called after an user has completed all the steps in your tour and passes all steps. Defaults to `undefined` | ||
**joyrideType** {string}: The type of your presentation. It can be `guided` (played sequencially with the Next button) or `single`. Defaults to `guided` | ||
`joyrideStepCallback` {function}: It will be called after each step and passes the completed step. Defaults to `undefined` | ||
**joyrideCompleteCallback** {function}: It will be called after an user has completed all the steps in your tour and passes all steps. Defaults to `undefined` | ||
**joyrideStepCallback** {function}: It will be called after each step and passes the completed step. Defaults to `undefined` | ||
You can change these in `componentWillMount`. All optional. | ||
@@ -83,0 +85,0 @@ |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
48846
819
210