', {
+ // 'class': 'content'
+ // }).appendTo(me._$modalBox);
+
+ // me._$closeButton = $('
', {
+ // 'class': 'btn icon--cross is--small btn--grey modal--close'
+ // }).appendTo(me._$modalBox);
+
+ // $('body').append(me._$modalBox);
+
+ $.publish('plugin/swModal/onInit', [ me ]);
+ },
+
+ /**
+ * Registers all needed event listeners.
+ *
+ * @public
+ * @method registerEvents
+ */
+ registerEvents: function () {
+ // TODO: NO YET IMPLEMENTED FOR Bootstrap Theme!
+ // Original Responsive Theme Code:
+ var me = this,
+ $window = $(window);
+
+ // me._$closeButton.on('click.modal touchstart.modal', $.proxy(me.close, me));
+
+ // $window.on('keydown.modal', $.proxy(me.onKeyDown, me));
+ // StateManager.on('resize', me.onWindowResize, me);
+
+ // StateManager.registerListener({
+ // state: 'xs',
+ // enter: function() {
+ // me._$modalBox.addClass('is--fullscreen');
+ // },
+ // exit: function () {
+ // me._$modalBox.removeClass('is--fullscreen');
+ // }
+ // });
+
+ $.publish('plugin/swModal/onRegisterEvents', [ me ]);
+ },
+
+ /**
+ * Called when a key was pressed.
+ * Closes the modal box when the keyCode is mapped to a close key.
+ *
+ * @public
+ * @method onKeyDown
+ */
+ onKeyDown: function (event) {
+
+ var me = this,
+ keyCode = event.which,
+ keys = me.options.closeKeys,
+ len = keys.length,
+ i = 0;
+
+ if (!me.options.keyboardClosing) {
+ return;
+ }
+
+ for (; i < len; i++) {
+ if (keys[i] === keyCode) {
+ me.close();
+ }
+ }
+
+ $.publish('plugin/swModal/onKeyDown', [ me, event, keyCode ]);
+ },
+
+ /**
+ * Called when the window was resized.
+ * Centers the modal box when the sizing is set to 'content'.
+ *
+ * @public
+ * @method onWindowResize
+ */
+ onWindowResize: function (event) {
+ // TODO: NO YET IMPLEMENTED FOR Bootstrap Theme!
+ // Original Responsive Theme Code:
+ var me = this;
+
+ // if (me.options.sizing === 'content') {
+ // me.center();
+ // }
+
+ $.publish('plugin/swModal/onWindowResize', [ me, event ]);
+ },
+
+ /**
+ * Sets the top position of the modal box to center it to the screen
+ *
+ * @public
+ * @method centerModalBox
+ */
+ center: function () {
+ // TODO: NO YET IMPLEMENTED FOR Bootstrap Theme!
+ // Original Responsive Theme Code:
+ var me = this,
+ $modalBox = me._$modalBox,
+ windowHeight = window.innerHeight || $(window).height();
+
+ // $modalBox.css('top', (windowHeight - $modalBox.height()) / 2);
+
+ $.publish('plugin/swModal/onCenter', [ me ]);
+ },
+
+ /**
+ * Called when the overlay was clicked.
+ * Closes the modalbox when the 'closeOnOverlay' option is active.
+ *
+ * @public
+ * @method onOverlayClose
+ */
+ onOverlayClose: function () {
+ var me = this;
+
+ if (!me.options.closeOnOverlay) {
+ return;
+ }
+
+ me.close();
+
+ $.publish('plugin/swModal/onOverlayClick', [ me ]);
+ },
+
+ /**
+ * Removes the current modalbox element from the DOM and destroys its items.
+ * Also clears the options.
+ *
+ * @public
+ * @method destroy
+ */
+ destroy: function () {
+ // TODO: NO YET IMPLEMENTED FOR Bootstrap Theme!
+ // Original Responsive Theme Code:
+ var me = this,
+ p;
+
+ // me._$modalBox.remove();
+
+ // me._$modalBox = null;
+ // me._$header = null;
+ // me._$title = null;
+ // me._$content = null;
+ // me._$closeButton = null;
+
+ // for (p in me.options) {
+ // if (!me.options.hasOwnProperty(p)) {
+ // continue;
+ // }
+ // delete me.options[p];
+ // }
+
+ // StateManager.off('resize', me.onWindowResize, [ me ]);
+ }
+ };
+
+ $.plugin('swModalbox', {
+ // TODO: NO YET IMPLEMENTED FOR Bootstrap Theme!
+ init: function () {
+ console.error('This pluigin function is not yet implemented in swbt theme!');
+ },
+ open: function() {
+ console.error('This pluigin function is not yet implemented in swbt theme!');
+ },
+ close: function() {
+ console.error('This pluigin function is not yet implemented in swbt theme!');
+ },
+ });
+
+ $.plugin('imgModal', {
+ defaults: {
+ responsiveImgClass: 'img-responsive img-center',
+ imgModalSelector: 'img-modal',
+ imgModalGallerySelector: 'img-modal-gallery',
+ detailGallery: '#gallery',
+ detailModalAttr: '-modal',
+ detailThumbs: '#thumbs',
+ href: false,
+ title: '',
+ 'modal-size': 'modal-lg', // modal-sm | modal-md | modal-lg | modal-full
+ 'modal-gallery-url': false
+ },
+
+ init: function () {
+ var me = this;
+
+ me.modalBody = '';
+ me.modalSelector = me.opts.imgModalSelector;
+
+ me.applyDataAttributes();
+ me.registerEvents();
+
+ $.publish('plugin/imgModal/onInit', [me]);
+ },
+
+ registerEvents: function () {
+ var me = this;
+
+ me._on(me.$el, 'click', $.proxy(me.openModal, me));
+
+ $.publish('plugin/imgModal/onRegisterEvents', [me]);
+ },
+
+ setSliderAttributes: function ($slider) {
+ var opts = $slider.attr('data-modal-gallery-opts');
+
+ if (opts) {
+ $.each($.parseJSON(opts), function (key, value) {
+ $slider.attr('data-' + key, JSON.stringify(value));
+ });
+ }
+ },
+
+ openModal: function (event) {
+ event.preventDefault();
+ var me = this,
+ imgSrc = me.opts.href || me.$el.attr("href");
+
+ if (!imgSrc) {
+ return;
+ }
+
+ if (!me.opts['modal-gallery-url']) {
+ me.modalBody = '

';
+ var content = me.modalBody;
+ var title = me.opts.title;
+ me._$modalBox = $('body').createModal(content, me.opts['modal-size'], me.opts.imgModalSelector + ' fade', title);
+ me._$content = $(content);
+ me._$header = $(title);
+ me._$title = $(title);
+ me._$closeButton = null;
+ } else {
+ $body.loader('show');
+ $.publish('plugin/imgModal/beforeOpenModal', [me]);
+
+ $.ajax({
+ url: safeUrl(me.opts['modal-gallery-url']),
+ type: 'GET',
+ dataType: 'html',
+ success: function (result) {
+ var $detail = $(result),
+ $gallery = $detail.find(me.opts.detailGallery),
+ $thumbs = $detail.find(me.opts.detailThumbs);
+
+ // id's need to be me made unique again
+ $gallery.attr('id', $gallery.attr('id') + me.opts.detailModalAttr);
+ $thumbs.attr('id', $thumbs.attr('id') + me.opts.detailModalAttr);
+
+ // asnavfor data attribute needs to be updated with the new id's
+ $gallery.attr('data-asnavfor', '#' + $thumbs.attr('id'));
+ $thumbs.attr('data-asnavfor', '#' + $gallery.attr('id'));
+
+ // remove data-toggle="img-modal"
+ $gallery.find('[data-toggle="img-modal"]').attr('data-toggle', false).attr('href', '#');
+
+ // set slider options
+ me.setSliderAttributes($thumbs);
+ me.setSliderAttributes($gallery);
+
+ if ($gallery[0] && $thumbs[0]) {
+ var content = $gallery[0].outerHTML + $thumbs[0].outerHTML;
+ var title = me.opts.title;
+ me._$modalBox = $body.createModal(content, me.opts['modal-size'], me.opts.imgModalGallerySelector + ' fade', title, false, function (modal) {
+ picturefill();
+ $(modal).find('.slick').slickWrapper();
+ $body.loader('hide');
+ });
+ me._$content = $(content);
+ me._$header = $(title);
+ me._$title = $(title);
+ me._$closeButton = null;
+
+ } else {
+ $body.loader('hide');
+ }
+
+ $.publish('plugin/imgModal/afterOpenModal', [me]);
+ }
+ });
+ }
+
+ $.publish('plugin/imgModal/onOpenModal', [me]);
+ }
+ });
+
+ $.plugin('ajaxModal', {
+
+ defaults: {
+ customModalClass: 'custom-page-modal',
+ 'modal-class': '',
+ modalWrapperClassSelector: '.modal-dialog',
+ modalSelector: 'modal',
+ href: false,
+ 'modal-size': 'modal-md' // modal-sm | modal-md | modal-lg | modal-full
+ },
+
+ init: function () {
+ var me = this;
+
+ me.applyDataAttributes();
+ me.registerEvents();
+
+ $.publish('plugin/ajaxModal/onInit', [me]);
+ },
+
+ registerEvents: function () {
+ var me = this;
+
+ me._on(me.$el, 'click', $.proxy(me.openModal, me));
+
+ $.publish('plugin/ajaxModal/onRegisterEvents', [me]);
+ },
+
+ openModal: function (event) {
+ event.preventDefault();
+ var me = this,
+ link = me.opts.href || me.$el.attr("href");
+
+ if (!link) {
+ return;
+ }
+
+ $body.loader('show');
+ $.publish('plugin/ajaxModal/beforeOpenModal', [me]);
+
+ $.ajax(safeUrl(link), {
+ data: {
+ isXHR: 1
+ },
+ success: function (data) {
+
+ me.modalData = data;
+
+ $.publish('plugin/ajaxModal/beforeCreateModal', [me]);
+
+ $body.showModal(me.modalData, me.opts.customModalClass + ' ' + me.opts['modal-class'], function (modal) {
+ $body.loader('hide');
+
+ var $modal = $(modal);
+
+ // add modal size classes
+ $modal.find(me.opts.modalWrapperClassSelector).addClass(me.opts['modal-size']);
+ if (me.opts['modal-size'] == 'modal-full') {
+ $modal.addClass('fullscreen');
+ }
+
+ $modal.swSelectboxReplacement();
+
+ picturefill();
+
+ me.$modal = $modal;
+
+ $.publish('plugin/ajaxModal/afterCreateModal', [me]);
+ });
+
+ $.publish('plugin/ajaxModal/afterOpenModal', [me]);
+ }
+ });
+
+ $.publish('plugin/ajaxModal/onOpenModal', [me]);
+ }
+ });
+
+ $.plugin('notifyModal', {
+ defaults: {
+ notifyModalSelector: '.notify-modal-alert',
+ articleNotificationSelector: '#article_notification',
+ modalAlertSelector: '.alert-info, .alert-success',
+ notifyModalFormSelector: '.notify-modal-form',
+ notifyModalIdSelector: '[id*="notifyModal"]',
+ notifyModalClassSelector: '.modal[id^=notifyModal-]'
+ },
+
+ init: function () {
+ var me = this;
+
+ me.applyDataAttributes();
+ me.registerEvents();
+
+ $.publish('plugin/notifyModal/onInit', [me]);
+ },
+
+ registerEvents: function () {
+ var me = this;
+
+ me._on(me.$el, 'click', $.proxy(me.openModal, me));
+
+ // reset notify modal content
+ $(me.opts.notifyModalClassSelector).on('show.bs.modal', function () {
+ $(me.opts.notifyModalFormSelector).removeClass('hidden');
+ $(me.opts.notifyModalSelector).html('');
+ });
+
+ $.publish('plugin/notifyModal/onRegisterEvents', [me]);
+ },
+
+ openModal: function (event) {
+ event.preventDefault();
+ var me = this,
+ $form = me.$el.closest('form');
+
+ me.$el.loader('show');
+ $.publish('plugin/notifyModal/beforeOpenModal', [me]);
+
+ $.ajax({
+ type: 'POST',
+ url: safeUrl($form.attr('action')),
+ data: $form.serialize(),
+ beforeSend: function (xhr) { // change header, complete template needs to be loaded
+ xhr.setRequestHeader('X-Requested-With', {
+ toString: function () {
+ return '';
+ }
+ }
+ );
+ }
+ }).done(function (response) {
+ var $alertContainer = $(me.opts.notifyModalSelector);
+
+ $alertContainer.html($(response).find(me.opts.articleNotificationSelector).html());
+
+ if ($alertContainer.find(me.opts.modalAlertSelector).length > 0) {
+ me.$el.parents(me.opts.notifyModalIdSelector).find('form').addClass('hidden');
+ }
+
+ me.$el.loader('hide');
+
+ $.publish('plugin/notifyModal/afterOpenModal', [me]);
+ });
+
+ $.publish('plugin/notifyModal/onOpenModal', [me]);
+ },
+ });
+
+
+ // creates a new modal out of an existing html structure (e.g. the result of an ajax request)
+ $.fn.showModal = function (content, additionalClass, onShownCallback, options) {
+ var options = options || {},
+ id = options.id || ('modal' + Math.floor(Math.random() * 1000) + 1),
+ selector = selector || 'default',
+ callback = callback || function () { },
+ mergedOptions = $.extend({ show: true }, options),
+ modal = '
' + content + '
',
+ $modal,
+ showExisting = false;
+
+ // If content already IS a swbt-modal, don't build it, just show it instead.
+ if($(content).is('.modal.swbt-modal')){
+ $modal = $(body);
+ showExisting = true;
+ } else {
+ // Append new modal:
+ $(this).append(modal);
+ $modal = $('#' + id);
+
+ // Ensure removal on close:
+ $modal.on('hidden.bs.modal', function () {
+ $modal.remove();
+ });
+ }
+
+ // Register callbacks:
+ if(onShownCallback){
+ $modal.on('shown.bs.modal', function () {
+ onShownCallback(this);
+ });
+ }
+ if(options.onCloseCallback){
+ $modal.on('hide.bs.modal', function () {
+ options.onCloseCallback(this);
+ });
+ }
+
+ $modal.modal(mergedOptions);
+
+ return $modal;
+ };
+
+ // creates a new modal on the fly (the delivered content is wrapped in the standard bootstrap modal html structure)
+ $.fn.createModal = function (body, size, additionalClass, header, footer, onShownCallback, options) {
+ var modalTemplate = {
+ start: '
',
+ headerstart: '',
+ bodystart: '
',
+ bodyend: '
',
+ footerstart: '',
+ end: '
',
+ error: '
Modal konnte nicht geladen werden'
+ },
+ options = options || {},
+ $modal,
+ id = options.id || ('modal' + Math.floor(Math.random() * 1000) + 1),
+ callback = callback || function () { },
+ modal = '
' + modalTemplate.start;
+
+ if (header)
+ modal = modal + modalTemplate.headerstart + header + modalTemplate.headerend;
+ if (body)
+ modal = modal + modalTemplate.bodystart + body + modalTemplate.bodyend;
+ if (footer)
+ modal = modal + modalTemplate.footerstart + footer + modalTemplate.footerend;
+ if (!header && !body && !footer){
+ modal = modal + modalTemplate.headerstart + modalTemplate.error + modalTemplate.headerend;
+ }
+ modal = modal + modalTemplate.end + '
';
+
+ // If body already IS a swbt-modal, don't build it, just show it instead.
+ if($(body).is('.modal.swbt-modal')){
+ $modal = $(body);
+ $modal.modal('show');
+ } else {
+ // Create modal:
+ $(this).append(modal);
+ $modal = $('#' + id);
+
+ // Ensure removal on close:
+ $modal.on('hidden.bs.modal', function () {
+ $modal.remove();
+ });
+ }
+
+
+ if (size) {
+ switch (size) {
+ case 'modal-sm':
+ size = 'modal-sm';
+ break;
+ case 'modal-md':
+ size = 'modal-md';
+ break;
+ case 'modal-lg':
+ case 'modal-full':
+ // Map SW sizes:
+ case 'auto':
+ case 'fixed':
+ case 'content':
+ case 'full':
+ size = 'modal-lg';
+ break;
+ default:
+ break;
+ }
+
+ $modal.find('.modal-dialog').addClass(size);
+
+ // add modal size classes
+ if (size == 'modal-full') {
+ $modal.addClass('fullscreen');
+ }
+ }
+
+ // Register callbacks:
+ if(onShownCallback){
+ $modal.on('shown.bs.modal', function () {
+ onShownCallback(this);
+ });
+ }
+ if(options.onCloseCallback){
+ $modal.on('hide.bs.modal', function () {
+ options.onCloseCallback(this);
+ });
+ }
+
+ // Show!
+ $modal.modal('show');
+
+ return $modal;
+ };
+
+ // escape close
+ $(document).on('keydown', function (e) {
+ if (e.keyCode === 27) $(".swbt-modal").modal('hide');
+ });
+
+}(jQuery));
diff --git a/Resources/Themes/Frontend/BootstrapBare/frontend/_public/src/less/_components/sw-cookie-consent-manager.less b/Resources/Themes/Frontend/BootstrapBare/frontend/_public/src/less/_components/sw-cookie-consent-manager.less
new file mode 100644
index 0000000..3c4b0fc
--- /dev/null
+++ b/Resources/Themes/Frontend/BootstrapBare/frontend/_public/src/less/_components/sw-cookie-consent-manager.less
@@ -0,0 +1,112 @@
+#cookie-consent:extend(.sidebar-main.off-canvas) {
+ z-index: @swf-zindex-cookie-message;
+ .cookie-consent--configuration {
+ .cookie-consent--group {
+ border-bottom: 1px solid @gray-light;
+ position: relative;
+ .panel-title{
+ display:flex;
+ align-items:center;
+ text-align:left;
+ }
+ }
+ .cookie-consent--group-state{
+ flex: 0 0 auto;
+ }
+ .cookie-consent--group-title {
+ cursor: pointer;
+ flex: 1 0 auto;
+ display:flex;
+ align-items:center;
+ &[aria-expanded="true"]{
+ .cookie-consent--group-state-icon{
+ transform: rotate(-180deg);
+ }
+ }
+ }
+ .cookie-consent--group-state-icon{
+ margin-left:auto;
+ transition-duration:80ms;
+ transition-property: transform;
+ }
+ .cookie-consent--cookies-container{
+ &:last-child{
+ margin-bottom:0;
+ }
+ }
+ .cookie-consent--cookie{
+ display:flex;
+ align-items:center;
+ }
+ .cookie-consent--state-input{
+ flex:0 0 auto;
+ }
+ .cookie--label{
+ flex:1 0 auto;
+ cursor:pointer;
+ }
+ }
+}
+
+// State input
+.cookie-consent--state-input {
+ margin:0;
+ .unitize(margin-right, 10);
+ &.cookie-consent--required {
+ opacity: 0.4;
+
+ .cookie-consent--state-input-element {
+ cursor: default;
+ }
+ }
+
+ .cookie-consent--state-input-element {
+ .unitize-height(20);
+ .unitize-width(20);
+ .unitize(border-radius, 3);
+ border: 1px solid @border-color;
+ cursor: pointer;
+ display: block;
+ position: relative;
+ }
+
+ input {
+ display: none;
+
+ &:checked+.cookie-consent--state-input-element {
+ background: @highlight-success;
+
+ &::after {
+ .unitize-width(10);
+ .unitize-height(5);
+ .unitize(top, 4);
+ .unitize(left, 3);
+
+ border: 2px solid #fff;
+ border-top: none;
+ border-right: none;
+ background: transparent;
+ content: '';
+ position: absolute;
+ transform: rotate(-45deg);
+ }
+ }
+
+ &:indeterminate+.cookie-consent--state-input-element {
+ background: #5f7285;
+
+ &::after {
+ .unitize-width(10);
+ .unitize-height(5);
+ .unitize(top, 3);
+ .unitize(left, 4);
+
+ border: 2px none #fff;
+ border-bottom-style: solid;
+ background: transparent;
+ content: '';
+ position: absolute;
+ }
+ }
+ }
+}
diff --git a/Resources/Themes/Frontend/BootstrapBare/frontend/_public/src/less/_modules/sw-cookie-permission.less b/Resources/Themes/Frontend/BootstrapBare/frontend/_public/src/less/_modules/sw-cookie-permission.less
new file mode 100644
index 0000000..3dc2301
--- /dev/null
+++ b/Resources/Themes/Frontend/BootstrapBare/frontend/_public/src/less/_modules/sw-cookie-permission.less
@@ -0,0 +1,88 @@
+.page-wrap--cookie-permission {
+ .unitize(padding, 10);
+ z-index: @swf-zindex-cookie-message;
+ border-top: 1px solid @gray-light;
+ background: #fff;
+ position: fixed;
+ bottom: 0;
+ right: 0;
+ left: 0;
+
+ .cookie-permission--container {
+ position: relative;
+ display: flex;
+ flex-direction: column;
+ text-align: center;
+ @media screen and (min-width: @phoneLandscapeViewportWidth) {
+ flex-direction: row;
+ align-items: center;
+ text-align: left;
+ }
+ .cookie-permission--button {
+ display: flex;
+ flex-direction: column;
+ flex:1 0 auto;
+ .unitize(margin-top, 15);
+ @media screen and (min-width: @phoneLandscapeViewportWidth) {
+ margin-top:0;
+ .unitize(margin-left, 15);
+ }
+ @media screen and (min-width: @tabletLandscapeViewportWidth) {
+ flex-direction: row;
+ align-items: center;
+ flex: 1 1 auto;
+ }
+
+ .btn {
+ flex: 1 0 auto;
+ .unitize(margin, 5);
+ @media screen and (min-width: @tabletLandscapeViewportWidth) {
+ flex: 0 1 auto;
+ }
+ }
+ }
+ .cookie-permission--privacy-link{
+ text-decoration: underline @swf-brand-primary;
+ }
+ }
+}
+
+// TODO: What is this?
+.cookie-removal--container {
+ .unitize(padding, 25);
+
+ .cookie-removal--list {
+ .unitize(margin-bottom, 20);
+ list-style-position: inside;
+ }
+
+ .cookie-removal--buttons {
+ .unitize(margin-top, 20);
+ }
+
+ .cookie-removal--buttons .btn {
+ .unitize(margin-bottom, 6);
+ }
+}
+
+@media screen and (min-width: @phoneLandscapeViewportWidth) {
+ .cookie-removal--container {
+ .cookie-removal--buttons {
+ margin: 0;
+ }
+
+ .privacy--notice {
+ .unitize(padding-top, 8);
+ display: inline-block;
+ }
+ }
+
+ .page-wrap--cookie-permission .cookie-permission--container {
+
+ .cookie-permission--accept-button,
+ .cookie-permission--decline-button,
+ .cookie-permission--configure-button {
+ margin-top: 0;
+ }
+ }
+}
diff --git a/Resources/Themes/Frontend/BootstrapBare/frontend/_public/src/less/_variables/swf-zindex.less b/Resources/Themes/Frontend/BootstrapBare/frontend/_public/src/less/_variables/swf-zindex.less
index 37d3d1d..be61011 100755
--- a/Resources/Themes/Frontend/BootstrapBare/frontend/_public/src/less/_variables/swf-zindex.less
+++ b/Resources/Themes/Frontend/BootstrapBare/frontend/_public/src/less/_variables/swf-zindex.less
@@ -10,10 +10,10 @@
// custom
@swf-zindex-variant-label: 100;
-@swf-zindex-emotion-slider-title: 100;
+@swf-zindex-emotion-slider-title: 100;
@swf-zindex-variant-input: 101;
-@swf-zindex-emotion-mapping-link: 110;
-@swf-zindex-box-emotion-image-element: 500;
+@swf-zindex-emotion-mapping-link: 110;
+@swf-zindex-box-emotion-image-element:500;
@swf-zindex-box-label-element: 501;
@swf-zindex-menu: 999;
@swf-zindex-scroll-up: 999;
@@ -21,13 +21,14 @@
@swf-zindex-emotion-overlay: 1000;
@swf-zindex-custom-select: 1035; // must be lower than modal-background, but higher than navbar-fixed
@swf-zindex-compare-popover: 1049; // must be lower than modal
-@swf-zindex-emotion-video-element: 1000;
+@swf-zindex-emotion-video-element: 1000;
@swf-zindex-emotion-video-text: 1100;
-@swf-zindex-emotion-video-play-btn: 1200;
+@swf-zindex-emotion-video-play-btn: 1200;
@swf-zindex-emotion-video-cover: 1300;
@swf-zindex-overlay: 5000;
@swf-zindex-loader-full: 5001;
-@swf-zindex-cookie-message: 6000;
+@swf-zindex-cookie-message: 9999999999; // Trusted shops badge has a very high z-index - we need to overlay it
+@swf-zindex-cookie-consent-manager: @swf-zindex-cookie-message;
// selectBoxIt z-index is set via javascript to 999999.
// offcanvas needs to have a higher z-index,
diff --git a/Resources/Themes/Frontend/BootstrapBare/frontend/_public/src/less/components.less b/Resources/Themes/Frontend/BootstrapBare/frontend/_public/src/less/components.less
index 25650fe..b90cf07 100755
--- a/Resources/Themes/Frontend/BootstrapBare/frontend/_public/src/less/components.less
+++ b/Resources/Themes/Frontend/BootstrapBare/frontend/_public/src/less/components.less
@@ -11,3 +11,4 @@
@import "_components/menu.less";
@import "_components/popover.less";
@import "_components/captcha-honeypot.less";
+@import "_components/sw-cookie-consent-manager.less";
diff --git a/Resources/Themes/Frontend/BootstrapBare/frontend/_public/src/less/modules.less b/Resources/Themes/Frontend/BootstrapBare/frontend/_public/src/less/modules.less
index a6452bd..eb88aaa 100755
--- a/Resources/Themes/Frontend/BootstrapBare/frontend/_public/src/less/modules.less
+++ b/Resources/Themes/Frontend/BootstrapBare/frontend/_public/src/less/modules.less
@@ -6,3 +6,4 @@
@import "_modules/swf-listing.less";
@import "_modules/swf-emotion.less";
@import "_modules/swf-blog.less";
+@import "_modules/sw-cookie-permission.less";
diff --git a/Resources/Themes/Frontend/BootstrapBare/frontend/_public/vendors/js/shopware/jquery.cookie-consent-manager.js b/Resources/Themes/Frontend/BootstrapBare/frontend/_public/vendors/js/shopware/jquery.cookie-consent-manager.js
new file mode 100755
index 0000000..c21d6b4
--- /dev/null
+++ b/Resources/Themes/Frontend/BootstrapBare/frontend/_public/vendors/js/shopware/jquery.cookie-consent-manager.js
@@ -0,0 +1,449 @@
+(function ($, window, undefined) {
+ 'use strict';
+
+ $.getCookiePreference = function(cookieName) {
+ var cookie = $.getCookie('cookiePreferences'),
+ activeState = false,
+ groupKeys,
+ cookieKeys,
+ cookiePreferences;
+
+ if (!cookie) {
+ return activeState;
+ }
+
+ cookiePreferences = JSON.parse(cookie);
+ groupKeys = Object.keys(cookiePreferences.groups);
+
+ $.each(groupKeys, function (groupIndex, groupKey) {
+ if (!cookiePreferences.groups.hasOwnProperty(groupKey)) {
+ return;
+ }
+
+ cookieKeys = Object.keys(cookiePreferences.groups[groupKey].cookies);
+
+ $.each(cookieKeys, function (cookieIndex, cookieKey) {
+ if (!cookiePreferences.groups[groupKey].cookies.hasOwnProperty(cookieKey)) {
+ return;
+ }
+
+ if (cookieKey !== cookieName) {
+ return;
+ }
+
+ activeState = cookiePreferences.groups[groupKey].cookies[cookieKey].active;
+ });
+ });
+
+ return activeState;
+ };
+
+ $.plugin('swCookieConsentManager', {
+
+ defaults: {
+ /**
+ * Class which will be applied when opening the cookie consent manager.
+ *
+ * @property openClass
+ * @type {String}
+ */
+ openClass: 'is--open',
+
+ /**
+ * Selector of the element that should be clicked to close the consent manager modal.
+ *
+ * @property closeModalSelector
+ * @type {String}
+ */
+ closeModalSelector: '.cookie-consent--close',
+
+ /**
+ * Selector of the element that wraps around each group.
+ *
+ * @property cookieGroupSelector
+ * @type {String}
+ */
+ cookieGroupSelector: '.cookie-consent--group',
+
+ /**
+ * Selector of the hidden input element that contains the group's name.
+ *
+ * @property cookieGroupNameSelector
+ * @type {String}
+ */
+ cookieGroupNameSelector: '.cookie-consent--group-name',
+
+ /**
+ * Selector of the input element which contains the 'active' state of the cookie group.
+ *
+ * @property cookieGroupToggleInputSelector
+ * @type {String}
+ */
+ cookieGroupToggleInputSelector: '.cookie-consent--group-state-input',
+
+ /**
+ * Selector of the element which contains the cookies assigned to a group.
+ *
+ * @property cookieContainerSelector
+ * @type {String}
+ */
+ cookieContainerSelector: '.cookie-consent--cookie',
+
+ /**
+ * Selector of the hidden input element which contains the name of a cookie.
+ *
+ * @property cookieNameSelector
+ * @type {String}
+ */
+ cookieNameSelector: '.cookie-consent--cookie-name',
+
+ /**
+ * Selector of the input element which contains the 'active' state of the cookie.
+ *
+ * @property cookieActiveInputSelector
+ * @type {String}
+ */
+ cookieActiveInputSelector: '.cookie-consent--cookie-state-input',
+
+ /**
+ * Selector of the label element for the active input.
+ *
+ * @property cookieActiveInputLabelSelector
+ * @type {String}
+ */
+ cookieActiveInputLabelSelector: '.cookie-consent--cookie-state',
+
+ /**
+ * Selector of the button which should save the configured preferences.
+ *
+ * @property saveButtonSelector
+ * @type {String}
+ */
+ saveButtonSelector: '.cookie-consent--save-button',
+
+ /**
+ * Selector of the buttons to open the cookie consent manager.
+ *
+ * @property openConsentManagerButton
+ * @type {string}
+ */
+ openConsentManagerButton: '*[data-openConsentManager=true]',
+
+ /**
+ * Selector of the element which can be clicked as well to toggle a cookies state.
+ *
+ * @property cookieLabelSelector
+ * @type {string}
+ */
+ cookieLabelSelector: '.cookie--label',
+
+ /**
+ * The class which marks a group as "required".
+ *
+ * @property requiredClass
+ * @type {string}
+ */
+ requiredClass: 'cookie-consent--required'
+ },
+
+ /**
+ * Contains the selected cookie preferences.
+ *
+ * @property preferences
+ * @type {Object}
+ */
+ preferences: null,
+
+ /**
+ * Contains if the cookie consent manager is already open.
+ *
+ * @property isOpened
+ * @type {Boolean}
+ */
+ isOpened: false,
+
+ /**
+ * Contains the name for preference cookie.
+ *
+ * @property preferenceCookieName
+ * @type {String}
+ */
+ preferenceCookieName: 'cookiePreferences',
+
+ /**
+ * Contains the cookie permission jQuery plugin.
+ *
+ * @property cookiePermissionPlugin
+ * @type {Object}
+ */
+ cookiePermissionPlugin: null,
+
+ init: function () {
+ this.applyDataAttributes();
+
+ this.registerEvents();
+ this.cookiePermissionPlugin = $('*[data-cookie-permission="true"]').data('plugin_swCookiePermission');
+ },
+
+ registerEvents: function () {
+ this.$el.find(this.opts.closeModalSelector).on('click', $.proxy(this.onCloseClicked, this));
+ this.$el.find(this.opts.cookieGroupToggleInputSelector).on('change', $.proxy(this.onGroupToggleChanged, this));
+ this.$el.find(this.opts.cookieActiveInputSelector).on('change', $.proxy(this.onCookieToggleChanged, this));
+ this.$el.find(this.opts.saveButtonSelector).on('click', $.proxy(this.onSave, this));
+ this.$el.find(this.opts.cookieLabelSelector).on('click', $.proxy(this.onClickCookieName, this));
+
+ this._on(this.opts.openConsentManagerButton, 'click', $.proxy(this.openConsentManager, this));
+ },
+
+ assignCookieData: function () {
+ if (!this.hasSetPreferences()) {
+ return;
+ }
+
+ this.preferences = JSON.parse($.getCookie(this.preferenceCookieName));
+ this.parsePreferences();
+ },
+
+ parsePreferences: function () {
+ var me = this,
+ groupNames = Object.keys(me.preferences['groups']),
+ group,
+ groupRequired,
+ cookieNames,
+ cookie;
+
+ $.each(groupNames, function (groupIndex, groupName) {
+ group = me.findGroupByName(groupName);
+ groupRequired = group.find(me.opts.cookieActiveInputLabelSelector).hasClass(me.opts.requiredClass);
+ me.toggleGroup(group, groupRequired || me.preferences['groups'][groupName].active);
+
+ cookieNames = Object.keys(me.preferences['groups'][groupName].cookies);
+
+ $.each(cookieNames, function (cookieIndex, cookieName) {
+ cookie = me.findCookieByName(cookieName);
+ me.toggleCookie(cookie, groupRequired || me.preferences['groups'][groupName].cookies[cookieName].active);
+
+ me.checkActiveStateForAllCookiesOfGroup(group, groupRequired || me.preferences['groups'][groupName].cookies[cookieName].active);
+ });
+ });
+ },
+
+ findGroupByName: function (groupName) {
+ return $(this.opts.cookieGroupNameSelector + '[value=' + groupName + ']').parent();
+ },
+
+ findCookieByName: function (cookieName) {
+ return $(this.opts.cookieNameSelector + '[value=' + cookieName + ']').parent();
+ },
+
+ hasSetPreferences: function () {
+ return $.getCookie(this.preferenceCookieName) !== undefined;
+ },
+
+ openConsentManager: function () {
+ this.open();
+
+ if (window.cookieRemoval !== 2) {
+ this.cookiePermissionPlugin.hideElement();
+ }
+ },
+
+ buildCookiePreferences: function (allTrue) {
+ var opts = this.opts,
+ cookieGroups = this.$el.find(this.opts.cookieGroupSelector),
+ preferences = { 'groups': {}},
+ date = new Date(),
+ uniqueNames = [];
+
+ allTrue = allTrue || false;
+
+ cookieGroups.each(function (index, cookieGroup) {
+ var groupName = $(cookieGroup).find(opts.cookieGroupNameSelector).val(),
+ isActive = allTrue ? allTrue : $(cookieGroup).find(opts.cookieGroupToggleInputSelector).is(':checked'),
+ cookies = $(cookieGroup).find(opts.cookieContainerSelector);
+
+ uniqueNames.push(groupName);
+
+ if (!preferences['groups'].hasOwnProperty(groupName)) {
+ preferences['groups'][groupName] = {
+ name: groupName,
+ cookies: {}
+ };
+ }
+
+ preferences['groups'][groupName].active = isActive;
+
+ cookies.each(function (cookieIndex, cookie) {
+ var cookieName = $(cookie).find(opts.cookieNameSelector).val(),
+ isCookieActive = allTrue ? allTrue : $(cookie).find(opts.cookieActiveInputSelector).is(':checked');
+
+ uniqueNames.push(cookieName);
+
+ if (!preferences['groups'][groupName].cookies.hasOwnProperty(cookieName)) {
+ preferences['groups'][groupName].cookies[cookieName] = {
+ name: cookieName
+ };
+ }
+
+ preferences['groups'][groupName].cookies[cookieName].active = isCookieActive;
+ });
+ });
+
+ uniqueNames.sort();
+ preferences.hash = window.btoa(JSON.stringify(uniqueNames));
+
+ date.setTime(date.getTime() + (180 * 24 * 60 * 60 * 1000));
+ document.cookie = this.preferenceCookieName + '=' + JSON.stringify(preferences) + ';path=' + this.getBasePath() +';expires=' + date.toGMTString() + ';';
+
+ $.publish('plugin/swCookieConsentManager/onBuildCookiePreferences', [ this, preferences ]);
+ },
+
+ onClickCookieName: function (event) {
+ var cookieNameEl = $(event.currentTarget),
+ cookieCt = cookieNameEl.parent(this.opts.cookieContainerSelector),
+ inputEl = cookieCt.find(this.opts.cookieActiveInputSelector);
+
+ inputEl.click();
+ },
+
+ toggleAllCookiesFromGroup: function (cookies, active) {
+ var me = this;
+
+ cookies.each(function (cookieIndex, cookie) {
+ me.toggleCookie($(cookie), active);
+ });
+ },
+
+ checkActiveStateForAllCookiesOfGroup: function (group, cookieActiveStatus) {
+ var opts = this.opts,
+ cookies = group.find(this.opts.cookieContainerSelector),
+ allOfSame = true,
+ groupInput = group.find(this.opts.cookieGroupToggleInputSelector),
+ cookieInput;
+
+ cookies.each(function (cookieIndex, cookie) {
+ cookie = $(cookie);
+ cookieInput = cookie.find(opts.cookieActiveInputSelector);
+
+ if (cookieInput.is(':checked') !== cookieActiveStatus) {
+ allOfSame = false;
+ }
+ });
+
+ if (allOfSame) {
+ groupInput.prop('indeterminate', false);
+ this.toggleGroup(group, cookieActiveStatus);
+ } else {
+ groupInput.prop('indeterminate', true);
+ }
+ },
+
+ toggleGroup: function (group, activeStatus) {
+ group.find(this.opts.cookieGroupToggleInputSelector).prop('checked', activeStatus);
+ },
+
+ toggleCookie: function (cookie, activeStatus) {
+ cookie.find(this.opts.cookieActiveInputSelector).prop('checked', activeStatus);
+ },
+
+ onSave: function () {
+ this.buildCookiePreferences();
+ this.close();
+ this.removeDeclinedAndAcceptedCookie();
+ $.overlay.close();
+
+ $.publish('plugin/swCookieConsentManager/onSave', [ this ]);
+ },
+
+ onGroupToggleChanged: function (event) {
+ var opts = this.opts,
+ groupToggle = $(event.currentTarget),
+ group = groupToggle.parents(opts.cookieGroupSelector),
+ cookies = group.find(opts.cookieContainerSelector);
+
+ this.toggleAllCookiesFromGroup(cookies, groupToggle.is(':checked'));
+
+ $.publish('plugin/swCookieConsentManager/onGroupToggleChanged', [ this, groupToggle ]);
+ },
+
+ onCookieToggleChanged: function (event) {
+ var opts = this.opts,
+ cookieToggle = $(event.currentTarget),
+ cookie = cookieToggle.parents(opts.cookieContainerSelector),
+ group = cookie.parents(opts.cookieGroupSelector);
+
+ this.checkActiveStateForAllCookiesOfGroup(group, cookieToggle.is(':checked'));
+
+ $.publish('plugin/swCookieConsentManager/onCookieToggleChanged', [ this, cookieToggle ]);
+ },
+
+ onCloseClicked: function () {
+ $.overlay.close();
+ this.close();
+ },
+
+ open: function () {
+ if (this.isOpened) {
+ return;
+ }
+
+ this.assignCookieData();
+
+ // TODO - Modification of copied SW core file / MANUAL HANDLING REQUIRED ON UPDATE!
+ // This currently has to be added because the core implementation
+ // doesn't call a js plugin (like modal in swbt.modal.js) but directly
+ // uses the jQuery functions (show / hide) which makes it impossible
+ // to delegate the function cleanly to a js $.plugin implementation!
+ // Hopefully the core implementation will change in the future
+ // and uses a plugin instead like $.modal.open() / $.modal.close()
+ // Util that we have to adopt this change to SW Updates!
+
+ // Call bootstrap API modal show function instead of jquery show().
+ // this.$el.show();
+ $.modal.open(this.$el);
+ // this.$el.addClass(this.opts.openClass);
+ // $.overlay.open({
+ // onClose: $.proxy(this.close, this)
+ // });
+ // TODO - Modification of core file END.
+ this.isOpened = true;
+ },
+
+ close: function () {
+ if (!this.isOpened) {
+ return;
+ }
+
+ // TODO - Modification of copied SW core file / MANUAL HANDLING REQUIRED ON UPDATE!
+ // This currently has to be added because the core implementation
+ // doesn't call a js plugin (like modal in swbt.modal.js) but directly
+ // uses the jQuery functions (show / hide) which makes it impossible
+ // to delegate the function cleanly to a js $.plugin implementation!
+ // Hopefully the core implementation will change in the future
+ // and uses a plugin instead like $.modal.open() / $.modal.close().
+ // Util that we have to adopt this change to SW Updates!
+
+ // Call modal plugin function
+ $.modal.close();
+ // this.$el.removeClass(this.opts.openClass);
+ // TODO - Modification of core file END.
+ this.isOpened = false;
+ },
+
+ removeDeclinedAndAcceptedCookie: function () {
+ $.removeCookie('cookieDeclined');
+ $.removeCookie('allowCookie');
+
+ window.localStorage.removeItem(this.cookiePermissionPlugin.storageKey);
+ },
+
+ getBasePath: function () {
+ return window.csrfConfig.basePath || '/';
+ }
+ });
+})(jQuery, window);
+
+function openCookieConsentManager () {
+ var plugin = $('*[data-cookie-consent-manager="true"]').data('plugin_swCookieConsentManager');
+ plugin.openConsentManager();
+}
diff --git a/Resources/Themes/Frontend/BootstrapBare/frontend/_public/vendors/js/shopware/jquery.cookie-permission.js b/Resources/Themes/Frontend/BootstrapBare/frontend/_public/vendors/js/shopware/jquery.cookie-permission.js
old mode 100644
new mode 100755
index 68a079b..9d8c913
--- a/Resources/Themes/Frontend/BootstrapBare/frontend/_public/vendors/js/shopware/jquery.cookie-permission.js
+++ b/Resources/Themes/Frontend/BootstrapBare/frontend/_public/vendors/js/shopware/jquery.cookie-permission.js
@@ -31,6 +31,30 @@
*/
acceptButtonSelector: '.cookie-permission--accept-button',
+ /**
+ * Selector of the decline button to select the button and register events on it.
+ *
+ * @property declineButtonSelector
+ * @type {string}
+ */
+ declineButtonSelector: '.cookie-permission--decline-button',
+
+ /**
+ * Selector of the cookie consent manager.
+ *
+ * @property cookieConsentManagerSelector
+ * @type {string}
+ */
+ cookieConsentManagerSelector: '*[data-cookie-consent-manager="true"]',
+
+ /**
+ * Selector of the close button to select the button and register events on it.
+ *
+ * @property declineButtonSelector
+ * @type {string}
+ */
+ closeButtonSelector: '.cookie-permission--close-button',
+
/**
* Selector of the privacy statement link "More information" to select and prepare the href property.
*
@@ -39,6 +63,24 @@
*/
privacyLinkSelector: '.cookie-permission--privacy-link',
+ /**
+ * Selector of the hidden input element that contains a cookie group's name.
+ * Will be used to check if the cookie preferences are up to date by checking against a hash.
+ *
+ * @property cookieGroupNameSelector
+ * @type {String}
+ */
+ cookieGroupNameSelector: '.cookie-consent--group-name',
+
+ /**
+ * Selector of the hidden input element which contains the name of a cookie.
+ * Will be used to check if the cookie preferences are up to date by checking against a hash.
+ *
+ * @property cookieNameSelector
+ * @type {String}
+ */
+ cookieNameSelector: '.cookie-consent--cookie-name',
+
/**
* The current shopId for create the storageKey
*
@@ -53,7 +95,12 @@
* @property host
* @type {string}
*/
- urlPrefix: ''
+ urlPrefix: '',
+
+ /**
+ * Modal title
+ */
+ title: ''
},
/**
@@ -113,7 +160,13 @@
* @return {void}
*/
update: function() {
- this.setPermissionHeight();
+ var me = this;
+
+ this.displayCookiePermission(function(display) {
+ if (display) {
+ me.setPermissionHeight();
+ }
+ });
},
/**
@@ -125,6 +178,7 @@
createProperties: function() {
this.$privacyLink = this.$el.find(this.opts.privacyLinkSelector);
this.$acceptButton = this.$el.find(this.opts.acceptButtonSelector);
+ this.$declineButton = this.$el.find(this.opts.declineButtonSelector);
this.storageKey = this.createStorageKey();
this.storage = window.StorageManager.getLocalStorage();
},
@@ -167,6 +221,7 @@
*/
registerEvents: function() {
this._on(this.$acceptButton, 'click', $.proxy(this.onAcceptButtonClick, this));
+ this._on(this.$declineButton, 'click', $.proxy(this.onDeclineButtonClick, this));
},
/**
@@ -175,9 +230,52 @@
* @param {function} callback
*/
displayCookiePermission: function(callback) {
+ if (window.cookieRemoval === 1) {
+ if ($.getCookie('cookieDeclined')) {
+ callback(false);
+ return;
+ }
+
+ if ($.getCookie('cookiePreferences') && !this.hasPreferencesHashChanged()) {
+ callback(false);
+ return;
+ }
+ }
+
+ if ((window.cookieRemoval === 2 && document.cookie.indexOf('allowCookie') !== -1)) {
+ callback(false);
+ return;
+ }
+
callback(!this.storage.getItem(this.storageKey));
},
+ /**
+ * Checks if the hash for the preferences has changed. This happened e.g. when a new cookie
+ * was registered by a plugin.
+ *
+ * @returns { boolean }
+ */
+ hasPreferencesHashChanged: function () {
+ var preferences = JSON.parse($.getCookie('cookiePreferences')),
+ currentHash = preferences.hash,
+ uniqueNames = [],
+ newHash;
+
+ $(this.opts.cookieGroupNameSelector).each(function (key, group) {
+ uniqueNames.push($(group).val());
+ });
+
+ $(this.opts.cookieNameSelector).each(function (key, cookie) {
+ uniqueNames.push($(cookie).val());
+ });
+
+ uniqueNames.sort();
+ newHash = window.btoa(JSON.stringify(uniqueNames));
+
+ return newHash !== currentHash;
+ },
+
/**
* Creates the storageKey from the prefix and the shopId like the following example:
*
@@ -206,7 +304,51 @@
onAcceptButtonClick: function(event) {
event.preventDefault();
- this.storage.setItem(this.storageKey, 'true');
+ try {
+ window.localStorage.setItem(this.storageKey, 'true');
+ } catch (err) {}
+
+ var d = new Date();
+ d.setTime(d.getTime() + (180 * 24 * 60 * 60 * 1000));
+
+ document.cookie = 'allowCookie=1; path=' + this.getBasePath() + ';expires=' + d.toGMTString() + ';';
+
+ this.hideElement();
+ this.applyActiveToPreferences();
+
+ $.publish('plugin/swCookiePermission/onAcceptButtonClick', [this, event]);
+ },
+
+ applyActiveToPreferences: function () {
+ var cookieConsentPlugin = $(this.opts.cookieConsentManagerSelector).data('plugin_swCookieConsentManager');
+ cookieConsentPlugin.buildCookiePreferences(true);
+ },
+
+ /**
+ * Event handler for the declineButton click.
+ *
+ * @public
+ * @method onDeclineButtonClick
+ */
+ onDeclineButtonClick: function(event) {
+ event.preventDefault();
+
+ document.cookie = 'cookieDeclined=1; path=' + this.getBasePath() + ';';
+
+ this.hideElement();
+
+ $.publish('plugin/swCookiePermission/onDeclineButtonClick', [this, event]);
+ },
+
+ /**
+ * Event handler for the closeButton click.
+ *
+ * @public
+ * @method onCloseButtonClick
+ */
+ onCloseButtonClick: function(event) {
+ event.preventDefault();
+
this.hideElement();
},
@@ -217,8 +359,21 @@
* @method showElement
*/
showElement: function() {
- this.$el.removeClass(this.opts.isHiddenClass);
- this.setPermissionHeight();
+ if (window.cookieRemoval === 2) {
+ $.modal.open(this.$el.html(), {
+ title: this.opts.title,
+ sizing: 'content',
+ width: 500
+ });
+
+ this.$acceptButton = $(this.opts.acceptButtonSelector);
+ this.$closeButton = $(this.opts.closeButtonSelector);
+ this._on(this.$acceptButton, 'click', $.proxy(this.onAcceptButtonClick, this));
+ this._on(this.$closeButton, 'click', $.proxy(this.onCloseButtonClick, this));
+ } else {
+ this.$el.removeClass(this.opts.isHiddenClass);
+ this.setPermissionHeight();
+ }
},
/**
@@ -230,6 +385,17 @@
hideElement: function() {
this.$el.addClass(this.opts.isHiddenClass);
$body.css('padding-bottom', 0);
+ // TODO - Modification of copied SW core file / MANUAL HANDLING REQUIRED ON UPDATE!
+ // The condition from showElement was missing here in SW core file
+ // which lead to unintended close of the cookie-consent-manager layer.
+ // Hopefully SW will fix this so this file can be reverted to be equal to core.
+ if (window.cookieRemoval === 2) {
+ $.modal.close();
+ }
+ },
+
+ getBasePath: function () {
+ return window.csrfConfig.basePath || '/';
}
});
}(jQuery, window));
diff --git a/Resources/Themes/Frontend/BootstrapBare/frontend/_public/vendors/js/shopware/jquery.invalid-tos-jump.js b/Resources/Themes/Frontend/BootstrapBare/frontend/_public/vendors/js/shopware/jquery.invalid-tos-jump.js
new file mode 100644
index 0000000..5603192
--- /dev/null
+++ b/Resources/Themes/Frontend/BootstrapBare/frontend/_public/vendors/js/shopware/jquery.invalid-tos-jump.js
@@ -0,0 +1,53 @@
+;(function($, window) {
+ 'use strict';
+
+ /**
+ * Invalid ToS Jump plugin
+ *
+ * Triggers the has--error class for the sAGB checkbox (ToS-Checkbox) and scrolls up to display its unchecked state.
+ * Especially made for iOS-Devices due to missing hints if AGB/TOS hasn't been checked
+ *
+ * @example The example shows the basic usage:
+ *
+ * ```
+ *
+ * ```
+ */
+ $.plugin('swInvalidTosJump', {
+
+ /**
+ * Default settings for the plugin
+ * @type {Object}
+ */
+ defaults: {
+ /**
+ * Selector, which is associated to the jumpElement to toggle an visual indicator / error-class
+ */
+ jumpLabelSelector: 'label[for="sAGB"]',
+
+ /**
+ * Class to add on invalid
+ */
+ errorClass: 'has--error'
+ },
+
+ /**
+ * Initializes the plugin and sets up the necessary event listeners.
+ */
+ init: function () {
+ var me = this;
+ me.$jumpLabel = $(me.opts.jumpLabelSelector);
+
+ me._on(me.$el, 'invalid', $.proxy(me.jumpToInvalid, me));
+ },
+
+ jumpToInvalid: function () {
+ var me = this;
+
+ window.scroll(0, me.$el.offset().top - (window.innerHeight/2));
+ me.$jumpLabel.addClass(me.opts.errorClass);
+ }
+ });
+})(jQuery, window);
diff --git a/Resources/Themes/Frontend/BootstrapBare/frontend/_public/vendors/js/shopware/jquery.notification-message-close.js b/Resources/Themes/Frontend/BootstrapBare/frontend/_public/vendors/js/shopware/jquery.notification-message-close.js
new file mode 100644
index 0000000..ef0d0ec
--- /dev/null
+++ b/Resources/Themes/Frontend/BootstrapBare/frontend/_public/vendors/js/shopware/jquery.notification-message-close.js
@@ -0,0 +1,29 @@
+$.plugin('swNotificationMessageClose', {
+
+ defaults: {
+ /**
+ * @var selector for notification
+ */
+ notificationSelector: '.alert',
+
+ /**
+ * @var called url when x is pressed
+ */
+ link: ''
+ },
+
+ init: function () {
+ this.applyDataAttributes();
+
+ this.$alert = this.$el.closest(this.opts.notificationSelector);
+
+ this._on(this.$el, 'click', $.proxy(this.closeMessage, this));
+ },
+
+ closeMessage: function (event) {
+ event.preventDefault();
+
+ $.post(this.opts.link);
+ this.$alert.fadeOut();
+ }
+});
diff --git a/Resources/Themes/Frontend/BootstrapBare/frontend/_public/vendors/js/shopware/jquery.state-manager.js b/Resources/Themes/Frontend/BootstrapBare/frontend/_public/vendors/js/shopware/jquery.state-manager.js
index 33e4800..aee84c5 100644
--- a/Resources/Themes/Frontend/BootstrapBare/frontend/_public/vendors/js/shopware/jquery.state-manager.js
+++ b/Resources/Themes/Frontend/BootstrapBare/frontend/_public/vendors/js/shopware/jquery.state-manager.js
@@ -109,6 +109,41 @@
vendorPropertyDiv = document.createElement('div'),
vendorPrefixes = ['webkit', 'moz', 'ms', 'o'];
+ /**
+ * @returns { boolean }
+ */
+ function hasCookiesAllowed () {
+ if (window.cookieRemoval === 0) {
+ return true;
+ }
+
+ if (window.cookieRemoval === 1) {
+ if (document.cookie.indexOf('cookiePreferences') !== -1) {
+ return true;
+ }
+
+ return document.cookie.indexOf('cookieDeclined') === -1;
+ }
+
+ /**
+ * Must be cookieRemoval = 2, so only depends on existence of `allowCookie`
+ */
+ return document.cookie.indexOf('allowCookie') !== -1;
+ }
+
+ /**
+ * @returns { boolean }
+ */
+ function isDeviceCookieAllowed () {
+ var cookiesAllowed = hasCookiesAllowed();
+
+ if (window.cookieRemoval !== 1) {
+ return cookiesAllowed;
+ }
+
+ return cookiesAllowed && document.cookie.indexOf('"name":"x-ua-device","active":true') !== -1;
+ }
+
/**
* @class EventEmitter
* @constructor
@@ -294,7 +329,7 @@
* @type {Object}
*/
window.StateManager = $.extend(Object.create(EventEmitter.prototype), {
-
+
/**
* Constructor for Shopware EventEmitter
*
@@ -303,7 +338,7 @@
* @constructor
*/
EventEmitter: EventEmitter,
-
+
/**
* Collection of all registered breakpoints
*
@@ -1095,6 +1130,7 @@
* @method destroyPlugin
* @param {String|jQuery} selector
* @param {String} pluginName
+ * @returns {StateManager}
*/
destroyPlugin: function (selector, pluginName) {
var $el = (typeof selector === 'string') ? $(selector) : selector,
@@ -1105,7 +1141,7 @@
plugin;
if (!len) {
- return;
+ return this;
}
for (; i < len; i++) {
@@ -1116,6 +1152,8 @@
$currentEl.removeData(name);
}
}
+
+ return this;
},
/**
@@ -1300,6 +1338,13 @@
});
},
+ /**
+ * Returns true when user has allowed to set cookies
+ *
+ * @returns {boolean}
+ */
+ hasCookiesAllowed: hasCookiesAllowed,
+
_getCurrentDevice: function() {
var i = 0,
width = this.getViewportWidth(),
@@ -1316,9 +1361,17 @@
},
_setDeviceCookie: function() {
- var device = this._getCurrentDevice();
+ if (!isDeviceCookieAllowed()) {
+ return;
+ }
+
+ var device = this._getCurrentDevice(),
+ cookieString = 'x-ua-device=' + device + '; path=/';
- document.cookie = 'x-ua-device=' + device + '; path=/';
+ if (window.secureShop !== undefined && window.secureShop === true) {
+ cookieString = 'x-ua-device=' + device + ';secure; path=/';
+ }
+ document.cookie = cookieString;
},
/**
@@ -1326,33 +1379,43 @@
* and saves it to a object that can be accessed.
*
* @private
- * @property _scrollBarSize
+ * @method _getScrollBarSize
* @type {Object}
*/
- _scrollBarSize: (function () {
- var $el = $('
', {
- css: {
- width: 100,
- height: 100,
- overflow: 'scroll',
- position: 'absolute',
- top: -9999
- }
- }),
- el = $el[0],
- width,
- height;
+ _getScrollBarSize: (function () {
+ var cache;
+ var getSize = function(){
+ var $el = $('
', {
+ css: {
+ width: 100,
+ height: 100,
+ overflow: 'scroll',
+ position: 'absolute',
+ top: -9999
+ }
+ }),
+ el = $el[0],
+ width,
+ height;
- $('body').append($el);
+ $('body').append($el);
- width = el.offsetWidth - el.clientWidth;
- height = el.offsetHeight - el.clientHeight;
+ width = el.offsetWidth - el.clientWidth;
+ height = el.offsetHeight - el.clientHeight;
- $($el).remove();
+ $($el).remove();
- return {
- width: width,
- height: height
+ return {
+ width: width,
+ height: height
+ };
+ };
+
+ return function() {
+ if (!cache) {
+ cache = getSize();
+ }
+ return cache;
};
}()),
@@ -1365,7 +1428,7 @@
* @returns {Object} The width/height pair of the scroll bar size.
*/
getScrollBarSize: function () {
- return $.extend({}, this._scrollBarSize);
+ return $.extend({}, this._getScrollBarSize());
},
/**
@@ -1376,7 +1439,7 @@
* @returns {Number} Width of the default browser scroll bar.
*/
getScrollBarWidth: function () {
- return this._scrollBarSize.width;
+ return this._getScrollBarSize().width;
},
/**
@@ -1387,7 +1450,7 @@
* @returns {Number} Height of the default browser scroll bar.
*/
getScrollBarHeight: function () {
- return this._scrollBarSize.height;
+ return this._getScrollBarSize().height;
},
/**
diff --git a/Resources/Themes/Frontend/BootstrapBare/frontend/blog/comment/form.tpl b/Resources/Themes/Frontend/BootstrapBare/frontend/blog/comment/form.tpl
index b7790d4..3950e35 100755
--- a/Resources/Themes/Frontend/BootstrapBare/frontend/blog/comment/form.tpl
+++ b/Resources/Themes/Frontend/BootstrapBare/frontend/blog/comment/form.tpl
@@ -111,6 +111,13 @@
{/block}
+ {* Data protection information *}
+ {block name='frontend_forms_form_elements_form_privacy'}
+ {if {config name=ACTDPRTEXT} || {config name=ACTDPRCHECK}}
+ {include file="frontend/_includes/privacy.tpl"}
+ {/if}
+ {/block}
+
{* Submit button *}
{block name='frontend_blog_comments_input_submit'}
{/block}
{block name='frontend_checkout_confirm_information_addresses_equal_panel_shipping'}
@@ -180,11 +189,11 @@
{/block}
{/block}
-