Merge branch 'wip-MDL-57456-master' of git://github.com/marinaglancy/moodle
authorDavid Monllao <davidm@moodle.com>
Wed, 19 Apr 2017 07:42:29 +0000 (15:42 +0800)
committerDavid Monllao <davidm@moodle.com>
Wed, 19 Apr 2017 07:42:29 +0000 (15:42 +0800)
790 files changed:
.eslintignore
.stylelintignore
.travis.yml
admin/environment.xml
admin/renderer.php
admin/tool/lp/tests/behat/behat_tool_lp_data_generators.php
admin/tool/messageinbound/classes/manager.php
admin/tool/mobile/classes/api.php
admin/tool/mobile/classes/external.php
admin/tool/mobile/launch.php
admin/tool/mobile/tests/externallib_test.php
admin/tool/mobile/upgrade.txt
admin/tool/usertours/amd/build/popper.min.js
admin/tool/usertours/amd/build/tour.min.js
admin/tool/usertours/amd/src/popper.js
admin/tool/usertours/amd/src/tour.js
admin/tool/usertours/thirdpartylibs.xml
admin/tool/xmldb/lang/en/tool_xmldb.php
auth/classes/output/login.php
auth/mnet/auth.php
auth/oauth2/classes/auth.php
auth/oauth2/config.html [deleted file]
auth/oauth2/settings.php [new file with mode: 0644]
auth/shibboleth/logout.php
auth/upgrade.txt
backup/converter/moodle1/lib.php
backup/converter/moodle1/tests/moodle1_converter_test.php
backup/moodle2/backup_course_task.class.php
backup/moodle2/backup_stepslib.php
backup/moodle2/restore_course_task.class.php
backup/moodle2/restore_stepslib.php
blocks/community/renderer.php
blocks/myoverview/amd/build/event_list.min.js
blocks/myoverview/amd/build/event_list_by_course.min.js
blocks/myoverview/amd/src/event_list.js
blocks/myoverview/amd/src/event_list_by_course.js
blocks/myoverview/classes/output/course_summary.php [deleted file]
blocks/myoverview/classes/output/courses_view.php
blocks/myoverview/classes/output/main.php
blocks/myoverview/lang/en/block_myoverview.php
blocks/myoverview/templates/course-event-list.mustache
blocks/myoverview/templates/courses-view-course-item.mustache
blocks/myoverview/templates/event-list.mustache
blocks/myoverview/templates/timeline-view-courses.mustache
cache/stores/redis/addinstanceform.php
cache/stores/redis/lang/en/cachestore_redis.php
cache/stores/redis/lib.php
cache/stores/redis/settings.php
cache/stores/redis/version.php
calendar/classes/local/api.php
calendar/export_execute.php
calendar/externallib.php
calendar/lib.php
calendar/renderer.php
calendar/tests/lib_test.php
calendar/tests/local_api_test.php
competency/classes/persistent.php
completion/classes/bulkedit_form.php [new file with mode: 0644]
completion/classes/defaultedit_form.php [new file with mode: 0644]
completion/classes/edit_base_form.php [new file with mode: 0644]
completion/classes/manager.php [new file with mode: 0644]
completion/tests/behat/bulk_edit_activity_completion.feature [new file with mode: 0644]
completion/tests/behat/default_activity_completion.feature [new file with mode: 0644]
completion/tests/bulk_update_test.php [new file with mode: 0644]
config-dist.php
course/bulkcompletion.php [new file with mode: 0644]
course/classes/output/bulk_activity_completion_renderer.php [new file with mode: 0644]
course/completion.php
course/defaultcompletion.php [new file with mode: 0644]
course/dnduploadlib.php
course/editbulkcompletion.php [new file with mode: 0644]
course/editdefaultcompletion.php [new file with mode: 0644]
course/externallib.php
course/lib.php
course/modedit.php
course/modlib.php
course/moodleform_mod.php
course/templates/activityinstance.mustache [new file with mode: 0644]
course/templates/bulkactivitycompletion.mustache [new file with mode: 0644]
course/templates/defaultactivitycompletion.mustache [new file with mode: 0644]
course/templates/editbulkactivitycompletion.mustache [new file with mode: 0644]
course/templates/editdefaultcompletion.mustache [new file with mode: 0644]
course/tests/externallib_test.php
course/tests/modlib_test.php
enrol/lti/tests/helper_test.php
enrol/tests/enrollib_test.php
enrol/yui/rolemanager/rolemanager.js
files/classes/converter.php
files/converter/unoconv/classes/converter.php
files/tests/converter_test.php
files/tests/externallib_test.php
filter/emoticon/tests/filter_test.php
filter/mathjaxloader/contrib/a11y/accessibility-menu.js [new file with mode: 0644]
filter/mathjaxloader/contrib/a11y/auto-collapse.js [new file with mode: 0644]
filter/mathjaxloader/contrib/a11y/collapsible.js [new file with mode: 0644]
filter/mathjaxloader/contrib/a11y/explorer.js [new file with mode: 0644]
filter/mathjaxloader/contrib/a11y/invalid_keypress.mp3 [new file with mode: 0644]
filter/mathjaxloader/contrib/a11y/invalid_keypress.ogg [new file with mode: 0644]
filter/mathjaxloader/contrib/a11y/mathjax-sre.js [new file with mode: 0644]
filter/mathjaxloader/contrib/a11y/mathmaps/.htaccess [new file with mode: 0644]
filter/mathjaxloader/contrib/a11y/mathmaps/functions/algebra.json [new file with mode: 0644]
filter/mathjaxloader/contrib/a11y/mathmaps/functions/elementary.json [new file with mode: 0644]
filter/mathjaxloader/contrib/a11y/mathmaps/functions/hyperbolic.json [new file with mode: 0644]
filter/mathjaxloader/contrib/a11y/mathmaps/functions/trigonometry.json [new file with mode: 0644]
filter/mathjaxloader/contrib/a11y/mathmaps/mathmaps_ie.js [new file with mode: 0644]
filter/mathjaxloader/contrib/a11y/mathmaps/symbols/greek-capital.json [new file with mode: 0644]
filter/mathjaxloader/contrib/a11y/mathmaps/symbols/greek-mathfonts.json [new file with mode: 0644]
filter/mathjaxloader/contrib/a11y/mathmaps/symbols/greek-scripts.json [new file with mode: 0644]
filter/mathjaxloader/contrib/a11y/mathmaps/symbols/greek-small.json [new file with mode: 0644]
filter/mathjaxloader/contrib/a11y/mathmaps/symbols/greek-symbols.json [new file with mode: 0644]
filter/mathjaxloader/contrib/a11y/mathmaps/symbols/hebrew_letters.json [new file with mode: 0644]
filter/mathjaxloader/contrib/a11y/mathmaps/symbols/latin-lower-double-accent.json [new file with mode: 0644]
filter/mathjaxloader/contrib/a11y/mathmaps/symbols/latin-lower-normal.json [new file with mode: 0644]
filter/mathjaxloader/contrib/a11y/mathmaps/symbols/latin-lower-phonetic.json [new file with mode: 0644]
filter/mathjaxloader/contrib/a11y/mathmaps/symbols/latin-lower-single-accent.json [new file with mode: 0644]
filter/mathjaxloader/contrib/a11y/mathmaps/symbols/latin-mathfonts.json [new file with mode: 0644]
filter/mathjaxloader/contrib/a11y/mathmaps/symbols/latin-rest.json [new file with mode: 0644]
filter/mathjaxloader/contrib/a11y/mathmaps/symbols/latin-upper-double-accent.json [new file with mode: 0644]
filter/mathjaxloader/contrib/a11y/mathmaps/symbols/latin-upper-normal.json [new file with mode: 0644]
filter/mathjaxloader/contrib/a11y/mathmaps/symbols/latin-upper-single-accent.json [new file with mode: 0644]
filter/mathjaxloader/contrib/a11y/mathmaps/symbols/math_angles.json [new file with mode: 0644]
filter/mathjaxloader/contrib/a11y/mathmaps/symbols/math_arrows.json [new file with mode: 0644]
filter/mathjaxloader/contrib/a11y/mathmaps/symbols/math_characters.json [new file with mode: 0644]
filter/mathjaxloader/contrib/a11y/mathmaps/symbols/math_delimiters.json [new file with mode: 0644]
filter/mathjaxloader/contrib/a11y/mathmaps/symbols/math_digits.json [new file with mode: 0644]
filter/mathjaxloader/contrib/a11y/mathmaps/symbols/math_geometry.json [new file with mode: 0644]
filter/mathjaxloader/contrib/a11y/mathmaps/symbols/math_harpoons.json [new file with mode: 0644]
filter/mathjaxloader/contrib/a11y/mathmaps/symbols/math_non_characters.json [new file with mode: 0644]
filter/mathjaxloader/contrib/a11y/mathmaps/symbols/math_symbols.json [new file with mode: 0644]
filter/mathjaxloader/contrib/a11y/mathmaps/symbols/math_whitespace.json [new file with mode: 0644]
filter/mathjaxloader/contrib/a11y/mathmaps/symbols/other_stars.json [new file with mode: 0644]
filter/mathjaxloader/contrib/a11y/mathmaps/units/energy.json [new file with mode: 0644]
filter/mathjaxloader/contrib/a11y/mathmaps/units/length.json [new file with mode: 0644]
filter/mathjaxloader/contrib/a11y/mathmaps/units/memory.json [new file with mode: 0644]
filter/mathjaxloader/contrib/a11y/mathmaps/units/other.json [new file with mode: 0644]
filter/mathjaxloader/contrib/a11y/mathmaps/units/speed.json [new file with mode: 0644]
filter/mathjaxloader/contrib/a11y/mathmaps/units/temperature.json [new file with mode: 0644]
filter/mathjaxloader/contrib/a11y/mathmaps/units/time.json [new file with mode: 0644]
filter/mathjaxloader/contrib/a11y/mathmaps/units/volume.json [new file with mode: 0644]
filter/mathjaxloader/contrib/a11y/mathmaps/units/weight.json [new file with mode: 0644]
filter/mathjaxloader/contrib/a11y/semantic-enrich.js [new file with mode: 0644]
filter/mathjaxloader/contrib/a11y/wgxpath.install.js [new file with mode: 0644]
filter/mathjaxloader/db/upgrade.php
filter/mathjaxloader/db/upgradelib.php [new file with mode: 0644]
filter/mathjaxloader/filter.php
filter/mathjaxloader/readme_moodle.txt
filter/mathjaxloader/settings.php
filter/mathjaxloader/tests/upgradelib_test.php [new file with mode: 0644]
filter/mathjaxloader/thirdpartylibs.xml [new file with mode: 0644]
filter/mathjaxloader/version.php
filter/mediaplugin/styles.css
install/lang/et/error.php
install/lang/et/install.php
install/lang/et/moodle.php
install/lang/fa/install.php
lang/en/admin.php
lang/en/auth.php
lang/en/completion.php
lang/en/mimetypes.php
lang/en/moodle.php
lib/amd/build/ajax.min.js
lib/amd/src/ajax.js
lib/authlib.php
lib/behat/lib.php
lib/classes/event/completion_defaults_updated.php [new file with mode: 0644]
lib/classes/filetypes.php
lib/classes/oauth2/client.php
lib/classes/output/icon_system_fontawesome.php
lib/classes/session/redis.php
lib/db/install.xml
lib/db/services.php
lib/db/upgrade.php
lib/ddl/sql_generator.php
lib/ddl/tests/ddl_test.php
lib/deprecatedlib.php
lib/enrollib.php
lib/filestorage/file_storage.php
lib/filestorage/file_system.php
lib/filestorage/file_system_filedir.php
lib/filestorage/stored_file.php
lib/filestorage/tests/file_storage_test.php
lib/filestorage/tests/file_system_filedir_test.php
lib/filestorage/tests/file_system_test.php
lib/filestorage/tests/tgz_packer_test.php
lib/filterlib.php
lib/moodlelib.php
lib/navigationlib.php
lib/oauthlib.php
lib/outputlib.php
lib/outputrequirementslib.php
lib/pagelib.php
lib/phpmailer/README_MOODLE.txt
lib/phpmailer/VERSION
lib/phpmailer/class.phpmailer.php
lib/phpmailer/class.smtp.php
lib/phpmailer/language/phpmailer.lang-de.php
lib/phpmailer/language/phpmailer.lang-es.php
lib/phpmailer/language/phpmailer.lang-ro.php
lib/phpunit/bootstrap.php
lib/searchlib.php
lib/statslib.php
lib/templates/permissionmanager_role.mustache
lib/templates/settings_link_page.mustache
lib/tests/configonlylib_test.php
lib/tests/filter_manager_test.php
lib/tests/grouplib_test.php
lib/tests/moodlelib_test.php
lib/tests/outputcomponents_test.php
lib/tests/setuplib_test.php
lib/tests/weblib_format_text_test.php
lib/thirdpartylibs.xml
lib/upgrade.txt
lib/upgradelib.php
lib/weblib.php
media/player/videojs/styles.css
mod/assign/feedback/editpdf/locallib.php
mod/assign/feedback/file/importziplib.php
mod/assign/lib.php
mod/assign/locallib.php
mod/assign/mod_form.php
mod/assign/submission/file/lang/en/assignsubmission_file.php
mod/assign/submission/file/locallib.php
mod/assign/submission/file/tests/behat/file_type_restriction.feature [new file with mode: 0644]
mod/assign/submission/file/tests/locallib_test.php
mod/assign/submission/file/version.php
mod/assign/tests/lib_test.php
mod/book/lib.php
mod/chat/classes/external.php
mod/chat/lib.php
mod/choice/lib.php
mod/choice/mod_form.php
mod/choice/tests/lib_test.php
mod/data/lang/en/data.php
mod/data/lib.php
mod/data/mod_form.php
mod/data/tests/lib_test.php
mod/feedback/classes/completion.php
mod/feedback/classes/external.php
mod/feedback/classes/external/feedback_completed_exporter.php [new file with mode: 0644]
mod/feedback/classes/structure.php
mod/feedback/complete.php
mod/feedback/db/services.php
mod/feedback/lang/en/deprecated.txt
mod/feedback/lang/en/feedback.php
mod/feedback/lib.php
mod/feedback/mod_form.php
mod/feedback/show_nonrespondents.php
mod/feedback/tests/behat/behat_mod_feedback.php
mod/feedback/tests/behat/multipleattempt.feature [new file with mode: 0644]
mod/feedback/tests/external_test.php
mod/feedback/tests/lib_test.php
mod/feedback/upgrade.txt
mod/feedback/version.php
mod/feedback/view.php
mod/folder/lib.php
mod/forum/backup/moodle2/backup_forum_stepslib.php
mod/forum/backup/moodle2/restore_forum_stepslib.php
mod/forum/classes/output/big_search_form.php
mod/forum/classes/post_form.php
mod/forum/db/tag.php [new file with mode: 0644]
mod/forum/lang/en/forum.php
mod/forum/lib.php
mod/forum/locallib.php
mod/forum/mod_form.php
mod/forum/post.php
mod/forum/search.php
mod/forum/templates/big_search_form.mustache
mod/forum/tests/behat/advanced_search.feature
mod/forum/tests/behat/edit_tags.feature [new file with mode: 0644]
mod/forum/tests/behat/forum_subscriptions_availability.feature
mod/forum/tests/behat/forum_subscriptions_management.feature
mod/forum/tests/generator/lib.php
mod/forum/tests/generator_test.php
mod/forum/tests/lib_test.php
mod/forum/tests/mail_test.php
mod/forum/version.php
mod/glossary/lang/en/glossary.php
mod/glossary/lib.php
mod/glossary/mod_form.php
mod/glossary/tests/lib_test.php
mod/imscp/lib.php
mod/label/lib.php
mod/lesson/lang/en/lesson.php
mod/lesson/lib.php
mod/lesson/mod_form.php
mod/lesson/tests/lib_test.php
mod/lti/lib.php
mod/lti/servicelib.php
mod/page/lib.php
mod/quiz/lang/en/quiz.php
mod/quiz/lib.php
mod/quiz/styles.css
mod/quiz/tests/lib_test.php
mod/resource/lib.php
mod/resource/tests/lib_test.php
mod/scorm/lang/en/scorm.php
mod/scorm/lib.php
mod/scorm/mod_form.php
mod/scorm/tests/lib_test.php
mod/survey/lib.php
mod/survey/mod_form.php
mod/survey/tests/lib_test.php
mod/upgrade.txt
mod/url/lib.php
mod/wiki/lib.php
mod/wiki/mod_form.php
mod/workshop/lib.php
pix/f/FileTypesIcons-LICENSE.txt [new file with mode: 0644]
pix/f/Oxygen-LICENSE.txt [new file with mode: 0644]
pix/f/archive-128.png [new file with mode: 0644]
pix/f/archive-24.png [new file with mode: 0644]
pix/f/archive-256.png [new file with mode: 0644]
pix/f/archive-32.png [new file with mode: 0644]
pix/f/archive-48.png [new file with mode: 0644]
pix/f/archive-64.png [new file with mode: 0644]
pix/f/archive-72.png [new file with mode: 0644]
pix/f/archive-80.png [new file with mode: 0644]
pix/f/archive-96.png [new file with mode: 0644]
pix/f/archive.png [new file with mode: 0644]
pix/f/archive.svg [deleted file]
pix/f/audio-128.png [new file with mode: 0644]
pix/f/audio-24.png [new file with mode: 0644]
pix/f/audio-256.png [new file with mode: 0644]
pix/f/audio-32.png [new file with mode: 0644]
pix/f/audio-48.png [new file with mode: 0644]
pix/f/audio-64.png [new file with mode: 0644]
pix/f/audio-72.png [new file with mode: 0644]
pix/f/audio-80.png [new file with mode: 0644]
pix/f/audio-96.png [new file with mode: 0644]
pix/f/audio.png [new file with mode: 0644]
pix/f/audio.svg [deleted file]
pix/f/avi-128.png [new file with mode: 0644]
pix/f/avi-24.png [new file with mode: 0644]
pix/f/avi-256.png [new file with mode: 0644]
pix/f/avi-32.png [new file with mode: 0644]
pix/f/avi-48.png [new file with mode: 0644]
pix/f/avi-64.png [new file with mode: 0644]
pix/f/avi-72.png [new file with mode: 0644]
pix/f/avi-80.png [new file with mode: 0644]
pix/f/avi-96.png [new file with mode: 0644]
pix/f/avi.png [new file with mode: 0644]
pix/f/avi.svg [deleted file]
pix/f/base-128.png [new file with mode: 0644]
pix/f/base-24.png [new file with mode: 0644]
pix/f/base-32.png [new file with mode: 0644]
pix/f/base-48.png [new file with mode: 0644]
pix/f/base-64.png [new file with mode: 0644]
pix/f/base-72.png [new file with mode: 0644]
pix/f/base-80.png [new file with mode: 0644]
pix/f/base-96.png [new file with mode: 0644]
pix/f/base.png [new file with mode: 0644]
pix/f/base.svg [deleted file]
pix/f/bmp-128.png [new file with mode: 0644]
pix/f/bmp-24.png [new file with mode: 0644]
pix/f/bmp-256.png [new file with mode: 0644]
pix/f/bmp-32.png [new file with mode: 0644]
pix/f/bmp-48.png [new file with mode: 0644]
pix/f/bmp-64.png [new file with mode: 0644]
pix/f/bmp-72.png [new file with mode: 0644]
pix/f/bmp-80.png [new file with mode: 0644]
pix/f/bmp-96.png [new file with mode: 0644]
pix/f/bmp.png [new file with mode: 0644]
pix/f/bmp.svg [deleted file]
pix/f/calc-128.png [new file with mode: 0644]
pix/f/calc-24.png [new file with mode: 0644]
pix/f/calc-32.png [new file with mode: 0644]
pix/f/calc-48.png [new file with mode: 0644]
pix/f/calc-64.png [new file with mode: 0644]
pix/f/calc-72.png [new file with mode: 0644]
pix/f/calc-80.png [new file with mode: 0644]
pix/f/calc-96.png [new file with mode: 0644]
pix/f/calc.png [new file with mode: 0644]
pix/f/calc.svg [deleted file]
pix/f/chart-128.png [new file with mode: 0644]
pix/f/chart-24.png [new file with mode: 0644]
pix/f/chart-32.png [new file with mode: 0644]
pix/f/chart-48.png [new file with mode: 0644]
pix/f/chart-64.png [new file with mode: 0644]
pix/f/chart-72.png [new file with mode: 0644]
pix/f/chart-80.png [new file with mode: 0644]
pix/f/chart-96.png [new file with mode: 0644]
pix/f/chart.png [new file with mode: 0644]
pix/f/chart.svg [deleted file]
pix/f/database-128.png [new file with mode: 0644]
pix/f/database-24.png [new file with mode: 0644]
pix/f/database-256.png [new file with mode: 0644]
pix/f/database-32.png [new file with mode: 0644]
pix/f/database-48.png [new file with mode: 0644]
pix/f/database-64.png [new file with mode: 0644]
pix/f/database-72.png [new file with mode: 0644]
pix/f/database-80.png [new file with mode: 0644]
pix/f/database-96.png [new file with mode: 0644]
pix/f/database.png [new file with mode: 0644]
pix/f/database.svg [deleted file]
pix/f/dmg-32.png [new file with mode: 0644]
pix/f/dmg.gif [new file with mode: 0644]
pix/f/dmg.svg [deleted file]
pix/f/document-128.png [new file with mode: 0644]
pix/f/document-24.png [new file with mode: 0644]
pix/f/document-256.png [new file with mode: 0644]
pix/f/document-32.png [new file with mode: 0644]
pix/f/document-48.png [new file with mode: 0644]
pix/f/document-64.png [new file with mode: 0644]
pix/f/document-72.png [new file with mode: 0644]
pix/f/document-80.png [new file with mode: 0644]
pix/f/document-96.png [new file with mode: 0644]
pix/f/document.png [new file with mode: 0644]
pix/f/document.svg [deleted file]
pix/f/draw-128.png [new file with mode: 0644]
pix/f/draw-24.png [new file with mode: 0644]
pix/f/draw-32.png [new file with mode: 0644]
pix/f/draw-48.png [new file with mode: 0644]
pix/f/draw-64.png [new file with mode: 0644]
pix/f/draw-72.png [new file with mode: 0644]
pix/f/draw-80.png [new file with mode: 0644]
pix/f/draw-96.png [new file with mode: 0644]
pix/f/draw.png [new file with mode: 0644]
pix/f/draw.svg [deleted file]
pix/f/edit-32.png [new file with mode: 0644]
pix/f/edit.gif [new file with mode: 0644]
pix/f/env.gif [new file with mode: 0644]
pix/f/eps-128.png [new file with mode: 0644]
pix/f/eps-24.png [new file with mode: 0644]
pix/f/eps-256.png [new file with mode: 0644]
pix/f/eps-32.png [new file with mode: 0644]
pix/f/eps-48.png [new file with mode: 0644]
pix/f/eps-64.png [new file with mode: 0644]
pix/f/eps-72.png [new file with mode: 0644]
pix/f/eps-80.png [new file with mode: 0644]
pix/f/eps-96.png [new file with mode: 0644]
pix/f/eps.png [new file with mode: 0644]
pix/f/eps.svg [deleted file]
pix/f/epub-128.png [new file with mode: 0644]
pix/f/epub-24.png [new file with mode: 0644]
pix/f/epub-256.png [new file with mode: 0644]
pix/f/epub-32.png [new file with mode: 0644]
pix/f/epub-48.png [new file with mode: 0644]
pix/f/epub-64.png [new file with mode: 0644]
pix/f/epub-72.png [new file with mode: 0644]
pix/f/epub-80.png [new file with mode: 0644]
pix/f/epub-96.png [new file with mode: 0644]
pix/f/epub.png [new file with mode: 0644]
pix/f/epub.svg [deleted file]
pix/f/explore-32.png [new file with mode: 0644]
pix/f/explore.gif [new file with mode: 0644]
pix/f/flash-128.png [new file with mode: 0644]
pix/f/flash-24.png [new file with mode: 0644]
pix/f/flash-256.png [new file with mode: 0644]
pix/f/flash-32.png [new file with mode: 0644]
pix/f/flash-48.png [new file with mode: 0644]
pix/f/flash-64.png [new file with mode: 0644]
pix/f/flash-72.png [new file with mode: 0644]
pix/f/flash-80.png [new file with mode: 0644]
pix/f/flash-96.png [new file with mode: 0644]
pix/f/flash.png [new file with mode: 0644]
pix/f/flash.svg [deleted file]
pix/f/folder-128.png [new file with mode: 0644]
pix/f/folder-24.png [new file with mode: 0644]
pix/f/folder-32.png [new file with mode: 0644]
pix/f/folder-48.png [new file with mode: 0644]
pix/f/folder-64.png [new file with mode: 0644]
pix/f/folder-open-128.png [new file with mode: 0644]
pix/f/folder-open-24.png [new file with mode: 0644]
pix/f/folder-open-32.png [new file with mode: 0644]
pix/f/folder-open-48.png [new file with mode: 0644]
pix/f/folder-open-64.png [new file with mode: 0644]
pix/f/folder-open.png [new file with mode: 0644]
pix/f/folder-open.svg [deleted file]
pix/f/folder.png [new file with mode: 0644]
pix/f/folder.svg [deleted file]
pix/f/gif-128.png [new file with mode: 0644]
pix/f/gif-24.png [new file with mode: 0644]
pix/f/gif-256.png [new file with mode: 0644]
pix/f/gif-32.png [new file with mode: 0644]
pix/f/gif-48.png [new file with mode: 0644]
pix/f/gif-64.png [new file with mode: 0644]
pix/f/gif-72.png [new file with mode: 0644]
pix/f/gif-80.png [new file with mode: 0644]
pix/f/gif-96.png [new file with mode: 0644]
pix/f/gif.png [new file with mode: 0644]
pix/f/gif.svg [deleted file]
pix/f/help-32.png [new file with mode: 0644]
pix/f/help.gif [new file with mode: 0644]
pix/f/html-128.png [new file with mode: 0644]
pix/f/html-24.png [new file with mode: 0644]
pix/f/html-256.png [new file with mode: 0644]
pix/f/html-32.png [new file with mode: 0644]
pix/f/html-48.png [new file with mode: 0644]
pix/f/html-64.png [new file with mode: 0644]
pix/f/html-72.png [new file with mode: 0644]
pix/f/html-80.png [new file with mode: 0644]
pix/f/html-96.png [new file with mode: 0644]
pix/f/html.gif [new file with mode: 0644]
pix/f/html.svg [deleted file]
pix/f/image-128.png [new file with mode: 0644]
pix/f/image-24.png [new file with mode: 0644]
pix/f/image-256.png [new file with mode: 0644]
pix/f/image-32.png [new file with mode: 0644]
pix/f/image-48.png [new file with mode: 0644]
pix/f/image-64.png [new file with mode: 0644]
pix/f/image-72.png [new file with mode: 0644]
pix/f/image-80.png [new file with mode: 0644]
pix/f/image-96.png [new file with mode: 0644]
pix/f/image.png [new file with mode: 0644]
pix/f/image.svg [deleted file]
pix/f/impress-128.png [new file with mode: 0644]
pix/f/impress-24.png [new file with mode: 0644]
pix/f/impress-32.png [new file with mode: 0644]
pix/f/impress-48.png [new file with mode: 0644]
pix/f/impress-64.png [new file with mode: 0644]
pix/f/impress-72.png [new file with mode: 0644]
pix/f/impress-80.png [new file with mode: 0644]
pix/f/impress-96.png [new file with mode: 0644]
pix/f/impress.png [new file with mode: 0644]
pix/f/impress.svg [deleted file]
pix/f/isf-128.png [new file with mode: 0644]
pix/f/isf-24.png [new file with mode: 0644]
pix/f/isf-256.png [new file with mode: 0644]
pix/f/isf-32.png [new file with mode: 0644]
pix/f/isf-48.png [new file with mode: 0644]
pix/f/isf-64.png [new file with mode: 0644]
pix/f/isf-72.png [new file with mode: 0644]
pix/f/isf-80.png [new file with mode: 0644]
pix/f/isf-96.png [new file with mode: 0644]
pix/f/isf.png [new file with mode: 0644]
pix/f/isf.svg [deleted file]
pix/f/jpeg-128.png [new file with mode: 0644]
pix/f/jpeg-24.png [new file with mode: 0644]
pix/f/jpeg-256.png [new file with mode: 0644]
pix/f/jpeg-32.png [new file with mode: 0644]
pix/f/jpeg-48.png [new file with mode: 0644]
pix/f/jpeg-64.png [new file with mode: 0644]
pix/f/jpeg-72.png [new file with mode: 0644]
pix/f/jpeg-80.png [new file with mode: 0644]
pix/f/jpeg-96.png [new file with mode: 0644]
pix/f/jpeg.png [new file with mode: 0644]
pix/f/jpeg.svg [deleted file]
pix/f/markup-128.png [new file with mode: 0644]
pix/f/markup-24.png [new file with mode: 0644]
pix/f/markup-256.png [new file with mode: 0644]
pix/f/markup-32.png [new file with mode: 0644]
pix/f/markup-48.png [new file with mode: 0644]
pix/f/markup-64.png [new file with mode: 0644]
pix/f/markup-72.png [new file with mode: 0644]
pix/f/markup-80.png [new file with mode: 0644]
pix/f/markup-96.png [new file with mode: 0644]
pix/f/markup.png [new file with mode: 0644]
pix/f/markup.svg [deleted file]
pix/f/math-128.png [new file with mode: 0644]
pix/f/math-24.png [new file with mode: 0644]
pix/f/math-32.png [new file with mode: 0644]
pix/f/math-48.png [new file with mode: 0644]
pix/f/math-64.png [new file with mode: 0644]
pix/f/math-72.png [new file with mode: 0644]
pix/f/math-80.png [new file with mode: 0644]
pix/f/math-96.png [new file with mode: 0644]
pix/f/math.png [new file with mode: 0644]
pix/f/math.svg [deleted file]
pix/f/moodle-128.png [new file with mode: 0644]
pix/f/moodle-24.png [new file with mode: 0644]
pix/f/moodle-256.png [new file with mode: 0644]
pix/f/moodle-32.png [new file with mode: 0644]
pix/f/moodle-48.png [new file with mode: 0644]
pix/f/moodle-64.png [new file with mode: 0644]
pix/f/moodle-72.png [new file with mode: 0644]
pix/f/moodle-80.png [new file with mode: 0644]
pix/f/moodle-96.png [new file with mode: 0644]
pix/f/moodle.png [new file with mode: 0644]
pix/f/moodle.svg [deleted file]
pix/f/mov.png [new file with mode: 0644]
pix/f/mov.svg [deleted file]
pix/f/move.gif [new file with mode: 0644]
pix/f/mp3-128.png [new file with mode: 0644]
pix/f/mp3-24.png [new file with mode: 0644]
pix/f/mp3-256.png [new file with mode: 0644]
pix/f/mp3-32.png [new file with mode: 0644]
pix/f/mp3-48.png [new file with mode: 0644]
pix/f/mp3-64.png [new file with mode: 0644]
pix/f/mp3-72.png [new file with mode: 0644]
pix/f/mp3-80.png [new file with mode: 0644]
pix/f/mp3-96.png [new file with mode: 0644]
pix/f/mp3.png [new file with mode: 0644]
pix/f/mp3.svg [deleted file]
pix/f/mpeg-128.png [new file with mode: 0644]
pix/f/mpeg-24.png [new file with mode: 0644]
pix/f/mpeg-256.png [new file with mode: 0644]
pix/f/mpeg-32.png [new file with mode: 0644]
pix/f/mpeg-48.png [new file with mode: 0644]
pix/f/mpeg-64.png [new file with mode: 0644]
pix/f/mpeg-72.png [new file with mode: 0644]
pix/f/mpeg-80.png [new file with mode: 0644]
pix/f/mpeg-96.png [new file with mode: 0644]
pix/f/mpeg.png [new file with mode: 0644]
pix/f/mpeg.svg [deleted file]
pix/f/oth-128.png [new file with mode: 0644]
pix/f/oth-24.png [new file with mode: 0644]
pix/f/oth-32.png [new file with mode: 0644]
pix/f/oth-48.png [new file with mode: 0644]
pix/f/oth-64.png [new file with mode: 0644]
pix/f/oth-72.png [new file with mode: 0644]
pix/f/oth-80.png [new file with mode: 0644]
pix/f/oth-96.png [new file with mode: 0644]
pix/f/oth.png [new file with mode: 0644]
pix/f/oth.svg [deleted file]
pix/f/parent-32.png [new file with mode: 0644]
pix/f/parent.gif [new file with mode: 0644]
pix/f/pdf-128.png [new file with mode: 0644]
pix/f/pdf-24.png [new file with mode: 0644]
pix/f/pdf-256.png [new file with mode: 0644]
pix/f/pdf-32.png [new file with mode: 0644]
pix/f/pdf-48.png [new file with mode: 0644]
pix/f/pdf-64.png [new file with mode: 0644]
pix/f/pdf-72.png [new file with mode: 0644]
pix/f/pdf-80.png [new file with mode: 0644]
pix/f/pdf-96.png [new file with mode: 0644]
pix/f/pdf.png [new file with mode: 0644]
pix/f/pdf.svg [deleted file]
pix/f/png-128.png [new file with mode: 0644]
pix/f/png-24.png [new file with mode: 0644]
pix/f/png-256.png [new file with mode: 0644]
pix/f/png-32.png [new file with mode: 0644]
pix/f/png-48.png [new file with mode: 0644]
pix/f/png-64.png [new file with mode: 0644]
pix/f/png-72.png [new file with mode: 0644]
pix/f/png-80.png [new file with mode: 0644]
pix/f/png-96.png [new file with mode: 0644]
pix/f/png.png [new file with mode: 0644]
pix/f/png.svg [deleted file]
pix/f/powerpoint-128.png [new file with mode: 0644]
pix/f/powerpoint-24.png [new file with mode: 0644]
pix/f/powerpoint-256.png [new file with mode: 0644]
pix/f/powerpoint-32.png [new file with mode: 0644]
pix/f/powerpoint-48.png [new file with mode: 0644]
pix/f/powerpoint-64.png [new file with mode: 0644]
pix/f/powerpoint-72.png [new file with mode: 0644]
pix/f/powerpoint-80.png [new file with mode: 0644]
pix/f/powerpoint-96.png [new file with mode: 0644]
pix/f/powerpoint.png [new file with mode: 0644]
pix/f/powerpoint.svg [deleted file]
pix/f/psd-128.png [new file with mode: 0644]
pix/f/psd-24.png [new file with mode: 0644]
pix/f/psd-256.png [new file with mode: 0644]
pix/f/psd-32.png [new file with mode: 0644]
pix/f/psd-48.png [new file with mode: 0644]
pix/f/psd-64.png [new file with mode: 0644]
pix/f/psd-72.png [new file with mode: 0644]
pix/f/psd-80.png [new file with mode: 0644]
pix/f/psd-96.png [new file with mode: 0644]
pix/f/psd.png [new file with mode: 0644]
pix/f/psd.svg [deleted file]
pix/f/publisher-128.png [new file with mode: 0644]
pix/f/publisher-24.png [new file with mode: 0644]
pix/f/publisher-256.png [new file with mode: 0644]
pix/f/publisher-32.png [new file with mode: 0644]
pix/f/publisher-48.png [new file with mode: 0644]
pix/f/publisher-64.png [new file with mode: 0644]
pix/f/publisher-72.png [new file with mode: 0644]
pix/f/publisher-80.png [new file with mode: 0644]
pix/f/publisher-96.png [new file with mode: 0644]
pix/f/publisher.png [new file with mode: 0644]
pix/f/publisher.svg [deleted file]
pix/f/quicktime-128.png [new file with mode: 0644]
pix/f/quicktime-24.png [new file with mode: 0644]
pix/f/quicktime-256.png [new file with mode: 0644]
pix/f/quicktime-32.png [new file with mode: 0644]
pix/f/quicktime-48.png [new file with mode: 0644]
pix/f/quicktime-64.png [new file with mode: 0644]
pix/f/quicktime-72.png [new file with mode: 0644]
pix/f/quicktime-80.png [new file with mode: 0644]
pix/f/quicktime-96.png [new file with mode: 0644]
pix/f/quicktime.png [new file with mode: 0644]
pix/f/quicktime.svg [deleted file]
pix/f/sourcecode-128.png [new file with mode: 0644]
pix/f/sourcecode-24.png [new file with mode: 0644]
pix/f/sourcecode-256.png [new file with mode: 0644]
pix/f/sourcecode-32.png [new file with mode: 0644]
pix/f/sourcecode-48.png [new file with mode: 0644]
pix/f/sourcecode-64.png [new file with mode: 0644]
pix/f/sourcecode-72.png [new file with mode: 0644]
pix/f/sourcecode-80.png [new file with mode: 0644]
pix/f/sourcecode-96.png [new file with mode: 0644]
pix/f/sourcecode.png [new file with mode: 0644]
pix/f/sourcecode.svg [deleted file]
pix/f/spreadsheet-128.png [new file with mode: 0644]
pix/f/spreadsheet-24.png [new file with mode: 0644]
pix/f/spreadsheet-256.png [new file with mode: 0644]
pix/f/spreadsheet-32.png [new file with mode: 0644]
pix/f/spreadsheet-48.png [new file with mode: 0644]
pix/f/spreadsheet-64.png [new file with mode: 0644]
pix/f/spreadsheet-72.png [new file with mode: 0644]
pix/f/spreadsheet-80.png [new file with mode: 0644]
pix/f/spreadsheet-96.png [new file with mode: 0644]
pix/f/spreadsheet.png [new file with mode: 0644]
pix/f/spreadsheet.svg [deleted file]
pix/f/text-128.png [new file with mode: 0644]
pix/f/text-24.png [new file with mode: 0644]
pix/f/text-256.png [new file with mode: 0644]
pix/f/text-32.png [new file with mode: 0644]
pix/f/text-48.png [new file with mode: 0644]
pix/f/text-64.png [new file with mode: 0644]
pix/f/text-72.png [new file with mode: 0644]
pix/f/text-80.png [new file with mode: 0644]
pix/f/text-96.png [new file with mode: 0644]
pix/f/text.png [new file with mode: 0644]
pix/f/text.svg [deleted file]
pix/f/tiff-128.png [new file with mode: 0644]
pix/f/tiff-24.png [new file with mode: 0644]
pix/f/tiff-256.png [new file with mode: 0644]
pix/f/tiff-32.png [new file with mode: 0644]
pix/f/tiff-48.png [new file with mode: 0644]
pix/f/tiff-64.png [new file with mode: 0644]
pix/f/tiff-72.png [new file with mode: 0644]
pix/f/tiff-80.png [new file with mode: 0644]
pix/f/tiff-96.png [new file with mode: 0644]
pix/f/tiff.png [new file with mode: 0644]
pix/f/tiff.svg [deleted file]
pix/f/unknown-128.png [new file with mode: 0644]
pix/f/unknown-24.png [new file with mode: 0644]
pix/f/unknown-256.png [new file with mode: 0644]
pix/f/unknown-32.png [new file with mode: 0644]
pix/f/unknown-48.png [new file with mode: 0644]
pix/f/unknown-64.png [new file with mode: 0644]
pix/f/unknown-72.png [new file with mode: 0644]
pix/f/unknown-80.png [new file with mode: 0644]
pix/f/unknown-96.png [new file with mode: 0644]
pix/f/unknown.png [new file with mode: 0644]
pix/f/unknown.svg [deleted file]
pix/f/video-128.png [new file with mode: 0644]
pix/f/video-24.png [new file with mode: 0644]
pix/f/video-256.png [new file with mode: 0644]
pix/f/video-32.png [new file with mode: 0644]
pix/f/video-48.png [new file with mode: 0644]
pix/f/video-64.png [new file with mode: 0644]
pix/f/video-72.png [new file with mode: 0644]
pix/f/video-80.png [new file with mode: 0644]
pix/f/video-96.png [new file with mode: 0644]
pix/f/video.png [new file with mode: 0644]
pix/f/video.svg [deleted file]
pix/f/wav-128.png [new file with mode: 0644]
pix/f/wav-24.png [new file with mode: 0644]
pix/f/wav-256.png [new file with mode: 0644]
pix/f/wav-32.png [new file with mode: 0644]
pix/f/wav-48.png [new file with mode: 0644]
pix/f/wav-64.png [new file with mode: 0644]
pix/f/wav-72.png [new file with mode: 0644]
pix/f/wav-80.png [new file with mode: 0644]
pix/f/wav-96.png [new file with mode: 0644]
pix/f/wav.png [new file with mode: 0644]
pix/f/wav.svg [deleted file]
pix/f/wmv-128.png [new file with mode: 0644]
pix/f/wmv-24.png [new file with mode: 0644]
pix/f/wmv-256.png [new file with mode: 0644]
pix/f/wmv-32.png [new file with mode: 0644]
pix/f/wmv-48.png [new file with mode: 0644]
pix/f/wmv-64.png [new file with mode: 0644]
pix/f/wmv-72.png [new file with mode: 0644]
pix/f/wmv-80.png [new file with mode: 0644]
pix/f/wmv-96.png [new file with mode: 0644]
pix/f/wmv.png [new file with mode: 0644]
pix/f/wmv.svg [deleted file]
pix/f/writer-128.png [new file with mode: 0644]
pix/f/writer-24.png [new file with mode: 0644]
pix/f/writer-32.png [new file with mode: 0644]
pix/f/writer-48.png [new file with mode: 0644]
pix/f/writer-64.png [new file with mode: 0644]
pix/f/writer-72.png [new file with mode: 0644]
pix/f/writer-80.png [new file with mode: 0644]
pix/f/writer-96.png [new file with mode: 0644]
pix/f/writer.png [new file with mode: 0644]
pix/f/writer.svg [deleted file]
report/participation/index.php
report/stats/locallib.php
repository/filesystem/lib.php
repository/lib.php
theme/boost/templates/core/settings_link_page.mustache
theme/boost/templates/mod_forum/big_search_form.mustache
theme/bootstrapbase/less/moodle/blocks.less
theme/bootstrapbase/less/moodle/forms.less
theme/bootstrapbase/style/moodle.css
theme/bootstrapbase/templates/block_myoverview/course-event-list-item.mustache
theme/bootstrapbase/templates/block_myoverview/course-event-list.mustache [new file with mode: 0644]
theme/bootstrapbase/templates/block_myoverview/course-item.mustache
theme/bootstrapbase/templates/block_myoverview/course-paging-content-item.mustache [new file with mode: 0644]
theme/bootstrapbase/templates/block_myoverview/course-summary.mustache [new file with mode: 0644]
theme/bootstrapbase/templates/block_myoverview/courses-view-course-item.mustache [new file with mode: 0644]
theme/bootstrapbase/templates/block_myoverview/courses-view.mustache [new file with mode: 0644]
theme/bootstrapbase/templates/block_myoverview/event-list-group.mustache [new file with mode: 0644]
theme/bootstrapbase/templates/block_myoverview/event-list-item.mustache
theme/bootstrapbase/templates/block_myoverview/timeline-view.mustache
version.php

