Merge lp:~openlp-dev/openlp/webengine-migrate into lp:openlp
- webengine-migrate
- Merge into trunk
Proposed by
Tomas Groth
Status: | Superseded |
---|---|
Proposed branch: | lp:~openlp-dev/openlp/webengine-migrate |
Merge into: | lp:openlp |
Diff against target: |
33116 lines (+15169/-5298) 370 files modified
.bzrignore (+7/-0) karma.conf.js (+77/-0) nose2.cfg (+8/-8) openlp/.version (+1/-1) openlp/core/api/deploy.py (+1/-1) openlp/core/api/endpoint/controller.py (+8/-6) openlp/core/api/endpoint/core.py (+2/-2) openlp/core/api/endpoint/remote.py (+1/-0) openlp/core/api/endpoint/service.py (+1/-0) openlp/core/api/http/server.py (+6/-7) openlp/core/api/http/wsgiapp.py (+1/-0) openlp/core/api/tab.py (+4/-3) openlp/core/api/websockets.py (+1/-0) openlp/core/app.py (+10/-7) openlp/core/common/actions.py (+1/-1) openlp/core/common/applocation.py (+2/-1) openlp/core/common/db.py (+1/-0) openlp/core/common/httputils.py (+1/-0) openlp/core/common/i18n.py (+2/-1) openlp/core/common/mixins.py (+1/-0) openlp/core/common/path.py (+1/-0) openlp/core/common/registry.py (+2/-0) openlp/core/common/settings.py (+41/-4) openlp/core/display/html/black.css (+292/-0) openlp/core/display/html/display.html (+39/-0) openlp/core/display/html/display.js (+789/-0) openlp/core/display/html/reveal.css (+1591/-0) openlp/core/display/html/reveal.js (+5586/-0) openlp/core/display/html/textFit.js (+237/-0) openlp/core/display/render.py (+738/-0) openlp/core/display/renderer.py (+0/-586) openlp/core/display/screens.py (+283/-181) openlp/core/display/webengine.py (+93/-0) openlp/core/display/window.py (+404/-0) openlp/core/lib/__init__.py (+97/-307) openlp/core/lib/db.py (+4/-3) openlp/core/lib/htmlbuilder.py (+9/-7) openlp/core/lib/imagemanager.py (+6/-5) openlp/core/lib/mediamanageritem.py (+6/-5) openlp/core/lib/plugin.py (+1/-0) openlp/core/lib/pluginmanager.py (+2/-0) openlp/core/lib/serviceitem.py (+105/-191) openlp/core/lib/settingstab.py (+4/-4) openlp/core/lib/theme.py (+9/-7) openlp/core/lib/ui.py (+1/-0) openlp/core/loader.py (+1/-1) openlp/core/projectors/constants.py (+1/-0) openlp/core/projectors/db.py (+7/-3) openlp/core/projectors/editform.py (+6/-5) openlp/core/projectors/manager.py (+6/-5) openlp/core/projectors/pjlink.py (+6/-5) openlp/core/projectors/sourceselectform.py (+2/-1) openlp/core/projectors/tab.py (+5/-4) openlp/core/projectors/upgrade.py (+2/-1) openlp/core/resources.py (+1/-1) openlp/core/server.py (+1/-1) openlp/core/ui/aboutform.py (+1/-0) openlp/core/ui/advancedtab.py (+5/-4) openlp/core/ui/exceptiondialog.py (+4/-4) openlp/core/ui/exceptionform.py (+7/-46) openlp/core/ui/filerenamedialog.py (+3/-3) openlp/core/ui/filerenameform.py (+1/-1) openlp/core/ui/firsttimeform.py (+42/-39) openlp/core/ui/firsttimelanguagedialog.py (+3/-3) openlp/core/ui/firsttimelanguageform.py (+2/-1) openlp/core/ui/firsttimewizard.py (+29/-32) openlp/core/ui/formattingtagdialog.py (+4/-4) openlp/core/ui/formattingtagform.py (+1/-1) openlp/core/ui/generaltab.py (+8/-144) openlp/core/ui/icons.py (+2/-1) openlp/core/ui/maindisplay.py (+0/-602) openlp/core/ui/mainwindow.py (+20/-27) openlp/core/ui/media/endpoint.py (+1/-0) openlp/core/ui/media/mediacontroller.py (+5/-4) openlp/core/ui/media/playertab.py (+4/-4) openlp/core/ui/media/systemplayer.py (+2/-1) openlp/core/ui/media/vendor/vlc.py (+1197/-892) openlp/core/ui/media/vlcplayer.py (+2/-1) openlp/core/ui/media/webkitplayer.py (+0/-312) openlp/core/ui/plugindialog.py (+3/-3) openlp/core/ui/pluginform.py (+2/-1) openlp/core/ui/printservicedialog.py (+4/-4) openlp/core/ui/printserviceform.py (+3/-2) openlp/core/ui/screenstab.py (+97/-0) openlp/core/ui/serviceitemeditdialog.py (+4/-4) openlp/core/ui/serviceitemeditform.py (+3/-3) openlp/core/ui/servicemanager.py (+20/-16) openlp/core/ui/servicenoteform.py (+4/-4) openlp/core/ui/settingsdialog.py (+3/-3) openlp/core/ui/settingsform.py (+21/-13) openlp/core/ui/shortcutlistdialog.py (+3/-3) openlp/core/ui/shortcutlistform.py (+2/-1) openlp/core/ui/slidecontroller.py (+165/-167) openlp/core/ui/splashscreen.py (+2/-2) openlp/core/ui/starttimedialog.py (+3/-3) openlp/core/ui/starttimeform.py (+1/-1) openlp/core/ui/style.py (+1/-0) openlp/core/ui/themeform.py (+14/-8) openlp/core/ui/themelayoutdialog.py (+3/-3) openlp/core/ui/themelayoutform.py (+1/-1) openlp/core/ui/thememanager.py (+10/-10) openlp/core/ui/themestab.py (+7/-7) openlp/core/ui/themewizard.py (+4/-4) openlp/core/version.py (+54/-2) openlp/core/widgets/docks.py (+2/-1) openlp/core/widgets/edits.py (+2/-1) openlp/core/widgets/layouts.py (+185/-0) openlp/core/widgets/toolbar.py (+1/-0) openlp/core/widgets/views.py (+40/-38) openlp/core/widgets/widgets.py (+267/-1) openlp/core/widgets/wizard.py (+5/-4) openlp/plugins/alerts/alertsplugin.py (+3/-2) openlp/plugins/alerts/endpoint.py (+1/-0) openlp/plugins/alerts/forms/__init__.py (+1/-1) openlp/plugins/alerts/forms/alertdialog.py (+4/-4) openlp/plugins/alerts/forms/alertform.py (+2/-1) openlp/plugins/alerts/lib/alertsmanager.py (+5/-4) openlp/plugins/alerts/lib/alertstab.py (+3/-3) openlp/plugins/bibles/bibleplugin.py (+1/-0) openlp/plugins/bibles/endpoint.py (+2/-1) openlp/plugins/bibles/forms/bibleimportform.py (+7/-6) openlp/plugins/bibles/forms/booknamedialog.py (+3/-3) openlp/plugins/bibles/forms/booknameform.py (+2/-1) openlp/plugins/bibles/forms/editbibledialog.py (+5/-5) openlp/plugins/bibles/forms/editbibleform.py (+3/-1) openlp/plugins/bibles/forms/languagedialog.py (+3/-3) openlp/plugins/bibles/forms/languageform.py (+2/-1) openlp/plugins/bibles/lib/biblestab.py (+6/-5) openlp/plugins/bibles/lib/db.py (+4/-3) openlp/plugins/bibles/lib/importers/csvbible.py (+1/-0) openlp/plugins/bibles/lib/importers/http.py (+1/-0) openlp/plugins/bibles/lib/importers/osis.py (+1/-0) openlp/plugins/bibles/lib/importers/sword.py (+1/-0) openlp/plugins/bibles/lib/importers/wordproject.py (+2/-1) openlp/plugins/bibles/lib/importers/zefania.py (+1/-0) openlp/plugins/bibles/lib/manager.py (+2/-0) openlp/plugins/bibles/lib/mediaitem.py (+7/-7) openlp/plugins/bibles/lib/upgrade.py (+1/-0) openlp/plugins/custom/customplugin.py (+3/-2) openlp/plugins/custom/endpoint.py (+2/-1) openlp/plugins/custom/forms/editcustomdialog.py (+4/-4) openlp/plugins/custom/forms/editcustomform.py (+1/-1) openlp/plugins/custom/forms/editcustomslidedialog.py (+3/-3) openlp/plugins/custom/forms/editcustomslideform.py (+2/-1) openlp/plugins/custom/lib/customtab.py (+3/-3) openlp/plugins/custom/lib/customxmlhandler.py (+1/-0) openlp/plugins/custom/lib/mediaitem.py (+5/-4) openlp/plugins/images/endpoint.py (+2/-1) openlp/plugins/images/forms/__init__.py (+1/-1) openlp/plugins/images/forms/addgroupdialog.py (+3/-3) openlp/plugins/images/forms/addgroupform.py (+1/-1) openlp/plugins/images/forms/choosegroupdialog.py (+3/-3) openlp/plugins/images/forms/choosegroupform.py (+1/-1) openlp/plugins/images/imageplugin.py (+3/-2) openlp/plugins/images/lib/imagetab.py (+3/-3) openlp/plugins/images/lib/mediaitem.py (+5/-5) openlp/plugins/images/lib/upgrade.py (+1/-0) openlp/plugins/media/endpoint.py (+2/-1) openlp/plugins/media/forms/mediaclipselectordialog.py (+3/-3) openlp/plugins/media/forms/mediaclipselectorform.py (+3/-2) openlp/plugins/media/lib/mediaitem.py (+4/-3) openlp/plugins/media/lib/mediatab.py (+3/-3) openlp/plugins/media/mediaplugin.py (+3/-0) openlp/plugins/presentations/endpoint.py (+2/-1) openlp/plugins/presentations/lib/impresscontroller.py (+4/-3) openlp/plugins/presentations/lib/mediaitem.py (+5/-5) openlp/plugins/presentations/lib/messagelistener.py (+1/-0) openlp/plugins/presentations/lib/pdfcontroller.py (+3/-2) openlp/plugins/presentations/lib/powerpointcontroller.py (+21/-10) openlp/plugins/presentations/lib/presentationcontroller.py (+1/-0) openlp/plugins/presentations/lib/presentationtab.py (+3/-3) openlp/plugins/presentations/presentationplugin.py (+2/-1) openlp/plugins/songs/endpoint.py (+2/-1) openlp/plugins/songs/forms/__init__.py (+1/-1) openlp/plugins/songs/forms/authorsdialog.py (+3/-3) openlp/plugins/songs/forms/authorsform.py (+1/-1) openlp/plugins/songs/forms/duplicatesongremovalform.py (+2/-1) openlp/plugins/songs/forms/editsongdialog.py (+4/-4) openlp/plugins/songs/forms/editsongform.py (+6/-5) openlp/plugins/songs/forms/editversedialog.py (+3/-3) openlp/plugins/songs/forms/editverseform.py (+2/-1) openlp/plugins/songs/forms/mediafilesdialog.py (+3/-3) openlp/plugins/songs/forms/mediafilesform.py (+2/-1) openlp/plugins/songs/forms/songbookdialog.py (+3/-3) openlp/plugins/songs/forms/songbookform.py (+1/-1) openlp/plugins/songs/forms/songexportform.py (+4/-3) openlp/plugins/songs/forms/songimportform.py (+4/-3) openlp/plugins/songs/forms/songmaintenancedialog.py (+3/-3) openlp/plugins/songs/forms/songmaintenanceform.py (+5/-3) openlp/plugins/songs/forms/songreviewwidget.py (+4/-4) openlp/plugins/songs/forms/songselectform.py (+1/-0) openlp/plugins/songs/forms/topicsdialog.py (+3/-3) openlp/plugins/songs/forms/topicsform.py (+1/-1) openlp/plugins/songs/lib/__init__.py (+2/-2) openlp/plugins/songs/lib/db.py (+2/-2) openlp/plugins/songs/lib/importer.py (+2/-0) openlp/plugins/songs/lib/importers/cclifile.py (+2/-0) openlp/plugins/songs/lib/importers/chordpro.py (+1/-0) openlp/plugins/songs/lib/importers/dreambeam.py (+1/-0) openlp/plugins/songs/lib/importers/easyslides.py (+1/-0) openlp/plugins/songs/lib/importers/easyworship.py (+3/-2) openlp/plugins/songs/lib/importers/foilpresenter.py (+2/-1) openlp/plugins/songs/lib/importers/lyrix.py (+1/-0) openlp/plugins/songs/lib/importers/mediashout.py (+1/-0) openlp/plugins/songs/lib/importers/openlp.py (+4/-2) openlp/plugins/songs/lib/importers/openlyrics.py (+1/-0) openlp/plugins/songs/lib/importers/openoffice.py (+2/-0) openlp/plugins/songs/lib/importers/opensong.py (+1/-0) openlp/plugins/songs/lib/importers/opspro.py (+1/-0) openlp/plugins/songs/lib/importers/powersong.py (+1/-0) openlp/plugins/songs/lib/importers/presentationmanager.py (+1/-1) openlp/plugins/songs/lib/importers/propresenter.py (+1/-0) openlp/plugins/songs/lib/importers/songbeamer.py (+2/-1) openlp/plugins/songs/lib/importers/songimport.py (+3/-2) openlp/plugins/songs/lib/importers/songshowplus.py (+1/-0) openlp/plugins/songs/lib/importers/songsoffellowship.py (+2/-0) openlp/plugins/songs/lib/importers/sundayplus.py (+2/-2) openlp/plugins/songs/lib/importers/videopsalm.py (+1/-0) openlp/plugins/songs/lib/importers/wordsofworship.py (+1/-0) openlp/plugins/songs/lib/importers/worshipassistant.py (+1/-0) openlp/plugins/songs/lib/importers/worshipcenterpro.py (+1/-0) openlp/plugins/songs/lib/importers/zionworx.py (+1/-0) openlp/plugins/songs/lib/mediaitem.py (+5/-4) openlp/plugins/songs/lib/openlyricsexport.py (+1/-0) openlp/plugins/songs/lib/openlyricsxml.py (+1/-0) openlp/plugins/songs/lib/songselect.py (+1/-0) openlp/plugins/songs/lib/songstab.py (+3/-3) openlp/plugins/songs/lib/upgrade.py (+3/-2) openlp/plugins/songs/reporting.py (+1/-0) openlp/plugins/songs/songsplugin.py (+5/-5) openlp/plugins/songusage/forms/songusagedeletedialog.py (+3/-3) openlp/plugins/songusage/forms/songusagedeleteform.py (+1/-1) openlp/plugins/songusage/forms/songusagedetaildialog.py (+3/-3) openlp/plugins/songusage/forms/songusagedetailform.py (+3/-1) openlp/plugins/songusage/lib/upgrade.py (+2/-1) openlp/plugins/songusage/songusageplugin.py (+3/-2) package.json (+25/-0) run_openlp.py (+3/-1) scripts/appveyor-webhook.py (+5/-4) scripts/appveyor.yml (+4/-10) scripts/check_dependencies.py (+1/-2) scripts/clean_up_resources.py (+1/-0) scripts/jenkins_script.py (+2/-1) scripts/lp-merge.py (+5/-4) scripts/mp_update.py (+3/-1) scripts/reveal-js.patch (+25/-0) scripts/translation_utils.py (+3/-3) scripts/websocket_client.py (+2/-1) setup.cfg (+1/-2) setup.py (+2/-1) tests/functional/openlp_core/api/endpoint/test_controller.py (+35/-13) tests/functional/openlp_core/api/endpoint/test_remote.py (+1/-1) tests/functional/openlp_core/api/http/test_init.py (+1/-2) tests/functional/openlp_core/api/http/test_wsgiapp.py (+1/-0) tests/functional/openlp_core/api/test_deploy.py (+7/-4) tests/functional/openlp_core/api/test_tab.py (+1/-0) tests/functional/openlp_core/api/test_websockets.py (+1/-0) tests/functional/openlp_core/common/test_actions.py (+123/-128) tests/functional/openlp_core/common/test_applocation.py (+1/-0) tests/functional/openlp_core/common/test_common.py (+2/-2) tests/functional/openlp_core/common/test_db.py (+1/-1) tests/functional/openlp_core/common/test_path.py (+2/-2) tests/functional/openlp_core/display/test_render.py (+210/-0) tests/functional/openlp_core/display/test_renderer.py (+0/-208) tests/functional/openlp_core/display/test_screens.py (+66/-18) tests/functional/openlp_core/lib/test_db.py (+2/-2) tests/functional/openlp_core/lib/test_formattingtags.py (+1/-0) tests/functional/openlp_core/lib/test_htmlbuilder.py (+4/-13) tests/functional/openlp_core/lib/test_image_manager.py (+2/-1) tests/functional/openlp_core/lib/test_lib.py (+3/-177) tests/functional/openlp_core/lib/test_serviceitem.py (+35/-55) tests/functional/openlp_core/lib/test_ui.py (+4/-4) tests/functional/openlp_core/test_app.py (+3/-0) tests/functional/openlp_core/test_server.py (+6/-5) tests/functional/openlp_core/test_threading.py (+1/-1) tests/functional/openlp_core/ui/media/test_systemplayer.py (+1/-1) tests/functional/openlp_core/ui/media/test_vlcplayer.py (+1/-1) tests/functional/openlp_core/ui/media/test_webkitplayer.py (+0/-66) tests/functional/openlp_core/ui/test_exceptionform.py (+42/-56) tests/functional/openlp_core/ui/test_firsttimeform.py (+63/-38) tests/functional/openlp_core/ui/test_formattingtagsform.py (+1/-1) tests/functional/openlp_core/ui/test_icons.py (+0/-1) tests/functional/openlp_core/ui/test_maindisplay.py (+0/-283) tests/functional/openlp_core/ui/test_mainwindow.py (+23/-14) tests/functional/openlp_core/ui/test_servicemanager.py (+15/-12) tests/functional/openlp_core/ui/test_slidecontroller.py (+17/-21) tests/functional/openlp_core/widgets/test_views.py (+15/-16) tests/functional/openlp_core/widgets/test_widgets.py (+199/-0) tests/functional/openlp_plugins/bibles/test_bibleimport.py (+1/-1) tests/functional/openlp_plugins/bibles/test_bibleserver.py (+1/-1) tests/functional/openlp_plugins/bibles/test_csvimport.py (+1/-0) tests/functional/openlp_plugins/bibles/test_mediaitem.py (+2/-2) tests/functional/openlp_plugins/bibles/test_opensongimport.py (+2/-1) tests/functional/openlp_plugins/bibles/test_osisimport.py (+1/-0) tests/functional/openlp_plugins/bibles/test_swordimport.py (+5/-3) tests/functional/openlp_plugins/bibles/test_wordprojectimport.py (+2/-1) tests/functional/openlp_plugins/bibles/test_zefaniaimport.py (+1/-0) tests/functional/openlp_plugins/custom/test_mediaitem.py (+2/-1) tests/functional/openlp_plugins/images/test_imagetab.py (+1/-0) tests/functional/openlp_plugins/images/test_upgrade.py (+1/-0) tests/functional/openlp_plugins/media/test_mediaitem.py (+1/-0) tests/functional/openlp_plugins/presentations/test_impresscontroller.py (+3/-3) tests/functional/openlp_plugins/presentations/test_mediaitem.py (+1/-1) tests/functional/openlp_plugins/presentations/test_messagelistener.py (+1/-1) tests/functional/openlp_plugins/presentations/test_pdfcontroller.py (+5/-5) tests/functional/openlp_plugins/presentations/test_powerpointcontroller.py (+3/-2) tests/functional/openlp_plugins/presentations/test_pptviewcontroller.py.THIS (+224/-0) tests/functional/openlp_plugins/presentations/test_presentationcontroller.py (+1/-0) tests/functional/openlp_plugins/songs/test_chordproimport.py (+2/-1) tests/functional/openlp_plugins/songs/test_db.py (+1/-1) tests/functional/openlp_plugins/songs/test_easyslidesimport.py (+1/-0) tests/functional/openlp_plugins/songs/test_editsongform.py (+1/-1) tests/functional/openlp_plugins/songs/test_editverseform.py (+1/-0) tests/functional/openlp_plugins/songs/test_ewimport.py (+1/-0) tests/functional/openlp_plugins/songs/test_foilpresenterimport.py (+1/-1) tests/functional/openlp_plugins/songs/test_lib.py (+2/-2) tests/functional/openlp_plugins/songs/test_lyriximport.py (+1/-0) tests/functional/openlp_plugins/songs/test_mediashout.py (+2/-1) tests/functional/openlp_plugins/songs/test_openlpimporter.py (+1/-1) tests/functional/openlp_plugins/songs/test_openlyricsimport.py (+1/-0) tests/functional/openlp_plugins/songs/test_openoffice.py (+1/-0) tests/functional/openlp_plugins/songs/test_opensongimport.py (+2/-1) tests/functional/openlp_plugins/songs/test_opsproimport.py (+5/-3) tests/functional/openlp_plugins/songs/test_powerpraiseimport.py (+1/-0) tests/functional/openlp_plugins/songs/test_presentationmanagerimport.py (+1/-0) tests/functional/openlp_plugins/songs/test_propresenterimport.py (+1/-0) tests/functional/openlp_plugins/songs/test_songbeamerimport.py (+1/-0) tests/functional/openlp_plugins/songs/test_songproimport.py (+1/-0) tests/functional/openlp_plugins/songs/test_songselect.py (+4/-3) tests/functional/openlp_plugins/songs/test_songshowplusimport.py (+2/-1) tests/functional/openlp_plugins/songs/test_sundayplusimport.py (+1/-0) tests/functional/openlp_plugins/songs/test_videopsalm.py (+2/-1) tests/functional/openlp_plugins/songs/test_wordsofworshipimport.py (+1/-0) tests/functional/openlp_plugins/songs/test_worshipassistantimport.py (+1/-0) tests/functional/openlp_plugins/songs/test_worshipcenterproimport.py (+3/-2) tests/functional/openlp_plugins/songs/test_zionworximport.py (+1/-0) tests/helpers/songfileimport.py (+2/-1) tests/interfaces/openlp_core/common/test_utils.py (+0/-1) tests/interfaces/openlp_core/ui/test_servicemanager.py (+3/-3) tests/interfaces/openlp_core/ui/test_settings_form.py (+1/-0) tests/interfaces/openlp_core/ui/test_thememanager.py (+1/-1) tests/interfaces/openlp_core/widgets/test_edits.py (+1/-1) tests/interfaces/openlp_core/widgets/test_views.py (+5/-0) tests/interfaces/openlp_plugins/bibles/test_lib_http.py (+1/-1) tests/interfaces/openlp_plugins/custom/forms/test_customform.py (+1/-1) tests/interfaces/openlp_plugins/media/forms/test_mediaclipselectorform.py (+9/-7) tests/interfaces/openlp_plugins/songs/forms/test_editsongform.py (+1/-0) tests/interfaces/openlp_plugins/songs/forms/test_editverseform.py (+1/-0) tests/interfaces/openlp_plugins/songs/forms/test_songmaintenanceform.py (+1/-1) tests/js/fake_webchannel.js (+5/-0) tests/js/polyfill.js (+84/-0) tests/js/test_display.js (+632/-0) tests/openlp_core/common/test_network_interfaces.py (+0/-1) tests/openlp_core/projectors/test_projector_bugfixes_01.py (+1/-0) tests/openlp_core/projectors/test_projector_constants.py (+1/-0) tests/openlp_core/projectors/test_projector_db.py (+1/-1) tests/openlp_core/projectors/test_projector_editform.py (+1/-1) tests/openlp_core/projectors/test_projector_pjlink_base_01.py (+3/-5) tests/openlp_core/projectors/test_projector_pjlink_base_02.py (+0/-1) tests/openlp_core/projectors/test_projector_pjlink_cmd_routing.py (+2/-3) tests/openlp_core/projectors/test_projector_pjlink_commands_01.py (+2/-12) tests/openlp_core/projectors/test_projector_pjlink_commands_02.py (+2/-2) tests/openlp_core/projectors/test_projector_pjlink_udp.py (+1/-1) tests/openlp_core/projectors/test_projector_sourceform.py (+3/-3) tests/openlp_core/projectors/test_projector_utilities.py (+3/-2) tests/openlp_core/projectors/test_projectormanager.py (+1/-1) tests/utils/__init__.py (+7/-10) tests/utils/constants.py (+1/-0) tests/utils/test_bzr_tags.py (+2/-1) tests/utils/test_pylint.py (+4/-2) |
To merge this branch: | bzr merge lp:~openlp-dev/openlp/webengine-migrate |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
OpenLP Core | Pending | ||
Review via email: mp+363088@code.launchpad.net |
This proposal supersedes a proposal from 2019-02-12.
This proposal has been superseded by a proposal from 2019-02-12.
Commit message
Migration from WebKit to Webengine. Also introduced reveal.js for slide rendering, new screen setup dialogs and many other changes.
Description of the change
To post a comment you must log in.
Revision history for this message
Raoul Snyman (raoul-snyman) wrote : Posted in a previous version of this proposal | # |
Revision history for this message
Raoul Snyman (raoul-snyman) wrote : Posted in a previous version of this proposal | # |
Linux tests failed, please see https:/
Revision history for this message
Raoul Snyman (raoul-snyman) wrote : | # |
Linux tests failed, please see https:/
- 2878. By Tim Bentley
-
fix up tests
- 2879. By Tomas Groth
-
Fix more tests
- 2880. By Tomas Groth
-
pep8 fixes
- 2881. By Tomas Groth
-
More pep8 fixes
- 2882. By Tomas Groth
-
Even more pep8 fixes and removed the old htmlbuilder.
- 2883. By Raoul Snyman
-
Fix an unused import and some incorrect patch()s
- 2884. By Raoul Snyman
-
HEAD
- 2885. By Tomas Groth
-
trunk
Unmerged revisions
- 2885. By Tomas Groth
-
trunk
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file '.bzrignore' | |||
2 | --- .bzrignore 2018-06-26 17:10:34 +0000 | |||
3 | +++ .bzrignore 2019-02-12 20:56:20 +0000 | |||
4 | @@ -45,4 +45,11 @@ | |||
5 | 45 | resources/windows/warnOpenLP.txt | 45 | resources/windows/warnOpenLP.txt |
6 | 46 | *.ropeproject | 46 | *.ropeproject |
7 | 47 | tags | 47 | tags |
8 | 48 | output | ||
9 | 49 | htmlcov | ||
10 | 50 | node_modules | ||
11 | 51 | openlp-test-projectordb.sqlite | ||
12 | 52 | package-lock.json | ||
13 | 53 | .cache | ||
14 | 54 | test | ||
15 | 48 | tests.kdev4 | 55 | tests.kdev4 |
16 | 49 | 56 | ||
17 | === added file 'karma.conf.js' | |||
18 | --- karma.conf.js 1970-01-01 00:00:00 +0000 | |||
19 | +++ karma.conf.js 2019-02-12 20:56:20 +0000 | |||
20 | @@ -0,0 +1,77 @@ | |||
21 | 1 | module.exports = function(config) { | ||
22 | 2 | config.set({ | ||
23 | 3 | // base path that will be used to resolve all patterns (eg. files, exclude) | ||
24 | 4 | basePath: "", | ||
25 | 5 | |||
26 | 6 | // frameworks to use | ||
27 | 7 | // available frameworks: https://npmjs.org/browse/keyword/karma-adapter | ||
28 | 8 | frameworks: ["jasmine"], | ||
29 | 9 | |||
30 | 10 | // list of files / patterns to load in the browser | ||
31 | 11 | files: [ | ||
32 | 12 | "tests/js/polyfill.js", | ||
33 | 13 | "tests/js/fake_webchannel.js", | ||
34 | 14 | "openlp/core/display/html/reveal.js", | ||
35 | 15 | "openlp/core/display/html/display.js", | ||
36 | 16 | "tests/js/test_*.js" | ||
37 | 17 | ], | ||
38 | 18 | |||
39 | 19 | // list of files to exclude | ||
40 | 20 | exclude: [ | ||
41 | 21 | ], | ||
42 | 22 | |||
43 | 23 | // preprocess matching files before serving them to the browser | ||
44 | 24 | // available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor | ||
45 | 25 | preprocessors: { | ||
46 | 26 | // source files, that you wanna generate coverage for | ||
47 | 27 | // do not include tests or libraries | ||
48 | 28 | // (these files will be instrumented by Istanbul) | ||
49 | 29 | "display.js": ["coverage"] | ||
50 | 30 | }, | ||
51 | 31 | |||
52 | 32 | // test results reporter to use | ||
53 | 33 | // possible values: "dots", "progress" | ||
54 | 34 | // available reporters: https://npmjs.org/browse/keyword/karma-reporter | ||
55 | 35 | reporters: ["progress", "coverage"], | ||
56 | 36 | |||
57 | 37 | // configure the coverateReporter | ||
58 | 38 | coverageReporter: { | ||
59 | 39 | type : "html", | ||
60 | 40 | dir : "htmlcov/" | ||
61 | 41 | }, | ||
62 | 42 | |||
63 | 43 | // web server port | ||
64 | 44 | port: 9876, | ||
65 | 45 | |||
66 | 46 | // enable / disable colors in the output (reporters and logs) | ||
67 | 47 | colors: true, | ||
68 | 48 | |||
69 | 49 | // level of logging | ||
70 | 50 | // possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG | ||
71 | 51 | logLevel: config.LOG_DEBUG, | ||
72 | 52 | |||
73 | 53 | // loggers | ||
74 | 54 | /* loggers: [ | ||
75 | 55 | {"type": "file", "filename": "karma.log"} | ||
76 | 56 | ],*/ | ||
77 | 57 | |||
78 | 58 | // enable / disable watching file and executing tests whenever any file changes | ||
79 | 59 | autoWatch: true, | ||
80 | 60 | |||
81 | 61 | // start these browsers | ||
82 | 62 | // available browser launchers: https://npmjs.org/browse/keyword/karma-launcher | ||
83 | 63 | browsers: ["PhantomJS"], | ||
84 | 64 | |||
85 | 65 | // Continuous Integration mode | ||
86 | 66 | // if true, Karma captures browsers, runs the tests and exits | ||
87 | 67 | singleRun: false, | ||
88 | 68 | |||
89 | 69 | // Concurrency level | ||
90 | 70 | // how many browser should be started simultaneous | ||
91 | 71 | concurrency: Infinity, | ||
92 | 72 | |||
93 | 73 | client: { | ||
94 | 74 | captureConsole: true | ||
95 | 75 | } | ||
96 | 76 | }) | ||
97 | 77 | } | ||
98 | 0 | 78 | ||
99 | === modified file 'nose2.cfg' | |||
100 | --- nose2.cfg 2017-11-16 05:03:19 +0000 | |||
101 | +++ nose2.cfg 2019-02-12 20:56:20 +0000 | |||
102 | @@ -1,5 +1,5 @@ | |||
103 | 1 | [unittest] | 1 | [unittest] |
105 | 2 | verbose = True | 2 | verbose = true |
106 | 3 | plugins = nose2.plugins.mp | 3 | plugins = nose2.plugins.mp |
107 | 4 | 4 | ||
108 | 5 | [log-capture] | 5 | [log-capture] |
109 | @@ -9,19 +9,19 @@ | |||
110 | 9 | log-level = ERROR | 9 | log-level = ERROR |
111 | 10 | 10 | ||
112 | 11 | [test-result] | 11 | [test-result] |
115 | 12 | always-on = True | 12 | always-on = true |
116 | 13 | descriptions = True | 13 | descriptions = true |
117 | 14 | 14 | ||
118 | 15 | [coverage] | 15 | [coverage] |
120 | 16 | always-on = True | 16 | always-on = true |
121 | 17 | coverage = openlp | 17 | coverage = openlp |
122 | 18 | coverage-report = html | 18 | coverage-report = html |
123 | 19 | 19 | ||
124 | 20 | [multiprocess] | 20 | [multiprocess] |
126 | 21 | always-on = False | 21 | always-on = false |
127 | 22 | processes = 4 | 22 | processes = 4 |
128 | 23 | 23 | ||
129 | 24 | [output-buffer] | 24 | [output-buffer] |
133 | 25 | always-on = True | 25 | always-on = true |
134 | 26 | stderr = True | 26 | stderr = true |
135 | 27 | stdout = False | 27 | stdout = true |
136 | 28 | 28 | ||
137 | === modified file 'openlp/.version' | |||
138 | --- openlp/.version 2019-01-11 20:23:24 +0000 | |||
139 | +++ openlp/.version 2019-02-12 20:56:20 +0000 | |||
140 | @@ -1,1 +1,1 @@ | |||
142 | 1 | 2.9.0 | 1 | 2.5.dev2856 |
143 | 2 | \ No newline at end of file | 2 | \ No newline at end of file |
144 | 3 | 3 | ||
145 | === modified file 'openlp/core/api/deploy.py' | |||
146 | --- openlp/core/api/deploy.py 2018-01-04 07:00:55 +0000 | |||
147 | +++ openlp/core/api/deploy.py 2019-02-12 20:56:20 +0000 | |||
148 | @@ -25,7 +25,7 @@ | |||
149 | 25 | from zipfile import ZipFile | 25 | from zipfile import ZipFile |
150 | 26 | 26 | ||
151 | 27 | from openlp.core.common.applocation import AppLocation | 27 | from openlp.core.common.applocation import AppLocation |
153 | 28 | from openlp.core.common.httputils import download_file, get_web_page, get_url_file_size | 28 | from openlp.core.common.httputils import download_file, get_url_file_size, get_web_page |
154 | 29 | from openlp.core.common.registry import Registry | 29 | from openlp.core.common.registry import Registry |
155 | 30 | 30 | ||
156 | 31 | 31 | ||
157 | 32 | 32 | ||
158 | === modified file 'openlp/core/api/endpoint/controller.py' | |||
159 | --- openlp/core/api/endpoint/controller.py 2018-08-25 14:08:19 +0000 | |||
160 | +++ openlp/core/api/endpoint/controller.py 2019-02-12 20:56:20 +0000 | |||
161 | @@ -34,6 +34,7 @@ | |||
162 | 34 | from openlp.core.lib import create_thumb | 34 | from openlp.core.lib import create_thumb |
163 | 35 | from openlp.core.lib.serviceitem import ItemCapabilities | 35 | from openlp.core.lib.serviceitem import ItemCapabilities |
164 | 36 | 36 | ||
165 | 37 | |||
166 | 37 | log = logging.getLogger(__name__) | 38 | log = logging.getLogger(__name__) |
167 | 38 | 39 | ||
168 | 39 | controller_endpoint = Endpoint('controller') | 40 | controller_endpoint = Endpoint('controller') |
169 | @@ -48,7 +49,7 @@ | |||
170 | 48 | 49 | ||
171 | 49 | :param request: the http request - not used | 50 | :param request: the http request - not used |
172 | 50 | """ | 51 | """ |
174 | 51 | log.debug("controller_text ") | 52 | log.debug('controller_text') |
175 | 52 | live_controller = Registry().get('live_controller') | 53 | live_controller = Registry().get('live_controller') |
176 | 53 | current_item = live_controller.service_item | 54 | current_item = live_controller.service_item |
177 | 54 | data = [] | 55 | data = [] |
178 | @@ -57,13 +58,14 @@ | |||
179 | 57 | item = {} | 58 | item = {} |
180 | 58 | # Handle text (songs, custom, bibles) | 59 | # Handle text (songs, custom, bibles) |
181 | 59 | if current_item.is_text(): | 60 | if current_item.is_text(): |
184 | 60 | if frame['verseTag']: | 61 | if frame['verse']: |
185 | 61 | item['tag'] = str(frame['verseTag']) | 62 | item['tag'] = str(frame['verse']) |
186 | 62 | else: | 63 | else: |
187 | 63 | item['tag'] = str(index + 1) | 64 | item['tag'] = str(index + 1) |
191 | 64 | item['chords_text'] = str(frame['chords_text']) | 65 | # TODO: Figure out rendering chords |
192 | 65 | item['text'] = str(frame['text']) | 66 | item['chords_text'] = str(frame.get('chords_text', '')) |
193 | 66 | item['html'] = str(frame['html']) | 67 | item['text'] = frame['text'] |
194 | 68 | item['html'] = current_item.get_rendered_frame(index) | ||
195 | 67 | # Handle images, unless a custom thumbnail is given or if thumbnails is disabled | 69 | # Handle images, unless a custom thumbnail is given or if thumbnails is disabled |
196 | 68 | elif current_item.is_image() and not frame.get('image', '') and Settings().value('api/thumbnails'): | 70 | elif current_item.is_image() and not frame.get('image', '') and Settings().value('api/thumbnails'): |
197 | 69 | item['tag'] = str(index + 1) | 71 | item['tag'] = str(index + 1) |
198 | 70 | 72 | ||
199 | === modified file 'openlp/core/api/endpoint/core.py' | |||
200 | --- openlp/core/api/endpoint/core.py 2018-08-25 14:08:19 +0000 | |||
201 | +++ openlp/core/api/endpoint/core.py 2019-02-12 20:56:20 +0000 | |||
202 | @@ -30,8 +30,8 @@ | |||
203 | 30 | from openlp.core.common.i18n import UiStrings, translate | 30 | from openlp.core.common.i18n import UiStrings, translate |
204 | 31 | from openlp.core.common.registry import Registry | 31 | from openlp.core.common.registry import Registry |
205 | 32 | from openlp.core.lib import image_to_byte | 32 | from openlp.core.lib import image_to_byte |
208 | 33 | from openlp.core.lib.plugin import StringContent | 33 | from openlp.core.lib.plugin import PluginStatus, StringContent |
209 | 34 | from openlp.core.lib.plugin import PluginStatus | 34 | |
210 | 35 | 35 | ||
211 | 36 | template_dir = 'templates' | 36 | template_dir = 'templates' |
212 | 37 | static_dir = 'static' | 37 | static_dir = 'static' |
213 | 38 | 38 | ||
214 | === modified file 'openlp/core/api/endpoint/remote.py' | |||
215 | --- openlp/core/api/endpoint/remote.py 2017-12-29 09:15:48 +0000 | |||
216 | +++ openlp/core/api/endpoint/remote.py 2019-02-12 20:56:20 +0000 | |||
217 | @@ -24,6 +24,7 @@ | |||
218 | 24 | from openlp.core.api.endpoint.core import TRANSLATED_STRINGS | 24 | from openlp.core.api.endpoint.core import TRANSLATED_STRINGS |
219 | 25 | from openlp.core.api.http.endpoint import Endpoint | 25 | from openlp.core.api.http.endpoint import Endpoint |
220 | 26 | 26 | ||
221 | 27 | |||
222 | 27 | log = logging.getLogger(__name__) | 28 | log = logging.getLogger(__name__) |
223 | 28 | 29 | ||
224 | 29 | remote_endpoint = Endpoint('remote', template_dir='remotes') | 30 | remote_endpoint = Endpoint('remote', template_dir='remotes') |
225 | 30 | 31 | ||
226 | === modified file 'openlp/core/api/endpoint/service.py' | |||
227 | --- openlp/core/api/endpoint/service.py 2017-12-29 09:15:48 +0000 | |||
228 | +++ openlp/core/api/endpoint/service.py 2019-02-12 20:56:20 +0000 | |||
229 | @@ -26,6 +26,7 @@ | |||
230 | 26 | from openlp.core.api.http.endpoint import Endpoint | 26 | from openlp.core.api.http.endpoint import Endpoint |
231 | 27 | from openlp.core.common.registry import Registry | 27 | from openlp.core.common.registry import Registry |
232 | 28 | 28 | ||
233 | 29 | |||
234 | 29 | log = logging.getLogger(__name__) | 30 | log = logging.getLogger(__name__) |
235 | 30 | 31 | ||
236 | 31 | service_endpoint = Endpoint('service') | 32 | service_endpoint = Endpoint('service') |
237 | 32 | 33 | ||
238 | === modified file 'openlp/core/api/http/server.py' | |||
239 | --- openlp/core/api/http/server.py 2018-01-07 04:36:45 +0000 | |||
240 | +++ openlp/core/api/http/server.py 2019-02-12 20:56:20 +0000 | |||
241 | @@ -30,22 +30,21 @@ | |||
242 | 30 | from waitress.server import create_server | 30 | from waitress.server import create_server |
243 | 31 | 31 | ||
244 | 32 | from openlp.core.api.deploy import download_and_check, download_sha256 | 32 | from openlp.core.api.deploy import download_and_check, download_sha256 |
247 | 33 | from openlp.core.api.endpoint.controller import controller_endpoint, api_controller_endpoint | 33 | from openlp.core.api.endpoint.controller import api_controller_endpoint, controller_endpoint |
248 | 34 | from openlp.core.api.endpoint.core import chords_endpoint, stage_endpoint, blank_endpoint, main_endpoint | 34 | from openlp.core.api.endpoint.core import blank_endpoint, chords_endpoint, main_endpoint, stage_endpoint |
249 | 35 | from openlp.core.api.endpoint.remote import remote_endpoint | 35 | from openlp.core.api.endpoint.remote import remote_endpoint |
253 | 36 | from openlp.core.api.endpoint.service import service_endpoint, api_service_endpoint | 36 | from openlp.core.api.endpoint.service import api_service_endpoint, service_endpoint |
254 | 37 | from openlp.core.api.http import application | 37 | from openlp.core.api.http import application, register_endpoint |
252 | 38 | from openlp.core.api.http import register_endpoint | ||
255 | 39 | from openlp.core.api.poll import Poller | 38 | from openlp.core.api.poll import Poller |
256 | 40 | from openlp.core.common.applocation import AppLocation | 39 | from openlp.core.common.applocation import AppLocation |
259 | 41 | from openlp.core.common.i18n import UiStrings | 40 | from openlp.core.common.i18n import UiStrings, translate |
258 | 42 | from openlp.core.common.i18n import translate | ||
260 | 43 | from openlp.core.common.mixins import LogMixin, RegistryProperties | 41 | from openlp.core.common.mixins import LogMixin, RegistryProperties |
261 | 44 | from openlp.core.common.path import create_paths | 42 | from openlp.core.common.path import create_paths |
262 | 45 | from openlp.core.common.registry import Registry, RegistryBase | 43 | from openlp.core.common.registry import Registry, RegistryBase |
263 | 46 | from openlp.core.common.settings import Settings | 44 | from openlp.core.common.settings import Settings |
264 | 47 | from openlp.core.threading import ThreadWorker, run_thread | 45 | from openlp.core.threading import ThreadWorker, run_thread |
265 | 48 | 46 | ||
266 | 47 | |||
267 | 49 | log = logging.getLogger(__name__) | 48 | log = logging.getLogger(__name__) |
268 | 50 | 49 | ||
269 | 51 | 50 | ||
270 | 52 | 51 | ||
271 | === modified file 'openlp/core/api/http/wsgiapp.py' | |||
272 | --- openlp/core/api/http/wsgiapp.py 2018-07-04 20:42:55 +0000 | |||
273 | +++ openlp/core/api/http/wsgiapp.py 2019-02-12 20:56:20 +0000 | |||
274 | @@ -33,6 +33,7 @@ | |||
275 | 33 | from openlp.core.api.http.errors import HttpError, NotFound, ServerError | 33 | from openlp.core.api.http.errors import HttpError, NotFound, ServerError |
276 | 34 | from openlp.core.common.applocation import AppLocation | 34 | from openlp.core.common.applocation import AppLocation |
277 | 35 | 35 | ||
278 | 36 | |||
279 | 36 | ARGS_REGEX = re.compile(r'''\{(\w+)(?::([^}]+))?\}''', re.VERBOSE) | 37 | ARGS_REGEX = re.compile(r'''\{(\w+)(?::([^}]+))?\}''', re.VERBOSE) |
280 | 37 | 38 | ||
281 | 38 | log = logging.getLogger(__name__) | 39 | log = logging.getLogger(__name__) |
282 | 39 | 40 | ||
283 | === modified file 'openlp/core/api/tab.py' | |||
284 | --- openlp/core/api/tab.py 2018-08-25 14:08:19 +0000 | |||
285 | +++ openlp/core/api/tab.py 2019-02-12 20:56:20 +0000 | |||
286 | @@ -31,6 +31,7 @@ | |||
287 | 31 | from openlp.core.lib.settingstab import SettingsTab | 31 | from openlp.core.lib.settingstab import SettingsTab |
288 | 32 | from openlp.core.ui.icons import UiIcons | 32 | from openlp.core.ui.icons import UiIcons |
289 | 33 | 33 | ||
290 | 34 | |||
291 | 34 | ZERO_URL = '0.0.0.0' | 35 | ZERO_URL = '0.0.0.0' |
292 | 35 | 36 | ||
293 | 36 | 37 | ||
294 | @@ -43,9 +44,9 @@ | |||
295 | 43 | advanced_translated = translate('OpenLP.AdvancedTab', 'Advanced') | 44 | advanced_translated = translate('OpenLP.AdvancedTab', 'Advanced') |
296 | 44 | super(ApiTab, self).__init__(parent, 'api', advanced_translated) | 45 | super(ApiTab, self).__init__(parent, 'api', advanced_translated) |
297 | 45 | 46 | ||
299 | 46 | def setupUi(self): | 47 | def setup_ui(self): |
300 | 47 | self.setObjectName('ApiTab') | 48 | self.setObjectName('ApiTab') |
302 | 48 | super(ApiTab, self).setupUi() | 49 | super(ApiTab, self).setup_ui() |
303 | 49 | self.server_settings_group_box = QtWidgets.QGroupBox(self.left_column) | 50 | self.server_settings_group_box = QtWidgets.QGroupBox(self.left_column) |
304 | 50 | self.server_settings_group_box.setObjectName('server_settings_group_box') | 51 | self.server_settings_group_box.setObjectName('server_settings_group_box') |
305 | 51 | self.server_settings_layout = QtWidgets.QFormLayout(self.server_settings_group_box) | 52 | self.server_settings_layout = QtWidgets.QFormLayout(self.server_settings_group_box) |
306 | @@ -154,7 +155,7 @@ | |||
307 | 154 | self.thumbnails_check_box.stateChanged.connect(self.on_thumbnails_check_box_changed) | 155 | self.thumbnails_check_box.stateChanged.connect(self.on_thumbnails_check_box_changed) |
308 | 155 | self.address_edit.textChanged.connect(self.set_urls) | 156 | self.address_edit.textChanged.connect(self.set_urls) |
309 | 156 | 157 | ||
311 | 157 | def retranslateUi(self): | 158 | def retranslate_ui(self): |
312 | 158 | self.tab_title_visible = translate('RemotePlugin.RemoteTab', 'Remote Interface') | 159 | self.tab_title_visible = translate('RemotePlugin.RemoteTab', 'Remote Interface') |
313 | 159 | self.server_settings_group_box.setTitle(translate('RemotePlugin.RemoteTab', 'Server Settings')) | 160 | self.server_settings_group_box.setTitle(translate('RemotePlugin.RemoteTab', 'Server Settings')) |
314 | 160 | self.address_label.setText(translate('RemotePlugin.RemoteTab', 'Serve on IP address:')) | 161 | self.address_label.setText(translate('RemotePlugin.RemoteTab', 'Serve on IP address:')) |
315 | 161 | 162 | ||
316 | === modified file 'openlp/core/api/websockets.py' | |||
317 | --- openlp/core/api/websockets.py 2018-01-07 17:50:29 +0000 | |||
318 | +++ openlp/core/api/websockets.py 2019-02-12 20:56:20 +0000 | |||
319 | @@ -35,6 +35,7 @@ | |||
320 | 35 | from openlp.core.common.settings import Settings | 35 | from openlp.core.common.settings import Settings |
321 | 36 | from openlp.core.threading import ThreadWorker, run_thread | 36 | from openlp.core.threading import ThreadWorker, run_thread |
322 | 37 | 37 | ||
323 | 38 | |||
324 | 38 | log = logging.getLogger(__name__) | 39 | log = logging.getLogger(__name__) |
325 | 39 | 40 | ||
326 | 40 | 41 | ||
327 | 41 | 42 | ||
328 | === modified file 'openlp/core/app.py' | |||
329 | --- openlp/core/app.py 2018-10-25 16:38:39 +0000 | |||
330 | +++ openlp/core/app.py 2019-02-12 20:56:20 +0000 | |||
331 | @@ -33,27 +33,28 @@ | |||
332 | 33 | from datetime import datetime | 33 | from datetime import datetime |
333 | 34 | from traceback import format_exception | 34 | from traceback import format_exception |
334 | 35 | 35 | ||
336 | 36 | from PyQt5 import QtCore, QtWidgets | 36 | from PyQt5 import QtCore, QtWebEngineWidgets, QtWidgets # noqa |
337 | 37 | 37 | ||
338 | 38 | from openlp.core.state import State | 38 | from openlp.core.state import State |
339 | 39 | from openlp.core.common import is_macosx, is_win | 39 | from openlp.core.common import is_macosx, is_win |
340 | 40 | from openlp.core.common.applocation import AppLocation | 40 | from openlp.core.common.applocation import AppLocation |
341 | 41 | from openlp.core.loader import loader | 41 | from openlp.core.loader import loader |
342 | 42 | from openlp.core.common.i18n import LanguageManager, UiStrings, translate | 42 | from openlp.core.common.i18n import LanguageManager, UiStrings, translate |
344 | 43 | from openlp.core.common.path import create_paths, copytree | 43 | from openlp.core.common.path import copytree, create_paths |
345 | 44 | from openlp.core.common.registry import Registry | 44 | from openlp.core.common.registry import Registry |
346 | 45 | from openlp.core.common.settings import Settings | 45 | from openlp.core.common.settings import Settings |
347 | 46 | from openlp.core.display.screens import ScreenList | 46 | from openlp.core.display.screens import ScreenList |
348 | 47 | from openlp.core.resources import qInitResources | 47 | from openlp.core.resources import qInitResources |
350 | 48 | from openlp.core.ui.splashscreen import SplashScreen | 48 | from openlp.core.server import Server |
351 | 49 | from openlp.core.ui.exceptionform import ExceptionForm | 49 | from openlp.core.ui.exceptionform import ExceptionForm |
352 | 50 | from openlp.core.ui.firsttimeform import FirstTimeForm | 50 | from openlp.core.ui.firsttimeform import FirstTimeForm |
353 | 51 | from openlp.core.ui.firsttimelanguageform import FirstTimeLanguageForm | 51 | from openlp.core.ui.firsttimelanguageform import FirstTimeLanguageForm |
354 | 52 | from openlp.core.ui.mainwindow import MainWindow | 52 | from openlp.core.ui.mainwindow import MainWindow |
355 | 53 | from openlp.core.ui.splashscreen import SplashScreen | ||
356 | 53 | from openlp.core.ui.style import get_application_stylesheet | 54 | from openlp.core.ui.style import get_application_stylesheet |
357 | 54 | from openlp.core.server import Server | ||
358 | 55 | from openlp.core.version import check_for_update, get_version | 55 | from openlp.core.version import check_for_update, get_version |
359 | 56 | 56 | ||
360 | 57 | |||
361 | 57 | __all__ = ['OpenLP', 'main'] | 58 | __all__ = ['OpenLP', 'main'] |
362 | 58 | 59 | ||
363 | 59 | 60 | ||
364 | @@ -74,7 +75,8 @@ | |||
365 | 74 | """ | 75 | """ |
366 | 75 | self.is_event_loop_active = True | 76 | self.is_event_loop_active = True |
367 | 76 | result = QtWidgets.QApplication.exec() | 77 | result = QtWidgets.QApplication.exec() |
369 | 77 | self.server.close_server() | 78 | if hasattr(self, 'server'): |
370 | 79 | self.server.close_server() | ||
371 | 78 | return result | 80 | return result |
372 | 79 | 81 | ||
373 | 80 | def run(self, args): | 82 | def run(self, args): |
374 | @@ -317,7 +319,7 @@ | |||
375 | 317 | file_path = log_path / 'openlp.log' | 319 | file_path = log_path / 'openlp.log' |
376 | 318 | # TODO: FileHandler accepts a Path object in Py3.6 | 320 | # TODO: FileHandler accepts a Path object in Py3.6 |
377 | 319 | logfile = logging.FileHandler(str(file_path), 'w', encoding='UTF-8') | 321 | logfile = logging.FileHandler(str(file_path), 'w', encoding='UTF-8') |
379 | 320 | logfile.setFormatter(logging.Formatter('%(asctime)s %(name)-55s %(levelname)-8s %(message)s')) | 322 | logfile.setFormatter(logging.Formatter('%(asctime)s %(threadName)s %(name)-55s %(levelname)-8s %(message)s')) |
380 | 321 | log.addHandler(logfile) | 323 | log.addHandler(logfile) |
381 | 322 | if log.isEnabledFor(logging.DEBUG): | 324 | if log.isEnabledFor(logging.DEBUG): |
382 | 323 | print('Logging to: {name}'.format(name=file_path)) | 325 | print('Logging to: {name}'.format(name=file_path)) |
383 | @@ -330,7 +332,8 @@ | |||
384 | 330 | :param args: Some args | 332 | :param args: Some args |
385 | 331 | """ | 333 | """ |
386 | 332 | args = parse_options(args) | 334 | args = parse_options(args) |
388 | 333 | qt_args = [] | 335 | qt_args = ['--disable-web-security'] |
389 | 336 | # qt_args = [] | ||
390 | 334 | if args and args.loglevel.lower() in ['d', 'debug']: | 337 | if args and args.loglevel.lower() in ['d', 'debug']: |
391 | 335 | log.setLevel(logging.DEBUG) | 338 | log.setLevel(logging.DEBUG) |
392 | 336 | elif args and args.loglevel.lower() in ['w', 'warning']: | 339 | elif args and args.loglevel.lower() in ['w', 'warning']: |
393 | 337 | 340 | ||
394 | === modified file 'openlp/core/common/actions.py' | |||
395 | --- openlp/core/common/actions.py 2018-10-13 10:24:01 +0000 | |||
396 | +++ openlp/core/common/actions.py 2019-02-12 20:56:20 +0000 | |||
397 | @@ -29,6 +29,7 @@ | |||
398 | 29 | 29 | ||
399 | 30 | from openlp.core.common.settings import Settings | 30 | from openlp.core.common.settings import Settings |
400 | 31 | 31 | ||
401 | 32 | |||
402 | 32 | log = logging.getLogger(__name__) | 33 | log = logging.getLogger(__name__) |
403 | 33 | 34 | ||
404 | 34 | 35 | ||
405 | @@ -113,7 +114,6 @@ | |||
406 | 113 | if item[1] == action: | 114 | if item[1] == action: |
407 | 114 | self.actions.remove(item) | 115 | self.actions.remove(item) |
408 | 115 | return | 116 | return |
409 | 116 | log.warning('Action "{action}" does not exist.'.format(action=action)) | ||
410 | 117 | 117 | ||
411 | 118 | 118 | ||
412 | 119 | class CategoryList(object): | 119 | class CategoryList(object): |
413 | 120 | 120 | ||
414 | === modified file 'openlp/core/common/applocation.py' | |||
415 | --- openlp/core/common/applocation.py 2018-10-07 23:34:00 +0000 | |||
416 | +++ openlp/core/common/applocation.py 2019-02-12 20:56:20 +0000 | |||
417 | @@ -29,10 +29,11 @@ | |||
418 | 29 | import appdirs | 29 | import appdirs |
419 | 30 | 30 | ||
420 | 31 | import openlp | 31 | import openlp |
422 | 32 | from openlp.core.common import get_frozen_path, is_win, is_macosx | 32 | from openlp.core.common import get_frozen_path, is_macosx, is_win |
423 | 33 | from openlp.core.common.path import Path, create_paths | 33 | from openlp.core.common.path import Path, create_paths |
424 | 34 | from openlp.core.common.settings import Settings | 34 | from openlp.core.common.settings import Settings |
425 | 35 | 35 | ||
426 | 36 | |||
427 | 36 | log = logging.getLogger(__name__) | 37 | log = logging.getLogger(__name__) |
428 | 37 | 38 | ||
429 | 38 | FROZEN_APP_PATH = Path(sys.argv[0]).parent | 39 | FROZEN_APP_PATH = Path(sys.argv[0]).parent |
430 | 39 | 40 | ||
431 | === modified file 'openlp/core/common/db.py' | |||
432 | --- openlp/core/common/db.py 2017-12-29 09:15:48 +0000 | |||
433 | +++ openlp/core/common/db.py 2019-02-12 20:56:20 +0000 | |||
434 | @@ -27,6 +27,7 @@ | |||
435 | 27 | 27 | ||
436 | 28 | import sqlalchemy | 28 | import sqlalchemy |
437 | 29 | 29 | ||
438 | 30 | |||
439 | 30 | log = logging.getLogger(__name__) | 31 | log = logging.getLogger(__name__) |
440 | 31 | 32 | ||
441 | 32 | 33 | ||
442 | 33 | 34 | ||
443 | === modified file 'openlp/core/common/httputils.py' | |||
444 | --- openlp/core/common/httputils.py 2018-06-08 20:55:20 +0000 | |||
445 | +++ openlp/core/common/httputils.py 2019-02-12 20:56:20 +0000 | |||
446 | @@ -34,6 +34,7 @@ | |||
447 | 34 | from openlp.core.common.registry import Registry | 34 | from openlp.core.common.registry import Registry |
448 | 35 | from openlp.core.common.settings import ProxyMode, Settings | 35 | from openlp.core.common.settings import ProxyMode, Settings |
449 | 36 | 36 | ||
450 | 37 | |||
451 | 37 | log = logging.getLogger(__name__ + '.__init__') | 38 | log = logging.getLogger(__name__ + '.__init__') |
452 | 38 | 39 | ||
453 | 39 | USER_AGENTS = { | 40 | USER_AGENTS = { |
454 | 40 | 41 | ||
455 | === modified file 'openlp/core/common/i18n.py' | |||
456 | --- openlp/core/common/i18n.py 2018-10-27 11:05:41 +0000 | |||
457 | +++ openlp/core/common/i18n.py 2019-02-12 20:56:20 +0000 | |||
458 | @@ -29,10 +29,11 @@ | |||
459 | 29 | 29 | ||
460 | 30 | from PyQt5 import QtCore, QtWidgets | 30 | from PyQt5 import QtCore, QtWidgets |
461 | 31 | 31 | ||
463 | 32 | from openlp.core.common import is_win, is_macosx | 32 | from openlp.core.common import is_macosx, is_win |
464 | 33 | from openlp.core.common.applocation import AppLocation | 33 | from openlp.core.common.applocation import AppLocation |
465 | 34 | from openlp.core.common.settings import Settings | 34 | from openlp.core.common.settings import Settings |
466 | 35 | 35 | ||
467 | 36 | |||
468 | 36 | log = logging.getLogger(__name__) | 37 | log = logging.getLogger(__name__) |
469 | 37 | 38 | ||
470 | 38 | 39 | ||
471 | 39 | 40 | ||
472 | === modified file 'openlp/core/common/mixins.py' | |||
473 | --- openlp/core/common/mixins.py 2018-11-18 17:29:47 +0000 | |||
474 | +++ openlp/core/common/mixins.py 2019-02-12 20:56:20 +0000 | |||
475 | @@ -28,6 +28,7 @@ | |||
476 | 28 | from openlp.core.common import is_win, trace_error_handler | 28 | from openlp.core.common import is_win, trace_error_handler |
477 | 29 | from openlp.core.common.registry import Registry | 29 | from openlp.core.common.registry import Registry |
478 | 30 | 30 | ||
479 | 31 | |||
480 | 31 | DO_NOT_TRACE_EVENTS = ['timerEvent', 'paintEvent', 'drag_enter_event', 'drop_event', 'on_controller_size_changed', | 32 | DO_NOT_TRACE_EVENTS = ['timerEvent', 'paintEvent', 'drag_enter_event', 'drop_event', 'on_controller_size_changed', |
481 | 32 | 'preview_size_changed', 'resizeEvent'] | 33 | 'preview_size_changed', 'resizeEvent'] |
482 | 33 | 34 | ||
483 | 34 | 35 | ||
484 | === modified file 'openlp/core/common/path.py' | |||
485 | --- openlp/core/common/path.py 2018-08-12 11:14:47 +0000 | |||
486 | +++ openlp/core/common/path.py 2019-02-12 20:56:20 +0000 | |||
487 | @@ -25,6 +25,7 @@ | |||
488 | 25 | 25 | ||
489 | 26 | from openlp.core.common import is_win | 26 | from openlp.core.common import is_win |
490 | 27 | 27 | ||
491 | 28 | |||
492 | 28 | if is_win(): | 29 | if is_win(): |
493 | 29 | from pathlib import WindowsPath as PathVariant # pragma: nocover | 30 | from pathlib import WindowsPath as PathVariant # pragma: nocover |
494 | 30 | else: | 31 | else: |
495 | 31 | 32 | ||
496 | === modified file 'openlp/core/common/registry.py' | |||
497 | --- openlp/core/common/registry.py 2018-10-25 16:38:39 +0000 | |||
498 | +++ openlp/core/common/registry.py 2019-02-12 20:56:20 +0000 | |||
499 | @@ -27,6 +27,7 @@ | |||
500 | 27 | 27 | ||
501 | 28 | from openlp.core.common import de_hump, trace_error_handler | 28 | from openlp.core.common import de_hump, trace_error_handler |
502 | 29 | 29 | ||
503 | 30 | |||
504 | 30 | log = logging.getLogger(__name__) | 31 | log = logging.getLogger(__name__) |
505 | 31 | 32 | ||
506 | 32 | 33 | ||
507 | @@ -143,6 +144,7 @@ | |||
508 | 143 | if event in self.functions_list: | 144 | if event in self.functions_list: |
509 | 144 | for function in self.functions_list[event]: | 145 | for function in self.functions_list[event]: |
510 | 145 | try: | 146 | try: |
511 | 147 | log.debug('Running function {} for {}'.format(function, event)) | ||
512 | 146 | result = function(*args, **kwargs) | 148 | result = function(*args, **kwargs) |
513 | 147 | if result: | 149 | if result: |
514 | 148 | results.append(result) | 150 | results.append(result) |
515 | 149 | 151 | ||
516 | === modified file 'openlp/core/common/settings.py' | |||
517 | --- openlp/core/common/settings.py 2018-10-24 19:35:22 +0000 | |||
518 | +++ openlp/core/common/settings.py 2019-02-12 20:56:20 +0000 | |||
519 | @@ -1,4 +1,4 @@ | |||
521 | 1 | # -*- coding: utf-8 -*- | 1 | # -*- coding: utf-8 -*- |
522 | 2 | # vim: autoindent shiftwidth=4 expandtab textwidth=120 tabstop=4 softtabstop=4 | 2 | # vim: autoindent shiftwidth=4 expandtab textwidth=120 tabstop=4 softtabstop=4 |
523 | 3 | 3 | ||
524 | 4 | ############################################################################### | 4 | ############################################################################### |
525 | @@ -33,7 +33,8 @@ | |||
526 | 33 | 33 | ||
527 | 34 | from openlp.core.common import SlideLimits, ThemeLevel, is_linux, is_win | 34 | from openlp.core.common import SlideLimits, ThemeLevel, is_linux, is_win |
528 | 35 | from openlp.core.common.json import OpenLPJsonDecoder, OpenLPJsonEncoder | 35 | from openlp.core.common.json import OpenLPJsonDecoder, OpenLPJsonEncoder |
530 | 36 | from openlp.core.common.path import Path, str_to_path, files_to_paths | 36 | from openlp.core.common.path import Path, files_to_paths, str_to_path |
531 | 37 | |||
532 | 37 | 38 | ||
533 | 38 | log = logging.getLogger(__name__) | 39 | log = logging.getLogger(__name__) |
534 | 39 | 40 | ||
535 | @@ -70,6 +71,34 @@ | |||
536 | 70 | return string | 71 | return string |
537 | 71 | 72 | ||
538 | 72 | 73 | ||
539 | 74 | def upgrade_screens(number, x_position, y_position, height, width, can_override, is_display_screen): | ||
540 | 75 | """ | ||
541 | 76 | Upgrade them monitor setting from a few single entries to a composite JSON entry | ||
542 | 77 | |||
543 | 78 | :param int number: The old monitor number | ||
544 | 79 | :param int x_position: The X position | ||
545 | 80 | :param int y_position: The Y position | ||
546 | 81 | :param bool can_override: Are the screen positions overridden | ||
547 | 82 | :param bool is_display_screen: Is this a display screen | ||
548 | 83 | :returns dict: Dictionary with the new value | ||
549 | 84 | """ | ||
550 | 85 | geometry_key = 'geometry' | ||
551 | 86 | if can_override: | ||
552 | 87 | geometry_key = 'custom_geometry' | ||
553 | 88 | return { | ||
554 | 89 | number: { | ||
555 | 90 | 'number': number, | ||
556 | 91 | geometry_key: { | ||
557 | 92 | 'x': x_position, | ||
558 | 93 | 'y': y_position, | ||
559 | 94 | 'height': height, | ||
560 | 95 | 'width': width | ||
561 | 96 | }, | ||
562 | 97 | 'is_display': is_display_screen | ||
563 | 98 | } | ||
564 | 99 | } | ||
565 | 100 | |||
566 | 101 | |||
567 | 73 | class Settings(QtCore.QSettings): | 102 | class Settings(QtCore.QSettings): |
568 | 74 | """ | 103 | """ |
569 | 75 | Class to wrap QSettings. | 104 | Class to wrap QSettings. |
570 | @@ -175,6 +204,7 @@ | |||
571 | 175 | # circular dependency. | 204 | # circular dependency. |
572 | 176 | 'core/display on monitor': True, | 205 | 'core/display on monitor': True, |
573 | 177 | 'core/override position': False, | 206 | 'core/override position': False, |
574 | 207 | 'core/monitor': {}, | ||
575 | 178 | 'core/application version': '0.0', | 208 | 'core/application version': '0.0', |
576 | 179 | 'images/background color': '#000000', | 209 | 'images/background color': '#000000', |
577 | 180 | 'media/players': 'system,webkit', | 210 | 'media/players': 'system,webkit', |
578 | @@ -276,6 +306,8 @@ | |||
579 | 276 | ('songuasge/db hostname', 'songusage/db hostname', []), | 306 | ('songuasge/db hostname', 'songusage/db hostname', []), |
580 | 277 | ('songuasge/db database', 'songusage/db database', []), | 307 | ('songuasge/db database', 'songusage/db database', []), |
581 | 278 | ('presentations / Powerpoint Viewer', '', []), | 308 | ('presentations / Powerpoint Viewer', '', []), |
582 | 309 | (['core/monitor', 'core/x position', 'core/y position', 'core/height', 'core/width', 'core/override', | ||
583 | 310 | 'core/display on monitor'], 'core/screens', [(upgrade_screens, [1, 0, 0, None, None, False, False])]), | ||
584 | 279 | ('bibles/proxy name', '', []), # Just remove these bible proxy settings. They weren't used in 2.4! | 311 | ('bibles/proxy name', '', []), # Just remove these bible proxy settings. They weren't used in 2.4! |
585 | 280 | ('bibles/proxy address', '', []), | 312 | ('bibles/proxy address', '', []), |
586 | 281 | ('bibles/proxy username', '', []), | 313 | ('bibles/proxy username', '', []), |
587 | @@ -545,7 +577,7 @@ | |||
588 | 545 | :param value: The value to save | 577 | :param value: The value to save |
589 | 546 | :rtype: None | 578 | :rtype: None |
590 | 547 | """ | 579 | """ |
592 | 548 | if isinstance(value, Path) or (isinstance(value, list) and value and isinstance(value[0], Path)): | 580 | if isinstance(value, (Path, dict)) or (isinstance(value, list) and value and isinstance(value[0], Path)): |
593 | 549 | value = json.dumps(value, cls=OpenLPJsonEncoder) | 581 | value = json.dumps(value, cls=OpenLPJsonEncoder) |
594 | 550 | super().setValue(key, value) | 582 | super().setValue(key, value) |
595 | 551 | 583 | ||
596 | @@ -568,8 +600,11 @@ | |||
597 | 568 | # An empty list saved to the settings results in a None type being returned. | 600 | # An empty list saved to the settings results in a None type being returned. |
598 | 569 | elif isinstance(default_value, list): | 601 | elif isinstance(default_value, list): |
599 | 570 | return [] | 602 | return [] |
600 | 603 | # An empty dictionary saved to the settings results in a None type being returned. | ||
601 | 604 | elif isinstance(default_value, dict): | ||
602 | 605 | return {} | ||
603 | 571 | elif isinstance(setting, str): | 606 | elif isinstance(setting, str): |
605 | 572 | if '__Path__' in setting: | 607 | if '__Path__' in setting or setting.startswith('{'): |
606 | 573 | return json.loads(setting, cls=OpenLPJsonDecoder) | 608 | return json.loads(setting, cls=OpenLPJsonDecoder) |
607 | 574 | # Convert the setting to the correct type. | 609 | # Convert the setting to the correct type. |
608 | 575 | if isinstance(default_value, bool): | 610 | if isinstance(default_value, bool): |
609 | @@ -578,6 +613,8 @@ | |||
610 | 578 | # Sometimes setting is string instead of a boolean. | 613 | # Sometimes setting is string instead of a boolean. |
611 | 579 | return setting == 'true' | 614 | return setting == 'true' |
612 | 580 | if isinstance(default_value, int): | 615 | if isinstance(default_value, int): |
613 | 616 | if setting is None: | ||
614 | 617 | return 0 | ||
615 | 581 | return int(setting) | 618 | return int(setting) |
616 | 582 | return setting | 619 | return setting |
617 | 583 | 620 | ||
618 | 584 | 621 | ||
619 | === added directory 'openlp/core/display/html' | |||
620 | === added file 'openlp/core/display/html/black.css' | |||
621 | --- openlp/core/display/html/black.css 1970-01-01 00:00:00 +0000 | |||
622 | +++ openlp/core/display/html/black.css 2019-02-12 20:56:20 +0000 | |||
623 | @@ -0,0 +1,292 @@ | |||
624 | 1 | /** | ||
625 | 2 | * Black theme for reveal.js. This is the opposite of the 'white' theme. | ||
626 | 3 | * | ||
627 | 4 | * By Hakim El Hattab, http://hakim.se | ||
628 | 5 | */ | ||
629 | 6 | @import url(../../lib/font/source-sans-pro/source-sans-pro.css); | ||
630 | 7 | section.has-light-background, section.has-light-background h1, section.has-light-background h2, section.has-light-background h3, section.has-light-background h4, section.has-light-background h5, section.has-light-background h6 { | ||
631 | 8 | color: #222; } | ||
632 | 9 | |||
633 | 10 | /********************************************* | ||
634 | 11 | * GLOBAL STYLES | ||
635 | 12 | *********************************************/ | ||
636 | 13 | body { | ||
637 | 14 | background: #222; | ||
638 | 15 | background-color: #222; } | ||
639 | 16 | |||
640 | 17 | .reveal { | ||
641 | 18 | font-family: "Source Sans Pro", Helvetica, sans-serif; | ||
642 | 19 | font-size: 42px; | ||
643 | 20 | font-weight: normal; | ||
644 | 21 | color: #fff; } | ||
645 | 22 | |||
646 | 23 | ::selection { | ||
647 | 24 | color: #fff; | ||
648 | 25 | background: #bee4fd; | ||
649 | 26 | text-shadow: none; } | ||
650 | 27 | |||
651 | 28 | ::-moz-selection { | ||
652 | 29 | color: #fff; | ||
653 | 30 | background: #bee4fd; | ||
654 | 31 | text-shadow: none; } | ||
655 | 32 | |||
656 | 33 | .reveal .slides > section, | ||
657 | 34 | .reveal .slides > section > section { | ||
658 | 35 | line-height: 1.3; | ||
659 | 36 | font-weight: inherit; } | ||
660 | 37 | |||
661 | 38 | /********************************************* | ||
662 | 39 | * HEADERS | ||
663 | 40 | *********************************************/ | ||
664 | 41 | .reveal h1, | ||
665 | 42 | .reveal h2, | ||
666 | 43 | .reveal h3, | ||
667 | 44 | .reveal h4, | ||
668 | 45 | .reveal h5, | ||
669 | 46 | .reveal h6 { | ||
670 | 47 | margin: 0 0 20px 0; | ||
671 | 48 | color: #fff; | ||
672 | 49 | font-family: "Source Sans Pro", Helvetica, sans-serif; | ||
673 | 50 | font-weight: 600; | ||
674 | 51 | line-height: 1.2; | ||
675 | 52 | letter-spacing: normal; | ||
676 | 53 | text-transform: uppercase; | ||
677 | 54 | text-shadow: none; | ||
678 | 55 | word-wrap: break-word; } | ||
679 | 56 | |||
680 | 57 | .reveal h1 { | ||
681 | 58 | font-size: 2.5em; } | ||
682 | 59 | |||
683 | 60 | .reveal h2 { | ||
684 | 61 | font-size: 1.6em; } | ||
685 | 62 | |||
686 | 63 | .reveal h3 { | ||
687 | 64 | font-size: 1.3em; } | ||
688 | 65 | |||
689 | 66 | .reveal h4 { | ||
690 | 67 | font-size: 1em; } | ||
691 | 68 | |||
692 | 69 | .reveal h1 { | ||
693 | 70 | text-shadow: none; } | ||
694 | 71 | |||
695 | 72 | /********************************************* | ||
696 | 73 | * OTHER | ||
697 | 74 | *********************************************/ | ||
698 | 75 | .reveal p { | ||
699 | 76 | margin: 20px 0; | ||
700 | 77 | line-height: 1.3; } | ||
701 | 78 | |||
702 | 79 | /* Ensure certain elements are never larger than the slide itself */ | ||
703 | 80 | .reveal img, | ||
704 | 81 | .reveal video, | ||
705 | 82 | .reveal iframe { | ||
706 | 83 | max-width: 95%; | ||
707 | 84 | max-height: 95%; } | ||
708 | 85 | |||
709 | 86 | .reveal strong, | ||
710 | 87 | .reveal b { | ||
711 | 88 | font-weight: bold; } | ||
712 | 89 | |||
713 | 90 | .reveal em { | ||
714 | 91 | font-style: italic; } | ||
715 | 92 | |||
716 | 93 | .reveal ol, | ||
717 | 94 | .reveal dl, | ||
718 | 95 | .reveal ul { | ||
719 | 96 | display: inline-block; | ||
720 | 97 | text-align: left; | ||
721 | 98 | margin: 0 0 0 1em; } | ||
722 | 99 | |||
723 | 100 | .reveal ol { | ||
724 | 101 | list-style-type: decimal; } | ||
725 | 102 | |||
726 | 103 | .reveal ul { | ||
727 | 104 | list-style-type: disc; } | ||
728 | 105 | |||
729 | 106 | .reveal ul ul { | ||
730 | 107 | list-style-type: square; } | ||
731 | 108 | |||
732 | 109 | .reveal ul ul ul { | ||
733 | 110 | list-style-type: circle; } | ||
734 | 111 | |||
735 | 112 | .reveal ul ul, | ||
736 | 113 | .reveal ul ol, | ||
737 | 114 | .reveal ol ol, | ||
738 | 115 | .reveal ol ul { | ||
739 | 116 | display: block; | ||
740 | 117 | margin-left: 40px; } | ||
741 | 118 | |||
742 | 119 | .reveal dt { | ||
743 | 120 | font-weight: bold; } | ||
744 | 121 | |||
745 | 122 | .reveal dd { | ||
746 | 123 | margin-left: 40px; } | ||
747 | 124 | |||
748 | 125 | .reveal q, | ||
749 | 126 | .reveal blockquote { | ||
750 | 127 | quotes: none; } | ||
751 | 128 | |||
752 | 129 | .reveal blockquote { | ||
753 | 130 | display: block; | ||
754 | 131 | position: relative; | ||
755 | 132 | width: 70%; | ||
756 | 133 | margin: 20px auto; | ||
757 | 134 | padding: 5px; | ||
758 | 135 | font-style: italic; | ||
759 | 136 | background: rgba(255, 255, 255, 0.05); | ||
760 | 137 | box-shadow: 0px 0px 2px rgba(0, 0, 0, 0.2); } | ||
761 | 138 | |||
762 | 139 | .reveal blockquote p:first-child, | ||
763 | 140 | .reveal blockquote p:last-child { | ||
764 | 141 | display: inline-block; } | ||
765 | 142 | |||
766 | 143 | .reveal q { | ||
767 | 144 | font-style: italic; } | ||
768 | 145 | |||
769 | 146 | .reveal pre { | ||
770 | 147 | display: block; | ||
771 | 148 | position: relative; | ||
772 | 149 | width: 90%; | ||
773 | 150 | margin: 20px auto; | ||
774 | 151 | text-align: left; | ||
775 | 152 | font-size: 0.55em; | ||
776 | 153 | font-family: monospace; | ||
777 | 154 | line-height: 1.2em; | ||
778 | 155 | word-wrap: break-word; | ||
779 | 156 | box-shadow: 0px 0px 6px rgba(0, 0, 0, 0.3); } | ||
780 | 157 | |||
781 | 158 | .reveal code { | ||
782 | 159 | font-family: monospace; } | ||
783 | 160 | |||
784 | 161 | .reveal pre code { | ||
785 | 162 | display: block; | ||
786 | 163 | padding: 5px; | ||
787 | 164 | overflow: auto; | ||
788 | 165 | max-height: 400px; | ||
789 | 166 | word-wrap: normal; } | ||
790 | 167 | |||
791 | 168 | .reveal table { | ||
792 | 169 | margin: auto; | ||
793 | 170 | border-collapse: collapse; | ||
794 | 171 | border-spacing: 0; } | ||
795 | 172 | |||
796 | 173 | .reveal table th { | ||
797 | 174 | font-weight: bold; } | ||
798 | 175 | |||
799 | 176 | .reveal table th, | ||
800 | 177 | .reveal table td { | ||
801 | 178 | text-align: left; | ||
802 | 179 | padding: 0.2em 0.5em 0.2em 0.5em; | ||
803 | 180 | border-bottom: 1px solid; } | ||
804 | 181 | |||
805 | 182 | .reveal table th[align="center"], | ||
806 | 183 | .reveal table td[align="center"] { | ||
807 | 184 | text-align: center; } | ||
808 | 185 | |||
809 | 186 | .reveal table th[align="right"], | ||
810 | 187 | .reveal table td[align="right"] { | ||
811 | 188 | text-align: right; } | ||
812 | 189 | |||
813 | 190 | .reveal table tbody tr:last-child th, | ||
814 | 191 | .reveal table tbody tr:last-child td { | ||
815 | 192 | border-bottom: none; } | ||
816 | 193 | |||
817 | 194 | .reveal sup { | ||
818 | 195 | vertical-align: super; } | ||
819 | 196 | |||
820 | 197 | .reveal sub { | ||
821 | 198 | vertical-align: sub; } | ||
822 | 199 | |||
823 | 200 | .reveal small { | ||
824 | 201 | display: inline-block; | ||
825 | 202 | font-size: 0.6em; | ||
826 | 203 | line-height: 1.2em; | ||
827 | 204 | vertical-align: top; } | ||
828 | 205 | |||
829 | 206 | .reveal small * { | ||
830 | 207 | vertical-align: top; } | ||
831 | 208 | |||
832 | 209 | /********************************************* | ||
833 | 210 | * LINKS | ||
834 | 211 | *********************************************/ | ||
835 | 212 | .reveal a { | ||
836 | 213 | color: #42affa; | ||
837 | 214 | text-decoration: none; | ||
838 | 215 | -webkit-transition: color .15s ease; | ||
839 | 216 | -moz-transition: color .15s ease; | ||
840 | 217 | transition: color .15s ease; } | ||
841 | 218 | |||
842 | 219 | .reveal a:hover { | ||
843 | 220 | color: #8dcffc; | ||
844 | 221 | text-shadow: none; | ||
845 | 222 | border: none; } | ||
846 | 223 | |||
847 | 224 | .reveal .roll span:after { | ||
848 | 225 | color: #fff; | ||
849 | 226 | background: #068de9; } | ||
850 | 227 | |||
851 | 228 | /********************************************* | ||
852 | 229 | * IMAGES | ||
853 | 230 | *********************************************/ | ||
854 | 231 | .reveal section img { | ||
855 | 232 | margin: 15px 0px; | ||
856 | 233 | background: rgba(255, 255, 255, 0.12); | ||
857 | 234 | border: 4px solid #fff; | ||
858 | 235 | box-shadow: 0 0 10px rgba(0, 0, 0, 0.15); } | ||
859 | 236 | |||
860 | 237 | .reveal section img.plain { | ||
861 | 238 | border: 0; | ||
862 | 239 | box-shadow: none; } | ||
863 | 240 | |||
864 | 241 | .reveal a img { | ||
865 | 242 | -webkit-transition: all .15s linear; | ||
866 | 243 | -moz-transition: all .15s linear; | ||
867 | 244 | transition: all .15s linear; } | ||
868 | 245 | |||
869 | 246 | .reveal a:hover img { | ||
870 | 247 | background: rgba(255, 255, 255, 0.2); | ||
871 | 248 | border-color: #42affa; | ||
872 | 249 | box-shadow: 0 0 20px rgba(0, 0, 0, 0.55); } | ||
873 | 250 | |||
874 | 251 | /********************************************* | ||
875 | 252 | * NAVIGATION CONTROLS | ||
876 | 253 | *********************************************/ | ||
877 | 254 | .reveal .controls .navigate-left, | ||
878 | 255 | .reveal .controls .navigate-left.enabled { | ||
879 | 256 | border-right-color: #42affa; } | ||
880 | 257 | |||
881 | 258 | .reveal .controls .navigate-right, | ||
882 | 259 | .reveal .controls .navigate-right.enabled { | ||
883 | 260 | border-left-color: #42affa; } | ||
884 | 261 | |||
885 | 262 | .reveal .controls .navigate-up, | ||
886 | 263 | .reveal .controls .navigate-up.enabled { | ||
887 | 264 | border-bottom-color: #42affa; } | ||
888 | 265 | |||
889 | 266 | .reveal .controls .navigate-down, | ||
890 | 267 | .reveal .controls .navigate-down.enabled { | ||
891 | 268 | border-top-color: #42affa; } | ||
892 | 269 | |||
893 | 270 | .reveal .controls .navigate-left.enabled:hover { | ||
894 | 271 | border-right-color: #8dcffc; } | ||
895 | 272 | |||
896 | 273 | .reveal .controls .navigate-right.enabled:hover { | ||
897 | 274 | border-left-color: #8dcffc; } | ||
898 | 275 | |||
899 | 276 | .reveal .controls .navigate-up.enabled:hover { | ||
900 | 277 | border-bottom-color: #8dcffc; } | ||
901 | 278 | |||
902 | 279 | .reveal .controls .navigate-down.enabled:hover { | ||
903 | 280 | border-top-color: #8dcffc; } | ||
904 | 281 | |||
905 | 282 | /********************************************* | ||
906 | 283 | * PROGRESS BAR | ||
907 | 284 | *********************************************/ | ||
908 | 285 | .reveal .progress { | ||
909 | 286 | background: rgba(0, 0, 0, 0.2); } | ||
910 | 287 | |||
911 | 288 | .reveal .progress span { | ||
912 | 289 | background: #42affa; | ||
913 | 290 | -webkit-transition: width 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985); | ||
914 | 291 | -moz-transition: width 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985); | ||
915 | 292 | transition: width 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985); } | ||
916 | 0 | 293 | ||
917 | === added file 'openlp/core/display/html/checkerboard.png' | |||
918 | 1 | Binary files openlp/core/display/html/checkerboard.png 1970-01-01 00:00:00 +0000 and openlp/core/display/html/checkerboard.png 2019-02-12 20:56:20 +0000 differ | 294 | Binary files openlp/core/display/html/checkerboard.png 1970-01-01 00:00:00 +0000 and openlp/core/display/html/checkerboard.png 2019-02-12 20:56:20 +0000 differ |
919 | === added file 'openlp/core/display/html/display.html' | |||
920 | --- openlp/core/display/html/display.html 1970-01-01 00:00:00 +0000 | |||
921 | +++ openlp/core/display/html/display.html 2019-02-12 20:56:20 +0000 | |||
922 | @@ -0,0 +1,39 @@ | |||
923 | 1 | <!DOCTYPE html> | ||
924 | 2 | <html> | ||
925 | 3 | <head> | ||
926 | 4 | <title>Display Window</title> | ||
927 | 5 | <link href="reveal.css" rel="stylesheet"> | ||
928 | 6 | <style type="text/css"> | ||
929 | 7 | body { | ||
930 | 8 | background: transparent !important; | ||
931 | 9 | color: #fff !important; | ||
932 | 10 | } | ||
933 | 11 | sup { | ||
934 | 12 | vertical-align: super !important; | ||
935 | 13 | font-size: smaller !important; | ||
936 | 14 | } | ||
937 | 15 | .reveal .slides > section, | ||
938 | 16 | .reveal .slides > section > section { | ||
939 | 17 | padding: 0; | ||
940 | 18 | } | ||
941 | 19 | .reveal > .backgrounds > .present { | ||
942 | 20 | visibility: hidden !important; | ||
943 | 21 | } | ||
944 | 22 | #global-background { | ||
945 | 23 | display: block; | ||
946 | 24 | visibility: visible; | ||
947 | 25 | z-index: -1; | ||
948 | 26 | } | ||
949 | 27 | </style> | ||
950 | 28 | <script type="text/javascript" src="qrc:///qtwebchannel/qwebchannel.js"></script> | ||
951 | 29 | <script type="text/javascript" src="reveal.js"></script> | ||
952 | 30 | <script type="text/javascript" src="display.js"></script> | ||
953 | 31 | </head> | ||
954 | 32 | <body> | ||
955 | 33 | <div class="reveal"> | ||
956 | 34 | <div id="global-background" class="slide-background present" data-loaded="true"></div> | ||
957 | 35 | <div class="slides"></div> | ||
958 | 36 | <div class="footer"></div> | ||
959 | 37 | </div> | ||
960 | 38 | </body> | ||
961 | 39 | </html> | ||
962 | 0 | 40 | ||
963 | === added file 'openlp/core/display/html/display.js' | |||
964 | --- openlp/core/display/html/display.js 1970-01-01 00:00:00 +0000 | |||
965 | +++ openlp/core/display/html/display.js 2019-02-12 20:56:20 +0000 | |||
966 | @@ -0,0 +1,789 @@ | |||
967 | 1 | /** | ||
968 | 2 | * display.js is the main Javascript file that is used to drive the display. | ||
969 | 3 | */ | ||
970 | 4 | |||
971 | 5 | /** | ||
972 | 6 | * Background type enumeration | ||
973 | 7 | */ | ||
974 | 8 | var BackgroundType = { | ||
975 | 9 | Transparent: "transparent", | ||
976 | 10 | Solid: "solid", | ||
977 | 11 | Gradient: "gradient", | ||
978 | 12 | Video: "video", | ||
979 | 13 | Image: "image" | ||
980 | 14 | }; | ||
981 | 15 | |||
982 | 16 | /** | ||
983 | 17 | * Gradient type enumeration | ||
984 | 18 | */ | ||
985 | 19 | var GradientType = { | ||
986 | 20 | Horizontal: "horizontal", | ||
987 | 21 | LeftTop: "leftTop", | ||
988 | 22 | LeftBottom: "leftBottom", | ||
989 | 23 | Vertical: "vertical", | ||
990 | 24 | Circular: "circular" | ||
991 | 25 | }; | ||
992 | 26 | |||
993 | 27 | /** | ||
994 | 28 | * Horizontal alignment enumeration | ||
995 | 29 | */ | ||
996 | 30 | var HorizontalAlign = { | ||
997 | 31 | Left: "left", | ||
998 | 32 | Right: "right", | ||
999 | 33 | Center: "center", | ||
1000 | 34 | Justify: "justify" | ||
1001 | 35 | }; | ||
1002 | 36 | |||
1003 | 37 | /** | ||
1004 | 38 | * Vertical alignment enumeration | ||
1005 | 39 | */ | ||
1006 | 40 | var VerticalAlign = { | ||
1007 | 41 | Top: "top", | ||
1008 | 42 | Middle: "middle", | ||
1009 | 43 | Bottom: "bottom" | ||
1010 | 44 | }; | ||
1011 | 45 | |||
1012 | 46 | /** | ||
1013 | 47 | * Audio state enumeration | ||
1014 | 48 | */ | ||
1015 | 49 | var AudioState = { | ||
1016 | 50 | Playing: "playing", | ||
1017 | 51 | Paused: "paused", | ||
1018 | 52 | Stopped: "stopped" | ||
1019 | 53 | }; | ||
1020 | 54 | |||
1021 | 55 | /** | ||
1022 | 56 | * Return an array of elements based on the selector query | ||
1023 | 57 | * @param {string} selector - The selector to find elements | ||
1024 | 58 | * @returns {array} An array of matching elements | ||
1025 | 59 | */ | ||
1026 | 60 | function $(selector) { | ||
1027 | 61 | return Array.from(document.querySelectorAll(selector)); | ||
1028 | 62 | } | ||
1029 | 63 | |||
1030 | 64 | /** | ||
1031 | 65 | * Build linear gradient CSS | ||
1032 | 66 | * @private | ||
1033 | 67 | * @param {string} startDir - Starting direction | ||
1034 | 68 | * @param {string} endDir - Ending direction | ||
1035 | 69 | * @param {string} startColor - The starting color | ||
1036 | 70 | * @param {string} endColor - The ending color | ||
1037 | 71 | * @returns {string} A string of the gradient CSS | ||
1038 | 72 | */ | ||
1039 | 73 | function _buildLinearGradient(startDir, endDir, startColor, endColor) { | ||
1040 | 74 | return "-webkit-gradient(linear, " + startDir + ", " + endDir + ", from(" + startColor + "), to(" + endColor + ")) fixed"; | ||
1041 | 75 | } | ||
1042 | 76 | |||
1043 | 77 | /** | ||
1044 | 78 | * Build radial gradient CSS | ||
1045 | 79 | * @private | ||
1046 | 80 | * @param {string} width - Width of the gradient | ||
1047 | 81 | * @param {string} startColor - The starting color | ||
1048 | 82 | * @param {string} endColor - The ending color | ||
1049 | 83 | * @returns {string} A string of the gradient CSS | ||
1050 | 84 | */ | ||
1051 | 85 | function _buildRadialGradient(width, startColor, endColor) { | ||
1052 | 86 | return "-webkit-gradient(radial, " + width + " 50%, 100, " + width + " 50%, " + width + ", from(" + startColor + "), to(" + endColor + ")) fixed"; | ||
1053 | 87 | } | ||
1054 | 88 | |||
1055 | 89 | /** | ||
1056 | 90 | * Get a style value from an element (computed or manual) | ||
1057 | 91 | * @private | ||
1058 | 92 | * @param {Object} element - The element whose style we want | ||
1059 | 93 | * @param {string} style - The name of the style we want | ||
1060 | 94 | * @returns {(Number|string)} The style value (type depends on the style) | ||
1061 | 95 | */ | ||
1062 | 96 | function _getStyle(element, style) { | ||
1063 | 97 | return document.defaultView.getComputedStyle(element).getPropertyValue(style); | ||
1064 | 98 | } | ||
1065 | 99 | |||
1066 | 100 | /** | ||
1067 | 101 | * Convert newlines to <br> tags | ||
1068 | 102 | * @private | ||
1069 | 103 | * @param {string} text - The text to parse | ||
1070 | 104 | * @returns {string} The text now with <br> tags | ||
1071 | 105 | */ | ||
1072 | 106 | function _nl2br(text) { | ||
1073 | 107 | return text.replace("\r\n", "\n").replace("\n", "<br>"); | ||
1074 | 108 | } | ||
1075 | 109 | |||
1076 | 110 | /** | ||
1077 | 111 | * Prepare text by creating paragraphs and calling _nl2br to convert newlines to <br> tags | ||
1078 | 112 | * @private | ||
1079 | 113 | * @param {string} text - The text to parse | ||
1080 | 114 | * @returns {string} The text now with <p> and <br> tags | ||
1081 | 115 | */ | ||
1082 | 116 | function _prepareText(text) { | ||
1083 | 117 | return "<p>" + _nl2br(text) + "</p>"; | ||
1084 | 118 | } | ||
1085 | 119 | |||
1086 | 120 | /** | ||
1087 | 121 | * The paths we get are JSON versions of Python Path objects, so let's just fix that. | ||
1088 | 122 | * @private | ||
1089 | 123 | * @param {object} path - The Path object | ||
1090 | 124 | * @returns {string} The actual file path | ||
1091 | 125 | */ | ||
1092 | 126 | function _pathToString(path) { | ||
1093 | 127 | var filename = path.__Path__.join("/").replace("//", "/"); | ||
1094 | 128 | if (!filename.startsWith("/")) { | ||
1095 | 129 | filename = "/" + filename; | ||
1096 | 130 | } | ||
1097 | 131 | return filename; | ||
1098 | 132 | } | ||
1099 | 133 | |||
1100 | 134 | /** | ||
1101 | 135 | * An audio player with a play list | ||
1102 | 136 | */ | ||
1103 | 137 | var AudioPlayer = function (audioElement) { | ||
1104 | 138 | this._audioElement = null; | ||
1105 | 139 | this._eventListeners = {}; | ||
1106 | 140 | this._playlist = []; | ||
1107 | 141 | this._currentTrack = null; | ||
1108 | 142 | this._canRepeat = false; | ||
1109 | 143 | this._state = AudioState.Stopped; | ||
1110 | 144 | this.createAudioElement(); | ||
1111 | 145 | }; | ||
1112 | 146 | |||
1113 | 147 | /** | ||
1114 | 148 | * Call all listeners associated with this event | ||
1115 | 149 | * @private | ||
1116 | 150 | * @param {object} event - The event that was emitted | ||
1117 | 151 | */ | ||
1118 | 152 | AudioPlayer.prototype._callListener = function (event) { | ||
1119 | 153 | if (this._eventListeners.hasOwnProperty(event.type)) { | ||
1120 | 154 | this._eventListeners[event.type].forEach(function (listener) { | ||
1121 | 155 | listener(event); | ||
1122 | 156 | }); | ||
1123 | 157 | } | ||
1124 | 158 | else { | ||
1125 | 159 | console.warn("Received unknown event \"" + event.type + "\", doing nothing."); | ||
1126 | 160 | } | ||
1127 | 161 | }; | ||
1128 | 162 | |||
1129 | 163 | /** | ||
1130 | 164 | * Create the <audio> element that is used to play the audio | ||
1131 | 165 | */ | ||
1132 | 166 | AudioPlayer.prototype.createAudioElement = function () { | ||
1133 | 167 | this._audioElement = document.createElement("audio"); | ||
1134 | 168 | this._audioElement.addEventListener("ended", this.onEnded); | ||
1135 | 169 | this._audioElement.addEventListener("ended", this._callListener); | ||
1136 | 170 | this._audioElement.addEventListener("timeupdate", this._callListener); | ||
1137 | 171 | this._audioElement.addEventListener("volumechange", this._callListener); | ||
1138 | 172 | this._audioElement.addEventListener("durationchange", this._callListener); | ||
1139 | 173 | this._audioElement.addEventListener("loadeddata", this._callListener); | ||
1140 | 174 | document.addEventListener("complete", function(event) { | ||
1141 | 175 | document.body.appendChild(this._audioElement); | ||
1142 | 176 | }); | ||
1143 | 177 | }; | ||
1144 | 178 | AudioPlayer.prototype.addEventListener = function (eventType, listener) { | ||
1145 | 179 | this._eventListeners[eventType] = this._eventListeners[eventType] || []; | ||
1146 | 180 | this._eventListeners[eventType].push(listener); | ||
1147 | 181 | }; | ||
1148 | 182 | AudioPlayer.prototype.onEnded = function (event) { | ||
1149 | 183 | this.nextTrack(); | ||
1150 | 184 | }; | ||
1151 | 185 | AudioPlayer.prototype.setCanRepeat = function (canRepeat) { | ||
1152 | 186 | this._canRepeat = canRepeat; | ||
1153 | 187 | }; | ||
1154 | 188 | AudioPlayer.prototype.clearTracks = function () { | ||
1155 | 189 | this._playlist = []; | ||
1156 | 190 | }; | ||
1157 | 191 | AudioPlayer.prototype.addTrack = function (track) { | ||
1158 | 192 | this._playlist.push(track); | ||
1159 | 193 | }; | ||
1160 | 194 | AudioPlayer.prototype.nextTrack = function () { | ||
1161 | 195 | if (!!this._currentTrack) { | ||
1162 | 196 | var trackIndex = this._playlist.indexOf(this._currentTrack); | ||
1163 | 197 | if ((trackIndex + 1 >= this._playlist.length) && this._canRepeat) { | ||
1164 | 198 | this.play(this._playlist[0]); | ||
1165 | 199 | } | ||
1166 | 200 | else if (trackIndex + 1 < this._playlist.length) { | ||
1167 | 201 | this.play(this._playlist[trackIndex + 1]); | ||
1168 | 202 | } | ||
1169 | 203 | else { | ||
1170 | 204 | this.stop(); | ||
1171 | 205 | } | ||
1172 | 206 | } | ||
1173 | 207 | else if (this._playlist.length > 0) { | ||
1174 | 208 | this.play(this._playlist[0]); | ||
1175 | 209 | } | ||
1176 | 210 | else { | ||
1177 | 211 | console.warn("No tracks in playlist, doing nothing."); | ||
1178 | 212 | } | ||
1179 | 213 | }; | ||
1180 | 214 | AudioPlayer.prototype.play = function () { | ||
1181 | 215 | if (arguments.length > 0) { | ||
1182 | 216 | this._currentTrack = arguments[0]; | ||
1183 | 217 | this._audioElement.src = this._currentTrack; | ||
1184 | 218 | this._audioElement.play(); | ||
1185 | 219 | this._state = AudioState.Playing; | ||
1186 | 220 | } | ||
1187 | 221 | else if (this._state == AudioState.Paused) { | ||
1188 | 222 | this._audioElement.play(); | ||
1189 | 223 | this._state = AudioState.Playing; | ||
1190 | 224 | } | ||
1191 | 225 | else { | ||
1192 | 226 | console.warn("No track currently paused and no track specified, doing nothing."); | ||
1193 | 227 | } | ||
1194 | 228 | }; | ||
1195 | 229 | |||
1196 | 230 | /** | ||
1197 | 231 | * Pause | ||
1198 | 232 | */ | ||
1199 | 233 | AudioPlayer.prototype.pause = function () { | ||
1200 | 234 | this._audioElement.pause(); | ||
1201 | 235 | this._state = AudioState.Paused; | ||
1202 | 236 | }; | ||
1203 | 237 | |||
1204 | 238 | /** | ||
1205 | 239 | * Stop playing | ||
1206 | 240 | */ | ||
1207 | 241 | AudioPlayer.prototype.stop = function () { | ||
1208 | 242 | this._audioElement.pause(); | ||
1209 | 243 | this._audioElement.src = ""; | ||
1210 | 244 | this._state = AudioState.Stopped; | ||
1211 | 245 | }; | ||
1212 | 246 | |||
1213 | 247 | /** | ||
1214 | 248 | * The Display object is what we use from OpenLP | ||
1215 | 249 | */ | ||
1216 | 250 | var Display = { | ||
1217 | 251 | _slides: {}, | ||
1218 | 252 | _revealConfig: { | ||
1219 | 253 | margin: 0.0, | ||
1220 | 254 | minScale: 1.0, | ||
1221 | 255 | maxScale: 1.0, | ||
1222 | 256 | controls: false, | ||
1223 | 257 | progress: false, | ||
1224 | 258 | history: false, | ||
1225 | 259 | overview: false, | ||
1226 | 260 | center: false, | ||
1227 | 261 | help: false, | ||
1228 | 262 | transition: "none", | ||
1229 | 263 | backgroundTransition: "none", | ||
1230 | 264 | viewDistance: 9999, | ||
1231 | 265 | width: "100%", | ||
1232 | 266 | height: "100%" | ||
1233 | 267 | }, | ||
1234 | 268 | /** | ||
1235 | 269 | * Start up reveal and do any other initialisation | ||
1236 | 270 | */ | ||
1237 | 271 | init: function () { | ||
1238 | 272 | Reveal.initialize(this._revealConfig); | ||
1239 | 273 | }, | ||
1240 | 274 | /** | ||
1241 | 275 | * Reinitialise Reveal | ||
1242 | 276 | */ | ||
1243 | 277 | reinit: function () { | ||
1244 | 278 | Reveal.reinitialize(); | ||
1245 | 279 | }, | ||
1246 | 280 | /** | ||
1247 | 281 | * Set the transition type | ||
1248 | 282 | * @param {string} transitionType - Can be one of "none", "fade", "slide", "convex", "concave", "zoom" | ||
1249 | 283 | */ | ||
1250 | 284 | setTransition: function (transitionType) { | ||
1251 | 285 | Reveal.configure({"transition": transitionType}); | ||
1252 | 286 | }, | ||
1253 | 287 | /** | ||
1254 | 288 | * Clear the current list of slides | ||
1255 | 289 | */ | ||
1256 | 290 | clearSlides: function () { | ||
1257 | 291 | $(".slides")[0].innerHTML = ""; | ||
1258 | 292 | this._slides = {}; | ||
1259 | 293 | }, | ||
1260 | 294 | /** | ||
1261 | 295 | * Checks if the present slide content fits within the slide | ||
1262 | 296 | */ | ||
1263 | 297 | doesContentFit: function () { | ||
1264 | 298 | console.debug("scrollHeight: " + $(".slides")[0].scrollHeight + ", clientHeight: " + $(".slides")[0].clientHeight); | ||
1265 | 299 | return $(".slides")[0].clientHeight >= $(".slides")[0].scrollHeight; | ||
1266 | 300 | }, | ||
1267 | 301 | /** | ||
1268 | 302 | * Generate the OpenLP startup splashscreen | ||
1269 | 303 | * @param {string} bg_color - The background color | ||
1270 | 304 | * @param {string} image - Path to the splash image | ||
1271 | 305 | */ | ||
1272 | 306 | setStartupSplashScreen: function(bg_color, image) { | ||
1273 | 307 | Display.clearSlides(); | ||
1274 | 308 | var globalBackground = $("#global-background")[0]; | ||
1275 | 309 | globalBackground.style.cssText = ""; | ||
1276 | 310 | globalBackground.style.setProperty("background", bg_color); | ||
1277 | 311 | var slidesDiv = $(".slides")[0]; | ||
1278 | 312 | var section = document.createElement("section"); | ||
1279 | 313 | section.setAttribute("id", 0); | ||
1280 | 314 | section.setAttribute("data-background", bg_color); | ||
1281 | 315 | section.setAttribute("style", "height: 100%; width: 100%; position: relative;"); | ||
1282 | 316 | var img = document.createElement('img'); | ||
1283 | 317 | img.src = image; | ||
1284 | 318 | img.setAttribute("style", "position: absolute; top: 0; bottom: 0; left: 0; right: 0; margin: auto;"); | ||
1285 | 319 | section.appendChild(img); | ||
1286 | 320 | slidesDiv.appendChild(section); | ||
1287 | 321 | Display._slides['0'] = 0; | ||
1288 | 322 | Display.reinit(); | ||
1289 | 323 | }, | ||
1290 | 324 | /** | ||
1291 | 325 | * Set fullscreen image from path | ||
1292 | 326 | * @param {string} bg_color - The background color | ||
1293 | 327 | * @param {string} image - Path to the image | ||
1294 | 328 | */ | ||
1295 | 329 | setFullscreenImage: function(bg_color, image) { | ||
1296 | 330 | Display.clearSlides(); | ||
1297 | 331 | var globalBackground = $("#global-background")[0]; | ||
1298 | 332 | globalBackground.style.cssText = ""; | ||
1299 | 333 | globalBackground.style.setProperty("background", bg_color); | ||
1300 | 334 | var slidesDiv = $(".slides")[0]; | ||
1301 | 335 | var section = document.createElement("section"); | ||
1302 | 336 | section.setAttribute("id", 0); | ||
1303 | 337 | section.setAttribute("data-background", bg_color); | ||
1304 | 338 | section.setAttribute("style", "height: 100%; width: 100%;"); | ||
1305 | 339 | var img = document.createElement('img'); | ||
1306 | 340 | img.src = image; | ||
1307 | 341 | img.setAttribute("style", "height: 100%; width: 100%"); | ||
1308 | 342 | section.appendChild(img); | ||
1309 | 343 | slidesDiv.appendChild(section); | ||
1310 | 344 | Display._slides['0'] = 0; | ||
1311 | 345 | Display.reinit(); | ||
1312 | 346 | }, | ||
1313 | 347 | /** | ||
1314 | 348 | * Set fullscreen image from base64 data | ||
1315 | 349 | * @param {string} bg_color - The background color | ||
1316 | 350 | * @param {string} image - Path to the image | ||
1317 | 351 | */ | ||
1318 | 352 | setFullscreenImageFromData: function(bg_color, image_data) { | ||
1319 | 353 | Display.clearSlides(); | ||
1320 | 354 | var globalBackground = $("#global-background")[0]; | ||
1321 | 355 | globalBackground.style.cssText = ""; | ||
1322 | 356 | globalBackground.style.setProperty("background", bg_color); | ||
1323 | 357 | var slidesDiv = $(".slides")[0]; | ||
1324 | 358 | var section = document.createElement("section"); | ||
1325 | 359 | section.setAttribute("id", 0); | ||
1326 | 360 | section.setAttribute("data-background", bg_color); | ||
1327 | 361 | section.setAttribute("style", "height: 100%; width: 100%;"); | ||
1328 | 362 | var img = document.createElement('img'); | ||
1329 | 363 | img.src = 'data:image/png;base64,' + image_data; | ||
1330 | 364 | img.setAttribute("style", "height: 100%; width: 100%"); | ||
1331 | 365 | section.appendChild(img); | ||
1332 | 366 | slidesDiv.appendChild(section); | ||
1333 | 367 | Display._slides['0'] = 0; | ||
1334 | 368 | Display.reinit(); | ||
1335 | 369 | }, | ||
1336 | 370 | /** | ||
1337 | 371 | * Display an alert | ||
1338 | 372 | * @param {string} text - The alert text | ||
1339 | 373 | * @param {int} location - The location of the text (top, middle or bottom) | ||
1340 | 374 | */ | ||
1341 | 375 | alert: function (text, location) { | ||
1342 | 376 | console.debug(" alert text: " + text, ", location: " + location); | ||
1343 | 377 | /* | ||
1344 | 378 | * The implementation should show an alert. | ||
1345 | 379 | * It should be able to handle receiving a new alert before a previous one is "finished", basically queueing it. | ||
1346 | 380 | */ | ||
1347 | 381 | return; | ||
1348 | 382 | }, | ||
1349 | 383 | |||
1350 | 384 | /** | ||
1351 | 385 | * Add a slides. If the slide exists but the HTML is different, update the slide. | ||
1352 | 386 | * @param {string} verse - The verse number, e.g. "v1" | ||
1353 | 387 | * @param {string} text - The HTML for the verse, e.g. "line1<br>line2" | ||
1354 | 388 | * @param {string} footer_text - The HTML for the footer" | ||
1355 | 389 | * @param {bool} [reinit=true] - Re-initialize Reveal. Defaults to true. | ||
1356 | 390 | */ | ||
1357 | 391 | addTextSlide: function (verse, text, footer_text) { | ||
1358 | 392 | var html = _prepareText(text); | ||
1359 | 393 | if (this._slides.hasOwnProperty(verse)) { | ||
1360 | 394 | var slide = $("#" + verse)[0]; | ||
1361 | 395 | if (slide.innerHTML != html) { | ||
1362 | 396 | slide.innerHTML = html; | ||
1363 | 397 | } | ||
1364 | 398 | } | ||
1365 | 399 | else { | ||
1366 | 400 | var slidesDiv = $(".slides")[0]; | ||
1367 | 401 | var slide = document.createElement("section"); | ||
1368 | 402 | slide.setAttribute("id", verse); | ||
1369 | 403 | slide.innerHTML = html; | ||
1370 | 404 | slidesDiv.appendChild(slide); | ||
1371 | 405 | var slides = $(".slides > section"); | ||
1372 | 406 | this._slides[verse] = slides.length - 1; | ||
1373 | 407 | |||
1374 | 408 | console.debug(" footer_text: " + footer_text); | ||
1375 | 409 | |||
1376 | 410 | var footerDiv = $(".footer")[0]; | ||
1377 | 411 | footerDiv.innerHTML = footer_text; | ||
1378 | 412 | } | ||
1379 | 413 | if ((arguments.length > 3) && (arguments[3] === true)) { | ||
1380 | 414 | this.reinit(); | ||
1381 | 415 | } | ||
1382 | 416 | else if (arguments.length == 3) { | ||
1383 | 417 | this.reinit(); | ||
1384 | 418 | } | ||
1385 | 419 | }, | ||
1386 | 420 | /** | ||
1387 | 421 | * Set text slides. | ||
1388 | 422 | * @param {Object[]} slides - A list of slides to add as JS objects: {"verse": "v1", "text": "line 1\nline2"} | ||
1389 | 423 | */ | ||
1390 | 424 | setTextSlides: function (slides) { | ||
1391 | 425 | Display.clearSlides(); | ||
1392 | 426 | slides.forEach(function (slide) { | ||
1393 | 427 | Display.addTextSlide(slide.verse, slide.text, slide.footer, false); | ||
1394 | 428 | }); | ||
1395 | 429 | Display.reinit(); | ||
1396 | 430 | Display.goToSlide(0); | ||
1397 | 431 | }, | ||
1398 | 432 | /** | ||
1399 | 433 | * Set image slides | ||
1400 | 434 | * @param {Object[]} slides - A list of images to add as JS objects [{"path": "url/to/file"}] | ||
1401 | 435 | */ | ||
1402 | 436 | setImageSlides: function (slides) { | ||
1403 | 437 | Display.clearSlides(); | ||
1404 | 438 | var slidesDiv = $(".slides")[0]; | ||
1405 | 439 | slides.forEach(function (slide, index) { | ||
1406 | 440 | var section = document.createElement("section"); | ||
1407 | 441 | section.setAttribute("id", index); | ||
1408 | 442 | section.setAttribute("data-background", "#000"); | ||
1409 | 443 | var img = document.createElement('img'); | ||
1410 | 444 | img.src = slide["path"]; | ||
1411 | 445 | img.setAttribute("style", "height: 100%; width: 100%;"); | ||
1412 | 446 | section.appendChild(img); | ||
1413 | 447 | slidesDiv.appendChild(section); | ||
1414 | 448 | Display._slides[index.toString()] = index; | ||
1415 | 449 | }); | ||
1416 | 450 | Display.reinit(); | ||
1417 | 451 | }, | ||
1418 | 452 | /** | ||
1419 | 453 | * Set a video | ||
1420 | 454 | * @param {Object} video - The video to show as a JS object: {"path": "url/to/file"} | ||
1421 | 455 | */ | ||
1422 | 456 | setVideo: function (video) { | ||
1423 | 457 | this.clearSlides(); | ||
1424 | 458 | var section = document.createElement("section"); | ||
1425 | 459 | section.setAttribute("data-background", "#000"); | ||
1426 | 460 | var videoElement = document.createElement("video"); | ||
1427 | 461 | videoElement.src = video["path"]; | ||
1428 | 462 | videoElement.preload = "auto"; | ||
1429 | 463 | videoElement.setAttribute("id", "video"); | ||
1430 | 464 | videoElement.setAttribute("style", "height: 100%; width: 100%;"); | ||
1431 | 465 | videoElement.autoplay = false; | ||
1432 | 466 | // All the update methods below are Python functions, hence not camelCase | ||
1433 | 467 | videoElement.addEventListener("durationchange", function (event) { | ||
1434 | 468 | mediaWatcher.update_duration(event.target.duration); | ||
1435 | 469 | }); | ||
1436 | 470 | videoElement.addEventListener("timeupdate", function (event) { | ||
1437 | 471 | mediaWatcher.update_progress(event.target.currentTime); | ||
1438 | 472 | }); | ||
1439 | 473 | videoElement.addEventListener("volumeupdate", function (event) { | ||
1440 | 474 | mediaWatcher.update_volume(event.target.volume); | ||
1441 | 475 | }); | ||
1442 | 476 | videoElement.addEventListener("ratechange", function (event) { | ||
1443 | 477 | mediaWatcher.update_playback_rate(event.target.playbackRate); | ||
1444 | 478 | }); | ||
1445 | 479 | videoElement.addEventListener("ended", function (event) { | ||
1446 | 480 | mediaWatcher.has_ended(event.target.ended); | ||
1447 | 481 | }); | ||
1448 | 482 | videoElement.addEventListener("muted", function (event) { | ||
1449 | 483 | mediaWatcher.has_muted(event.target.muted); | ||
1450 | 484 | }); | ||
1451 | 485 | section.appendChild(videoElement); | ||
1452 | 486 | $(".slides")[0].appendChild(section); | ||
1453 | 487 | this.reinit(); | ||
1454 | 488 | }, | ||
1455 | 489 | /** | ||
1456 | 490 | * Play a video | ||
1457 | 491 | */ | ||
1458 | 492 | playVideo: function () { | ||
1459 | 493 | if ($("#video").length == 1) { | ||
1460 | 494 | $("#video")[0].play(); | ||
1461 | 495 | } | ||
1462 | 496 | }, | ||
1463 | 497 | /** | ||
1464 | 498 | * Pause a video | ||
1465 | 499 | */ | ||
1466 | 500 | pauseVideo: function () { | ||
1467 | 501 | if ($("#video").length == 1) { | ||
1468 | 502 | $("#video")[0].pause(); | ||
1469 | 503 | } | ||
1470 | 504 | }, | ||
1471 | 505 | /** | ||
1472 | 506 | * Stop a video | ||
1473 | 507 | */ | ||
1474 | 508 | stopVideo: function () { | ||
1475 | 509 | if ($("#video").length == 1) { | ||
1476 | 510 | $("#video")[0].pause(); | ||
1477 | 511 | $("#video")[0].currentTime = 0.0; | ||
1478 | 512 | } | ||
1479 | 513 | }, | ||
1480 | 514 | /** | ||
1481 | 515 | * Go to a particular time in a video | ||
1482 | 516 | * @param seconds The position in seconds to seek to | ||
1483 | 517 | */ | ||
1484 | 518 | seekVideo: function (seconds) { | ||
1485 | 519 | if ($("#video").length == 1) { | ||
1486 | 520 | $("#video")[0].currentTime = seconds; | ||
1487 | 521 | } | ||
1488 | 522 | }, | ||
1489 | 523 | /** | ||
1490 | 524 | * Set the playback rate of a video | ||
1491 | 525 | * @param rate A Double of the rate. 1.0 => 100% speed, 0.75 => 75% speed, 1.25 => 125% speed, etc. | ||
1492 | 526 | */ | ||
1493 | 527 | setPlaybackRate: function (rate) { | ||
1494 | 528 | if ($("#video").length == 1) { | ||
1495 | 529 | $("#video")[0].playbackRate = rate; | ||
1496 | 530 | } | ||
1497 | 531 | }, | ||
1498 | 532 | /** | ||
1499 | 533 | * Set the volume | ||
1500 | 534 | * @param level The volume level from 0 to 100. | ||
1501 | 535 | */ | ||
1502 | 536 | setVideoVolume: function (level) { | ||
1503 | 537 | if ($("#video").length == 1) { | ||
1504 | 538 | $("#video")[0].volume = level / 100.0; | ||
1505 | 539 | } | ||
1506 | 540 | }, | ||
1507 | 541 | /** | ||
1508 | 542 | * Mute the volume | ||
1509 | 543 | */ | ||
1510 | 544 | toggleVideoMute: function () { | ||
1511 | 545 | if ($("#video").length == 1) { | ||
1512 | 546 | $("#video")[0].muted = !$("#video")[0].muted; | ||
1513 | 547 | } | ||
1514 | 548 | }, | ||
1515 | 549 | /** | ||
1516 | 550 | * Clear the background audio playlist | ||
1517 | 551 | */ | ||
1518 | 552 | clearPlaylist: function () { | ||
1519 | 553 | if ($("#background-audio").length == 1) { | ||
1520 | 554 | var audio = $("#background-audio")[0]; | ||
1521 | 555 | /* audio.playList */ | ||
1522 | 556 | } | ||
1523 | 557 | }, | ||
1524 | 558 | /** | ||
1525 | 559 | * Add background audio | ||
1526 | 560 | * @param files The list of files as objects in an array | ||
1527 | 561 | */ | ||
1528 | 562 | addBackgroundAudio: function (files) { | ||
1529 | 563 | }, | ||
1530 | 564 | /** | ||
1531 | 565 | * Go to a slide. | ||
1532 | 566 | * @param slide The slide number or name, e.g. "v1", 0 | ||
1533 | 567 | */ | ||
1534 | 568 | goToSlide: function (slide) { | ||
1535 | 569 | if (this._slides.hasOwnProperty(slide)) { | ||
1536 | 570 | Reveal.slide(this._slides[slide]); | ||
1537 | 571 | } | ||
1538 | 572 | else { | ||
1539 | 573 | Reveal.slide(slide); | ||
1540 | 574 | } | ||
1541 | 575 | }, | ||
1542 | 576 | /** | ||
1543 | 577 | * Go to the next slide in the list | ||
1544 | 578 | */ | ||
1545 | 579 | next: Reveal.next, | ||
1546 | 580 | /** | ||
1547 | 581 | * Go to the previous slide in the list | ||
1548 | 582 | */ | ||
1549 | 583 | prev: Reveal.prev, | ||
1550 | 584 | /** | ||
1551 | 585 | * Blank the screen | ||
1552 | 586 | */ | ||
1553 | 587 | blankToBlack: function () { | ||
1554 | 588 | if (!Reveal.isPaused()) { | ||
1555 | 589 | Reveal.togglePause(); | ||
1556 | 590 | } | ||
1557 | 591 | // var slidesDiv = $(".slides")[0]; | ||
1558 | 592 | }, | ||
1559 | 593 | /** | ||
1560 | 594 | * Blank to theme | ||
1561 | 595 | */ | ||
1562 | 596 | blankToTheme: function () { | ||
1563 | 597 | var slidesDiv = $(".slides")[0]; | ||
1564 | 598 | slidesDiv.style.visibility = "hidden"; | ||
1565 | 599 | var footerDiv = $(".footer")[0]; | ||
1566 | 600 | footerDiv.style.visibility = "hidden"; | ||
1567 | 601 | if (Reveal.isPaused()) { | ||
1568 | 602 | Reveal.togglePause(); | ||
1569 | 603 | } | ||
1570 | 604 | }, | ||
1571 | 605 | /** | ||
1572 | 606 | * Show the screen | ||
1573 | 607 | */ | ||
1574 | 608 | show: function () { | ||
1575 | 609 | var slidesDiv = $(".slides")[0]; | ||
1576 | 610 | slidesDiv.style.visibility = "visible"; | ||
1577 | 611 | var footerDiv = $(".footer")[0]; | ||
1578 | 612 | footerDiv.style.visibility = "visible"; | ||
1579 | 613 | if (Reveal.isPaused()) { | ||
1580 | 614 | Reveal.togglePause(); | ||
1581 | 615 | } | ||
1582 | 616 | }, | ||
1583 | 617 | /** | ||
1584 | 618 | * Figure out how many lines can fit on a slide given the font size | ||
1585 | 619 | * @param fontSize The font size in pts | ||
1586 | 620 | */ | ||
1587 | 621 | calculateLineCount: function (fontSize) { | ||
1588 | 622 | var p = $(".slides > section > p"); | ||
1589 | 623 | if (p.length == 0) { | ||
1590 | 624 | this.addSlide("v1", "Arky arky"); | ||
1591 | 625 | p = $(".slides > section > p"); | ||
1592 | 626 | } | ||
1593 | 627 | p = p[0]; | ||
1594 | 628 | p.style.fontSize = "" + fontSize + "pt"; | ||
1595 | 629 | var d = $(".slides")[0]; | ||
1596 | 630 | var lh = parseFloat(_getStyle(p, "line-height")); | ||
1597 | 631 | var dh = parseFloat(_getStyle(d, "height")); | ||
1598 | 632 | return Math.floor(dh / lh); | ||
1599 | 633 | }, | ||
1600 | 634 | setTheme: function (theme) { | ||
1601 | 635 | this._theme = theme; | ||
1602 | 636 | var slidesDiv = $(".slides") | ||
1603 | 637 | // Set the background | ||
1604 | 638 | var globalBackground = $("#global-background")[0]; | ||
1605 | 639 | var backgroundStyle = {}; | ||
1606 | 640 | var backgroundHtml = ""; | ||
1607 | 641 | switch (theme.background_type) { | ||
1608 | 642 | case BackgroundType.Transparent: | ||
1609 | 643 | backgroundStyle["background"] = "transparent"; | ||
1610 | 644 | break; | ||
1611 | 645 | case BackgroundType.Solid: | ||
1612 | 646 | backgroundStyle["background"] = theme.background_color; | ||
1613 | 647 | break; | ||
1614 | 648 | case BackgroundType.Gradient: | ||
1615 | 649 | switch (theme.background_direction) { | ||
1616 | 650 | case GradientType.Horizontal: | ||
1617 | 651 | backgroundStyle["background"] = _buildLinearGradient("left top", "left bottom", | ||
1618 | 652 | theme.background_start_color, | ||
1619 | 653 | theme.background_end_color); | ||
1620 | 654 | break; | ||
1621 | 655 | case GradientType.Vertical: | ||
1622 | 656 | backgroundStyle["background"] = _buildLinearGradient("left top", "right top", | ||
1623 | 657 | theme.background_start_color, | ||
1624 | 658 | theme.background_end_color); | ||
1625 | 659 | break; | ||
1626 | 660 | case GradientType.LeftTop: | ||
1627 | 661 | backgroundStyle["background"] = _buildLinearGradient("left top", "right bottom", | ||
1628 | 662 | theme.background_start_color, | ||
1629 | 663 | theme.background_end_color); | ||
1630 | 664 | break; | ||
1631 | 665 | case GradientType.LeftBottom: | ||
1632 | 666 | backgroundStyle["background"] = _buildLinearGradient("left bottom", "right top", | ||
1633 | 667 | theme.background_start_color, | ||
1634 | 668 | theme.background_end_color); | ||
1635 | 669 | break; | ||
1636 | 670 | case GradientType.Circular: | ||
1637 | 671 | backgroundStyle["background"] = _buildRadialGradient(window.innerWidth / 2, theme.background_start_color, | ||
1638 | 672 | theme.background_end_color); | ||
1639 | 673 | break; | ||
1640 | 674 | default: | ||
1641 | 675 | backgroundStyle["background"] = "#000"; | ||
1642 | 676 | } | ||
1643 | 677 | break; | ||
1644 | 678 | case BackgroundType.Image: | ||
1645 | 679 | background_filename = _pathToString(theme.background_filename); | ||
1646 | 680 | backgroundStyle["background-image"] = "url('file://" + background_filename + "')"; | ||
1647 | 681 | break; | ||
1648 | 682 | case BackgroundType.Video: | ||
1649 | 683 | background_filename = _pathToString(theme.background_filename); | ||
1650 | 684 | backgroundStyle["background-color"] = theme.background_border_color; | ||
1651 | 685 | backgroundHtml = "<video loop autoplay muted><source src='file://" + background_filename + "'></video>"; | ||
1652 | 686 | break; | ||
1653 | 687 | default: | ||
1654 | 688 | backgroundStyle["background"] = "#000"; | ||
1655 | 689 | } | ||
1656 | 690 | globalBackground.style.cssText = ""; | ||
1657 | 691 | for (var key in backgroundStyle) { | ||
1658 | 692 | if (backgroundStyle.hasOwnProperty(key)) { | ||
1659 | 693 | globalBackground.style.setProperty(key, backgroundStyle[key]); | ||
1660 | 694 | } | ||
1661 | 695 | } | ||
1662 | 696 | if (!!backgroundHtml) { | ||
1663 | 697 | globalBackground.innerHTML = backgroundHtml; | ||
1664 | 698 | } | ||
1665 | 699 | // set up the main area | ||
1666 | 700 | mainStyle = { | ||
1667 | 701 | "word-wrap": "break-word", | ||
1668 | 702 | /*"margin": "0", | ||
1669 | 703 | "padding": "0"*/ | ||
1670 | 704 | }; | ||
1671 | 705 | if (!!theme.font_main_outline) { | ||
1672 | 706 | mainStyle["-webkit-text-stroke"] = "" + theme.font_main_outline_size + "pt " + | ||
1673 | 707 | theme.font_main_outline_color; | ||
1674 | 708 | mainStyle["-webkit-text-fill-color"] = theme.font_main_color; | ||
1675 | 709 | } | ||
1676 | 710 | mainStyle["font-family"] = theme.font_main_name; | ||
1677 | 711 | mainStyle["font-size"] = "" + theme.font_main_size + "pt"; | ||
1678 | 712 | mainStyle["font-style"] = !!theme.font_main_italics ? "italic" : ""; | ||
1679 | 713 | mainStyle["font-weight"] = !!theme.font_main_bold ? "bold" : ""; | ||
1680 | 714 | mainStyle["color"] = theme.font_main_color; | ||
1681 | 715 | mainStyle["line-height"] = "" + (100 + theme.font_main_line_adjustment) + "%"; | ||
1682 | 716 | mainStyle["text-align"] = theme.display_horizontal_align; | ||
1683 | 717 | if (theme.display_horizontal_align != HorizontalAlign.Justify) { | ||
1684 | 718 | mainStyle["white-space"] = "pre-wrap"; | ||
1685 | 719 | } | ||
1686 | 720 | mainStyle["vertical-align"] = theme.display_vertical_align; | ||
1687 | 721 | if (theme.hasOwnProperty('font_main_shadow_size')) { | ||
1688 | 722 | mainStyle["text-shadow"] = theme.font_main_shadow_color + " " + theme.font_main_shadow_size + "px " + | ||
1689 | 723 | theme.font_main_shadow_size + "px"; | ||
1690 | 724 | } | ||
1691 | 725 | mainStyle["padding-bottom"] = theme.display_vertical_align == VerticalAlign.Bottom ? "0.5em" : "0"; | ||
1692 | 726 | mainStyle["padding-left"] = !!theme.font_main_outline ? "" + (theme.font_main_outline_size * 2) + "pt" : "0"; | ||
1693 | 727 | // These need to be fixed, in the Python they use a width passed in as a parameter | ||
1694 | 728 | mainStyle["position"] = "absolute"; | ||
1695 | 729 | mainStyle["width"] = "" + (window.innerWidth - (theme.font_main_outline_size * 4)) + "px"; | ||
1696 | 730 | mainStyle["height"] = "" + (window.innerHeight - (theme.font_main_outline_size * 4)) + "px"; | ||
1697 | 731 | mainStyle["left"] = "" + theme.font_main_x + "px"; | ||
1698 | 732 | mainStyle["top"] = "" + theme.font_main_y + "px"; | ||
1699 | 733 | var slidesDiv = $(".slides")[0]; | ||
1700 | 734 | slidesDiv.style.cssText = ""; | ||
1701 | 735 | for (var key in mainStyle) { | ||
1702 | 736 | if (mainStyle.hasOwnProperty(key)) { | ||
1703 | 737 | slidesDiv.style.setProperty(key, mainStyle[key]); | ||
1704 | 738 | } | ||
1705 | 739 | } | ||
1706 | 740 | // Set up the footer | ||
1707 | 741 | footerStyle = { | ||
1708 | 742 | "text-align": "left" | ||
1709 | 743 | }; | ||
1710 | 744 | footerStyle["position"] = "absolute"; | ||
1711 | 745 | footerStyle["left"] = "" + theme.font_footer_x + "px"; | ||
1712 | 746 | footerStyle["top"] = "" + theme.font_footer_y + "px"; | ||
1713 | 747 | footerStyle["bottom"] = "" + (window.innerHeight - theme.font_footer_y - theme.font_footer_height) + "px"; | ||
1714 | 748 | footerStyle["width"] = "" + theme.font_footer_width + "px"; | ||
1715 | 749 | footerStyle["font-family"] = theme.font_footer_name; | ||
1716 | 750 | footerStyle["font-size"] = "" + theme.font_footer_size + "pt"; | ||
1717 | 751 | footerStyle["color"] = theme.font_footer_color; | ||
1718 | 752 | footerStyle["white-space"] = theme.font_footer_wrap ? "normal" : "nowrap"; | ||
1719 | 753 | var footer = $(".footer")[0]; | ||
1720 | 754 | footer.style.cssText = ""; | ||
1721 | 755 | for (var key in footerStyle) { | ||
1722 | 756 | if (footerStyle.hasOwnProperty(key)) { | ||
1723 | 757 | footer.style.setProperty(key, footerStyle[key]); | ||
1724 | 758 | } | ||
1725 | 759 | } | ||
1726 | 760 | }, | ||
1727 | 761 | /** | ||
1728 | 762 | * Return the video types supported by the video tag | ||
1729 | 763 | */ | ||
1730 | 764 | getVideoTypes: function () { | ||
1731 | 765 | var videoElement = document.createElement('video'); | ||
1732 | 766 | var videoTypes = []; | ||
1733 | 767 | if (videoElement.canPlayType('video/mp4; codecs="mp4v.20.8"') == "probably" || | ||
1734 | 768 | videoElement.canPlayType('video/mp4; codecs="avc1.42E01E"') == "pobably" || | ||
1735 | 769 | videoElement.canPlayType('video/mp4; codecs="avc1.42E01E, mp4a.40.2"') == "probably") { | ||
1736 | 770 | videoTypes.push(['video/mp4', '*.mp4']); | ||
1737 | 771 | } | ||
1738 | 772 | if (videoElement.canPlayType('video/ogg; codecs="theora"') == "probably") { | ||
1739 | 773 | videoTypes.push(['video/ogg', '*.ogv']); | ||
1740 | 774 | } | ||
1741 | 775 | if (videoElement.canPlayType('video/webm; codecs="vp8, vorbis"') == "probably") { | ||
1742 | 776 | videoTypes.push(['video/webm', '*.webm']); | ||
1743 | 777 | } | ||
1744 | 778 | return videoTypes; | ||
1745 | 779 | }, | ||
1746 | 780 | /** | ||
1747 | 781 | * Sets the scale of the page - used to make preview widgets scale | ||
1748 | 782 | */ | ||
1749 | 783 | setScale: function(scale) { | ||
1750 | 784 | document.body.style.zoom = scale+"%"; | ||
1751 | 785 | } | ||
1752 | 786 | }; | ||
1753 | 787 | new QWebChannel(qt.webChannelTransport, function (channel) { | ||
1754 | 788 | window.mediaWatcher = channel.objects.mediaWatcher; | ||
1755 | 789 | }); | ||
1756 | 0 | 790 | ||
1757 | === added file 'openlp/core/display/html/openlp-splash-screen.png' | |||
1758 | 1 | Binary files openlp/core/display/html/openlp-splash-screen.png 1970-01-01 00:00:00 +0000 and openlp/core/display/html/openlp-splash-screen.png 2019-02-12 20:56:20 +0000 differ | 791 | Binary files openlp/core/display/html/openlp-splash-screen.png 1970-01-01 00:00:00 +0000 and openlp/core/display/html/openlp-splash-screen.png 2019-02-12 20:56:20 +0000 differ |
1759 | === added file 'openlp/core/display/html/reveal.css' | |||
1760 | --- openlp/core/display/html/reveal.css 1970-01-01 00:00:00 +0000 | |||
1761 | +++ openlp/core/display/html/reveal.css 2019-02-12 20:56:20 +0000 | |||
1762 | @@ -0,0 +1,1591 @@ | |||
1763 | 1 | /*! | ||
1764 | 2 | * reveal.js | ||
1765 | 3 | * http://revealjs.com | ||
1766 | 4 | * MIT licensed | ||
1767 | 5 | * | ||
1768 | 6 | * Copyright (C) 2018 Hakim El Hattab, http://hakim.se | ||
1769 | 7 | */ | ||
1770 | 8 | /********************************************* | ||
1771 | 9 | * RESET STYLES | ||
1772 | 10 | *********************************************/ | ||
1773 | 11 | html, body, .reveal div, .reveal span, .reveal applet, .reveal object, .reveal iframe, | ||
1774 | 12 | .reveal h1, .reveal h2, .reveal h3, .reveal h4, .reveal h5, .reveal h6, .reveal p, .reveal blockquote, .reveal pre, | ||
1775 | 13 | .reveal a, .reveal abbr, .reveal acronym, .reveal address, .reveal big, .reveal cite, .reveal code, | ||
1776 | 14 | .reveal del, .reveal dfn, .reveal em, .reveal img, .reveal ins, .reveal kbd, .reveal q, .reveal s, .reveal samp, | ||
1777 | 15 | .reveal small, .reveal strike, .reveal strong, .reveal sub, .reveal sup, .reveal tt, .reveal var, | ||
1778 | 16 | .reveal b, .reveal u, .reveal center, | ||
1779 | 17 | .reveal dl, .reveal dt, .reveal dd, .reveal ol, .reveal ul, .reveal li, | ||
1780 | 18 | .reveal fieldset, .reveal form, .reveal label, .reveal legend, | ||
1781 | 19 | .reveal table, .reveal caption, .reveal tbody, .reveal tfoot, .reveal thead, .reveal tr, .reveal th, .reveal td, | ||
1782 | 20 | .reveal article, .reveal aside, .reveal canvas, .reveal details, .reveal embed, | ||
1783 | 21 | .reveal figure, .reveal figcaption, .reveal footer, .reveal header, .reveal hgroup, | ||
1784 | 22 | .reveal menu, .reveal nav, .reveal output, .reveal ruby, .reveal section, .reveal summary, | ||
1785 | 23 | .reveal time, .reveal mark, .reveal audio, .reveal video { | ||
1786 | 24 | margin: 0; | ||
1787 | 25 | padding: 0; | ||
1788 | 26 | border: 0; | ||
1789 | 27 | font-size: 100%; | ||
1790 | 28 | font: inherit; | ||
1791 | 29 | vertical-align: baseline; } | ||
1792 | 30 | |||
1793 | 31 | .reveal article, .reveal aside, .reveal details, .reveal figcaption, .reveal figure, | ||
1794 | 32 | .reveal footer, .reveal header, .reveal hgroup, .reveal menu, .reveal nav, .reveal section { | ||
1795 | 33 | display: block; } | ||
1796 | 34 | |||
1797 | 35 | /********************************************* | ||
1798 | 36 | * GLOBAL STYLES | ||
1799 | 37 | *********************************************/ | ||
1800 | 38 | html, | ||
1801 | 39 | body { | ||
1802 | 40 | width: 100%; | ||
1803 | 41 | height: 100%; | ||
1804 | 42 | overflow: hidden; } | ||
1805 | 43 | |||
1806 | 44 | body { | ||
1807 | 45 | position: relative; | ||
1808 | 46 | line-height: 1; | ||
1809 | 47 | background-color: #fff; | ||
1810 | 48 | color: #000; } | ||
1811 | 49 | |||
1812 | 50 | /********************************************* | ||
1813 | 51 | * VIEW FRAGMENTS | ||
1814 | 52 | *********************************************/ | ||
1815 | 53 | .reveal .slides section .fragment { | ||
1816 | 54 | opacity: 0; | ||
1817 | 55 | visibility: hidden; | ||
1818 | 56 | transition: all .2s ease; } | ||
1819 | 57 | .reveal .slides section .fragment.visible { | ||
1820 | 58 | opacity: 1; | ||
1821 | 59 | visibility: inherit; } | ||
1822 | 60 | |||
1823 | 61 | .reveal .slides section .fragment.grow { | ||
1824 | 62 | opacity: 1; | ||
1825 | 63 | visibility: inherit; } | ||
1826 | 64 | .reveal .slides section .fragment.grow.visible { | ||
1827 | 65 | -webkit-transform: scale(1.3); | ||
1828 | 66 | transform: scale(1.3); } | ||
1829 | 67 | |||
1830 | 68 | .reveal .slides section .fragment.shrink { | ||
1831 | 69 | opacity: 1; | ||
1832 | 70 | visibility: inherit; } | ||
1833 | 71 | .reveal .slides section .fragment.shrink.visible { | ||
1834 | 72 | -webkit-transform: scale(0.7); | ||
1835 | 73 | transform: scale(0.7); } | ||
1836 | 74 | |||
1837 | 75 | .reveal .slides section .fragment.zoom-in { | ||
1838 | 76 | -webkit-transform: scale(0.1); | ||
1839 | 77 | transform: scale(0.1); } | ||
1840 | 78 | .reveal .slides section .fragment.zoom-in.visible { | ||
1841 | 79 | -webkit-transform: none; | ||
1842 | 80 | transform: none; } | ||
1843 | 81 | |||
1844 | 82 | .reveal .slides section .fragment.fade-out { | ||
1845 | 83 | opacity: 1; | ||
1846 | 84 | visibility: inherit; } | ||
1847 | 85 | .reveal .slides section .fragment.fade-out.visible { | ||
1848 | 86 | opacity: 0; | ||
1849 | 87 | visibility: hidden; } | ||
1850 | 88 | |||
1851 | 89 | .reveal .slides section .fragment.semi-fade-out { | ||
1852 | 90 | opacity: 1; | ||
1853 | 91 | visibility: inherit; } | ||
1854 | 92 | .reveal .slides section .fragment.semi-fade-out.visible { | ||
1855 | 93 | opacity: 0.5; | ||
1856 | 94 | visibility: inherit; } | ||
1857 | 95 | |||
1858 | 96 | .reveal .slides section .fragment.strike { | ||
1859 | 97 | opacity: 1; | ||
1860 | 98 | visibility: inherit; } | ||
1861 | 99 | .reveal .slides section .fragment.strike.visible { | ||
1862 | 100 | text-decoration: line-through; } | ||
1863 | 101 | |||
1864 | 102 | .reveal .slides section .fragment.fade-up { | ||
1865 | 103 | -webkit-transform: translate(0, 20%); | ||
1866 | 104 | transform: translate(0, 20%); } | ||
1867 | 105 | .reveal .slides section .fragment.fade-up.visible { | ||
1868 | 106 | -webkit-transform: translate(0, 0); | ||
1869 | 107 | transform: translate(0, 0); } | ||
1870 | 108 | |||
1871 | 109 | .reveal .slides section .fragment.fade-down { | ||
1872 | 110 | -webkit-transform: translate(0, -20%); | ||
1873 | 111 | transform: translate(0, -20%); } | ||
1874 | 112 | .reveal .slides section .fragment.fade-down.visible { | ||
1875 | 113 | -webkit-transform: translate(0, 0); | ||
1876 | 114 | transform: translate(0, 0); } | ||
1877 | 115 | |||
1878 | 116 | .reveal .slides section .fragment.fade-right { | ||
1879 | 117 | -webkit-transform: translate(-20%, 0); | ||
1880 | 118 | transform: translate(-20%, 0); } | ||
1881 | 119 | .reveal .slides section .fragment.fade-right.visible { | ||
1882 | 120 | -webkit-transform: translate(0, 0); | ||
1883 | 121 | transform: translate(0, 0); } | ||
1884 | 122 | |||
1885 | 123 | .reveal .slides section .fragment.fade-left { | ||
1886 | 124 | -webkit-transform: translate(20%, 0); | ||
1887 | 125 | transform: translate(20%, 0); } | ||
1888 | 126 | .reveal .slides section .fragment.fade-left.visible { | ||
1889 | 127 | -webkit-transform: translate(0, 0); | ||
1890 | 128 | transform: translate(0, 0); } | ||
1891 | 129 | |||
1892 | 130 | .reveal .slides section .fragment.fade-in-then-out, | ||
1893 | 131 | .reveal .slides section .fragment.current-visible { | ||
1894 | 132 | opacity: 0; | ||
1895 | 133 | visibility: hidden; } | ||
1896 | 134 | .reveal .slides section .fragment.fade-in-then-out.current-fragment, | ||
1897 | 135 | .reveal .slides section .fragment.current-visible.current-fragment { | ||
1898 | 136 | opacity: 1; | ||
1899 | 137 | visibility: inherit; } | ||
1900 | 138 | |||
1901 | 139 | .reveal .slides section .fragment.fade-in-then-semi-out { | ||
1902 | 140 | opacity: 0; | ||
1903 | 141 | visibility: hidden; } | ||
1904 | 142 | .reveal .slides section .fragment.fade-in-then-semi-out.visible { | ||
1905 | 143 | opacity: 0.5; | ||
1906 | 144 | visibility: inherit; } | ||
1907 | 145 | .reveal .slides section .fragment.fade-in-then-semi-out.current-fragment { | ||
1908 | 146 | opacity: 1; | ||
1909 | 147 | visibility: inherit; } | ||
1910 | 148 | |||
1911 | 149 | .reveal .slides section .fragment.highlight-red, | ||
1912 | 150 | .reveal .slides section .fragment.highlight-current-red, | ||
1913 | 151 | .reveal .slides section .fragment.highlight-green, | ||
1914 | 152 | .reveal .slides section .fragment.highlight-current-green, | ||
1915 | 153 | .reveal .slides section .fragment.highlight-blue, | ||
1916 | 154 | .reveal .slides section .fragment.highlight-current-blue { | ||
1917 | 155 | opacity: 1; | ||
1918 | 156 | visibility: inherit; } | ||
1919 | 157 | |||
1920 | 158 | .reveal .slides section .fragment.highlight-red.visible { | ||
1921 | 159 | color: #ff2c2d; } | ||
1922 | 160 | |||
1923 | 161 | .reveal .slides section .fragment.highlight-green.visible { | ||
1924 | 162 | color: #17ff2e; } | ||
1925 | 163 | |||
1926 | 164 | .reveal .slides section .fragment.highlight-blue.visible { | ||
1927 | 165 | color: #1b91ff; } | ||
1928 | 166 | |||
1929 | 167 | .reveal .slides section .fragment.highlight-current-red.current-fragment { | ||
1930 | 168 | color: #ff2c2d; } | ||
1931 | 169 | |||
1932 | 170 | .reveal .slides section .fragment.highlight-current-green.current-fragment { | ||
1933 | 171 | color: #17ff2e; } | ||
1934 | 172 | |||
1935 | 173 | .reveal .slides section .fragment.highlight-current-blue.current-fragment { | ||
1936 | 174 | color: #1b91ff; } | ||
1937 | 175 | |||
1938 | 176 | /********************************************* | ||
1939 | 177 | * DEFAULT ELEMENT STYLES | ||
1940 | 178 | *********************************************/ | ||
1941 | 179 | /* Fixes issue in Chrome where italic fonts did not appear when printing to PDF */ | ||
1942 | 180 | .reveal:after { | ||
1943 | 181 | content: ''; | ||
1944 | 182 | font-style: italic; } | ||
1945 | 183 | |||
1946 | 184 | .reveal iframe { | ||
1947 | 185 | z-index: 1; } | ||
1948 | 186 | |||
1949 | 187 | /** Prevents layering issues in certain browser/transition combinations */ | ||
1950 | 188 | .reveal a { | ||
1951 | 189 | position: relative; } | ||
1952 | 190 | |||
1953 | 191 | .reveal .stretch { | ||
1954 | 192 | max-width: none; | ||
1955 | 193 | max-height: none; } | ||
1956 | 194 | |||
1957 | 195 | .reveal pre.stretch code { | ||
1958 | 196 | height: 100%; | ||
1959 | 197 | max-height: 100%; | ||
1960 | 198 | box-sizing: border-box; } | ||
1961 | 199 | |||
1962 | 200 | /********************************************* | ||
1963 | 201 | * CONTROLS | ||
1964 | 202 | *********************************************/ | ||
1965 | 203 | @-webkit-keyframes bounce-right { | ||
1966 | 204 | 0%, 10%, 25%, 40%, 50% { | ||
1967 | 205 | -webkit-transform: translateX(0); | ||
1968 | 206 | transform: translateX(0); } | ||
1969 | 207 | 20% { | ||
1970 | 208 | -webkit-transform: translateX(10px); | ||
1971 | 209 | transform: translateX(10px); } | ||
1972 | 210 | 30% { | ||
1973 | 211 | -webkit-transform: translateX(-5px); | ||
1974 | 212 | transform: translateX(-5px); } } | ||
1975 | 213 | @keyframes bounce-right { | ||
1976 | 214 | 0%, 10%, 25%, 40%, 50% { | ||
1977 | 215 | -webkit-transform: translateX(0); | ||
1978 | 216 | transform: translateX(0); } | ||
1979 | 217 | 20% { | ||
1980 | 218 | -webkit-transform: translateX(10px); | ||
1981 | 219 | transform: translateX(10px); } | ||
1982 | 220 | 30% { | ||
1983 | 221 | -webkit-transform: translateX(-5px); | ||
1984 | 222 | transform: translateX(-5px); } } | ||
1985 | 223 | |||
1986 | 224 | @-webkit-keyframes bounce-down { | ||
1987 | 225 | 0%, 10%, 25%, 40%, 50% { | ||
1988 | 226 | -webkit-transform: translateY(0); | ||
1989 | 227 | transform: translateY(0); } | ||
1990 | 228 | 20% { | ||
1991 | 229 | -webkit-transform: translateY(10px); | ||
1992 | 230 | transform: translateY(10px); } | ||
1993 | 231 | 30% { | ||
1994 | 232 | -webkit-transform: translateY(-5px); | ||
1995 | 233 | transform: translateY(-5px); } } | ||
1996 | 234 | |||
1997 | 235 | @keyframes bounce-down { | ||
1998 | 236 | 0%, 10%, 25%, 40%, 50% { | ||
1999 | 237 | -webkit-transform: translateY(0); | ||
2000 | 238 | transform: translateY(0); } | ||
2001 | 239 | 20% { | ||
2002 | 240 | -webkit-transform: translateY(10px); | ||
2003 | 241 | transform: translateY(10px); } | ||
2004 | 242 | 30% { | ||
2005 | 243 | -webkit-transform: translateY(-5px); | ||
2006 | 244 | transform: translateY(-5px); } } | ||
2007 | 245 | |||
2008 | 246 | .reveal .controls { | ||
2009 | 247 | display: none; | ||
2010 | 248 | position: absolute; | ||
2011 | 249 | top: auto; | ||
2012 | 250 | bottom: 12px; | ||
2013 | 251 | right: 12px; | ||
2014 | 252 | left: auto; | ||
2015 | 253 | z-index: 1; | ||
2016 | 254 | color: #000; | ||
2017 | 255 | pointer-events: none; | ||
2018 | 256 | font-size: 10px; } | ||
2019 | 257 | .reveal .controls button { | ||
2020 | 258 | position: absolute; | ||
2021 | 259 | padding: 0; | ||
2022 | 260 | background-color: transparent; | ||
2023 | 261 | border: 0; | ||
2024 | 262 | outline: 0; | ||
2025 | 263 | cursor: pointer; | ||
2026 | 264 | color: currentColor; | ||
2027 | 265 | -webkit-transform: scale(0.9999); | ||
2028 | 266 | transform: scale(0.9999); | ||
2029 | 267 | transition: color 0.2s ease, opacity 0.2s ease, -webkit-transform 0.2s ease; | ||
2030 | 268 | transition: color 0.2s ease, opacity 0.2s ease, transform 0.2s ease; | ||
2031 | 269 | z-index: 2; | ||
2032 | 270 | pointer-events: auto; | ||
2033 | 271 | font-size: inherit; | ||
2034 | 272 | visibility: hidden; | ||
2035 | 273 | opacity: 0; | ||
2036 | 274 | -webkit-appearance: none; | ||
2037 | 275 | -webkit-tap-highlight-color: transparent; } | ||
2038 | 276 | .reveal .controls .controls-arrow:before, | ||
2039 | 277 | .reveal .controls .controls-arrow:after { | ||
2040 | 278 | content: ''; | ||
2041 | 279 | position: absolute; | ||
2042 | 280 | top: 0; | ||
2043 | 281 | left: 0; | ||
2044 | 282 | width: 2.6em; | ||
2045 | 283 | height: 0.5em; | ||
2046 | 284 | border-radius: 0.25em; | ||
2047 | 285 | background-color: currentColor; | ||
2048 | 286 | transition: all 0.15s ease, background-color 0.8s ease; | ||
2049 | 287 | -webkit-transform-origin: 0.2em 50%; | ||
2050 | 288 | transform-origin: 0.2em 50%; | ||
2051 | 289 | will-change: transform; } | ||
2052 | 290 | .reveal .controls .controls-arrow { | ||
2053 | 291 | position: relative; | ||
2054 | 292 | width: 3.6em; | ||
2055 | 293 | height: 3.6em; } | ||
2056 | 294 | .reveal .controls .controls-arrow:before { | ||
2057 | 295 | -webkit-transform: translateX(0.5em) translateY(1.55em) rotate(45deg); | ||
2058 | 296 | transform: translateX(0.5em) translateY(1.55em) rotate(45deg); } | ||
2059 | 297 | .reveal .controls .controls-arrow:after { | ||
2060 | 298 | -webkit-transform: translateX(0.5em) translateY(1.55em) rotate(-45deg); | ||
2061 | 299 | transform: translateX(0.5em) translateY(1.55em) rotate(-45deg); } | ||
2062 | 300 | .reveal .controls .controls-arrow:hover:before { | ||
2063 | 301 | -webkit-transform: translateX(0.5em) translateY(1.55em) rotate(40deg); | ||
2064 | 302 | transform: translateX(0.5em) translateY(1.55em) rotate(40deg); } | ||
2065 | 303 | .reveal .controls .controls-arrow:hover:after { | ||
2066 | 304 | -webkit-transform: translateX(0.5em) translateY(1.55em) rotate(-40deg); | ||
2067 | 305 | transform: translateX(0.5em) translateY(1.55em) rotate(-40deg); } | ||
2068 | 306 | .reveal .controls .controls-arrow:active:before { | ||
2069 | 307 | -webkit-transform: translateX(0.5em) translateY(1.55em) rotate(36deg); | ||
2070 | 308 | transform: translateX(0.5em) translateY(1.55em) rotate(36deg); } | ||
2071 | 309 | .reveal .controls .controls-arrow:active:after { | ||
2072 | 310 | -webkit-transform: translateX(0.5em) translateY(1.55em) rotate(-36deg); | ||
2073 | 311 | transform: translateX(0.5em) translateY(1.55em) rotate(-36deg); } | ||
2074 | 312 | .reveal .controls .navigate-left { | ||
2075 | 313 | right: 6.4em; | ||
2076 | 314 | bottom: 3.2em; | ||
2077 | 315 | -webkit-transform: translateX(-10px); | ||
2078 | 316 | transform: translateX(-10px); } | ||
2079 | 317 | .reveal .controls .navigate-right { | ||
2080 | 318 | right: 0; | ||
2081 | 319 | bottom: 3.2em; | ||
2082 | 320 | -webkit-transform: translateX(10px); | ||
2083 | 321 | transform: translateX(10px); } | ||
2084 | 322 | .reveal .controls .navigate-right .controls-arrow { | ||
2085 | 323 | -webkit-transform: rotate(180deg); | ||
2086 | 324 | transform: rotate(180deg); } | ||
2087 | 325 | .reveal .controls .navigate-right.highlight { | ||
2088 | 326 | -webkit-animation: bounce-right 2s 50 both ease-out; | ||
2089 | 327 | animation: bounce-right 2s 50 both ease-out; } | ||
2090 | 328 | .reveal .controls .navigate-up { | ||
2091 | 329 | right: 3.2em; | ||
2092 | 330 | bottom: 6.4em; | ||
2093 | 331 | -webkit-transform: translateY(-10px); | ||
2094 | 332 | transform: translateY(-10px); } | ||
2095 | 333 | .reveal .controls .navigate-up .controls-arrow { | ||
2096 | 334 | -webkit-transform: rotate(90deg); | ||
2097 | 335 | transform: rotate(90deg); } | ||
2098 | 336 | .reveal .controls .navigate-down { | ||
2099 | 337 | right: 3.2em; | ||
2100 | 338 | bottom: 0; | ||
2101 | 339 | -webkit-transform: translateY(10px); | ||
2102 | 340 | transform: translateY(10px); } | ||
2103 | 341 | .reveal .controls .navigate-down .controls-arrow { | ||
2104 | 342 | -webkit-transform: rotate(-90deg); | ||
2105 | 343 | transform: rotate(-90deg); } | ||
2106 | 344 | .reveal .controls .navigate-down.highlight { | ||
2107 | 345 | -webkit-animation: bounce-down 2s 50 both ease-out; | ||
2108 | 346 | animation: bounce-down 2s 50 both ease-out; } | ||
2109 | 347 | .reveal .controls[data-controls-back-arrows="faded"] .navigate-left.enabled, | ||
2110 | 348 | .reveal .controls[data-controls-back-arrows="faded"] .navigate-up.enabled { | ||
2111 | 349 | opacity: 0.3; } | ||
2112 | 350 | .reveal .controls[data-controls-back-arrows="faded"] .navigate-left.enabled:hover, | ||
2113 | 351 | .reveal .controls[data-controls-back-arrows="faded"] .navigate-up.enabled:hover { | ||
2114 | 352 | opacity: 1; } | ||
2115 | 353 | .reveal .controls[data-controls-back-arrows="hidden"] .navigate-left.enabled, | ||
2116 | 354 | .reveal .controls[data-controls-back-arrows="hidden"] .navigate-up.enabled { | ||
2117 | 355 | opacity: 0; | ||
2118 | 356 | visibility: hidden; } | ||
2119 | 357 | .reveal .controls .enabled { | ||
2120 | 358 | visibility: visible; | ||
2121 | 359 | opacity: 0.9; | ||
2122 | 360 | cursor: pointer; | ||
2123 | 361 | -webkit-transform: none; | ||
2124 | 362 | transform: none; } | ||
2125 | 363 | .reveal .controls .enabled.fragmented { | ||
2126 | 364 | opacity: 0.5; } | ||
2127 | 365 | .reveal .controls .enabled:hover, | ||
2128 | 366 | .reveal .controls .enabled.fragmented:hover { | ||
2129 | 367 | opacity: 1; } | ||
2130 | 368 | |||
2131 | 369 | .reveal:not(.has-vertical-slides) .controls .navigate-left { | ||
2132 | 370 | bottom: 1.4em; | ||
2133 | 371 | right: 5.5em; } | ||
2134 | 372 | |||
2135 | 373 | .reveal:not(.has-vertical-slides) .controls .navigate-right { | ||
2136 | 374 | bottom: 1.4em; | ||
2137 | 375 | right: 0.5em; } | ||
2138 | 376 | |||
2139 | 377 | .reveal:not(.has-horizontal-slides) .controls .navigate-up { | ||
2140 | 378 | right: 1.4em; | ||
2141 | 379 | bottom: 5em; } | ||
2142 | 380 | |||
2143 | 381 | .reveal:not(.has-horizontal-slides) .controls .navigate-down { | ||
2144 | 382 | right: 1.4em; | ||
2145 | 383 | bottom: 0.5em; } | ||
2146 | 384 | |||
2147 | 385 | .reveal.has-dark-background .controls { | ||
2148 | 386 | color: #fff; } | ||
2149 | 387 | |||
2150 | 388 | .reveal.has-light-background .controls { | ||
2151 | 389 | color: #000; } | ||
2152 | 390 | |||
2153 | 391 | .reveal.no-hover .controls .controls-arrow:hover:before, | ||
2154 | 392 | .reveal.no-hover .controls .controls-arrow:active:before { | ||
2155 | 393 | -webkit-transform: translateX(0.5em) translateY(1.55em) rotate(45deg); | ||
2156 | 394 | transform: translateX(0.5em) translateY(1.55em) rotate(45deg); } | ||
2157 | 395 | |||
2158 | 396 | .reveal.no-hover .controls .controls-arrow:hover:after, | ||
2159 | 397 | .reveal.no-hover .controls .controls-arrow:active:after { | ||
2160 | 398 | -webkit-transform: translateX(0.5em) translateY(1.55em) rotate(-45deg); | ||
2161 | 399 | transform: translateX(0.5em) translateY(1.55em) rotate(-45deg); } | ||
2162 | 400 | |||
2163 | 401 | @media screen and (min-width: 500px) { | ||
2164 | 402 | .reveal .controls[data-controls-layout="edges"] { | ||
2165 | 403 | top: 0; | ||
2166 | 404 | right: 0; | ||
2167 | 405 | bottom: 0; | ||
2168 | 406 | left: 0; } | ||
2169 | 407 | .reveal .controls[data-controls-layout="edges"] .navigate-left, | ||
2170 | 408 | .reveal .controls[data-controls-layout="edges"] .navigate-right, | ||
2171 | 409 | .reveal .controls[data-controls-layout="edges"] .navigate-up, | ||
2172 | 410 | .reveal .controls[data-controls-layout="edges"] .navigate-down { | ||
2173 | 411 | bottom: auto; | ||
2174 | 412 | right: auto; } | ||
2175 | 413 | .reveal .controls[data-controls-layout="edges"] .navigate-left { | ||
2176 | 414 | top: 50%; | ||
2177 | 415 | left: 8px; | ||
2178 | 416 | margin-top: -1.8em; } | ||
2179 | 417 | .reveal .controls[data-controls-layout="edges"] .navigate-right { | ||
2180 | 418 | top: 50%; | ||
2181 | 419 | right: 8px; | ||
2182 | 420 | margin-top: -1.8em; } | ||
2183 | 421 | .reveal .controls[data-controls-layout="edges"] .navigate-up { | ||
2184 | 422 | top: 8px; | ||
2185 | 423 | left: 50%; | ||
2186 | 424 | margin-left: -1.8em; } | ||
2187 | 425 | .reveal .controls[data-controls-layout="edges"] .navigate-down { | ||
2188 | 426 | bottom: 8px; | ||
2189 | 427 | left: 50%; | ||
2190 | 428 | margin-left: -1.8em; } } | ||
2191 | 429 | |||
2192 | 430 | /********************************************* | ||
2193 | 431 | * PROGRESS BAR | ||
2194 | 432 | *********************************************/ | ||
2195 | 433 | .reveal .progress { | ||
2196 | 434 | position: absolute; | ||
2197 | 435 | display: none; | ||
2198 | 436 | height: 3px; | ||
2199 | 437 | width: 100%; | ||
2200 | 438 | bottom: 0; | ||
2201 | 439 | left: 0; | ||
2202 | 440 | z-index: 10; | ||
2203 | 441 | background-color: rgba(0, 0, 0, 0.2); | ||
2204 | 442 | color: #fff; } | ||
2205 | 443 | |||
2206 | 444 | .reveal .progress:after { | ||
2207 | 445 | content: ''; | ||
2208 | 446 | display: block; | ||
2209 | 447 | position: absolute; | ||
2210 | 448 | height: 10px; | ||
2211 | 449 | width: 100%; | ||
2212 | 450 | top: -10px; } | ||
2213 | 451 | |||
2214 | 452 | .reveal .progress span { | ||
2215 | 453 | display: block; | ||
2216 | 454 | height: 100%; | ||
2217 | 455 | width: 0px; | ||
2218 | 456 | background-color: currentColor; | ||
2219 | 457 | transition: width 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985); } | ||
2220 | 458 | |||
2221 | 459 | /********************************************* | ||
2222 | 460 | * SLIDE NUMBER | ||
2223 | 461 | *********************************************/ | ||
2224 | 462 | .reveal .slide-number { | ||
2225 | 463 | position: absolute; | ||
2226 | 464 | display: block; | ||
2227 | 465 | right: 8px; | ||
2228 | 466 | bottom: 8px; | ||
2229 | 467 | z-index: 31; | ||
2230 | 468 | font-family: Helvetica, sans-serif; | ||
2231 | 469 | font-size: 12px; | ||
2232 | 470 | line-height: 1; | ||
2233 | 471 | color: #fff; | ||
2234 | 472 | background-color: rgba(0, 0, 0, 0.4); | ||
2235 | 473 | padding: 5px; } | ||
2236 | 474 | |||
2237 | 475 | .reveal .slide-number a { | ||
2238 | 476 | color: currentColor; } | ||
2239 | 477 | |||
2240 | 478 | .reveal .slide-number-delimiter { | ||
2241 | 479 | margin: 0 3px; } | ||
2242 | 480 | |||
2243 | 481 | /********************************************* | ||
2244 | 482 | * SLIDES | ||
2245 | 483 | *********************************************/ | ||
2246 | 484 | .reveal { | ||
2247 | 485 | position: relative; | ||
2248 | 486 | width: 100%; | ||
2249 | 487 | height: 100%; | ||
2250 | 488 | overflow: hidden; | ||
2251 | 489 | -ms-touch-action: none; | ||
2252 | 490 | touch-action: none; } | ||
2253 | 491 | |||
2254 | 492 | @media only screen and (orientation: landscape) { | ||
2255 | 493 | .reveal.ua-iphone { | ||
2256 | 494 | position: fixed; } } | ||
2257 | 495 | |||
2258 | 496 | .reveal .slides { | ||
2259 | 497 | position: absolute; | ||
2260 | 498 | width: 100%; | ||
2261 | 499 | height: 100%; | ||
2262 | 500 | top: 0; | ||
2263 | 501 | right: 0; | ||
2264 | 502 | bottom: 0; | ||
2265 | 503 | left: 0; | ||
2266 | 504 | margin: auto; | ||
2267 | 505 | pointer-events: none; | ||
2268 | 506 | overflow: visible; | ||
2269 | 507 | z-index: 1; | ||
2270 | 508 | text-align: center; | ||
2271 | 509 | -webkit-perspective: 600px; | ||
2272 | 510 | perspective: 600px; | ||
2273 | 511 | -webkit-perspective-origin: 50% 40%; | ||
2274 | 512 | perspective-origin: 50% 40%; } | ||
2275 | 513 | |||
2276 | 514 | .reveal .slides > section { | ||
2277 | 515 | -ms-perspective: 600px; } | ||
2278 | 516 | |||
2279 | 517 | .reveal .slides > section, | ||
2280 | 518 | .reveal .slides > section > section { | ||
2281 | 519 | display: none; | ||
2282 | 520 | position: absolute; | ||
2283 | 521 | width: 100%; | ||
2284 | 522 | padding: 20px 0px; | ||
2285 | 523 | pointer-events: auto; | ||
2286 | 524 | z-index: 10; | ||
2287 | 525 | -webkit-transform-style: flat; | ||
2288 | 526 | transform-style: flat; | ||
2289 | 527 | transition: -webkit-transform-origin 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985), -webkit-transform 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985), visibility 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985), opacity 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985); | ||
2290 | 528 | transition: transform-origin 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985), transform 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985), visibility 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985), opacity 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985); } | ||
2291 | 529 | |||
2292 | 530 | /* Global transition speed settings */ | ||
2293 | 531 | .reveal[data-transition-speed="fast"] .slides section { | ||
2294 | 532 | transition-duration: 400ms; } | ||
2295 | 533 | |||
2296 | 534 | .reveal[data-transition-speed="slow"] .slides section { | ||
2297 | 535 | transition-duration: 1200ms; } | ||
2298 | 536 | |||
2299 | 537 | /* Slide-specific transition speed overrides */ | ||
2300 | 538 | .reveal .slides section[data-transition-speed="fast"] { | ||
2301 | 539 | transition-duration: 400ms; } | ||
2302 | 540 | |||
2303 | 541 | .reveal .slides section[data-transition-speed="slow"] { | ||
2304 | 542 | transition-duration: 1200ms; } | ||
2305 | 543 | |||
2306 | 544 | .reveal .slides > section.stack { | ||
2307 | 545 | padding-top: 0; | ||
2308 | 546 | padding-bottom: 0; | ||
2309 | 547 | pointer-events: none; } | ||
2310 | 548 | |||
2311 | 549 | .reveal .slides > section.present, | ||
2312 | 550 | .reveal .slides > section > section.present { | ||
2313 | 551 | display: block; | ||
2314 | 552 | z-index: 11; | ||
2315 | 553 | opacity: 1; } | ||
2316 | 554 | |||
2317 | 555 | .reveal .slides > section:empty, | ||
2318 | 556 | .reveal .slides > section > section:empty, | ||
2319 | 557 | .reveal .slides > section[data-background-interactive], | ||
2320 | 558 | .reveal .slides > section > section[data-background-interactive] { | ||
2321 | 559 | pointer-events: none; } | ||
2322 | 560 | |||
2323 | 561 | .reveal.center, | ||
2324 | 562 | .reveal.center .slides, | ||
2325 | 563 | .reveal.center .slides section { | ||
2326 | 564 | min-height: 0 !important; } | ||
2327 | 565 | |||
2328 | 566 | /* Don't allow interaction with invisible slides */ | ||
2329 | 567 | .reveal .slides > section.future, | ||
2330 | 568 | .reveal .slides > section > section.future, | ||
2331 | 569 | .reveal .slides > section.past, | ||
2332 | 570 | .reveal .slides > section > section.past { | ||
2333 | 571 | pointer-events: none; } | ||
2334 | 572 | |||
2335 | 573 | .reveal.overview .slides > section, | ||
2336 | 574 | .reveal.overview .slides > section > section { | ||
2337 | 575 | pointer-events: auto; } | ||
2338 | 576 | |||
2339 | 577 | .reveal .slides > section.past, | ||
2340 | 578 | .reveal .slides > section.future, | ||
2341 | 579 | .reveal .slides > section > section.past, | ||
2342 | 580 | .reveal .slides > section > section.future { | ||
2343 | 581 | opacity: 0; } | ||
2344 | 582 | |||
2345 | 583 | /********************************************* | ||
2346 | 584 | * Mixins for readability of transitions | ||
2347 | 585 | *********************************************/ | ||
2348 | 586 | /********************************************* | ||
2349 | 587 | * SLIDE TRANSITION | ||
2350 | 588 | * Aliased 'linear' for backwards compatibility | ||
2351 | 589 | *********************************************/ | ||
2352 | 590 | .reveal.slide section { | ||
2353 | 591 | -webkit-backface-visibility: hidden; | ||
2354 | 592 | backface-visibility: hidden; } | ||
2355 | 593 | |||
2356 | 594 | .reveal .slides > section[data-transition=slide].past, | ||
2357 | 595 | .reveal .slides > section[data-transition~=slide-out].past, | ||
2358 | 596 | .reveal.slide .slides > section:not([data-transition]).past { | ||
2359 | 597 | -webkit-transform: translate(-150%, 0); | ||
2360 | 598 | transform: translate(-150%, 0); } | ||
2361 | 599 | |||
2362 | 600 | .reveal .slides > section[data-transition=slide].future, | ||
2363 | 601 | .reveal .slides > section[data-transition~=slide-in].future, | ||
2364 | 602 | .reveal.slide .slides > section:not([data-transition]).future { | ||
2365 | 603 | -webkit-transform: translate(150%, 0); | ||
2366 | 604 | transform: translate(150%, 0); } | ||
2367 | 605 | |||
2368 | 606 | .reveal .slides > section > section[data-transition=slide].past, | ||
2369 | 607 | .reveal .slides > section > section[data-transition~=slide-out].past, | ||
2370 | 608 | .reveal.slide .slides > section > section:not([data-transition]).past { | ||
2371 | 609 | -webkit-transform: translate(0, -150%); | ||
2372 | 610 | transform: translate(0, -150%); } | ||
2373 | 611 | |||
2374 | 612 | .reveal .slides > section > section[data-transition=slide].future, | ||
2375 | 613 | .reveal .slides > section > section[data-transition~=slide-in].future, | ||
2376 | 614 | .reveal.slide .slides > section > section:not([data-transition]).future { | ||
2377 | 615 | -webkit-transform: translate(0, 150%); | ||
2378 | 616 | transform: translate(0, 150%); } | ||
2379 | 617 | |||
2380 | 618 | .reveal.linear section { | ||
2381 | 619 | -webkit-backface-visibility: hidden; | ||
2382 | 620 | backface-visibility: hidden; } | ||
2383 | 621 | |||
2384 | 622 | .reveal .slides > section[data-transition=linear].past, | ||
2385 | 623 | .reveal .slides > section[data-transition~=linear-out].past, | ||
2386 | 624 | .reveal.linear .slides > section:not([data-transition]).past { | ||
2387 | 625 | -webkit-transform: translate(-150%, 0); | ||
2388 | 626 | transform: translate(-150%, 0); } | ||
2389 | 627 | |||
2390 | 628 | .reveal .slides > section[data-transition=linear].future, | ||
2391 | 629 | .reveal .slides > section[data-transition~=linear-in].future, | ||
2392 | 630 | .reveal.linear .slides > section:not([data-transition]).future { | ||
2393 | 631 | -webkit-transform: translate(150%, 0); | ||
2394 | 632 | transform: translate(150%, 0); } | ||
2395 | 633 | |||
2396 | 634 | .reveal .slides > section > section[data-transition=linear].past, | ||
2397 | 635 | .reveal .slides > section > section[data-transition~=linear-out].past, | ||
2398 | 636 | .reveal.linear .slides > section > section:not([data-transition]).past { | ||
2399 | 637 | -webkit-transform: translate(0, -150%); | ||
2400 | 638 | transform: translate(0, -150%); } | ||
2401 | 639 | |||
2402 | 640 | .reveal .slides > section > section[data-transition=linear].future, | ||
2403 | 641 | .reveal .slides > section > section[data-transition~=linear-in].future, | ||
2404 | 642 | .reveal.linear .slides > section > section:not([data-transition]).future { | ||
2405 | 643 | -webkit-transform: translate(0, 150%); | ||
2406 | 644 | transform: translate(0, 150%); } | ||
2407 | 645 | |||
2408 | 646 | /********************************************* | ||
2409 | 647 | * CONVEX TRANSITION | ||
2410 | 648 | * Aliased 'default' for backwards compatibility | ||
2411 | 649 | *********************************************/ | ||
2412 | 650 | .reveal .slides section[data-transition=default].stack, | ||
2413 | 651 | .reveal.default .slides section.stack { | ||
2414 | 652 | -webkit-transform-style: preserve-3d; | ||
2415 | 653 | transform-style: preserve-3d; } | ||
2416 | 654 | |||
2417 | 655 | .reveal .slides > section[data-transition=default].past, | ||
2418 | 656 | .reveal .slides > section[data-transition~=default-out].past, | ||
2419 | 657 | .reveal.default .slides > section:not([data-transition]).past { | ||
2420 | 658 | -webkit-transform: translate3d(-100%, 0, 0) rotateY(-90deg) translate3d(-100%, 0, 0); | ||
2421 | 659 | transform: translate3d(-100%, 0, 0) rotateY(-90deg) translate3d(-100%, 0, 0); } | ||
2422 | 660 | |||
2423 | 661 | .reveal .slides > section[data-transition=default].future, | ||
2424 | 662 | .reveal .slides > section[data-transition~=default-in].future, | ||
2425 | 663 | .reveal.default .slides > section:not([data-transition]).future { | ||
2426 | 664 | -webkit-transform: translate3d(100%, 0, 0) rotateY(90deg) translate3d(100%, 0, 0); | ||
2427 | 665 | transform: translate3d(100%, 0, 0) rotateY(90deg) translate3d(100%, 0, 0); } | ||
2428 | 666 | |||
2429 | 667 | .reveal .slides > section > section[data-transition=default].past, | ||
2430 | 668 | .reveal .slides > section > section[data-transition~=default-out].past, | ||
2431 | 669 | .reveal.default .slides > section > section:not([data-transition]).past { | ||
2432 | 670 | -webkit-transform: translate3d(0, -300px, 0) rotateX(70deg) translate3d(0, -300px, 0); | ||
2433 | 671 | transform: translate3d(0, -300px, 0) rotateX(70deg) translate3d(0, -300px, 0); } | ||
2434 | 672 | |||
2435 | 673 | .reveal .slides > section > section[data-transition=default].future, | ||
2436 | 674 | .reveal .slides > section > section[data-transition~=default-in].future, | ||
2437 | 675 | .reveal.default .slides > section > section:not([data-transition]).future { | ||
2438 | 676 | -webkit-transform: translate3d(0, 300px, 0) rotateX(-70deg) translate3d(0, 300px, 0); | ||
2439 | 677 | transform: translate3d(0, 300px, 0) rotateX(-70deg) translate3d(0, 300px, 0); } | ||
2440 | 678 | |||
2441 | 679 | .reveal .slides section[data-transition=convex].stack, | ||
2442 | 680 | .reveal.convex .slides section.stack { | ||
2443 | 681 | -webkit-transform-style: preserve-3d; | ||
2444 | 682 | transform-style: preserve-3d; } | ||
2445 | 683 | |||
2446 | 684 | .reveal .slides > section[data-transition=convex].past, | ||
2447 | 685 | .reveal .slides > section[data-transition~=convex-out].past, | ||
2448 | 686 | .reveal.convex .slides > section:not([data-transition]).past { | ||
2449 | 687 | -webkit-transform: translate3d(-100%, 0, 0) rotateY(-90deg) translate3d(-100%, 0, 0); | ||
2450 | 688 | transform: translate3d(-100%, 0, 0) rotateY(-90deg) translate3d(-100%, 0, 0); } | ||
2451 | 689 | |||
2452 | 690 | .reveal .slides > section[data-transition=convex].future, | ||
2453 | 691 | .reveal .slides > section[data-transition~=convex-in].future, | ||
2454 | 692 | .reveal.convex .slides > section:not([data-transition]).future { | ||
2455 | 693 | -webkit-transform: translate3d(100%, 0, 0) rotateY(90deg) translate3d(100%, 0, 0); | ||
2456 | 694 | transform: translate3d(100%, 0, 0) rotateY(90deg) translate3d(100%, 0, 0); } | ||
2457 | 695 | |||
2458 | 696 | .reveal .slides > section > section[data-transition=convex].past, | ||
2459 | 697 | .reveal .slides > section > section[data-transition~=convex-out].past, | ||
2460 | 698 | .reveal.convex .slides > section > section:not([data-transition]).past { | ||
2461 | 699 | -webkit-transform: translate3d(0, -300px, 0) rotateX(70deg) translate3d(0, -300px, 0); | ||
2462 | 700 | transform: translate3d(0, -300px, 0) rotateX(70deg) translate3d(0, -300px, 0); } | ||
2463 | 701 | |||
2464 | 702 | .reveal .slides > section > section[data-transition=convex].future, | ||
2465 | 703 | .reveal .slides > section > section[data-transition~=convex-in].future, | ||
2466 | 704 | .reveal.convex .slides > section > section:not([data-transition]).future { | ||
2467 | 705 | -webkit-transform: translate3d(0, 300px, 0) rotateX(-70deg) translate3d(0, 300px, 0); | ||
2468 | 706 | transform: translate3d(0, 300px, 0) rotateX(-70deg) translate3d(0, 300px, 0); } | ||
2469 | 707 | |||
2470 | 708 | /********************************************* | ||
2471 | 709 | * CONCAVE TRANSITION | ||
2472 | 710 | *********************************************/ | ||
2473 | 711 | .reveal .slides section[data-transition=concave].stack, | ||
2474 | 712 | .reveal.concave .slides section.stack { | ||
2475 | 713 | -webkit-transform-style: preserve-3d; | ||
2476 | 714 | transform-style: preserve-3d; } | ||
2477 | 715 | |||
2478 | 716 | .reveal .slides > section[data-transition=concave].past, | ||
2479 | 717 | .reveal .slides > section[data-transition~=concave-out].past, | ||
2480 | 718 | .reveal.concave .slides > section:not([data-transition]).past { | ||
2481 | 719 | -webkit-transform: translate3d(-100%, 0, 0) rotateY(90deg) translate3d(-100%, 0, 0); | ||
2482 | 720 | transform: translate3d(-100%, 0, 0) rotateY(90deg) translate3d(-100%, 0, 0); } | ||
2483 | 721 | |||
2484 | 722 | .reveal .slides > section[data-transition=concave].future, | ||
2485 | 723 | .reveal .slides > section[data-transition~=concave-in].future, | ||
2486 | 724 | .reveal.concave .slides > section:not([data-transition]).future { | ||
2487 | 725 | -webkit-transform: translate3d(100%, 0, 0) rotateY(-90deg) translate3d(100%, 0, 0); | ||
2488 | 726 | transform: translate3d(100%, 0, 0) rotateY(-90deg) translate3d(100%, 0, 0); } | ||
2489 | 727 | |||
2490 | 728 | .reveal .slides > section > section[data-transition=concave].past, | ||
2491 | 729 | .reveal .slides > section > section[data-transition~=concave-out].past, | ||
2492 | 730 | .reveal.concave .slides > section > section:not([data-transition]).past { | ||
2493 | 731 | -webkit-transform: translate3d(0, -80%, 0) rotateX(-70deg) translate3d(0, -80%, 0); | ||
2494 | 732 | transform: translate3d(0, -80%, 0) rotateX(-70deg) translate3d(0, -80%, 0); } | ||
2495 | 733 | |||
2496 | 734 | .reveal .slides > section > section[data-transition=concave].future, | ||
2497 | 735 | .reveal .slides > section > section[data-transition~=concave-in].future, | ||
2498 | 736 | .reveal.concave .slides > section > section:not([data-transition]).future { | ||
2499 | 737 | -webkit-transform: translate3d(0, 80%, 0) rotateX(70deg) translate3d(0, 80%, 0); | ||
2500 | 738 | transform: translate3d(0, 80%, 0) rotateX(70deg) translate3d(0, 80%, 0); } | ||
2501 | 739 | |||
2502 | 740 | /********************************************* | ||
2503 | 741 | * ZOOM TRANSITION | ||
2504 | 742 | *********************************************/ | ||
2505 | 743 | .reveal .slides section[data-transition=zoom], | ||
2506 | 744 | .reveal.zoom .slides section:not([data-transition]) { | ||
2507 | 745 | transition-timing-function: ease; } | ||
2508 | 746 | |||
2509 | 747 | .reveal .slides > section[data-transition=zoom].past, | ||
2510 | 748 | .reveal .slides > section[data-transition~=zoom-out].past, | ||
2511 | 749 | .reveal.zoom .slides > section:not([data-transition]).past { | ||
2512 | 750 | visibility: hidden; | ||
2513 | 751 | -webkit-transform: scale(16); | ||
2514 | 752 | transform: scale(16); } | ||
2515 | 753 | |||
2516 | 754 | .reveal .slides > section[data-transition=zoom].future, | ||
2517 | 755 | .reveal .slides > section[data-transition~=zoom-in].future, | ||
2518 | 756 | .reveal.zoom .slides > section:not([data-transition]).future { | ||
2519 | 757 | visibility: hidden; | ||
2520 | 758 | -webkit-transform: scale(0.2); | ||
2521 | 759 | transform: scale(0.2); } | ||
2522 | 760 | |||
2523 | 761 | .reveal .slides > section > section[data-transition=zoom].past, | ||
2524 | 762 | .reveal .slides > section > section[data-transition~=zoom-out].past, | ||
2525 | 763 | .reveal.zoom .slides > section > section:not([data-transition]).past { | ||
2526 | 764 | -webkit-transform: translate(0, -150%); | ||
2527 | 765 | transform: translate(0, -150%); } | ||
2528 | 766 | |||
2529 | 767 | .reveal .slides > section > section[data-transition=zoom].future, | ||
2530 | 768 | .reveal .slides > section > section[data-transition~=zoom-in].future, | ||
2531 | 769 | .reveal.zoom .slides > section > section:not([data-transition]).future { | ||
2532 | 770 | -webkit-transform: translate(0, 150%); | ||
2533 | 771 | transform: translate(0, 150%); } | ||
2534 | 772 | |||
2535 | 773 | /********************************************* | ||
2536 | 774 | * CUBE TRANSITION | ||
2537 | 775 | * | ||
2538 | 776 | * WARNING: | ||
2539 | 777 | * this is deprecated and will be removed in a | ||
2540 | 778 | * future version. | ||
2541 | 779 | *********************************************/ | ||
2542 | 780 | .reveal.cube .slides { | ||
2543 | 781 | -webkit-perspective: 1300px; | ||
2544 | 782 | perspective: 1300px; } | ||
2545 | 783 | |||
2546 | 784 | .reveal.cube .slides section { | ||
2547 | 785 | padding: 30px; | ||
2548 | 786 | min-height: 700px; | ||
2549 | 787 | -webkit-backface-visibility: hidden; | ||
2550 | 788 | backface-visibility: hidden; | ||
2551 | 789 | box-sizing: border-box; | ||
2552 | 790 | -webkit-transform-style: preserve-3d; | ||
2553 | 791 | transform-style: preserve-3d; } | ||
2554 | 792 | |||
2555 | 793 | .reveal.center.cube .slides section { | ||
2556 | 794 | min-height: 0; } | ||
2557 | 795 | |||
2558 | 796 | .reveal.cube .slides section:not(.stack):before { | ||
2559 | 797 | content: ''; | ||
2560 | 798 | position: absolute; | ||
2561 | 799 | display: block; | ||
2562 | 800 | width: 100%; | ||
2563 | 801 | height: 100%; | ||
2564 | 802 | left: 0; | ||
2565 | 803 | top: 0; | ||
2566 | 804 | background: rgba(0, 0, 0, 0.1); | ||
2567 | 805 | border-radius: 4px; | ||
2568 | 806 | -webkit-transform: translateZ(-20px); | ||
2569 | 807 | transform: translateZ(-20px); } | ||
2570 | 808 | |||
2571 | 809 | .reveal.cube .slides section:not(.stack):after { | ||
2572 | 810 | content: ''; | ||
2573 | 811 | position: absolute; | ||
2574 | 812 | display: block; | ||
2575 | 813 | width: 90%; | ||
2576 | 814 | height: 30px; | ||
2577 | 815 | left: 5%; | ||
2578 | 816 | bottom: 0; | ||
2579 | 817 | background: none; | ||
2580 | 818 | z-index: 1; | ||
2581 | 819 | border-radius: 4px; | ||
2582 | 820 | box-shadow: 0px 95px 25px rgba(0, 0, 0, 0.2); | ||
2583 | 821 | -webkit-transform: translateZ(-90px) rotateX(65deg); | ||
2584 | 822 | transform: translateZ(-90px) rotateX(65deg); } | ||
2585 | 823 | |||
2586 | 824 | .reveal.cube .slides > section.stack { | ||
2587 | 825 | padding: 0; | ||
2588 | 826 | background: none; } | ||
2589 | 827 | |||
2590 | 828 | .reveal.cube .slides > section.past { | ||
2591 | 829 | -webkit-transform-origin: 100% 0%; | ||
2592 | 830 | transform-origin: 100% 0%; | ||
2593 | 831 | -webkit-transform: translate3d(-100%, 0, 0) rotateY(-90deg); | ||
2594 | 832 | transform: translate3d(-100%, 0, 0) rotateY(-90deg); } | ||
2595 | 833 | |||
2596 | 834 | .reveal.cube .slides > section.future { | ||
2597 | 835 | -webkit-transform-origin: 0% 0%; | ||
2598 | 836 | transform-origin: 0% 0%; | ||
2599 | 837 | -webkit-transform: translate3d(100%, 0, 0) rotateY(90deg); | ||
2600 | 838 | transform: translate3d(100%, 0, 0) rotateY(90deg); } | ||
2601 | 839 | |||
2602 | 840 | .reveal.cube .slides > section > section.past { | ||
2603 | 841 | -webkit-transform-origin: 0% 100%; | ||
2604 | 842 | transform-origin: 0% 100%; | ||
2605 | 843 | -webkit-transform: translate3d(0, -100%, 0) rotateX(90deg); | ||
2606 | 844 | transform: translate3d(0, -100%, 0) rotateX(90deg); } | ||
2607 | 845 | |||
2608 | 846 | .reveal.cube .slides > section > section.future { | ||
2609 | 847 | -webkit-transform-origin: 0% 0%; | ||
2610 | 848 | transform-origin: 0% 0%; | ||
2611 | 849 | -webkit-transform: translate3d(0, 100%, 0) rotateX(-90deg); | ||
2612 | 850 | transform: translate3d(0, 100%, 0) rotateX(-90deg); } | ||
2613 | 851 | |||
2614 | 852 | /********************************************* | ||
2615 | 853 | * PAGE TRANSITION | ||
2616 | 854 | * | ||
2617 | 855 | * WARNING: | ||
2618 | 856 | * this is deprecated and will be removed in a | ||
2619 | 857 | * future version. | ||
2620 | 858 | *********************************************/ | ||
2621 | 859 | .reveal.page .slides { | ||
2622 | 860 | -webkit-perspective-origin: 0% 50%; | ||
2623 | 861 | perspective-origin: 0% 50%; | ||
2624 | 862 | -webkit-perspective: 3000px; | ||
2625 | 863 | perspective: 3000px; } | ||
2626 | 864 | |||
2627 | 865 | .reveal.page .slides section { | ||
2628 | 866 | padding: 30px; | ||
2629 | 867 | min-height: 700px; | ||
2630 | 868 | box-sizing: border-box; | ||
2631 | 869 | -webkit-transform-style: preserve-3d; | ||
2632 | 870 | transform-style: preserve-3d; } | ||
2633 | 871 | |||
2634 | 872 | .reveal.page .slides section.past { | ||
2635 | 873 | z-index: 12; } | ||
2636 | 874 | |||
2637 | 875 | .reveal.page .slides section:not(.stack):before { | ||
2638 | 876 | content: ''; | ||
2639 | 877 | position: absolute; | ||
2640 | 878 | display: block; | ||
2641 | 879 | width: 100%; | ||
2642 | 880 | height: 100%; | ||
2643 | 881 | left: 0; | ||
2644 | 882 | top: 0; | ||
2645 | 883 | background: rgba(0, 0, 0, 0.1); | ||
2646 | 884 | -webkit-transform: translateZ(-20px); | ||
2647 | 885 | transform: translateZ(-20px); } | ||
2648 | 886 | |||
2649 | 887 | .reveal.page .slides section:not(.stack):after { | ||
2650 | 888 | content: ''; | ||
2651 | 889 | position: absolute; | ||
2652 | 890 | display: block; | ||
2653 | 891 | width: 90%; | ||
2654 | 892 | height: 30px; | ||
2655 | 893 | left: 5%; | ||
2656 | 894 | bottom: 0; | ||
2657 | 895 | background: none; | ||
2658 | 896 | z-index: 1; | ||
2659 | 897 | border-radius: 4px; | ||
2660 | 898 | box-shadow: 0px 95px 25px rgba(0, 0, 0, 0.2); | ||
2661 | 899 | -webkit-transform: translateZ(-90px) rotateX(65deg); } | ||
2662 | 900 | |||
2663 | 901 | .reveal.page .slides > section.stack { | ||
2664 | 902 | padding: 0; | ||
2665 | 903 | background: none; } | ||
2666 | 904 | |||
2667 | 905 | .reveal.page .slides > section.past { | ||
2668 | 906 | -webkit-transform-origin: 0% 0%; | ||
2669 | 907 | transform-origin: 0% 0%; | ||
2670 | 908 | -webkit-transform: translate3d(-40%, 0, 0) rotateY(-80deg); | ||
2671 | 909 | transform: translate3d(-40%, 0, 0) rotateY(-80deg); } | ||
2672 | 910 | |||
2673 | 911 | .reveal.page .slides > section.future { | ||
2674 | 912 | -webkit-transform-origin: 100% 0%; | ||
2675 | 913 | transform-origin: 100% 0%; | ||
2676 | 914 | -webkit-transform: translate3d(0, 0, 0); | ||
2677 | 915 | transform: translate3d(0, 0, 0); } | ||
2678 | 916 | |||
2679 | 917 | .reveal.page .slides > section > section.past { | ||
2680 | 918 | -webkit-transform-origin: 0% 0%; | ||
2681 | 919 | transform-origin: 0% 0%; | ||
2682 | 920 | -webkit-transform: translate3d(0, -40%, 0) rotateX(80deg); | ||
2683 | 921 | transform: translate3d(0, -40%, 0) rotateX(80deg); } | ||
2684 | 922 | |||
2685 | 923 | .reveal.page .slides > section > section.future { | ||
2686 | 924 | -webkit-transform-origin: 0% 100%; | ||
2687 | 925 | transform-origin: 0% 100%; | ||
2688 | 926 | -webkit-transform: translate3d(0, 0, 0); | ||
2689 | 927 | transform: translate3d(0, 0, 0); } | ||
2690 | 928 | |||
2691 | 929 | /********************************************* | ||
2692 | 930 | * FADE TRANSITION | ||
2693 | 931 | *********************************************/ | ||
2694 | 932 | .reveal .slides section[data-transition=fade], | ||
2695 | 933 | .reveal.fade .slides section:not([data-transition]), | ||
2696 | 934 | .reveal.fade .slides > section > section:not([data-transition]) { | ||
2697 | 935 | -webkit-transform: none; | ||
2698 | 936 | transform: none; | ||
2699 | 937 | transition: opacity 0.5s; } | ||
2700 | 938 | |||
2701 | 939 | .reveal.fade.overview .slides section, | ||
2702 | 940 | .reveal.fade.overview .slides > section > section { | ||
2703 | 941 | transition: none; } | ||
2704 | 942 | |||
2705 | 943 | /********************************************* | ||
2706 | 944 | * NO TRANSITION | ||
2707 | 945 | *********************************************/ | ||
2708 | 946 | .reveal .slides section[data-transition=none], | ||
2709 | 947 | .reveal.none .slides section:not([data-transition]) { | ||
2710 | 948 | -webkit-transform: none; | ||
2711 | 949 | transform: none; | ||
2712 | 950 | transition: none; } | ||
2713 | 951 | |||
2714 | 952 | /********************************************* | ||
2715 | 953 | * PAUSED MODE | ||
2716 | 954 | *********************************************/ | ||
2717 | 955 | .reveal .pause-overlay { | ||
2718 | 956 | position: absolute; | ||
2719 | 957 | top: 0; | ||
2720 | 958 | left: 0; | ||
2721 | 959 | width: 100%; | ||
2722 | 960 | height: 100%; | ||
2723 | 961 | background: black; | ||
2724 | 962 | visibility: hidden; | ||
2725 | 963 | opacity: 0; | ||
2726 | 964 | z-index: 100; | ||
2727 | 965 | transition: all 1s ease; } | ||
2728 | 966 | |||
2729 | 967 | .reveal .pause-overlay .resume-button { | ||
2730 | 968 | position: absolute; | ||
2731 | 969 | bottom: 20px; | ||
2732 | 970 | right: 20px; | ||
2733 | 971 | color: #ccc; | ||
2734 | 972 | border-radius: 2px; | ||
2735 | 973 | padding: 6px 14px; | ||
2736 | 974 | border: 2px solid #ccc; | ||
2737 | 975 | font-size: 16px; | ||
2738 | 976 | background: transparent; | ||
2739 | 977 | cursor: pointer; } | ||
2740 | 978 | .reveal .pause-overlay .resume-button:hover { | ||
2741 | 979 | color: #fff; | ||
2742 | 980 | border-color: #fff; } | ||
2743 | 981 | |||
2744 | 982 | .reveal.paused .pause-overlay { | ||
2745 | 983 | visibility: visible; | ||
2746 | 984 | opacity: 1; } | ||
2747 | 985 | |||
2748 | 986 | /********************************************* | ||
2749 | 987 | * FALLBACK | ||
2750 | 988 | *********************************************/ | ||
2751 | 989 | .no-transforms { | ||
2752 | 990 | overflow-y: auto; } | ||
2753 | 991 | |||
2754 | 992 | .no-transforms .reveal .slides { | ||
2755 | 993 | position: relative; | ||
2756 | 994 | width: 80%; | ||
2757 | 995 | height: auto !important; | ||
2758 | 996 | top: 0; | ||
2759 | 997 | left: 50%; | ||
2760 | 998 | margin: 0; | ||
2761 | 999 | text-align: center; } | ||
2762 | 1000 | |||
2763 | 1001 | .no-transforms .reveal .controls, | ||
2764 | 1002 | .no-transforms .reveal .progress { | ||
2765 | 1003 | display: none !important; } | ||
2766 | 1004 | |||
2767 | 1005 | .no-transforms .reveal .slides section { | ||
2768 | 1006 | display: block !important; | ||
2769 | 1007 | opacity: 1 !important; | ||
2770 | 1008 | position: relative !important; | ||
2771 | 1009 | height: auto; | ||
2772 | 1010 | min-height: 0; | ||
2773 | 1011 | top: 0; | ||
2774 | 1012 | left: -50%; | ||
2775 | 1013 | margin: 70px 0; | ||
2776 | 1014 | -webkit-transform: none; | ||
2777 | 1015 | transform: none; } | ||
2778 | 1016 | |||
2779 | 1017 | .no-transforms .reveal .slides section section { | ||
2780 | 1018 | left: 0; } | ||
2781 | 1019 | |||
2782 | 1020 | .reveal .no-transition, | ||
2783 | 1021 | .reveal .no-transition * { | ||
2784 | 1022 | transition: none !important; } | ||
2785 | 1023 | |||
2786 | 1024 | /********************************************* | ||
2787 | 1025 | * PER-SLIDE BACKGROUNDS | ||
2788 | 1026 | *********************************************/ | ||
2789 | 1027 | .reveal .backgrounds { | ||
2790 | 1028 | position: absolute; | ||
2791 | 1029 | width: 100%; | ||
2792 | 1030 | height: 100%; | ||
2793 | 1031 | top: 0; | ||
2794 | 1032 | left: 0; | ||
2795 | 1033 | -webkit-perspective: 600px; | ||
2796 | 1034 | perspective: 600px; } | ||
2797 | 1035 | |||
2798 | 1036 | .reveal .slide-background { | ||
2799 | 1037 | display: none; | ||
2800 | 1038 | position: absolute; | ||
2801 | 1039 | width: 100%; | ||
2802 | 1040 | height: 100%; | ||
2803 | 1041 | opacity: 0; | ||
2804 | 1042 | visibility: hidden; | ||
2805 | 1043 | overflow: hidden; | ||
2806 | 1044 | background-color: transparent; | ||
2807 | 1045 | transition: all 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985); } | ||
2808 | 1046 | |||
2809 | 1047 | .reveal .slide-background-content { | ||
2810 | 1048 | position: absolute; | ||
2811 | 1049 | width: 100%; | ||
2812 | 1050 | height: 100%; | ||
2813 | 1051 | background-position: 50% 50%; | ||
2814 | 1052 | background-repeat: no-repeat; | ||
2815 | 1053 | background-size: cover; } | ||
2816 | 1054 | |||
2817 | 1055 | .reveal .slide-background.stack { | ||
2818 | 1056 | display: block; } | ||
2819 | 1057 | |||
2820 | 1058 | .reveal .slide-background.present { | ||
2821 | 1059 | opacity: 1; | ||
2822 | 1060 | visibility: visible; | ||
2823 | 1061 | z-index: 2; } | ||
2824 | 1062 | |||
2825 | 1063 | .print-pdf .reveal .slide-background { | ||
2826 | 1064 | opacity: 1 !important; | ||
2827 | 1065 | visibility: visible !important; } | ||
2828 | 1066 | |||
2829 | 1067 | /* Video backgrounds */ | ||
2830 | 1068 | .reveal .slide-background video { | ||
2831 | 1069 | position: absolute; | ||
2832 | 1070 | width: 100%; | ||
2833 | 1071 | height: 100%; | ||
2834 | 1072 | max-width: none; | ||
2835 | 1073 | max-height: none; | ||
2836 | 1074 | top: 0; | ||
2837 | 1075 | left: 0; | ||
2838 | 1076 | -o-object-fit: cover; | ||
2839 | 1077 | object-fit: cover; } | ||
2840 | 1078 | |||
2841 | 1079 | .reveal .slide-background[data-background-size="contain"] video { | ||
2842 | 1080 | -o-object-fit: contain; | ||
2843 | 1081 | object-fit: contain; } | ||
2844 | 1082 | |||
2845 | 1083 | /* Immediate transition style */ | ||
2846 | 1084 | .reveal[data-background-transition=none] > .backgrounds .slide-background, | ||
2847 | 1085 | .reveal > .backgrounds .slide-background[data-background-transition=none] { | ||
2848 | 1086 | transition: none; } | ||
2849 | 1087 | |||
2850 | 1088 | /* Slide */ | ||
2851 | 1089 | .reveal[data-background-transition=slide] > .backgrounds .slide-background, | ||
2852 | 1090 | .reveal > .backgrounds .slide-background[data-background-transition=slide] { | ||
2853 | 1091 | opacity: 1; | ||
2854 | 1092 | -webkit-backface-visibility: hidden; | ||
2855 | 1093 | backface-visibility: hidden; } | ||
2856 | 1094 | |||
2857 | 1095 | .reveal[data-background-transition=slide] > .backgrounds .slide-background.past, | ||
2858 | 1096 | .reveal > .backgrounds .slide-background.past[data-background-transition=slide] { | ||
2859 | 1097 | -webkit-transform: translate(-100%, 0); | ||
2860 | 1098 | transform: translate(-100%, 0); } | ||
2861 | 1099 | |||
2862 | 1100 | .reveal[data-background-transition=slide] > .backgrounds .slide-background.future, | ||
2863 | 1101 | .reveal > .backgrounds .slide-background.future[data-background-transition=slide] { | ||
2864 | 1102 | -webkit-transform: translate(100%, 0); | ||
2865 | 1103 | transform: translate(100%, 0); } | ||
2866 | 1104 | |||
2867 | 1105 | .reveal[data-background-transition=slide] > .backgrounds .slide-background > .slide-background.past, | ||
2868 | 1106 | .reveal > .backgrounds .slide-background > .slide-background.past[data-background-transition=slide] { | ||
2869 | 1107 | -webkit-transform: translate(0, -100%); | ||
2870 | 1108 | transform: translate(0, -100%); } | ||
2871 | 1109 | |||
2872 | 1110 | .reveal[data-background-transition=slide] > .backgrounds .slide-background > .slide-background.future, | ||
2873 | 1111 | .reveal > .backgrounds .slide-background > .slide-background.future[data-background-transition=slide] { | ||
2874 | 1112 | -webkit-transform: translate(0, 100%); | ||
2875 | 1113 | transform: translate(0, 100%); } | ||
2876 | 1114 | |||
2877 | 1115 | /* Convex */ | ||
2878 | 1116 | .reveal[data-background-transition=convex] > .backgrounds .slide-background.past, | ||
2879 | 1117 | .reveal > .backgrounds .slide-background.past[data-background-transition=convex] { | ||
2880 | 1118 | opacity: 0; | ||
2881 | 1119 | -webkit-transform: translate3d(-100%, 0, 0) rotateY(-90deg) translate3d(-100%, 0, 0); | ||
2882 | 1120 | transform: translate3d(-100%, 0, 0) rotateY(-90deg) translate3d(-100%, 0, 0); } | ||
2883 | 1121 | |||
2884 | 1122 | .reveal[data-background-transition=convex] > .backgrounds .slide-background.future, | ||
2885 | 1123 | .reveal > .backgrounds .slide-background.future[data-background-transition=convex] { | ||
2886 | 1124 | opacity: 0; | ||
2887 | 1125 | -webkit-transform: translate3d(100%, 0, 0) rotateY(90deg) translate3d(100%, 0, 0); | ||
2888 | 1126 | transform: translate3d(100%, 0, 0) rotateY(90deg) translate3d(100%, 0, 0); } | ||
2889 | 1127 | |||
2890 | 1128 | .reveal[data-background-transition=convex] > .backgrounds .slide-background > .slide-background.past, | ||
2891 | 1129 | .reveal > .backgrounds .slide-background > .slide-background.past[data-background-transition=convex] { | ||
2892 | 1130 | opacity: 0; | ||
2893 | 1131 | -webkit-transform: translate3d(0, -100%, 0) rotateX(90deg) translate3d(0, -100%, 0); | ||
2894 | 1132 | transform: translate3d(0, -100%, 0) rotateX(90deg) translate3d(0, -100%, 0); } | ||
2895 | 1133 | |||
2896 | 1134 | .reveal[data-background-transition=convex] > .backgrounds .slide-background > .slide-background.future, | ||
2897 | 1135 | .reveal > .backgrounds .slide-background > .slide-background.future[data-background-transition=convex] { | ||
2898 | 1136 | opacity: 0; | ||
2899 | 1137 | -webkit-transform: translate3d(0, 100%, 0) rotateX(-90deg) translate3d(0, 100%, 0); | ||
2900 | 1138 | transform: translate3d(0, 100%, 0) rotateX(-90deg) translate3d(0, 100%, 0); } | ||
2901 | 1139 | |||
2902 | 1140 | /* Concave */ | ||
2903 | 1141 | .reveal[data-background-transition=concave] > .backgrounds .slide-background.past, | ||
2904 | 1142 | .reveal > .backgrounds .slide-background.past[data-background-transition=concave] { | ||
2905 | 1143 | opacity: 0; | ||
2906 | 1144 | -webkit-transform: translate3d(-100%, 0, 0) rotateY(90deg) translate3d(-100%, 0, 0); | ||
2907 | 1145 | transform: translate3d(-100%, 0, 0) rotateY(90deg) translate3d(-100%, 0, 0); } | ||
2908 | 1146 | |||
2909 | 1147 | .reveal[data-background-transition=concave] > .backgrounds .slide-background.future, | ||
2910 | 1148 | .reveal > .backgrounds .slide-background.future[data-background-transition=concave] { | ||
2911 | 1149 | opacity: 0; | ||
2912 | 1150 | -webkit-transform: translate3d(100%, 0, 0) rotateY(-90deg) translate3d(100%, 0, 0); | ||
2913 | 1151 | transform: translate3d(100%, 0, 0) rotateY(-90deg) translate3d(100%, 0, 0); } | ||
2914 | 1152 | |||
2915 | 1153 | .reveal[data-background-transition=concave] > .backgrounds .slide-background > .slide-background.past, | ||
2916 | 1154 | .reveal > .backgrounds .slide-background > .slide-background.past[data-background-transition=concave] { | ||
2917 | 1155 | opacity: 0; | ||
2918 | 1156 | -webkit-transform: translate3d(0, -100%, 0) rotateX(-90deg) translate3d(0, -100%, 0); | ||
2919 | 1157 | transform: translate3d(0, -100%, 0) rotateX(-90deg) translate3d(0, -100%, 0); } | ||
2920 | 1158 | |||
2921 | 1159 | .reveal[data-background-transition=concave] > .backgrounds .slide-background > .slide-background.future, | ||
2922 | 1160 | .reveal > .backgrounds .slide-background > .slide-background.future[data-background-transition=concave] { | ||
2923 | 1161 | opacity: 0; | ||
2924 | 1162 | -webkit-transform: translate3d(0, 100%, 0) rotateX(90deg) translate3d(0, 100%, 0); | ||
2925 | 1163 | transform: translate3d(0, 100%, 0) rotateX(90deg) translate3d(0, 100%, 0); } | ||
2926 | 1164 | |||
2927 | 1165 | /* Zoom */ | ||
2928 | 1166 | .reveal[data-background-transition=zoom] > .backgrounds .slide-background, | ||
2929 | 1167 | .reveal > .backgrounds .slide-background[data-background-transition=zoom] { | ||
2930 | 1168 | transition-timing-function: ease; } | ||
2931 | 1169 | |||
2932 | 1170 | .reveal[data-background-transition=zoom] > .backgrounds .slide-background.past, | ||
2933 | 1171 | .reveal > .backgrounds .slide-background.past[data-background-transition=zoom] { | ||
2934 | 1172 | opacity: 0; | ||
2935 | 1173 | visibility: hidden; | ||
2936 | 1174 | -webkit-transform: scale(16); | ||
2937 | 1175 | transform: scale(16); } | ||
2938 | 1176 | |||
2939 | 1177 | .reveal[data-background-transition=zoom] > .backgrounds .slide-background.future, | ||
2940 | 1178 | .reveal > .backgrounds .slide-background.future[data-background-transition=zoom] { | ||
2941 | 1179 | opacity: 0; | ||
2942 | 1180 | visibility: hidden; | ||
2943 | 1181 | -webkit-transform: scale(0.2); | ||
2944 | 1182 | transform: scale(0.2); } | ||
2945 | 1183 | |||
2946 | 1184 | .reveal[data-background-transition=zoom] > .backgrounds .slide-background > .slide-background.past, | ||
2947 | 1185 | .reveal > .backgrounds .slide-background > .slide-background.past[data-background-transition=zoom] { | ||
2948 | 1186 | opacity: 0; | ||
2949 | 1187 | visibility: hidden; | ||
2950 | 1188 | -webkit-transform: scale(16); | ||
2951 | 1189 | transform: scale(16); } | ||
2952 | 1190 | |||
2953 | 1191 | .reveal[data-background-transition=zoom] > .backgrounds .slide-background > .slide-background.future, | ||
2954 | 1192 | .reveal > .backgrounds .slide-background > .slide-background.future[data-background-transition=zoom] { | ||
2955 | 1193 | opacity: 0; | ||
2956 | 1194 | visibility: hidden; | ||
2957 | 1195 | -webkit-transform: scale(0.2); | ||
2958 | 1196 | transform: scale(0.2); } | ||
2959 | 1197 | |||
2960 | 1198 | /* Global transition speed settings */ | ||
2961 | 1199 | .reveal[data-transition-speed="fast"] > .backgrounds .slide-background { | ||
2962 | 1200 | transition-duration: 400ms; } | ||
2963 | 1201 | |||
2964 | 1202 | .reveal[data-transition-speed="slow"] > .backgrounds .slide-background { | ||
2965 | 1203 | transition-duration: 1200ms; } | ||
2966 | 1204 | |||
2967 | 1205 | /********************************************* | ||
2968 | 1206 | * OVERVIEW | ||
2969 | 1207 | *********************************************/ | ||
2970 | 1208 | .reveal.overview { | ||
2971 | 1209 | -webkit-perspective-origin: 50% 50%; | ||
2972 | 1210 | perspective-origin: 50% 50%; | ||
2973 | 1211 | -webkit-perspective: 700px; | ||
2974 | 1212 | perspective: 700px; } | ||
2975 | 1213 | .reveal.overview .slides { | ||
2976 | 1214 | -moz-transform-style: preserve-3d; } | ||
2977 | 1215 | .reveal.overview .slides section { | ||
2978 | 1216 | height: 100%; | ||
2979 | 1217 | top: 0 !important; | ||
2980 | 1218 | opacity: 1 !important; | ||
2981 | 1219 | overflow: hidden; | ||
2982 | 1220 | visibility: visible !important; | ||
2983 | 1221 | cursor: pointer; | ||
2984 | 1222 | box-sizing: border-box; } | ||
2985 | 1223 | .reveal.overview .slides section:hover, | ||
2986 | 1224 | .reveal.overview .slides section.present { | ||
2987 | 1225 | outline: 10px solid rgba(150, 150, 150, 0.4); | ||
2988 | 1226 | outline-offset: 10px; } | ||
2989 | 1227 | .reveal.overview .slides section .fragment { | ||
2990 | 1228 | opacity: 1; | ||
2991 | 1229 | transition: none; } | ||
2992 | 1230 | .reveal.overview .slides section:after, | ||
2993 | 1231 | .reveal.overview .slides section:before { | ||
2994 | 1232 | display: none !important; } | ||
2995 | 1233 | .reveal.overview .slides > section.stack { | ||
2996 | 1234 | padding: 0; | ||
2997 | 1235 | top: 0 !important; | ||
2998 | 1236 | background: none; | ||
2999 | 1237 | outline: none; | ||
3000 | 1238 | overflow: visible; } | ||
3001 | 1239 | .reveal.overview .backgrounds { | ||
3002 | 1240 | -webkit-perspective: inherit; | ||
3003 | 1241 | perspective: inherit; | ||
3004 | 1242 | -moz-transform-style: preserve-3d; } | ||
3005 | 1243 | .reveal.overview .backgrounds .slide-background { | ||
3006 | 1244 | opacity: 1; | ||
3007 | 1245 | visibility: visible; | ||
3008 | 1246 | outline: 10px solid rgba(150, 150, 150, 0.1); | ||
3009 | 1247 | outline-offset: 10px; } | ||
3010 | 1248 | .reveal.overview .backgrounds .slide-background.stack { | ||
3011 | 1249 | overflow: visible; } | ||
3012 | 1250 | |||
3013 | 1251 | .reveal.overview .slides section, | ||
3014 | 1252 | .reveal.overview-deactivating .slides section { | ||
3015 | 1253 | transition: none; } | ||
3016 | 1254 | |||
3017 | 1255 | .reveal.overview .backgrounds .slide-background, | ||
3018 | 1256 | .reveal.overview-deactivating .backgrounds .slide-background { | ||
3019 | 1257 | transition: none; } | ||
3020 | 1258 | |||
3021 | 1259 | /********************************************* | ||
3022 | 1260 | * RTL SUPPORT | ||
3023 | 1261 | *********************************************/ | ||
3024 | 1262 | .reveal.rtl .slides, | ||
3025 | 1263 | .reveal.rtl .slides h1, | ||
3026 | 1264 | .reveal.rtl .slides h2, | ||
3027 | 1265 | .reveal.rtl .slides h3, | ||
3028 | 1266 | .reveal.rtl .slides h4, | ||
3029 | 1267 | .reveal.rtl .slides h5, | ||
3030 | 1268 | .reveal.rtl .slides h6 { | ||
3031 | 1269 | direction: rtl; | ||
3032 | 1270 | font-family: sans-serif; } | ||
3033 | 1271 | |||
3034 | 1272 | .reveal.rtl pre, | ||
3035 | 1273 | .reveal.rtl code { | ||
3036 | 1274 | direction: ltr; } | ||
3037 | 1275 | |||
3038 | 1276 | .reveal.rtl ol, | ||
3039 | 1277 | .reveal.rtl ul { | ||
3040 | 1278 | text-align: right; } | ||
3041 | 1279 | |||
3042 | 1280 | .reveal.rtl .progress span { | ||
3043 | 1281 | float: right; } | ||
3044 | 1282 | |||
3045 | 1283 | /********************************************* | ||
3046 | 1284 | * PARALLAX BACKGROUND | ||
3047 | 1285 | *********************************************/ | ||
3048 | 1286 | .reveal.has-parallax-background .backgrounds { | ||
3049 | 1287 | transition: all 0.8s ease; } | ||
3050 | 1288 | |||
3051 | 1289 | /* Global transition speed settings */ | ||
3052 | 1290 | .reveal.has-parallax-background[data-transition-speed="fast"] .backgrounds { | ||
3053 | 1291 | transition-duration: 400ms; } | ||
3054 | 1292 | |||
3055 | 1293 | .reveal.has-parallax-background[data-transition-speed="slow"] .backgrounds { | ||
3056 | 1294 | transition-duration: 1200ms; } | ||
3057 | 1295 | |||
3058 | 1296 | /********************************************* | ||
3059 | 1297 | * LINK PREVIEW OVERLAY | ||
3060 | 1298 | *********************************************/ | ||
3061 | 1299 | .reveal .overlay { | ||
3062 | 1300 | position: absolute; | ||
3063 | 1301 | top: 0; | ||
3064 | 1302 | left: 0; | ||
3065 | 1303 | width: 100%; | ||
3066 | 1304 | height: 100%; | ||
3067 | 1305 | z-index: 1000; | ||
3068 | 1306 | background: rgba(0, 0, 0, 0.9); | ||
3069 | 1307 | opacity: 0; | ||
3070 | 1308 | visibility: hidden; | ||
3071 | 1309 | transition: all 0.3s ease; } | ||
3072 | 1310 | |||
3073 | 1311 | .reveal .overlay.visible { | ||
3074 | 1312 | opacity: 1; | ||
3075 | 1313 | visibility: visible; } | ||
3076 | 1314 | |||
3077 | 1315 | .reveal .overlay .spinner { | ||
3078 | 1316 | position: absolute; | ||
3079 | 1317 | display: block; | ||
3080 | 1318 | top: 50%; | ||
3081 | 1319 | left: 50%; | ||
3082 | 1320 | width: 32px; | ||
3083 | 1321 | height: 32px; | ||
3084 | 1322 | margin: -16px 0 0 -16px; | ||
3085 | 1323 | z-index: 10; | ||
3086 | 1324 | background-image: url(data:image/gif;base64,R0lGODlhIAAgAPMAAJmZmf%2F%2F%2F6%2Bvr8nJybW1tcDAwOjo6Nvb26ioqKOjo7Ozs%2FLy8vz8%2FAAAAAAAAAAAACH%2FC05FVFNDQVBFMi4wAwEAAAAh%2FhpDcmVhdGVkIHdpdGggYWpheGxvYWQuaW5mbwAh%2BQQJCgAAACwAAAAAIAAgAAAE5xDISWlhperN52JLhSSdRgwVo1ICQZRUsiwHpTJT4iowNS8vyW2icCF6k8HMMBkCEDskxTBDAZwuAkkqIfxIQyhBQBFvAQSDITM5VDW6XNE4KagNh6Bgwe60smQUB3d4Rz1ZBApnFASDd0hihh12BkE9kjAJVlycXIg7CQIFA6SlnJ87paqbSKiKoqusnbMdmDC2tXQlkUhziYtyWTxIfy6BE8WJt5YJvpJivxNaGmLHT0VnOgSYf0dZXS7APdpB309RnHOG5gDqXGLDaC457D1zZ%2FV%2FnmOM82XiHRLYKhKP1oZmADdEAAAh%2BQQJCgAAACwAAAAAIAAgAAAE6hDISWlZpOrNp1lGNRSdRpDUolIGw5RUYhhHukqFu8DsrEyqnWThGvAmhVlteBvojpTDDBUEIFwMFBRAmBkSgOrBFZogCASwBDEY%2FCZSg7GSE0gSCjQBMVG023xWBhklAnoEdhQEfyNqMIcKjhRsjEdnezB%2BA4k8gTwJhFuiW4dokXiloUepBAp5qaKpp6%2BHo7aWW54wl7obvEe0kRuoplCGepwSx2jJvqHEmGt6whJpGpfJCHmOoNHKaHx61WiSR92E4lbFoq%2BB6QDtuetcaBPnW6%2BO7wDHpIiK9SaVK5GgV543tzjgGcghAgAh%2BQQJCgAAACwAAAAAIAAgAAAE7hDISSkxpOrN5zFHNWRdhSiVoVLHspRUMoyUakyEe8PTPCATW9A14E0UvuAKMNAZKYUZCiBMuBakSQKG8G2FzUWox2AUtAQFcBKlVQoLgQReZhQlCIJesQXI5B0CBnUMOxMCenoCfTCEWBsJColTMANldx15BGs8B5wlCZ9Po6OJkwmRpnqkqnuSrayqfKmqpLajoiW5HJq7FL1Gr2mMMcKUMIiJgIemy7xZtJsTmsM4xHiKv5KMCXqfyUCJEonXPN2rAOIAmsfB3uPoAK%2B%2BG%2Bw48edZPK%2BM6hLJpQg484enXIdQFSS1u6UhksENEQAAIfkECQoAAAAsAAAAACAAIAAABOcQyEmpGKLqzWcZRVUQnZYg1aBSh2GUVEIQ2aQOE%2BG%2BcD4ntpWkZQj1JIiZIogDFFyHI0UxQwFugMSOFIPJftfVAEoZLBbcLEFhlQiqGp1Vd140AUklUN3eCA51C1EWMzMCezCBBmkxVIVHBWd3HHl9JQOIJSdSnJ0TDKChCwUJjoWMPaGqDKannasMo6WnM562R5YluZRwur0wpgqZE7NKUm%2BFNRPIhjBJxKZteWuIBMN4zRMIVIhffcgojwCF117i4nlLnY5ztRLsnOk%2BaV%2BoJY7V7m76PdkS4trKcdg0Zc0tTcKkRAAAIfkECQoAAAAsAAAAACAAIAAABO4QyEkpKqjqzScpRaVkXZWQEximw1BSCUEIlDohrft6cpKCk5xid5MNJTaAIkekKGQkWyKHkvhKsR7ARmitkAYDYRIbUQRQjWBwJRzChi9CRlBcY1UN4g0%2FVNB0AlcvcAYHRyZPdEQFYV8ccwR5HWxEJ02YmRMLnJ1xCYp0Y5idpQuhopmmC2KgojKasUQDk5BNAwwMOh2RtRq5uQuPZKGIJQIGwAwGf6I0JXMpC8C7kXWDBINFMxS4DKMAWVWAGYsAdNqW5uaRxkSKJOZKaU3tPOBZ4DuK2LATgJhkPJMgTwKCdFjyPHEnKxFCDhEAACH5BAkKAAAALAAAAAAgACAAAATzEMhJaVKp6s2nIkolIJ2WkBShpkVRWqqQrhLSEu9MZJKK9y1ZrqYK9WiClmvoUaF8gIQSNeF1Er4MNFn4SRSDARWroAIETg1iVwuHjYB1kYc1mwruwXKC9gmsJXliGxc%2BXiUCby9ydh1sOSdMkpMTBpaXBzsfhoc5l58Gm5yToAaZhaOUqjkDgCWNHAULCwOLaTmzswadEqggQwgHuQsHIoZCHQMMQgQGubVEcxOPFAcMDAYUA85eWARmfSRQCdcMe0zeP1AAygwLlJtPNAAL19DARdPzBOWSm1brJBi45soRAWQAAkrQIykShQ9wVhHCwCQCACH5BAkKAAAALAAAAAAgACAAAATrEMhJaVKp6s2nIkqFZF2VIBWhUsJaTokqUCoBq%2BE71SRQeyqUToLA7VxF0JDyIQh%2FMVVPMt1ECZlfcjZJ9mIKoaTl1MRIl5o4CUKXOwmyrCInCKqcWtvadL2SYhyASyNDJ0uIiRMDjI0Fd30%2FiI2UA5GSS5UDj2l6NoqgOgN4gksEBgYFf0FDqKgHnyZ9OX8HrgYHdHpcHQULXAS2qKpENRg7eAMLC7kTBaixUYFkKAzWAAnLC7FLVxLWDBLKCwaKTULgEwbLA4hJtOkSBNqITT3xEgfLpBtzE%2FjiuL04RGEBgwWhShRgQExHBAAh%2BQQJCgAAACwAAAAAIAAgAAAE7xDISWlSqerNpyJKhWRdlSAVoVLCWk6JKlAqAavhO9UkUHsqlE6CwO1cRdCQ8iEIfzFVTzLdRAmZX3I2SfZiCqGk5dTESJeaOAlClzsJsqwiJwiqnFrb2nS9kmIcgEsjQydLiIlHehhpejaIjzh9eomSjZR%2BipslWIRLAgMDOR2DOqKogTB9pCUJBagDBXR6XB0EBkIIsaRsGGMMAxoDBgYHTKJiUYEGDAzHC9EACcUGkIgFzgwZ0QsSBcXHiQvOwgDdEwfFs0sDzt4S6BK4xYjkDOzn0unFeBzOBijIm1Dgmg5YFQwsCMjp1oJ8LyIAACH5BAkKAAAALAAAAAAgACAAAATwEMhJaVKp6s2nIkqFZF2VIBWhUsJaTokqUCoBq%2BE71SRQeyqUToLA7VxF0JDyIQh%2FMVVPMt1ECZlfcjZJ9mIKoaTl1MRIl5o4CUKXOwmyrCInCKqcWtvadL2SYhyASyNDJ0uIiUd6GGl6NoiPOH16iZKNlH6KmyWFOggHhEEvAwwMA0N9GBsEC6amhnVcEwavDAazGwIDaH1ipaYLBUTCGgQDA8NdHz0FpqgTBwsLqAbWAAnIA4FWKdMLGdYGEgraigbT0OITBcg5QwPT4xLrROZL6AuQAPUS7bxLpoWidY0JtxLHKhwwMJBTHgPKdEQAACH5BAkKAAAALAAAAAAgACAAAATrEMhJaVKp6s2nIkqFZF2VIBWhUsJaTokqUCoBq%2BE71SRQeyqUToLA7VxF0JDyIQh%2FMVVPMt1ECZlfcjZJ9mIKoaTl1MRIl5o4CUKXOwmyrCInCKqcWtvadL2SYhyASyNDJ0uIiUd6GAULDJCRiXo1CpGXDJOUjY%2BYip9DhToJA4RBLwMLCwVDfRgbBAaqqoZ1XBMHswsHtxtFaH1iqaoGNgAIxRpbFAgfPQSqpbgGBqUD1wBXeCYp1AYZ19JJOYgH1KwA4UBvQwXUBxPqVD9L3sbp2BNk2xvvFPJd%2BMFCN6HAAIKgNggY0KtEBAAh%2BQQJCgAAACwAAAAAIAAgAAAE6BDISWlSqerNpyJKhWRdlSAVoVLCWk6JKlAqAavhO9UkUHsqlE6CwO1cRdCQ8iEIfzFVTzLdRAmZX3I2SfYIDMaAFdTESJeaEDAIMxYFqrOUaNW4E4ObYcCXaiBVEgULe0NJaxxtYksjh2NLkZISgDgJhHthkpU4mW6blRiYmZOlh4JWkDqILwUGBnE6TYEbCgevr0N1gH4At7gHiRpFaLNrrq8HNgAJA70AWxQIH1%2BvsYMDAzZQPC9VCNkDWUhGkuE5PxJNwiUK4UfLzOlD4WvzAHaoG9nxPi5d%2BjYUqfAhhykOFwJWiAAAIfkECQoAAAAsAAAAACAAIAAABPAQyElpUqnqzaciSoVkXVUMFaFSwlpOCcMYlErAavhOMnNLNo8KsZsMZItJEIDIFSkLGQoQTNhIsFehRww2CQLKF0tYGKYSg%2BygsZIuNqJksKgbfgIGepNo2cIUB3V1B3IvNiBYNQaDSTtfhhx0CwVPI0UJe0%2Bbm4g5VgcGoqOcnjmjqDSdnhgEoamcsZuXO1aWQy8KAwOAuTYYGwi7w5h%2BKr0SJ8MFihpNbx%2B4Erq7BYBuzsdiH1jCAzoSfl0rVirNbRXlBBlLX%2BBP0XJLAPGzTkAuAOqb0WT5AH7OcdCm5B8TgRwSRKIHQtaLCwg1RAAAOwAAAAAAAAAAAA%3D%3D); | ||
3087 | 1325 | visibility: visible; | ||
3088 | 1326 | opacity: 0.6; | ||
3089 | 1327 | transition: all 0.3s ease; } | ||
3090 | 1328 | |||
3091 | 1329 | .reveal .overlay header { | ||
3092 | 1330 | position: absolute; | ||
3093 | 1331 | left: 0; | ||
3094 | 1332 | top: 0; | ||
3095 | 1333 | width: 100%; | ||
3096 | 1334 | height: 40px; | ||
3097 | 1335 | z-index: 2; | ||
3098 | 1336 | border-bottom: 1px solid #222; } | ||
3099 | 1337 | |||
3100 | 1338 | .reveal .overlay header a { | ||
3101 | 1339 | display: inline-block; | ||
3102 | 1340 | width: 40px; | ||
3103 | 1341 | height: 40px; | ||
3104 | 1342 | line-height: 36px; | ||
3105 | 1343 | padding: 0 10px; | ||
3106 | 1344 | float: right; | ||
3107 | 1345 | opacity: 0.6; | ||
3108 | 1346 | box-sizing: border-box; } | ||
3109 | 1347 | |||
3110 | 1348 | .reveal .overlay header a:hover { | ||
3111 | 1349 | opacity: 1; } | ||
3112 | 1350 | |||
3113 | 1351 | .reveal .overlay header a .icon { | ||
3114 | 1352 | display: inline-block; | ||
3115 | 1353 | width: 20px; | ||
3116 | 1354 | height: 20px; | ||
3117 | 1355 | background-position: 50% 50%; | ||
3118 | 1356 | background-size: 100%; | ||
3119 | 1357 | background-repeat: no-repeat; } | ||
3120 | 1358 | |||
3121 | 1359 | .reveal .overlay header a.close .icon { | ||
3122 | 1360 | background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAABkklEQVRYR8WX4VHDMAxG6wnoJrABZQPYBCaBTWAD2g1gE5gg6OOsXuxIlr40d81dfrSJ9V4c2VLK7spHuTJ/5wpM07QXuXc5X0opX2tEJcadjHuV80li/FgxTIEK/5QBCICBD6xEhSMGHgQPgBgLiYVAB1dpSqKDawxTohFw4JSEA3clzgIBPCURwE2JucBR7rhPJJv5OpJwDX+SfDjgx1wACQeJG1aChP9K/IMmdZ8DtESV1WyP3Bt4MwM6sj4NMxMYiqUWHQu4KYA/SYkIjOsm3BXYWMKFDwU2khjCQ4ELJUJ4SmClRArOCmSXGuKma0fYD5CbzHxFpCSGAhfAVSSUGDUk2BWZaff2g6GE15BsBQ9nwmpIGDiyHQddwNTMKkbZaf9fajXQca1EX44puJZUsnY0ObGmITE3GVLCbEhQUjGVt146j6oasWN+49Vph2w1pZ5EansNZqKBm1txbU57iRRcZ86RWMDdWtBJUHBHwoQPi1GV+JCbntmvok7iTX4/Up9mgyTc/FJYDTcndgH/AA5A/CHsyEkVAAAAAElFTkSuQmCC); } | ||
3123 | 1361 | |||
3124 | 1362 | .reveal .overlay header a.external .icon { | ||
3125 | 1363 | background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAcElEQVRYR+2WSQoAIQwEzf8f7XiOMkUQxUPlGkM3hVmiQfQR9GYnH1SsAQlI4DiBqkCMoNb9y2e90IAEJPAcgdznU9+engMaeJ7Azh5Y1U67gAho4DqBqmB1buAf0MB1AlVBek83ZPkmJMGc1wAR+AAqod/B97TRpQAAAABJRU5ErkJggg==); } | ||
3126 | 1364 | |||
3127 | 1365 | .reveal .overlay .viewport { | ||
3128 | 1366 | position: absolute; | ||
3129 | 1367 | display: -webkit-box; | ||
3130 | 1368 | display: -ms-flexbox; | ||
3131 | 1369 | display: flex; | ||
3132 | 1370 | top: 40px; | ||
3133 | 1371 | right: 0; | ||
3134 | 1372 | bottom: 0; | ||
3135 | 1373 | left: 0; } | ||
3136 | 1374 | |||
3137 | 1375 | .reveal .overlay.overlay-preview .viewport iframe { | ||
3138 | 1376 | width: 100%; | ||
3139 | 1377 | height: 100%; | ||
3140 | 1378 | max-width: 100%; | ||
3141 | 1379 | max-height: 100%; | ||
3142 | 1380 | border: 0; | ||
3143 | 1381 | opacity: 0; | ||
3144 | 1382 | visibility: hidden; | ||
3145 | 1383 | transition: all 0.3s ease; } | ||
3146 | 1384 | |||
3147 | 1385 | .reveal .overlay.overlay-preview.loaded .viewport iframe { | ||
3148 | 1386 | opacity: 1; | ||
3149 | 1387 | visibility: visible; } | ||
3150 | 1388 | |||
3151 | 1389 | .reveal .overlay.overlay-preview.loaded .viewport-inner { | ||
3152 | 1390 | position: absolute; | ||
3153 | 1391 | z-index: -1; | ||
3154 | 1392 | left: 0; | ||
3155 | 1393 | top: 45%; | ||
3156 | 1394 | width: 100%; | ||
3157 | 1395 | text-align: center; | ||
3158 | 1396 | letter-spacing: normal; } | ||
3159 | 1397 | |||
3160 | 1398 | .reveal .overlay.overlay-preview .x-frame-error { | ||
3161 | 1399 | opacity: 0; | ||
3162 | 1400 | transition: opacity 0.3s ease 0.3s; } | ||
3163 | 1401 | |||
3164 | 1402 | .reveal .overlay.overlay-preview.loaded .x-frame-error { | ||
3165 | 1403 | opacity: 1; } | ||
3166 | 1404 | |||
3167 | 1405 | .reveal .overlay.overlay-preview.loaded .spinner { | ||
3168 | 1406 | opacity: 0; | ||
3169 | 1407 | visibility: hidden; | ||
3170 | 1408 | -webkit-transform: scale(0.2); | ||
3171 | 1409 | transform: scale(0.2); } | ||
3172 | 1410 | |||
3173 | 1411 | .reveal .overlay.overlay-help .viewport { | ||
3174 | 1412 | overflow: auto; | ||
3175 | 1413 | color: #fff; } | ||
3176 | 1414 | |||
3177 | 1415 | .reveal .overlay.overlay-help .viewport .viewport-inner { | ||
3178 | 1416 | width: 600px; | ||
3179 | 1417 | margin: auto; | ||
3180 | 1418 | padding: 20px 20px 80px 20px; | ||
3181 | 1419 | text-align: center; | ||
3182 | 1420 | letter-spacing: normal; } | ||
3183 | 1421 | |||
3184 | 1422 | .reveal .overlay.overlay-help .viewport .viewport-inner .title { | ||
3185 | 1423 | font-size: 20px; } | ||
3186 | 1424 | |||
3187 | 1425 | .reveal .overlay.overlay-help .viewport .viewport-inner table { | ||
3188 | 1426 | border: 1px solid #fff; | ||
3189 | 1427 | border-collapse: collapse; | ||
3190 | 1428 | font-size: 16px; } | ||
3191 | 1429 | |||
3192 | 1430 | .reveal .overlay.overlay-help .viewport .viewport-inner table th, | ||
3193 | 1431 | .reveal .overlay.overlay-help .viewport .viewport-inner table td { | ||
3194 | 1432 | width: 200px; | ||
3195 | 1433 | padding: 14px; | ||
3196 | 1434 | border: 1px solid #fff; | ||
3197 | 1435 | vertical-align: middle; } | ||
3198 | 1436 | |||
3199 | 1437 | .reveal .overlay.overlay-help .viewport .viewport-inner table th { | ||
3200 | 1438 | padding-top: 20px; | ||
3201 | 1439 | padding-bottom: 20px; } | ||
3202 | 1440 | |||
3203 | 1441 | /********************************************* | ||
3204 | 1442 | * PLAYBACK COMPONENT | ||
3205 | 1443 | *********************************************/ | ||
3206 | 1444 | .reveal .playback { | ||
3207 | 1445 | position: absolute; | ||
3208 | 1446 | left: 15px; | ||
3209 | 1447 | bottom: 20px; | ||
3210 | 1448 | z-index: 30; | ||
3211 | 1449 | cursor: pointer; | ||
3212 | 1450 | transition: all 400ms ease; | ||
3213 | 1451 | -webkit-tap-highlight-color: transparent; } | ||
3214 | 1452 | |||
3215 | 1453 | .reveal.overview .playback { | ||
3216 | 1454 | opacity: 0; | ||
3217 | 1455 | visibility: hidden; } | ||
3218 | 1456 | |||
3219 | 1457 | /********************************************* | ||
3220 | 1458 | * ROLLING LINKS | ||
3221 | 1459 | *********************************************/ | ||
3222 | 1460 | .reveal .roll { | ||
3223 | 1461 | display: inline-block; | ||
3224 | 1462 | line-height: 1.2; | ||
3225 | 1463 | overflow: hidden; | ||
3226 | 1464 | vertical-align: top; | ||
3227 | 1465 | -webkit-perspective: 400px; | ||
3228 | 1466 | perspective: 400px; | ||
3229 | 1467 | -webkit-perspective-origin: 50% 50%; | ||
3230 | 1468 | perspective-origin: 50% 50%; } | ||
3231 | 1469 | |||
3232 | 1470 | .reveal .roll:hover { | ||
3233 | 1471 | background: none; | ||
3234 | 1472 | text-shadow: none; } | ||
3235 | 1473 | |||
3236 | 1474 | .reveal .roll span { | ||
3237 | 1475 | display: block; | ||
3238 | 1476 | position: relative; | ||
3239 | 1477 | padding: 0 2px; | ||
3240 | 1478 | pointer-events: none; | ||
3241 | 1479 | transition: all 400ms ease; | ||
3242 | 1480 | -webkit-transform-origin: 50% 0%; | ||
3243 | 1481 | transform-origin: 50% 0%; | ||
3244 | 1482 | -webkit-transform-style: preserve-3d; | ||
3245 | 1483 | transform-style: preserve-3d; | ||
3246 | 1484 | -webkit-backface-visibility: hidden; | ||
3247 | 1485 | backface-visibility: hidden; } | ||
3248 | 1486 | |||
3249 | 1487 | .reveal .roll:hover span { | ||
3250 | 1488 | background: rgba(0, 0, 0, 0.5); | ||
3251 | 1489 | -webkit-transform: translate3d(0px, 0px, -45px) rotateX(90deg); | ||
3252 | 1490 | transform: translate3d(0px, 0px, -45px) rotateX(90deg); } | ||
3253 | 1491 | |||
3254 | 1492 | .reveal .roll span:after { | ||
3255 | 1493 | content: attr(data-title); | ||
3256 | 1494 | display: block; | ||
3257 | 1495 | position: absolute; | ||
3258 | 1496 | left: 0; | ||
3259 | 1497 | top: 0; | ||
3260 | 1498 | padding: 0 2px; | ||
3261 | 1499 | -webkit-backface-visibility: hidden; | ||
3262 | 1500 | backface-visibility: hidden; | ||
3263 | 1501 | -webkit-transform-origin: 50% 0%; | ||
3264 | 1502 | transform-origin: 50% 0%; | ||
3265 | 1503 | -webkit-transform: translate3d(0px, 110%, 0px) rotateX(-90deg); | ||
3266 | 1504 | transform: translate3d(0px, 110%, 0px) rotateX(-90deg); } | ||
3267 | 1505 | |||
3268 | 1506 | /********************************************* | ||
3269 | 1507 | * SPEAKER NOTES | ||
3270 | 1508 | *********************************************/ | ||
3271 | 1509 | .reveal aside.notes { | ||
3272 | 1510 | display: none; } | ||
3273 | 1511 | |||
3274 | 1512 | .reveal .speaker-notes { | ||
3275 | 1513 | display: none; | ||
3276 | 1514 | position: absolute; | ||
3277 | 1515 | width: 25vw; | ||
3278 | 1516 | height: 100%; | ||
3279 | 1517 | top: 0; | ||
3280 | 1518 | left: 100%; | ||
3281 | 1519 | padding: 14px 18px 14px 18px; | ||
3282 | 1520 | z-index: 1; | ||
3283 | 1521 | font-size: 18px; | ||
3284 | 1522 | line-height: 1.4; | ||
3285 | 1523 | border: 1px solid rgba(0, 0, 0, 0.05); | ||
3286 | 1524 | color: #222; | ||
3287 | 1525 | background-color: #f5f5f5; | ||
3288 | 1526 | overflow: auto; | ||
3289 | 1527 | box-sizing: border-box; | ||
3290 | 1528 | text-align: left; | ||
3291 | 1529 | font-family: Helvetica, sans-serif; | ||
3292 | 1530 | -webkit-overflow-scrolling: touch; } | ||
3293 | 1531 | .reveal .speaker-notes .notes-placeholder { | ||
3294 | 1532 | color: #ccc; | ||
3295 | 1533 | font-style: italic; } | ||
3296 | 1534 | .reveal .speaker-notes:focus { | ||
3297 | 1535 | outline: none; } | ||
3298 | 1536 | .reveal .speaker-notes:before { | ||
3299 | 1537 | content: 'Speaker notes'; | ||
3300 | 1538 | display: block; | ||
3301 | 1539 | margin-bottom: 10px; | ||
3302 | 1540 | opacity: 0.5; } | ||
3303 | 1541 | |||
3304 | 1542 | .reveal.show-notes { | ||
3305 | 1543 | max-width: 75vw; | ||
3306 | 1544 | overflow: visible; } | ||
3307 | 1545 | |||
3308 | 1546 | .reveal.show-notes .speaker-notes { | ||
3309 | 1547 | display: block; } | ||
3310 | 1548 | |||
3311 | 1549 | @media screen and (min-width: 1600px) { | ||
3312 | 1550 | .reveal .speaker-notes { | ||
3313 | 1551 | font-size: 20px; } } | ||
3314 | 1552 | |||
3315 | 1553 | @media screen and (max-width: 1024px) { | ||
3316 | 1554 | .reveal.show-notes { | ||
3317 | 1555 | border-left: 0; | ||
3318 | 1556 | max-width: none; | ||
3319 | 1557 | max-height: 70%; | ||
3320 | 1558 | overflow: visible; } | ||
3321 | 1559 | .reveal.show-notes .speaker-notes { | ||
3322 | 1560 | top: 100%; | ||
3323 | 1561 | left: 0; | ||
3324 | 1562 | width: 100%; | ||
3325 | 1563 | height: 42.8571428571%; } } | ||
3326 | 1564 | |||
3327 | 1565 | @media screen and (max-width: 600px) { | ||
3328 | 1566 | .reveal.show-notes { | ||
3329 | 1567 | max-height: 60%; } | ||
3330 | 1568 | .reveal.show-notes .speaker-notes { | ||
3331 | 1569 | top: 100%; | ||
3332 | 1570 | height: 66.6666666667%; } | ||
3333 | 1571 | .reveal .speaker-notes { | ||
3334 | 1572 | font-size: 14px; } } | ||
3335 | 1573 | |||
3336 | 1574 | /********************************************* | ||
3337 | 1575 | * ZOOM PLUGIN | ||
3338 | 1576 | *********************************************/ | ||
3339 | 1577 | .zoomed .reveal *, | ||
3340 | 1578 | .zoomed .reveal *:before, | ||
3341 | 1579 | .zoomed .reveal *:after { | ||
3342 | 1580 | -webkit-backface-visibility: visible !important; | ||
3343 | 1581 | backface-visibility: visible !important; } | ||
3344 | 1582 | |||
3345 | 1583 | .zoomed .reveal .progress, | ||
3346 | 1584 | .zoomed .reveal .controls { | ||
3347 | 1585 | opacity: 0; } | ||
3348 | 1586 | |||
3349 | 1587 | .zoomed .reveal .roll span { | ||
3350 | 1588 | background: none; } | ||
3351 | 1589 | |||
3352 | 1590 | .zoomed .reveal .roll span:after { | ||
3353 | 1591 | visibility: hidden; } | ||
3354 | 0 | 1592 | ||
3355 | === added file 'openlp/core/display/html/reveal.js' | |||
3356 | --- openlp/core/display/html/reveal.js 1970-01-01 00:00:00 +0000 | |||
3357 | +++ openlp/core/display/html/reveal.js 2019-02-12 20:56:20 +0000 | |||
3358 | @@ -0,0 +1,5586 @@ | |||
3359 | 1 | /*! | ||
3360 | 2 | * reveal.js | ||
3361 | 3 | * http://revealjs.com | ||
3362 | 4 | * MIT licensed | ||
3363 | 5 | * | ||
3364 | 6 | * Copyright (C) 2018 Hakim El Hattab, http://hakim.se | ||
3365 | 7 | */ | ||
3366 | 8 | (function( root, factory ) { | ||
3367 | 9 | if( typeof define === 'function' && define.amd ) { | ||
3368 | 10 | // AMD. Register as an anonymous module. | ||
3369 | 11 | define( function() { | ||
3370 | 12 | root.Reveal = factory(); | ||
3371 | 13 | return root.Reveal; | ||
3372 | 14 | } ); | ||
3373 | 15 | } else if( typeof exports === 'object' ) { | ||
3374 | 16 | // Node. Does not work with strict CommonJS. | ||
3375 | 17 | module.exports = factory(); | ||
3376 | 18 | } else { | ||
3377 | 19 | // Browser globals. | ||
3378 | 20 | root.Reveal = factory(); | ||
3379 | 21 | } | ||
3380 | 22 | }( this, function() { | ||
3381 | 23 | |||
3382 | 24 | 'use strict'; | ||
3383 | 25 | |||
3384 | 26 | var Reveal; | ||
3385 | 27 | |||
3386 | 28 | // The reveal.js version | ||
3387 | 29 | var VERSION = '3.7.0'; | ||
3388 | 30 | |||
3389 | 31 | var SLIDES_SELECTOR = '.slides section', | ||
3390 | 32 | HORIZONTAL_SLIDES_SELECTOR = '.slides>section', | ||
3391 | 33 | VERTICAL_SLIDES_SELECTOR = '.slides>section.present>section', | ||
3392 | 34 | HOME_SLIDE_SELECTOR = '.slides>section:first-of-type', | ||
3393 | 35 | UA = navigator.userAgent, | ||
3394 | 36 | |||
3395 | 37 | // Configuration defaults, can be overridden at initialization time | ||
3396 | 38 | config = { | ||
3397 | 39 | |||
3398 | 40 | // The "normal" size of the presentation, aspect ratio will be preserved | ||
3399 | 41 | // when the presentation is scaled to fit different resolutions | ||
3400 | 42 | width: 960, | ||
3401 | 43 | height: 700, | ||
3402 | 44 | |||
3403 | 45 | // Factor of the display size that should remain empty around the content | ||
3404 | 46 | margin: 0.04, | ||
3405 | 47 | |||
3406 | 48 | // Bounds for smallest/largest possible scale to apply to content | ||
3407 | 49 | minScale: 0.2, | ||
3408 | 50 | maxScale: 2.0, | ||
3409 | 51 | |||
3410 | 52 | // Display presentation control arrows | ||
3411 | 53 | controls: true, | ||
3412 | 54 | |||
3413 | 55 | // Help the user learn the controls by providing hints, for example by | ||
3414 | 56 | // bouncing the down arrow when they first encounter a vertical slide | ||
3415 | 57 | controlsTutorial: true, | ||
3416 | 58 | |||
3417 | 59 | // Determines where controls appear, "edges" or "bottom-right" | ||
3418 | 60 | controlsLayout: 'bottom-right', | ||
3419 | 61 | |||
3420 | 62 | // Visibility rule for backwards navigation arrows; "faded", "hidden" | ||
3421 | 63 | // or "visible" | ||
3422 | 64 | controlsBackArrows: 'faded', | ||
3423 | 65 | |||
3424 | 66 | // Display a presentation progress bar | ||
3425 | 67 | progress: true, | ||
3426 | 68 | |||
3427 | 69 | // Display the page number of the current slide | ||
3428 | 70 | slideNumber: false, | ||
3429 | 71 | |||
3430 | 72 | // Use 1 based indexing for # links to match slide number (default is zero | ||
3431 | 73 | // based) | ||
3432 | 74 | hashOneBasedIndex: false, | ||
3433 | 75 | |||
3434 | 76 | // Determine which displays to show the slide number on | ||
3435 | 77 | showSlideNumber: 'all', | ||
3436 | 78 | |||
3437 | 79 | // Push each slide change to the browser history | ||
3438 | 80 | history: false, | ||
3439 | 81 | |||
3440 | 82 | // Enable keyboard shortcuts for navigation | ||
3441 | 83 | keyboard: true, | ||
3442 | 84 | |||
3443 | 85 | // Optional function that blocks keyboard events when retuning false | ||
3444 | 86 | keyboardCondition: null, | ||
3445 | 87 | |||
3446 | 88 | // Enable the slide overview mode | ||
3447 | 89 | overview: true, | ||
3448 | 90 | |||
3449 | 91 | // Disables the default reveal.js slide layout so that you can use | ||
3450 | 92 | // custom CSS layout | ||
3451 | 93 | disableLayout: false, | ||
3452 | 94 | |||
3453 | 95 | // Vertical centering of slides | ||
3454 | 96 | center: true, | ||
3455 | 97 | |||
3456 | 98 | // Enables touch navigation on devices with touch input | ||
3457 | 99 | touch: true, | ||
3458 | 100 | |||
3459 | 101 | // Loop the presentation | ||
3460 | 102 | loop: false, | ||
3461 | 103 | |||
3462 | 104 | // Change the presentation direction to be RTL | ||
3463 | 105 | rtl: false, | ||
3464 | 106 | |||
3465 | 107 | // Randomizes the order of slides each time the presentation loads | ||
3466 | 108 | shuffle: false, | ||
3467 | 109 | |||
3468 | 110 | // Turns fragments on and off globally | ||
3469 | 111 | fragments: true, | ||
3470 | 112 | |||
3471 | 113 | // Flags whether to include the current fragment in the URL, | ||
3472 | 114 | // so that reloading brings you to the same fragment position | ||
3473 | 115 | fragmentInURL: false, | ||
3474 | 116 | |||
3475 | 117 | // Flags if the presentation is running in an embedded mode, | ||
3476 | 118 | // i.e. contained within a limited portion of the screen | ||
3477 | 119 | embedded: false, | ||
3478 | 120 | |||
3479 | 121 | // Flags if we should show a help overlay when the question-mark | ||
3480 | 122 | // key is pressed | ||
3481 | 123 | help: true, | ||
3482 | 124 | |||
3483 | 125 | // Flags if it should be possible to pause the presentation (blackout) | ||
3484 | 126 | pause: true, | ||
3485 | 127 | |||
3486 | 128 | // Flags if speaker notes should be visible to all viewers | ||
3487 | 129 | showNotes: false, | ||
3488 | 130 | |||
3489 | 131 | // Global override for autolaying embedded media (video/audio/iframe) | ||
3490 | 132 | // - null: Media will only autoplay if data-autoplay is present | ||
3491 | 133 | // - true: All media will autoplay, regardless of individual setting | ||
3492 | 134 | // - false: No media will autoplay, regardless of individual setting | ||
3493 | 135 | autoPlayMedia: null, | ||
3494 | 136 | |||
3495 | 137 | // Controls automatic progression to the next slide | ||
3496 | 138 | // - 0: Auto-sliding only happens if the data-autoslide HTML attribute | ||
3497 | 139 | // is present on the current slide or fragment | ||
3498 | 140 | // - 1+: All slides will progress automatically at the given interval | ||
3499 | 141 | // - false: No auto-sliding, even if data-autoslide is present | ||
3500 | 142 | autoSlide: 0, | ||
3501 | 143 | |||
3502 | 144 | // Stop auto-sliding after user input | ||
3503 | 145 | autoSlideStoppable: true, | ||
3504 | 146 | |||
3505 | 147 | // Use this method for navigation when auto-sliding (defaults to navigateNext) | ||
3506 | 148 | autoSlideMethod: null, | ||
3507 | 149 | |||
3508 | 150 | // Specify the average time in seconds that you think you will spend | ||
3509 | 151 | // presenting each slide. This is used to show a pacing timer in the | ||
3510 | 152 | // speaker view | ||
3511 | 153 | defaultTiming: null, | ||
3512 | 154 | |||
3513 | 155 | // Enable slide navigation via mouse wheel | ||
3514 | 156 | mouseWheel: false, | ||
3515 | 157 | |||
3516 | 158 | // Apply a 3D roll to links on hover | ||
3517 | 159 | rollingLinks: false, | ||
3518 | 160 | |||
3519 | 161 | // Hides the address bar on mobile devices | ||
3520 | 162 | hideAddressBar: true, | ||
3521 | 163 | |||
3522 | 164 | // Opens links in an iframe preview overlay | ||
3523 | 165 | // Add `data-preview-link` and `data-preview-link="false"` to customise each link | ||
3524 | 166 | // individually | ||
3525 | 167 | previewLinks: false, | ||
3526 | 168 | |||
3527 | 169 | // Exposes the reveal.js API through window.postMessage | ||
3528 | 170 | postMessage: true, | ||
3529 | 171 | |||
3530 | 172 | // Dispatches all reveal.js events to the parent window through postMessage | ||
3531 | 173 | postMessageEvents: false, | ||
3532 | 174 | |||
3533 | 175 | // Focuses body when page changes visibility to ensure keyboard shortcuts work | ||
3534 | 176 | focusBodyOnPageVisibilityChange: true, | ||
3535 | 177 | |||
3536 | 178 | // Transition style | ||
3537 | 179 | transition: 'slide', // none/fade/slide/convex/concave/zoom | ||
3538 | 180 | |||
3539 | 181 | // Transition speed | ||
3540 | 182 | transitionSpeed: 'default', // default/fast/slow | ||
3541 | 183 | |||
3542 | 184 | // Transition style for full page slide backgrounds | ||
3543 | 185 | backgroundTransition: 'fade', // none/fade/slide/convex/concave/zoom | ||
3544 | 186 | |||
3545 | 187 | // Parallax background image | ||
3546 | 188 | parallaxBackgroundImage: '', // CSS syntax, e.g. "a.jpg" | ||
3547 | 189 | |||
3548 | 190 | // Parallax background size | ||
3549 | 191 | parallaxBackgroundSize: '', // CSS syntax, e.g. "3000px 2000px" | ||
3550 | 192 | |||
3551 | 193 | // Parallax background repeat | ||
3552 | 194 | parallaxBackgroundRepeat: '', // repeat/repeat-x/repeat-y/no-repeat/initial/inherit | ||
3553 | 195 | |||
3554 | 196 | // Parallax background position | ||
3555 | 197 | parallaxBackgroundPosition: '', // CSS syntax, e.g. "top left" | ||
3556 | 198 | |||
3557 | 199 | // Amount of pixels to move the parallax background per slide step | ||
3558 | 200 | parallaxBackgroundHorizontal: null, | ||
3559 | 201 | parallaxBackgroundVertical: null, | ||
3560 | 202 | |||
3561 | 203 | // The maximum number of pages a single slide can expand onto when printing | ||
3562 | 204 | // to PDF, unlimited by default | ||
3563 | 205 | pdfMaxPagesPerSlide: Number.POSITIVE_INFINITY, | ||
3564 | 206 | |||
3565 | 207 | // Prints each fragment on a separate slide | ||
3566 | 208 | pdfSeparateFragments: true, | ||
3567 | 209 | |||
3568 | 210 | // Offset used to reduce the height of content within exported PDF pages. | ||
3569 | 211 | // This exists to account for environment differences based on how you | ||
3570 | 212 | // print to PDF. CLI printing options, like phantomjs and wkpdf, can end | ||
3571 | 213 | // on precisely the total height of the document whereas in-browser | ||
3572 | 214 | // printing has to end one pixel before. | ||
3573 | 215 | pdfPageHeightOffset: -1, | ||
3574 | 216 | |||
3575 | 217 | // Number of slides away from the current that are visible | ||
3576 | 218 | viewDistance: 3, | ||
3577 | 219 | |||
3578 | 220 | // The display mode that will be used to show slides | ||
3579 | 221 | display: 'block', | ||
3580 | 222 | |||
3581 | 223 | // Script dependencies to load | ||
3582 | 224 | dependencies: [] | ||
3583 | 225 | |||
3584 | 226 | }, | ||
3585 | 227 | |||
3586 | 228 | // Flags if Reveal.initialize() has been called | ||
3587 | 229 | initialized = false, | ||
3588 | 230 | |||
3589 | 231 | // Flags if reveal.js is loaded (has dispatched the 'ready' event) | ||
3590 | 232 | loaded = false, | ||
3591 | 233 | |||
3592 | 234 | // Flags if the overview mode is currently active | ||
3593 | 235 | overview = false, | ||
3594 | 236 | |||
3595 | 237 | // Holds the dimensions of our overview slides, including margins | ||
3596 | 238 | overviewSlideWidth = null, | ||
3597 | 239 | overviewSlideHeight = null, | ||
3598 | 240 | |||
3599 | 241 | // The horizontal and vertical index of the currently active slide | ||
3600 | 242 | indexh, | ||
3601 | 243 | indexv, | ||
3602 | 244 | |||
3603 | 245 | // The previous and current slide HTML elements | ||
3604 | 246 | previousSlide, | ||
3605 | 247 | currentSlide, | ||
3606 | 248 | |||
3607 | 249 | previousBackground, | ||
3608 | 250 | |||
3609 | 251 | // Remember which directions that the user has navigated towards | ||
3610 | 252 | hasNavigatedRight = false, | ||
3611 | 253 | hasNavigatedDown = false, | ||
3612 | 254 | |||
3613 | 255 | // Slides may hold a data-state attribute which we pick up and apply | ||
3614 | 256 | // as a class to the body. This list contains the combined state of | ||
3615 | 257 | // all current slides. | ||
3616 | 258 | state = [], | ||
3617 | 259 | |||
3618 | 260 | // The current scale of the presentation (see width/height config) | ||
3619 | 261 | scale = 1, | ||
3620 | 262 | |||
3621 | 263 | // CSS transform that is currently applied to the slides container, | ||
3622 | 264 | // split into two groups | ||
3623 | 265 | slidesTransform = { layout: '', overview: '' }, | ||
3624 | 266 | |||
3625 | 267 | // Cached references to DOM elements | ||
3626 | 268 | dom = {}, | ||
3627 | 269 | |||
3628 | 270 | // Features supported by the browser, see #checkCapabilities() | ||
3629 | 271 | features = {}, | ||
3630 | 272 | |||
3631 | 273 | // Client is a mobile device, see #checkCapabilities() | ||
3632 | 274 | isMobileDevice, | ||
3633 | 275 | |||
3634 | 276 | // Client is a desktop Chrome, see #checkCapabilities() | ||
3635 | 277 | isChrome, | ||
3636 | 278 | |||
3637 | 279 | // Throttles mouse wheel navigation | ||
3638 | 280 | lastMouseWheelStep = 0, | ||
3639 | 281 | |||
3640 | 282 | // Delays updates to the URL due to a Chrome thumbnailer bug | ||
3641 | 283 | writeURLTimeout = 0, | ||
3642 | 284 | |||
3643 | 285 | // Flags if the interaction event listeners are bound | ||
3644 | 286 | eventsAreBound = false, | ||
3645 | 287 | |||
3646 | 288 | // The current auto-slide duration | ||
3647 | 289 | autoSlide = 0, | ||
3648 | 290 | |||
3649 | 291 | // Auto slide properties | ||
3650 | 292 | autoSlidePlayer, | ||
3651 | 293 | autoSlideTimeout = 0, | ||
3652 | 294 | autoSlideStartTime = -1, | ||
3653 | 295 | autoSlidePaused = false, | ||
3654 | 296 | |||
3655 | 297 | // Holds information about the currently ongoing touch input | ||
3656 | 298 | touch = { | ||
3657 | 299 | startX: 0, | ||
3658 | 300 | startY: 0, | ||
3659 | 301 | startSpan: 0, | ||
3660 | 302 | startCount: 0, | ||
3661 | 303 | captured: false, | ||
3662 | 304 | threshold: 40 | ||
3663 | 305 | }, | ||
3664 | 306 | |||
3665 | 307 | // Holds information about the keyboard shortcuts | ||
3666 | 308 | keyboardShortcuts = { | ||
3667 | 309 | 'N , SPACE': 'Next slide', | ||
3668 | 310 | 'P': 'Previous slide', | ||
3669 | 311 | '← , H': 'Navigate left', | ||
3670 | 312 | '→ , L': 'Navigate right', | ||
3671 | 313 | '↑ , K': 'Navigate up', | ||
3672 | 314 | '↓ , J': 'Navigate down', | ||
3673 | 315 | 'Home': 'First slide', | ||
3674 | 316 | 'End': 'Last slide', | ||
3675 | 317 | 'B , .': 'Pause', | ||
3676 | 318 | 'F': 'Fullscreen', | ||
3677 | 319 | 'ESC, O': 'Slide overview' | ||
3678 | 320 | }, | ||
3679 | 321 | |||
3680 | 322 | // Holds custom key code mappings | ||
3681 | 323 | registeredKeyBindings = {}; | ||
3682 | 324 | |||
3683 | 325 | /** | ||
3684 | 326 | * Starts up the presentation if the client is capable. | ||
3685 | 327 | */ | ||
3686 | 328 | function initialize( options ) { | ||
3687 | 329 | |||
3688 | 330 | // Make sure we only initialize once | ||
3689 | 331 | if( initialized === true ) return; | ||
3690 | 332 | |||
3691 | 333 | initialized = true; | ||
3692 | 334 | |||
3693 | 335 | checkCapabilities(); | ||
3694 | 336 | |||
3695 | 337 | if( !features.transforms2d && !features.transforms3d ) { | ||
3696 | 338 | document.body.setAttribute( 'class', 'no-transforms' ); | ||
3697 | 339 | |||
3698 | 340 | // Since JS won't be running any further, we load all lazy | ||
3699 | 341 | // loading elements upfront | ||
3700 | 342 | var images = toArray( document.getElementsByTagName( 'img' ) ), | ||
3701 | 343 | iframes = toArray( document.getElementsByTagName( 'iframe' ) ); | ||
3702 | 344 | |||
3703 | 345 | var lazyLoadable = images.concat( iframes ); | ||
3704 | 346 | |||
3705 | 347 | for( var i = 0, len = lazyLoadable.length; i < len; i++ ) { | ||
3706 | 348 | var element = lazyLoadable[i]; | ||
3707 | 349 | if( element.getAttribute( 'data-src' ) ) { | ||
3708 | 350 | element.setAttribute( 'src', element.getAttribute( 'data-src' ) ); | ||
3709 | 351 | element.removeAttribute( 'data-src' ); | ||
3710 | 352 | } | ||
3711 | 353 | } | ||
3712 | 354 | |||
3713 | 355 | // If the browser doesn't support core features we won't be | ||
3714 | 356 | // using JavaScript to control the presentation | ||
3715 | 357 | return; | ||
3716 | 358 | } | ||
3717 | 359 | |||
3718 | 360 | // Cache references to key DOM elements | ||
3719 | 361 | dom.wrapper = document.querySelector( '.reveal' ); | ||
3720 | 362 | dom.slides = document.querySelector( '.reveal .slides' ); | ||
3721 | 363 | |||
3722 | 364 | // Force a layout when the whole page, incl fonts, has loaded | ||
3723 | 365 | window.addEventListener( 'load', layout, false ); | ||
3724 | 366 | |||
3725 | 367 | var query = Reveal.getQueryHash(); | ||
3726 | 368 | |||
3727 | 369 | // Do not accept new dependencies via query config to avoid | ||
3728 | 370 | // the potential of malicious script injection | ||
3729 | 371 | if( typeof query['dependencies'] !== 'undefined' ) delete query['dependencies']; | ||
3730 | 372 | |||
3731 | 373 | // Copy options over to our config object | ||
3732 | 374 | extend( config, options ); | ||
3733 | 375 | extend( config, query ); | ||
3734 | 376 | |||
3735 | 377 | // Hide the address bar in mobile browsers | ||
3736 | 378 | hideAddressBar(); | ||
3737 | 379 | |||
3738 | 380 | // Loads the dependencies and continues to #start() once done | ||
3739 | 381 | load(); | ||
3740 | 382 | |||
3741 | 383 | } | ||
3742 | 384 | |||
3743 | 385 | /** | ||
3744 | 386 | * Restarts up the presentation if the client is capable. | ||
3745 | 387 | */ | ||
3746 | 388 | function reinitialize() { | ||
3747 | 389 | initialized = false; | ||
3748 | 390 | initialize(config); | ||
3749 | 391 | } | ||
3750 | 392 | |||
3751 | 393 | /** | ||
3752 | 394 | * Inspect the client to see what it's capable of, this | ||
3753 | 395 | * should only happens once per runtime. | ||
3754 | 396 | */ | ||
3755 | 397 | function checkCapabilities() { | ||
3756 | 398 | |||
3757 | 399 | isMobileDevice = /(iphone|ipod|ipad|android)/gi.test( UA ); | ||
3758 | 400 | isChrome = /chrome/i.test( UA ) && !/edge/i.test( UA ); | ||
3759 | 401 | |||
3760 | 402 | var testElement = document.createElement( 'div' ); | ||
3761 | 403 | |||
3762 | 404 | features.transforms3d = 'WebkitPerspective' in testElement.style || | ||
3763 | 405 | 'MozPerspective' in testElement.style || | ||
3764 | 406 | 'msPerspective' in testElement.style || | ||
3765 | 407 | 'OPerspective' in testElement.style || | ||
3766 | 408 | 'perspective' in testElement.style; | ||
3767 | 409 | |||
3768 | 410 | features.transforms2d = 'WebkitTransform' in testElement.style || | ||
3769 | 411 | 'MozTransform' in testElement.style || | ||
3770 | 412 | 'msTransform' in testElement.style || | ||
3771 | 413 | 'OTransform' in testElement.style || | ||
3772 | 414 | 'transform' in testElement.style; | ||
3773 | 415 | |||
3774 | 416 | features.requestAnimationFrameMethod = window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame; | ||
3775 | 417 | features.requestAnimationFrame = typeof features.requestAnimationFrameMethod === 'function'; | ||
3776 | 418 | |||
3777 | 419 | features.canvas = !!document.createElement( 'canvas' ).getContext; | ||
3778 | 420 | |||
3779 | 421 | // Transitions in the overview are disabled in desktop and | ||
3780 | 422 | // Safari due to lag | ||
3781 | 423 | features.overviewTransitions = !/Version\/[\d\.]+.*Safari/.test( UA ); | ||
3782 | 424 | |||
3783 | 425 | // Flags if we should use zoom instead of transform to scale | ||
3784 | 426 | // up slides. Zoom produces crisper results but has a lot of | ||
3785 | 427 | // xbrowser quirks so we only use it in whitelsited browsers. | ||
3786 | 428 | features.zoom = 'zoom' in testElement.style && !isMobileDevice && | ||
3787 | 429 | ( isChrome || /Version\/[\d\.]+.*Safari/.test( UA ) ); | ||
3788 | 430 | |||
3789 | 431 | } | ||
3790 | 432 | |||
3791 | 433 | /** | ||
3792 | 434 | * Loads the dependencies of reveal.js. Dependencies are | ||
3793 | 435 | * defined via the configuration option 'dependencies' | ||
3794 | 436 | * and will be loaded prior to starting/binding reveal.js. | ||
3795 | 437 | * Some dependencies may have an 'async' flag, if so they | ||
3796 | 438 | * will load after reveal.js has been started up. | ||
3797 | 439 | */ | ||
3798 | 440 | function load() { | ||
3799 | 441 | |||
3800 | 442 | var scripts = [], | ||
3801 | 443 | scriptsAsync = [], | ||
3802 | 444 | scriptsToPreload = 0; | ||
3803 | 445 | |||
3804 | 446 | // Called once synchronous scripts finish loading | ||
3805 | 447 | function proceed() { | ||
3806 | 448 | if( scriptsAsync.length ) { | ||
3807 | 449 | // Load asynchronous scripts | ||
3808 | 450 | head.js.apply( null, scriptsAsync ); | ||
3809 | 451 | } | ||
3810 | 452 | |||
3811 | 453 | start(); | ||
3812 | 454 | } | ||
3813 | 455 | |||
3814 | 456 | function loadScript( s ) { | ||
3815 | 457 | head.ready( s.src.match( /([\w\d_\-]*)\.?js(\?[\w\d.=&]*)?$|[^\\\/]*$/i )[0], function() { | ||
3816 | 458 | // Extension may contain callback functions | ||
3817 | 459 | if( typeof s.callback === 'function' ) { | ||
3818 | 460 | s.callback.apply( this ); | ||
3819 | 461 | } | ||
3820 | 462 | |||
3821 | 463 | if( --scriptsToPreload === 0 ) { | ||
3822 | 464 | proceed(); | ||
3823 | 465 | } | ||
3824 | 466 | }); | ||
3825 | 467 | } | ||
3826 | 468 | |||
3827 | 469 | for( var i = 0, len = config.dependencies.length; i < len; i++ ) { | ||
3828 | 470 | var s = config.dependencies[i]; | ||
3829 | 471 | |||
3830 | 472 | // Load if there's no condition or the condition is truthy | ||
3831 | 473 | if( !s.condition || s.condition() ) { | ||
3832 | 474 | if( s.async ) { | ||
3833 | 475 | scriptsAsync.push( s.src ); | ||
3834 | 476 | } | ||
3835 | 477 | else { | ||
3836 | 478 | scripts.push( s.src ); | ||
3837 | 479 | } | ||
3838 | 480 | |||
3839 | 481 | loadScript( s ); | ||
3840 | 482 | } | ||
3841 | 483 | } | ||
3842 | 484 | |||
3843 | 485 | if( scripts.length ) { | ||
3844 | 486 | scriptsToPreload = scripts.length; | ||
3845 | 487 | |||
3846 | 488 | // Load synchronous scripts | ||
3847 | 489 | head.js.apply( null, scripts ); | ||
3848 | 490 | } | ||
3849 | 491 | else { | ||
3850 | 492 | proceed(); | ||
3851 | 493 | } | ||
3852 | 494 | |||
3853 | 495 | } | ||
3854 | 496 | |||
3855 | 497 | /** | ||
3856 | 498 | * Starts up reveal.js by binding input events and navigating | ||
3857 | 499 | * to the current URL deeplink if there is one. | ||
3858 | 500 | */ | ||
3859 | 501 | function start() { | ||
3860 | 502 | |||
3861 | 503 | loaded = true; | ||
3862 | 504 | |||
3863 | 505 | // Make sure we've got all the DOM elements we need | ||
3864 | 506 | setupDOM(); | ||
3865 | 507 | |||
3866 | 508 | // Listen to messages posted to this window | ||
3867 | 509 | setupPostMessage(); | ||
3868 | 510 | |||
3869 | 511 | // Prevent the slides from being scrolled out of view | ||
3870 | 512 | setupScrollPrevention(); | ||
3871 | 513 | |||
3872 | 514 | // Resets all vertical slides so that only the first is visible | ||
3873 | 515 | resetVerticalSlides(); | ||
3874 | 516 | |||
3875 | 517 | // Updates the presentation to match the current configuration values | ||
3876 | 518 | configure(); | ||
3877 | 519 | |||
3878 | 520 | // Read the initial hash | ||
3879 | 521 | readURL(); | ||
3880 | 522 | |||
3881 | 523 | // Update all backgrounds | ||
3882 | 524 | updateBackground( true ); | ||
3883 | 525 | |||
3884 | 526 | // Notify listeners that the presentation is ready but use a 1ms | ||
3885 | 527 | // timeout to ensure it's not fired synchronously after #initialize() | ||
3886 | 528 | setTimeout( function() { | ||
3887 | 529 | // Enable transitions now that we're loaded | ||
3888 | 530 | dom.slides.classList.remove( 'no-transition' ); | ||
3889 | 531 | |||
3890 | 532 | dom.wrapper.classList.add( 'ready' ); | ||
3891 | 533 | |||
3892 | 534 | dispatchEvent( 'ready', { | ||
3893 | 535 | 'indexh': indexh, | ||
3894 | 536 | 'indexv': indexv, | ||
3895 | 537 | 'currentSlide': currentSlide | ||
3896 | 538 | } ); | ||
3897 | 539 | }, 1 ); | ||
3898 | 540 | |||
3899 | 541 | // Special setup and config is required when printing to PDF | ||
3900 | 542 | if( isPrintingPDF() ) { | ||
3901 | 543 | removeEventListeners(); | ||
3902 | 544 | |||
3903 | 545 | // The document needs to have loaded for the PDF layout | ||
3904 | 546 | // measurements to be accurate | ||
3905 | 547 | if( document.readyState === 'complete' ) { | ||
3906 | 548 | setupPDF(); | ||
3907 | 549 | } | ||
3908 | 550 | else { | ||
3909 | 551 | window.addEventListener( 'load', setupPDF ); | ||
3910 | 552 | } | ||
3911 | 553 | } | ||
3912 | 554 | |||
3913 | 555 | } | ||
3914 | 556 | |||
3915 | 557 | /** | ||
3916 | 558 | * Finds and stores references to DOM elements which are | ||
3917 | 559 | * required by the presentation. If a required element is | ||
3918 | 560 | * not found, it is created. | ||
3919 | 561 | */ | ||
3920 | 562 | function setupDOM() { | ||
3921 | 563 | |||
3922 | 564 | // Prevent transitions while we're loading | ||
3923 | 565 | dom.slides.classList.add( 'no-transition' ); | ||
3924 | 566 | |||
3925 | 567 | if( isMobileDevice ) { | ||
3926 | 568 | dom.wrapper.classList.add( 'no-hover' ); | ||
3927 | 569 | } | ||
3928 | 570 | else { | ||
3929 | 571 | dom.wrapper.classList.remove( 'no-hover' ); | ||
3930 | 572 | } | ||
3931 | 573 | |||
3932 | 574 | if( /iphone/gi.test( UA ) ) { | ||
3933 | 575 | dom.wrapper.classList.add( 'ua-iphone' ); | ||
3934 | 576 | } | ||
3935 | 577 | else { | ||
3936 | 578 | dom.wrapper.classList.remove( 'ua-iphone' ); | ||
3937 | 579 | } | ||
3938 | 580 | |||
3939 | 581 | // Background element | ||
3940 | 582 | dom.background = createSingletonNode( dom.wrapper, 'div', 'backgrounds', null ); | ||
3941 | 583 | |||
3942 | 584 | // Progress bar | ||
3943 | 585 | dom.progress = createSingletonNode( dom.wrapper, 'div', 'progress', '<span></span>' ); | ||
3944 | 586 | dom.progressbar = dom.progress.querySelector( 'span' ); | ||
3945 | 587 | |||
3946 | 588 | // Arrow controls | ||
3947 | 589 | dom.controls = createSingletonNode( dom.wrapper, 'aside', 'controls', | ||
3948 | 590 | '<button class="navigate-left" aria-label="previous slide"><div class="controls-arrow"></div></button>' + | ||
3949 | 591 | '<button class="navigate-right" aria-label="next slide"><div class="controls-arrow"></div></button>' + | ||
3950 | 592 | '<button class="navigate-up" aria-label="above slide"><div class="controls-arrow"></div></button>' + | ||
3951 | 593 | '<button class="navigate-down" aria-label="below slide"><div class="controls-arrow"></div></button>' ); | ||
3952 | 594 | |||
3953 | 595 | // Slide number | ||
3954 | 596 | dom.slideNumber = createSingletonNode( dom.wrapper, 'div', 'slide-number', '' ); | ||
3955 | 597 | |||
3956 | 598 | // Element containing notes that are visible to the audience | ||
3957 | 599 | dom.speakerNotes = createSingletonNode( dom.wrapper, 'div', 'speaker-notes', null ); | ||
3958 | 600 | dom.speakerNotes.setAttribute( 'data-prevent-swipe', '' ); | ||
3959 | 601 | dom.speakerNotes.setAttribute( 'tabindex', '0' ); | ||
3960 | 602 | |||
3961 | 603 | // Overlay graphic which is displayed during the paused mode | ||
3962 | 604 | dom.pauseOverlay = createSingletonNode( dom.wrapper, 'div', 'pause-overlay', '<button class="resume-button">Resume presentation</button>' ); | ||
3963 | 605 | dom.resumeButton = dom.pauseOverlay.querySelector( '.resume-button' ); | ||
3964 | 606 | |||
3965 | 607 | dom.wrapper.setAttribute( 'role', 'application' ); | ||
3966 | 608 | |||
3967 | 609 | // There can be multiple instances of controls throughout the page | ||
3968 | 610 | dom.controlsLeft = toArray( document.querySelectorAll( '.navigate-left' ) ); | ||
3969 | 611 | dom.controlsRight = toArray( document.querySelectorAll( '.navigate-right' ) ); | ||
3970 | 612 | dom.controlsUp = toArray( document.querySelectorAll( '.navigate-up' ) ); | ||
3971 | 613 | dom.controlsDown = toArray( document.querySelectorAll( '.navigate-down' ) ); | ||
3972 | 614 | dom.controlsPrev = toArray( document.querySelectorAll( '.navigate-prev' ) ); | ||
3973 | 615 | dom.controlsNext = toArray( document.querySelectorAll( '.navigate-next' ) ); | ||
3974 | 616 | |||
3975 | 617 | // The right and down arrows in the standard reveal.js controls | ||
3976 | 618 | dom.controlsRightArrow = dom.controls.querySelector( '.navigate-right' ); | ||
3977 | 619 | dom.controlsDownArrow = dom.controls.querySelector( '.navigate-down' ); | ||
3978 | 620 | |||
3979 | 621 | dom.statusDiv = createStatusDiv(); | ||
3980 | 622 | } | ||
3981 | 623 | |||
3982 | 624 | /** | ||
3983 | 625 | * Creates a hidden div with role aria-live to announce the | ||
3984 | 626 | * current slide content. Hide the div off-screen to make it | ||
3985 | 627 | * available only to Assistive Technologies. | ||
3986 | 628 | * | ||
3987 | 629 | * @return {HTMLElement} | ||
3988 | 630 | */ | ||
3989 | 631 | function createStatusDiv() { | ||
3990 | 632 | |||
3991 | 633 | var statusDiv = document.getElementById( 'aria-status-div' ); | ||
3992 | 634 | if( !statusDiv ) { | ||
3993 | 635 | statusDiv = document.createElement( 'div' ); | ||
3994 | 636 | statusDiv.style.position = 'absolute'; | ||
3995 | 637 | statusDiv.style.height = '1px'; | ||
3996 | 638 | statusDiv.style.width = '1px'; | ||
3997 | 639 | statusDiv.style.overflow = 'hidden'; | ||
3998 | 640 | statusDiv.style.clip = 'rect( 1px, 1px, 1px, 1px )'; | ||
3999 | 641 | statusDiv.setAttribute( 'id', 'aria-status-div' ); | ||
4000 | 642 | statusDiv.setAttribute( 'aria-live', 'polite' ); | ||
4001 | 643 | statusDiv.setAttribute( 'aria-atomic','true' ); | ||
4002 | 644 | dom.wrapper.appendChild( statusDiv ); | ||
4003 | 645 | } | ||
4004 | 646 | return statusDiv; | ||
4005 | 647 | |||
4006 | 648 | } | ||
4007 | 649 | |||
4008 | 650 | /** | ||
4009 | 651 | * Converts the given HTML element into a string of text | ||
4010 | 652 | * that can be announced to a screen reader. Hidden | ||
4011 | 653 | * elements are excluded. | ||
4012 | 654 | */ | ||
4013 | 655 | function getStatusText( node ) { | ||
4014 | 656 | |||
4015 | 657 | var text = ''; | ||
4016 | 658 | |||
4017 | 659 | // Text node | ||
4018 | 660 | if( node.nodeType === 3 ) { | ||
4019 | 661 | text += node.textContent; | ||
4020 | 662 | } | ||
4021 | 663 | // Element node | ||
4022 | 664 | else if( node.nodeType === 1 ) { | ||
4023 | 665 | |||
4024 | 666 | var isAriaHidden = node.getAttribute( 'aria-hidden' ); | ||
4025 | 667 | var isDisplayHidden = window.getComputedStyle( node )['display'] === 'none'; | ||
4026 | 668 | if( isAriaHidden !== 'true' && !isDisplayHidden ) { | ||
4027 | 669 | |||
4028 | 670 | toArray( node.childNodes ).forEach( function( child ) { | ||
4029 | 671 | text += getStatusText( child ); | ||
4030 | 672 | } ); | ||
4031 | 673 | |||
4032 | 674 | } | ||
4033 | 675 | |||
4034 | 676 | } | ||
4035 | 677 | |||
4036 | 678 | return text; | ||
4037 | 679 | |||
4038 | 680 | } | ||
4039 | 681 | |||
4040 | 682 | /** | ||
4041 | 683 | * Configures the presentation for printing to a static | ||
4042 | 684 | * PDF. | ||
4043 | 685 | */ | ||
4044 | 686 | function setupPDF() { | ||
4045 | 687 | |||
4046 | 688 | var slideSize = getComputedSlideSize( window.innerWidth, window.innerHeight ); | ||
4047 | 689 | |||
4048 | 690 | // Dimensions of the PDF pages | ||
4049 | 691 | var pageWidth = Math.floor( slideSize.width * ( 1 + config.margin ) ), | ||
4050 | 692 | pageHeight = Math.floor( slideSize.height * ( 1 + config.margin ) ); | ||
4051 | 693 | |||
4052 | 694 | // Dimensions of slides within the pages | ||
4053 | 695 | var slideWidth = slideSize.width, | ||
4054 | 696 | slideHeight = slideSize.height; | ||
4055 | 697 | |||
4056 | 698 | // Let the browser know what page size we want to print | ||
4057 | 699 | injectStyleSheet( '@page{size:'+ pageWidth +'px '+ pageHeight +'px; margin: 0px;}' ); | ||
4058 | 700 | |||
4059 | 701 | // Limit the size of certain elements to the dimensions of the slide | ||
4060 | 702 | injectStyleSheet( '.reveal section>img, .reveal section>video, .reveal section>iframe{max-width: '+ slideWidth +'px; max-height:'+ slideHeight +'px}' ); | ||
4061 | 703 | |||
4062 | 704 | document.body.classList.add( 'print-pdf' ); | ||
4063 | 705 | document.body.style.width = pageWidth + 'px'; | ||
4064 | 706 | document.body.style.height = pageHeight + 'px'; | ||
4065 | 707 | |||
4066 | 708 | // Make sure stretch elements fit on slide | ||
4067 | 709 | layoutSlideContents( slideWidth, slideHeight ); | ||
4068 | 710 | |||
4069 | 711 | // Add each slide's index as attributes on itself, we need these | ||
4070 | 712 | // indices to generate slide numbers below | ||
4071 | 713 | toArray( dom.wrapper.querySelectorAll( HORIZONTAL_SLIDES_SELECTOR ) ).forEach( function( hslide, h ) { | ||
4072 | 714 | hslide.setAttribute( 'data-index-h', h ); | ||
4073 | 715 | |||
4074 | 716 | if( hslide.classList.contains( 'stack' ) ) { | ||
4075 | 717 | toArray( hslide.querySelectorAll( 'section' ) ).forEach( function( vslide, v ) { | ||
4076 | 718 | vslide.setAttribute( 'data-index-h', h ); | ||
4077 | 719 | vslide.setAttribute( 'data-index-v', v ); | ||
4078 | 720 | } ); | ||
4079 | 721 | } | ||
4080 | 722 | } ); | ||
4081 | 723 | |||
4082 | 724 | // Slide and slide background layout | ||
4083 | 725 | toArray( dom.wrapper.querySelectorAll( SLIDES_SELECTOR ) ).forEach( function( slide ) { | ||
4084 | 726 | |||
4085 | 727 | // Vertical stacks are not centred since their section | ||
4086 | 728 | // children will be | ||
4087 | 729 | if( slide.classList.contains( 'stack' ) === false ) { | ||
4088 | 730 | // Center the slide inside of the page, giving the slide some margin | ||
4089 | 731 | var left = ( pageWidth - slideWidth ) / 2, | ||
4090 | 732 | top = ( pageHeight - slideHeight ) / 2; | ||
4091 | 733 | |||
4092 | 734 | var contentHeight = slide.scrollHeight; | ||
4093 | 735 | var numberOfPages = Math.max( Math.ceil( contentHeight / pageHeight ), 1 ); | ||
4094 | 736 | |||
4095 | 737 | // Adhere to configured pages per slide limit | ||
4096 | 738 | numberOfPages = Math.min( numberOfPages, config.pdfMaxPagesPerSlide ); | ||
4097 | 739 | |||
4098 | 740 | // Center slides vertically | ||
4099 | 741 | if( numberOfPages === 1 && config.center || slide.classList.contains( 'center' ) ) { | ||
4100 | 742 | top = Math.max( ( pageHeight - contentHeight ) / 2, 0 ); | ||
4101 | 743 | } | ||
4102 | 744 | |||
4103 | 745 | // Wrap the slide in a page element and hide its overflow | ||
4104 | 746 | // so that no page ever flows onto another | ||
4105 | 747 | var page = document.createElement( 'div' ); | ||
4106 | 748 | page.className = 'pdf-page'; | ||
4107 | 749 | page.style.height = ( ( pageHeight + config.pdfPageHeightOffset ) * numberOfPages ) + 'px'; | ||
4108 | 750 | slide.parentNode.insertBefore( page, slide ); | ||
4109 | 751 | page.appendChild( slide ); | ||
4110 | 752 | |||
4111 | 753 | // Position the slide inside of the page | ||
4112 | 754 | slide.style.left = left + 'px'; | ||
4113 | 755 | slide.style.top = top + 'px'; | ||
4114 | 756 | slide.style.width = slideWidth + 'px'; | ||
4115 | 757 | |||
4116 | 758 | if( slide.slideBackgroundElement ) { | ||
4117 | 759 | page.insertBefore( slide.slideBackgroundElement, slide ); | ||
4118 | 760 | } | ||
4119 | 761 | |||
4120 | 762 | // Inject notes if `showNotes` is enabled | ||
4121 | 763 | if( config.showNotes ) { | ||
4122 | 764 | |||
4123 | 765 | // Are there notes for this slide? | ||
4124 | 766 | var notes = getSlideNotes( slide ); | ||
4125 | 767 | if( notes ) { | ||
4126 | 768 | |||
4127 | 769 | var notesSpacing = 8; | ||
4128 | 770 | var notesLayout = typeof config.showNotes === 'string' ? config.showNotes : 'inline'; | ||
4129 | 771 | var notesElement = document.createElement( 'div' ); | ||
4130 | 772 | notesElement.classList.add( 'speaker-notes' ); | ||
4131 | 773 | notesElement.classList.add( 'speaker-notes-pdf' ); | ||
4132 | 774 | notesElement.setAttribute( 'data-layout', notesLayout ); | ||
4133 | 775 | notesElement.innerHTML = notes; | ||
4134 | 776 | |||
4135 | 777 | if( notesLayout === 'separate-page' ) { | ||
4136 | 778 | page.parentNode.insertBefore( notesElement, page.nextSibling ); | ||
4137 | 779 | } | ||
4138 | 780 | else { | ||
4139 | 781 | notesElement.style.left = notesSpacing + 'px'; | ||
4140 | 782 | notesElement.style.bottom = notesSpacing + 'px'; | ||
4141 | 783 | notesElement.style.width = ( pageWidth - notesSpacing*2 ) + 'px'; | ||
4142 | 784 | page.appendChild( notesElement ); | ||
4143 | 785 | } | ||
4144 | 786 | |||
4145 | 787 | } | ||
4146 | 788 | |||
4147 | 789 | } | ||
4148 | 790 | |||
4149 | 791 | // Inject slide numbers if `slideNumbers` are enabled | ||
4150 | 792 | if( config.slideNumber && /all|print/i.test( config.showSlideNumber ) ) { | ||
4151 | 793 | var slideNumberH = parseInt( slide.getAttribute( 'data-index-h' ), 10 ) + 1, | ||
4152 | 794 | slideNumberV = parseInt( slide.getAttribute( 'data-index-v' ), 10 ) + 1; | ||
4153 | 795 | |||
4154 | 796 | var numberElement = document.createElement( 'div' ); | ||
4155 | 797 | numberElement.classList.add( 'slide-number' ); | ||
4156 | 798 | numberElement.classList.add( 'slide-number-pdf' ); | ||
4157 | 799 | numberElement.innerHTML = formatSlideNumber( slideNumberH, '.', slideNumberV ); | ||
4158 | 800 | page.appendChild( numberElement ); | ||
4159 | 801 | } | ||
4160 | 802 | |||
4161 | 803 | // Copy page and show fragments one after another | ||
4162 | 804 | if( config.pdfSeparateFragments ) { | ||
4163 | 805 | |||
4164 | 806 | // Each fragment 'group' is an array containing one or more | ||
4165 | 807 | // fragments. Multiple fragments that appear at the same time | ||
4166 | 808 | // are part of the same group. | ||
4167 | 809 | var fragmentGroups = sortFragments( page.querySelectorAll( '.fragment' ), true ); | ||
4168 | 810 | |||
4169 | 811 | var previousFragmentStep; | ||
4170 | 812 | var previousPage; | ||
4171 | 813 | |||
4172 | 814 | fragmentGroups.forEach( function( fragments ) { | ||
4173 | 815 | |||
4174 | 816 | // Remove 'current-fragment' from the previous group | ||
4175 | 817 | if( previousFragmentStep ) { | ||
4176 | 818 | previousFragmentStep.forEach( function( fragment ) { | ||
4177 | 819 | fragment.classList.remove( 'current-fragment' ); | ||
4178 | 820 | } ); | ||
4179 | 821 | } | ||
4180 | 822 | |||
4181 | 823 | // Show the fragments for the current index | ||
4182 | 824 | fragments.forEach( function( fragment ) { | ||
4183 | 825 | fragment.classList.add( 'visible', 'current-fragment' ); | ||
4184 | 826 | } ); | ||
4185 | 827 | |||
4186 | 828 | // Create a separate page for the current fragment state | ||
4187 | 829 | var clonedPage = page.cloneNode( true ); | ||
4188 | 830 | page.parentNode.insertBefore( clonedPage, ( previousPage || page ).nextSibling ); | ||
4189 | 831 | |||
4190 | 832 | previousFragmentStep = fragments; | ||
4191 | 833 | previousPage = clonedPage; | ||
4192 | 834 | |||
4193 | 835 | } ); | ||
4194 | 836 | |||
4195 | 837 | // Reset the first/original page so that all fragments are hidden | ||
4196 | 838 | fragmentGroups.forEach( function( fragments ) { | ||
4197 | 839 | fragments.forEach( function( fragment ) { | ||
4198 | 840 | fragment.classList.remove( 'visible', 'current-fragment' ); | ||
4199 | 841 | } ); | ||
4200 | 842 | } ); | ||
4201 | 843 | |||
4202 | 844 | } | ||
4203 | 845 | // Show all fragments | ||
4204 | 846 | else { | ||
4205 | 847 | toArray( page.querySelectorAll( '.fragment:not(.fade-out)' ) ).forEach( function( fragment ) { | ||
4206 | 848 | fragment.classList.add( 'visible' ); | ||
4207 | 849 | } ); | ||
4208 | 850 | } | ||
4209 | 851 | |||
4210 | 852 | } | ||
4211 | 853 | |||
4212 | 854 | } ); | ||
4213 | 855 | |||
4214 | 856 | // Notify subscribers that the PDF layout is good to go | ||
4215 | 857 | dispatchEvent( 'pdf-ready' ); | ||
4216 | 858 | |||
4217 | 859 | } | ||
4218 | 860 | |||
4219 | 861 | /** | ||
4220 | 862 | * This is an unfortunate necessity. Some actions – such as | ||
4221 | 863 | * an input field being focused in an iframe or using the | ||
4222 | 864 | * keyboard to expand text selection beyond the bounds of | ||
4223 | 865 | * a slide – can trigger our content to be pushed out of view. | ||
4224 | 866 | * This scrolling can not be prevented by hiding overflow in | ||
4225 | 867 | * CSS (we already do) so we have to resort to repeatedly | ||
4226 | 868 | * checking if the slides have been offset :( | ||
4227 | 869 | */ | ||
4228 | 870 | function setupScrollPrevention() { | ||
4229 | 871 | |||
4230 | 872 | setInterval( function() { | ||
4231 | 873 | if( dom.wrapper.scrollTop !== 0 || dom.wrapper.scrollLeft !== 0 ) { | ||
4232 | 874 | dom.wrapper.scrollTop = 0; | ||
4233 | 875 | dom.wrapper.scrollLeft = 0; | ||
4234 | 876 | } | ||
4235 | 877 | }, 1000 ); | ||
4236 | 878 | |||
4237 | 879 | } | ||
4238 | 880 | |||
4239 | 881 | /** | ||
4240 | 882 | * Creates an HTML element and returns a reference to it. | ||
4241 | 883 | * If the element already exists the existing instance will | ||
4242 | 884 | * be returned. | ||
4243 | 885 | * | ||
4244 | 886 | * @param {HTMLElement} container | ||
4245 | 887 | * @param {string} tagname | ||
4246 | 888 | * @param {string} classname | ||
4247 | 889 | * @param {string} innerHTML | ||
4248 | 890 | * | ||
4249 | 891 | * @return {HTMLElement} | ||
4250 | 892 | */ | ||
4251 | 893 | function createSingletonNode( container, tagname, classname, innerHTML ) { | ||
4252 | 894 | |||
4253 | 895 | // Find all nodes matching the description | ||
4254 | 896 | var nodes = container.querySelectorAll( '.' + classname ); | ||
4255 | 897 | |||
4256 | 898 | // Check all matches to find one which is a direct child of | ||
4257 | 899 | // the specified container | ||
4258 | 900 | for( var i = 0; i < nodes.length; i++ ) { | ||
4259 | 901 | var testNode = nodes[i]; | ||
4260 | 902 | if( testNode.parentNode === container ) { | ||
4261 | 903 | return testNode; | ||
4262 | 904 | } | ||
4263 | 905 | } | ||
4264 | 906 | |||
4265 | 907 | // If no node was found, create it now | ||
4266 | 908 | var node = document.createElement( tagname ); | ||
4267 | 909 | node.className = classname; | ||
4268 | 910 | if( typeof innerHTML === 'string' ) { | ||
4269 | 911 | node.innerHTML = innerHTML; | ||
4270 | 912 | } | ||
4271 | 913 | container.appendChild( node ); | ||
4272 | 914 | |||
4273 | 915 | return node; | ||
4274 | 916 | |||
4275 | 917 | } | ||
4276 | 918 | |||
4277 | 919 | /** | ||
4278 | 920 | * Creates the slide background elements and appends them | ||
4279 | 921 | * to the background container. One element is created per | ||
4280 | 922 | * slide no matter if the given slide has visible background. | ||
4281 | 923 | */ | ||
4282 | 924 | function createBackgrounds() { | ||
4283 | 925 | |||
4284 | 926 | var printMode = isPrintingPDF(); | ||
4285 | 927 | |||
4286 | 928 | // Clear prior backgrounds | ||
4287 | 929 | dom.background.innerHTML = ''; | ||
4288 | 930 | dom.background.classList.add( 'no-transition' ); | ||
4289 | 931 | |||
4290 | 932 | // Iterate over all horizontal slides | ||
4291 | 933 | toArray( dom.wrapper.querySelectorAll( HORIZONTAL_SLIDES_SELECTOR ) ).forEach( function( slideh ) { | ||
4292 | 934 | |||
4293 | 935 | var backgroundStack = createBackground( slideh, dom.background ); | ||
4294 | 936 | |||
4295 | 937 | // Iterate over all vertical slides | ||
4296 | 938 | toArray( slideh.querySelectorAll( 'section' ) ).forEach( function( slidev ) { | ||
4297 | 939 | |||
4298 | 940 | createBackground( slidev, backgroundStack ); | ||
4299 | 941 | |||
4300 | 942 | backgroundStack.classList.add( 'stack' ); | ||
4301 | 943 | |||
4302 | 944 | } ); | ||
4303 | 945 | |||
4304 | 946 | } ); | ||
4305 | 947 | |||
4306 | 948 | // Add parallax background if specified | ||
4307 | 949 | if( config.parallaxBackgroundImage ) { | ||
4308 | 950 | |||
4309 | 951 | dom.background.style.backgroundImage = 'url("' + config.parallaxBackgroundImage + '")'; | ||
4310 | 952 | dom.background.style.backgroundSize = config.parallaxBackgroundSize; | ||
4311 | 953 | dom.background.style.backgroundRepeat = config.parallaxBackgroundRepeat; | ||
4312 | 954 | dom.background.style.backgroundPosition = config.parallaxBackgroundPosition; | ||
4313 | 955 | |||
4314 | 956 | // Make sure the below properties are set on the element - these properties are | ||
4315 | 957 | // needed for proper transitions to be set on the element via CSS. To remove | ||
4316 | 958 | // annoying background slide-in effect when the presentation starts, apply | ||
4317 | 959 | // these properties after short time delay | ||
4318 | 960 | setTimeout( function() { | ||
4319 | 961 | dom.wrapper.classList.add( 'has-parallax-background' ); | ||
4320 | 962 | }, 1 ); | ||
4321 | 963 | |||
4322 | 964 | } | ||
4323 | 965 | else { | ||
4324 | 966 | |||
4325 | 967 | dom.background.style.backgroundImage = ''; | ||
4326 | 968 | dom.wrapper.classList.remove( 'has-parallax-background' ); | ||
4327 | 969 | |||
4328 | 970 | } | ||
4329 | 971 | |||
4330 | 972 | } | ||
4331 | 973 | |||
4332 | 974 | /** | ||
4333 | 975 | * Creates a background for the given slide. | ||
4334 | 976 | * | ||
4335 | 977 | * @param {HTMLElement} slide | ||
4336 | 978 | * @param {HTMLElement} container The element that the background | ||
4337 | 979 | * should be appended to | ||
4338 | 980 | * @return {HTMLElement} New background div | ||
4339 | 981 | */ | ||
4340 | 982 | function createBackground( slide, container ) { | ||
4341 | 983 | |||
4342 | 984 | |||
4343 | 985 | // Main slide background element | ||
4344 | 986 | var element = document.createElement( 'div' ); | ||
4345 | 987 | element.className = 'slide-background ' + slide.className.replace( /present|past|future/, '' ); | ||
4346 | 988 | |||
4347 | 989 | // Inner background element that wraps images/videos/iframes | ||
4348 | 990 | var contentElement = document.createElement( 'div' ); | ||
4349 | 991 | contentElement.className = 'slide-background-content'; | ||
4350 | 992 | |||
4351 | 993 | element.appendChild( contentElement ); | ||
4352 | 994 | container.appendChild( element ); | ||
4353 | 995 | |||
4354 | 996 | slide.slideBackgroundElement = element; | ||
4355 | 997 | slide.slideBackgroundContentElement = contentElement; | ||
4356 | 998 | |||
4357 | 999 | // Syncs the background to reflect all current background settings | ||
4358 | 1000 | syncBackground( slide ); | ||
4359 | 1001 | |||
4360 | 1002 | return element; | ||
4361 | 1003 | |||
4362 | 1004 | } | ||
4363 | 1005 | |||
4364 | 1006 | /** | ||
4365 | 1007 | * Renders all of the visual properties of a slide background | ||
4366 | 1008 | * based on the various background attributes. | ||
4367 | 1009 | * | ||
4368 | 1010 | * @param {HTMLElement} slide | ||
4369 | 1011 | */ | ||
4370 | 1012 | function syncBackground( slide ) { | ||
4371 | 1013 | |||
4372 | 1014 | var element = slide.slideBackgroundElement, | ||
4373 | 1015 | contentElement = slide.slideBackgroundContentElement; | ||
4374 | 1016 | |||
4375 | 1017 | // Reset the prior background state in case this is not the | ||
4376 | 1018 | // initial sync | ||
4377 | 1019 | slide.classList.remove( 'has-dark-background' ); | ||
4378 | 1020 | slide.classList.remove( 'has-light-background' ); | ||
4379 | 1021 | |||
4380 | 1022 | element.removeAttribute( 'data-loaded' ); | ||
4381 | 1023 | element.removeAttribute( 'data-background-hash' ); | ||
4382 | 1024 | element.removeAttribute( 'data-background-size' ); | ||
4383 | 1025 | element.removeAttribute( 'data-background-transition' ); | ||
4384 | 1026 | element.style.backgroundColor = ''; | ||
4385 | 1027 | |||
4386 | 1028 | contentElement.style.backgroundSize = ''; | ||
4387 | 1029 | contentElement.style.backgroundRepeat = ''; | ||
4388 | 1030 | contentElement.style.backgroundPosition = ''; | ||
4389 | 1031 | contentElement.style.backgroundImage = ''; | ||
4390 | 1032 | contentElement.style.opacity = ''; | ||
4391 | 1033 | contentElement.innerHTML = ''; | ||
4392 | 1034 | |||
4393 | 1035 | var data = { | ||
4394 | 1036 | background: slide.getAttribute( 'data-background' ), | ||
4395 | 1037 | backgroundSize: slide.getAttribute( 'data-background-size' ), | ||
4396 | 1038 | backgroundImage: slide.getAttribute( 'data-background-image' ), | ||
4397 | 1039 | backgroundVideo: slide.getAttribute( 'data-background-video' ), | ||
4398 | 1040 | backgroundIframe: slide.getAttribute( 'data-background-iframe' ), | ||
4399 | 1041 | backgroundColor: slide.getAttribute( 'data-background-color' ), | ||
4400 | 1042 | backgroundRepeat: slide.getAttribute( 'data-background-repeat' ), | ||
4401 | 1043 | backgroundPosition: slide.getAttribute( 'data-background-position' ), | ||
4402 | 1044 | backgroundTransition: slide.getAttribute( 'data-background-transition' ), | ||
4403 | 1045 | backgroundOpacity: slide.getAttribute( 'data-background-opacity' ) | ||
4404 | 1046 | }; | ||
4405 | 1047 | |||
4406 | 1048 | if( data.background ) { | ||
4407 | 1049 | // Auto-wrap image urls in url(...) | ||
4408 | 1050 | if( /^(http|file|\/\/)/gi.test( data.background ) || /\.(svg|png|jpg|jpeg|gif|bmp)([?#\s]|$)/gi.test( data.background ) ) { | ||
4409 | 1051 | slide.setAttribute( 'data-background-image', data.background ); | ||
4410 | 1052 | } | ||
4411 | 1053 | else { | ||
4412 | 1054 | element.style.background = data.background; | ||
4413 | 1055 | } | ||
4414 | 1056 | } | ||
4415 | 1057 | |||
4416 | 1058 | // Create a hash for this combination of background settings. | ||
4417 | 1059 | // This is used to determine when two slide backgrounds are | ||
4418 | 1060 | // the same. | ||
4419 | 1061 | if( data.background || data.backgroundColor || data.backgroundImage || data.backgroundVideo || data.backgroundIframe ) { | ||
4420 | 1062 | element.setAttribute( 'data-background-hash', data.background + | ||
4421 | 1063 | data.backgroundSize + | ||
4422 | 1064 | data.backgroundImage + | ||
4423 | 1065 | data.backgroundVideo + | ||
4424 | 1066 | data.backgroundIframe + | ||
4425 | 1067 | data.backgroundColor + | ||
4426 | 1068 | data.backgroundRepeat + | ||
4427 | 1069 | data.backgroundPosition + | ||
4428 | 1070 | data.backgroundTransition + | ||
4429 | 1071 | data.backgroundOpacity ); | ||
4430 | 1072 | } | ||
4431 | 1073 | |||
4432 | 1074 | // Additional and optional background properties | ||
4433 | 1075 | if( data.backgroundSize ) element.setAttribute( 'data-background-size', data.backgroundSize ); | ||
4434 | 1076 | if( data.backgroundColor ) element.style.backgroundColor = data.backgroundColor; | ||
4435 | 1077 | if( data.backgroundTransition ) element.setAttribute( 'data-background-transition', data.backgroundTransition ); | ||
4436 | 1078 | |||
4437 | 1079 | // Background image options are set on the content wrapper | ||
4438 | 1080 | if( data.backgroundSize ) contentElement.style.backgroundSize = data.backgroundSize; | ||
4439 | 1081 | if( data.backgroundRepeat ) contentElement.style.backgroundRepeat = data.backgroundRepeat; | ||
4440 | 1082 | if( data.backgroundPosition ) contentElement.style.backgroundPosition = data.backgroundPosition; | ||
4441 | 1083 | if( data.backgroundOpacity ) contentElement.style.opacity = data.backgroundOpacity; | ||
4442 | 1084 | |||
4443 | 1085 | // If this slide has a background color, add a class that | ||
4444 | 1086 | // signals if it is light or dark. If the slide has no background | ||
4445 | 1087 | // color, no class will be set | ||
4446 | 1088 | var computedBackgroundStyle = window.getComputedStyle( element ); | ||
4447 | 1089 | if( computedBackgroundStyle && computedBackgroundStyle.backgroundColor ) { | ||
4448 | 1090 | var rgb = colorToRgb( computedBackgroundStyle.backgroundColor ); | ||
4449 | 1091 | |||
4450 | 1092 | // Ignore fully transparent backgrounds. Some browsers return | ||
4451 | 1093 | // rgba(0,0,0,0) when reading the computed background color of | ||
4452 | 1094 | // an element with no background | ||
4453 | 1095 | if( rgb && rgb.a !== 0 ) { | ||
4454 | 1096 | if( colorBrightness( computedBackgroundStyle.backgroundColor ) < 128 ) { | ||
4455 | 1097 | slide.classList.add( 'has-dark-background' ); | ||
4456 | 1098 | } | ||
4457 | 1099 | else { | ||
4458 | 1100 | slide.classList.add( 'has-light-background' ); | ||
4459 | 1101 | } | ||
4460 | 1102 | } | ||
4461 | 1103 | } | ||
4462 | 1104 | |||
4463 | 1105 | } | ||
4464 | 1106 | |||
4465 | 1107 | /** | ||
4466 | 1108 | * Registers a listener to postMessage events, this makes it | ||
4467 | 1109 | * possible to call all reveal.js API methods from another | ||
4468 | 1110 | * window. For example: | ||
4469 | 1111 | * | ||
4470 | 1112 | * revealWindow.postMessage( JSON.stringify({ | ||
4471 | 1113 | * method: 'slide', | ||
4472 | 1114 | * args: [ 2 ] | ||
4473 | 1115 | * }), '*' ); | ||
4474 | 1116 | */ | ||
4475 | 1117 | function setupPostMessage() { | ||
4476 | 1118 | |||
4477 | 1119 | if( config.postMessage ) { | ||
4478 | 1120 | window.addEventListener( 'message', function ( event ) { | ||
4479 | 1121 | var data = event.data; | ||
4480 | 1122 | |||
4481 | 1123 | // Make sure we're dealing with JSON | ||
4482 | 1124 | if( typeof data === 'string' && data.charAt( 0 ) === '{' && data.charAt( data.length - 1 ) === '}' ) { | ||
4483 | 1125 | data = JSON.parse( data ); | ||
4484 | 1126 | |||
4485 | 1127 | // Check if the requested method can be found | ||
4486 | 1128 | if( data.method && typeof Reveal[data.method] === 'function' ) { | ||
4487 | 1129 | Reveal[data.method].apply( Reveal, data.args ); | ||
4488 | 1130 | } | ||
4489 | 1131 | } | ||
4490 | 1132 | }, false ); | ||
4491 | 1133 | } | ||
4492 | 1134 | |||
4493 | 1135 | } | ||
4494 | 1136 | |||
4495 | 1137 | /** | ||
4496 | 1138 | * Applies the configuration settings from the config | ||
4497 | 1139 | * object. May be called multiple times. | ||
4498 | 1140 | * | ||
4499 | 1141 | * @param {object} options | ||
4500 | 1142 | */ | ||
4501 | 1143 | function configure( options ) { | ||
4502 | 1144 | |||
4503 | 1145 | var oldTransition = config.transition; | ||
4504 | 1146 | |||
4505 | 1147 | // New config options may be passed when this method | ||
4506 | 1148 | // is invoked through the API after initialization | ||
4507 | 1149 | if( typeof options === 'object' ) extend( config, options ); | ||
4508 | 1150 | |||
4509 | 1151 | // Abort if reveal.js hasn't finished loading, config | ||
4510 | 1152 | // changes will be applied automatically once loading | ||
4511 | 1153 | // finishes | ||
4512 | 1154 | if( loaded === false ) return; | ||
4513 | 1155 | |||
4514 | 1156 | var numberOfSlides = dom.wrapper.querySelectorAll( SLIDES_SELECTOR ).length; | ||
4515 | 1157 | |||
4516 | 1158 | // Remove the previously configured transition class | ||
4517 | 1159 | dom.wrapper.classList.remove( oldTransition ); | ||
4518 | 1160 | |||
4519 | 1161 | // Force linear transition based on browser capabilities | ||
4520 | 1162 | if( features.transforms3d === false ) config.transition = 'linear'; | ||
4521 | 1163 | |||
4522 | 1164 | dom.wrapper.classList.add( config.transition ); | ||
4523 | 1165 | |||
4524 | 1166 | dom.wrapper.setAttribute( 'data-transition-speed', config.transitionSpeed ); | ||
4525 | 1167 | dom.wrapper.setAttribute( 'data-background-transition', config.backgroundTransition ); | ||
4526 | 1168 | |||
4527 | 1169 | dom.controls.style.display = config.controls ? 'block' : 'none'; | ||
4528 | 1170 | dom.progress.style.display = config.progress ? 'block' : 'none'; | ||
4529 | 1171 | |||
4530 | 1172 | dom.controls.setAttribute( 'data-controls-layout', config.controlsLayout ); | ||
4531 | 1173 | dom.controls.setAttribute( 'data-controls-back-arrows', config.controlsBackArrows ); | ||
4532 | 1174 | |||
4533 | 1175 | if( config.shuffle ) { | ||
4534 | 1176 | shuffle(); | ||
4535 | 1177 | } | ||
4536 | 1178 | |||
4537 | 1179 | if( config.rtl ) { | ||
4538 | 1180 | dom.wrapper.classList.add( 'rtl' ); | ||
4539 | 1181 | } | ||
4540 | 1182 | else { | ||
4541 | 1183 | dom.wrapper.classList.remove( 'rtl' ); | ||
4542 | 1184 | } | ||
4543 | 1185 | |||
4544 | 1186 | if( config.center ) { | ||
4545 | 1187 | dom.wrapper.classList.add( 'center' ); | ||
4546 | 1188 | } | ||
4547 | 1189 | else { | ||
4548 | 1190 | dom.wrapper.classList.remove( 'center' ); | ||
4549 | 1191 | } | ||
4550 | 1192 | |||
4551 | 1193 | // Exit the paused mode if it was configured off | ||
4552 | 1194 | if( config.pause === false ) { | ||
4553 | 1195 | resume(); | ||
4554 | 1196 | } | ||
4555 | 1197 | |||
4556 | 1198 | if( config.showNotes ) { | ||
4557 | 1199 | dom.speakerNotes.setAttribute( 'data-layout', typeof config.showNotes === 'string' ? config.showNotes : 'inline' ); | ||
4558 | 1200 | } | ||
4559 | 1201 | |||
4560 | 1202 | if( config.mouseWheel ) { | ||
4561 | 1203 | document.addEventListener( 'DOMMouseScroll', onDocumentMouseScroll, false ); // FF | ||
4562 | 1204 | document.addEventListener( 'mousewheel', onDocumentMouseScroll, false ); | ||
4563 | 1205 | } | ||
4564 | 1206 | else { | ||
4565 | 1207 | document.removeEventListener( 'DOMMouseScroll', onDocumentMouseScroll, false ); // FF | ||
4566 | 1208 | document.removeEventListener( 'mousewheel', onDocumentMouseScroll, false ); | ||
4567 | 1209 | } | ||
4568 | 1210 | |||
4569 | 1211 | // Rolling 3D links | ||
4570 | 1212 | if( config.rollingLinks ) { | ||
4571 | 1213 | enableRollingLinks(); | ||
4572 | 1214 | } | ||
4573 | 1215 | else { | ||
4574 | 1216 | disableRollingLinks(); | ||
4575 | 1217 | } | ||
4576 | 1218 | |||
4577 | 1219 | // Iframe link previews | ||
4578 | 1220 | if( config.previewLinks ) { | ||
4579 | 1221 | enablePreviewLinks(); | ||
4580 | 1222 | disablePreviewLinks( '[data-preview-link=false]' ); | ||
4581 | 1223 | } | ||
4582 | 1224 | else { | ||
4583 | 1225 | disablePreviewLinks(); | ||
4584 | 1226 | enablePreviewLinks( '[data-preview-link]:not([data-preview-link=false])' ); | ||
4585 | 1227 | } | ||
4586 | 1228 | |||
4587 | 1229 | // Remove existing auto-slide controls | ||
4588 | 1230 | if( autoSlidePlayer ) { | ||
4589 | 1231 | autoSlidePlayer.destroy(); | ||
4590 | 1232 | autoSlidePlayer = null; | ||
4591 | 1233 | } | ||
4592 | 1234 | |||
4593 | 1235 | // Generate auto-slide controls if needed | ||
4594 | 1236 | if( numberOfSlides > 1 && config.autoSlide && config.autoSlideStoppable && features.canvas && features.requestAnimationFrame ) { | ||
4595 | 1237 | autoSlidePlayer = new Playback( dom.wrapper, function() { | ||
4596 | 1238 | return Math.min( Math.max( ( Date.now() - autoSlideStartTime ) / autoSlide, 0 ), 1 ); | ||
4597 | 1239 | } ); | ||
4598 | 1240 | |||
4599 | 1241 | autoSlidePlayer.on( 'click', onAutoSlidePlayerClick ); | ||
4600 | 1242 | autoSlidePaused = false; | ||
4601 | 1243 | } | ||
4602 | 1244 | |||
4603 | 1245 | // When fragments are turned off they should be visible | ||
4604 | 1246 | if( config.fragments === false ) { | ||
4605 | 1247 | toArray( dom.slides.querySelectorAll( '.fragment' ) ).forEach( function( element ) { | ||
4606 | 1248 | element.classList.add( 'visible' ); | ||
4607 | 1249 | element.classList.remove( 'current-fragment' ); | ||
4608 | 1250 | } ); | ||
4609 | 1251 | } | ||
4610 | 1252 | |||
4611 | 1253 | // Slide numbers | ||
4612 | 1254 | var slideNumberDisplay = 'none'; | ||
4613 | 1255 | if( config.slideNumber && !isPrintingPDF() ) { | ||
4614 | 1256 | if( config.showSlideNumber === 'all' ) { | ||
4615 | 1257 | slideNumberDisplay = 'block'; | ||
4616 | 1258 | } | ||
4617 | 1259 | else if( config.showSlideNumber === 'speaker' && isSpeakerNotes() ) { | ||
4618 | 1260 | slideNumberDisplay = 'block'; | ||
4619 | 1261 | } | ||
4620 | 1262 | } | ||
4621 | 1263 | |||
4622 | 1264 | dom.slideNumber.style.display = slideNumberDisplay; | ||
4623 | 1265 | |||
4624 | 1266 | sync(); | ||
4625 | 1267 | |||
4626 | 1268 | } | ||
4627 | 1269 | |||
4628 | 1270 | /** | ||
4629 | 1271 | * Binds all event listeners. | ||
4630 | 1272 | */ | ||
4631 | 1273 | function addEventListeners() { | ||
4632 | 1274 | |||
4633 | 1275 | eventsAreBound = true; | ||
4634 | 1276 | |||
4635 | 1277 | window.addEventListener( 'hashchange', onWindowHashChange, false ); | ||
4636 | 1278 | window.addEventListener( 'resize', onWindowResize, false ); | ||
4637 | 1279 | |||
4638 | 1280 | if( config.touch ) { | ||
4639 | 1281 | if( 'onpointerdown' in window ) { | ||
4640 | 1282 | // Use W3C pointer events | ||
4641 | 1283 | dom.wrapper.addEventListener( 'pointerdown', onPointerDown, false ); | ||
4642 | 1284 | dom.wrapper.addEventListener( 'pointermove', onPointerMove, false ); | ||
4643 | 1285 | dom.wrapper.addEventListener( 'pointerup', onPointerUp, false ); | ||
4644 | 1286 | } | ||
4645 | 1287 | else if( window.navigator.msPointerEnabled ) { | ||
4646 | 1288 | // IE 10 uses prefixed version of pointer events | ||
4647 | 1289 | dom.wrapper.addEventListener( 'MSPointerDown', onPointerDown, false ); | ||
4648 | 1290 | dom.wrapper.addEventListener( 'MSPointerMove', onPointerMove, false ); | ||
4649 | 1291 | dom.wrapper.addEventListener( 'MSPointerUp', onPointerUp, false ); | ||
4650 | 1292 | } | ||
4651 | 1293 | else { | ||
4652 | 1294 | // Fall back to touch events | ||
4653 | 1295 | dom.wrapper.addEventListener( 'touchstart', onTouchStart, false ); | ||
4654 | 1296 | dom.wrapper.addEventListener( 'touchmove', onTouchMove, false ); | ||
4655 | 1297 | dom.wrapper.addEventListener( 'touchend', onTouchEnd, false ); | ||
4656 | 1298 | } | ||
4657 | 1299 | } | ||
4658 | 1300 | |||
4659 | 1301 | if( config.keyboard ) { | ||
4660 | 1302 | document.addEventListener( 'keydown', onDocumentKeyDown, false ); | ||
4661 | 1303 | document.addEventListener( 'keypress', onDocumentKeyPress, false ); | ||
4662 | 1304 | } | ||
4663 | 1305 | |||
4664 | 1306 | if( config.progress && dom.progress ) { | ||
4665 | 1307 | dom.progress.addEventListener( 'click', onProgressClicked, false ); | ||
4666 | 1308 | } | ||
4667 | 1309 | |||
4668 | 1310 | dom.resumeButton.addEventListener( 'click', resume, false ); | ||
4669 | 1311 | |||
4670 | 1312 | if( config.focusBodyOnPageVisibilityChange ) { | ||
4671 | 1313 | var visibilityChange; | ||
4672 | 1314 | |||
4673 | 1315 | if( 'hidden' in document ) { | ||
4674 | 1316 | visibilityChange = 'visibilitychange'; | ||
4675 | 1317 | } | ||
4676 | 1318 | else if( 'msHidden' in document ) { | ||
4677 | 1319 | visibilityChange = 'msvisibilitychange'; | ||
4678 | 1320 | } | ||
4679 | 1321 | else if( 'webkitHidden' in document ) { | ||
4680 | 1322 | visibilityChange = 'webkitvisibilitychange'; | ||
4681 | 1323 | } | ||
4682 | 1324 | |||
4683 | 1325 | if( visibilityChange ) { | ||
4684 | 1326 | document.addEventListener( visibilityChange, onPageVisibilityChange, false ); | ||
4685 | 1327 | } | ||
4686 | 1328 | } | ||
4687 | 1329 | |||
4688 | 1330 | // Listen to both touch and click events, in case the device | ||
4689 | 1331 | // supports both | ||
4690 | 1332 | var pointerEvents = [ 'touchstart', 'click' ]; | ||
4691 | 1333 | |||
4692 | 1334 | // Only support touch for Android, fixes double navigations in | ||
4693 | 1335 | // stock browser | ||
4694 | 1336 | if( UA.match( /android/gi ) ) { | ||
4695 | 1337 | pointerEvents = [ 'touchstart' ]; | ||
4696 | 1338 | } | ||
4697 | 1339 | |||
4698 | 1340 | pointerEvents.forEach( function( eventName ) { | ||
4699 | 1341 | dom.controlsLeft.forEach( function( el ) { el.addEventListener( eventName, onNavigateLeftClicked, false ); } ); | ||
4700 | 1342 | dom.controlsRight.forEach( function( el ) { el.addEventListener( eventName, onNavigateRightClicked, false ); } ); | ||
4701 | 1343 | dom.controlsUp.forEach( function( el ) { el.addEventListener( eventName, onNavigateUpClicked, false ); } ); | ||
4702 | 1344 | dom.controlsDown.forEach( function( el ) { el.addEventListener( eventName, onNavigateDownClicked, false ); } ); | ||
4703 | 1345 | dom.controlsPrev.forEach( function( el ) { el.addEventListener( eventName, onNavigatePrevClicked, false ); } ); | ||
4704 | 1346 | dom.controlsNext.forEach( function( el ) { el.addEventListener( eventName, onNavigateNextClicked, false ); } ); | ||
4705 | 1347 | } ); | ||
4706 | 1348 | |||
4707 | 1349 | } | ||
4708 | 1350 | |||
4709 | 1351 | /** | ||
4710 | 1352 | * Unbinds all event listeners. | ||
4711 | 1353 | */ | ||
4712 | 1354 | function removeEventListeners() { | ||
4713 | 1355 | |||
4714 | 1356 | eventsAreBound = false; | ||
4715 | 1357 | |||
4716 | 1358 | document.removeEventListener( 'keydown', onDocumentKeyDown, false ); | ||
4717 | 1359 | document.removeEventListener( 'keypress', onDocumentKeyPress, false ); | ||
4718 | 1360 | window.removeEventListener( 'hashchange', onWindowHashChange, false ); | ||
4719 | 1361 | window.removeEventListener( 'resize', onWindowResize, false ); | ||
4720 | 1362 | |||
4721 | 1363 | dom.wrapper.removeEventListener( 'pointerdown', onPointerDown, false ); | ||
4722 | 1364 | dom.wrapper.removeEventListener( 'pointermove', onPointerMove, false ); | ||
4723 | 1365 | dom.wrapper.removeEventListener( 'pointerup', onPointerUp, false ); | ||
4724 | 1366 | |||
4725 | 1367 | dom.wrapper.removeEventListener( 'MSPointerDown', onPointerDown, false ); | ||
4726 | 1368 | dom.wrapper.removeEventListener( 'MSPointerMove', onPointerMove, false ); | ||
4727 | 1369 | dom.wrapper.removeEventListener( 'MSPointerUp', onPointerUp, false ); | ||
4728 | 1370 | |||
4729 | 1371 | dom.wrapper.removeEventListener( 'touchstart', onTouchStart, false ); | ||
4730 | 1372 | dom.wrapper.removeEventListener( 'touchmove', onTouchMove, false ); | ||
4731 | 1373 | dom.wrapper.removeEventListener( 'touchend', onTouchEnd, false ); | ||
4732 | 1374 | |||
4733 | 1375 | dom.resumeButton.removeEventListener( 'click', resume, false ); | ||
4734 | 1376 | |||
4735 | 1377 | if ( config.progress && dom.progress ) { | ||
4736 | 1378 | dom.progress.removeEventListener( 'click', onProgressClicked, false ); | ||
4737 | 1379 | } | ||
4738 | 1380 | |||
4739 | 1381 | [ 'touchstart', 'click' ].forEach( function( eventName ) { | ||
4740 | 1382 | dom.controlsLeft.forEach( function( el ) { el.removeEventListener( eventName, onNavigateLeftClicked, false ); } ); | ||
4741 | 1383 | dom.controlsRight.forEach( function( el ) { el.removeEventListener( eventName, onNavigateRightClicked, false ); } ); | ||
4742 | 1384 | dom.controlsUp.forEach( function( el ) { el.removeEventListener( eventName, onNavigateUpClicked, false ); } ); | ||
4743 | 1385 | dom.controlsDown.forEach( function( el ) { el.removeEventListener( eventName, onNavigateDownClicked, false ); } ); | ||
4744 | 1386 | dom.controlsPrev.forEach( function( el ) { el.removeEventListener( eventName, onNavigatePrevClicked, false ); } ); | ||
4745 | 1387 | dom.controlsNext.forEach( function( el ) { el.removeEventListener( eventName, onNavigateNextClicked, false ); } ); | ||
4746 | 1388 | } ); | ||
4747 | 1389 | |||
4748 | 1390 | } | ||
4749 | 1391 | |||
4750 | 1392 | /** | ||
4751 | 1393 | * Add a custom key binding with optional description to | ||
4752 | 1394 | * be added to the help screen. | ||
4753 | 1395 | */ | ||
4754 | 1396 | function addKeyBinding( binding, callback ) { | ||
4755 | 1397 | |||
4756 | 1398 | if( typeof binding === 'object' && binding.keyCode ) { | ||
4757 | 1399 | registeredKeyBindings[binding.keyCode] = { | ||
4758 | 1400 | callback: callback, | ||
4759 | 1401 | key: binding.key, | ||
4760 | 1402 | description: binding.description | ||
4761 | 1403 | }; | ||
4762 | 1404 | } | ||
4763 | 1405 | else { | ||
4764 | 1406 | registeredKeyBindings[binding] = { | ||
4765 | 1407 | callback: callback, | ||
4766 | 1408 | key: null, | ||
4767 | 1409 | description: null | ||
4768 | 1410 | }; | ||
4769 | 1411 | } | ||
4770 | 1412 | |||
4771 | 1413 | } | ||
4772 | 1414 | |||
4773 | 1415 | /** | ||
4774 | 1416 | * Removes the specified custom key binding. | ||
4775 | 1417 | */ | ||
4776 | 1418 | function removeKeyBinding( keyCode ) { | ||
4777 | 1419 | |||
4778 | 1420 | delete registeredKeyBindings[keyCode]; | ||
4779 | 1421 | |||
4780 | 1422 | } | ||
4781 | 1423 | |||
4782 | 1424 | /** | ||
4783 | 1425 | * Extend object a with the properties of object b. | ||
4784 | 1426 | * If there's a conflict, object b takes precedence. | ||
4785 | 1427 | * | ||
4786 | 1428 | * @param {object} a | ||
4787 | 1429 | * @param {object} b | ||
4788 | 1430 | */ | ||
4789 | 1431 | function extend( a, b ) { | ||
4790 | 1432 | |||
4791 | 1433 | for( var i in b ) { | ||
4792 | 1434 | a[ i ] = b[ i ]; | ||
4793 | 1435 | } | ||
4794 | 1436 | |||
4795 | 1437 | return a; | ||
4796 | 1438 | |||
4797 | 1439 | } | ||
4798 | 1440 | |||
4799 | 1441 | /** | ||
4800 | 1442 | * Converts the target object to an array. | ||
4801 | 1443 | * | ||
4802 | 1444 | * @param {object} o | ||
4803 | 1445 | * @return {object[]} | ||
4804 | 1446 | */ | ||
4805 | 1447 | function toArray( o ) { | ||
4806 | 1448 | |||
4807 | 1449 | return Array.prototype.slice.call( o ); | ||
4808 | 1450 | |||
4809 | 1451 | } | ||
4810 | 1452 | |||
4811 | 1453 | /** | ||
4812 | 1454 | * Utility for deserializing a value. | ||
4813 | 1455 | * | ||
4814 | 1456 | * @param {*} value | ||
4815 | 1457 | * @return {*} | ||
4816 | 1458 | */ | ||
4817 | 1459 | function deserialize( value ) { | ||
4818 | 1460 | |||
4819 | 1461 | if( typeof value === 'string' ) { | ||
4820 | 1462 | if( value === 'null' ) return null; | ||
4821 | 1463 | else if( value === 'true' ) return true; | ||
4822 | 1464 | else if( value === 'false' ) return false; | ||
4823 | 1465 | else if( value.match( /^-?[\d\.]+$/ ) ) return parseFloat( value ); | ||
4824 | 1466 | } | ||
4825 | 1467 | |||
4826 | 1468 | return value; | ||
4827 | 1469 | |||
4828 | 1470 | } | ||
4829 | 1471 | |||
4830 | 1472 | /** | ||
4831 | 1473 | * Measures the distance in pixels between point a | ||
4832 | 1474 | * and point b. | ||
4833 | 1475 | * | ||
4834 | 1476 | * @param {object} a point with x/y properties | ||
4835 | 1477 | * @param {object} b point with x/y properties | ||
4836 | 1478 | * | ||
4837 | 1479 | * @return {number} | ||
4838 | 1480 | */ | ||
4839 | 1481 | function distanceBetween( a, b ) { | ||
4840 | 1482 | |||
4841 | 1483 | var dx = a.x - b.x, | ||
4842 | 1484 | dy = a.y - b.y; | ||
4843 | 1485 | |||
4844 | 1486 | return Math.sqrt( dx*dx + dy*dy ); | ||
4845 | 1487 | |||
4846 | 1488 | } | ||
4847 | 1489 | |||
4848 | 1490 | /** | ||
4849 | 1491 | * Applies a CSS transform to the target element. | ||
4850 | 1492 | * | ||
4851 | 1493 | * @param {HTMLElement} element | ||
4852 | 1494 | * @param {string} transform | ||
4853 | 1495 | */ | ||
4854 | 1496 | function transformElement( element, transform ) { | ||
4855 | 1497 | |||
4856 | 1498 | element.style.WebkitTransform = transform; | ||
4857 | 1499 | element.style.MozTransform = transform; | ||
4858 | 1500 | element.style.msTransform = transform; | ||
4859 | 1501 | element.style.transform = transform; | ||
4860 | 1502 | |||
4861 | 1503 | } | ||
4862 | 1504 | |||
4863 | 1505 | /** | ||
4864 | 1506 | * Applies CSS transforms to the slides container. The container | ||
4865 | 1507 | * is transformed from two separate sources: layout and the overview | ||
4866 | 1508 | * mode. | ||
4867 | 1509 | * | ||
4868 | 1510 | * @param {object} transforms | ||
4869 | 1511 | */ | ||
4870 | 1512 | function transformSlides( transforms ) { | ||
4871 | 1513 | |||
4872 | 1514 | // Pick up new transforms from arguments | ||
4873 | 1515 | if( typeof transforms.layout === 'string' ) slidesTransform.layout = transforms.layout; | ||
4874 | 1516 | if( typeof transforms.overview === 'string' ) slidesTransform.overview = transforms.overview; | ||
4875 | 1517 | |||
4876 | 1518 | // Apply the transforms to the slides container | ||
4877 | 1519 | if( slidesTransform.layout ) { | ||
4878 | 1520 | transformElement( dom.slides, slidesTransform.layout + ' ' + slidesTransform.overview ); | ||
4879 | 1521 | } | ||
4880 | 1522 | else { | ||
4881 | 1523 | transformElement( dom.slides, slidesTransform.overview ); | ||
4882 | 1524 | } | ||
4883 | 1525 | |||
4884 | 1526 | } | ||
4885 | 1527 | |||
4886 | 1528 | /** | ||
4887 | 1529 | * Injects the given CSS styles into the DOM. | ||
4888 | 1530 | * | ||
4889 | 1531 | * @param {string} value | ||
4890 | 1532 | */ | ||
4891 | 1533 | function injectStyleSheet( value ) { | ||
4892 | 1534 | |||
4893 | 1535 | var tag = document.createElement( 'style' ); | ||
4894 | 1536 | tag.type = 'text/css'; | ||
4895 | 1537 | if( tag.styleSheet ) { | ||
4896 | 1538 | tag.styleSheet.cssText = value; | ||
4897 | 1539 | } | ||
4898 | 1540 | else { | ||
4899 | 1541 | tag.appendChild( document.createTextNode( value ) ); | ||
4900 | 1542 | } | ||
4901 | 1543 | document.getElementsByTagName( 'head' )[0].appendChild( tag ); | ||
4902 | 1544 | |||
4903 | 1545 | } | ||
4904 | 1546 | |||
4905 | 1547 | /** | ||
4906 | 1548 | * Find the closest parent that matches the given | ||
4907 | 1549 | * selector. | ||
4908 | 1550 | * | ||
4909 | 1551 | * @param {HTMLElement} target The child element | ||
4910 | 1552 | * @param {String} selector The CSS selector to match | ||
4911 | 1553 | * the parents against | ||
4912 | 1554 | * | ||
4913 | 1555 | * @return {HTMLElement} The matched parent or null | ||
4914 | 1556 | * if no matching parent was found | ||
4915 | 1557 | */ | ||
4916 | 1558 | function closestParent( target, selector ) { | ||
4917 | 1559 | |||
4918 | 1560 | var parent = target.parentNode; | ||
4919 | 1561 | |||
4920 | 1562 | while( parent ) { | ||
4921 | 1563 | |||
4922 | 1564 | // There's some overhead doing this each time, we don't | ||
4923 | 1565 | // want to rewrite the element prototype but should still | ||
4924 | 1566 | // be enough to feature detect once at startup... | ||
4925 | 1567 | var matchesMethod = parent.matches || parent.matchesSelector || parent.msMatchesSelector; | ||
4926 | 1568 | |||
4927 | 1569 | // If we find a match, we're all set | ||
4928 | 1570 | if( matchesMethod && matchesMethod.call( parent, selector ) ) { | ||
4929 | 1571 | return parent; | ||
4930 | 1572 | } | ||
4931 | 1573 | |||
4932 | 1574 | // Keep searching | ||
4933 | 1575 | parent = parent.parentNode; | ||
4934 | 1576 | |||
4935 | 1577 | } | ||
4936 | 1578 | |||
4937 | 1579 | return null; | ||
4938 | 1580 | |||
4939 | 1581 | } | ||
4940 | 1582 | |||
4941 | 1583 | /** | ||
4942 | 1584 | * Converts various color input formats to an {r:0,g:0,b:0} object. | ||
4943 | 1585 | * | ||
4944 | 1586 | * @param {string} color The string representation of a color | ||
4945 | 1587 | * @example | ||
4946 | 1588 | * colorToRgb('#000'); | ||
4947 | 1589 | * @example | ||
4948 | 1590 | * colorToRgb('#000000'); | ||
4949 | 1591 | * @example | ||
4950 | 1592 | * colorToRgb('rgb(0,0,0)'); | ||
4951 | 1593 | * @example | ||
4952 | 1594 | * colorToRgb('rgba(0,0,0)'); | ||
4953 | 1595 | * | ||
4954 | 1596 | * @return {{r: number, g: number, b: number, [a]: number}|null} | ||
4955 | 1597 | */ | ||
4956 | 1598 | function colorToRgb( color ) { | ||
4957 | 1599 | |||
4958 | 1600 | var hex3 = color.match( /^#([0-9a-f]{3})$/i ); | ||
4959 | 1601 | if( hex3 && hex3[1] ) { | ||
4960 | 1602 | hex3 = hex3[1]; | ||
4961 | 1603 | return { | ||
4962 | 1604 | r: parseInt( hex3.charAt( 0 ), 16 ) * 0x11, | ||
4963 | 1605 | g: parseInt( hex3.charAt( 1 ), 16 ) * 0x11, | ||
4964 | 1606 | b: parseInt( hex3.charAt( 2 ), 16 ) * 0x11 | ||
4965 | 1607 | }; | ||
4966 | 1608 | } | ||
4967 | 1609 | |||
4968 | 1610 | var hex6 = color.match( /^#([0-9a-f]{6})$/i ); | ||
4969 | 1611 | if( hex6 && hex6[1] ) { | ||
4970 | 1612 | hex6 = hex6[1]; | ||
4971 | 1613 | return { | ||
4972 | 1614 | r: parseInt( hex6.substr( 0, 2 ), 16 ), | ||
4973 | 1615 | g: parseInt( hex6.substr( 2, 2 ), 16 ), | ||
4974 | 1616 | b: parseInt( hex6.substr( 4, 2 ), 16 ) | ||
4975 | 1617 | }; | ||
4976 | 1618 | } | ||
4977 | 1619 | |||
4978 | 1620 | var rgb = color.match( /^rgb\s*\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\)$/i ); | ||
4979 | 1621 | if( rgb ) { | ||
4980 | 1622 | return { | ||
4981 | 1623 | r: parseInt( rgb[1], 10 ), | ||
4982 | 1624 | g: parseInt( rgb[2], 10 ), | ||
4983 | 1625 | b: parseInt( rgb[3], 10 ) | ||
4984 | 1626 | }; | ||
4985 | 1627 | } | ||
4986 | 1628 | |||
4987 | 1629 | var rgba = color.match( /^rgba\s*\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\,\s*([\d]+|[\d]*.[\d]+)\s*\)$/i ); | ||
4988 | 1630 | if( rgba ) { | ||
4989 | 1631 | return { | ||
4990 | 1632 | r: parseInt( rgba[1], 10 ), | ||
4991 | 1633 | g: parseInt( rgba[2], 10 ), | ||
4992 | 1634 | b: parseInt( rgba[3], 10 ), | ||
4993 | 1635 | a: parseFloat( rgba[4] ) | ||
4994 | 1636 | }; | ||
4995 | 1637 | } | ||
4996 | 1638 | |||
4997 | 1639 | return null; | ||
4998 | 1640 | |||
4999 | 1641 | } | ||
5000 | 1642 |
The diff has been truncated for viewing.
Linux tests failed, please see https:/ /ci.openlp. io/job/ MP-02-Linux_ Tests/73/ for more details