Skip to content

Commit

Permalink
BS4 compatibility & sanitize fixes
Browse files Browse the repository at this point in the history
Fixes for additional Bootstrap4 compatibility. Resolved issues with BS4 sanitize feature, which is broken in the Bootstrap CDN. These changes require further testing.
  • Loading branch information
IGreatlyDislikeJavascript authored Mar 11, 2019
1 parent 8c1f1a2 commit 0f620fa
Show file tree
Hide file tree
Showing 2 changed files with 102 additions and 25 deletions.
48 changes: 37 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,14 @@ The original Bootstrap Tour was written in coffeescript, and had a number of ope
This repo has been created to give an easy way to update and track the revisions to the code, rather than filling up the original Tour forum.


Tourist automatically works with Bootstrap 3 and 4, however the "standalone" non-Bootstrap version is not available
Tourist works with Bootstrap 3 and 4 (specify "framework" option), however the "standalone" non-Bootstrap version is not available

## Changelog from previous version:

Changes from 0.7:
Fast release to fix breaking change in Bootstrap 3.4.1, fixes this issue: https://github.com/sorich87/bootstrap-tour/issues/723#issuecomment-471107788
Issue is caused by the BS sanitizer, to avoid this reoccurring the "sanitizeWhitelist:" and "sanitizeFunction:" global options added
Changes from 0.8:
The fast fix in v0.7 didn't work for Bootstrap 4. This release is to ensure fully working popovers in BS4. Issue is that the Bootstrap CDN
doesn't actually have the whitelist property, so developing against it is basically useless :(
Improved BS4 support and template switching. Changed options for framework vs template.

Full changelog can be found in the top of bootstrap-tourist.js

Expand Down Expand Up @@ -58,8 +59,22 @@ If you already have a working tour using Bootstrap Tour, and you want to move to

1. Copy over the Tourist CSS and JS, include them instead of Bootstrap Tour
2. If you are using Bootstrap 4, add the following option to your initialization code:

```framework: "bootstrap4"```

For example:

```
var tour = new Tour({
name: "tourist",
steps:[...steps go here...],
debug: true, // you may wish to turn on debug for the first run through
framework: "bootstrap4", // set Tourist to use BS4 compatibility
});
```

3. Remove the call to tour.init() - this is not required

4. Add a call to tour.start() to start the tour, and optionally add a call to tour.restart() to force restart the tour