index e62d329..f23715a 100644 (file)
@@ -9,6 +9,7 @@ auth/cas/CAS/
 auth/fc/fcFPP.php
 enrol/lti/ims-blti/
 filter/algebra/AlgParser.pm
+filter/mathjaxloader/contrib/a11y/
 filter/tex/mimetex.*
 lib/editor/atto/yui/src/rangy/js/*.*
 lib/editor/tinymce/plugins/pdw/tinymce/
index 8c3d147..02e5607 100644 (file)
@@ -10,6 +10,7 @@ auth/cas/CAS/
 auth/fc/fcFPP.php
 enrol/lti/ims-blti/
 filter/algebra/AlgParser.pm
+filter/mathjaxloader/contrib/a11y/
 filter/tex/mimetex.*
 lib/editor/atto/yui/src/rangy/js/*.*
 lib/editor/tinymce/plugins/pdw/tinymce/
index 799bd5d..ff2b674 100644 (file)
@@ -16,6 +16,9 @@ php:
     - 7.1
     - 5.6
 
+addons:
+  postgresql: "9.3"
+
 services:
     - redis-server
 
@@ -114,7 +117,7 @@ before_script:
 
         # The wwwroot and dataroot.
         sed -i \
-          -e "s%http://example.com/moodle%http://localhost%" \
+          -e "s%http://example.com/moodle%https://localhost%" \
           -e "s%/home/example/moodledata%/home/travis/roots/base%" \
           config.php ;
 
index 38207ed..f875211 100644 (file)
       </CUSTOM_CHECK>
     </CUSTOM_CHECKS>
   </MOODLE>
+  <MOODLE version="3.3" requires="2.7">
+    <UNICODE level="required">
+      <FEEDBACK>
+        <ON_ERROR message="unicoderequired" />
+      </FEEDBACK>
+    </UNICODE>
+    <DATABASE level="required">
+      <VENDOR name="mariadb" version="5.5.31" />
+      <VENDOR name="mysql" version="5.5.31" />
+      <VENDOR name="postgres" version="9.3" />
+      <VENDOR name="mssql" version="10.0" />
+      <VENDOR name="oracle" version="10.2" />
+    </DATABASE>
+    <PHP version="5.6.5" level="required">
+    </PHP>
+    <PCREUNICODE level="optional">
+      <FEEDBACK>
+        <ON_CHECK message="pcreunicodewarning" />
+      </FEEDBACK>
+    </PCREUNICODE>
+    <PHP_EXTENSIONS>
+      <PHP_EXTENSION name="iconv" level="required">
+        <FEEDBACK>
+          <ON_ERROR message="iconvrequired" />
+        </FEEDBACK>
+      </PHP_EXTENSION>
+      <PHP_EXTENSION name="mbstring" level="optional">
+        <FEEDBACK>
+          <ON_CHECK message="mbstringrecommended" />
+        </FEEDBACK>
+      </PHP_EXTENSION>
+      <PHP_EXTENSION name="curl" level="required">
+        <FEEDBACK>
+          <ON_ERROR message="curlrequired" />
+        </FEEDBACK>
+      </PHP_EXTENSION>
+      <PHP_EXTENSION name="openssl" level="required">
+        <FEEDBACK>
+          <ON_ERROR message="opensslrequired" />
+        </FEEDBACK>
+      </PHP_EXTENSION>
+      <PHP_EXTENSION name="tokenizer" level="optional">
+        <FEEDBACK>
+          <ON_CHECK message="tokenizerrecommended" />
+        </FEEDBACK>
+      </PHP_EXTENSION>
+      <PHP_EXTENSION name="xmlrpc" level="optional">
+        <FEEDBACK>
+          <ON_CHECK message="xmlrpcrecommended" />
+        </FEEDBACK>
+      </PHP_EXTENSION>
+      <PHP_EXTENSION name="soap" level="optional">
+        <FEEDBACK>
+          <ON_CHECK message="soaprecommended" />
+        </FEEDBACK>
+      </PHP_EXTENSION>
+      <PHP_EXTENSION name="ctype" level="required">
+        <FEEDBACK>
+          <ON_ERROR message="ctyperequired" />
+        </FEEDBACK>
+      </PHP_EXTENSION>
+      <PHP_EXTENSION name="zip" level="required">
+        <FEEDBACK>
+          <ON_ERROR message="ziprequired" />
+        </FEEDBACK>
+      </PHP_EXTENSION>
+      <PHP_EXTENSION name="zlib" level="required">
+      </PHP_EXTENSION>
+      <PHP_EXTENSION name="gd" level="required">
+        <FEEDBACK>
+          <ON_ERROR message="gdrequired" />
+        </FEEDBACK>
+      </PHP_EXTENSION>
+      <PHP_EXTENSION name="simplexml" level="required">
+        <FEEDBACK>
+          <ON_ERROR message="simplexmlrequired" />
+        </FEEDBACK>
+      </PHP_EXTENSION>
+      <PHP_EXTENSION name="spl" level="required">
+        <FEEDBACK>
+          <ON_ERROR message="splrequired" />
+        </FEEDBACK>
+      </PHP_EXTENSION>
+      <PHP_EXTENSION name="pcre" level="required">
+      </PHP_EXTENSION>
+      <PHP_EXTENSION name="dom" level="required">
+      </PHP_EXTENSION>
+      <PHP_EXTENSION name="xml" level="required">
+      </PHP_EXTENSION>
+      <PHP_EXTENSION name="xmlreader" level="required">
+      </PHP_EXTENSION>
+      <PHP_EXTENSION name="intl" level="optional">
+        <FEEDBACK>
+          <ON_CHECK message="intlrecommended" />
+        </FEEDBACK>
+      </PHP_EXTENSION>
+      <PHP_EXTENSION name="json" level="required">
+      </PHP_EXTENSION>
+      <PHP_EXTENSION name="hash" level="required"/>
+    </PHP_EXTENSIONS>
+    <PHP_SETTINGS>
+      <PHP_SETTING name="memory_limit" value="96M" level="required">
+        <FEEDBACK>
+          <ON_ERROR message="settingmemorylimit" />
+        </FEEDBACK>
+      </PHP_SETTING>
+      <PHP_SETTING name="file_uploads" value="1" level="optional">
+        <FEEDBACK>
+          <ON_CHECK message="settingfileuploads" />
+        </FEEDBACK>
+      </PHP_SETTING>
+      <PHP_SETTING name="opcache.enable" value="1" level="optional">
+        <FEEDBACK>
+          <ON_CHECK message="opcacherecommended" />
+        </FEEDBACK>
+      </PHP_SETTING>
+    </PHP_SETTINGS>
+    <CUSTOM_CHECKS>
+      <CUSTOM_CHECK file="lib/upgradelib.php" function="check_database_storage_engine" level="required">
+        <FEEDBACK>
+          <ON_ERROR message="unsupporteddbstorageengine" />
+        </FEEDBACK>
+      </CUSTOM_CHECK>
+      <CUSTOM_CHECK file="question/engine/upgrade/upgradelib.php" function="quiz_attempts_upgraded" level="required">
+        <FEEDBACK>
+          <ON_ERROR message="quizattemptsupgradedmessage" />
+        </FEEDBACK>
+      </CUSTOM_CHECK>
+      <CUSTOM_CHECK file="lib/upgradelib.php" function="check_slasharguments" level="optional">
+        <FEEDBACK>
+          <ON_CHECK message="slashargumentswarning" />
+        </FEEDBACK>
+      </CUSTOM_CHECK>
+      <CUSTOM_CHECK file="lib/upgradelib.php" function="check_database_tables_row_format" level="optional">
+        <FEEDBACK>
+          <ON_CHECK message="unsupporteddbtablerowformat" />
+        </FEEDBACK>
+      </CUSTOM_CHECK>
+      <CUSTOM_CHECK file="lib/upgradelib.php" function="check_unoconv_version" level="optional">
+        <FEEDBACK>
+          <ON_CHECK message="unoconvwarning" />
+        </FEEDBACK>
+      </CUSTOM_CHECK>
+      <CUSTOM_CHECK file="lib/upgradelib.php" function="check_libcurl_version" level="optional">
+        <FEEDBACK>
+          <ON_CHECK message="libcurlwarning" />
+        </FEEDBACK>
+      </CUSTOM_CHECK>
+      <CUSTOM_CHECK file="lib/upgradelib.php" function="check_mysql_file_format" level="required">
+        <FEEDBACK>
+          <ON_ERROR message="unsupporteddbfileformat" />
+        </FEEDBACK>
+      </CUSTOM_CHECK>
+      <CUSTOM_CHECK file="lib/upgradelib.php" function="check_mysql_file_per_table" level="required">
+        <FEEDBACK>
+          <ON_ERROR message="unsupporteddbfilepertable" />
+        </FEEDBACK>
+      </CUSTOM_CHECK>
+      <CUSTOM_CHECK file="lib/upgradelib.php" function="check_mysql_large_prefix" level="required">
+        <FEEDBACK>
+          <ON_ERROR message="unsupporteddblargeprefix" />
+        </FEEDBACK>
+      </CUSTOM_CHECK>
+      <CUSTOM_CHECK file="lib/upgradelib.php" function="check_is_https" level="optional">
+        <FEEDBACK>
+          <ON_CHECK message="ishttpswarning" />
+        </FEEDBACK>
+      </CUSTOM_CHECK>
+      <CUSTOM_CHECK file="lib/upgradelib.php" function="check_mysql_incomplete_unicode_support" level="optional">
+        <FEEDBACK>
+          <ON_CHECK message="incompleteunicodesupport" />
+        </FEEDBACK>
+      </CUSTOM_CHECK>
+    </CUSTOM_CHECKS>
+  </MOODLE>
 </COMPATIBILITY_MATRIX>
index 451a504..2d6c362 100644 (file)
@@ -1612,7 +1612,7 @@ class core_admin_renderer extends plugin_renderer_base {
                 $row = new html_table_row();
                 $row->attributes['class'] = 'type-' . $plugin->type . ' name-' . $plugin->type . '_' . $plugin->name;
 
-                if ($this->page->theme->resolve_image_location('icon', $plugin->type . '_' . $plugin->name)) {
+                if ($this->page->theme->resolve_image_location('icon', $plugin->type . '_' . $plugin->name, null)) {
                     $icon = $this->output->pix_icon('icon', '', $plugin->type . '_' . $plugin->name, array('class' => 'icon pluginicon'));
                 } else {
                     $icon = $this->output->spacer();
index 8eea3dc..166b4c5 100644 (file)
@@ -175,11 +175,11 @@ class behat_tool_lp_data_generators extends behat_base {
         if (isset($data['framework'])) {
             $framework = competency_framework::get_record(array('idnumber' => $data['framework']));
             if ($framework) {
-                $data['competencyframeworkid'] = $framework->get_id();
+                $data['competencyframeworkid'] = $framework->get('id');
             } else {
                 $framework = competency_framework::get_record(array('id' => $data['framework']));
                 if ($framework) {
-                    $data['competencyframeworkid'] = $framework->get_id();
+                    $data['competencyframeworkid'] = $framework->get('id');
                 } else {
                     throw new Exception('Could not resolve framework with idnumber or id : "' . $data['category'] . '"');
                 }
index 775f006..74de88a 100644 (file)
@@ -1012,7 +1012,7 @@ class manager {
         $messageparams = new \stdClass();
         $messageparams->html    = $message->html;
         $messageparams->plain   = $message->plain;
-        $messagepreferencesurl = new \moodle_url("/message/edit.php", array('id' => $USER->id));
+        $messagepreferencesurl = new \moodle_url("/message/notificationpreferences.php", array('id' => $USER->id));
         $messageparams->messagepreferencesurl = $messagepreferencesurl->out();
         $htmlmessage = get_string('messageprocessingsuccesshtml', 'tool_messageinbound', $messageparams);
         $plainmessage = get_string('messageprocessingsuccess', 'tool_messageinbound', $messageparams);
index 68363af..1545996 100644 (file)
@@ -153,6 +153,14 @@ class api {
             $settings['compactlogourl'] = $compactlogourl->out(false);
         }
 
+        // Identity providers.
+        $authsequence = get_enabled_auth_plugins(true);
+        $identityproviders = \auth_plugin_base::get_identity_providers($authsequence);
+        $identityprovidersdata = \auth_plugin_base::prepare_identity_providers_for_output($identityproviders, $OUTPUT);
+        if (!empty($identityprovidersdata)) {
+            $settings['identityproviders'] = $identityprovidersdata;
+        }
+
         return $settings;
     }
 
index d56966e..a9fdd1f 100644 (file)
@@ -150,6 +150,16 @@ class external extends external_api {
                 'launchurl' => new external_value(PARAM_URL, 'SSO login launch URL. Empty if it won\'t be used.', VALUE_OPTIONAL),
                 'mobilecssurl' => new external_value(PARAM_URL, 'Mobile custom CSS theme', VALUE_OPTIONAL),
                 'tool_mobile_disabledfeatures' => new external_value(PARAM_RAW, 'Disabled features in the app', VALUE_OPTIONAL),
+                'identityproviders' => new external_multiple_structure(
+                    new external_single_structure(
+                        array(
+                            'name' => new external_value(PARAM_TEXT, 'The identity provider name.'),
+                            'iconurl' => new external_value(PARAM_URL, 'The icon URL for the provider.'),
+                            'url' => new external_value(PARAM_URL, 'The URL of the provider.'),
+                        )
+                    ),
+                    'Identity providers', VALUE_OPTIONAL
+                ),
                 'warnings' => new external_warnings(),
             )
         );
index a5a7154..1e74e37 100644 (file)
@@ -32,12 +32,23 @@ $serviceshortname  = required_param('service',  PARAM_ALPHANUMEXT);
 $passport          = required_param('passport',  PARAM_RAW);    // Passport send from the app to validate the response URL.
 $urlscheme         = optional_param('urlscheme', 'moodlemobile', PARAM_NOTAGS); // The URL scheme the app supports.
 $confirmed         = optional_param('confirmed', false, PARAM_BOOL);  // If we are being redirected after user confirmation.
+$oauthsso          = optional_param('oauthsso', 0, PARAM_INT); // Id of the OpenID issuer (for OAuth direct SSO).
 
 // Check web services enabled.
 if (!$CFG->enablewebservices) {
     throw new moodle_exception('enablewsdescription', 'webservice');
 }
 
+// We have been requested to start a SSO process via OpenID.
+if (!empty($oauthsso) && is_enabled_auth('oauth2')) {
+    $wantsurl = new moodle_url('/admin/tool/mobile/launch.php',
+        array('service' => $serviceshortname, 'passport' => $passport, 'urlscheme' => $urlscheme, 'confirmed' => $confirmed));
+    $oauthurl = new moodle_url('/auth/oauth2/login.php',
+        array('id' => $oauthsso, 'sesskey' => sesskey(), 'wantsurl' => $wantsurl));
+    header('Location: ' . $oauthurl->out(false));
+    die;
+}
+
 // Check if the plugin is properly configured.
 $typeoflogin = get_config('tool_mobile', 'typeoflogin');
 if (empty($SESSION->justloggedin) and
index be10099..04c0e24 100644 (file)
@@ -183,9 +183,6 @@ class tool_mobile_external_testcase extends externallib_advanced_testcase {
         $this->assertTrue(isset($token->privatetoken));
 
         // Enable requeriments.
-        $CFG->httpswwwroot = str_replace('http:', 'https:', $CFG->httpswwwroot);    // Mock https.
-        $CFG->enablewebservices = 1;
-        $CFG->enablemobilewebservice = 1;
         $_GET['wstoken'] = $token->token;   // Mock parameters.
 
         // Even if we force the password change for the current user we should be able to retrieve the key.
@@ -212,8 +209,13 @@ class tool_mobile_external_testcase extends externallib_advanced_testcase {
      * Test get_autologin_key missing ws.
      */
     public function test_get_autologin_key_missing_ws() {
+        global $CFG;
         $this->resetAfterTest(true);
 
+        // Need to disable webservices to verify that's checked.
+        $CFG->enablewebservices = 0;
+        $CFG->enablemobilewebservice = 0;
+
         $this->setAdminUser();
         $this->expectException('moodle_exception');
         $this->expectExceptionMessage(get_string('enablewsdescription', 'webservice'));
@@ -226,10 +228,12 @@ class tool_mobile_external_testcase extends externallib_advanced_testcase {
     public function test_get_autologin_key_missing_https() {
         global $CFG;
 
+        // Need to simulate a non HTTPS site here.
+        $CFG->wwwroot = str_replace('https:', 'http:', $CFG->wwwroot);
+        $CFG->httpswwwroot = str_replace('https:', 'http:', $CFG->wwwroot);
+
         $this->resetAfterTest(true);
         $this->setAdminUser();
-        $CFG->enablewebservices = 1;
-        $CFG->enablemobilewebservice = 1;
 
         $this->expectException('moodle_exception');
         $this->expectExceptionMessage(get_string('httpsrequired', 'tool_mobile'));
@@ -244,9 +248,6 @@ class tool_mobile_external_testcase extends externallib_advanced_testcase {
 
         $this->resetAfterTest(true);
         $this->setAdminUser();
-        $CFG->enablewebservices = 1;
-        $CFG->enablemobilewebservice = 1;
-        $CFG->httpswwwroot = str_replace('http:', 'https:', $CFG->httpswwwroot);
 
         $this->expectException('moodle_exception');
         $this->expectExceptionMessage(get_string('autologinnotallowedtoadmins', 'tool_mobile'));
@@ -262,9 +263,6 @@ class tool_mobile_external_testcase extends externallib_advanced_testcase {
         $this->resetAfterTest(true);
         $user = $this->getDataGenerator()->create_user();
         $this->setUser($user);
-        $CFG->enablewebservices = 1;
-        $CFG->enablemobilewebservice = 1;
-        $CFG->httpswwwroot = str_replace('http:', 'https:', $CFG->httpswwwroot);
 
         $service = $DB->get_record('external_services', array('shortname' => MOODLE_OFFICIAL_MOBILE_SERVICE));
 
index ccfc819..9a93520 100644 (file)
@@ -4,4 +4,5 @@ Information provided here is intended especially for developers.
 === 3.3 ===
 
  * External function tool_mobile::get_public_config now returns the mobilecssurl field (Mobile custom CSS theme).
+ * External function tool_mobile::get_public_config now returns the identityproviders field (list of external identity providers).
 
index a86924e..40214ba 100644 (file)
Binary files a/admin/tool/usertours/amd/build/popper.min.js and b/admin/tool/usertours/amd/build/popper.min.js differ
index eaeb288..84a70c2 100644 (file)
Binary files a/admin/tool/usertours/amd/build/tour.min.js and b/admin/tool/usertours/amd/build/tour.min.js differ
index c0fb1d7..a1d9d8c 100644 (file)
-
-/*
-* @fileOverview Kickass library to create and place poppers near their reference elements.
-* @version 1.0.0-alpha.3
-* @license
-* Copyright (c) 2016 Federico Zivolo and contributors
-*
-* Permission is hereby granted, free of charge, to any person obtaining a copy
-* of this software and associated documentation files (the "Software"), to deal
-* in the Software without restriction, including without limitation the rights
-* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-* copies of the Software, and to permit persons to whom the Software is
-* furnished to do so, subject to the following conditions:
-*
-* The above copyright notice and this permission notice shall be included in all
-* copies or substantial portions of the Software.
-*
-* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-* SOFTWARE.
-*/
-                    
+/**!
+ * @fileOverview Kickass library to create and place poppers near their reference elements.
+ * @version 1.0.8
+ * @license
+ * Copyright (c) 2016 Federico Zivolo and contributors
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */    
 (function (global, factory) {
-  typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
-  typeof define === 'function' && define.amd ? define(factory) :
-  (global.Popper = factory());
-}(this, function () { 'use strict';
-
-  /**
-   * The Object.assign() method is used to copy the values of all enumerable own properties from one or more source
-   * objects to a target object. It will return the target object.
-   * This polyfill doesn't support symbol properties, since ES5 doesn't have symbols anyway
-   * Source: https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Object/assign
-   * @function
-   * @ignore
-   */
-  if (!Object.assign) {
-      Object.defineProperty(Object, 'assign', {
-          enumerable: false,
-          configurable: true,
-          writable: true,
-          value: function value(target) {
-              if (target === undefined || target === null) {
-                  throw new TypeError('Cannot convert first argument to object');
-              }
-
-              var to = Object(target);
-              for (var i = 1; i < arguments.length; i++) {
-                  var nextSource = arguments[i];
-                  if (nextSource === undefined || nextSource === null) {
-                      continue;
-                  }
-                  nextSource = Object(nextSource);
-
-                  var keysArray = Object.keys(nextSource);
-                  for (var nextIndex = 0, len = keysArray.length; nextIndex < len; nextIndex++) {
-                      var nextKey = keysArray[nextIndex];
-                      var desc = Object.getOwnPropertyDescriptor(nextSource, nextKey);
-                      if (desc !== undefined && desc.enumerable) {
-                          to[nextKey] = nextSource[nextKey];
-                      }
-                  }
-              }
-              return to;
-          }
-      });
-  }
+       typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
+       typeof define === 'function' && define.amd ? define(factory) :
+       (global.Popper = factory());
+}(this, (function () { 'use strict';
+
+/**
+ * Returns the offset parent of the given element
+ * @method
+ * @memberof Popper.Utils
+ * @argument {Element} element
+ * @returns {Element} offset parent
+ */
+function getOffsetParent(element) {
+    // NOTE: 1 DOM access here
+    var offsetParent = element.offsetParent;
+    var nodeName = offsetParent && offsetParent.nodeName;
 
-  /**
-   * Polyfill for requestAnimationFrame
-   * @function
-   * @ignore
-   */
-  if (!window.requestAnimationFrame) {
-      var lastTime = 0;
-      var vendors = ['ms', 'moz', 'webkit', 'o'];
-      for (var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) {
-          window.requestAnimationFrame = window[vendors[x] + 'RequestAnimationFrame'];
-          window.cancelAnimationFrame = window[vendors[x] + 'CancelAnimationFrame'] || window[vendors[x] + 'CancelRequestAnimationFrame'];
-      }
+    if (!nodeName || nodeName === 'BODY' || nodeName === 'HTML') {
+        return window.document.documentElement;
+    }
 
-      if (!window.requestAnimationFrame) {
-          window.requestAnimationFrame = function (callback) {
-              var currTime = new Date().getTime();
-              var timeToCall = Math.max(0, 16 - (currTime - lastTime));
-              var id = window.setTimeout(function () {
-                  callback(currTime + timeToCall);
-              }, timeToCall);
-              lastTime = currTime + timeToCall;
-              return id;
-          };
-      }
+    return offsetParent;
+}
+
+/**
+ * Get CSS computed property of the given element
+ * @method
+ * @memberof Popper.Utils
+ * @argument {Eement} element
+ * @argument {String} property
+ */
+function getStyleComputedProperty(element, property) {
+    if (element.nodeType !== 1) {
+        return [];
+    }
+    // NOTE: 1 DOM access here
+    var css = window.getComputedStyle(element, null);
+    return property ? css[property] : css;
+}
+
+/**
+ * Returns the parentNode or the host of the element
+ * @method
+ * @memberof Popper.Utils
+ * @argument {Element} element
+ * @returns {Element} parent
+ */
+function getParentNode(element) {
+    if (element.nodeName === 'HTML') {
+        return element;
+    }
+    return element.parentNode || element.host;
+}
+
+/**
+ * Returns the scrolling parent of the given element
+ * @method
+ * @memberof Popper.Utils
+ * @argument {Element} element
+ * @returns {Element} scroll parent
+ */
+function getScrollParent(element) {
+    // Return body, `getScroll` will take care to get the correct `scrollTop` from it
+    if (!element || ['HTML', 'BODY', '#document'].indexOf(element.nodeName) !== -1) {
+        return window.document.body;
+    }
 
-      if (!window.cancelAnimationFrame) {
-          window.cancelAnimationFrame = function (id) {
-              clearTimeout(id);
-          };
-      }
-  }
+    // Firefox want us to check `-x` and `-y` variations as well
 
-  /**
-   * Return the index of the matching object
-   * @method
-   * @memberof Popper.Utils
-   * @argument {Array} arr
-   * @argument prop
-   * @argument value
-   * @returns index or -1
-   */
-  function findIndex(arr, prop, value) {
-    // use filter instead of find because find has less cross-browser support
-    var match = arr.filter(function (obj) {
-      return obj[prop] === value;
-    })[0];
-    return arr.indexOf(match);
-  }
+    var _getStyleComputedProp = getStyleComputedProperty(element),
+        overflow = _getStyleComputedProp.overflow,
+        overflowX = _getStyleComputedProp.overflowX,
+        overflowY = _getStyleComputedProp.overflowY;
 
-  /**
-   * Returns the offset parent of the given element
-   * @method
-   * @memberof Popper.Utils
-   * @argument {Element} element
-   * @returns {Element} offset parent
-   */
-  function getOffsetParent(element) {
-    // NOTE: 1 DOM access here
-    var offsetParent = element.offsetParent;
-    return !offsetParent || offsetParent.nodeName === 'BODY' ? window.document.documentElement : offsetParent;
-  }
+    if (/(auto|scroll)/.test(overflow + overflowY + overflowX)) {
+        return element;
+    }
 
-  /**
-   * Get CSS computed property of the given element
-   * @method
-   * @memberof Popper.Utils
-   * @argument {Eement} element
-   * @argument {String} property
-   */
-  function getStyleComputedProperty(element, property) {
-      if (element.nodeType !== 1) {
-          return [];
-      }
-      // NOTE: 1 DOM access here
-      var css = window.getComputedStyle(element, null);
-      return css[property];
-  }
+    return getScrollParent(getParentNode(element));
+}
+
+/**
+ * Check if the given element is fixed or is inside a fixed parent
+ * @method
+ * @memberof Popper.Utils
+ * @argument {Element} element
+ * @argument {Element} customContainer
+ * @returns {Boolean} answer to "isFixed?"
+ */
+function isFixed(element) {
+    var nodeName = element.nodeName;
+    if (nodeName === 'BODY' || nodeName === 'HTML') {
+        return false;
+    }
+    if (getStyleComputedProperty(element, 'position') === 'fixed') {
+        return true;
+    }
+    return isFixed(getParentNode(element));
+}
+
+/**
+ * Helper used to get the position which will be applied to the popper
+ * @method
+ * @memberof Popper.Utils
+ * @param {HTMLElement} element - popper element
+ * @returns {String} position
+ */
+function getPosition(element) {
+  var container = getOffsetParent(element);
+
+  // Decide if the popper will be fixed
+  // If the reference element is inside a fixed context, the popper will be fixed as well to allow them to scroll together
+  var isParentFixed = isFixed(container);
+  return isParentFixed ? 'fixed' : 'absolute';
+}
 
-  /**
-   * Returns the parentNode or the host of the element
-   * @method
-   * @memberof Popper.Utils
-   * @argument {Element} element
-   * @returns {Element} parent
-   */
-  function getParentNode(element) {
-    return element.parentNode || element.host;
-  }
+/*
+ * Helper to detect borders of a given element
+ * @method
+ * @memberof Popper.Utils
+ * @param {CSSStyleDeclaration} styles - result of `getStyleComputedProperty` on the given element
+ * @param {String} axis - `x` or `y`
+ * @return {Number} borders - the borders size of the given axis
+ */
+
+function getBordersSize(styles, axis) {
+  var sideA = axis === 'x' ? 'Left' : 'Top';
+  var sideB = sideA === 'Left' ? 'Right' : 'Bottom';
+
+  return Number(styles['border' + sideA + 'Width'].split('px')[0]) + Number(styles['border' + sideB + 'Width'].split('px')[0]);
+}
+
+/**
+ * Get bounding client rect of given element
+ * @method
+ * @memberof Popper.Utils
+ * @param {HTMLElement} element
+ * @return {Object} client rect
+ */
+function getBoundingClientRect(element) {
+    var isIE10 = navigator.appVersion.indexOf('MSIE 10') !== -1;
+    var rect = void 0;
+
+    // IE10 10 FIX: Please, don't ask, the element isn't
+    // considered in DOM in some circumstances...
+    // This isn't reproducible in IE10 compatibility mode of IE11
+    if (isIE10) {
+        try {
+            rect = element.getBoundingClientRect();
+        } catch (err) {
+            rect = {};
+        }
+    } else {
+        rect = element.getBoundingClientRect();
+    }
 
-  /**
-   * Returns the scrolling parent of the given element
-   * @method
-   * @memberof Popper.Utils
-   * @argument {Element} element
-   * @returns {Element} offset parent
-   */
-  function getScrollParent(element) {
-      if (element === window.document) {
-          // Firefox puts the scrollTOp value on `documentElement` instead of `body`, we then check which of them is
-          // greater than 0 and return the proper element
-          if (window.document.body.scrollTop) {
-              return window.document.body;
-          } else {
-              return window.document.documentElement;
-          }
-      }
+    var result = {
+        left: rect.left,
+        top: rect.top,
+        right: rect.right,
+        bottom: rect.bottom,
+        width: rect.right - rect.left,
+        height: rect.bottom - rect.top
+    };
 
-      // Firefox want us to check `-x` and `-y` variations as well
-      if (['scroll', 'auto'].indexOf(getStyleComputedProperty(element, 'overflow')) !== -1 || ['scroll', 'auto'].indexOf(getStyleComputedProperty(element, 'overflow-x')) !== -1 || ['scroll', 'auto'].indexOf(getStyleComputedProperty(element, 'overflow-y')) !== -1) {
-          // If the detected scrollParent is body, we perform an additional check on its parentNode
-          // in this way we'll get body if the browser is Chrome-ish, or documentElement otherwise
-          // fixes issue #65
-          return element === window.document.body ? getScrollParent(getParentNode(element)) : element;
-      }
-      return getParentNode(element) ? getScrollParent(getParentNode(element)) : element;
-  }
+    // IE10 FIX: `getBoundingClientRect`, when executed on `documentElement`
+    // will not take in account the `scrollTop` and `scrollLeft`
+    if (element.nodeName === 'HTML' && isIE10) {
+        var _window$document$docu = window.document.documentElement,
+            scrollTop = _window$document$docu.scrollTop,
+            scrollLeft = _window$document$docu.scrollLeft;
+
+        result.top -= scrollTop;
+        result.bottom -= scrollTop;
+        result.left -= scrollLeft;
+        result.right -= scrollLeft;
+    }
 
-  /**
-   * Get the position of the given element, relative to its offset parent
-   * @method
-   * @memberof Popper.Utils
-   * @param {Element} element
-   * @return {Object} position - Coordinates of the element and its `scrollTop`
-   */
-  function getOffsetRect(element) {
-      var elementRect = {
-          width: element.offsetWidth,
-          height: element.offsetHeight,
-          left: element.offsetLeft,
-          top: element.offsetTop
-      };
-
-      elementRect.right = elementRect.left + elementRect.width;
-      elementRect.bottom = elementRect.top + elementRect.height;
-
-      // position
-      return elementRect;
-  }
+    // subtract scrollbar size from sizes
+    var horizScrollbar = rect.width - (element.clientWidth || rect.right - rect.left);
+    var vertScrollbar = rect.height - (element.clientHeight || rect.bottom - rect.top);
 
-  /**
-   * Computed the boundaries limits and return them
-   * @method
-   * @memberof Popper.Utils
-   * @param {Object} data - Object containing the property "offsets" generated by `_getOffsets`
-   * @param {Number} padding - Boundaries padding
-   * @param {Element} boundariesElement - Element used to define the boundaries
-   * @returns {Object} Coordinates of the boundaries
-   */
-  function getBoundaries(popper, data, padding, boundariesElement) {
-      // NOTE: 1 DOM access here
-      var boundaries = {};
-      if (boundariesElement === 'window') {
-          var body = window.document.body;
-          var html = window.document.documentElement;
-          var height = Math.max(body.scrollHeight, body.offsetHeight, html.clientHeight, html.scrollHeight, html.offsetHeight);
-          var width = Math.max(body.scrollWidth, body.offsetWidth, html.clientWidth, html.scrollWidth, html.offsetWidth);
-
-          boundaries = {
-              top: 0,
-              right: width,
-              bottom: height,
-              left: 0
-          };
-      } else if (boundariesElement === 'viewport') {
-          var offsetParent = getOffsetParent(popper);
-          var scrollParent = getScrollParent(popper);
-          var offsetParentRect = getOffsetRect(offsetParent);
-
-          // if the popper is fixed we don't have to substract scrolling from the boundaries
-          var scrollTop = data.offsets.popper.position === 'fixed' ? 0 : scrollParent.scrollTop;
-          var scrollLeft = data.offsets.popper.position === 'fixed' ? 0 : scrollParent.scrollLeft;
-
-          boundaries = {
-              top: 0 - (offsetParentRect.top - scrollTop),
-              right: window.document.documentElement.clientWidth - (offsetParentRect.left - scrollLeft),
-              bottom: window.document.documentElement.clientHeight - (offsetParentRect.top - scrollTop),
-              left: 0 - (offsetParentRect.left - scrollLeft)
-          };
-      } else {
-          if (getOffsetParent(popper) === boundariesElement) {
-              boundaries = {
-                  top: 0,
-                  left: 0,
-                  right: boundariesElement.clientWidth,
-                  bottom: boundariesElement.clientHeight
-              };
-          } else {
-              boundaries = getOffsetRect(boundariesElement);
-          }
-      }
-      boundaries.left += padding;
-      boundaries.right -= padding;
-      boundaries.top = boundaries.top + padding;
-      boundaries.bottom = boundaries.bottom - padding;
-      return boundaries;
-  }
+    // if an hypothetical scrollbar is detected, we must be sure it's not a `border`
+    // we make this check conditional for performance reasons
+    if (horizScrollbar || vertScrollbar) {
+        var styles = getStyleComputedProperty(element);
+        horizScrollbar -= getBordersSize(styles, 'x');
+        vertScrollbar -= getBordersSize(styles, 'y');
+    }
 
-  /**
-   * Get bounding client rect of given element
-   * @method
-   * @memberof Popper.Utils
-   * @param {HTMLElement} element
-   * @return {Object} client rect
-   */
-  function getBoundingClientRect(element) {
-      var rect = element.getBoundingClientRect();
-      return {
-          left: rect.left,
-          top: rect.top,
-          right: rect.right,
-          bottom: rect.bottom,
-          width: rect.right - rect.left,
-          height: rect.bottom - rect.top
-      };
-  }
+    result.right -= horizScrollbar;
+    result.width -= horizScrollbar;
+    result.bottom -= vertScrollbar;
+    result.height -= vertScrollbar;
 
-  /**
-   * Given an element and one of its parents, return the offset
-   * @method
-   * @memberof Popper.Utils
-   * @param {HTMLElement} element
-   * @param {HTMLElement} parent
-   * @return {Object} rect
-   */
-  function getOffsetRectRelativeToCustomParent(element, parent, fixed, transformed) {
-      var elementRect = getBoundingClientRect(element);
-      var parentRect = getBoundingClientRect(parent);
-
-      if (fixed && !transformed) {
-          var scrollParent = getScrollParent(parent);
-          parentRect.top += scrollParent.scrollTop;
-          parentRect.bottom += scrollParent.scrollTop;
-          parentRect.left += scrollParent.scrollLeft;
-          parentRect.right += scrollParent.scrollLeft;
-      }
+    return result;
+}
 
-      var rect = {
-          top: elementRect.top - parentRect.top,
-          left: elementRect.left - parentRect.left,
-          bottom: elementRect.top - parentRect.top + elementRect.height,
-          right: elementRect.left - parentRect.left + elementRect.width,
-          width: elementRect.width,
-          height: elementRect.height
-      };
-      return rect;
-  }
+function getScroll(element) {
+    var side = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'top';
 
-  /**
-   * Get the outer sizes of the given element (offset size + margins)
-   * @method
-   * @memberof Popper.Utils
-   * @argument {Element} element
-   * @returns {Object} object containing width and height properties
-   */
-  function getOuterSizes(element) {
-      // NOTE: 1 DOM access here
-      var display = element.style.display;
-      var visibility = element.style.visibility;
-
-      element.style.display = 'block';
-      element.style.visibility = 'hidden';
-
-      // original method
-      var styles = window.getComputedStyle(element);
-      var x = parseFloat(styles.marginTop) + parseFloat(styles.marginBottom);
-      var y = parseFloat(styles.marginLeft) + parseFloat(styles.marginRight);
-      var result = {
-          width: element.offsetWidth + y,
-          height: element.offsetHeight + x
-      };
-
-      // reset element styles
-      element.style.display = display;
-      element.style.visibility = visibility;
-
-      return result;
-  }
+    var upperSide = side === 'top' ? 'scrollTop' : 'scrollLeft';
+    var nodeName = element.nodeName;
 
-  /**
-   * Given the popper offsets, generate an output similar to getBoundingClientRect
-   * @method
-   * @memberof Popper.Utils
-   * @argument {Object} popperOffsets
-   * @returns {Object} ClientRect like output
-   */
-  function getPopperClientRect(popperOffsets) {
-      return Object.assign({}, popperOffsets, {
-          right: popperOffsets.left + popperOffsets.width,
-          bottom: popperOffsets.top + popperOffsets.height
-      });
-  }
+    if (nodeName === 'BODY' || nodeName === 'HTML') {
+        var html = window.document.documentElement;
+        var scrollingElement = window.document.scrollingElement || html;
+        return scrollingElement[upperSide];
+    }
 
-  /**
-   * Check if the given element is fixed or is inside a fixed parent
-   * @method
-   * @memberof Popper.Utils
-   * @argument {Element} element
-   * @argument {Element} customContainer
-   * @returns {Boolean} answer to "isFixed?"
-   */
-  function isFixed(element) {
-      if (element === window.document.body) {
-          return false;
-      }
-      if (getStyleComputedProperty(element, 'position') === 'fixed') {
-          return true;
-      }
-      return getParentNode(element) ? isFixed(getParentNode(element)) : element;
-  }
+    return element[upperSide];
+}
 
-  /**
-   * Helper used to get the position which will be applied to the popper
-   * @method
-   * @memberof Popper.Utils
-   * @param config {HTMLElement} popper element
-   * @returns {HTMLElement} reference element
-   */
-  function getPosition(popper, reference) {
-    var container = getOffsetParent(reference);
-
-    // Decide if the popper will be fixed
-    // If the reference element is inside a fixed context, the popper will be fixed as well to allow them to scroll together
-    var isParentFixed = isFixed(container);
-    return isParentFixed ? 'fixed' : 'absolute';
-  }
+/*
+ * Sum or subtract the element scroll values (left and top) from a given rect object
+ * @method
+ * @memberof Popper.Utils
+ * @param {Object} rect - Rect object you want to change
+ * @param {HTMLElement} element - The element from the function reads the scroll values
+ * @param {Boolean} subtract - set to true if you want to subtract the scroll values
+ * @return {Object} rect - The modifier rect object
+ */
+function includeScroll(rect, element) {
+  var subtract = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
+
+  var scrollTop = getScroll(element, 'top');
+  var scrollLeft = getScroll(element, 'left');
+  var modifier = subtract ? -1 : 1;
+  rect.top += scrollTop * modifier;
+  rect.bottom += scrollTop * modifier;
+  rect.left += scrollLeft * modifier;
+  rect.right += scrollLeft * modifier;
+  return rect;
+}
+
+/**
+ * Given an element and one of its parents, return the offset
+ * @method
+ * @memberof Popper.Utils
+ * @param {HTMLElement} element
+ * @param {HTMLElement} parent
+ * @return {Object} rect
+ */
+function getOffsetRectRelativeToCustomParent(element, parent) {
+    var fixed = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
+    var transformed = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false;
+
+    var scrollParent = getScrollParent(parent);
+    var elementRect = getBoundingClientRect(element);
+    var parentRect = getBoundingClientRect(parent);
+
+    var rect = {
+        top: elementRect.top - parentRect.top,
+        left: elementRect.left - parentRect.left,
+        bottom: elementRect.top - parentRect.top + elementRect.height,
+        right: elementRect.left - parentRect.left + elementRect.width,
+        width: elementRect.width,
+        height: elementRect.height
+    };
 
-  /**
-   * Get the prefixed supported property name
-   * @method
-   * @memberof Popper.Utils
-   * @argument {String} property (camelCase)
-   * @returns {String} prefixed property (camelCase)
-   */
-  function getSupportedPropertyName(property) {
-      var prefixes = ['', 'ms', 'webkit', 'moz', 'o'];
-
-      for (var i = 0; i < prefixes.length; i++) {
-          var toCheck = prefixes[i] ? prefixes[i] + property.charAt(0).toUpperCase() + property.slice(1) : property;
-          if (typeof window.document.body.style[toCheck] !== 'undefined') {
-              return toCheck;
-          }
-      }
-      return null;
-  }
+    if (fixed && !transformed) {
+        rect = includeScroll(rect, scrollParent, true);
+    }
+    // When a popper doesn't have any positioned or scrollable parents, `offsetParent.contains(scrollParent)`
+    // will return a "false positive". This is happening because `getOffsetParent` returns `html` node,
+    // and `scrollParent` is the `body` node. Hence the additional check.
+    else if (getOffsetParent(element).contains(scrollParent) && scrollParent.nodeName !== 'BODY') {
+            rect = includeScroll(rect, parent);
+        }
+
+    // subtract borderTopWidth and borderTopWidth from final result
+    var styles = getStyleComputedProperty(parent);
+    var borderTopWidth = Number(styles.borderTopWidth.split('px')[0]);
+    var borderLeftWidth = Number(styles.borderLeftWidth.split('px')[0]);
+
+    rect.top -= borderTopWidth;
+    rect.bottom -= borderTopWidth;
+    rect.left -= borderLeftWidth;
+    rect.right -= borderLeftWidth;
+
+    return rect;
+}
+
+function getWindowSizes() {
+    var body = window.document.body;
+    var html = window.document.documentElement;
+    return {
+        height: Math.max(body.scrollHeight, body.offsetHeight, html.clientHeight, html.scrollHeight, html.offsetHeight),
+        width: Math.max(body.scrollWidth, body.offsetWidth, html.clientWidth, html.scrollWidth, html.offsetWidth)
+    };
+}
+
+/**
+ * Get the position of the given element, relative to its offset parent
+ * @method
+ * @memberof Popper.Utils
+ * @param {Element} element
+ * @return {Object} position - Coordinates of the element and its `scrollTop`
+ */
+function getOffsetRect(element) {
+    var elementRect = void 0;
+    if (element.nodeName === 'HTML') {
+        var _getWindowSizes = getWindowSizes(),
+            width = _getWindowSizes.width,
+            height = _getWindowSizes.height;
+
+        elementRect = {
+            width: width,
+            height: height,
+            left: 0,
+            top: 0
+        };
+    } else {
+        elementRect = {
+            width: element.offsetWidth,
+            height: element.offsetHeight,
+            left: element.offsetLeft,
+            top: element.offsetTop
+        };
+    }
 
-  /**
-   * Check if the given variable is a function
-   * @method
-   * @memberof Popper.Utils
-   * @argument {Element} element - Element to check
-   * @returns {Boolean} answer to: is a function?
-   */
-  function isFunction(functionToCheck) {
-    var getType = {};
-    return functionToCheck && getType.toString.call(functionToCheck) === '[object Function]';
-  }
+    elementRect.right = elementRect.left + elementRect.width;
+    elementRect.bottom = elementRect.top + elementRect.height;
+
+    // position
+    return elementRect;
+}
+
+function getOffsetRectRelativeToViewport(element) {
+    // Offset relative to offsetParent
+    var relativeOffset = getOffsetRect(element);
+
+    if (element.nodeName !== 'HTML') {
+        var offsetParent = getOffsetParent(element);
+        var parentOffset = getOffsetRectRelativeToViewport(offsetParent);
+        var offset = {
+            width: relativeOffset.offsetWidth,
+            height: relativeOffset.offsetHeight,
+            left: relativeOffset.left + parentOffset.left,
+            top: relativeOffset.top + parentOffset.top,
+            right: relativeOffset.right - parentOffset.right,
+            bottom: relativeOffset.bottom - parentOffset.bottom
+        };
+        return offset;
+    }
 
-  /**
-   * Helper used to know if the given modifier depends from another one.
-   * @method
-   * @memberof Popper.Utils
-   * @returns {Boolean}
-   */
-  function isModifierRequired(modifiers, requesting, requested) {
-      return !!modifiers.filter(function (modifier) {
-          if (modifier.name === requested) {
-              return true;
-          } else if (modifier.name === requesting) {
-              return false;
-          }
-          return false;
-      }).length;
-  }
+    return relativeOffset;
+}
 
-  /**
-   * Tells if a given input is a number
-   * @method
-   * @memberof Popper.Utils
-   * @param {*} input to check
-   * @return {Boolean}
-   */
-  function isNumeric(n) {
-    return n !== '' && !isNaN(parseFloat(n)) && isFinite(n);
-  }
+function getTotalScroll(element) {
+    var side = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'top';
 
-  /**
-   * Check if the given element has transforms applied to itself or a parent
-   * @method
-   * @memberof Popper.Utils
-   * @param  {Element} element
-   * @return {Boolean} answer to "isTransformed?"
-   */
-  function isTransformed(element) {
-      if (element === window.document.body) {
-          return false;
-      }
-      if (getStyleComputedProperty(element, 'transform') !== 'none') {
-          return true;
-      }
-      return getParentNode(element) ? isTransformed(getParentNode(element)) : element;
-  }
+    var scrollParent = getScrollParent(element);
+    var scroll = getScroll(scrollParent, side);
 
-  /**
-   * Loop trough the list of modifiers and run them in order, each of them will then edit the data object
-   * @method
-   * @memberof Popper.Utils
-   * @param {Object} data
-   * @param {Array} modifiers
-   * @param {Function} ends
-   */
-  function runModifiers(modifiers, options, data, ends) {
-      var modifiersToRun = ends === undefined ? modifiers : modifiers.slice(0, findIndex(modifiers, 'name', ends));
-
-      modifiersToRun.forEach(function (modifier) {
-          if (modifier.enabled && isFunction(modifier.function)) {
-              data = modifier.function(data, modifier);
-          }
-      });
-
-      return data;
-  }
+    if (['BODY', 'HTML'].indexOf(scrollParent.nodeName) === -1) {
+        return scroll + getTotalScroll(getParentNode(scrollParent), side);
+    }
+    return scroll;
+}
+
+/**
+ * Computed the boundaries limits and return them
+ * @method
+ * @memberof Popper.Utils
+ * @param {Object} data - Object containing the property "offsets" generated by `_getOffsets`
+ * @param {Number} padding - Boundaries padding
+ * @param {Element} boundariesElement - Element used to define the boundaries
+ * @returns {Object} Coordinates of the boundaries
+ */
+function getBoundaries(popper, padding, boundariesElement) {
+    // NOTE: 1 DOM access here
+    var boundaries = { top: 0, left: 0 };
+    var offsetParent = getOffsetParent(popper);
+
+    // Handle viewport case
+    if (boundariesElement === 'viewport') {
+        var _getOffsetRectRelativ = getOffsetRectRelativeToViewport(offsetParent),
+            left = _getOffsetRectRelativ.left,
+            top = _getOffsetRectRelativ.top;
+
+        var _window$document$docu = window.document.documentElement,
+            width = _window$document$docu.clientWidth,
+            height = _window$document$docu.clientHeight;
+
+
+        if (getPosition(popper) === 'fixed') {
+            boundaries.right = width;
+            boundaries.bottom = height;
+        } else {
+            var scrollLeft = getTotalScroll(popper, 'left');
+            var scrollTop = getTotalScroll(popper, 'top');
+
+            boundaries = {
+                top: 0 - top,
+                right: width - left + scrollLeft,
+                bottom: height - top + scrollTop,
+                left: 0 - left
+            };
+        }
+    }
+    // Handle other cases based on DOM element used as boundaries
+    else {
+            var boundariesNode = void 0;
+            if (boundariesElement === 'scrollParent') {
+                boundariesNode = getScrollParent(getParentNode(popper));
+            } else if (boundariesElement === 'window') {
+                boundariesNode = window.document.body;
+            } else {
+                boundariesNode = boundariesElement;
+            }
+
+            // In case of BODY, we need a different computation
+            if (boundariesNode.nodeName === 'BODY') {
+                var _getWindowSizes = getWindowSizes(),
+                    _height = _getWindowSizes.height,
+                    _width = _getWindowSizes.width;
+
+                boundaries.right = _width;
+                boundaries.bottom = _height;
+            }
+            // for all the other DOM elements, this one is good
+            else {
+                    boundaries = getOffsetRectRelativeToCustomParent(boundariesNode, offsetParent, isFixed(popper));
+                }
+        }
+
+    // Add paddings
+    boundaries.left += padding;
+    boundaries.top += padding;
+    boundaries.right -= padding;
+    boundaries.bottom -= padding;
+
+    return boundaries;
+}
+
+/**
+ * Utility used to transform the `auto` placement to the placement with more
+ * available space.
+ * @method
+ * @memberof Popper.Utils
+ * @argument {Object} data - The data object generated by update method
+ * @argument {Object} options - Modifiers configuration and options
+ * @returns {Object} The data object, properly modified
+ */
+function computeAutoPlacement(placement, refRect, popper) {
+    if (placement.indexOf('auto') === -1) {
+        return placement;
+    }
 
-  /**
-   * Set the style to the given popper
-   * @method
-   * @memberof Popper.Utils
-   * @argument {Element} element - Element to apply the style to
-   * @argument {Object} styles - Object with a list of properties and values which will be applied to the element
-   */
-  function setStyle(element, styles) {
-      Object.keys(styles).forEach(function (prop) {
-          var unit = '';
-          // add unit if the value is numeric and is one of the following
-          if (['width', 'height', 'top', 'right', 'bottom', 'left'].indexOf(prop) !== -1 && isNumeric(styles[prop])) {
-              unit = 'px';
-          }
-          element.style[prop] = styles[prop] + unit;
-      });
-  }
+    var boundaries = getBoundaries(popper, 0, 'scrollParent');
 
-  /** @namespace Popper.Utils */
-  var Utils = {
-      findIndex: findIndex,
-      getBoundaries: getBoundaries,
-      getBoundingClientRect: getBoundingClientRect,
-      getOffsetParent: getOffsetParent,
-      getOffsetRectRelativeToCustomParent: getOffsetRectRelativeToCustomParent,
-      getOuterSizes: getOuterSizes,
-      getPopperClientRect: getPopperClientRect,
-      getPosition: getPosition,
-      getScrollParent: getScrollParent,
-      getStyleComputedProperty: getStyleComputedProperty,
-      getSupportedPropertyName: getSupportedPropertyName,
-      isFixed: isFixed,
-      isFunction: isFunction,
-      isModifierRequired: isModifierRequired,
-      isNumeric: isNumeric,
-      isTransformed: isTransformed,
-      runModifiers: runModifiers,
-      setStyle: setStyle
-  };
+    var sides = {
+        top: refRect.top - boundaries.top,
+        right: boundaries.right - refRect.right,
+        bottom: boundaries.bottom - refRect.bottom,
+        left: refRect.left - boundaries.left
+    };
 
-  /**
-   * Get offsets to the popper
-   * @method
-   * @memberof Popper.Utils
-   * @param {Element} popper - the popper element
-   * @param {Element} reference - the reference element (the popper will be relative to this)
-   * @returns {Object} An object containing the offsets which will be applied to the popper
-   */
-  function getOffsets(state, popper, reference, placement) {
-      placement = placement.split('-')[0];
-
-      var popperOffsets = {};
-      popperOffsets.position = state.position;
-
-      var isParentFixed = popperOffsets.position === 'fixed';
-      var isParentTransformed = state.isParentTransformed;
-
-      //
-      // Get reference element position
-      //
-      var offsetParent = getOffsetParent(isParentFixed && isParentTransformed ? reference : popper);
-      var referenceOffsets = getOffsetRectRelativeToCustomParent(reference, offsetParent, isParentFixed, isParentTransformed);
-
-      //
-      // Get popper sizes
-      //
-      var popperRect = getOuterSizes(popper);
-
-      //
-      // Compute offsets of popper
-      //
-
-      // depending by the popper placement we have to compute its offsets slightly differently
-      if (['right', 'left'].indexOf(placement) !== -1) {
-          popperOffsets.top = referenceOffsets.top + referenceOffsets.height / 2 - popperRect.height / 2;
-          if (placement === 'left') {
-              popperOffsets.left = referenceOffsets.left - popperRect.width;
-          } else {
-              popperOffsets.left = referenceOffsets.right;
-          }
-      } else {
-          popperOffsets.left = referenceOffsets.left + referenceOffsets.width / 2 - popperRect.width / 2;
-          if (placement === 'top') {
-              popperOffsets.top = referenceOffsets.top - popperRect.height;
-          } else {
-              popperOffsets.top = referenceOffsets.bottom;
-          }
-      }
+    var computedPlacement = Object.keys(sides).sort(function (a, b) {
+        return sides[b] - sides[a];
+    })[0];
+    var variation = placement.split('-')[1];
+
+    return computedPlacement + (variation ? '-' + variation : '');
+}
+
+var nativeHints = ['native code', '[object MutationObserverConstructor]' // for mobile safari iOS 9.0
+];
+
+/**
+ * Determine if a function is implemented natively (as opposed to a polyfill).
+ * @argument {Function | undefined} fn the function to check
+ * @returns {boolean}
+ */
+var isNative = (function (fn) {
+  return nativeHints.some(function (hint) {
+    return (fn || '').toString().indexOf(hint) > -1;
+  });
+});
+
+var isBrowser = typeof window !== 'undefined';
+var longerTimeoutBrowsers = ['Edge', 'Trident', 'Firefox'];
+var timeoutDuration = 0;
+for (var i = 0; i < longerTimeoutBrowsers.length; i += 1) {
+    if (isBrowser && navigator.userAgent.indexOf(longerTimeoutBrowsers[i]) >= 0) {
+        timeoutDuration = 1;
+        break;
+    }
+}
+
+function microtaskDebounce(fn) {
+    var scheduled = false;
+    var i = 0;
+    var elem = document.createElement('span');
+
+    // MutationObserver provides a mechanism for scheduling microtasks, which
+    // are scheduled *before* the next task. This gives us a way to debounce
+    // a function but ensure it's called *before* the next paint.
+    var observer = new MutationObserver(function () {
+        fn();
+        scheduled = false;
+    });
 
-      // Add width and height to our offsets object
-      popperOffsets.width = popperRect.width;
-      popperOffsets.height = popperRect.height;
+    observer.observe(elem, { attributes: true });
 
-      return {
-          popper: popperOffsets,
-          reference: referenceOffsets
-      };
-  }
+    return function () {
+        if (!scheduled) {
+            scheduled = true;
+            elem.setAttribute('x-index', i);
+            i = i + 1; // don't use compund (+=) because it doesn't get optimized in V8
+        }
+    };
+}
+
+function taskDebounce(fn) {
+    var scheduled = false;
+    return function () {
+        if (!scheduled) {
+            scheduled = true;
+            setTimeout(function () {
+                scheduled = false;
+                fn();
+            }, timeoutDuration);
+        }
+    };
+}
 
-  /**
-   * Setup needed event listeners used to update the popper position
-   * @method
-   * @memberof Popper.Utils
-   * @private
-   */
-  function setupEventListeners(reference, options, state, updateBound) {
-      // NOTE: 1 DOM access here
-      state.updateBound = updateBound;
-      window.addEventListener('resize', state.updateBound, { passive: true });
-      // if the boundariesElement is window we don't need to listen for the scroll event
-      if (options.boundariesElement !== 'window') {
-          var target = getScrollParent(reference);
-          // here it could be both `body` or `documentElement` thanks to Firefox, we then check both
-          if (target === window.document.body || target === window.document.documentElement) {
-              target = window;
-          }
-          target.addEventListener('scroll', state.updateBound, { passive: true });
-      }
-  }
+// It's common for MutationObserver polyfills to be seen in the wild, however
+// these rely on Mutation Events which only occur when an element is connected
+// to the DOM. The algorithm used in this module does not use a connected element,
+// and so we must ensure that a *native* MutationObserver is available.
+var supportsNativeMutationObserver = isBrowser && isNative(window.MutationObserver);
 
-  /**
-   * Remove event listeners used to update the popper position
-   * @method
-   * @memberof Popper.Utils
-   * @private
-   */
-  function removeEventListeners(reference, state, options) {
-      // NOTE: 1 DOM access here
-      window.removeEventListener('resize', state.updateBound);
-      if (options.boundariesElement !== 'window') {
-          var target = getScrollParent(reference);
-          // here it could be both `body` or `documentElement` thanks to Firefox, we then check both
-          if (target === window.document.body || target === window.document.documentElement) {
-              target = window;
-          }
-          target.removeEventListener('scroll', state.updateBound);
-      }
-      state.updateBound = null;
-      return state;
-  }
+/**
+* Create a debounced version of a method, that's asynchronously deferred
+* but called in the minimum time possible.
+*
+* @method
+* @memberof Popper.Utils
+* @argument {Function} fn
+* @returns {Function}
+*/
+var debounce = supportsNativeMutationObserver ? microtaskDebounce : taskDebounce;
+
+/**
+ * Mimics the `find` method of Array
+ * @method
+ * @memberof Popper.Utils
+ * @argument {Array} arr
+ * @argument prop
+ * @argument value
+ * @returns index or -1
+ */
+function find(arr, check) {
+    // use native find if supported
+    if (Array.prototype.find) {
+        return arr.find(check);
+    }
 
-  /**
-   * Sorts the modifiers based on their `order` property
-   * @method
-   * @memberof Popper.Utils
-   */
-  function sortModifiers(a, b) {
-      if (a.order < b.order) {
-          return -1;
-      } else if (a.order > b.order) {
-          return 1;
-      }
-      return 0;
-  }
+    // use `filter` to obtain the same behavior of `find`
+    return arr.filter(check)[0];
+}
+
+/**
+ * Return the index of the matching object
+ * @method
+ * @memberof Popper.Utils
+ * @argument {Array} arr
+ * @argument prop
+ * @argument value
+ * @returns index or -1
+ */
+function findIndex(arr, prop, value) {
+    // use native findIndex if supported
+    if (Array.prototype.findIndex) {
+        return arr.findIndex(function (cur) {
+            return cur[prop] === value;
+        });
+    }
 
-  /**
-   * Apply the computed styles to the popper element
-   * @method
-   * @memberof Modifiers
-   * @argument {Object} data - The data object generated by `update` method
-   * @argument {Object} options - Modifiers configuration and options
-   * @returns {Object} The same data object
-   */
-  function applyStyle(data) {
-      // apply the final offsets to the popper
-      // NOTE: 1 DOM access here
-      var styles = {
-          position: data.offsets.popper.position
-      };
-
-      // round top and left to avoid blurry text
-      var left = Math.round(data.offsets.popper.left);
-      var top = Math.round(data.offsets.popper.top);
-
-      // if gpuAcceleration is set to true and transform is supported, we use `translate3d` to apply the position to the popper
-      // we automatically use the supported prefixed version if needed
-      var prefixedProperty = getSupportedPropertyName('transform');
-      if (data.instance.options.gpuAcceleration && prefixedProperty) {
-          styles[prefixedProperty] = 'translate3d(' + left + 'px, ' + top + 'px, 0)';
-          styles.top = 0;
-          styles.left = 0;
-      }
-      // othwerise, we use the standard `left` and `top` properties
-      else {
-              styles.left = left;
-              styles.top = top;
-          }
-
-      // any property present in `data.styles` will be applied to the popper,
-      // in this way we can make the 3rd party modifiers add custom styles to it
-      // Be aware, modifiers could override the properties defined in the previous
-      // lines of this modifier!
-      Object.assign(styles, data.styles);
-
-      setStyle(data.instance.popper, styles);
-
-      // set an attribute which will be useful to style the tooltip (use it to properly position its arrow)
-      // NOTE: 1 DOM access here
-      data.instance.popper.setAttribute('x-placement', data.placement);
-
-      // if the arrow style has been computed, apply the arrow style
-      if (data.offsets.arrow) {
-          setStyle(data.arrowElement, data.offsets.arrow);
-      }
+    // use `find` + `indexOf` if `findIndex` isn't supported
+    var match = find(arr, function (obj) {
+        return obj[prop] === value;
+    });
+    return arr.indexOf(match);
+}
 
-      return data;
+var classCallCheck = function (instance, Constructor) {
+  if (!(instance instanceof Constructor)) {
+    throw new TypeError("Cannot call a class as a function");
   }
-
-  /**
-   * Set the x-placement attribute before everything else because it could be used to add margins to the popper
-   * margins needs to be calculated to get the correct popper offsets
-   * @method
-   * @memberof Popper.modifiers
-   * @param {HTMLElement} reference - The reference element used to position the popper
-   * @param {HTMLElement} popper - The HTML element used as popper.
-   * @param {Object} options - Popper.js options
-   */
-  function applyStyleOnLoad(reference, popper, options) {
-      popper.setAttribute('x-placement', options.placement);
+};
+
+var createClass = function () {
+  function defineProperties(target, props) {
+    for (var i = 0; i < props.length; i++) {
+      var descriptor = props[i];
+      descriptor.enumerable = descriptor.enumerable || false;
+      descriptor.configurable = true;
+      if ("value" in descriptor) descriptor.writable = true;
+      Object.defineProperty(target, descriptor.key, descriptor);
+    }
   }
 
-  /**
-   * Modifier used to move the arrows on the edge of the popper to make sure them are always between the popper and the reference element
-   * It will use the CSS outer size of the arrow element to know how many pixels of conjuction are needed
-   * @method
-   * @memberof Modifiers
-   * @argument {Object} data - The data object generated by update method
-   * @argument {Object} options - Modifiers configuration and options
-   * @returns {Object} The data object, properly modified
-   */
-  function arrow(data, options) {
-      var arrow = options.element;
-
-      // if the arrowElement is a string, suppose it's a CSS selector
-      if (typeof arrow === 'string') {
-          arrow = data.instance.popper.querySelector(arrow);
-      }
+  return function (Constructor, protoProps, staticProps) {
+    if (protoProps) defineProperties(Constructor.prototype, protoProps);
+    if (staticProps) defineProperties(Constructor, staticProps);
+    return Constructor;
+  };
+}();
 
-      // if arrow element is not found, don't run the modifier
-      if (!arrow) {
-          return data;
-      }
 
-      // the arrow element must be child of its popper
-      if (!data.instance.popper.contains(arrow)) {
-          console.warn('WARNING: `arrowElement` must be child of its popper element!');
-          return data;
-      }
 
-      // arrow depends on keepTogether in order to work
-      if (!isModifierRequired(data.instance.modifiers, 'arrow', 'keepTogether')) {
-          console.warn('WARNING: keepTogether modifier is required by arrow modifier in order to work, be sure to include it before arrow!');
-          return data;
-      }
 
-      var arrowStyle = {};
-      var placement = data.placement.split('-')[0];
-      var popper = getPopperClientRect(data.offsets.popper);
-      var reference = data.offsets.reference;
-      var isVertical = ['left', 'right'].indexOf(placement) !== -1;
-
-      var len = isVertical ? 'height' : 'width';
-      var side = isVertical ? 'top' : 'left';
-      var altSide = isVertical ? 'left' : 'top';
-      var opSide = isVertical ? 'bottom' : 'right';
-      var arrowSize = getOuterSizes(arrow)[len];
-
-      //
-      // extends keepTogether behavior making sure the popper and its reference have enough pixels in conjuction
-      //
-
-      // top/left side
-      if (reference[opSide] - arrowSize < popper[side]) {
-          data.offsets.popper[side] -= popper[side] - (reference[opSide] - arrowSize);
-      }
-      // bottom/right side
-      if (reference[side] + arrowSize > popper[opSide]) {
-          data.offsets.popper[side] += reference[side] + arrowSize - popper[opSide];
+
+var defineProperty = function (obj, key, value) {
+  if (key in obj) {
+    Object.defineProperty(obj, key, {
+      value: value,
+      enumerable: true,
+      configurable: true,
+      writable: true
+    });
+  } else {
+    obj[key] = value;
+  }
+
+  return obj;
+};
+
+var _extends = Object.assign || function (target) {
+  for (var i = 1; i < arguments.length; i++) {
+    var source = arguments[i];
+
+    for (var key in source) {
+      if (Object.prototype.hasOwnProperty.call(source, key)) {
+        target[key] = source[key];
       }
+    }
+  }
 
-      // compute center of the popper
-      var center = reference[side] + reference[len] / 2 - arrowSize / 2;
+  return target;
+};
+
+/**
+ * Given the popper offsets, generate an output similar to getBoundingClientRect
+ * @method
+ * @memberof Popper.Utils
+ * @argument {Object} popperOffsets
+ * @returns {Object} ClientRect like output
+ */
+function getClientRect(popperOffsets) {
+    return _extends({}, popperOffsets, {
+        right: popperOffsets.left + popperOffsets.width,
+        bottom: popperOffsets.top + popperOffsets.height
+    });
+}
+
+/**
+ * Get the outer sizes of the given element (offset size + margins)
+ * @method
+ * @memberof Popper.Utils
+ * @argument {Element} element
+ * @returns {Object} object containing width and height properties
+ */
+function getOuterSizes(element) {
+    var styles = window.getComputedStyle(element);
+    var x = parseFloat(styles.marginTop) + parseFloat(styles.marginBottom);
+    var y = parseFloat(styles.marginLeft) + parseFloat(styles.marginRight);
+    var result = {
+        width: element.offsetWidth + y,
+        height: element.offsetHeight + x
+    };
+    return result;
+}
+
+/**
+ * Get the opposite placement of the given one/
+ * @method
+ * @memberof Popper.Utils
+ * @argument {String} placement
+ * @returns {String} flipped placement
+ */
+function getOppositePlacement(placement) {
+  var hash = { left: 'right', right: 'left', bottom: 'top', top: 'bottom' };
+  return placement.replace(/left|right|bottom|top/g, function (matched) {
+    return hash[matched];
+  });
+}
+
+/**
+ * Get offsets to the popper
+ * @method
+ * @memberof Popper.Utils
+ * @param {Object} position - CSS position the Popper will get applied
+ * @param {HTMLElement} popper - the popper element
+ * @param {Object} referenceOffsets - the reference offsets (the popper will be relative to this)
+ * @param {String} placement - one of the valid placement options
+ * @returns {Object} popperOffsets - An object containing the offsets which will be applied to the popper
+ */
+function getPopperOffsets(position, popper, referenceOffsets, placement) {
+    placement = placement.split('-')[0];
+
+    // Get popper node sizes
+    var popperRect = getOuterSizes(popper);
+
+    // Add position, width and height to our offsets object
+    var popperOffsets = {
+        position: position,
+        width: popperRect.width,
+        height: popperRect.height
+    };
 
-      // Compute the sideValue using the updated popper offsets
-      var sideValue = center - getPopperClientRect(data.offsets.popper)[side];
+    // depending by the popper placement we have to compute its offsets slightly differently
+    var isHoriz = ['right', 'left'].indexOf(placement) !== -1;
+    var mainSide = isHoriz ? 'top' : 'left';
+    var secondarySide = isHoriz ? 'left' : 'top';
+    var measurement = isHoriz ? 'height' : 'width';
+    var secondaryMeasurement = !isHoriz ? 'height' : 'width';
+
+    popperOffsets[mainSide] = referenceOffsets[mainSide] + referenceOffsets[measurement] / 2 - popperRect[measurement] / 2;
+    if (placement === secondarySide) {
+        popperOffsets[secondarySide] = referenceOffsets[secondarySide] - popperRect[secondaryMeasurement];
+    } else {
+        popperOffsets[secondarySide] = referenceOffsets[getOppositePlacement(secondarySide)];
+    }
 
-      // prevent arrow from being placed not contiguously to its popper
-      sideValue = Math.max(Math.min(popper[len] - arrowSize, sideValue), 0);
-      arrowStyle[side] = sideValue;
-      arrowStyle[altSide] = ''; // make sure to remove any old style from the arrow
+    return popperOffsets;
+}
+
+/**
+ * Get offsets to the reference element
+ * @method
+ * @memberof Popper.Utils
+ * @param {Object} state
+ * @param {Element} popper - the popper element
+ * @param {Element} reference - the reference element (the popper will be relative to this)
+ * @returns {Object} An object containing the offsets which will be applied to the popper
+ */
+function getReferenceOffsets(state, popper, reference) {
+  var isParentFixed = state.position === 'fixed';
+  var isParentTransformed = state.isParentTransformed;
+  var offsetParent = getOffsetParent(isParentFixed && isParentTransformed ? reference : popper);
+
+  return getOffsetRectRelativeToCustomParent(reference, offsetParent, isParentFixed, isParentTransformed);
+}
+
+/**
+ * Get the prefixed supported property name
+ * @method
+ * @memberof Popper.Utils
+ * @argument {String} property (camelCase)
+ * @returns {String} prefixed property (camelCase)
+ */
+function getSupportedPropertyName(property) {
+    var prefixes = [false, 'ms', 'webkit', 'moz', 'o'];
+    var upperProp = property.charAt(0).toUpperCase() + property.slice(1);
+
+    for (var i = 0; i < prefixes.length - 1; i++) {
+        var prefix = prefixes[i];
+        var toCheck = prefix ? '' + prefix + upperProp : property;
+        if (typeof window.document.body.style[toCheck] !== 'undefined') {
+            return toCheck;
+        }
+    }
+    return null;
+}
+
+/**
+ * Check if the given variable is a function
+ * @method
+ * @memberof Popper.Utils
+ * @argument {*} functionToCheck - variable to check
+ * @returns {Boolean} answer to: is a function?
+ */
+function isFunction(functionToCheck) {
+  var getType = {};
+  return functionToCheck && getType.toString.call(functionToCheck) === '[object Function]';
+}
+
+/**
+ * Helper used to know if the given modifier is enabled.
+ * @method
+ * @memberof Popper.Utils
+ * @returns {Boolean}
+ */
+function isModifierEnabled(modifiers, modifierName) {
+    return modifiers.some(function (_ref) {
+        var name = _ref.name,
+            enabled = _ref.enabled;
+        return enabled && name === modifierName;
+    });
+}
+
+/**
+ * Helper used to know if the given modifier depends from another one.
+ * It checks if the needed modifier is listed and enabled.
+ * @method
+ * @memberof Popper.Utils
+ * @param {Array} modifiers - list of modifiers
+ * @param {String} requestingName - name of requesting modifier
+ * @param {String} requestedName - name of requested modifier
+ * @returns {Boolean}
+ */
+function isModifierRequired(modifiers, requestingName, requestedName) {
+    var requesting = find(modifiers, function (_ref) {
+        var name = _ref.name;
+        return name === requestingName;
+    });
 
-      data.offsets.arrow = arrowStyle;
-      data.arrowElement = arrow;
+    return !!requesting && modifiers.some(function (modifier) {
+        return modifier.name === requestedName && modifier.enabled && modifier.order < requesting.order;
+    });
+}
+
+/**
+ * Tells if a given input is a number
+ * @method
+ * @memberof Popper.Utils
+ * @param {*} input to check
+ * @return {Boolean}
+ */
+function isNumeric(n) {
+  return n !== '' && !isNaN(parseFloat(n)) && isFinite(n);
+}
+
+/**
+ * Check if the given element has transforms applied to itself or a parent
+ * @method
+ * @memberof Popper.Utils
+ * @param  {Element} element
+ * @return {Boolean} answer to "isTransformed?"
+ */
+function isTransformed(element) {
+    if (element.nodeName === 'BODY') {
+        return false;
+    }
+    if (getStyleComputedProperty(element, 'transform') !== 'none') {
+        return true;
+    }
+    return getParentNode(element) ? isTransformed(getParentNode(element)) : element;
+}
+
+/**
+ * Remove event listeners used to update the popper position
+ * @method
+ * @memberof Popper.Utils
+ * @private
+ */
+function removeEventListeners(reference, state) {
+    // Remove resize event listener on window
+    window.removeEventListener('resize', state.updateBound);
+
+    // Remove scroll event listener on scroll parents
+    state.scrollParents.forEach(function (target) {
+        target.removeEventListener('scroll', state.updateBound);
+    });
 
-      return data;
-  }
+    // Reset state
+    state.updateBound = null;
+    state.scrollParents = [];
+    state.scrollElement = null;
+    state.eventsEnabled = false;
+    return state;
+}
+
+/**
+ * Loop trough the list of modifiers and run them in order, each of them will then edit the data object
+ * @method
+ * @memberof Popper.Utils
+ * @param {Object} data
+ * @param {Array} modifiers
+ * @param {Function} ends
+ */
+function runModifiers(modifiers, data, ends) {
+    var modifiersToRun = ends === undefined ? modifiers : modifiers.slice(0, findIndex(modifiers, 'name', ends));
+
+    modifiersToRun.forEach(function (modifier) {
+        if (modifier.enabled && isFunction(modifier.function)) {
+            data = modifier.function(data, modifier);
+        }
+    });
 
-  /**
-   * Get the opposite placement of the given one/
-   * @method
-   * @memberof Popper.Utils
-   * @argument {String} placement
-   * @returns {String} flipped placement
-   */
-  function getOppositePlacement(placement) {
-    var hash = { left: 'right', right: 'left', bottom: 'top', top: 'bottom' };
-    return placement.replace(/left|right|bottom|top/g, function (matched) {
-      return hash[matched];
+    return data;
+}
+
+/**
+ * Set the attributes to the given popper
+ * @method
+ * @memberof Popper.Utils
+ * @argument {Element} element - Element to apply the attributes to
+ * @argument {Object} styles - Object with a list of properties and values which will be applied to the element
+ */
+function setAttributes(element, attributes) {
+    Object.keys(attributes).forEach(function (prop) {
+        var value = attributes[prop];
+        if (value !== false) {
+            element.setAttribute(prop, attributes[prop]);
+        } else {
+            element.removeAttribute(prop);
+        }
     });
-  }
+}
+
+/**
+ * Set the style to the given popper
+ * @method
+ * @memberof Popper.Utils
+ * @argument {Element} element - Element to apply the style to
+ * @argument {Object} styles - Object with a list of properties and values which will be applied to the element
+ */
+function setStyles(element, styles) {
+    Object.keys(styles).forEach(function (prop) {
+        var unit = '';
+        // add unit if the value is numeric and is one of the following
+        if (['width', 'height', 'top', 'right', 'bottom', 'left'].indexOf(prop) !== -1 && isNumeric(styles[prop])) {
+            unit = 'px';
+        }
+        element.style[prop] = styles[prop] + unit;
+    });
+}
 
-  /**
-   * Get the opposite placement variation of the given one/
-   * @method
-   * @memberof Popper.Utils
-   * @argument {String} placement variation
-   * @returns {String} flipped placement variation
-   */
-  function getOppositeVariation(variation) {
-      if (variation === 'end') {
-          return 'start';
-      } else if (variation === 'start') {
-          return 'end';
-      }
-      return variation;
-  }
+function attachToScrollParents(scrollParent, event, callback, scrollParents) {
+    var isBody = scrollParent.nodeName === 'BODY';
+    var target = isBody ? window : scrollParent;
+    target.addEventListener(event, callback, { passive: true });
 
-  /**
-   * Modifier used to flip the placement of the popper when the latter is starting overlapping its reference element.
-   * Requires the `preventOverflow` modifier before it in order to work.
-   * **NOTE:** data.instance modifier will run all its previous modifiers everytime it tries to flip the popper!
-   * @method
-   * @memberof Modifiers
-   * @argument {Object} data - The data object generated by update method
-   * @argument {Object} options - Modifiers configuration and options
-   * @returns {Object} The data object, properly modified
-   */
-  function flip(data, options) {
-      // check if preventOverflow is in the list of modifiers before the flip modifier.
-      // otherwise flip would not work as expected.
-      if (!isModifierRequired(data.instance.modifiers, 'flip', 'preventOverflow')) {
-          console.warn('WARNING: preventOverflow modifier is required by flip modifier in order to work, be sure to include it before flip!');
-          return data;
-      }
+    if (!isBody) {
+        attachToScrollParents(getScrollParent(target.parentNode), event, callback, scrollParents);
+    }
+    scrollParents.push(target);
+}
+
+/**
+ * Setup needed event listeners used to update the popper position
+ * @method
+ * @memberof Popper.Utils
+ * @private
+ */
+function setupEventListeners(reference, options, state, updateBound) {
+    // Resize event listener on window
+    state.updateBound = updateBound;
+    window.addEventListener('resize', state.updateBound, { passive: true });
+
+    // Scroll event listener on scroll parents
+    var scrollElement = getScrollParent(reference);
+    attachToScrollParents(scrollElement, 'scroll', state.updateBound, state.scrollParents);
+    state.scrollElement = scrollElement;
+    state.eventsEnabled = true;
+
+    return state;
+}
+
+/** @namespace Popper.Utils */
+var Utils = {
+    computeAutoPlacement: computeAutoPlacement,
+    debounce: debounce,
+    findIndex: findIndex,
+    getBordersSize: getBordersSize,
+    getBoundaries: getBoundaries,
+    getBoundingClientRect: getBoundingClientRect,
+    getClientRect: getClientRect,
+    getOffsetParent: getOffsetParent,
+    getOffsetRect: getOffsetRect,
+    getOffsetRectRelativeToCustomParent: getOffsetRectRelativeToCustomParent,
+    getOuterSizes: getOuterSizes,
+    getParentNode: getParentNode,
+    getPopperOffsets: getPopperOffsets,
+    getPosition: getPosition,
+    getReferenceOffsets: getReferenceOffsets,
+    getScroll: getScroll,
+    getScrollParent: getScrollParent,
+    getStyleComputedProperty: getStyleComputedProperty,
+    getSupportedPropertyName: getSupportedPropertyName,
+    getTotalScroll: getTotalScroll,
+    getWindowSizes: getWindowSizes,
+    includeScroll: includeScroll,
+    isFixed: isFixed,
+    isFunction: isFunction,
+    isModifierEnabled: isModifierEnabled,
+    isModifierRequired: isModifierRequired,
+    isNative: isNative,
+    isNumeric: isNumeric,
+    isTransformed: isTransformed,
+    removeEventListeners: removeEventListeners,
+    runModifiers: runModifiers,
+    setAttributes: setAttributes,
+    setStyles: setStyles,
+    setupEventListeners: setupEventListeners
+};
+
+/**
+ * Apply the computed styles to the popper element
+ * @method
+ * @memberof Modifiers
+ * @argument {Object} data - The data object generated by `update` method
+ * @argument {Object} data.styles - List of style properties - values to apply to popper element
+ * @argument {Object} data.attributes - List of attribute properties - values to apply to popper element
+ * @argument {Object} options - Modifiers configuration and options
+ * @returns {Object} The same data object
+ */
+function applyStyle(data, options) {
+    // apply the final offsets to the popper
+    // NOTE: 1 DOM access here
+    var styles = {
+        position: data.offsets.popper.position
+    };
 
-      if (data.flipped && data.placement === data.originalPlacement) {
-          // seems like flip is trying to loop, probably there's not enough space on any of the flippable sides
-          return data;
-      }
+    var attributes = {
+        'x-placement': data.placement
+    };
 
-      var placement = data.placement.split('-')[0];
-      var placementOpposite = getOppositePlacement(placement);
-      var variation = data.placement.split('-')[1] || '';
+    // round top and left to avoid blurry text
+    var left = Math.round(data.offsets.popper.left);
+    var top = Math.round(data.offsets.popper.top);
+
+    // if gpuAcceleration is set to true and transform is supported,
+    //  we use `translate3d` to apply the position to the popper we
+    // automatically use the supported prefixed version if needed
+    var prefixedProperty = getSupportedPropertyName('transform');
+    if (options.gpuAcceleration && prefixedProperty) {
+        styles[prefixedProperty] = 'translate3d(' + left + 'px, ' + top + 'px, 0)';
+        styles.top = 0;
+        styles.left = 0;
+        styles.willChange = 'transform';
+    }
+    // othwerise, we use the standard `left` and `top` properties
+    else {
+            styles.left = left;
+            styles.top = top;
+            styles.willChange = 'top, left';
+        }
+
+    // any property present in `data.styles` will be applied to the popper,
+    // in this way we can make the 3rd party modifiers add custom styles to it
+    // Be aware, modifiers could override the properties defined in the previous
+    // lines of this modifier!
+    setStyles(data.instance.popper, _extends({}, styles, data.styles));
+
+    // any property present in `data.attributes` will be applied to the popper,
+    // they will be set as HTML attributes of the element
+    setAttributes(data.instance.popper, _extends({}, attributes, data.attributes));
+
+    // if the arrow style has been computed, apply the arrow style
+    if (data.offsets.arrow) {
+        setStyles(data.arrowElement, data.offsets.arrow);
+    }
 
-      var flipOrder = [];
+    return data;
+}
+
+/**
+ * Set the x-placement attribute before everything else because it could be used to add margins to the popper
+ * margins needs to be calculated to get the correct popper offsets
+ * @method
+ * @memberof Popper.modifiers
+ * @param {HTMLElement} reference - The reference element used to position the popper
+ * @param {HTMLElement} popper - The HTML element used as popper.
+ * @param {Object} options - Popper.js options
+ */
+function applyStyleOnLoad(reference, popper, options, modifierOptions, state) {
+    // compute reference element offsets
+    var referenceOffsets = getReferenceOffsets(state, popper, reference);
+
+    // compute auto placement, store placement inside the data object,
+    // modifiers will be able to edit `placement` if needed
+    // and refer to originalPlacement to know the original value
+    options.placement = computeAutoPlacement(options.placement, referenceOffsets, popper);
+
+    popper.setAttribute('x-placement', options.placement);
+    return options;
+}
+
+/**
+ * Modifier used to move the arrowElements on the edge of the popper to make sure them are always between the popper and the reference element
+ * It will use the CSS outer size of the arrowElement element to know how many pixels of conjuction are needed
+ * @method
+ * @memberof Modifiers
+ * @argument {Object} data - The data object generated by update method
+ * @argument {Object} options - Modifiers configuration and options
+ * @returns {Object} The data object, properly modified
+ */
+function arrow(data, options) {
+    // arrow depends on keepTogether in order to work
+    if (!isModifierRequired(data.instance.modifiers, 'arrow', 'keepTogether')) {
+        console.warn('WARNING: `keepTogether` modifier is required by arrow modifier in order to work, be sure to include it before `arrow`!');
+        return data;
+    }
 
-      if (options.behavior === 'flip') {
-          flipOrder = [placement, placementOpposite];
-      } else {
-          flipOrder = options.behavior;
-      }
+    var arrowElement = options.element;
+
+    // if arrowElement is a string, suppose it's a CSS selector
+    if (typeof arrowElement === 'string') {
+        arrowElement = data.instance.popper.querySelector(arrowElement);
+
+        // if arrowElement is not found, don't run the modifier
+        if (!arrowElement) {
+            return data;
+        }
+    } else {
+        // if the arrowElement isn't a query selector we must check that the
+        // provided DOM node is child of its popper node
+        if (!data.instance.popper.contains(arrowElement)) {
+            console.warn('WARNING: `arrow.element` must be child of its popper element!');
+            return data;
+        }
+    }
 
-      flipOrder.forEach(function (step, index) {
-          if (placement !== step || flipOrder.length === index + 1) {
-              return data;
-          }
+    var placement = data.placement.split('-')[0];
+    var popper = getClientRect(data.offsets.popper);
+    var reference = data.offsets.reference;
+    var isVertical = ['left', 'right'].indexOf(placement) !== -1;
 
-          placement = data.placement.split('-')[0];
-          placementOpposite = getOppositePlacement(placement);
+    var len = isVertical ? 'height' : 'width';
+    var side = isVertical ? 'top' : 'left';
+    var altSide = isVertical ? 'left' : 'top';
+    var opSide = isVertical ? 'bottom' : 'right';
+    var arrowElementSize = getOuterSizes(arrowElement)[len];
 
-          var popperOffsets = getPopperClientRect(data.offsets.popper);
+    //
+    // extends keepTogether behavior making sure the popper and its reference have enough pixels in conjuction
+    //
 
-          // this boolean is used to distinguish right and bottom from top and left
-          // they need different computations to get flipped
-          var a = ['right', 'bottom'].indexOf(placement) !== -1;
-          var b = ['top', 'bottom'].indexOf(placement) !== -1;
+    // top/left side
+    if (reference[opSide] - arrowElementSize < popper[side]) {
+        data.offsets.popper[side] -= popper[side] - (reference[opSide] - arrowElementSize);
+    }
+    // bottom/right side
+    if (reference[side] + arrowElementSize > popper[opSide]) {
+        data.offsets.popper[side] += reference[side] + arrowElementSize - popper[opSide];
+    }
 
-          // using Math.floor because the reference offsets may contain decimals we are not going to consider here
-          var flippedPosition = a && Math.floor(data.offsets.reference[placement]) > Math.floor(popperOffsets[placementOpposite]) || !a && Math.floor(data.offsets.reference[placement]) < Math.floor(popperOffsets[placementOpposite]);
+    // compute center of the popper
+    var center = reference[side] + reference[len] / 2 - arrowElementSize / 2;
+
+    // Compute the sideValue using the updated popper offsets
+    var sideValue = center - getClientRect(data.offsets.popper)[side];
+
+    // prevent arrowElement from being placed not contiguously to its popper
+    sideValue = Math.max(Math.min(popper[len] - arrowElementSize, sideValue), 0);
+
+    data.arrowElement = arrowElement;
+    data.offsets.arrow = {};
+    data.offsets.arrow[side] = sideValue;
+    data.offsets.arrow[altSide] = ''; // make sure to unset any eventual altSide value from the DOM node
+
+    return data;
+}
+
+/**
+ * Get the opposite placement variation of the given one/
+ * @method
+ * @memberof Popper.Utils
+ * @argument {String} placement variation
+ * @returns {String} flipped placement variation
+ */
+function getOppositeVariation(variation) {
+    if (variation === 'end') {
+        return 'start';
+    } else if (variation === 'start') {
+        return 'end';
+    }
+    return variation;
+}
+
+/**
+ * Modifier used to flip the placement of the popper when the latter is starting overlapping its reference element.
+ * Requires the `preventOverflow` modifier before it in order to work.
+ * **NOTE:** data.instance modifier will run all its previous modifiers everytime it tries to flip the popper!
+ * @method
+ * @memberof Modifiers
+ * @argument {Object} data - The data object generated by update method
+ * @argument {Object} options - Modifiers configuration and options
+ * @returns {Object} The data object, properly modified
+ */
+function flip(data, options) {
+    // if `inner` modifier is enabled, we can't use the `flip` modifier
+    if (isModifierEnabled(data.instance.modifiers, 'inner')) {
+        return data;
+    }
 
-          var flippedVariation = options.flipVariations && (b && variation === 'start' && Math.floor(popperOffsets.left) < Math.floor(data.boundaries.left) || b && variation === 'end' && Math.floor(popperOffsets.right) > Math.floor(data.boundaries.right) || !b && variation === 'start' && Math.floor(popperOffsets.top) < Math.floor(data.boundaries.top) || !b && variation === 'end' && Math.floor(popperOffsets.bottom) > Math.floor(data.boundaries.bottom));
+    if (data.flipped && data.placement === data.originalPlacement) {
+        // seems like flip is trying to loop, probably there's not enough space on any of the flippable sides
+        return data;
+    }
 
-          if (flippedPosition || flippedVariation) {
-              // this boolean to detect any flip loop
-              data.flipped = true;
+    var boundaries = getBoundaries(data.instance.popper, options.padding, options.boundariesElement);
 
-              if (flippedPosition) {
-                  placement = flipOrder[index + 1];
-              }
-              if (flippedVariation) {
-                  variation = getOppositeVariation(variation);
-              }
+    var placement = data.placement.split('-')[0];
+    var placementOpposite = getOppositePlacement(placement);
+    var variation = data.placement.split('-')[1] || '';
 
-              data.placement = placement + (variation ? '-' + variation : '');
-              data.offsets.popper = getOffsets(data.instance.state, data.instance.popper, data.instance.reference, data.placement).popper;
+    var flipOrder = [];
 
-              data = runModifiers(data.instance.modifiers, data.instance.options, data, 'flip');
-          }
-      });
-      return data;
-  }
+    if (options.behavior === 'flip') {
+        flipOrder = [placement, placementOpposite];
+    } else {
+        flipOrder = options.behavior;
+    }
 
-  /**
-   * Modifier used to make sure the popper is always near its reference element
-   * It cares only about the first axis, you can still have poppers with margin
-   * between the popper and its reference element.
-   * @method
-   * @memberof Modifiers
-   * @argument {Object} data - The data object generated by update method
-   * @argument {Object} options - Modifiers configuration and options
-   * @returns {Object} The data object, properly modified
-   */
-  function keepTogether(data) {
-      var popper = getPopperClientRect(data.offsets.popper);
-      var reference = data.offsets.reference;
-      var f = Math.floor;
-      var placement = data.placement.split('-')[0];
-
-      if (['top', 'bottom'].indexOf(placement) !== -1) {
-          if (popper.right < f(reference.left)) {
-              data.offsets.popper.left = f(reference.left) - popper.width;
-          }
-          if (popper.left > f(reference.right)) {
-              data.offsets.popper.left = f(reference.right);
-          }
-      } else {
-          if (popper.bottom < f(reference.top)) {
-              data.offsets.popper.top = f(reference.top) - popper.height;
-          }
-          if (popper.top > f(reference.bottom)) {
-              data.offsets.popper.top = f(reference.bottom);
-          }
-      }
+    flipOrder.forEach(function (step, index) {
+        if (placement !== step || flipOrder.length === index + 1) {
+            return data;
+        }
 
-      return data;
-  }
+        placement = data.placement.split('-')[0];
+        placementOpposite = getOppositePlacement(placement);
 
-  /**
-   * Modifier used to add an offset to the popper, useful if you more granularity positioning your popper.
-   * The offsets will shift the popper on the side of its reference element.
-   * @method
-   * @memberof Modifiers
-   * @argument {Object} data - The data object generated by update method
-   * @argument {Object} options - Modifiers configuration and options
-   * @argument {Number|String} options.offset=0
-   *      Basic usage allows a number used to nudge the popper by the given amount of pixels.
-   *      You can pass a percentage value as string (eg. `20%`) to nudge by the given percentage (relative to reference element size)
-   *      Other supported units are `vh` and `vw` (relative to viewport)
-   *      Additionally, you can pass a pair of values (eg. `10 20` or `2vh 20%`) to nudge the popper
-   *      on both axis.
-   *      A note about percentage values, if you want to refer a percentage to the popper size instead of the reference element size,
-   *      use `%p` instead of `%` (eg: `20%p`). To make it clearer, you can replace `%` with `%r` and use eg.`10%p 25%r`.
-   *      > **Heads up!** The order of the axis is relative to the popper placement: `bottom` or `top` are `X,Y`, the other are `Y,X`
-   * @returns {Object} The data object, properly modified
-   */
-  function offset(data, options) {
-      var placement = data.placement;
-      var popper = data.offsets.popper;
-
-      var offsets = void 0;
-      if (isNumeric(options.offset)) {
-          offsets = [options.offset, 0];
-      } else {
-          // split the offset in case we are providing a pair of offsets separated
-          // by a blank space
-          offsets = options.offset.split(' ');
-
-          // itherate through each offset to compute them in case they are percentages
-          offsets = offsets.map(function (offset, index) {
-              // separate value from unit
-              var split = offset.match(/(\d*\.?\d*)(.*)/);
-              var value = +split[1];
-              var unit = split[2];
-
-              // use height if placement is left or right and index is 0
-              // otherwise use height
-              // in this way the first offset will use an axis and the second one
-              // will use the other one
-              var useHeight = placement.indexOf('right') !== -1 || placement.indexOf('left') !== -1;
-
-              if (index === 1) {
-                  useHeight = !useHeight;
-              }
-
-              // if is a percentage, we calculate the value of it using as base the
-              // sizes of the reference element
-              if (unit === '%' || unit === '%r') {
-                  var referenceRect = getPopperClientRect(data.offsets.reference);
-                  var len = void 0;
-                  if (useHeight) {
-                      len = referenceRect.height;
-                  } else {
-                      len = referenceRect.width;
-                  }
-                  return len / 100 * value;
-              }
-              // if is a percentage relative to the popper, we calculate the value of it using
-              // as base the sizes of the popper
-              else if (unit === '%p') {
-                      var popperRect = getPopperClientRect(data.offsets.popper);
-                      var _len = void 0;
-                      if (useHeight) {
-                          _len = popperRect.height;
-                      } else {
-                          _len = popperRect.width;
-                      }
-                      return _len / 100 * value;
-                  }
-                  // if is a vh or vw, we calculate the size based on the viewport
-                  else if (unit === 'vh' || unit === 'vw') {
-                          var size = void 0;
-                          if (unit === 'vh') {
-                              size = Math.max(document.documentElement.clientHeight, window.innerHeight || 0);
-                          } else {
-                              size = Math.max(document.documentElement.clientWidth, window.innerWidth || 0);
-                          }
-                          return size / 100 * value;
-                      }
-                      // if is an explicit pixel unit, we get rid of the unit and keep the value
-                      else if (unit === 'px') {
-                              return +value;
-                          }
-                          // if is an implicit unit, it's px, and we return just the value
-                          else {
-                                  return +offset;
-                              }
-          });
-      }
+        var popperOffsets = getClientRect(data.offsets.popper);
+        var refOffsets = data.offsets.reference;
 
-      if (data.placement.indexOf('left') !== -1) {
-          popper.top += offsets[0];
-          popper.left -= offsets[1] || 0;
-      } else if (data.placement.indexOf('right') !== -1) {
-          popper.top += offsets[0];
-          popper.left += offsets[1] || 0;
-      } else if (data.placement.indexOf('top') !== -1) {
-          popper.left += offsets[0];
-          popper.top -= offsets[1] || 0;
-      } else if (data.placement.indexOf('bottom') !== -1) {
-          popper.left += offsets[0];
-          popper.top += offsets[1] || 0;
-      }
-      return data;
-  }
+        // using floor because the reference offsets may contain decimals we are not going to consider here
+        var floor = Math.floor;
+        var overlapsRef = placement === 'left' && floor(popperOffsets.right) > floor(refOffsets.left) || placement === 'right' && floor(popperOffsets.left) < floor(refOffsets.right) || placement === 'top' && floor(popperOffsets.bottom) > floor(refOffsets.top) || placement === 'bottom' && floor(popperOffsets.top) < floor(refOffsets.bottom);
 
-  /**
-   * Modifier used to make sure the popper does not overflows from it's boundaries
-   * @method
-   * @memberof Modifiers
-   * @argument {Object} data - The data object generated by `update` method
-   * @argument {Object} options - Modifiers configuration and options
-   * @returns {Object} The data object, properly modified
-   */
-  function preventOverflow(data, options) {
-      function shouldMoveWithTarget(direction) {
-          if (!options.moveWithTarget) {
-              return false;
-          }
-          var placement = data.originalPlacement.split('-')[0];
-
-          if (data.flipped && placement === direction || placement === getOppositePlacement(direction)) {
-              return true;
-          }
-          if (placement !== direction && placement !== getOppositePlacement(direction)) {
-              return true;
-          }
-
-          return false;
-      }
-      var order = options.priority;
-      var popper = getPopperClientRect(data.offsets.popper);
-
-      var check = {
-          left: function left() {
-              var left = popper.left;
-              if (popper.left < data.boundaries.left && !shouldMoveWithTarget('left')) {
-                  left = Math.max(popper.left, data.boundaries.left);
-              }
-              return { left: left };
-          },
-          right: function right() {
-              var left = popper.left;
-              if (popper.right > data.boundaries.right && !shouldMoveWithTarget('right')) {
-                  left = Math.min(popper.left, data.boundaries.right - popper.width);
-              }
-              return { left: left };
-          },
-          top: function top() {
-              var top = popper.top;
-              if (popper.top < data.boundaries.top && !shouldMoveWithTarget('top')) {
-                  top = Math.max(popper.top, data.boundaries.top);
-              }
-              return { top: top };
-          },
-          bottom: function bottom() {
-              var top = popper.top;
-              if (popper.bottom > data.boundaries.bottom && !shouldMoveWithTarget('bottom')) {
-                  top = Math.min(popper.top, data.boundaries.bottom - popper.height);
-              }
-              return { top: top };
-          }
-      };
-
-      order.forEach(function (direction) {
-          data.offsets.popper = Object.assign(popper, check[direction]());
-      });
-
-      return data;
-  }
+        var overflowsLeft = floor(popperOffsets.left) < floor(boundaries.left);
+        var overflowsRight = floor(popperOffsets.right) > floor(boundaries.right);
+        var overflowsTop = floor(popperOffsets.top) < floor(boundaries.top);
+        var overflowsBottom = floor(popperOffsets.bottom) > floor(boundaries.bottom);
 
-  /**
-   * Modifier used to shift the popper on the start or end of its reference element side
-   * @method
-   * @memberof Modifiers
-   * @argument {Object} data - The data object generated by `update` method
-   * @argument {Object} options - Modifiers configuration and options
-   * @returns {Object} The data object, properly modified
-   */
-  function shift(data) {
-      var placement = data.placement;
-      var basePlacement = placement.split('-')[0];
-      var shiftvariation = placement.split('-')[1];
-
-      // if shift shiftvariation is specified, run the modifier
-      if (shiftvariation) {
-          var reference = data.offsets.reference;
-          var popper = getPopperClientRect(data.offsets.popper);
-
-          var shiftOffsets = {
-              y: {
-                  start: { top: reference.top },
-                  end: { top: reference.top + reference.height - popper.height }
-              },
-              x: {
-                  start: { left: reference.left },
-                  end: { left: reference.left + reference.width - popper.width }
-              }
-          };
-
-          var axis = ['bottom', 'top'].indexOf(basePlacement) !== -1 ? 'x' : 'y';
-
-          data.offsets.popper = Object.assign(popper, shiftOffsets[axis][shiftvariation]);
-      }
+        var overflowsBoundaries = placement === 'left' && overflowsLeft || placement === 'right' && overflowsRight || placement === 'top' && overflowsTop || placement === 'bottom' && overflowsBottom;
 
-      return data;
-  }
+        // flip the variation if required
+        var isVertical = ['top', 'bottom'].indexOf(placement) !== -1;
+        var flippedVariation = !!options.flipVariations && (isVertical && variation === 'start' && overflowsLeft || isVertical && variation === 'end' && overflowsRight || !isVertical && variation === 'start' && overflowsTop || !isVertical && variation === 'end' && overflowsBottom);
 
-  /**
-   * Modifier used to hide the popper when its reference element is outside of the
-   * popper boundaries. It will set an x-hidden attribute which can be used to hide
-   * the popper when its reference is out of boundaries.
-   * @method
-   * @memberof Modifiers
-   * @argument {Object} data - The data object generated by update method
-   * @argument {Object} options - Modifiers configuration and options
-   * @returns {Object} The data object, properly modified
-   */
-  function hide(data) {
-      var refRect = data.offsets.reference;
-      var bound = data.boundaries;
-
-      if (refRect.bottom < bound.top || refRect.left > bound.right || refRect.top > bound.bottom || refRect.right < bound.left) {
-          data.hide = true;
-          data.instance.popper.setAttribute('x-out-of-boundaries', '');
-      } else {
-          data.hide = false;
-          data.instance.popper.removeAttribute('x-out-of-boundaries');
-      }
+        if (overlapsRef || overflowsBoundaries || flippedVariation) {
+            // this boolean to detect any flip loop
+            data.flipped = true;
 
-      return data;
-  }
+            if (overlapsRef || overflowsBoundaries) {
+                placement = flipOrder[index + 1];
+            }
 
-  /**
-   * Modifiers are plugins used to alter the behavior of your poppers.
-   * Popper.js uses a set of 7 modifiers to provide all the basic functionalities
-   * needed by the library.
-   *
-   * Each modifier is an object containing several properties listed below.
-   * @namespace Modifiers
-   * @param {Object} modifier - Modifier descriptor
-   * @param {Integer} modifier.order
-   *      The `order` property defines the execution order of the modifiers.
-   *      The built-in modifiers have orders with a gap of 100 units in between,
-   *      this allows you to inject additional modifiers between the existing ones
-   *      without having to redefine the order of all of them.
-   *      The modifiers are executed starting from the one with the lowest order.
-   * @param {Boolean} modifier.enabled - When `true`, the modifier will be used.
-   * @param {Modifiers~modifier} modifier.function - Modifier function.
-   * @param {Modifiers~onLoad} modifier.onLoad - Function executed on popper initalization
-   * @return {Object} data - Each modifier must return the modified `data` object.
-   */
-
-  var modifiersFunctions = {
-    applyStyle: applyStyle,
-    arrow: arrow,
-    flip: flip,
-    keepTogether: keepTogether,
-    offset: offset,
-    preventOverflow: preventOverflow,
-    shift: shift,
-    hide: hide
-  };
+            if (flippedVariation) {
+                variation = getOppositeVariation(variation);
+            }
 
-  var modifiersOnLoad = {
-    applyStyleOnLoad: applyStyleOnLoad
-  };
+            data.placement = placement + (variation ? '-' + variation : '');
+            data.offsets.popper = getPopperOffsets(data.instance.state.position, data.instance.popper, data.offsets.reference, data.placement);
 
-  /**
-   * Modifiers can edit the `data` object to change the beheavior of the popper.
-   * This object contains all the informations used by Popper.js to compute the
-   * popper position.
-   * The modifier can edit the data as needed, and then `return` it as result.
-   *
-   * @callback Modifiers~modifier
-   * @param {dataObject} data
-   * @return {dataObject} modified data
-   */
-
-  /**
-   * The `dataObject` is an object containing all the informations used by Popper.js
-   * this object get passed to modifiers and to the `onCreate` and `onUpdate` callbacks.
-   * @name dataObject
-   * @property {Object} data.instance The Popper.js instance
-   * @property {String} data.placement Placement applied to popper
-   * @property {String} data.originalPlacement Placement originally defined on init
-   * @property {Boolean} data.flipped True if popper has been flipped by flip modifier
-   * @property {Boolean} data.hide True if the reference element is out of boundaries, useful to know when to hide the popper.
-   * @property {HTMLElement} data.arrowElement Node used as arrow by arrow modifier
-   * @property {Object} data.styles Any CSS property defined here will be applied to the popper, it expects the JavaScript nomenclature (eg. `marginBottom`)
-   * @property {Object} data.boundaries Offsets of the popper boundaries
-   * @property {Object} data.offsets The measurements of popper, reference and arrow elements.
-   * @property {Object} data.offsets.popper `top`, `left`, `width`, `height` values
-   * @property {Object} data.offsets.reference `top`, `left`, `width`, `height` values
-   * @property {Object} data.offsets.arro] `top` and `left` offsets, only one of them will be different from 0
-   */
-
-  var classCallCheck = function (instance, Constructor) {
-    if (!(instance instanceof Constructor)) {
-      throw new TypeError("Cannot call a class as a function");
+            data = runModifiers(data.instance.modifiers, data, 'flip');
+        }
+    });
+    return data;
+}
+
+/**
+ * Modifier used to make sure the popper is always near its reference element
+ * It cares only about the first axis, you can still have poppers with margin
+ * between the popper and its reference element.
+ * @method
+ * @memberof Modifiers
+ * @argument {Object} data - The data object generated by update method
+ * @argument {Object} options - Modifiers configuration and options
+ * @returns {Object} The data object, properly modified
+ */
+function keepTogether(data) {
+    var popper = getClientRect(data.offsets.popper);
+    var reference = data.offsets.reference;
+    var placement = data.placement.split('-')[0];
+    var floor = Math.floor;
+    var isVertical = ['top', 'bottom'].indexOf(placement) !== -1;
+    var side = isVertical ? 'right' : 'bottom';
+    var opSide = isVertical ? 'left' : 'top';
+    var measurement = isVertical ? 'width' : 'height';
+
+    if (popper[side] < floor(reference[opSide])) {
+        data.offsets.popper[opSide] = floor(reference[opSide]) - popper[measurement];
+    }
+    if (popper[opSide] > floor(reference[side])) {
+        data.offsets.popper[opSide] = floor(reference[side]);
     }
-  };
 
-  var createClass = function () {
-    function defineProperties(target, props) {
-      for (var i = 0; i < props.length; i++) {
-        var descriptor = props[i];
-        descriptor.enumerable = descriptor.enumerable || false;
-        descriptor.configurable = true;
-        if ("value" in descriptor) descriptor.writable = true;
-        Object.defineProperty(target, descriptor.key, descriptor);
-      }
+    return data;
+}
+
+/**
+ * Modifier used to add an offset to the popper, useful if you more granularity positioning your popper.
+ * The offsets will shift the popper on the side of its reference element.
+ * @method
+ * @memberof Modifiers
+ * @argument {Object} data - The data object generated by update method
+ * @argument {Object} options - Modifiers configuration and options
+ * @argument {Number|String} options.offset=0
+ *      Basic usage allows a number used to nudge the popper by the given amount of pixels.
+ *      You can pass a percentage value as string (eg. `20%`) to nudge by the given percentage (relative to reference element size)
+ *      Other supported units are `vh` and `vw` (relative to viewport)
+ *      Additionally, you can pass a pair of values (eg. `10 20` or `2vh 20%`) to nudge the popper
+ *      on both axis.
+ *      A note about percentage values, if you want to refer a percentage to the popper size instead of the reference element size,
+ *      use `%p` instead of `%` (eg: `20%p`). To make it clearer, you can replace `%` with `%r` and use eg.`10%p 25%r`.
+ *      > **Heads up!** The order of the axis is relative to the popper placement: `bottom` or `top` are `X,Y`, the other are `Y,X`
+ * @returns {Object} The data object, properly modified
+ */
+function offset(data, options) {
+    var placement = data.placement;
+    var popper = data.offsets.popper;
+
+    var offsets = void 0;
+    if (isNumeric(options.offset)) {
+        offsets = [options.offset, 0];
+    } else {
+        // split the offset in case we are providing a pair of offsets separated
+        // by a blank space
+        offsets = options.offset.split(' ');
+
+        // itherate through each offset to compute them in case they are percentages
+        offsets = offsets.map(function (offset, index) {
+            // separate value from unit
+            var split = offset.match(/(\d*\.?\d*)(.*)/);
+            var value = +split[1];
+            var unit = split[2];
+
+            // use height if placement is left or right and index is 0 otherwise use width
+            // in this way the first offset will use an axis and the second one
+            // will use the other one
+            var useHeight = placement.indexOf('right') !== -1 || placement.indexOf('left') !== -1;
+
+            if (index === 1) {
+                useHeight = !useHeight;
+            }
+
+            var measurement = useHeight ? 'height' : 'width';
+
+            // if is a percentage relative to the popper (%p), we calculate the value of it using
+            // as base the sizes of the popper
+            // if is a percentage (% or %r), we calculate the value of it using as base the
+            // sizes of the reference element
+            if (unit.indexOf('%') === 0) {
+                var element = void 0;
+                switch (unit) {
+                    case '%p':
+                        element = data.offsets.popper;
+                        break;
+                    case '%':
+                    case '$r':
+                    default:
+                        element = data.offsets.reference;
+                }
+
+                var rect = getClientRect(element);
+                var len = rect[measurement];
+                return len / 100 * value;
+            }
+            // if is a vh or vw, we calculate the size based on the viewport
+            else if (unit === 'vh' || unit === 'vw') {
+                    var size = void 0;
+                    if (unit === 'vh') {
+                        size = Math.max(document.documentElement.clientHeight, window.innerHeight || 0);
+                    } else {
+                        size = Math.max(document.documentElement.clientWidth, window.innerWidth || 0);
+                    }
+                    return size / 100 * value;
+                }
+                // if is an explicit pixel unit, we get rid of the unit and keep the value
+                else if (unit === 'px') {
+                        return +value;
+                    }
+                    // if is an implicit unit, it's px, and we return just the value
+                    else {
+                            return +offset;
+                        }
+        });
     }
 
-    return function (Constructor, protoProps, staticProps) {
-      if (protoProps) defineProperties(Constructor.prototype, protoProps);
-      if (staticProps) defineProperties(Constructor, staticProps);
-      return Constructor;
+    if (data.placement.indexOf('left') !== -1) {
+        popper.top += offsets[0];
+        popper.left -= offsets[1] || 0;
+    } else if (data.placement.indexOf('right') !== -1) {
+        popper.top += offsets[0];
+        popper.left += offsets[1] || 0;
+    } else if (data.placement.indexOf('top') !== -1) {
+        popper.left += offsets[0];
+        popper.top -= offsets[1] || 0;
+    } else if (data.placement.indexOf('bottom') !== -1) {
+        popper.left += offsets[0];
+        popper.top += offsets[1] || 0;
+    }
+    return data;
+}
+
+/**
+ * Modifier used to prevent the popper from being positioned outside the boundary.
+ *
+ * An scenario exists where the reference itself is not within the boundaries. We can
+ * say it has "escaped the boundaries" — or just "escaped". In this case we need to
+ * decide whether the popper should either:
+ *
+ * - detach from the reference and remain "trapped" in the boundaries, or
+ * - if it should be ignore the boundary and "escape with the reference"
+ *
+ * When `escapeWithReference` is `true`, and reference is completely outside the
+ * boundaries, the popper will overflow (or completely leave) the boundaries in order
+ * to remain attached to the edge of the reference.
+ *
+ * @method
+ * @memberof Modifiers
+ * @argument {Object} data - The data object generated by `update` method
+ * @argument {Object} options - Modifiers configuration and options
+ * @returns {Object} The data object, properly modified
+ */
+function preventOverflow(data, options) {
+    var boundariesElement = options.boundariesElement || getOffsetParent(data.instance.popper);
+    var boundaries = getBoundaries(data.instance.popper, options.padding, boundariesElement);
+    options.boundaries = boundaries;
+
+    var order = options.priority;
+    var popper = getClientRect(data.offsets.popper);
+
+    var check = {
+        primary: function primary(placement) {
+            var value = popper[placement];
+            if (popper[placement] < boundaries[placement] && !options.escapeWithReference) {
+                value = Math.max(popper[placement], boundaries[placement]);
+            }
+            return defineProperty({}, placement, value);
+        },
+        secondary: function secondary(placement) {
+            var mainSide = placement === 'right' ? 'left' : 'top';
+            var value = popper[mainSide];
+            if (popper[placement] > boundaries[placement] && !options.escapeWithReference) {
+                value = Math.min(popper[mainSide], boundaries[placement] - (placement === 'right' ? popper.width : popper.height));
+            }
+            return defineProperty({}, mainSide, value);
+        }
     };
-  }();
-
-  // default options
-  var DEFAULTS = {
-      // placement of the popper
-      placement: 'bottom',
-
-      // if true, it uses the CSS 3d transformation to position the popper
-      gpuAcceleration: true,
-
-      // the element which will act as boundary of the popper
-      boundariesElement: 'viewport',
-
-      // amount of pixel used to define a minimum distance between the boundaries and the popper
-      boundariesPadding: 5,
-
-      // list of functions used to modify the offsets before they are applied to the popper
-      modifiers: {
-          shift: {
-              order: 100,
-              enabled: true,
-              function: modifiersFunctions.shift
-          },
-          offset: {
-              order: 200,
-              enabled: true,
-              function: modifiersFunctions.offset,
-              // nudges popper from its origin by the given amount of pixels (can be negative)
-              offset: 0
-          },
-          preventOverflow: {
-              order: 300,
-              enabled: true,
-              function: modifiersFunctions.preventOverflow,
-              // popper will try to prevent overflow following these priorities
-              //  by default, then, it could overflow on the left and on top of the boundariesElement
-              priority: ['left', 'right', 'top', 'bottom']
-          },
-          keepTogether: {
-              order: 400,
-              enabled: true,
-              function: modifiersFunctions.keepTogether
-          },
-          arrow: {
-              order: 500,
-              enabled: true,
-              function: modifiersFunctions.arrow,
-              // selector or node used as arrow
-              element: '[x-arrow]'
-          },
-          flip: {
-              order: 600,
-              enabled: true,
-              function: modifiersFunctions.flip,
-              // the behavior used to change the popper's placement
-              behavior: 'flip'
-          },
-          hide: {
-              order: 700,
-              enabled: true,
-              function: modifiersFunctions.hide
-          },
-          applyStyle: {
-              order: 800,
-              enabled: true,
-              function: modifiersFunctions.applyStyle,
-              onLoad: modifiersOnLoad.applyStyleOnLoad
-          }
-      }
-  };
 
-  /**
-   * Create a new Popper.js instance
-   * @class Popper
-   * @param {HTMLElement} reference - The reference element used to position the popper
-   * @param {HTMLElement} popper - The HTML element used as popper.
-   * @param {Object} options
-   * @param {String} options.placement=bottom
-   *      Placement of the popper accepted values: `top(-start, -end), right(-start, -end), bottom(-start, -right),
-   *      left(-start, -end)`
-   *
-   * @param {Boolean} options.gpuAcceleration=true
-   *      When this property is set to true, the popper position will be applied using CSS3 translate3d, allowing the
-   *      browser to use the GPU to accelerate the rendering.
-   *      If set to false, the popper will be placed using `top` and `left` properties, not using the GPU.
-   *
-   * @param {String|Element} options.boundariesElement='viewport'
-   *      The element which will define the boundaries of the popper position, the popper will never be placed outside
-   *      of the defined boundaries (except if `keepTogether` is enabled)
-   *
-   * @param {Number} options.boundariesPadding=5
-   *      Additional padding for the boundaries
-   *
-   * @param {Boolean} options.removeOnDestroy=false
-   *      Set to true if you want to automatically remove the popper when you call the `destroy` method.
-   *
-   * @param {Object} options.modifiers
-   *      List of functions used to modify the data before they are applied to the popper (see source code for default values)
-   *
-   * @param {Object} options.modifiers.arrow - Arrow modifier configuration
-   * @param {HTMLElement|String} options.modifiers.arrow.element='[x-arrow]'
-   *      The DOM Node used as arrow for the popper, or a CSS selector used to get the DOM node. It must be child of
-   *      its parent Popper. Popper.js will apply to the given element the style required to align the arrow with its
-   *      reference element.
-   *      By default, it will look for a child node of the popper with the `x-arrow` attribute.
-   *
-   * @param {Object} options.modifiers.offset - Offset modifier configuration
-   * @param {Number} options.modifiers.offset.offset=0
-   *      Amount of pixels the popper will be shifted (can be negative).
-   *
-   * @param {Object} options.modifiers.preventOverflow - PreventOverflow modifier configuration
-   * @param {Array} [options.modifiers.preventOverflow.priority=['left', 'right', 'top', 'bottom']]
-   *      Priority used when Popper.js tries to avoid overflows from the boundaries, they will be checked in order,
-   *      this means that the last one will never overflow
-   *
-   * @param {Object} options.modifiers.flip - Flip modifier configuration
-   * @param {String|Array} options.modifiers.flip.behavior='flip'
-   *      The behavior used by the `flip` modifier to change the placement of the popper when the latter is trying to
-   *      overlap its reference element. Defining `flip` as value, the placement will be flipped on
-   *      its axis (`right - left`, `top - bottom`).
-   *      You can even pass an array of placements (eg: `['right', 'left', 'top']` ) to manually specify
-   *      how alter the placement when a flip is needed. (eg. in the above example, it would first flip from right to left,
-   *      then, if even in its new placement, the popper is overlapping its reference element, it will be moved to top)
-   *
-   * @return {Object} instance - The generated Popper.js instance
-   */
-
-  var Popper = function () {
-      function Popper(reference, popper) {
-          var _this = this;
-
-          var options = arguments.length <= 2 || arguments[2] === undefined ? {} : arguments[2];
-          classCallCheck(this, Popper);
-          this.Defaults = DEFAULTS;
-
-          // init state
-          this.state = {
-              isDestroyed: false
-          };
-
-          // get reference and popper elements (allow jQuery wrappers)
-          this.reference = reference.jquery ? reference[0] : reference;
-          this.popper = popper.jquery ? popper[0] : popper;
-
-          // with {} we create a new object with the options inside it
-          this.options = Object.assign({}, DEFAULTS, options);
-
-          // refactoring modifiers' list (Object => Array)
-          this.modifiers = Object.keys(DEFAULTS.modifiers).map(function (name) {
-              return Object.assign({ name: name }, DEFAULTS.modifiers[name]);
-          });
-
-          // assign default values to modifiers, making sure to override them with
-          // the ones defined by user
-          this.modifiers = this.modifiers.map(function (defaultConfig) {
-              var userConfig = options.modifiers && options.modifiers[defaultConfig.name] || {};
-              var finalConfig = Object.assign({}, defaultConfig, userConfig);
-              return finalConfig;
-          });
-
-          // add custom modifiers to the modifiers list
-          if (options.modifiers) {
-              Object.keys(options.modifiers).forEach(function (name) {
-                  // take in account only custom modifiers
-                  if (DEFAULTS.modifiers[name] === undefined) {
-                      var modifier = options.modifiers[name];
-                      modifier.name = name;
-                      _this.modifiers.push(modifier);
-                  }
-              });
-          }
-
-          // sort the modifiers by order
-          this.modifiers = this.modifiers.sort(sortModifiers);
-
-          // modifiers have the ability to execute arbitrary code when Popper.js get inited
-          // such code is executed in the same order of its modifier
-          this.modifiers.forEach(function (modifier) {
-              if (modifier.enabled && isFunction(modifier.onLoad)) {
-                  modifier.onLoad(_this.reference, _this.popper, _this.options);
-              }
-          });
-
-          // get the popper position type
-          this.state.position = getPosition(this.popper, this.reference);
-
-          // determine how we should set the origin of offsets
-          this.state.isParentTransformed = isTransformed(this.popper.parentNode);
-
-          // fire the first update to position the popper in the right place
-          this.update(true);
-
-          // setup event listeners, they will take care of update the position in specific situations
-          setupEventListeners(this.reference, this.options, this.state, function () {
-              return _this.update();
-          });
-
-          // make it chainable
-          return this;
-      }
+    order.forEach(function (placement) {
+        var side = ['left', 'top'].indexOf(placement) !== -1 ? 'primary' : 'secondary';
+        popper = _extends({}, popper, check[side](placement));
+    });
+
+    data.offsets.popper = popper;
+
+    return data;
+}
+
+/**
+ * Modifier used to shift the popper on the start or end of its reference element side
+ * @method
+ * @memberof Modifiers
+ * @argument {Object} data - The data object generated by `update` method
+ * @argument {Object} options - Modifiers configuration and options
+ * @returns {Object} The data object, properly modified
+ */
+function shift(data) {
+    var placement = data.placement;
+    var basePlacement = placement.split('-')[0];
+    var shiftvariation = placement.split('-')[1];
+
+    // if shift shiftvariation is specified, run the modifier
+    if (shiftvariation) {
+        var reference = data.offsets.reference;
+        var popper = getClientRect(data.offsets.popper);
+        var isVertical = ['bottom', 'top'].indexOf(basePlacement) !== -1;
+        var side = isVertical ? 'left' : 'top';
+        var measurement = isVertical ? 'width' : 'height';
+
+        var shiftOffsets = {
+            start: defineProperty({}, side, reference[side]),
+            end: defineProperty({}, side, reference[side] + reference[measurement] - popper[measurement])
+        };
+
+        data.offsets.popper = _extends({}, popper, shiftOffsets[shiftvariation]);
+    }
+
+    return data;
+}
+
+/**
+ * Modifier used to hide the popper when its reference element is outside of the
+ * popper boundaries. It will set an x-hidden attribute which can be used to hide
+ * the popper when its reference is out of boundaries.
+ * @method
+ * @memberof Modifiers
+ * @argument {Object} data - The data object generated by update method
+ * @argument {Object} options - Modifiers configuration and options
+ * @returns {Object} The data object, properly modified
+ */
+function hide(data) {
+    if (!isModifierRequired(data.instance.modifiers, 'hide', 'preventOverflow')) {
+        console.warn('WARNING: preventOverflow modifier is required by hide modifier in order to work, be sure to include it before hide!');
+        return data;
+    }
+
+    var refRect = data.offsets.reference;
+    var bound = find(data.instance.modifiers, function (modifier) {
+        return modifier.name === 'preventOverflow';
+    }).boundaries;
+
+    if (refRect.bottom < bound.top || refRect.left > bound.right || refRect.top > bound.bottom || refRect.right < bound.left) {
+        // Avoid unnecessary DOM access if visibility hasn't changed
+        if (data.hide === true) {
+            return data;
+        }
+
+        data.hide = true;
+        data.attributes['x-out-of-boundaries'] = '';
+    } else {
+        // Avoid unnecessary DOM access if visibility hasn't changed
+        if (data.hide === false) {
+            return data;
+        }
+
+        data.hide = false;
+        data.attributes['x-out-of-boundaries'] = false;
+    }
+
+    return data;
+}
+
+/**
+ * Modifier used to make the popper flow toward the inner of the reference element.
+ * By default, when this modifier is disabled, the popper will be placed outside
+ * the reference element.
+ * @method
+ * @memberof Modifiers
+ * @argument {Object} data - The data object generated by `update` method
+ * @argument {Object} options - Modifiers configuration and options
+ * @returns {Object} The data object, properly modified
+ */
+function inner(data) {
+    var placement = data.placement;
+    var basePlacement = placement.split('-')[0];
+    var popper = getClientRect(data.offsets.popper);
+    var reference = getClientRect(data.offsets.reference);
+    var isHoriz = ['left', 'right'].indexOf(basePlacement) !== -1;
+
+    var subtractLength = ['top', 'left'].indexOf(basePlacement) === -1;
+
+    popper[isHoriz ? 'left' : 'top'] = reference[placement] - (subtractLength ? popper[isHoriz ? 'width' : 'height'] : 0);
+
+    data.placement = getOppositePlacement(placement);
+    data.offsets.popper = getClientRect(popper);
+
+    return data;
+}
+
+/**
+ * Modifiers are plugins used to alter the behavior of your poppers.
+ * Popper.js uses a set of 7 modifiers to provide all the basic functionalities
+ * needed by the library.
+ *
+ * Each modifier is an object containing several properties listed below.
+ * @namespace Modifiers
+ * @param {Object} modifier - Modifier descriptor
+ * @param {Integer} modifier.order
+ *      The `order` property defines the execution order of the modifiers.
+ *      The built-in modifiers have orders with a gap of 100 units in between,
+ *      this allows you to inject additional modifiers between the existing ones
+ *      without having to redefine the order of all of them.
+ *      The modifiers are executed starting from the one with the lowest order.
+ * @param {Boolean} modifier.enabled - When `true`, the modifier will be used.
+ * @param {Modifiers~modifier} modifier.function - Modifier function.
+ * @param {Modifiers~onLoad} modifier.onLoad - Function executed on popper initalization
+ * @return {Object} data - Each modifier must return the modified `data` object.
+ */
+var modifiers = {
+  shift: {
+    order: 100,
+    enabled: true,
+    function: shift
+  },
+  offset: {
+    order: 200,
+    enabled: true,
+    function: offset,
+    // nudges popper from its origin by the given amount of pixels (can be negative)
+    offset: 0
+  },
+  preventOverflow: {
+    order: 300,
+    enabled: true,
+    function: preventOverflow,
+    // popper will try to prevent overflow following these priorities
+    //  by default, then, it could overflow on the left and on top of the boundariesElement
+    priority: ['left', 'right', 'top', 'bottom'],
+    // amount of pixel used to define a minimum distance between the boundaries and the popper
+    // this makes sure the popper has always a little padding between the edges of its container
+    padding: 5,
+    boundariesElement: 'scrollParent'
+  },
+  keepTogether: {
+    order: 400,
+    enabled: true,
+    function: keepTogether
+  },
+  arrow: {
+    order: 500,
+    enabled: true,
+    function: arrow,
+    // selector or node used as arrow
+    element: '[x-arrow]'
+  },
+  flip: {
+    order: 600,
+    enabled: true,
+    function: flip,
+    // the behavior used to change the popper's placement
+    behavior: 'flip',
+    // the popper will flip if it hits the edges of the boundariesElement - padding
+    padding: 5,
+    boundariesElement: 'viewport'
+  },
+  inner: {
+    order: 700,
+    enabled: false,
+    function: inner
+  },
+  hide: {
+    order: 800,
+    enabled: true,
+    function: hide
+  },
+  applyStyle: {
+    order: 900,
+    enabled: true,
+    // if true, it uses the CSS 3d transformation to position the popper
+    gpuAcceleration: true,
+    function: applyStyle,
+    onLoad: applyStyleOnLoad
+  }
+};
+
+/**
+ * Modifiers can edit the `data` object to change the beheavior of the popper.
+ * This object contains all the informations used by Popper.js to compute the
+ * popper position.
+ * The modifier can edit the data as needed, and then `return` it as result.
+ *
+ * @callback Modifiers~modifier
+ * @param {dataObject} data
+ * @return {dataObject} modified data
+ */
+
+/**
+ * The `dataObject` is an object containing all the informations used by Popper.js
+ * this object get passed to modifiers and to the `onCreate` and `onUpdate` callbacks.
+ * @name dataObject
+ * @property {Object} data.instance The Popper.js instance
+ * @property {String} data.placement Placement applied to popper
+ * @property {String} data.originalPlacement Placement originally defined on init
+ * @property {Boolean} data.flipped True if popper has been flipped by flip modifier
+ * @property {Boolean} data.hide True if the reference element is out of boundaries, useful to know when to hide the popper.
+ * @property {HTMLElement} data.arrowElement Node used as arrow by arrow modifier
+ * @property {Object} data.styles Any CSS property defined here will be applied to the popper, it expects the JavaScript nomenclature (eg. `marginBottom`)
+ * @property {Object} data.boundaries Offsets of the popper boundaries
+ * @property {Object} data.offsets The measurements of popper, reference and arrow elements.
+ * @property {Object} data.offsets.popper `top`, `left`, `width`, `height` values
+ * @property {Object} data.offsets.reference `top`, `left`, `width`, `height` values
+ * @property {Object} data.offsets.arro] `top` and `left` offsets, only one of them will be different from 0
+ */
+
+// Utils
+// Modifiers
+// default options
+var DEFAULTS = {
+    // placement of the popper
+    placement: 'bottom',
+
+    // whether events (resize, scroll) are initially enabled
+    eventsEnabled: true,
+
+    /**
+     * Callback called when the popper is created.
+     * By default, is set to no-op.
+     * Access Popper.js instance with `data.instance`.
+     * @callback createCallback
+     * @static
+     * @param {dataObject} data
+     */
+    onCreate: function onCreate() {},
+
+    /**
+     * Callback called when the popper is updated, this callback is not called
+     * on the initialization/creation of the popper, but only on subsequent
+     * updates.
+     * By default, is set to no-op.
+     * Access Popper.js instance with `data.instance`.
+     * @callback updateCallback
+     * @static
+     * @param {dataObject} data
+     */
+    onUpdate: function onUpdate() {},
+
+    // list of functions used to modify the offsets before they are applied to the popper
+    modifiers: modifiers
+};
+
+/**
+ * Create a new Popper.js instance
+ * @class Popper
+ * @param {HTMLElement} reference - The reference element used to position the popper
+ * @param {HTMLElement} popper - The HTML element used as popper.
+ * @param {Object} options
+ * @param {String} options.placement=bottom
+ *      Placement of the popper accepted values: `top(-start, -end), right(-start, -end), bottom(-start, -end),
+ *      left(-start, -end)`
+ *
+ * @param {Boolean} options.eventsEnabled=true
+ *      Whether events (resize, scroll) are initially enabled
+ * @param {Boolean} options.gpuAcceleration=true
+ *      When this property is set to true, the popper position will be applied using CSS3 translate3d, allowing the
+ *      browser to use the GPU to accelerate the rendering.
+ *      If set to false, the popper will be placed using `top` and `left` properties, not using the GPU.
+ *
+ * @param {Boolean} options.removeOnDestroy=false
+ *      Set to true if you want to automatically remove the popper when you call the `destroy` method.
+ *
+ * @param {Object} options.modifiers
+ *      List of functions used to modify the data before they are applied to the popper (see source code for default values)
+ *
+ * @param {Object} options.modifiers.arrow - Arrow modifier configuration
+ * @param {String|HTMLElement} options.modifiers.arrow.element='[x-arrow]'
+ *      The DOM Node used as arrow for the popper, or a CSS selector used to get the DOM node. It must be child of
+ *      its parent Popper. Popper.js will apply to the given element the style required to align the arrow with its
+ *      reference element.
+ *      By default, it will look for a child node of the popper with the `x-arrow` attribute.
+ *
+ * @param {Object} options.modifiers.offset - Offset modifier configuration
+ * @param {Number} options.modifiers.offset.offset=0
+ *      Amount of pixels the popper will be shifted (can be negative).
+ *
+ * @param {Object} options.modifiers.preventOverflow - PreventOverflow modifier configuration
+ * @param {Array} [options.modifiers.preventOverflow.priority=['left', 'right', 'top', 'bottom']]
+ *      Priority used when Popper.js tries to avoid overflows from the boundaries, they will be checked in order,
+ *      this means that the last one will never overflow
+ * @param {String|HTMLElement} options.modifiers.preventOverflow.boundariesElement='scrollParent'
+ *      Boundaries used by the modifier, can be `scrollParent`, `window`, `viewport` or any DOM element.
+ * @param {Number} options.modifiers.preventOverflow.padding=5
+ *      Amount of pixel used to define a minimum distance between the boundaries and the popper
+ *      this makes sure the popper has always a little padding between the edges of its container.
+ *
+ * @param {Object} options.modifiers.flip - Flip modifier configuration
+ * @param {String|Array} options.modifiers.flip.behavior='flip'
+ *      The behavior used by the `flip` modifier to change the placement of the popper when the latter is trying to
+ *      overlap its reference element. Defining `flip` as value, the placement will be flipped on
+ *      its axis (`right - left`, `top - bottom`).
+ *      You can even pass an array of placements (eg: `['right', 'left', 'top']` ) to manually specify
+ *      how alter the placement when a flip is needed. (eg. in the above example, it would first flip from right to left,
+ *      then, if even in its new placement, the popper is overlapping its reference element, it will be moved to top)
+ * @param {String|HTMLElement} options.modifiers.flip.boundariesElement='viewport'
+ *      The element which will define the boundaries of the popper position, the popper will never be placed outside
+ *      of the defined boundaries (except if `keepTogether` is enabled)
+ *
+ * @param {Object} options.modifiers.inner - Inner modifier configuration
+ * @param {Number} options.modifiers.inner.enabled=false
+ *      Set to `true` to make the popper flow toward the inner of the reference element.
+ *
+ * @param {Number} options.modifiers.flip.padding=5
+ *      Amount of pixel used to define a minimum distance between the boundaries and the popper
+ *      this makes sure the popper has always a little padding between the edges of its container.
+ *
+ * @param {createCallback} options.onCreate - onCreate callback
+ *      Function called after the Popper has been instantiated.
+ *
+ * @param {updateCallback} options.onUpdate - onUpdate callback
+ *      Function called on subsequent updates of Popper.
+ *
+ * @return {Object} instance - The generated Popper.js instance
+ */
+
+var Popper = function () {
+    function Popper(reference, popper) {
+        var _this = this;
+
+        var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
+        classCallCheck(this, Popper);
+
+        this.scheduleUpdate = function () {
+            return requestAnimationFrame(_this.update);
+        };
+
+        // make update() debounced, so that it only runs at most once-per-tick
+        this.update = debounce(this.update.bind(this));
+
+        // with {} we create a new object with the options inside it
+        this.options = _extends({}, Popper.Defaults, options);
+
+        // init state
+        this.state = {
+            isDestroyed: false,
+            isCreated: false,
+            scrollParents: []
+        };
+
+        // get reference and popper elements (allow jQuery wrappers)
+        this.reference = reference.jquery ? reference[0] : reference;
+        this.popper = popper.jquery ? popper[0] : popper;
+
+        // refactoring modifiers' list (Object => Array)
+        this.modifiers = Object.keys(Popper.Defaults.modifiers).map(function (name) {
+            return _extends({ name: name }, Popper.Defaults.modifiers[name]);
+        });
+
+        // assign default values to modifiers, making sure to override them with
+        // the ones defined by user
+        this.modifiers = this.modifiers.map(function (defaultConfig) {
+            var userConfig = options.modifiers && options.modifiers[defaultConfig.name] || {};
+            return _extends({}, defaultConfig, userConfig);
+        });
+
+        // add custom modifiers to the modifiers list
+        if (options.modifiers) {
+            this.options.modifiers = _extends({}, Popper.Defaults.modifiers, options.modifiers);
+            Object.keys(options.modifiers).forEach(function (name) {
+                // take in account only custom modifiers
+                if (Popper.Defaults.modifiers[name] === undefined) {
+                    var modifier = options.modifiers[name];
+                    modifier.name = name;
+                    _this.modifiers.push(modifier);
+                }
+            });
+        }
+
+        // get the popper position type
+        this.state.position = getPosition(this.reference);
+
+        // sort the modifiers by order
+        this.modifiers = this.modifiers.sort(function (a, b) {
+            return a.order - b.order;
+        });
+
+        // modifiers have the ability to execute arbitrary code when Popper.js get inited
+        // such code is executed in the same order of its modifier
+        // they could add new properties to their options configuration
+        // BE AWARE: don't add options to `options.modifiers.name` but to `modifierOptions`!
+        this.modifiers.forEach(function (modifierOptions) {
+            if (modifierOptions.enabled && isFunction(modifierOptions.onLoad)) {
+                modifierOptions.onLoad(_this.reference, _this.popper, _this.options, modifierOptions, _this.state);
+            }
+        });
+
+        // determine how we should set the origin of offsets
+        this.state.isParentTransformed = isTransformed(this.popper.parentNode);
+
+        // fire the first update to position the popper in the right place
+        this.update();
+
+        var eventsEnabled = this.options.eventsEnabled;
+        if (eventsEnabled) {
+            // setup event listeners, they will take care of update the position in specific situations
+            this.enableEventListeners();
+        }
+
+        this.state.eventsEnabled = eventsEnabled;
+    }
 
-      //
-      // Methods
-      //
-
-      /**
-       * Updates the position of the popper, computing the new offsets and applying the new style
-       * @method
-       * @param {Boolean} isFirstCall
-       *      When true, the onCreate callback is called, otherwise it calls the onUpdate callback
-       * @memberof Popper
-       */
-
-
-      createClass(Popper, [{
-          key: 'update',
-          value: function update(isFirstCall) {
-              var _this2 = this;
-
-              var data = { instance: this, styles: {} };
-
-              // make sure to apply the popper position before any computation
-              this.state.position = getPosition(this.popper, this.reference);
-              setStyle(this.popper, { position: this.state.position });
-
-              // to avoid useless computations we throttle the popper position refresh to 60fps
-              window.requestAnimationFrame(function () {
-                  // if popper is destroyed, don't perform any further update
-                  if (_this2.state.isDestroyed) {
-                      return;
-                  }
-
-                  var now = window.performance.now();
-                  if (now - _this2.state.lastFrame <= 16) {
-                      // this update fired to early! drop it
-                      // but schedule a new one that will be ran at the end of the updates
-                      // chain to make sure everything is proper updated
-                      return _this2.update();
-                  }
-                  _this2.state.lastFrame = now;
-
-                  // store placement inside the data object, modifiers will be able to edit `placement` if needed
-                  // and refer to originalPlacement to know the original value
-                  data.placement = _this2.options.placement;
-                  data.originalPlacement = _this2.options.placement;
-
-                  // compute the popper and reference offsets and put them inside data.offsets
-                  data.offsets = getOffsets(_this2.state, _this2.popper, _this2.reference, data.placement);
-
-                  // get boundaries
-                  data.boundaries = getBoundaries(_this2.popper, data, _this2.options.boundariesPadding, _this2.options.boundariesElement);
-
-                  // run the modifiers
-                  data = runModifiers(_this2.modifiers, _this2.options, data);
-
-                  // the first `update` will call `onCreate` callback
-                  // the other ones will call `onUpdate` callback
-                  if (isFirstCall && isFunction(_this2.state.createCalback)) {
-                      _this2.state.createCalback(data);
-                  } else if (!isFirstCall && isFunction(_this2.state.updateCallback)) {
-                      _this2.state.updateCallback(data);
-                  }
-              });
-          }
-
-          /**
-           * If a function is passed, it will be executed after the initialization of popper with as first argument the Popper instance.
-           * @method
-           * @memberof Popper
-           * @param {createCallback} callback
-           */
-
-      }, {
-          key: 'onCreate',
-          value: function onCreate(callback) {
-              // the createCallbacks return as first argument the popper instance
-              this.state.createCalback = callback;
-              return this;
-          }
-
-          /**
-           * Callback called when the popper is created.
-           * Access Popper.js instance with `data.instance`.
-           * @callback createCallback
-           * @static
-           * @param {dataObject} data
-           */
-
-          /**
-           * If a function is passed, it will be executed after each update of popper with as first argument the set of coordinates and informations
-           * used to style popper and its arrow.
-           * NOTE: it doesn't get fired on the first call of the `Popper.update()` method inside the `Popper` constructor!
-           * @method
-           * @memberof Popper
-           * @param {updateCallback} callback
-           */
-
-      }, {
-          key: 'onUpdate',
-          value: function onUpdate(callback) {
-              this.state.updateCallback = callback;
-              return this;
-          }
-
-          /**
-           * Callback called when the popper is updated, this callback is not called
-           * on the initialization/creation of the popper, but only on subsequent
-           * updates.
-           * Access Popper.js instance with `data.instance`.
-           * @callback updateCallback
-           * @static
-           * @param {dataObject} data
-           */
-
-          /**
-           * Destroy the popper
-           * @method
-           * @memberof Popper
-           */
-
-      }, {
-          key: 'destroy',
-          value: function destroy() {
-              this.state.isDestroyed = true;
-              this.popper.removeAttribute('x-placement');
-              this.popper.style.left = '';
-              this.popper.style.position = '';
-              this.popper.style.top = '';
-              this.popper.style[getSupportedPropertyName('transform')] = '';
-              this.state = removeEventListeners(this.reference, this.state, this.options);
-
-              // remove the popper if user explicity asked for the deletion on destroy
-              // do not use `remove` because IE11 doesn't support it
-              if (this.options.removeOnDestroy) {
-                  this.popper.parentNode.removeChild(this.popper);
-              }
-              return this;
-          }
-
-          /**
-           * Collection of utilities useful when writing custom modifiers
-           * @memberof Popper
-           */
-
-
-          /**
-           * Default Popper.js options
-           * @memberof Popper
-           */
-
-      }]);
-      return Popper;
-  }();
-
-  Popper.Utils = Utils;
-
-  return Popper;
-
-}));
\ No newline at end of file
+    //
+    // Methods
+    //
+
+    /**
+     * Updates the position of the popper, computing the new offsets and applying the new style
+     * Prefer `scheduleUpdate` over `update` because of performance reasons
+     * @method
+     * @memberof Popper
+     */
+
+
+    createClass(Popper, [{
+        key: 'update',
+        value: function update() {
+            // if popper is destroyed, don't perform any further update
+            if (this.state.isDestroyed) {
+                return;
+            }
+
+            var data = {
+                instance: this,
+                styles: {},
+                attributes: {},
+                flipped: false,
+                offsets: {}
+            };
+
+            // make sure to apply the popper position before any computation
+            this.state.position = getPosition(this.reference);
+            setStyles(this.popper, { position: this.state.position });
+
+            // compute reference element offsets
+            data.offsets.reference = getReferenceOffsets(this.state, this.popper, this.reference);
+
+            // compute auto placement, store placement inside the data object,
+            // modifiers will be able to edit `placement` if needed
+            // and refer to originalPlacement to know the original value
+            data.placement = computeAutoPlacement(this.options.placement, data.offsets.reference, this.popper);
+
+            // store the computed placement inside `originalPlacement`
+            data.originalPlacement = this.options.placement;
+
+            // compute the popper offsets
+            data.offsets.popper = getPopperOffsets(this.state, this.popper, data.offsets.reference, data.placement);
+
+            // run the modifiers
+            data = runModifiers(this.modifiers, data);
+
+            // the first `update` will call `onCreate` callback
+            // the other ones will call `onUpdate` callback
+            if (!this.state.isCreated) {
+                this.state.isCreated = true;
+                this.options.onCreate(data);
+            } else {
+                this.options.onUpdate(data);
+            }
+        }
+
+        /**
+         * Schedule an update, it will run on the next UI update available
+         * @method scheduleUpdate
+         * @memberof Popper
+         */
+
+    }, {
+        key: 'destroy',
+
+
+        /**
+         * Destroy the popper
+         * @method
+         * @memberof Popper
+         */
+        value: function destroy() {
+            this.state.isDestroyed = true;
+
+            // touch DOM only if `applyStyle` modifier is enabled
+            if (isModifierEnabled(this.modifiers, 'applyStyle')) {
+                this.popper.removeAttribute('x-placement');
+                this.popper.style.left = '';
+                this.popper.style.position = '';
+                this.popper.style.top = '';
+                this.popper.style[getSupportedPropertyName('transform')] = '';
+            }
+
+            this.disableEventListeners();
+
+            // remove the popper if user explicity asked for the deletion on destroy
+            // do not use `remove` because IE11 doesn't support it
+            if (this.options.removeOnDestroy) {
+                this.popper.parentNode.removeChild(this.popper);
+            }
+            return this;
+        }
+
+        /**
+         * it will add resize/scroll events and start recalculating
+         * position of the popper element when they are triggered
+         * @method
+         * @memberof Popper
+         */
+
+    }, {
+        key: 'enableEventListeners',
+        value: function enableEventListeners() {
+            if (!this.state.eventsEnabled) {
+                this.state = setupEventListeners(this.reference, this.options, this.state, this.scheduleUpdate);
+            }
+        }
+
+        /**
+         * it will remove resize/scroll events and won't recalculate
+         * popper position when they are triggered. It also won't trigger onUpdate callback anymore,
+         * unless you call 'update' method manually.
+         * @method
+         * @memberof Popper
+         */
+
+    }, {
+        key: 'disableEventListeners',
+        value: function disableEventListeners() {
+            if (this.state.eventsEnabled) {
+                window.cancelAnimationFrame(this.scheduleUpdate);
+                this.state = removeEventListeners(this.reference, this.state);
+            }
+        }
+
+        /**
+         * Collection of utilities useful when writing custom modifiers
+         * @memberof Popper
+         */
+
+
+        /**
+         * List of accepted placements to use as values of the `placement` option
+         * @memberof Popper
+         */
+
+
+        /**
+         * Default Popper.js options
+         * @memberof Popper
+         */
+
+    }]);
+    return Popper;
+}();
+
+Popper.Utils = Utils;
+Popper.placements = ['auto', 'auto-start', 'auto-end', 'top', 'top-start', 'top-end', 'right', 'right-start', 'right-end', 'bottom', 'bottom-start', 'bottom-end', 'left', 'left-start', 'left-end'];
+Popper.Defaults = DEFAULTS;
+
+return Popper;
+
+})));
+//# sourceMappingURL=popper.es5.js.map
index d09a505..ff3a01c 100644 (file)
@@ -5,13 +5,13 @@
     define(["jquery","./popper"], function (a0,b1) {
       return (root['Tour'] = factory(a0,b1));
     });
-  } else if (typeof exports === 'object') {
+  } else if (typeof module === 'object' && module.exports) {
     // Node. Does not work with strict CommonJS, but
     // only CommonJS-like environments that support module.exports,
     // like Node.
     module.exports = factory(require("jquery"),require("popper.js"));
   } else {
-    root['Tour'] = factory($,Popper);
+    root['Tour'] = factory(root["$"],root["Popper"]);
   }
 }(this, function ($, Popper) {
 
@@ -24,7 +24,7 @@
  * @param   {object}    config  The configuration object.
  */
 
-var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol ? "symbol" : typeof obj; };
+var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };
 
 function Tour(config) {
     this.init(config);
@@ -773,12 +773,8 @@ Tour.prototype.addStepToPage = function (stepConfig) {
         // Add the backdrop.
         th