SeleniumBase/seleniumbase/core/tour_helper.py

1144 lines
42 KiB
Python

"""This module contains methods for running website tours.
These helper methods SHOULD NOT be called directly from tests."""
import os
import re
import textwrap
import time
from seleniumbase import config as sb_config
from seleniumbase.config import settings
from seleniumbase.core import style_sheet
from seleniumbase.fixtures import constants
from seleniumbase.fixtures import js_utils
from seleniumbase.fixtures import page_actions
EXPORTED_TOURS_FOLDER = constants.Tours.EXPORTED_TOURS_FOLDER
def activate_bootstrap(driver):
"""Allows you to use Bootstrap Tours with SeleniumBase
http://bootstraptour.com/
"""
bootstrap_tour_css = constants.BootstrapTour.MIN_CSS
bootstrap_tour_js = constants.BootstrapTour.MIN_JS
verify_script = """// Verify Bootstrap Tour activated
var tour2 = new Tour({
});"""
backdrop_style = style_sheet.get_bt_backdrop_style()
js_utils.add_css_style(driver, backdrop_style)
js_utils.wait_for_ready_state_complete(driver)
js_utils.wait_for_angularjs(driver)
for x in range(4):
js_utils.activate_jquery(driver)
js_utils.add_css_link(driver, bootstrap_tour_css)
js_utils.add_js_link(driver, bootstrap_tour_js)
time.sleep(0.1)
for x in range(int(settings.MINI_TIMEOUT * 2.0)):
# Bootstrap needs a small amount of time to load & activate.
try:
driver.execute_script(verify_script)
time.sleep(0.05)
return
except Exception:
time.sleep(0.15)
js_utils.raise_unable_to_load_jquery_exception(driver)
def is_bootstrap_activated(driver):
verify_script = """// Verify Bootstrap Tour activated
var tour2 = new Tour({
});"""
try:
driver.execute_script(verify_script)
return True
except Exception:
return False
def activate_driverjs(driver):
"""Allows you to use DriverJS Tours with SeleniumBase
https://kamranahmed.info/driver.js/
"""
backdrop_style = style_sheet.get_dt_backdrop_style()
driverjs_css = constants.DriverJS.MIN_CSS
driverjs_js = constants.DriverJS.MIN_JS
verify_script = """// Verify DriverJS activated
var driverjs2 = Driver.name;
"""
js_utils.wait_for_ready_state_complete(driver)
js_utils.wait_for_angularjs(driver)
js_utils.add_css_style(driver, backdrop_style)
for x in range(4):
js_utils.activate_jquery(driver)
js_utils.add_css_link(driver, driverjs_css)
js_utils.add_js_link(driver, driverjs_js)
time.sleep(0.1)
for x in range(int(settings.MINI_TIMEOUT * 2.0)):
# DriverJS needs a small amount of time to load & activate.
try:
driver.execute_script(verify_script)
js_utils.wait_for_ready_state_complete(driver)
js_utils.wait_for_angularjs(driver)
time.sleep(0.05)
return
except Exception:
time.sleep(0.15)
js_utils.raise_unable_to_load_jquery_exception(driver)
def is_driverjs_activated(driver):
verify_script = """// Verify DriverJS activated
var driverjs2 = Driver.name;
"""
try:
driver.execute_script(verify_script)
return True
except Exception:
return False
def activate_hopscotch(driver):
"""Allows you to use Hopscotch Tours with SeleniumBase
http://linkedin.github.io/hopscotch/
"""
hopscotch_css = constants.Hopscotch.MIN_CSS
hopscotch_js = constants.Hopscotch.MIN_JS
backdrop_style = style_sheet.get_hops_backdrop_style()
verify_script = """// Verify Hopscotch activated
var hops = hopscotch.isActive;
"""
js_utils.wait_for_ready_state_complete(driver)
js_utils.wait_for_angularjs(driver)
js_utils.add_css_style(driver, backdrop_style)
for x in range(4):
js_utils.activate_jquery(driver)
js_utils.add_css_link(driver, hopscotch_css)
js_utils.add_js_link(driver, hopscotch_js)
time.sleep(0.1)
for x in range(int(settings.MINI_TIMEOUT * 2.0)):
# Hopscotch needs a small amount of time to load & activate.
try:
driver.execute_script(verify_script)
js_utils.wait_for_ready_state_complete(driver)
js_utils.wait_for_angularjs(driver)
time.sleep(0.05)
return
except Exception:
time.sleep(0.15)
js_utils.raise_unable_to_load_jquery_exception(driver)
def is_hopscotch_activated(driver):
verify_script = """// Verify Hopscotch activated
var hops = hopscotch.isActive;
"""
try:
driver.execute_script(verify_script)
return True
except Exception:
return False
def activate_introjs(driver):
"""Allows you to use IntroJS Tours with SeleniumBase
https://introjs.com/
"""
intro_css = constants.IntroJS.MIN_CSS
intro_js = constants.IntroJS.MIN_JS
theme_color = sb_config.introjs_theme_color
hover_color = sb_config.introjs_hover_color
backdrop_style = style_sheet.get_introjs_style() % (
theme_color,
hover_color,
hover_color,
hover_color,
theme_color,
)
verify_script = """// Verify IntroJS activated
var intro2 = introJs();
"""
js_utils.wait_for_ready_state_complete(driver)
js_utils.wait_for_angularjs(driver)
js_utils.add_css_style(driver, backdrop_style)
for x in range(4):
js_utils.activate_jquery(driver)
js_utils.add_css_link(driver, intro_css)
js_utils.add_js_link(driver, intro_js)
time.sleep(0.1)
for x in range(int(settings.MINI_TIMEOUT * 2.0)):
# IntroJS needs a small amount of time to load & activate.
try:
driver.execute_script(verify_script)
js_utils.wait_for_ready_state_complete(driver)
js_utils.wait_for_angularjs(driver)
time.sleep(0.05)
return
except Exception:
time.sleep(0.15)
js_utils.raise_unable_to_load_jquery_exception(driver)
def is_introjs_activated(driver):
verify_script = """// Verify IntroJS activated
var intro2 = introJs();
"""
try:
driver.execute_script(verify_script)
return True
except Exception:
return False
def activate_shepherd(driver):
"""Allows you to use Shepherd Tours with SeleniumBase
https://cdnjs.com/libraries/shepherd/1.8.1
"""
shepherd_js = constants.Shepherd.MIN_JS
sh_theme_arrows_css = constants.Shepherd.THEME_ARROWS_CSS
sh_theme_arrows_fix_css = constants.Shepherd.THEME_ARR_FIX_CSS
sh_theme_default_css = constants.Shepherd.THEME_DEFAULT_CSS
sh_theme_dark_css = constants.Shepherd.THEME_DARK_CSS
sh_theme_sq_css = constants.Shepherd.THEME_SQ_CSS
sh_theme_sq_dark_css = constants.Shepherd.THEME_SQ_DK_CSS
tether_js = constants.Tether.MIN_JS
spinner_css = constants.Messenger.SPINNER_CSS
sh_style = style_sheet.get_sh_style_test()
backdrop_style = style_sheet.get_sh_backdrop_style()
js_utils.wait_for_ready_state_complete(driver)
js_utils.wait_for_angularjs(driver)
js_utils.add_css_style(driver, backdrop_style)
js_utils.wait_for_ready_state_complete(driver)
js_utils.wait_for_angularjs(driver)
for x in range(4):
js_utils.add_css_link(driver, spinner_css)
js_utils.add_css_link(driver, sh_theme_arrows_css)
js_utils.add_css_link(driver, sh_theme_arrows_fix_css)
js_utils.add_css_link(driver, sh_theme_default_css)
js_utils.add_css_link(driver, sh_theme_dark_css)
js_utils.add_css_link(driver, sh_theme_sq_css)
js_utils.add_css_link(driver, sh_theme_sq_dark_css)
js_utils.add_js_link(driver, tether_js)
js_utils.add_js_link(driver, shepherd_js)
time.sleep(0.1)
for x in range(int(settings.MINI_TIMEOUT * 2.0)):
# Shepherd needs a small amount of time to load & activate.
try:
driver.execute_script(sh_style) # Verify Shepherd has loaded
js_utils.wait_for_ready_state_complete(driver)
js_utils.wait_for_angularjs(driver)
driver.execute_script(sh_style) # Need it twice for ordering
js_utils.wait_for_ready_state_complete(driver)
js_utils.wait_for_angularjs(driver)
time.sleep(0.05)
return
except Exception:
time.sleep(0.15)
js_utils.raise_unable_to_load_jquery_exception(driver)
def is_shepherd_activated(driver):
sh_style = style_sheet.get_sh_style_test()
try:
driver.execute_script(sh_style) # Verify Shepherd has loaded
return True
except Exception:
return False
def play_shepherd_tour(driver, tour_steps, msg_dur, name=None, interval=0):
"""Plays a Shepherd tour on the current website."""
instructions = ""
for tour_step in tour_steps[name]:
instructions += tour_step
instructions += """
// Start the tour
tour.start();
$tour = tour;"""
extra = """
document.body.addEventListener('keyup', function (event) {
if (event.key === 'PageUp' || event.key === 'ArrowLeft') {
Shepherd.activeTour.back(); }
if (event.key === 'PageDown' || event.key === 'ArrowRight') {
Shepherd.activeTour.next(); }
})"""
autoplay = False
if interval and interval > 0:
autoplay = True
interval = float(interval)
if interval < 0.5:
interval = 0.5
if not is_shepherd_activated(driver):
instructions += extra
activate_shepherd(driver)
if len(tour_steps[name]) > 1:
try:
selector = re.search(
r"[\S\s]+{element: '([\S\s]+)', on: [\S\s]+",
tour_steps[name][1],
).group(1)
selector = selector.replace("\\", "")
page_actions.wait_for_element_present(
driver,
selector,
by="css selector",
timeout=settings.SMALL_TIMEOUT,
)
except Exception:
js_utils.post_messenger_error_message(
driver, "Tour Error: {'%s'} was not found!" % selector, msg_dur
)
raise Exception(
"Tour Error: {'%s'} was not found! "
"Exiting due to failure on first tour step!"
"" % selector
)
driver.execute_script(instructions)
try:
page_actions.wait_for_element_visible(
driver, "a.tour-button-right", by="css selector", timeout=1.2
)
except Exception:
pass
try:
driver.execute_script('document.activeElement.blur();')
except Exception:
pass
tour_on = True
if autoplay:
start_ms = time.time() * 1000.0
stop_ms = start_ms + (interval * 1000.0)
latest_element = None
latest_text = None
while tour_on:
try:
time.sleep(0.01)
result = driver.execute_script(
"return Shepherd.activeTour.currentStep.isOpen()"
)
except Exception:
tour_on = False
result = None
if result:
tour_on = True
if autoplay:
try:
element = driver.execute_script(
"return Shepherd.activeTour.currentStep"
".options.attachTo.element"
)
shep_text = driver.execute_script(
"return Shepherd.activeTour.currentStep"
".options.text"
)
except Exception:
continue
if element != latest_element or shep_text != latest_text:
latest_element = element
latest_text = shep_text
start_ms = time.time() * 1000.0
stop_ms = start_ms + (interval * 1000.0)
now_ms = time.time() * 1000.0
if now_ms >= stop_ms:
if (element == latest_element) and (
shep_text == latest_text
):
driver.execute_script("Shepherd.activeTour.next()")
try:
latest_element = driver.execute_script(
"return Shepherd.activeTour.currentStep"
".options.attachTo.element"
)
latest_text = driver.execute_script(
"return Shepherd.activeTour.currentStep"
".options.text"
)
start_ms = time.time() * 1000.0
stop_ms = start_ms + (interval * 1000.0)
except Exception:
pass
continue
else:
try:
time.sleep(0.01)
selector = driver.execute_script(
"return Shepherd.activeTour"
".currentStep.options.attachTo.element"
)
try:
js_utils.wait_for_css_query_selector(
driver, selector, timeout=settings.SMALL_TIMEOUT
)
except Exception:
remove_script = (
"jQuery('%s').remove()" % "div.shepherd-content"
)
driver.execute_script(remove_script)
js_utils.post_messenger_error_message(
driver,
"Tour Error: {'%s'} was not found!" % selector,
msg_dur,
)
time.sleep(0.1)
driver.execute_script("Shepherd.activeTour.next()")
if autoplay:
start_ms = time.time() * 1000.0
stop_ms = start_ms + (interval * 1000.0)
tour_on = True
except Exception:
tour_on = False
time.sleep(0.1)
def play_bootstrap_tour(
driver, tour_steps, browser, msg_dur, name=None, interval=0
):
"""Plays a Bootstrap tour on the current website."""
instructions = ""
for tour_step in tour_steps[name]:
instructions += tour_step
instructions += """]);
// Initialize the tour
tour.init();
// Start the tour
tour.start();
// Fix timing issue by restarting tour immediately
tour.restart();
// Save for later
$tour = tour;"""
if interval and interval > 0:
if interval < 1:
interval = 1
interval = str(float(interval) * 1000.0)
instructions = instructions.replace(
"duration: 0,", "duration: %s," % interval
)
if not is_bootstrap_activated(driver):
activate_bootstrap(driver)
if len(tour_steps[name]) > 1:
try:
if "element: " in tour_steps[name][1]:
selector = re.search(
r"[\S\s]+element: '([\S\s]+)',[\S\s]+title: '",
tour_steps[name][1],
).group(1)
selector = selector.replace("\\", "").replace(":first", "")
page_actions.wait_for_element_present(
driver,
selector,
by="css selector",
timeout=settings.SMALL_TIMEOUT,
)
else:
selector = "html"
except Exception:
js_utils.post_messenger_error_message(
driver, "Tour Error: {'%s'} was not found!" % selector, msg_dur
)
raise Exception(
"Tour Error: {'%s'} was not found! "
"Exiting due to failure on first tour step!"
"" % selector
)
driver.execute_script(instructions)
tour_on = True
try:
page_actions.wait_for_element_visible(
driver, ".tour-tour", by="css selector", timeout=1.2
)
except Exception:
pass
try:
driver.execute_script('document.activeElement.blur();')
except Exception:
pass
while tour_on:
try:
time.sleep(0.01)
if browser != "firefox":
result = driver.execute_script("return $tour.ended()")
else:
page_actions.wait_for_element_present(
driver, ".tour-tour", by="css selector", timeout=0.48
)
result = False
except Exception:
tour_on = False
result = None
if result is False:
tour_on = True
time.sleep(0.05)
else:
try:
time.sleep(0.01)
if browser != "firefox":
result = driver.execute_script("return $tour.ended()")
else:
page_actions.wait_for_element_present(
driver, ".tour-tour", by="css selector", timeout=0.48
)
result = False
if result is False:
time.sleep(0.05)
continue
else:
return
except Exception:
tour_on = False
time.sleep(0.1)
def play_driverjs_tour(
driver, tour_steps, browser, msg_dur, name=None, interval=0
):
"""Plays a DriverJS tour on the current website."""
instructions = ""
for tour_step in tour_steps[name]:
instructions += tour_step
instructions += """]
);
// Start the tour!
tour.start();
$tour = tour;"""
extra = """
document.body.addEventListener('keyup', function (event) {
if (event.key === 'PageUp') { $tour.movePrevious(); }
if (event.key === 'PageDown') { $tour.moveNext(); }
})"""
autoplay = False
if interval and interval > 0:
autoplay = True
interval = float(interval)
if interval < 0.5:
interval = 0.5
if not is_driverjs_activated(driver):
instructions += extra
activate_driverjs(driver)
if len(tour_steps[name]) > 1:
try:
if "element: " in tour_steps[name][1]:
selector = re.search(
r"[\S\s]+element: '([\S\s]+)',[\S\s]+popover: {",
tour_steps[name][1],
).group(1)
selector = selector.replace("\\", "").replace(":first", "")
page_actions.wait_for_element_present(
driver,
selector,
by="css selector",
timeout=settings.SMALL_TIMEOUT,
)
else:
selector = "html"
except Exception:
js_utils.post_messenger_error_message(
driver, "Tour Error: {'%s'} was not found!" % selector, msg_dur
)
raise Exception(
"Tour Error: {'%s'} was not found! "
"Exiting due to failure on first tour step!"
"" % selector
)
driver.execute_script(instructions)
driver.execute_script(
'document.querySelector(".driver-next-btn").focus();'
)
tour_on = True
if autoplay:
start_ms = time.time() * 1000.0
stop_ms = start_ms + (interval * 1000.0)
latest_step = 0
while tour_on:
try:
time.sleep(0.01)
if browser != "firefox":
result = not driver.execute_script("return $tour.isActivated")
else:
page_actions.wait_for_element_visible(
driver,
"#driver-popover-item",
by="css selector",
timeout=1.1,
)
result = False
except Exception:
tour_on = False
result = None
if result is False:
tour_on = True
driver.execute_script(
'document.querySelector(".driver-next-btn").focus();'
)
if autoplay:
try:
current_step = driver.execute_script(
"return $tour.currentStep"
)
except Exception:
continue
if current_step != latest_step:
latest_step = current_step
start_ms = time.time() * 1000.0
stop_ms = start_ms + (interval * 1000.0)
now_ms = time.time() * 1000.0
if now_ms >= stop_ms:
if current_step == latest_step:
driver.execute_script("$tour.moveNext()")
try:
latest_step = driver.execute_script(
"return $tour.currentStep"
)
start_ms = time.time() * 1000.0
stop_ms = start_ms + (interval * 1000.0)
except Exception:
pass
continue
else:
try:
time.sleep(0.01)
if browser != "firefox":
result = not driver.execute_script(
"return $tour.isActivated"
)
else:
page_actions.wait_for_element_visible(
driver,
"#driver-popover-item",
by="css selector",
timeout=1.1,
)
result = False
if result is False:
time.sleep(0.1)
continue
else:
return
except Exception:
tour_on = False
time.sleep(0.1)
def play_hopscotch_tour(
driver, tour_steps, browser, msg_dur, name=None, interval=0
):
"""Plays a Hopscotch tour on the current website."""
instructions = ""
for tour_step in tour_steps[name]:
instructions += tour_step
instructions += """]
};
// Start the tour!
hopscotch.startTour(tour);
$tour = hopscotch;"""
extra = """
document.body.addEventListener('keyup', function (event) {
if (event.key === 'PageUp' || event.key === 'ArrowLeft') {
$tour.prevStep(); }
if (event.key === 'PageDown' || event.key === 'ArrowRight') {
$tour.nextStep(); }
})"""
autoplay = False
if interval and interval > 0:
autoplay = True
interval = float(interval)
if interval < 0.5:
interval = 0.5
if not is_hopscotch_activated(driver):
instructions += extra
activate_hopscotch(driver)
if len(tour_steps[name]) > 1:
try:
if "target: " in tour_steps[name][1]:
selector = re.search(
r"[\S\s]+target: '([\S\s]+)',[\S\s]+title: '",
tour_steps[name][1],
).group(1)
selector = selector.replace("\\", "").replace(":first", "")
page_actions.wait_for_element_present(
driver,
selector,
by="css selector",
timeout=settings.SMALL_TIMEOUT,
)
else:
selector = "html"
except Exception:
js_utils.post_messenger_error_message(
driver, "Tour Error: {'%s'} was not found!" % selector, msg_dur
)
raise Exception(
"Tour Error: {'%s'} was not found! "
"Exiting due to failure on first tour step!"
"" % selector
)
driver.execute_script(instructions)
try:
page_actions.wait_for_element_visible(
driver, "button.hopscotch-next", by="css selector", timeout=1.2
)
except Exception:
pass
try:
driver.execute_script('document.activeElement.blur();')
except Exception:
pass
tour_on = True
if autoplay:
start_ms = time.time() * 1000.0
stop_ms = start_ms + (interval * 1000.0)
latest_step = 0
while tour_on:
try:
time.sleep(0.01)
if browser != "firefox":
result = not driver.execute_script("return $tour.isActive")
else:
page_actions.wait_for_element_present(
driver,
".hopscotch-bubble",
by="css selector",
timeout=0.4,
)
result = False
except Exception:
tour_on = False
result = None
if result is False:
tour_on = True
if autoplay:
try:
current_step = driver.execute_script(
"return $tour.getCurrStepNum()"
)
except Exception:
continue
if current_step != latest_step:
latest_step = current_step
start_ms = time.time() * 1000.0
stop_ms = start_ms + (interval * 1000.0)
now_ms = time.time() * 1000.0
if now_ms >= stop_ms:
if current_step == latest_step:
driver.execute_script("$tour.nextStep()")
try:
latest_step = driver.execute_script(
"return $tour.getCurrStepNum()"
)
start_ms = time.time() * 1000.0
stop_ms = start_ms + (interval * 1000.0)
except Exception:
pass
continue
else:
try:
time.sleep(0.01)
if browser != "firefox":
result = not driver.execute_script("return $tour.isActive")
else:
page_actions.wait_for_element_present(
driver,
".hopscotch-bubble",
by="css selector",
timeout=0.4,
)
result = False
if result is False:
time.sleep(0.1)
continue
else:
return
except Exception:
tour_on = False
time.sleep(0.1)
def play_introjs_tour(
driver, tour_steps, browser, msg_dur, name=None, interval=0
):
"""Plays an IntroJS tour on the current website."""
instructions = ""
for tour_step in tour_steps[name]:
instructions += tour_step
instructions += """]
});
intro.setOption("disableInteraction", true);
intro.setOption("overlayOpacity", .29);
intro.setOption("scrollToElement", true);
intro.setOption("keyboardNavigation", true);
intro.setOption("exitOnEsc", true);
intro.setOption("hidePrev", true);
intro.setOption("nextToDone", true);
intro.setOption("exitOnOverlayClick", false);
intro.setOption("showStepNumbers", false);
intro.setOption("showProgress", false);
intro.start();
$tour = intro;
};
// Start the tour
startIntro();
"""
extra = """
document.body.addEventListener('keyup', function (event) {
if (event.key === 'PageUp') { $tour.previousStep(); }
if (event.key === 'PageDown') { $tour.nextStep(); }
})"""
autoplay = False
if interval and interval > 0:
autoplay = True
interval = float(interval)
if interval < 0.5:
interval = 0.5
if not is_introjs_activated(driver):
instructions += extra
activate_introjs(driver)
if len(tour_steps[name]) > 1:
try:
if "element: " in tour_steps[name][1]:
selector = re.search(
r"[\S\s]+element: '([\S\s]+)',[\S\s]+intro: '",
tour_steps[name][1],
).group(1)
selector = selector.replace("\\", "")
page_actions.wait_for_element_present(
driver,
selector,
by="css selector",
timeout=settings.SMALL_TIMEOUT,
)
else:
selector = "html"
except Exception:
js_utils.post_messenger_error_message(
driver, "Tour Error: {'%s'} was not found!" % selector, msg_dur
)
raise Exception(
"Tour Error: {'%s'} was not found! "
"Exiting due to failure on first tour step!"
"" % selector
)
driver.execute_script(instructions)
tour_on = True
if autoplay:
start_ms = time.time() * 1000.0
stop_ms = start_ms + (interval * 1000.0)
latest_step = 0
while tour_on:
try:
time.sleep(0.01)
if browser != "firefox":
result = driver.execute_script("return $tour._currentStep")
else:
page_actions.wait_for_element_present(
driver, ".introjs-tooltip", by="css selector", timeout=0.4
)
result = True
except Exception:
tour_on = False
result = None
if result is not None:
tour_on = True
if autoplay:
try:
current_step = driver.execute_script(
"return $tour._currentStep"
)
except Exception:
continue
if current_step != latest_step:
latest_step = current_step
start_ms = time.time() * 1000.0
stop_ms = start_ms + (interval * 1000.0)
now_ms = time.time() * 1000.0
if now_ms >= stop_ms:
if current_step == latest_step:
try:
driver.execute_script("$tour.nextStep()")
except Exception:
driver.execute_script("$tour.exit()")
try:
latest_step = driver.execute_script(
"return $tour._currentStep"
)
start_ms = time.time() * 1000.0
stop_ms = start_ms + (interval * 1000.0)
except Exception:
pass
continue
else:
try:
time.sleep(0.01)
if browser != "firefox":
result = driver.execute_script("return $tour._currentStep")
else:
page_actions.wait_for_element_present(
driver,
".introjs-tooltip",
by="css selector",
timeout=0.4,
)
result = True
if result is not None:
time.sleep(0.1)
continue
else:
return
except Exception:
tour_on = False
time.sleep(0.1)
def export_tour(tour_steps, name=None, filename="my_tour.js", url=None):
"""Exports a tour as a JS file.
It will include necessary resources as well, such as jQuery.
You'll be able to copy the tour directly into the Console of
any web browser to play the tour outside of SeleniumBase runs."""
if not name:
name = "default"
if name not in tour_steps:
raise Exception("Tour {%s} does not exist!" % name)
if not filename.endswith(".js"):
raise Exception('Tour file must end in ".js"!')
if not url:
url = "data:,"
tour_type = None
if "Bootstrap" in tour_steps[name][0]:
tour_type = "bootstrap"
elif "DriverJS" in tour_steps[name][0]:
tour_type = "driverjs"
elif "Hopscotch" in tour_steps[name][0]:
tour_type = "hopscotch"
elif "IntroJS" in tour_steps[name][0]:
tour_type = "introjs"
elif "Shepherd" in tour_steps[name][0]:
tour_type = "shepherd"
else:
raise Exception("Unknown tour type!")
instructions = (
"""//////// Load Tour Start Page (if not there now) ////////\n\n"""
"""if (window.location.href != "%s") {\n"""
""" window.location.href="%s";\n"""
"""}\n\n"""
"""//////// Resources ////////\n\n"""
"""function injectCSS(css_link) {"""
"""var head = document.getElementsByTagName("head")[0];"""
"""var link = document.createElement("link");"""
"""link.rel = "stylesheet";"""
"""link.type = "text/css";"""
"""link.href = css_link;"""
"""link.crossorigin = "anonymous";"""
"""head.appendChild(link);"""
"""};\n"""
"""function injectJS(js_link) {"""
"""var head = document.getElementsByTagName("head")[0];"""
"""var script = document.createElement("script");"""
"""script.src = js_link;"""
"""script.defer;"""
"""script.type="text/javascript";"""
"""script.crossorigin = "anonymous";"""
"""script.onload = function() { null };"""
"""head.appendChild(script);"""
"""};\n"""
"""function injectStyle(css) {"""
"""var head = document.getElementsByTagName("head")[0];"""
"""var style = document.createElement("style");"""
"""style.type = "text/css";"""
"""style.appendChild(document.createTextNode(css));"""
"""head.appendChild(style);"""
"""};\n""" % (url, url)
)
if tour_type == "bootstrap":
jquery_js = constants.JQuery.MIN_JS
bootstrap_tour_css = constants.BootstrapTour.MIN_CSS
bootstrap_tour_js = constants.BootstrapTour.MIN_JS
backdrop_style = style_sheet.get_bt_backdrop_style()
backdrop_style = backdrop_style.replace("\n", "")
backdrop_style = js_utils.escape_quotes_if_needed(backdrop_style)
instructions += 'injectJS("%s");\n' % jquery_js
instructions += "\n"
instructions += "function loadResources() { "
instructions += 'if ( typeof jQuery !== "undefined" ) {\n'
instructions += 'injectCSS("%s");\n' % bootstrap_tour_css
instructions += 'injectStyle("%s");\n' % backdrop_style
instructions += 'injectJS("%s");' % bootstrap_tour_js
instructions += '} else { window.setTimeout("loadResources();",100); '
instructions += "} }\n"
instructions += "loadResources()"
elif tour_type == "driverjs":
driverjs_css = constants.DriverJS.MIN_CSS
driverjs_js = constants.DriverJS.MIN_JS
backdrop_style = style_sheet.get_dt_backdrop_style()
backdrop_style = backdrop_style.replace("\n", "")
backdrop_style = js_utils.escape_quotes_if_needed(backdrop_style)
instructions += 'injectCSS("%s");\n' % driverjs_css
instructions += 'injectStyle("%s");\n' % backdrop_style
instructions += 'injectJS("%s");' % driverjs_js
elif tour_type == "hopscotch":
hopscotch_css = constants.Hopscotch.MIN_CSS
hopscotch_js = constants.Hopscotch.MIN_JS
backdrop_style = style_sheet.get_hops_backdrop_style()
backdrop_style = backdrop_style.replace("\n", "")
backdrop_style = js_utils.escape_quotes_if_needed(backdrop_style)
instructions += 'injectCSS("%s");\n' % hopscotch_css
instructions += 'injectStyle("%s");\n' % backdrop_style
instructions += 'injectJS("%s");' % hopscotch_js
elif tour_type == "introjs":
intro_css = constants.IntroJS.MIN_CSS
intro_js = constants.IntroJS.MIN_JS
theme_color = sb_config.introjs_theme_color
hover_color = sb_config.introjs_hover_color
backdrop_style = style_sheet.get_introjs_style() % (
theme_color,
hover_color,
hover_color,
hover_color,
theme_color,
)
backdrop_style = backdrop_style.replace("\n", "")
backdrop_style = js_utils.escape_quotes_if_needed(backdrop_style)
instructions += 'injectCSS("%s");\n' % intro_css
instructions += 'injectStyle("%s");\n' % backdrop_style
instructions += 'injectJS("%s");' % intro_js
elif tour_type == "shepherd":
jquery_js = constants.JQuery.MIN_JS
shepherd_js = constants.Shepherd.MIN_JS
sh_theme_arrows_css = constants.Shepherd.THEME_ARROWS_CSS
sh_theme_arrows_fix_css = constants.Shepherd.THEME_ARR_FIX_CSS
sh_theme_default_css = constants.Shepherd.THEME_DEFAULT_CSS
sh_theme_dark_css = constants.Shepherd.THEME_DARK_CSS
sh_theme_sq_css = constants.Shepherd.THEME_SQ_CSS
sh_theme_sq_dark_css = constants.Shepherd.THEME_SQ_DK_CSS
tether_js = constants.Tether.MIN_JS
spinner_css = constants.Messenger.SPINNER_CSS
backdrop_style = style_sheet.get_sh_backdrop_style()
backdrop_style = backdrop_style.replace("\n", "")
backdrop_style = js_utils.escape_quotes_if_needed(backdrop_style)
instructions += 'injectCSS("%s");\n' % spinner_css
instructions += 'injectJS("%s");\n' % jquery_js
instructions += 'injectJS("%s");\n' % tether_js
instructions += "\n"
instructions += "function loadResources() { "
instructions += 'if ( typeof jQuery !== "undefined" ) {\n'
instructions += 'injectCSS("%s");' % sh_theme_arrows_css
instructions += 'injectCSS("%s");' % sh_theme_arrows_fix_css
instructions += 'injectCSS("%s");' % sh_theme_default_css
instructions += 'injectCSS("%s");' % sh_theme_dark_css
instructions += 'injectCSS("%s");' % sh_theme_sq_css
instructions += 'injectCSS("%s");\n' % sh_theme_sq_dark_css
instructions += 'injectStyle("%s");\n' % backdrop_style
instructions += 'injectJS("%s");\n' % shepherd_js
instructions += '} else { window.setTimeout("loadResources();",100); '
instructions += "} }\n"
instructions += "loadResources()"
instructions += "\n\n//////// Tour Code ////////\n\n"
first_instructions = instructions
instructions = " "
if tour_type == "bootstrap":
instructions += "function loadTour() { "
instructions += 'if ( typeof Tour !== "undefined" ) {\n'
elif tour_type == "driverjs":
instructions += "function loadTour() { "
instructions += 'if ( typeof Driver !== "undefined" ) {\n'
elif tour_type == "hopscotch":
instructions += "function loadTour() { "
instructions += 'if ( typeof hopscotch !== "undefined" ) {\n'
elif tour_type == "introjs":
instructions += "function loadTour() { "
instructions += 'if ( typeof introJs !== "undefined" ) {\n'
elif tour_type == "shepherd":
instructions += "function loadTour() { "
instructions += 'if ( typeof Shepherd !== "undefined" ) {\n'
for tour_step in tour_steps[name]:
instructions += tour_step
if tour_type == "bootstrap":
instructions += """]);
// Initialize the tour
tour.init();
// Start the tour
tour.start();
$tour = tour;
$tour.restart();\n"""
elif tour_type == "driverjs":
instructions += """]
);
// Start the tour!
tour.start();
$tour = tour;\n"""
elif tour_type == "hopscotch":
instructions += """]
};
// Start the tour!
hopscotch.startTour(tour);
$tour = hopscotch;\n"""
elif tour_type == "introjs":
instructions += """]
});
intro.setOption("disableInteraction", true);
intro.setOption("overlayOpacity", .29);
intro.setOption("scrollToElement", true);
intro.setOption("keyboardNavigation", true);
intro.setOption("exitOnEsc", true);
intro.setOption("hidePrev", true);
intro.setOption("nextToDone", true);
intro.setOption("exitOnOverlayClick", false);
intro.setOption("showStepNumbers", false);
intro.setOption("showProgress", false);
intro.start();
$tour = intro;
};
startIntro();\n"""
elif tour_type == "shepherd":
instructions += """
tour.start();
$tour = tour;\n"""
else:
pass
instructions = textwrap.dedent(instructions)
instructions = first_instructions + instructions
instructions += '\n} else { window.setTimeout("loadTour();",100); } '
instructions += "}\n"
instructions += "loadTour()\n"
exported_tours_folder = EXPORTED_TOURS_FOLDER
if exported_tours_folder.endswith("/"):
exported_tours_folder = exported_tours_folder[:-1]
if not os.path.exists(exported_tours_folder):
try:
os.makedirs(exported_tours_folder)
except Exception:
pass
import codecs
file_path = exported_tours_folder + "/" + filename
out_file = codecs.open(file_path, "w+", encoding="utf-8")
out_file.writelines(instructions)
out_file.close()
print("\n>>> [%s] was saved!\n" % file_path)