Expand Down Expand Up @@ -119,6 +134,7 @@ var tourSteps = [
var Tour=new Tour({
steps: tourSteps,
framework: "bootstrap3", // or "bootstrap4" depending on your version of bootstrap
onNext: function(tour)
{
if(someVar = true)
Expand Down Expand Up @@ -228,6 +244,7 @@ var tourSteps = [
var Tour=new Tour({
steps: tourSteps,
framework: "bootstrap3", // or "bootstrap4" depending on your version of bootstrap
showProgressBar: true, // default show progress bar
showProgressText: true, // default show progress text
});
Expand Down Expand Up @@ -266,6 +283,7 @@ var tourSteps = [
];
var Tour=new Tour({
steps: tourSteps,
framework: "bootstrap3", // or "bootstrap4" depending on your version of bootstrap
showProgressBar: true, // default show progress bar
showProgressText: true, // default show progress text
getProgressBarHTML: function(percent)
Expand Down Expand Up @@ -367,6 +385,7 @@ element === Bootstrap modal, or element parent === bootstrap modal is automatica
```
var Tour=new Tour({
steps: tourSteps,
framework: "bootstrap3", // or "bootstrap4" depending on your version of bootstrap
onModalHidden: function(tour, stepNumber)
{
console.log("Well damn, this step's element was a modal, or inside a modal, and the modal just done got dismissed y'all. Moving to step 3.");
Expand All @@ -379,6 +398,7 @@ var Tour=new Tour({
var Tour=new Tour({
steps: tourSteps,
framework: "bootstrap3", // or "bootstrap4" depending on your version of bootstrap
onModalHidden: function(tour, stepNumber)
{
if(validateSomeModalContent() == false)
Expand Down Expand Up @@ -455,6 +475,7 @@ the tour really is started or ended.
```
var Tour=new Tour({
steps: [ ..... ],
framework: "bootstrap3", // or "bootstrap4" depending on your version of bootstrap
onPreviouslyEnded: function(tour)
{
console.log("Looks like this tour has already ended");
Expand All @@ -468,13 +489,16 @@ Tour.start();
### Switch between Bootstrap 3 or 4 (popover template) automatically using tour options, or use a custom template
With thanks to this thread: https://github.com/sorich87/bootstrap-tour/pull/643

Tour is compatible with bootstrap 3 and 4 if the right template is used for the popover. To select the correct template, use the "framework" global option.
Tour is compatible with bootstrap 3 and 4 if the right template and framework is used for the popover. Bootstrap3 framework compatibility is used by default.

To select the correct template and framework, use the "framework" global option. Note this option does more than just select a template, it also changes which methods are used to manage the Tour popovers to be BS3 or BS4 compatible.

```
var Tour=new Tour({
steps: tourSteps,
template: null, // template option is null by default, but MUST BE SET TO NULL to use the framework option
framework: "bootstrap4" // can be string literal "bootstrap3" or "bootstrap4"
template: null, // template option is null by default. Tourist will use the appropriate template
// for the framework version, in this case BS3 as per next option
framework: "bootstrap3" // can be string literal "bootstrap3" or "bootstrap4"
});
```

Expand All @@ -483,15 +507,16 @@ To use a custom template, use the "template" global option:
```
var Tour=new Tour({
steps: tourSteps,
framework: "bootstrap4", // or "bootstrap4" depending on your version of bootstrap
template: '<div class="popover" role="tooltip">....blah....</div>'
});
```

Review the following logic:
- If neither template nor framework options are specified, bootstrap3 compatibility template is used by default
- If template == null, framework option is used
- If template != null, template is always used
- If template == null, and framework option is not literal "bootstrap3" or "bootstrap4", error will occur
- If template == null, default framework template is used based on whether framework is set to "bootstrap3" or "bootstrap4"
- If template != null, the specified template is always used
- If framework option is not literal "bootstrap3" or "bootstrap4", error will occur


To add additional templates, search the code for "PLACEHOLDER: TEMPLATES LOCATION". This will take you to an array that contains the templates, simply edit
or add as required.
Expand Down Expand Up @@ -554,6 +579,7 @@ Note: if you have complete control over the tour content (i.e.: no risk of XSS o
```
var Tour=new Tour({
steps: tourSteps,
framework: "bootstrap3", // or "bootstrap4" depending on your version of bootstrap
sanitizeFunction: function(stepContent)
{
// POTENTIAL SECURITY RISK
Expand Down
79 changes: 65 additions & 14 deletions bootstrap-tourist.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/* ========================================================================
*
* Bootstrap Tourist v0.8
* Bootstrap Tourist v0.9
* Copyright FFS 2019
* @ IGreatlyDislikeJavascript on Github
*
Expand Down Expand Up @@ -40,7 +40,12 @@
* limitations under the License.
* ========================================================================
*
* Updated for CS by FFS 2018 - v0.8
* Updated for CS by FFS 2018 - v0.9
*
* Changes from 0.8:
* - The fast fix in v0.7 didn't work for Bootstrap 4. This release is to ensure fully working popovers in BS4. Issue is that the Bootstrap CDN
* doesn't actually have the whitelist property, so developing against it is basically useless :(
* - Improved BS4 support and template switching. Changed options for framework vs template.
*
* Changes from 0.7:
* - Fast release to fix breaking change in Bootstrap 3.4.1, fixes this issue: https://github.com/sorich87/bootstrap-tour/issues/723#issuecomment-471107788
Expand Down Expand Up @@ -75,7 +80,7 @@
10. Handle bootstrap modal dialogs better - autodetect modals or children of modals, and call onModalHidden to handle when user dismisses modal without following tour steps
11. Automagically fixes drawing issues with Bootstrap Selectpicker (https://github.com/snapappointments/bootstrap-select/)
12. Call onPreviouslyEnded if tour.start() is called for a tour that has previously ended (see docs)
13. Switch between Bootstrap 3 or 4 (popover template) automatically using tour options
13. Switch between Bootstrap 3 or 4 (popover methods and template) automatically using tour options
14. Added sanitizeWhitelist and sanitizeFunction global options
--------------
Expand Down Expand Up @@ -103,6 +108,7 @@
var Tour=new Tour({
steps: tourSteps,
framework: "bootstrap3", // or "bootstrap4" depending on your version of bootstrap
onNext: function(tour)
{
if(someVar = true)
Expand Down Expand Up @@ -203,6 +209,7 @@
}
];
var Tour=new Tour({
framework: "bootstrap3", // or "bootstrap4" depending on your version of bootstrap
steps: tourSteps,
showProgressBar: true, // default show progress bar
showProgressText: true, // default show progress text
Expand Down Expand Up @@ -328,6 +335,7 @@
var Tour=new Tour({
steps: tourSteps,
framework: "bootstrap3", // or "bootstrap4" depending on your version of bootstrap
onModalHidden: function(tour, stepNumber)
{
console.log("Well damn, this step's element was a modal, or inside a modal, and the modal just done got dismissed y'all. Moving to step 3.");
Expand Down Expand Up @@ -412,6 +420,7 @@
var Tour=new Tour({
steps: [ ..... ],
framework: "bootstrap3", // or "bootstrap4" depending on your version of bootstrap
onPreviouslyEnded: function(tour)
{
console.log("Looks like this tour has already ended");
Expand All @@ -421,14 +430,18 @@
tour.start();
----------------
13. Switch between Bootstrap 3 or 4 (popover template) automatically using tour options, or use a custom template
13. Switch between Bootstrap 3 or 4 (popover methods, template) automatically using tour options, or use a custom template
With thanks to this thread: https://github.com/sorich87/bootstrap-tour/pull/643
Tour is compatible with bootstrap 3 and 4 if the right template is used for the popover. To select the correct template, use the "framework" global option.
Tour is compatible with bootstrap 3 and 4 if the right template and framework is used for the popover. Bootstrap3 framework compatibility is used by default.
To select the correct template and framework, use the "framework" global option. Note this option does more than just select a template, it also changes which
methods are used to manage the Tour popovers to be BS3 or BS4 compatible.
var Tour=new Tour({
steps: tourSteps,
template: null, // template option is null by default, but MUST BE SET TO NULL to use the framework option
template: null, // template option is null by default. Tourist will use the appropriate template
// for the framework version, in this case BS3 as per next option
framework: "bootstrap3", // can be string literal "bootstrap3" or "bootstrap4"
});
Expand All @@ -437,13 +450,14 @@
var Tour=new Tour({
steps: tourSteps,
framework: "bootstrap4", // can be string literal "bootstrap3" or "bootstrap4"
template: '<div class="popover" role="tooltip">....blah....</div>'
});
Review the following logic:
- If template == null, framework option is used
- If template != null, template is always used
- If template == null, and framework option is not literal "bootstrap3" or "bootstrap4", error will occur
- If template == null, default framework template is used based on whether framework is set to "bootstrap3" or "bootstrap4"
- If template != null, the specified template is always used
- If framework option is not literal "bootstrap3" or "bootstrap4", error will occur
To add additional templates, search the code for "PLACEHOLDER: TEMPLATES LOCATION". This will take you to an array that contains the templates, simply edit
Expand Down Expand Up @@ -597,6 +611,12 @@
onModalHidden: null, // function(tour, stepNumber) {}
}, options);

if(this._options.framework !== "bootstrap3" && this._options.framework !== "bootstrap4")
{
this._debug('Invalid framework specified: ' + this._options.framework);
throw "Bootstrap Tourist: Invalid framework specified";
}

// template option is default null. If not null after extend, caller has set a custom template, so don't touch it
if(this._options.template === null)
{
Expand All @@ -610,7 +630,7 @@
}
else
{
this._debug('Warning: ' + this._options.framework + ' specified for template, but framework is unknown. Tour will not work!');
this._debug('Warning: ' + this._options.framework + ' specified for template (no template option set), but framework is unknown. Tour will not work!');
}
}
else
Expand All @@ -632,8 +652,20 @@
// bootstrap 3.4.1 has whitelist functionality that strips tags from title, content etc of popovers and tooltips. Need to
// add buttons to the whitelist otherwise the navigation buttons will be stripped from the popover content.
// See issue: https://github.com/sorich87/bootstrap-tour/issues/723#issuecomment-471107788
//
// ** UPDATE: BS3 and BS4 have the whitelist function. However:
// BS3 uses $.fn.popover.Constructor.DEFAULTS.whiteList
// BS4 uses $.fn.popover.Constructor.Default.whiteList
// Even better, the CDN version of BS4 doesn't seem to include a whitelist property at all, which utterly screwed the first attempt at implementing
// this, making it seem like my fix was working when in fact it was utterly broken.
var defaultWhiteList = [];
if($.fn.popover.Constructor.DEFAULTS.whiteList !== undefined)

if(this._options.framework == "bootstrap4" && $.fn.popover.Constructor.Default.whiteList !== undefined)
{
defaultWhiteList = $.fn.popover.Constructor.Default.whiteList;
}

if(this._options.framework == "bootstrap3" && $.fn.popover.Constructor.DEFAULTS.whiteList !== undefined)
{
defaultWhiteList = $.fn.popover.Constructor.DEFAULTS.whiteList;
}
Expand Down Expand Up @@ -977,7 +1009,17 @@
$element = $('body');
}

$element.popover('destroy').removeClass("tour-" + _this._options.name + "-element tour-" + _this._options.name + "-" + _this.getCurrentStepIndex() + "-element").removeData('bs.popover');
if(_this._options.framework == "bootstrap3")
{
$element.popover('destroy');
}

if(_this._options.framework == "bootstrap4")
{
$element.popover('dispose');
}

$element.removeClass("tour-" + _this._options.name + "-element tour-" + _this._options.name + "-" + _this.getCurrentStepIndex() + "-element").removeData('bs.popover');

if (step.reflex)
{
Expand Down Expand Up @@ -1615,14 +1657,23 @@
html: true,
//sanitize: false, // turns off all bootstrap sanitization of popover content, only use in last resort case - use whiteListAdditions instead!
whiteList: this._options.sanitizeWhitelist, // ignored if sanitizeFn is specified
sanitizeFn: this._options.santizeFunction,
sanitizeFn: this._options.sanitizeFunction,
animation: step.animation,
container: step.container,
template: step.template,
selector: step.element
}).popover('show');

$tip = $element.data('bs.popover') ? $element.data('bs.popover').tip() : $element.data('popover').tip();
if(this._options.framework == "bootstrap3")
{
$tip = $element.data('bs.popover') ? $element.data('bs.popover').tip() : $element.data('popover').tip();
}

if(this._options.framework == "bootstrap4")
{
$tip = $( ($element.data('bs.popover') ? $element.data('bs.popover').getTipElement() : $element.data('popover').getTipElement() ) );
}

$tip.attr('id', step.id);
if ($element.css('position') === 'fixed') {
$tip.css('position', 'fixed');
Expand Down

0 comments on commit 0f620fa

Please sign in to comment.