From 1945540ad08d2df11859a9bf2e9e347f1b69d69c Mon Sep 17 00:00:00 2001
From: Maximilian Lauterbach
Date: Thu, 3 Dec 2015 14:06:12 +0100
Subject: [PATCH 01/17] missing version update
---
tools/scripts.json | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/tools/scripts.json b/tools/scripts.json
index 400032d..cae103c 100644
--- a/tools/scripts.json
+++ b/tools/scripts.json
@@ -10,7 +10,7 @@
"libs/jquery-ui.min.js",
"libs/jquery.ui.touch-punch.min.js",
"plenty/plenty-2.js",
- "plenty/plentymarketsCMStools-0.9.0.js"
+ "plenty/plentymarketsCMStools-1.0.1.js"
]
},
"PageDesignContent": {
From 3ebb9b5be498aa565641cd6c5cf6c1e7466445b1 Mon Sep 17 00:00:00 2001
From: Felix
Date: Fri, 4 Dec 2015 14:13:48 +0100
Subject: [PATCH 02/17] FEATURE add events 'check' & 'uncheck' for directives
at checkboxes and radio buttons
---
src/plentyFramework.js | 45 ++++++++++++++++++++++++++++++++++++++++++
1 file changed, 45 insertions(+)
diff --git a/src/plentyFramework.js b/src/plentyFramework.js
index 8e71709..247636c 100644
--- a/src/plentyFramework.js
+++ b/src/plentyFramework.js
@@ -159,6 +159,8 @@
return;
}
+ addCustomEvents( element );
+
for ( var i = 0; i < directives.length; i++ )
{
var directive = directives[i];
@@ -250,6 +252,49 @@
} );
}
+ function addCustomEvents( element )
+ {
+
+ var $elem = $( element );
+
+ if( $elem.is('input[type="checkbox"]') )
+ {
+ $elem.on('change', function() {
+
+ if( $elem.is(':checked') )
+ {
+ $elem.trigger('check');
+ }
+ else
+ {
+ $elem.trigger('uncheck');
+ }
+ });
+ }
+
+ if( $elem.is('input[type="radio"]') )
+ {
+ $elem.on('change', function() {
+
+ var radioGroup = $elem.attr('name');
+
+ $( 'input[type="radio"][name="' + radioGroup + '"]' ).each(function( i, radio ) {
+ var $radio = $( radio );
+ if( $radio.is(':checked') )
+ {
+ $radio.trigger('check');
+ }
+ else
+ {
+ $radio.trigger('uncheck');
+ }
+
+ });
+
+ });
+ }
+ }
+
function parseDirectives( input, thisValue )
{
var directivePattern = /^(([\w]+):)?([\w]+)\.([\w]+)(\((.*)\))?$/;
From 5480b88198f5d64159cb37d0da424f511f658f42 Mon Sep 17 00:00:00 2001
From: Felix
Date: Fri, 4 Dec 2015 14:15:19 +0100
Subject: [PATCH 03/17] Add addClass() and removeClass() to UI directive,
working like toggleClass()
---
src/directives/UI.js | 32 +++++++++++++++++++++++++++++---
1 file changed, 29 insertions(+), 3 deletions(-)
diff --git a/src/directives/UI.js b/src/directives/UI.js
index 0e7b042..b608ae7 100644
--- a/src/directives/UI.js
+++ b/src/directives/UI.js
@@ -23,7 +23,9 @@
initSlideToggle : initSlideToggle,
toggleHideShow : toggleHideShow,
toggleSocialShare : toggleSocialShare,
- toggleClass : toggleClass
+ toggleClass : toggleClass,
+ addClass : addClass,
+ removeClass : removeClass
};
function initUIWindowEvents()
@@ -346,8 +348,32 @@
{
var e = pm.getRecentEvent();
if( !!e ) e.preventDefault();
- var $elem = $( target );
- $elem.toggleClass( cssClass );
+
+ $( target ).toggleClass( cssClass );
+ return false;
+ }
+ }
+
+ function addClass( cssClass, target, interval )
+ {
+ if ( !!target && !!cssClass && ( !interval || MediaSizeService.isInterval( interval ) ) )
+ {
+ var e = pm.getRecentEvent();
+ if( !!e ) e.preventDefault();
+
+ $( target ).addClass( cssClass );
+ return false;
+ }
+ }
+
+ function removeClass( cssClass, target, interval )
+ {
+ if ( !!target && !!cssClass && ( !interval || MediaSizeService.isInterval( interval ) ) )
+ {
+ var e = pm.getRecentEvent();
+ if( !!e ) e.preventDefault();
+
+ $( target ).removeClass( cssClass );
return false;
}
}
From c04292a7205e6030c263cd7ceaad7286e4896571 Mon Sep 17 00:00:00 2001
From: Felix
Date: Fri, 4 Dec 2015 14:16:29 +0100
Subject: [PATCH 04/17] remove jquery-ui from scripts.json: Already included in
plenty.shop.min.js
---
tools/scripts.json | 1 -
1 file changed, 1 deletion(-)
diff --git a/tools/scripts.json b/tools/scripts.json
index cae103c..286834d 100644
--- a/tools/scripts.json
+++ b/tools/scripts.json
@@ -7,7 +7,6 @@
"libs/owl.carousel.min.js",
"libs/jquery.lazyload.js",
"libs/jquery.touchSwipe.min.js",
- "libs/jquery-ui.min.js",
"libs/jquery.ui.touch-punch.min.js",
"plenty/plenty-2.js",
"plenty/plentymarketsCMStools-1.0.1.js"
From 834ca6abdbd522b9d8b76730c6d210b271a9ba78 Mon Sep 17 00:00:00 2001
From: Felix
Date: Fri, 4 Dec 2015 17:18:06 +0100
Subject: [PATCH 05/17] Add slide methods to UI directive
---
src/directives/UI.js | 31 +++++++++++++++++++++++++++++++
1 file changed, 31 insertions(+)
diff --git a/src/directives/UI.js b/src/directives/UI.js
index b608ae7..5154e2b 100644
--- a/src/directives/UI.js
+++ b/src/directives/UI.js
@@ -21,6 +21,9 @@
initToTop : initToTop,
initLazyload : initLazyload,
initSlideToggle : initSlideToggle,
+ slideDown : slideDown,
+ slideUp : slideUp,
+ slideToggle : slideToggle,
toggleHideShow : toggleHideShow,
toggleSocialShare : toggleSocialShare,
toggleClass : toggleClass,
@@ -263,6 +266,34 @@
}
}
+ function slideDown( target, duration )
+ {
+ duration = duration || 400;
+ $(target).parents( '[data-plenty-rel="equal-target"]' ).css( 'height', 'auto' );
+ $(target).slideDown( duration, function() {
+ fireEqualHeight();
+ });
+ }
+
+ function slideUp( target, duration )
+ {
+ duration = duration || 400;
+ $(target).parents( '[data-plenty-rel="equal-target"]' ).css( 'height', 'auto' );
+ $(target).slideUp( duration, function() {
+ fireEqualHeight();
+ });
+ }
+
+ function slideToggle( target, duration )
+ {
+ duration = duration || 400;
+ $(target).parents( '[data-plenty-rel="equal-target"]' ).css( 'height', 'auto' );
+ $(target).slideToggle( duration, function() {
+ fireEqualHeight();
+ });
+ }
+
+
/**
* TODO check comment
* Social Share Activation
From 7b84cbdede35145f164241edf42f5ceaa33182ae Mon Sep 17 00:00:00 2001
From: Felix
Date: Wed, 9 Dec 2015 11:33:29 +0100
Subject: [PATCH 06/17] FEATURE introduce FeedbackService
---
src/services/FeedbackService.js | 127 ++++++++++++++++++++++++++++++++
1 file changed, 127 insertions(+)
create mode 100644 src/services/FeedbackService.js
diff --git a/src/services/FeedbackService.js b/src/services/FeedbackService.js
new file mode 100644
index 0000000..3054f0e
--- /dev/null
+++ b/src/services/FeedbackService.js
@@ -0,0 +1,127 @@
+/**
+ * Licensed under AGPL v3
+ * (https://github.com/plentymarkets/plenty-cms-library/blob/master/LICENSE)
+ * =====================================================================================
+ * @copyright Copyright (c) 2015, plentymarkets GmbH (http://www.plentymarkets.com)
+ * @author Felix Dausch
+ * =====================================================================================
+ */
+
+/**
+ * @module Services
+ */
+(function($, pm) {
+
+ pm.service('FeedbackService', function( API ) {
+
+ return {
+ getFeedbacks: getFeedbacks,
+ addFeedback: addFeedback,
+ ArticleTypes: articleTypes(),
+ FeedbackTypes: feedbackTypes()
+ };
+
+ /*
+ FeedbackService
+ .getFeedbacks().between('2014-12-03', '2015-07-01')
+ .for( FeedbackService.ArticleTypes.ITEM, 2732, FeedbackService.FeedbackTypes.COMMENTS_ONLY );
+ */
+ function getFeedbacks() {
+ var feedbackInterval = {
+ dateStart: null,
+ dateEnd: null
+ };
+
+ return {
+ between: setFeedbackInterval,
+ for: listFeedbacks
+ };
+
+ function setFeedbackInterval( start, end ) {
+ feedbackInterval.dateStart = start;
+ feedbackInterval.dateEnd = end;
+ return this;
+ }
+
+ function listFeedbacks( articleType, referenceId, feedbackType ) {
+
+ var params = {
+ ReferenceId: referenceId,
+ FromDate: feedbackInterval.dateStart,
+ ToDate: feedbackInterval.dateEnd,
+ FeedbackType: feedbackType || feedbackTypes().COMMENTS_AND_RATINGS
+ };
+ return API.get( '/rest/feedback/'+articleType+'/', params );
+
+ }
+ }
+
+ /*
+ FeedbackService
+ .addFeedback()
+ .withRating( 5 )
+ .withComment( 'Hallo' )
+ .withAuthor( 'Felix', 'felix.dausch@plentymarkets.com', 123456 )
+ .to( FeedbackService.ArticleTypes.ITEM, 2732 );
+ */
+ function addFeedback() {
+
+ var params = {
+ Rating: 1.0,
+ Text: '',
+ Author: '',
+ Email: '',
+ CustomerId: 0
+ };
+
+ return {
+ withRating: withRating,
+ withComment: withComment,
+ withAuthor: withAuthor,
+ to: sendFeedback
+ };
+
+ function withRating( rating ) {
+ params.Rating = rating;
+ return this;
+ }
+
+ function withComment( comment ) {
+ params.Text = comment;
+ return this;
+ }
+
+ function withAuthor( author, mail, customerID ) {
+ params.Author = author;
+ if( !!mail ) params.Email = mail;
+ if( !!customerID ) params.CustomerId = customerID;
+ return this;
+ }
+
+ function sendFeedback( articleType, referenceId ) {
+ return API.post( '/rest/feedback/'+articleType+'/', params );
+
+ }
+
+ }
+
+ function feedbackTypes() {
+ return {
+ COMMENTS_ONLY: 'comments_only',
+ RATINGS_ONLY: 'ratings_only',
+ COMMENTS_AND_RATINGS: 'comments_with_ratings'
+ }
+ }
+
+ function articleTypes() {
+ return {
+ ITEM: 'item',
+ CATEGORY: 'category',
+ BLOG: 'blog'
+ }
+ }
+
+
+
+ }, ['APIFactory']);
+}(jQuery, PlentyFramework));
\ No newline at end of file
From 03dde143b1e9ab5177c7694cceb36b7b5847f2ab Mon Sep 17 00:00:00 2001
From: Maximilian Lauterbach
Date: Wed, 9 Dec 2015 12:03:08 +0100
Subject: [PATCH 07/17] fixed variable name for PostFinder
---
dist/plentymarketsCMStools-1.0.1.js | 6195 +++++++++++++++++++++++++++
src/services/CheckoutService.js | 2 +-
2 files changed, 6196 insertions(+), 1 deletion(-)
create mode 100644 dist/plentymarketsCMStools-1.0.1.js
diff --git a/dist/plentymarketsCMStools-1.0.1.js b/dist/plentymarketsCMStools-1.0.1.js
new file mode 100644
index 0000000..85181f0
--- /dev/null
+++ b/dist/plentymarketsCMStools-1.0.1.js
@@ -0,0 +1,6195 @@
+(function defineMustache(global,factory){if(typeof exports==="object"&&exports&&typeof exports.nodeName!=="string"){factory(exports)}else if(typeof define==="function"&&define.amd){define(["exports"],factory)}else{global.Mustache={};factory(Mustache)}})(this,function mustacheFactory(mustache){var objectToString=Object.prototype.toString;var isArray=Array.isArray||function isArrayPolyfill(object){return objectToString.call(object)==="[object Array]"};function isFunction(object){return typeof object==="function"}function typeStr(obj){return isArray(obj)?"array":typeof obj}function escapeRegExp(string){return string.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g,"\\$&")}function hasProperty(obj,propName){return obj!=null&&typeof obj==="object"&&propName in obj}var regExpTest=RegExp.prototype.test;function testRegExp(re,string){return regExpTest.call(re,string)}var nonSpaceRe=/\S/;function isWhitespace(string){return!testRegExp(nonSpaceRe,string)}var entityMap={"&":"&","<":"<",">":">",'"':""","'":"'","/":"/"};function escapeHtml(string){return String(string).replace(/[&<>"'\/]/g,function fromEntityMap(s){return entityMap[s]})}var whiteRe=/\s*/;var spaceRe=/\s+/;var equalsRe=/\s*=/;var curlyRe=/\s*\}/;var tagRe=/#|\^|\/|>|\{|&|=|!/;function parseTemplate(template,tags){if(!template)return[];var sections=[];var tokens=[];var spaces=[];var hasTag=false;var nonSpace=false;function stripSpace(){if(hasTag&&!nonSpace){while(spaces.length)delete tokens[spaces.pop()]}else{spaces=[]}hasTag=false;nonSpace=false}var openingTagRe,closingTagRe,closingCurlyRe;function compileTags(tagsToCompile){if(typeof tagsToCompile==="string")tagsToCompile=tagsToCompile.split(spaceRe,2);if(!isArray(tagsToCompile)||tagsToCompile.length!==2)throw new Error("Invalid tags: "+tagsToCompile);openingTagRe=new RegExp(escapeRegExp(tagsToCompile[0])+"\\s*");closingTagRe=new RegExp("\\s*"+escapeRegExp(tagsToCompile[1]));closingCurlyRe=new RegExp("\\s*"+escapeRegExp("}"+tagsToCompile[1]))}compileTags(tags||mustache.tags);var scanner=new Scanner(template);var start,type,value,chr,token,openSection;while(!scanner.eos()){start=scanner.pos;value=scanner.scanUntil(openingTagRe);if(value){for(var i=0,valueLength=value.length;i0?sections[sections.length-1][4]:nestedTokens;break;default:collector.push(token)}}return nestedTokens}function Scanner(string){this.string=string;this.tail=string;this.pos=0}Scanner.prototype.eos=function eos(){return this.tail===""};Scanner.prototype.scan=function scan(re){var match=this.tail.match(re);if(!match||match.index!==0)return"";var string=match[0];this.tail=this.tail.substring(string.length);this.pos+=string.length;return string};Scanner.prototype.scanUntil=function scanUntil(re){var index=this.tail.search(re),match;switch(index){case-1:match=this.tail;this.tail="";break;case 0:match="";break;default:match=this.tail.substring(0,index);this.tail=this.tail.substring(index)}this.pos+=match.length;return match};function Context(view,parentContext){this.view=view;this.cache={".":this.view};this.parent=parentContext}Context.prototype.push=function push(view){return new Context(view,this)};Context.prototype.lookup=function lookup(name){var cache=this.cache;var value;if(cache.hasOwnProperty(name)){value=cache[name]}else{var context=this,names,index,lookupHit=false;while(context){if(name.indexOf(".")>0){value=context.view;names=name.split(".");index=0;while(value!=null&&index")value=this.renderPartial(token,context,partials,originalTemplate);else if(symbol==="&")value=this.unescapedValue(token,context);else if(symbol==="name")value=this.escapedValue(token,context);else if(symbol==="text")value=this.rawValue(token);if(value!==undefined)buffer+=value}return buffer};Writer.prototype.renderSection=function renderSection(token,context,partials,originalTemplate){var self=this;var buffer="";var value=context.lookup(token[1]);function subRender(template){return self.render(template,context,partials)}if(!value)return;if(isArray(value)){for(var j=0,valueLength=value.length;j\n" +
+ " {{#values}}\n" +
+ " \n" +
+ " \n" +
+ " {{.}}\n" +
+ " \n" +
+ " \n" +
+ " {{/values}}\n" +
+ "";
+
+TemplateCache["addressSuggestions/postFinder.html"] = "{{#addresses}}\n" +
+ "\n" +
+ "
\n" +
+ " \n" +
+ "
\n" +
+ "
\n" +
+ "{{/addresses}}\n" +
+ "";
+
+TemplateCache["error/errorMessage.html"] = "\n" +
+ " Code {{code}}:\n" +
+ " {{{message}}}\n" +
+ "
\n" +
+ "";
+
+TemplateCache["error/errorPopup.html"] = "\n" +
+ "
\n" +
+ "
\n" +
+ "
\n" +
+ "
\n" +
+ "";
+
+TemplateCache["modal/modal.html"] = "\n" +
+ "
\n" +
+ "
\n" +
+ "\n" +
+ " {{#title}}\n" +
+ " \n" +
+ " {{/title}}\n" +
+ "\n" +
+ "
{{{content}}}
\n" +
+ "\n" +
+ " \n" +
+ "
\n" +
+ "
\n" +
+ "
\n" +
+ "";
+
+TemplateCache["waitscreen/waitscreen.html"] = "";
+
+/**
+ * Licensed under AGPL v3
+ * (https://github.com/plentymarkets/plenty-cms-library/blob/master/LICENSE)
+ * =====================================================================================
+ * @copyright Copyright (c) 2015, plentymarkets GmbH (http://www.plentymarkets.com)
+ * @author Felix Dausch
+ * =====================================================================================
+ */
+
+/**
+ * @module PlentyFramework
+ */
+(function( $ )
+{
+
+ /**
+ * Collection of uncompiled registered factories & services.
+ * See {{#crossLink "PlentyFramework/compile:method"}}.compile(){{/crossLink}}
+ * @attribute components
+ * @static
+ * @type {{factories: {}, services: {}}}
+ */
+ var components = {
+ factories : {},
+ services : {},
+ directives: {}
+ };
+
+ /**
+ * Framework providing client functions for plentymarkets Webshops.
+ * @class PlentyFramework
+ * @constructor
+ */
+ PlentyFramework = function()
+ {
+ };
+
+ var instance = null;
+ PlentyFramework.getInstance = function()
+ {
+ instance = instance || new PlentyFramework();
+ return instance;
+ };
+
+ /**
+ * Customizable controls for partials will be injected here.
+ * (e.g. Modal)
+ * @attribute
+ * @static
+ * @type {object}
+ */
+ PlentyFramework.partials = {};
+
+ /**
+ * Collection of registered global variables
+ * @attribute
+ * @static
+ * @type {object}
+ */
+ PlentyFramework.globals = {};
+
+ /**
+ * Set a global variable.
+ * @function setGlobal
+ * @static
+ * @param {string} identifier A unique identifier to reference this variable
+ * @param {*} value The value to set
+ * @return {*} The value
+ */
+ PlentyFramework.setGlobal = function( identifier, value )
+ {
+ if ( PlentyFramework.globals.hasOwnProperty( identifier ) )
+ {
+ console.error( 'Global variable "' + identifier + '" already exists and cannot be overridden.' );
+ return null;
+ }
+
+ PlentyFramework.globals[identifier] = value;
+
+ return PlentyFramework.globals[identifier];
+ };
+
+ /**
+ * Get the value of a global variable or undefined if not exists
+ * @function getGlobal
+ * @static
+ * @param identifier The identifier of the requested variable
+ * @return {*} The value of the variable
+ */
+ PlentyFramework.getGlobal = function( identifier )
+ {
+ return PlentyFramework.globals[identifier];
+ };
+
+ /**
+ * Collection of registered directives
+ * @type {Array}
+ * @static
+ */
+ PlentyFramework.directives = {};
+
+ /**
+ * Register directive. Directives can be bound to dynamically added nodes by calling pm.bindPlentyFunctions();
+ * @function directive
+ * @static
+ * @param {string} selector jQuery selector of the DOM-elements to bind the directive to
+ * @param {function} callback Function to add directives behaviour
+ * @param {Array} dependencies List of required services. Services will be passed to callback function
+ * @param {boolean} allowDuplicates Defines if a directive can be bound to the same element multiple times
+ * @return {object} The created directive
+ */
+ PlentyFramework.directive = function( directiveName, directiveFunctions, dependencies )
+ {
+ // Catch type mismatching for 'directiveName'
+ if ( typeof directiveName !== 'string' )
+ {
+ console.error( "Type mismatch: Expect first parameter to be a 'string', '" + typeof directiveName + "' given." );
+ return;
+ }
+
+ // Catch type mismatching for 'serviceFunctions'
+ if ( typeof directiveFunctions !== 'function' )
+ {
+ console.error( "Type mismatch: Expect second parameter to be a 'function', '" + typeof directiveFunctions + "' given." );
+ return;
+ }
+
+ dependencies = dependencies || [];
+
+ components.directives[directiveName] = {
+ name : directiveName,
+ dependencies: dependencies,
+ compile : function()
+ {
+ var params = PlentyFramework.resolveServices( dependencies );
+ PlentyFramework.directives[directiveName] = directiveFunctions.apply( null, params );
+ }
+ };
+ };
+
+ /**
+ * Bind registered directives.
+ * @function bindDirectives
+ * @param {string} [directiveSelector] restrict binding to elements matching this selector
+ */
+ PlentyFramework.prototype.bindDirectives = function( rootElement )
+ {
+
+ rootElement = rootElement || 'html';
+
+ $( rootElement ).find( '[data-plenty]' ).each( function( i, element )
+ {
+
+ var directives = parseDirectives( $( element ).attr( 'data-plenty' ), $( element ) );
+
+ if ( directives.length <= 0 )
+ {
+ // continue
+ return;
+ }
+
+ addCustomEvents( element );
+
+ for ( var i = 0; i < directives.length; i++ )
+ {
+ var directive = directives[i];
+ if ( !!PlentyFramework.directives[directive.class] && PlentyFramework.directives.hasOwnProperty( directive.class ) )
+ {
+
+ var callback = PlentyFramework.directives[directive.class][directive.method];
+ if ( !!callback && typeof callback == "function" )
+ {
+
+ if ( directive.event == "ready" )
+ {
+ callback.apply( null, directive.params );
+ }
+ else
+ {
+ bindEventCallback( $( element ), directive.event, callback, directive.params );
+ /*
+ $( element ).on( directive.event, function( e )
+ {
+ directive = injectEvent( directive, e );
+ return callback.apply( null, directive.params );
+ } );
+ */
+ }
+
+ }
+ else
+ {
+ console.error( "Method not found: " + directive.method + " in " + directive.class );
+ }
+
+ }
+ else
+ {
+ console.error( "Directive not found: " + directive.class );
+ }
+ }
+ } );
+
+ $( document ).trigger( 'initPartials', rootElement );
+ };
+
+ var eventStack = [];
+
+ PlentyFramework.getRecentEvent = function( eventType )
+ {
+ var lastEventIdx = eventStack.length - 1;
+ if( !eventType )
+ {
+ return eventStack[ lastEventIdx ];
+ }
+ else
+ {
+ for( var i = lastEventIdx; i >= 0; i-- )
+ {
+ if( eventType == eventStack[i].type )
+ {
+ return eventStack[i];
+ }
+ }
+ }
+
+ return null;
+
+ };
+
+ PlentyFramework.pushEvent = function( event )
+ {
+ eventStack.push( event );
+ };
+
+
+ /**
+ * Bind event to element by eventType.
+ * If cms says "click:Foo.bar(this, event)" eventType is "click".
+ *
+ * @param $elem - jQuery object on which event was triggered
+ * @param eventType - type of event
+ * @param callback - callback function of directive [example: "bar(this, event)"]
+ * @param params - list of parameters for callback function.
+ */
+ function bindEventCallback( $elem, eventType, callback, params )
+ {
+ $elem.on( eventType, function( event )
+ {
+ eventStack.push( event );
+ return callback.apply( null, params );
+ } );
+ }
+
+ function addCustomEvents( element )
+ {
+
+ var $elem = $( element );
+
+ if( $elem.is('input[type="checkbox"]') )
+ {
+ $elem.on('change', function() {
+
+ if( $elem.is(':checked') )
+ {
+ $elem.trigger('check');
+ }
+ else
+ {
+ $elem.trigger('uncheck');
+ }
+ });
+ }
+
+ if( $elem.is('input[type="radio"]') )
+ {
+ $elem.on('change', function() {
+
+ var radioGroup = $elem.attr('name');
+
+ $( 'input[type="radio"][name="' + radioGroup + '"]' ).each(function( i, radio ) {
+ var $radio = $( radio );
+ if( $radio.is(':checked') )
+ {
+ $radio.trigger('check');
+ }
+ else
+ {
+ $radio.trigger('uncheck');
+ }
+
+ });
+
+ });
+ }
+ }
+
+ function parseDirectives( input, thisValue )
+ {
+ var directivePattern = /^(([\w]+):)?([\w]+)\.([\w]+)(\((.*)\))?$/;
+ var expressions = input.split( ';' );
+ var directives = [];
+
+ for ( var i = 0; i < expressions.length; i++ )
+ {
+ var expression = expressions[i].trim();
+
+ if ( !expression )
+ {
+ continue;
+ }
+
+ if ( !directivePattern.test( expression ) )
+ {
+ // console.warn( "Invalid directive: " + expression );
+ continue;
+ }
+
+ var match = expression.match( directivePattern );
+
+ if ( !match[3] || match[3].length <= 0 )
+ {
+ console.error( "Cannot parse '" + expression + "': Class name not set." );
+ continue;
+ }
+
+ if ( !match[4] || match[4].length <= 0 )
+ {
+ console.error( "Cannot parse '" + expression + "': Method not set." );
+ continue;
+ }
+
+ var directive = {
+ event : match[2] || 'ready',
+ class : match[3],
+ method: match[4],
+ params: []
+ };
+
+ if ( !!match[6] && match[6].length > 0 )
+ {
+ var params = match[6].match( /(['][^']+['])|([\w-]+)|(["][^"]+["])/g );
+ for ( var j = 0; j < params.length; j++ )
+ {
+ var param = params[j].trim();
+ if ( !isNaN( parseFloat( param ) ) )
+ {
+ directive.params.push( parseFloat( param ) );
+ }
+ else if ( param.toLowerCase() == 'true' )
+ {
+ directive.params.push( true );
+ }
+ else if ( param.toLowerCase() == 'false' )
+ {
+ directive.params.push( false );
+ }
+ else if ( param.toLowerCase() == 'this' )
+ {
+ directive.params.push( thisValue );
+ }
+ else
+ {
+ directive.params.push( param.replace( /^['"]|['"]$/g, '' ) );
+ }
+ }
+ }
+
+ directives.push( directive );
+
+ }
+ return directives;
+ }
+
+ /**
+ * Register a new service
+ * @function service
+ * @static
+ * @param {string} serviceName Unique identifier of the service to get/ create
+ * @param {function} serviceFunctions Callback containing all public functions of this service.
+ * @param {Array} [dependencies] Identifiers of required services to inject in serviceFunctions
+ * @return {object} The object described in serviceFunctions(). Can be received via
+ * PlentyFramework.[serviceName]
+ */
+ PlentyFramework.service = function( serviceName, serviceFunctions, dependencies )
+ {
+
+ // Catch type mismatching for 'serviceName'
+ if ( typeof serviceName !== 'string' )
+ {
+ console.error( "Type mismatch: Expect first parameter to be a 'string', '" + typeof serviceName + "' given." );
+ return;
+ }
+
+ // Catch type mismatching for 'serviceFunctions'
+ if ( typeof serviceFunctions !== 'function' )
+ {
+ console.error( "Type mismatch: Expect second parameter to be a 'function', '" + typeof serviceFunctions + "' given." );
+ return;
+ }
+
+ dependencies = dependencies || [];
+
+ components.services[serviceName] = {
+ name : serviceName,
+ dependencies: dependencies,
+ compile : function()
+ {
+ var params = PlentyFramework.resolveFactories( dependencies );
+ PlentyFramework.prototype[serviceName] = serviceFunctions.apply( null, params );
+ }
+ };
+
+ };
+
+ /**
+ * Returns an array containing required factories given by string identifier
+ * @function resolveServices
+ * @static
+ * @private
+ * @param {Array} dependencies Names of required factories
+ * @return {Array} Objects to apply to callback function
+ */
+ PlentyFramework.resolveServices = function( dependencies )
+ {
+ var compiledServices = [];
+
+ $.each( dependencies, function( j, dependency )
+ {
+
+ // factory not found: try to compile dependent factory first
+ if ( !PlentyFramework.prototype.hasOwnProperty( dependency ) )
+ {
+ if ( components.services.hasOwnProperty( dependency ) )
+ {
+ components.services[dependency].compile();
+ }
+ else
+ {
+ console.error( 'Cannot inject Service "' + dependency + '": Service not found.' );
+ return false;
+ }
+ }
+ var service = PlentyFramework.prototype[dependency];
+ compiledServices.push( service );
+ } );
+
+ return compiledServices;
+ };
+
+ /**
+ * Collection of compiled factories
+ * @attribute factories
+ * @static
+ * @type {object}
+ */
+ PlentyFramework.factories = {};
+
+ /**
+ * Register a new factory
+ * @function factory
+ * @static
+ * @param {string} factoryName A unique name of the new factory
+ * @param {function} factoryFunctions The function describing the factory
+ * @param {Array} dependencies List of required factories to inject
+ */
+ PlentyFramework.factory = function( factoryName, factoryFunctions, dependencies )
+ {
+
+ // Catch type mismatching for 'serviceName'
+ if ( typeof factoryName !== 'string' )
+ {
+ console.error( "Type mismatch: Expect first parameter to be a 'string', '" + typeof factoryName + "' given." );
+ return;
+ }
+
+ // Catch type mismatching for 'serviceFunctions'
+ if ( typeof factoryFunctions !== 'function' )
+ {
+ console.error( "Type mismatch: Expect second parameter to be a 'function', '" + typeof factoryFunctions + "' given." );
+ return;
+ }
+
+ dependencies = dependencies || [];
+ components.factories[factoryName] = {
+ name : factoryName,
+ dependencies: dependencies,
+ compile : function()
+ {
+ var params = PlentyFramework.resolveFactories( dependencies );
+ PlentyFramework.factories[factoryName] = factoryFunctions.apply( null, params );
+ }
+ };
+
+ };
+
+ /**
+ * Returns an array containing required factories given by string identifier
+ * @function resolveFactories
+ * @static
+ * @private
+ * @param {Array} dependencies Names of required factories
+ * @return {Array} Objects to apply to callback function
+ */
+ PlentyFramework.resolveFactories = function( dependencies )
+ {
+ var compiledFactories = [];
+
+ $.each( dependencies, function( j, dependency )
+ {
+
+ // factory not found: try to compile dependent factory first
+ if ( !PlentyFramework.factories.hasOwnProperty( dependency ) )
+ {
+ if ( components.factories.hasOwnProperty( dependency ) )
+ {
+ components.factories[dependency].compile();
+ }
+ else
+ {
+ console.error( 'Cannot inject Factory "' + dependency + '": Factory not found.' );
+ return false;
+ }
+ }
+ var factory = PlentyFramework.factories[dependency];
+ compiledFactories.push( factory );
+ } );
+
+ return compiledFactories;
+ };
+
+ /**
+ * Renders html template. Will provide given data to templates scope.
+ * Uses Mustache syntax for data-binding.
+ * @function compileTemplate
+ * @static
+ * @param {String} template relative path to partials template to load. Base path = '/src/partials/'
+ * @param {Object} data data to privide to templates scope.
+ * @returns {String} The rendered html string
+ */
+ PlentyFramework.compileTemplate = function( template, data )
+ {
+ data = data || {};
+ data.translate = function()
+ {
+ return function( text, render )
+ {
+ return render( PlentyFramework.translate( text ) );
+ };
+ };
+ return Mustache.render( TemplateCache[template], data );
+ };
+
+ /**
+ * The path on the server where the script is located in.
+ * @attribute
+ * @static
+ * @type {String}
+ */
+ PlentyFramework.scriptPath = '';
+
+ /**
+ * Collection of locale strings will be injected here after reading language file.
+ * @attribute
+ * @static
+ * @type {Object}
+ */
+ PlentyFramework.Strings = {};
+
+ /**
+ * Load language file containing translations of locale strings.
+ * @function loadLanguageFile
+ * @static
+ * @param fileName relative path to language file.
+ */
+ PlentyFramework.loadLanguageFile = function( fileName )
+ {
+ $.get( PlentyFramework.scriptPath + fileName ).done( function( response )
+ {
+ PlentyFramework.Strings = response;
+ } );
+ };
+
+ /**
+ * Try to get locale translation of given string.
+ * Render translated string using Mustache syntax
+ * if additional parameters are given.
+ * @function translate
+ * @static
+ * @param {String} string The string to translate
+ * @param {Object} [params] additional data for rendering
+ * @returns {String} The translation of the given string if found. Otherwise returns the original string.
+ */
+ PlentyFramework.translate = function( string, params )
+ {
+ var localeString;
+ if ( PlentyFramework.Strings.hasOwnProperty( string ) )
+ {
+ localeString = PlentyFramework.Strings[string];
+ }
+ else
+ {
+ localeString = string;
+ console.warn( 'No translation found for "' + localeString + '".' );
+ }
+
+ if ( !!params )
+ {
+ localeString = Mustache.render( localeString, params );
+ }
+
+ return localeString;
+
+ };
+
+ /**
+ * Compile registered factories & services
+ * @function compile
+ * @static
+ */
+ PlentyFramework.compile = function()
+ {
+
+ for ( var factory in components.factories )
+ {
+ if ( !PlentyFramework.factories.hasOwnProperty( factory ) )
+ {
+ components.factories[factory].compile();
+ }
+ }
+
+ for ( var service in components.services )
+ {
+ if ( !PlentyFramework.prototype.hasOwnProperty( service ) )
+ {
+ components.services[service].compile();
+ }
+ }
+
+ for ( var directive in components.directives )
+ {
+ if ( !PlentyFramework.directives.hasOwnProperty( directive ) )
+ {
+ components.directives[directive].compile();
+ }
+ }
+
+ var scripts = document.getElementsByTagName( 'SCRIPT' );
+ if ( scripts.length > 0 )
+ {
+ PlentyFramework.scriptPath = scripts[scripts.length - 1].src.match( /(.*)\/(.*)\.js(\?\S*)?$/ )[1];
+ }
+
+ };
+
+}( jQuery ));
+
+
+
+
+PlentyFramework.cssClasses = {
+
+ active: "active"
+
+};
+(function( $, pm )
+{
+
+ pm.partials.Error = {
+
+ /**
+ * Will be called, after the error popup was created and injected in DOM.
+ * @param {HTMLElement} popup The injected element of the popup
+ */
+ init: function( popup )
+ {
+ $( popup ).find( '.close' ).click( function()
+ {
+ popup.hide();
+ popup.find( '.plentyErrorBoxInner' ).html( '' );
+ } );
+ },
+
+ /**
+ * Will be called for each thrown error. Has to be injected in DOM manually.
+ * @param {HTMLElement} popup The error popup element
+ * @param {HTMLElement} error The error message element
+ */
+ addError: function( popup, error )
+ {
+ var errorCode = $( error ).attr( 'data-plenty-error-code' );
+
+ if ( $( popup ).find( '[data-plenty-error-code="' + errorCode + '"]' ).length <= 0 )
+ {
+ $( popup ).find( '.plentyErrorBoxInner' ).append( error );
+ }
+ },
+
+ /**
+ * Will be called, after initialization and injection of all errors
+ * @param {HTMLElement} popup The error popup element
+ */
+ show: function( popup )
+ {
+ $( popup ).show();
+ }
+
+ }
+
+})( jQuery, PlentyFramework );
+(function( $, pm )
+{
+
+ pm.partials.Modal = {
+
+ /**
+ * Will be called after a new modal was created and injected into DOM
+ * @param {HTMLElement} element The injected modal element
+ * @param {Modal} modal The instance of the current modal
+ */
+ init: function( element, modal )
+ {
+ element.on( 'hidden.bs.modal', function()
+ {
+ modal.hide();
+ element.remove();
+ } );
+
+ if ( modal.timeout > 0 )
+ {
+ element.on( 'hide.bs.modal', modal.stopTimeout );
+ element.find( '.modal-content' ).hover( function()
+ {
+ modal.pauseTimeout();
+ }, function()
+ {
+ if ( element.is( '.in' ) )
+ {
+ modal.continueTimeout();
+ }
+ } );
+ }
+ },
+
+ /**
+ * Will be called if a Modal requests to show.
+ * @param {HTMLElement} element The injected modal element
+ */
+ show: function( element )
+ {
+ element.modal( 'show' );
+ },
+
+ /**
+ * Will be called if a Modal requests to hide.
+ * @param {HTMLElement} element The injected modal element
+ */
+ hide: function( element )
+ {
+ element.modal( 'hide' );
+ },
+
+ /**
+ * Detect if a given HTML string contains a modal
+ * @param {HTMLElement} html the element to search a modal in.
+ * @returns {boolean} true if a modal was found
+ */
+ isModal: function( html )
+ {
+ return $( html ).filter( '.modal' ).length + $( html ).find( '.modal' ).length > 0;
+ },
+
+ /**
+ * Filter a modal from a given HTML string
+ * @param {HTMLElement} html the element to get a modal from.
+ * @returns {HTMLElement} the filtered modal element
+ */
+ getModal: function( html )
+ {
+ var modal = $( html );
+ if ( modal.length > 1 )
+ {
+ modal = $( html ).filter( '.modal' ) || $( html ).find( '.modal' );
+ }
+
+ return modal;
+ }
+
+ };
+
+}( jQuery, PlentyFramework ));
+(function( $ )
+{
+
+ $( document ).on( 'initPartials', function( e, root )
+ {
+
+ $( root ).find( '[data-toggle="tooltip"]' ).tooltip( {
+ container: 'body'
+ } );
+
+ } );
+
+})( jQuery );
+(function( $, pm )
+{
+
+ pm.partials.WaitScreen = {
+
+ /**
+ * Will be called if the wait screen should be shown
+ * @param {HTMLElement} element The wait screen element
+ */
+ show: function( element )
+ {
+ element.addClass( 'in' );
+ },
+
+ /**
+ * Will be called if the wait screen should be hidden
+ * @param {HTMLElement} element The wait screen element
+ */
+ hide: function( element )
+ {
+ element.removeClass( 'in' );
+ }
+
+ };
+
+})( jQuery, PlentyFramework );
+/**
+ * Licensed under AGPL v3
+ * (https://github.com/plentymarkets/plenty-cms-library/blob/master/LICENSE)
+ * =====================================================================================
+ * @copyright Copyright (c) 2015, plentymarkets GmbH (http://www.plentymarkets.com)
+ * @author Felix Dausch
+ * =====================================================================================
+ */
+
+/**
+ * @module Factories
+ */
+(function( $, pm )
+{
+
+ /**
+ * Handles requests to ReST API. Provides a {{#crossLink "APIFactory/handleError:method"}}default
+ * error-handling{{/crossLink}}. Request parameters will be parsed to json internally
+ * Requires:
+ *
+ * - {{#crossLink "UIFactory"}}UIFactory{{/crossLink}}
+ *
+ * @class APIFactory
+ * @static
+ */
+ pm.factory( 'APIFactory', function( UI )
+ {
+
+ return {
+ get : _get,
+ post : _post,
+ put : _put,
+ delete: _delete,
+ idle : _idle
+ };
+
+ /**
+ * Is called by default if a request failed.
+ * Can be prevented by setting the requests last parameter to false.
+ *
+ * @function handleError
+ * @private
+ *
+ * @param {object} jqXHR jQuery
+ * deferred Object
+ */
+ function handleError( jqXHR )
+ {
+ try
+ {
+ var responseText = $.parseJSON( jqXHR.responseText );
+ UI.printErrors( responseText.error.error_stack );
+ }
+ catch ( e )
+ {
+ UI.throwError( jqXHR.status, jqXHR.statusText );
+ }
+ }
+
+ /**
+ * Sends a GET request to ReST-API
+ *
+ * @function get
+ *
+ * @param {string} url The URL to send the request to
+ * @param {object} params The data to append to requests body. Will be converted to JSON
+ * internally
+ * @param {boolean} [ignoreErrors=false] disable/ enable defaults error handling
+ * @param {boolean} [runInBackground=false] show wait screen while request is in progress.
+ * @return {object} jQuery
+ * deferred Object
+ */
+ function _get( url, params, ignoreErrors, runInBackground, sync )
+ {
+
+ if ( !runInBackground )
+ {
+ UI.showWaitScreen();
+ }
+
+ return $.ajax(
+ url,
+ {
+ type : 'GET',
+ data: params,
+ dataType: 'json',
+ async : !sync,
+ error : function( jqXHR )
+ {
+ if ( !ignoreErrors )
+ {
+ handleError( jqXHR )
+ }
+ }
+ }
+ ).always( function()
+ {
+ if ( !runInBackground )
+ {
+ UI.hideWaitScreen();
+ }
+ } );
+
+ }
+
+ /**
+ * Sends a POST request to ReST-API
+ *
+ * @function post
+ *
+ * @param {string} url The URL to send the request to
+ * @param {object} data The data to append to requests body. Will be converted to JSON
+ * internally
+ * @param {boolean} [ignoreErrors=false] disable/ enable defaults error handling
+ * @param {boolean} [runInBackground=false] show wait screen while request is in progress.
+ * @return {object} jQuery
+ * deferred Object
+ */
+ function _post( url, data, ignoreErrors, runInBackground )
+ {
+
+ var params = {
+ type : 'POST',
+ dataType: 'json',
+ error : function( jqXHR )
+ {
+ if ( !ignoreErrors )
+ {
+ handleError( jqXHR )
+ }
+ }
+ };
+
+ if ( !!data && data.isFile )
+ {
+ params.cache = data.cache;
+ params.processData = data.processData;
+ params.data = data.data;
+ params.contentType = false;
+ }
+ else
+ {
+ params.data = JSON.stringify( data );
+ params.contentType = 'application/json';
+ }
+
+ if ( !runInBackground )
+ {
+ UI.showWaitScreen();
+ }
+
+ return $.ajax(
+ url, params
+ ).always( function()
+ {
+ if ( !runInBackground )
+ {
+ UI.hideWaitScreen();
+ }
+ } );
+ }
+
+ /**
+ * Sends a PUT request to ReST-API
+ *
+ * @function put
+ *
+ * @param {string} url The URL to send the request to
+ * @param {object} data The data to append to requests body. Will be converted to JSON
+ * internally
+ * @param {boolean} [ignoreErrors=false] disable/ enable defaults error handling
+ * @param {boolean} [runInBackground=false] show wait screen while request is in progress.
+ * @return {object} jQuery
+ * deferred Object
+ */
+ function _put( url, data, ignoreErrors, runInBackground )
+ {
+
+ if ( !runInBackground )
+ {
+ UI.showWaitScreen();
+ }
+
+ return $.ajax(
+ url,
+ {
+ type : 'PUT',
+ data: JSON.stringify( data ),
+ dataType: 'json',
+ contentType: 'application/json',
+ error : function( jqXHR )
+ {
+ if ( !ignoreErrors )
+ {
+ handleError( jqXHR )
+ }
+ }
+ }
+ ).always( function()
+ {
+ if ( !runInBackground )
+ {
+ UI.hideWaitScreen();
+ }
+ } );
+
+ }
+
+ /**
+ * Sends a DELETE request to ReST-API
+ *
+ * @function delete
+ *
+ * @param {string} url The URL to send the request to
+ * @param {object} data The data to append to requests body. Will be converted to JSON
+ * internally
+ * @param {boolean} [ignoreErrors=false] disable/ enable defaults error handling
+ * @param {boolean} [runInBackground=false] show wait screen while request is in progress.
+ * @returns {object} jQuery
+ * deferred Object
+ */
+ function _delete( url, data, ignoreErrors, runInBackground )
+ {
+
+ if ( !runInBackground )
+ {
+ UI.showWaitScreen();
+ }
+
+ return $.ajax(
+ url,
+ {
+ type : 'DELETE',
+ data: JSON.stringify( data ),
+ dataType: 'json',
+ contentType: 'application/json',
+ error : function( jqXHR )
+ {
+ if ( !ignoreErrors )
+ {
+ handleError( jqXHR )
+ }
+ }
+ }
+ ).always( function()
+ {
+ if ( !runInBackground )
+ {
+ UI.hideWaitScreen();
+ }
+ } );
+
+ }
+
+ /**
+ * Get a idle request doing nothing for chaining methods
+ * @returns {object} jQuery
+ * deferred Object
+ */
+ function _idle()
+ {
+ return $.Deferred().resolve();
+ }
+
+ }, ['UIFactory'] );
+}( jQuery, PlentyFramework ));
+/**
+ * Licensed under AGPL v3
+ * (https://github.com/plentymarkets/plenty-cms-library/blob/master/LICENSE)
+ * =====================================================================================
+ * @copyright Copyright (c) 2015, plentymarkets GmbH (http://www.plentymarkets.com)
+ * @author Felix Dausch
+ * =====================================================================================
+ */
+
+/**
+ * @module Factories
+ */
+(function( pm )
+{
+
+ /**
+ * Provide methods for receiving layout containers, layout parameters
+ * or category content from API
+ * Requires:
+ *
+ * - {{#crossLink "APIFactory"}}APIFactory{{/crossLink}}
+ *
+ * @class CMSFactory
+ * @static
+ */
+ pm.factory( 'CMSFactory', function( API )
+ {
+
+ return {
+ getContainer : getContainer,
+ getParams : getParams,
+ getCategoryContent: getCategoryContent
+ };
+
+ /**
+ * Prepare the request to receive HTML-Content from CMS
+ * @function getContainer
+ * @param {string} containerName The Layoutcontainer to receive.
+ * @param {object} params Additional GET-parameters.
+ * @returns {object} The prepared request. Call .from( layoutGroup )
to specify the location in
+ * the CMS
+ * (e.g. 'Checkout')
+ * @example
+ * CMSFactory.getContainer( 'CheckoutTotals' ).from( 'Checkout' )
+ * .done(function( response ) {
+ * // container content
+ * var html = response.data[0]
+ * });
+ */
+ function getContainer( containerName, params )
+ {
+
+ function from( layoutGroup )
+ {
+ return API.get( '/rest/' + layoutGroup.toLowerCase() + '/container_' + containerName.toLowerCase() + '/', params );
+ }
+
+ return {
+ from: from
+ }
+
+ }
+
+ /**
+ * Prepare the request to receive Layout parameters for a template
+ * @function getParams
+ * @param {string} containerName The Layoutcontainer to receive the parameteres of.
+ * @param {object} params Additional GET-parameters.
+ * @returns {object} The prepared request. Call .from( layoutGroup )
to specify the
+ * location in the CMS
+ * (e.g. 'ItemView')
+ * @example
+ * CMSFactory.getParams( 'BasketItemsList' ).from( 'ItemView' )
+ * .done(function( response ) {
+ * // BasketItems
+ * var items = response.data;
+ * });
+ */
+ function getParams( containerName, params )
+ {
+
+ function from( layoutGroup )
+ {
+ return API.get( '/rest/' + layoutGroup.toLowerCase() + '/' + containerName.toLowerCase() + '/', params );
+ }
+
+ return {
+ from: from
+ }
+ }
+
+ /**
+ * Get the content of a category specified by its ID
+ * @function getCategoryContent
+ * @param {number} categoryID The ID of the category to get the content from
+ * @returns {object} jQuery deferred
+ * Object
+ */
+ function getCategoryContent( categoryID )
+ {
+
+ return API.get( '/rest/categoryview/categorycontentbody/?categoryID=' + categoryID );
+ }
+
+ }, ['APIFactory'] );
+}( PlentyFramework ));
+/**
+ * Licensed under AGPL v3
+ * (https://github.com/plentymarkets/plenty-cms-library/blob/master/LICENSE)
+ * =====================================================================================
+ * @copyright Copyright (c) 2015, plentymarkets GmbH (http://www.plentymarkets.com)
+ * @author Felix Dausch
+ * =====================================================================================
+ */
+
+/**
+ * @module Factories
+ */
+(function( pm )
+{
+
+ /**
+ * Holds checkout data for global access and provides methods
+ * for reloading content dynamically-
+ * Requires:
+ *
+ * - {{#crossLink "APIFactory"}}APIFactory{{/crossLink}}
+ * - {{#crossLink "CMSFactory"}}CMSFactory{{/crossLink}}
+ * - {{#crossLink "UIFactory"}}UIFactory{{/crossLink}}
+ *
+ * @class CheckoutFactory
+ * @static
+ */
+ pm.factory( 'CheckoutFactory', function( API, CMS, UI )
+ {
+
+ // data received from ReST API
+ var checkoutData;
+
+ // instance wrapped checkout object for global access
+ var checkout;
+
+ return {
+ getCheckout : getCheckout,
+ setCheckout : setCheckout,
+ loadCheckout : loadCheckout,
+ reloadContainer : reloadContainer,
+ reloadCatContent : reloadCatContent,
+ reloadItemContainer: reloadItemContainer
+ };
+
+ function Checkout()
+ {
+ return checkoutData;
+ }
+
+ /**
+ * Returns instance of wrapped checkout object
+ * @function getCheckout
+ * @returns {Checkout} Instance of checkout object
+ */
+ function getCheckout( copy )
+ {
+ if ( !checkout || !checkoutData )
+ {
+ loadCheckout( true );
+ }
+
+ if ( !!copy )
+ {
+ return $.extend( true, {}, checkoutData );
+ }
+ return checkout;
+ }
+
+ /**
+ * Receive global checkout data from ReST-API
+ * @function loadCheckout
+ * @return {object} jQuery deferred
+ * Object
+ */
+ function loadCheckout( sync )
+ {
+
+ return API.get( '/rest/checkout/', null, false, false, sync )
+ .done( function( response )
+ {
+ if ( !!response )
+ {
+ checkoutData = response.data;
+ checkout = new Checkout();
+ }
+ else
+ {
+ UI.throwError( 0, 'Could not receive checkout data [GET "/rest/checkout/" receives null value]' );
+ }
+ } );
+ }
+
+ /**
+ * Update checkout data on server
+ * @function setCheckout
+ * @return {object} jQuery deferred
+ * Object
+ */
+ function setCheckout()
+ {
+
+ return API.put( '/rest/checkout', checkout )
+ .done( function( response )
+ {
+ if ( !!response )
+ {
+ checkoutData = response.data;
+ checkout = new Checkout();
+ }
+ else
+ {
+ UI.throwError( 0, 'Could not receive checkout data [GET "/rest/checkout/" receives null value]' );
+ }
+ } );
+
+ }
+
+ /**
+ * Get layout container from server and replace received HTML
+ * in containers marked with data-plenty-checkout-template="..."
+ * @function reloadContainer
+ * @param {string} container Name of the template to load from server
+ * @return {object} jQuery deferred
+ * Object
+ */
+ function reloadContainer( container )
+ {
+
+ return CMS.getContainer( "checkout" + container ).from( 'checkout' )
+ .done( function( response )
+ {
+ $( '[data-plenty-checkout-template="' + container + '"]' )
+ .each( function( i, elem )
+ {
+ $( elem ).html( response.data[0] );
+ pm.getInstance().bindDirectives( elem );
+ $( window ).trigger( 'contentChanged' );
+ } );
+ } );
+ }
+
+ /**
+ * Get category content from server and replace received HTML
+ * in containers marked with data-plenty-checkout-catcontent="..."
+ * @function reloadCatContent
+ * @param {number} catId ID of the category to load content (description 1) from server
+ * @return {object} jQuery deferred
+ * Object
+ * @deprecated
+ */
+ function reloadCatContent( catId )
+ {
+
+ return CMS.getCategoryContent( catId )
+ .done( function( response )
+ {
+ $( '[data-plenty-checkout-catcontent="' + catId + '"]' )
+ .each( function( i, elem )
+ {
+ $( elem ).html( response.data[0] );
+ pm.getInstance().bindDirectives( elem );
+ $( window ).trigger( 'contentChanged' );
+
+ } );
+ } );
+
+ }
+
+ /**
+ * Get layout container from server and replace received HTML
+ * in containers marked with data-plenty-itemview-template="..."
+ * @function reloadItemContainer
+ * @param {string} container Name of the (item view) template to load from server
+ * @return {object} jQuery deferred
+ * Object
+ */
+ function reloadItemContainer( container )
+ {
+
+ return CMS.getContainer( 'itemview' + container ).from( 'itemview' )
+ .done( function( response )
+ {
+ $( '[data-plenty-itemview-template="' + container + '"]' )
+ .each( function( i, elem )
+ {
+ $( elem ).html( response.data[0] );
+ pm.getInstance().bindDirectives( elem );
+ $( window ).trigger( 'contentChanged' );
+
+ } );
+ } );
+
+ }
+
+ }, ['APIFactory', 'CMSFactory', 'UIFactory'] );
+}( PlentyFramework ));
+/**
+ * Licensed under AGPL v3
+ * (https://github.com/plentymarkets/plenty-cms-library/blob/master/LICENSE)
+ * =====================================================================================
+ * @copyright Copyright (c) 2015, plentymarkets GmbH (http://www.plentymarkets.com)
+ * @author Felix Dausch
+ * =====================================================================================
+ */
+
+/**
+ * @module Factories
+ */
+(function( $, pm )
+{
+
+ /**
+ * Provides methods for creating and displaying modal popups.
+ * @class ModalFactory
+ * @static
+ */
+ pm.factory( 'ModalFactory', function()
+ {
+
+ return {
+ prepare: prepare,
+ isModal: isModal
+ };
+
+ /**
+ * Detect if given html contains a valid modal
+ * @function isModal
+ * @param {string} html
+ * @returns {boolean}
+ */
+ function isModal( html )
+ {
+ return PlentyFramework.partials.Modal.isModal( html );
+ }
+
+ /**
+ * Create a new Instance of {{#crossLink "ModalFactory.Modal"}}Modal{{/crossLink}}
+ * @function prepare
+ * @returns {Modal}
+ */
+ function prepare()
+ {
+ return new Modal();
+ }
+
+ /**
+ * Holds configuration of a modal and provides methods for displaying and hiding the modal
+ * @class Modal
+ * @for ModalFactory
+ * @returns {Modal}
+ * @constructor
+ */
+ function Modal()
+ {
+
+ var modal = this;
+ /**
+ * The title of the modal
+ * @attribute title
+ * @type {string}
+ * @private
+ * @default ""
+ */
+ modal.title = '';
+
+ modal.cssClass = '';
+
+ /**
+ * The content of the modal
+ * @attribute content
+ * @type {string}
+ * @private
+ * @default ""
+ */
+ modal.content = '';
+
+ /**
+ * The content of the dismiss-button
+ * @attribute labelDismiss
+ * @type {string}
+ * @private
+ * @default "Abbrechen"
+ */
+ modal.labelDismiss = pm.translate( "Cancel" );
+
+ /**
+ * the label of the confirmation button
+ * @attribute labelConfirm
+ * @type {string}
+ * @private
+ * @default "Bestätigen"
+ */
+ modal.labelConfirm = pm.translate( "Confirm" );
+
+ /**
+ * Callback when modal is confirmed by clicking confirmation button.
+ * Modal will not be dismissed if callback returns false.
+ * @attribute onConfirm
+ * @type {function}
+ * @private
+ * @default function() {}
+ */
+ modal.onConfirm = function()
+ {
+ };
+
+ /**
+ * Callback when modal is dismissed by closing the modal
+ * @attribute onDismiss
+ * @type {function}
+ * @private
+ * @default function() {}
+ */
+ modal.onDismiss = function()
+ {
+ };
+
+ /**
+ * jQuery selector of the container element to display the modal in.
+ * @attribute container
+ * @type {string}
+ * @private
+ * @default "body"
+ */
+ modal.container = 'body';
+
+ /**
+ * Timeout to close the modal automatically. Set <0 to disable.
+ * @attribute timeout
+ * @type {number}
+ * @private
+ * @default -1
+ */
+ modal.timeout = -1;
+
+ modal.hide = hide;
+ modal.startTimeout = startTimeout;
+ modal.stopTimeout = stopTimeout;
+ modal.pauseTimeout = pauseTimeout;
+ modal.continueTimeout = continueTimeout;
+
+ var bsModal;
+ var timeout, interval;
+ var timeRemaining, timeStart;
+ var paused = false;
+
+ return {
+ setTitle : setTitle,
+ setClass : setClass,
+ setContent : setContent,
+ setContainer : setContainer,
+ setLabelConfirm: setLabelConfirm,
+ setLabelDismiss: setLabelDismiss,
+ onConfirm : onConfirm,
+ onDismiss : onDismiss,
+ setTimeout : setTimeout,
+ show : show,
+ hide : hide
+ };
+
+ /**
+ * Set the {{#crossLink "ModalFactory.Modal/title:attribute}}title{{/crossLink}} of the modal
+ * @function setTitle
+ * @param {string} title The title
+ * @returns {Modal} Modal object for chaining methods
+ */
+ function setTitle( title )
+ {
+ modal.title = title;
+ return this;
+ }
+
+ function setClass( cssClass )
+ {
+ modal.cssClass = cssClass;
+ return this;
+ }
+
+ /**
+ * Set the {{#crossLink "ModalFactory.Modal/content:attribute}}content{{/crossLink}} of the modal
+ * @function setContent
+ * @param {string} content The content
+ * @returns {Modal} Modal object for chaining methods
+ */
+ function setContent( content )
+ {
+ modal.content = content;
+ return this;
+ }
+
+ /**
+ * Set the {{#crossLink "ModalFactory.Modal/labelConfirm:attribute}}label of the confirmation
+ * button{{/crossLink}} of the modal
+ * @function setLabelConfirm
+ * @param {string} label The label
+ * @returns {Modal} Modal object for chaining methods
+ */
+ function setLabelConfirm( label )
+ {
+ modal.labelConfirm = label;
+ return this;
+ }
+
+ /**
+ * Set the {{#crossLink "ModalFactory.Modal/labelDismiss:attribute}}label if the dismiss
+ * button{{/crossLink}} of the modal
+ * @function setLabelDismiss
+ * @param {string} label The label
+ * @returns {Modal} Modal object for chaining methods
+ */
+ function setLabelDismiss( label )
+ {
+ modal.labelDismiss = label;
+ return this;
+ }
+
+ /**
+ * Set the {{#crossLink "ModalFactory.Modal/onConfirm:attribute}}confirmation callback{{/crossLink}} of the
+ * modal
+ * @function onConfirm
+ * @param {function} callback The callback if modal is confirmed
+ * @returns {Modal} Modal object for chaining methods
+ */
+ function onConfirm( callback )
+ {
+ modal.onConfirm = callback;
+ return this;
+ }
+
+ /**
+ * Set the {{#crossLink "ModalFactory.Modal/onDismiss:attribute}}dismiss callback{{/crossLink}} of the modal
+ * @function onDismiss
+ * @param {function} callback The callback if modal is dismissed
+ * @returns {Modal} Modal object for chaining methods
+ */
+ function onDismiss( callback )
+ {
+ modal.onDismiss = callback;
+ return this;
+ }
+
+ /**
+ * Set the {{#crossLink "ModalFactory.Modal/container:attribute}}container{{/crossLink}} of the modal
+ * @function setContainer
+ * @param {string} container The jQuery selector of the container to display the modal in
+ * @returns {Modal} Modal object for chaining methods
+ */
+ function setContainer( container )
+ {
+ modal.container = container;
+ return this;
+ }
+
+ /**
+ * Set the {{#crossLink "ModalFactory.Modal/timeout:attribute}}timeout{{/crossLink}} of the modal
+ * @function setTimeout
+ * @param {number} timeout The timeout to close the modal automatically. Set <0 to disable
+ * @returns {Modal} Modal object for chaining methods
+ */
+ function setTimeout( timeout )
+ {
+ modal.timeout = timeout;
+ return this;
+ }
+
+ /**
+ * Inject modal data in default template if not template is given
+ * and display the modal inside the configured container.
+ * Start timer to hide the modal automatically if timeout is set.
+ * @function show
+ */
+ function show()
+ {
+ var entryNumber = 0;
+ if ( isModal( modal.content ) )
+ {
+ bsModal = PlentyFramework.partials.Modal.getModal( modal.content );
+ }
+ else
+ {
+ bsModal = $( PlentyFramework.compileTemplate( 'modal/modal.html', modal ) );
+ }
+
+ $( modal.container ).append( bsModal );
+
+ // append additional scripts executable
+ var scripts = $( modal.content ).filter( 'script' );
+ if ( scripts.length > 0 )
+ {
+ scripts.each( function( i, script )
+ {
+ var element = document.createElement( 'script' );
+ element.type = 'text/javascript';
+ element.innerHTML = $( script ).text();
+ $( modal.container ).append( element );
+ } );
+ }
+
+ // bind callback functions
+ PlentyFramework.partials.Modal.init( bsModal, modal );
+ bsModal.find( '[data-plenty-modal="confirm"]' ).click( function()
+ {
+ var close = modal.onConfirm();
+
+ if( typeof close == "undefined" )
+ {
+ close = true;
+ }
+
+ if ( close )
+ {
+ hide( true );
+ }
+ } );
+
+ PlentyFramework.partials.Modal.show( bsModal );
+
+ if ( modal.timeout > 0 )
+ {
+ startTimeout();
+ }
+
+ }
+
+ /**
+ * Hide the modal.
+ * @function hide
+ * @param {boolean} confirmed Flag indicating of modal is closed by confirmation button or dismissed
+ */
+ function hide( confirmed )
+ {
+ PlentyFramework.partials.Modal.hide( bsModal );
+
+ if ( !confirmed )
+ {
+ modal.onDismiss();
+ }
+ }
+
+ /**
+ * Start the configured timeout initially
+ * @function startTimeout
+ * @private
+ */
+ function startTimeout()
+ {
+ timeRemaining = modal.timeout;
+ timeStart = (new Date()).getTime();
+
+ timeout = window.setTimeout( function()
+ {
+ window.clearInterval( interval );
+ hide();
+ }, modal.timeout );
+
+ bsModal.find( '[data-plenty-modal="timer"]' ).text( timeRemaining / 1000 );
+ interval = window.setInterval( function()
+ {
+ if ( !paused )
+ {
+ var secondsRemaining = timeRemaining - (new Date()).getTime() + timeStart;
+ secondsRemaining = Math.round( secondsRemaining / 1000 );
+ bsModal.find( '[data-plenty-modal="timer"]' ).text( secondsRemaining );
+ }
+ }, 1000 )
+ }
+
+ /**
+ * Pause the timeout (e.g. on hover)
+ * @function pauseTimeout
+ * @private
+ */
+ function pauseTimeout()
+ {
+ paused = true;
+ timeRemaining -= (new Date()).getTime() - timeStart;
+ window.clearTimeout( timeout );
+ }
+
+ /**
+ * Continue paused timeout
+ * @function continueTimeout
+ * @private
+ */
+ function continueTimeout()
+ {
+ paused = false;
+ timeStart = (new Date()).getTime();
+ timeout = window.setTimeout( function()
+ {
+ hide();
+ window.clearInterval( interval );
+ }, timeRemaining );
+ }
+
+ /**
+ * Stop timeout. Stopped timeouts cannot be continued.
+ * @function stopTimeout
+ * @private
+ */
+ function stopTimeout()
+ {
+ window.clearTimeout( timeout );
+ window.clearInterval( interval );
+ }
+
+ }
+
+ } );
+}( jQuery, PlentyFramework ));
+/**
+ * Licensed under AGPL v3
+ * (https://github.com/plentymarkets/plenty-cms-library/blob/master/LICENSE)
+ * =====================================================================================
+ * @copyright Copyright (c) 2015, plentymarkets GmbH (http://www.plentymarkets.com)
+ * @author Felix Dausch
+ * =====================================================================================
+ */
+
+/**
+ * @module Factories
+ */
+(function( $, pm )
+{
+
+ /**
+ * Displaying error messages and handling wait screen
+ * @class UIFactory
+ * @static
+ */
+ pm.factory( 'UIFactory', function()
+ {
+ /**
+ * Increased/ decreased when showing/ hiding wait screen to avoid stacking
+ * multiple instances of overlays.
+ * @attribute waitScreenCount
+ * @private
+ * @type {number}
+ * @default 0
+ */
+ var waitScreenCount = 0;
+ var waitScreen;
+ var errorPopup = null;
+
+ return {
+ throwError : throwError,
+ printErrors : printErrors,
+ showWaitScreen: showWaitScreen,
+ hideWaitScreen: hideWaitScreen
+ };
+
+ /**
+ * Display a single error message.
+ * @function throwError
+ * @param {number} code A code identifying this error
+ * @param {string} msg The error message to display
+ */
+ function throwError( code, msg )
+ {
+ printErrors( [{code: code, message: msg}] );
+ }
+
+ /**
+ * Wrap error messages in error popup, if popup doesn't already contain this error
+ * If popup is already visible, append new errors to popup's inner HTML
+ * otherwise create new popup
+ * @function printErrors
+ * @param {Array} errorMessages A list of errors to display
+ */
+ function printErrors( errorMessages )
+ {
+
+ // create error-popup if not exist
+ if ( !errorPopup || $( 'body' ).has( errorPopup ).length <= 0 )
+ {
+ errorPopup = $( pm.compileTemplate( 'error/errorPopup.html' ) );
+ $( 'body' ).append( errorPopup );
+ pm.partials.Error.init( errorPopup );
+ }
+
+ $.each( errorMessages, function( key, error )
+ {
+ // add additional error, if not exist.
+ pm.partials.Error.addError( errorPopup, $( pm.compileTemplate( 'error/errorMessage.html', error ) ) );
+ } );
+
+ pm.partials.Error.show( errorPopup );
+
+ hideWaitScreen( true );
+ }
+
+ /**
+ * Show wait screen if not visible and increase
+ * {{#crossLink "UIFactory/waitScreenCount:attribute"}}waitScreenCount{{/crossLink}}
+ * @function showWaitScreen
+ */
+ function showWaitScreen()
+ {
+ waitScreenCount = waitScreenCount || 0;
+
+ // create wait-overlay if not exist
+ if ( !waitScreen || $( 'body' ).has( waitScreen ).length <= 0 )
+ {
+ waitScreen = $( pm.compileTemplate( 'waitscreen/waitscreen.html' ) );
+ $( 'body' ).append( waitScreen );
+ }
+
+ pm.partials.WaitScreen.show( waitScreen );
+
+ // increase instance counter to avoid showing multiple overlays
+ waitScreenCount++;
+ return waitScreenCount;
+ }
+
+ /**
+ * Decrease {{#crossLink "UIFactory/waitScreenCount:attribute"}}waitScreenCount{{/crossLink}}
+ * and hide wait screen if waitScreenCount is 0
+ * @function hideWaitScreen
+ * @param {boolean} forceClose set true to hide wait screen independent from the value of waitScreenCount.
+ */
+ function hideWaitScreen( forceClose )
+ {
+
+ // decrease overlay count
+ waitScreenCount--;
+
+ // hide if all instances of overlays has been closed
+ // or if closing is forced by user
+ if ( waitScreenCount <= 0 || !!forceClose )
+ {
+ waitScreenCount = 0;
+ pm.partials.WaitScreen.hide( waitScreen );
+ }
+ return waitScreenCount;
+ }
+
+ } );
+}( jQuery, PlentyFramework ));
+/**
+ * Factories provide static functions and can be injected into
+ * {{#crossLinkModule "Services"}}services{{/crossLinkModule}}.
+ * Factories also can inject other factories. Compared to services,
+ * factories are not visible in instances of {{#crossLinkModule "PlentyFramework"}}PlentyFramework{{/crossLinkModule}}.
+ *
+ * @module Factories
+ * @main Factories
+ */
+/**
+ * Licensed under AGPL v3
+ * (https://github.com/plentymarkets/plenty-cms-library/blob/master/LICENSE)
+ * =====================================================================================
+ * @copyright Copyright (c) 2015, plentymarkets GmbH (http://www.plentymarkets.com)
+ * @author Felix Dausch
+ * =====================================================================================
+ */
+
+(function( $, pm )
+{
+ pm.service( 'AddressDoctorService', function( API )
+ {
+ return {
+ validateAddress: validateAddress
+ };
+
+ function validateAddress( addressForms )
+ {
+ var addressIsValid = true;
+ addressForms = addressForms || '[data-plenty-address-doctor]';
+ $( addressForms ).filter('[data-plenty-address-doctor]:visible').each( function( i, form )
+ {
+ var addressDoctor = new AddressDoctor( form );
+ var requiredFields = $( form ).attr( 'data-plenty-address-doctor' ).replace( /\s/g, '' ).split( ',' );
+ if ( !addressDoctor.isValid( requiredFields ) )
+ {
+ addressIsValid = false;
+ }
+
+ } );
+
+ return addressIsValid;
+ }
+
+ function AddressDoctor( form )
+ {
+ var $form = $( form );
+ var $inputs = {
+ Street : $form.find( 'input[name="Street"]' ),
+ ZIP : $form.find( 'input[name="ZIP"]' ),
+ City : $form.find( 'input[name="City"]' ),
+ HouseNo: $form.find( 'input[name="HouseNo"]' )
+ };
+ var $suggestionContainer = {};
+
+ var suggestions;
+ var requiredFields;
+
+ return {
+ isValid: isValid
+ };
+
+ function isValid( fields )
+ {
+
+ if ( isPackstation() )
+ {
+ return true;
+ }
+
+ suggestions = new AddressList( $form.getFormValues() );
+ requiredFields = fields;
+
+ refreshView();
+
+ return suggestions.getAddresses().length == 1;
+ }
+
+ function refreshView()
+ {
+ $( '.suggestion-list' ).remove();
+
+ var suggestionListVisible = false;
+ for ( var i = 0; i < requiredFields.length; i++ )
+ {
+ if ( !validateInput( requiredFields[i], suggestionListVisible ) )
+ {
+ $form.trigger( 'validationFailed' );
+ suggestionListVisible = true;
+ }
+ }
+
+ if ( suggestions.houseNoAllowed( $inputs.HouseNo.val() ) )
+ {
+ $inputs.HouseNo.removeClass( 'has-error' );
+ $form.find( 'label[for="' + $inputs.HouseNo.attr( 'id' ) + '"]' ).removeClass( 'has-error' );
+
+ $inputs.HouseNo.addClass( 'has-success' );
+ $form.find( 'label[for="' + $inputs.HouseNo.attr( 'id' ) + '"]' ).addClass( 'has-success' );
+ }
+ else
+ {
+ $inputs.HouseNo.removeClass( 'has-success' );
+ $form.find( 'label[for="' + $inputs.HouseNo.attr( 'id' ) + '"]' ).removeClass( 'has-success' );
+
+ $inputs.HouseNo.addClass( 'has-error' );
+ $form.find( 'label[for="' + $inputs.HouseNo.attr( 'id' ) + '"]' ).addClass( 'has-error' );
+ }
+ }
+
+ function validateInput( key, suggestionListVisible )
+ {
+ var valueList = suggestions.getList( key );
+
+ if ( !!$suggestionContainer[key] )
+ {
+ $suggestionContainer[key].remove();
+ }
+
+ if ( !$inputs[key] )
+ {
+ return true;
+ }
+
+ if ( valueList.length == 1 )
+ {
+ $inputs[key].val( valueList[0] );
+
+ $inputs[key].removeClass( 'has-error' );
+ $form.find( 'label[for="' + $inputs[key].attr( 'id' ) + '"]' ).removeClass( 'has-error' );
+
+ $inputs[key].addClass( 'has-success' );
+ $form.find( 'label[for="' + $inputs[key].attr( 'id' ) + '"]' ).addClass( 'has-success' );
+ return true;
+ }
+ else
+ {
+ $inputs[key].removeClass( 'has-success' );
+ $form.find( 'label[for="' + $inputs[key].attr( 'id' ) + '"]' ).removeClass( 'has-success' );
+
+ $inputs[key].addClass( 'has-error' );
+ $form.find( 'label[for="' + $inputs[key].attr( 'id' ) + '"]' ).addClass( 'has-error' );
+
+ if( !suggestionListVisible ) buildSuggestionList( $inputs[key], valueList );
+ $inputs[key].off( 'focus' );
+ $inputs[key].focus();
+ return false;
+
+ }
+ }
+
+ function buildSuggestionList( $parent, values )
+ {
+ var suggestionKey = $parent.attr( 'name' );
+
+ // render html content
+ $suggestionContainer[suggestionKey] = $( pm.compileTemplate( 'addressSuggestions/addressDoctor.html', {values: values} ) );
+ $suggestionContainer[suggestionKey].css( {
+ 'width': $parent.outerWidth( true ),
+ 'left' : $parent.position().left,
+ 'top' : $parent.position().top + $parent.outerHeight( true )
+ } );
+
+ // bind click event to list elements
+ $suggestionContainer[suggestionKey].find( '[data-address-value]' ).each( function( i, elem )
+ {
+
+ var $elem = $( elem );
+ var value = $elem.attr( 'data-address-value' );
+
+ $elem.click( function()
+ {
+ // insert clicked value in input
+ $parent.val( value );
+
+ // filter addresses and show remaining suggestions
+ var filterAddress = {};
+ filterAddress[$parent.attr( 'name' )] = value;
+ suggestions.filter( filterAddress );
+
+ // refresh suggestion lists
+ refreshView();
+
+ } );
+
+ } );
+
+ // inject html
+ $parent.parent().append( $suggestionContainer[suggestionKey] );
+ }
+
+ function isPackstation()
+ {
+ return ( $inputs.Street.val().toUpperCase() == "PACKSTATION" || $inputs.Street.val().toUpperCase() == "POSTFILIALE" );
+ }
+
+ }
+
+ function AddressList( addressInput )
+ {
+ var addresses = [];
+
+ init();
+
+ return {
+ getAddresses : getAddresses,
+ getList : getList,
+ filter : filter,
+ houseNoAllowed: houseNoAllowed
+ };
+
+ function init()
+ {
+ API.get( '/rest/checkout/addresssuggestionresultslist/', {
+ suggestionType: "addressdoctor",
+ street : addressInput.Street,
+ ZIP : addressInput.ZIP,
+ city : addressInput.City,
+ houseNo : addressInput.HouseNo,
+ country : addressInput.CountryID
+ }, false, false, true ).done( function( response )
+ {
+
+ var responseLength = response.data.length;
+
+ for ( var i = 0; i < responseLength; i++ )
+ {
+ var currentResponse = response.data[i];
+
+ var address = getAddress( currentResponse )
+ if ( !address )
+ {
+ currentResponse.HouseNo = [currentResponse.HouseNo];
+ addresses.push( currentResponse );
+ }
+ else
+ {
+ address.HouseNo.push( currentResponse.HouseNo );
+ }
+
+ }
+
+ } );
+ }
+
+ function getAddress( suggestion )
+ {
+ var addressCount = addresses.length;
+
+ for ( var j = 0; j < addressCount; j++ )
+ {
+ if ( suggestion.Street == addresses[j].Street && addresses.ZIP == addresses[j].ZIP && suggestion.City == addresses[j].City )
+ {
+ return addresses[j];
+ }
+ }
+
+ return null;
+
+ }
+
+ function getAddresses()
+ {
+ return addresses;
+ }
+
+ function getList( key )
+ {
+ var results = [];
+ var addressCount = addresses.length;
+
+ for ( var i = 0; i < addressCount; i++ )
+ {
+ var address = addresses[i];
+ if ( $.inArray( address[key], results ) < 0 )
+ {
+ results.push( address[key] );
+ }
+ }
+
+ return results;
+ }
+
+ function filter( filterAddress )
+ {
+ var filteredAddresses = [];
+ var addressCount = addresses.length;
+
+ for ( var i = 0; i < addressCount; i++ )
+ {
+ var address = addresses[i];
+ if ( (!!filterAddress.Street && filterAddress.Street == address.Street)
+ || (!!filterAddress.ZIP && filterAddress.ZIP == address.ZIP)
+ || (!!filterAddress.City && filterAddress.City == address.City) )
+ {
+ filteredAddresses.push( address );
+ }
+ }
+
+ addresses = filteredAddresses;
+ }
+
+ function houseNoAllowed( houseNo )
+ {
+ houseNo = parseInt( houseNo );
+
+ var addressCount = addresses.length;
+
+ for ( var i = 0; i < addressCount; i++ )
+ {
+ var address = addresses[i];
+
+ for ( var j = 0; j < address.HouseNo.length; j++ )
+ {
+ var range = address.HouseNo[j].split( '-' );
+ if ( ( range.length == 1 && houseNo == range[0] )
+ || range.length == 2 && houseNo >= range[0] && houseNo <= range[1] )
+ {
+ return true;
+ }
+ }
+ }
+
+ return false;
+ }
+ }
+
+ }, ['APIFactory'] );
+}( jQuery, PlentyFramework ));
+/**
+ * Licensed under AGPL v3
+ * (https://github.com/plentymarkets/plenty-cms-library/blob/master/LICENSE)
+ * =====================================================================================
+ * @copyright Copyright (c) 2015, plentymarkets GmbH (http://www.plentymarkets.com)
+ * @author Felix Dausch
+ * =====================================================================================
+ */
+
+/**
+ * @module Services
+ */
+(function( $, pm )
+{
+
+ /**
+ * Providing methods for logging in and out and registering new customers.
+ * Requires:
+ *
+ * - {{#crossLink "APIFactory"}}APIFactory{{/crossLink}}
+ * - {{#crossLink "CheckoutFactory"}}CheckoutFactory{{/crossLink}}
+ *
+ * @class AuthenticationService
+ * @static
+ */
+ pm.service( 'AuthenticationService', function( API, Checkout, UI )
+ {
+
+ return {
+ resetPassword : resetPassword,
+ customerLogin : customerLogin,
+ setInvoiceAddress: setInvoiceAddress,
+ registerCustomer : registerCustomer
+ };
+
+ /**
+ * Reading E-Mail from form marked with data-plenty-checkout="lostPasswordForm"
+ * and sends request to provide a new password to the entered E-Mail-Address.
+ *
+ * @function resetPasswort
+ * @return {object} jQuery deferred
+ * Object
+ */
+ function resetPassword()
+ {
+
+ var form = $( '[data-plenty-checkout="lostPasswordForm"]' );
+
+ if ( form.validateForm() )
+ {
+
+ var values = form.getFormValues();
+
+ var params = {
+ Email: values.Email
+ };
+
+ return API.post( "/rest/checkout/lostpassword/", params )
+ .done( function( response )
+ {
+ if ( response.data.IsMailSend == true )
+ {
+ $( '[data-plenty-checkout="lostPasswordTextContainer"]' ).hide();
+ $( '[data-plenty-checkout="lostPasswordSuccessMessage"]' ).show();
+ }
+ } );
+
+ }
+ }
+
+ /**
+ * Try to login in with credentials read from given <form> - element.
+ * On success redirect to forms 'action' attribute.
+ *
+ * @function customerLogin
+ * @param {object} form The jQuery-wrapped form-element to read the credentials from
+ * @return {object} jQuery deferred
+ * Object
+ */
+ function customerLogin( form )
+ {
+ if ( form.validateForm() )
+ {
+ var values = form.getFormValues();
+
+ var params = {
+ Email : values.loginMail,
+ Password: values.loginPassword
+ };
+
+
+ UI.showWaitScreen();
+ return API.post( "/rest/checkout/login/", params )
+ .done( function()
+ {
+ // successful login -> go to form's target referenced by action-attribute
+ window.location.assign( form.attr( 'action' ) );
+
+ } );
+ }
+ }
+
+ /**
+ * Setting the invoice address of a newly registered customer or a guest.
+ *
+ * @function setInvoiceAddress
+ * @param {object} invoiceAddress containing address-data sent to server
+ * @return {object} jQuery deferred
+ * Object
+ */
+ function setInvoiceAddress( invoiceAddress )
+ {
+
+ return API.post( "/rest/checkout/customerinvoiceaddress/", invoiceAddress )
+ .done( function( response )
+ {
+ Checkout.getCheckout().CustomerInvoiceAddress = response.data;
+ } );
+ }
+
+ /**
+ * Prepare address-data to register new customer. Read the address-data from a <form> marked with
+ * data-plenty-checkout-form="customerRegistration"
+ * On success, redirect to forms target referenced by action-attribute
+ *
+ * @function registerCustomer
+ * @return {object} jQuery deferred
+ * Object
+ */
+ function registerCustomer()
+ {
+ var form = $( '[data-plenty-checkout-form="customerRegistration"]' );
+
+ if ( form.validateForm() && pm.getInstance().AddressDoctorService.validateAddress() )
+ {
+ var values = form.getFormValues();
+
+ // create new invoice address
+ var invoiceAddress = {
+ LoginType : 2,
+ FormOfAddressID : values.FormOfAddressID,
+ Company : values.Company,
+ FirstName : values.FirstName,
+ LastName : values.LastName,
+ Street : values.Street,
+ HouseNo : values.HouseNo,
+ AddressAdditional: values.AddressAdditional,
+ ZIP : values.ZIP,
+ City : values.City,
+ CountryID : values.CountryID,
+ VATNumber : values.VATNumber,
+ Email : values.Email,
+ EmailRepeat : values.EmailRepeat,
+ BirthDay : values.BirthDay,
+ BirthMonth : values.BirthMonth,
+ BirthYear : values.BirthYear,
+ Password : values.Password,
+ PasswordRepeat : values.PasswordRepeat,
+ PhoneNumber : values.PhoneNumber,
+ MobileNumber : values.MobileNumber,
+ FaxNumber : values.FaxNumber,
+ Postnummer : values.Postnummer
+ };
+
+ invoiceAddress.CustomerPropertiesList = invoiceAddress.CustomerPropertiesList || [];
+
+ form.find( "[data-plenty-property-id]" ).each( function( i, propertyInput )
+ {
+
+ invoiceAddress.CustomerPropertiesList.push( {
+ PropertyID : $( propertyInput ).attr( 'data-plenty-property-id' ),
+ PropertyValue: $( propertyInput ).val()
+ } );
+ } );
+
+ return setInvoiceAddress( invoiceAddress )
+ .done( function()
+ {
+ window.location.assign( form.attr( 'action' ) );
+ } );
+ }
+ }
+ }, ['APIFactory', 'CheckoutFactory', 'UIFactory'] );
+
+}( jQuery, PlentyFramework ));
+/**
+ * Licensed under AGPL v3
+ * (https://github.com/plentymarkets/plenty-cms-library/blob/master/LICENSE)
+ * =====================================================================================
+ * @copyright Copyright (c) 2015, plentymarkets GmbH (http://www.plentymarkets.com)
+ * @author Felix Dausch
+ * =====================================================================================
+ */
+
+/**
+ * @module Services
+ */
+(function( $, pm )
+{
+
+ /**
+ * Providing methods for adding, editing or removing basket items and coupon codes
+ * Requires:
+ *
+ * - {{#crossLink "APIFactory"}}APIFactory{{/crossLink}}
+ * - {{#crossLink "UIFactory"}}UIFactory{{/crossLink}}
+ * - {{#crossLink "CMSFactory"}}CMSFactory{{/crossLink}}
+ * - {{#crossLink "CheckoutFactory"}}CheckoutFactory{{/crossLink}}
+ * - {{#crossLink "ModalFactory"}}ModalFactory{{/crossLink}}
+ *
+ * @class BasketService
+ * @static
+ */
+ pm.service( 'BasketService', function( API, UI, CMS, Checkout, Modal )
+ {
+
+ return {
+ addItem : addBasketItem,
+ removeItem : removeBasketItem,
+ getItem : getBasketItem,
+ setItemQuantity : setItemQuantity,
+ editItemAttributes: editItemAttributes,
+ editOrderParams : editOrderParams,
+ addCoupon : addCoupon,
+ removeCoupon : removeCoupon
+ };
+
+ /**
+ * Add item to basket. Will fail and show a popup if item has order params
+ * @function addBasketItem
+ * @param {Array} article Array containing the item to add
+ * @param {boolean} [isUpdate=false] Indicating if item's OrderParams are updated
+ * @return {object} jQuery deferred
+ * Object
+ */
+ function addBasketItem( article )
+ {
+
+ if ( !!article )
+ {
+
+ API.get( '/rest/checkout/container_' + 'CheckoutOrderParamsList'.toLowerCase() + '/',
+ {
+ itemID : article[0].BasketItemItemID,
+ quantity: article[0].BasketItemQuantity
+ }, false, true ).done( function( resp )
+ {
+ // checking for order params!
+ if ( resp.data[0].indexOf( "form-group" ) > 0 )
+ {
+ Modal.prepare()
+ .setContent( resp.data[0] )
+ .setTitle( pm.translate( "Select order parameters" ) )
+ .setLabelConfirm( pm.translate( "Save" ) )
+ .onConfirm( function()
+ {
+ // validate form
+ if ( $('[data-plenty-checkout-form="OrderParamsForm"]').validateForm() )
+ {
+ // save order params
+ addArticle( saveOrderParams( article ) );
+
+ // close modal after saving order params
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+ } )
+ .show();
+ }
+ else
+ {
+ addArticle( article );
+ }
+ } );
+ }
+ }
+
+ /**
+ * Read OrderParams from <form> marked with data-plenty-checkout-form="OrderParamsForm" and inject
+ * read values in 'addBasketList'. Update item by calling addBasketItem()
again
+ * @function saveOrderParams
+ * @private
+ * @param {Array} articleWithParams Containing the current item to add. Read OrderParams will be injected
+ */
+ function saveOrderParams( articleWithParams )
+ {
+ //TODO use $("[data-plenty-checkout-form='OrderParamsForm']").serializeArray() to get order params
+ var orderParamsForm = $( '[data-plenty-checkout-form="OrderParamsForm"]' );
+ var $self = {};
+ var attrType = "";
+ var match;
+
+ //Groups
+ orderParamsForm.find( '[name^="ParamGroup"]' ).each( function()
+ {
+ match = this.name.match( /^ParamGroup\[(\d+)]\[(\d+)]$/ );
+ articleWithParams = addOrderParamValue( articleWithParams, match[1], $( this ).val(), $( this ).val() );
+ } );
+
+ //Values
+ orderParamsForm.find( '[name^="ParamValue"]' ).each( function()
+ {
+ $self = $( this );
+ attrType = $self.attr( 'type' );
+
+ if ( ((attrType == 'checkbox' && $self.is( ':checked' )) ||
+ (attrType == 'radio' && $self.is( ':checked' )) ||
+ (attrType != 'radio' && attrType != 'checkbox')) && attrType != 'file' && attrType != 'hidden' )
+ {
+
+ var match = $self[0].name.match( /^ParamValue\[(\d+)]\[(\d+)]$/ );
+ articleWithParams = addOrderParamValue( articleWithParams, match[1], match[2], $self.val() );
+
+ }
+ else if ( attrType == 'file' )
+ {
+ if( $self[0].files && $self[0].files.length > 0 )
+ {
+ articleWithParams = orderParamFileUpload( $self, articleWithParams );
+ }
+ else
+ {
+ var match = $self[0].name.match( /^ParamValueFile\[(\d+)]\[(\d+)]$/ );
+ var paramValue = $( 'input[type="hidden"][name="ParamValue[' + match[1] + '][' + match[2] + ']"]' ).val();
+ articleWithParams = addOrderParamValue( articleWithParams, match[1], match[2], paramValue );
+ }
+ }
+ } );
+
+ return articleWithParams;
+ }
+
+ function addArticle( article )
+ {
+ API.post( '/rest/checkout/basketitemslist/', article, true )
+ .done( function()
+ {
+ // Item has no OrderParams -> Refresh Checkout & BasketPreview
+ Checkout.loadCheckout()
+ .done( function()
+ {
+ refreshBasketPreview();
+ // Show confirmation popup
+ CMS.getContainer( 'ItemViewItemToBasketConfirmationOverlay', {ArticleID: article[0].BasketItemItemID} ).from( 'ItemView' )
+ .done( function( response )
+ {
+ Modal.prepare()
+ .setContent( response.data[0] )
+ .setTimeout( 5000 )
+ .show();
+ } );
+ } );
+ } ).fail( function( jqXHR )
+ {
+ // some other error occured
+ UI.printErrors( JSON.parse( jqXHR.responseText ).error.error_stack );
+ } );
+ }
+
+ function updateArticle( article )
+ {
+ API.put( '/rest/checkout/basketitemslist/', article )
+ .done( function()
+ {
+ // Item has no OrderParams -> Refresh Checkout & BasketPreview
+ Checkout.reloadCatContent( pm.getGlobal( 'basketCatID' ) );
+ Checkout.loadCheckout()
+ .done( function()
+ {
+ refreshBasketPreview();
+ } );
+ } )
+ }
+
+ function orderParamFileUpload( $input, articleWithParams )
+ {
+ var key = $input[0].id;
+ var orderParamUploadFiles = {};
+ var orderParamFileIdStack = [];
+ var formData;
+ var fileData;
+ var params = {
+ type : 'POST',
+ data : {},
+ isFile : true,
+ cache : false,
+ dataType : 'json',
+ processData: false,
+ contentType: false
+ };
+
+ orderParamUploadFiles[key] = $input[0].files;
+
+ // if input not pushed before.
+ if ( orderParamFileIdStack.indexOf( key ) == -1 )
+ {
+ orderParamFileIdStack.push( key );
+ }
+
+ for ( var i = 0, length = orderParamFileIdStack.length; i < length; ++i )
+ {
+ formData = new FormData();
+ fileData = orderParamUploadFiles[orderParamFileIdStack[i]];
+ formData.append( "0", fileData[0], fileData[0].name );
+
+ params.data = formData;
+
+ API.post( "/rest/checkout/orderparamfile/", params );
+ }
+
+ var match = $input[0].name.match( /^ParamValueFile\[(\d+)]\[(\d+)]$/ );
+
+ return addOrderParamValue( articleWithParams, match[1], match[2], $input.val() );
+ }
+
+ /**
+ * Inject an OrderParam.
+ * @function addOrderParamValue
+ * @private
+ * @param {Array} basketList The target to inject the value in.
+ * @param {number} position Position where to inject the value
+ * @param {number} paramId The ID of the OrderParam to inject
+ * @param {string|number} paramValue the value of the OrderParam to inject
+ * @returns {Array} Containing the item and the injected OrderParam
+ */
+ function addOrderParamValue( basketList, position, paramId, paramValue )
+ {
+ if ( position > 0 && basketList[position] == undefined )
+ {
+ basketList[position] = $.extend( true, {}, basketList[0] );
+ basketList[position].BasketItemOrderParamsList = [];
+ }
+
+ if ( basketList[position] != undefined )
+ {
+ basketList[position].BasketItemQuantity = 1;
+ if ( basketList[position].BasketItemOrderParamsList == undefined )
+ {
+ basketList[position].BasketItemOrderParamsList = [];
+ }
+ if ( paramValue )
+ {
+ basketList[position].BasketItemOrderParamsList.push( {
+ BasketItemOrderParamID : paramId,
+ BasketItemOrderParamValue: paramValue
+ } );
+ }
+ }
+
+ return basketList;
+ }
+
+ function editItemAttributes( BasketItemID )
+ {
+ var modal = $( '[data-plenty-basket-item="' + BasketItemID + '"' );
+ modal.modal( 'show' );
+ modal.find( '[data-plenty-modal="confirm"]' ).on( 'click', function()
+ {
+ var basketItem = getBasketItem( BasketItemID );
+ var attributesList = [];
+
+ // check for select or list of images
+ modal.find( 'select, .PlentyFormContainer.AttrImage > input[type="hidden"]' ).each( function( i, attributeSelect )
+ {
+ var match = attributeSelect.name.match( /^ArticleAttribute\[\d+]\[\d+]\[(\d+)]$/ );
+ if ( match && match[1] )
+ {
+ attributesList.push( {
+ BasketItemAttributeID : match[1],
+ BasketItemAttributeValueID: $( attributeSelect ).val()
+ } );
+ }
+
+ } );
+
+ if ( attributesList.length != 0 )
+ {
+ basketItem.BasketItemAttributesList = attributesList;
+ }
+ //update basketItem and refresh previewLists
+ updateArticle( [basketItem] );
+
+ } );
+ }
+
+ function editOrderParams( BasketItemID )
+ {
+
+ var basketItem = getBasketItem( BasketItemID );
+ // FIX: unset old order params
+
+ basketItem.BasketItemOrderParamsList = [];
+
+ API.get( '/rest/checkout/container_' + 'CheckoutOrderParamsList'.toLowerCase() + '/', {
+ itemID : basketItem.BasketItemItemID,
+ quantity : basketItem.BasketItemQuantity,
+ basketItemID: BasketItemID
+ } ).done( function( resp )
+ {
+ // checking for order params!
+ Modal.prepare()
+ .setContent( resp.data[0] )
+ .setTitle( pm.translate( "Edit order parameters" ) )
+ .setLabelConfirm( pm.translate( "Save" ) )
+ .onConfirm( function()
+ {
+ // validate form
+ if ( $('[data-plenty-checkout-form="OrderParamsForm"]').validateForm() )
+ {
+ // save order params
+ updateArticle( saveOrderParams( [basketItem] ) );
+
+ // close modal after saving order params
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+ } )
+ .show();
+ } );
+ }
+
+ function getBasketItem( BasketItemID )
+ {
+ var basketItems = Checkout.getCheckout().BasketItemsList;
+ for ( var i = 0; i < basketItems.length; i++ )
+ {
+ if ( basketItems[i].BasketItemID == BasketItemID )
+ {
+ return basketItems[i];
+ }
+ }
+
+ return null;
+ }
+
+ /**
+ * Remove item from basket. Will show a confirmation popup at first.
+ * @function removeBasketItem
+ * @param {number} BasketItemID The ID of the basket item to remove
+ * @param {boolean} [forceDelete=false] Set true to remove the basket item without showing a confirmation popup
+ * @return Promise
+ */
+ function removeBasketItem( BasketItemID, forceDelete )
+ {
+
+ var deferred = $.Deferred();
+
+ // get item name
+ var itemName = getBasketItem( BasketItemID ).BasketItemNameMap[1];
+
+ // calling the delete request
+ function doDelete()
+ {
+ API.delete( '/rest/checkout/basketitemslist/?basketItemIdsList[0]=' + BasketItemID )
+ .done( function()
+ {
+ Checkout.loadCheckout().done( function()
+ {
+ $( '[data-basket-item-id="' + BasketItemID + '"]' ).remove();
+
+ if ( !Checkout.getCheckout().BasketItemsList || Checkout.getCheckout().BasketItemsList.length <= 0 )
+ {
+ Checkout.reloadCatContent( pm.getGlobal( 'basketCatID' ) );
+ }
+ else
+ {
+ Checkout.reloadContainer( 'Totals' );
+ }
+
+ refreshBasketPreview();
+
+ deferred.resolve();
+ } );
+ } );
+ }
+
+ if ( !forceDelete )
+ {
+ // show confirmation popup
+ Modal.prepare()
+ .setTitle( pm.translate( 'Please confirm' ) )
+ .setContent( '' + pm.translate( "Do you really want to remove \"{{item}}\" from your basket?", {item: itemName} ) + '
' )
+ .onDismiss( function()
+ {
+ //$('[data-basket-item-id="' + BasketItemID +
+ // '"]').find('[data-plenty="quantityInput"]').val(originalItemQuantity);
+ deferred.reject();
+ } )
+ .onConfirm( function()
+ {
+ doDelete();
+ } )
+ .setLabelConfirm( pm.translate( "Delete" ) )
+ .show();
+ }
+ else
+ {
+ doDelete();
+ }
+
+ return deferred;
+ }
+
+ /**
+ * Set a new quantity for the given BasketItem. If quantity is set to 0,
+ * remove the item.
+ * @function setItemQuantity
+ * @param {number} BasketItemID The ID of the basket item to change the quantity of
+ * @param {number} BasketItemQuantity The new quantity to set or 0 to remove the item
+ */
+ function setItemQuantity( BasketItemID, BasketItemQuantity )
+ {
+ // delete item if quantity is 0
+ if ( BasketItemQuantity <= 0 )
+ {
+ return removeBasketItem( BasketItemID );
+ }
+
+ var deferred = $.Deferred();
+ var params = Checkout.getCheckout().BasketItemsList;
+ var basketItem;
+ var basketItemIndex;
+
+ for ( var i = 0; i < params.length; i++ )
+ {
+ if ( params[i].BasketItemID == BasketItemID )
+ {
+ basketItemIndex = i;
+ basketItem = params[i];
+ break;
+
+ }
+ }
+
+ if ( !!basketItem && basketItem.BasketItemQuantity != BasketItemQuantity )
+ {
+ params[basketItemIndex].BasketItemQuantity = parseInt( BasketItemQuantity );
+
+ API.post( "/rest/checkout/basketitemslist/", params )
+ .done( function()
+ {
+ Checkout.setCheckout().done( function()
+ {
+ Checkout.reloadCatContent( pm.getGlobal( 'basketCatID' ) );
+ refreshBasketPreview();
+ deferred.resolve();
+ } );
+ } );
+ }
+
+ return deferred;
+ }
+
+ /**
+ * Reload BasketPreview-Template and update basket totals
+ * @function refreshBasketPreview
+ * @private
+ */
+ function refreshBasketPreview()
+ {
+
+ Checkout.reloadItemContainer( 'BasketPreviewList' )
+ .done( function()
+ {
+
+ $( '[data-plenty-basket-empty]' ).each( function( i, elem )
+ {
+ var toggleClass = $( elem ).attr( 'data-plenty-basket-empty' );
+ if ( Checkout.getCheckout().BasketItemsList.length <= 0 )
+ {
+ $( elem ).addClass( toggleClass );
+ }
+ else
+ {
+ $( elem ).removeClass( toggleClass );
+ }
+ } );
+
+ } );
+
+ //update quantity
+ var itemQuantityTotal = 0;
+ $.each( Checkout.getCheckout().BasketItemsList, function( i, basketItem )
+ {
+ itemQuantityTotal += basketItem.BasketItemQuantity;
+ } );
+
+ $( '[data-plenty-basket-preview="itemQuantityTotal"]' ).text( itemQuantityTotal );
+ $( '[data-plenty-basket-preview="totalsItemSum"]' ).text( Checkout.getCheckout().Totals.TotalsItemSum );
+ }
+
+ /**
+ * Read the coupon code from an <input> element marked with data-plenty-checkout-form="couponCode"
+ * and try to add this coupon.
+ * @function addCoupon
+ * @return {object} jQuery deferred
+ * Object
+ */
+ function addCoupon()
+ {
+ var params = {
+ CouponActiveCouponCode: $( '[data-plenty-checkout-form="couponCode"]' ).val()
+ };
+
+ return API.post( "/rest/checkout/coupon/", params )
+ .done( function()
+ {
+ Checkout.setCheckout()
+ .done( function()
+ {
+
+ updateContainer();
+ } );
+ } );
+ }
+
+ /**
+ * Remove the currently added coupon
+ * @function removeCoupon
+ * @return {object} jQuery deferred
+ * Object
+ */
+ function removeCoupon()
+ {
+ var params = {
+ CouponActiveCouponCode: Checkout.getCheckout().Coupon.CouponActiveCouponCode
+ };
+
+ return API.delete( "/rest/checkout/coupon/", params )
+ .done( function()
+ {
+ Checkout.setCheckout()
+ .done( function()
+ {
+ delete Checkout.getCheckout().Coupon;
+
+ updateContainer();
+ } );
+ } );
+ }
+
+ // update container
+ function updateContainer()
+ {
+ Checkout.reloadContainer( 'Coupon' );
+ // reload totals, if we are at basket
+ if ( $( '[data-plenty-checkout-template="Totals"]' ).length > 0 )
+ {
+ Checkout.reloadContainer( 'Totals' );
+ }
+ }
+
+ }, ['APIFactory', 'UIFactory', 'CMSFactory', 'CheckoutFactory', 'ModalFactory'] );
+}( jQuery, PlentyFramework ));
+/**
+ * Licensed under AGPL v3
+ * (https://github.com/plentymarkets/plenty-cms-library/blob/master/LICENSE)
+ * =====================================================================================
+ * @copyright Copyright (c) 2015, plentymarkets GmbH (http://www.plentymarkets.com)
+ * @author Felix Dausch
+ * =====================================================================================
+ */
+
+/**
+ * @module Services
+ */
+(function( $, pm )
+{
+
+ /**
+ * Providing methods for checkout process like setting shipping & payment information and placing the order.
+ * Requires:
+ *
+ * - {{#crossLink "APIFactory"}}APIFactory{{/crossLink}}
+ * - {{#crossLink "CMSFactory"}}CMSFactory{{/crossLink}}
+ * - {{#crossLink "CheckoutFactory"}}CheckoutFactory{{/crossLink}}
+ * - {{#crossLink "ModalFactory"}}ModalFactory{{/crossLink}}
+ *
+ * @class CheckoutService
+ * @static
+ */
+ pm.service( 'CheckoutService', function( API, CMS, Checkout, Modal )
+ {
+
+ return {
+ init : init,
+ setCustomerSignAndInfo: setCustomerSignAndInfo,
+ registerGuest : registerGuest,
+ setShippingProfile : setShippingProfile,
+ saveShippingAddress : saveShippingAddress,
+ loadAddressSuggestion : loadAddressSuggestion,
+ preparePayment : preparePayment,
+ setMethodOfPayment : setMethodOfPayment,
+ editBankDetails : editBankDetails,
+ editCreditCard : editCreditCard,
+ placeOrder : placeOrder
+ };
+
+ /**
+ * Load checkout data initially on page load
+ * @function init
+ */
+ function init()
+ {
+ Checkout.loadCheckout( true );
+ }
+
+ /**
+ * Read customer sign and order information text from <form> marked with
+ * data-plenty-checkout-form="details" and update checkout.
+ * @function setCustomerSignAndInfo
+ * @return {object} jQuery deferred
+ * Object
+ */
+ function setCustomerSignAndInfo()
+ {
+ var form = $( '[data-plenty-checkout-form="details"]' );
+ var values = form.getFormValues();
+
+ // initialize CustomerSign & InfoText to avoid updating empty values
+ if ( !Checkout.getCheckout().CheckoutCustomerSign )
+ {
+ Checkout.getCheckout().CheckoutCustomerSign = "";
+ }
+ if ( !Checkout.getCheckout().CheckoutOrderInfoText )
+ {
+ Checkout.getCheckout().CheckoutOrderInfoText = "";
+ }
+
+ if ( ( Checkout.getCheckout().CheckoutCustomerSign !== values.CustomerSign && $( form ).find( '[name="CustomerSign"]' ).length > 0 )
+ || ( Checkout.getCheckout().CheckoutOrderInfoText !== values.OrderInfoText && $( form ).find( '[name="OrderInfoText"]' ).length > 0 ) )
+ {
+
+ Checkout.getCheckout().CheckoutCustomerSign = values.CustomerSign;
+ Checkout.getCheckout().CheckoutOrderInfoText = values.OrderInfoText;
+
+ return Checkout.setCheckout();
+
+ }
+ else
+ {
+ // No changes detected -> Do nothing
+ return API.idle();
+ }
+ }
+
+ /**
+ * Read address data from <form> marked with data-plenty-checkout-form="shippingAddress".
+ * Create new shipping address or update the shipping address ID.
+ * @function saveShippingAddress
+ * @param {boolean} [validateForm = false] validate form before processing requests
+ * @return {object} jQuery deferred
+ * Object
+ */
+ function saveShippingAddress( validateForm )
+ {
+ var form = $( '[data-plenty-checkout-form="shippingAddress"]' );
+
+ if ( !validateForm && !form.validateForm() )
+ {
+ return false;
+ }
+
+ if ( !validateForm && !pm.getInstance().AddressDoctorService.validateAddress( form ) )
+ {
+ return false;
+ }
+
+ var values = form.getFormValues();
+ var shippingAddressID = $( '[name="shippingAddressID"]:checked' ).val();
+
+ // TODO: move bootstrap specific function
+ $( '#shippingAdressSelect' ).modal( 'hide' );
+
+ if ( shippingAddressID < 0 )
+ {
+ // save separate
+ var shippingAddress = values;
+
+ if ( !addressesAreEqual( shippingAddress, Checkout.getCheckout().CustomerShippingAddress ) )
+ {
+ if ( shippingAddress.Street == "PACKSTATION" )
+ {
+ shippingAddress.isPackstation = 1;
+ shippingAddress.PackstationNo = shippingAddress.HouseNo;
+ }
+ else if ( shippingAddress.Street == "POSTFILIALE" )
+ {
+ shippingAddress.IsPostfiliale = 1;
+ shippingAddress.PostfilialNo = shippingAddress.HouseNo;
+ }
+
+ // new shipping address
+ return API.post( "/rest/checkout/customershippingaddress/", shippingAddress )
+ .done( function( response )
+ {
+
+ Checkout.getCheckout().CheckoutCustomerShippingAddressID = response.data.ID;
+ Checkout.getCheckout().CheckoutShippingCountryID = response.data.CountryID;
+ delete Checkout.getCheckout().CheckoutMethodOfPaymentID;
+ delete Checkout.getCheckout().CheckoutShippingProfileID;
+
+ Checkout.setCheckout().done( function()
+ {
+ Checkout.reloadContainer("MethodsOfPaymentList");
+ Checkout.reloadContainer("ShippingProfilesList");
+ if ( Checkout.getCheckout().CustomerInvoiceAddress.LoginType == 2 )
+ {
+ Checkout.reloadContainer( 'CustomerShippingAddress' );
+ }
+ } );
+ } );
+ }
+ else
+ {
+ // no changes detected
+ return API.idle();
+ }
+
+ }
+ else
+ {
+ if ( shippingAddressID != Checkout.getCheckout().CheckoutCustomerShippingAddressID )
+ {
+ // change shipping address id
+ Checkout.getCheckout().CheckoutCustomerShippingAddressID = shippingAddressID;
+ delete Checkout.getCheckout().CheckoutMethodOfPaymentID;
+ delete Checkout.getCheckout().CheckoutShippingProfileID;
+
+ return Checkout.setCheckout().done( function()
+ {
+ Checkout.reloadContainer("MethodsOfPaymentList");
+ Checkout.reloadContainer("ShippingProfilesList");
+ if ( Checkout.getCheckout().CustomerInvoiceAddress.LoginType == 2 )
+ {
+ Checkout.reloadContainer( 'CustomerShippingAddress' );
+ }
+ } );
+ }
+ else
+ {
+ return API.idle();
+ }
+ }
+ }
+
+ /**
+ * Prepare address-data to register a guest. Reads the address-data from a <form> marked with
+ * data-plenty-checkout-form="guestRegistration"
+ * @function registerGuest
+ * @return {object} jQuery deferred
+ * Object
+ */
+ function registerGuest()
+ {
+ var form = $( '[data-plenty-checkout-form="guestRegistration"]' );
+
+ var invoiceAddress = form.getFormValues();
+ invoiceAddress.LoginType = 1;
+
+ invoiceAddress.CustomerPropertiesList = invoiceAddress.CustomerPropertiesList || [];
+
+ form.find( "[data-plenty-property-id]" ).each( function( i, propertyInput )
+ {
+ invoiceAddress.CustomerPropertiesList.push( {
+ PropertyID : $( propertyInput ).attr( 'data-plenty-property-id' ),
+ PropertyValue: $( propertyInput ).val()
+ } );
+ } );
+
+ if ( !addressesAreEqual( invoiceAddress, Checkout.getCheckout().CustomerInvoiceAddress ) )
+ {
+ return API.post( "/rest/checkout/customerinvoiceaddress/", invoiceAddress )
+ .done( function( response )
+ {
+ //Checkout.getCheckout().CheckoutShippingCountryID = response.data.CountryID;
+ saveShippingAddress().done( function()
+ {
+ Checkout.loadCheckout();
+ //Checkout.getCheckout().CustomerInvoiceAddress = response.data;
+ } );
+ } );
+ }
+ else
+ {
+ return saveShippingAddress();
+ }
+ }
+
+ /**
+ * Check if values of addresses are equal
+ * @function addressesAreEqual
+ * @private
+ * @param {object} address1
+ * @param {object} address2
+ * @returns {boolean}
+ */
+ function addressesAreEqual( address1, address2 )
+ {
+ for ( var key in address1 )
+ {
+ if ( address1[key] + '' !== address2[key] + '' && key !== 'EmailRepeat' )
+ {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Set the shipping profile used for this order and update checkout. Selected shipping profile will be
+ * read from <form> marked with data-plenty-checkout-form="shippingProfileSelect"
+ * @function setShippingProfile
+ * @return {object} jQuery deferred
+ * Object
+ */
+ function setShippingProfile()
+ {
+
+ var values = $( '[data-plenty-checkout-form="shippingProfileSelect"]' ).getFormValues();
+
+ Checkout.getCheckout().CheckoutShippingProfileID = values.ShippingProfileID;
+ delete Checkout.getCheckout().CheckoutCustomerShippingAddressID;
+ delete Checkout.getCheckout().CheckoutMethodOfPaymentID;
+
+ return Checkout.setCheckout()
+ .done( function()
+ {
+ Checkout.reloadContainer( 'MethodsOfPaymentList' );
+ } );
+
+ }
+
+ /**
+ * Prepare method of payment to check if external checkout is used or addition content should be displayed
+ * @function preparePayment
+ * @return {object} jQuery deferred
+ * Object
+ */
+ function preparePayment()
+ {
+ return API.post( "/rest/checkout/preparepayment/", null )
+ .done( function( response )
+ {
+ if ( response.data.CheckoutMethodOfPaymentRedirectURL != '' )
+ {
+
+ document.location.assign( response.data.CheckoutMethodOfPaymentRedirectURL );
+
+ }
+ else if ( !!response.data.CheckoutMethodOfPaymentAdditionalContent )
+ {
+
+ var isBankDetails = $( response.data.CheckoutMethodOfPaymentAdditionalContent ).find( '[data-plenty-checkout-form="bankDetails"]' ).length > 0;
+ Modal.prepare()
+ .setContent( response.data.CheckoutMethodOfPaymentAdditionalContent )
+ .onConfirm( function()
+ {
+ if ( isBankDetails )
+ {
+ return saveBankDetails();
+ }
+ else
+ {
+ return saveCreditCard();
+ }
+ } )
+ .show();
+ }
+ } );
+
+ }
+
+ /**
+ * Set the method of payment used for this order.
+ * @function setMethodOfPayment
+ * @param {number|undefined} paymentID ID of the method of payment to use. Read from <form> marked with
+ * data-plenty-checkout-form="methodOfPayment" if unset.
+ * @return {object} jQuery deferred
+ * Object
+ */
+ function setMethodOfPayment( paymentID )
+ {
+
+ paymentID = paymentID || $( '[data-plenty-checkout-form="methodOfPayment"]' ).getFormValues().MethodOfPaymentID;
+
+ Checkout.getCheckout().CheckoutMethodOfPaymentID = paymentID;
+ delete Checkout.getCheckout().CheckoutCustomerShippingAddressID;
+ delete Checkout.getCheckout().CheckoutShippingProfileID;
+
+ return Checkout.setCheckout()
+ .done( function()
+ {
+ Checkout.reloadContainer( 'ShippingProfilesList' );
+ } );
+ }
+
+ /**
+ * Display the popup to enter or edit customers bank details
+ * @function editBankDetails
+ */
+ function editBankDetails()
+ {
+
+ CMS.getContainer( 'CheckoutPaymentInformationBankDetails' ).from( 'Checkout' )
+ .done( function( response )
+ {
+ Modal.prepare()
+ .setContent( response.data[0] )
+ .onDismiss( function()
+ {
+ $( 'input[name="MethodOfPaymentID"]' ).each( function( i, radio )
+ {
+ if ( $( radio ).val() == Checkout.getCheckout().CheckoutMethodOfPaymentID )
+ {
+ $( radio ).attr( 'checked', 'checked' );
+ }
+ else
+ {
+ $( radio ).removeAttr( 'checked' );
+ }
+ } );
+ } ).onConfirm( function()
+ {
+ return saveBankDetails();
+ } )
+ .show();
+ } );
+
+ }
+
+ /**
+ * Read entered bank details from data-plenty-checkout-form="bankDetails" and update checkout.
+ * @function saveBankDetails
+ * @private
+ * @return {boolean} the result of form validation
+ */
+ function saveBankDetails()
+ {
+ var form = $( '[data-plenty-checkout-form="bankDetails"]' );
+
+ if ( form.validateForm() )
+ {
+ var values = form.getFormValues().checkout.customerBankDetails;
+
+ var bankDetails = {
+ CustomerBankName : values.bankName,
+ CustomerBLZ : values.blz,
+ CustomerAccountNumber: values.accountNo,
+ CustomerAccountOwner : values.accountOwner,
+ CustomerIBAN : values.iban,
+ CustomerBIC : values.bic
+ };
+
+ API.post( "/rest/checkout/paymentinformationbankdetails/", bankDetails )
+ .done( function()
+ {
+ Checkout.loadCheckout().done( function()
+ {
+ setMethodOfPayment( 3 );
+ Checkout.reloadContainer( 'MethodsOfPaymentList' );
+ } );
+ } );
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ /**
+ * Display a popup containing credit card form
+ * @function editCreditCard
+ */
+ function editCreditCard()
+ {
+
+ CMS.getContainer( 'CheckoutPaymentInformationCreditCard' ).from( 'Checkout' )
+ .done( function( response )
+ {
+ Modal.prepare()
+ .setContent( response.data[0] )
+ .onDismiss( function()
+ {
+ $( 'input[name="MethodOfPaymentID"]' ).each( function( i, radio )
+ {
+ if ( $( radio ).val() == Checkout.getCheckout().CheckoutMethodOfPaymentID )
+ {
+ $( radio ).attr( 'checked', 'checked' );
+ }
+ else
+ {
+ $( radio ).removeAttr( 'checked' );
+ }
+ } );
+ } ).onConfirm( function()
+ {
+ return saveCreditCard();
+ } )
+ .show();
+ } );
+ }
+
+ /**
+ * Read values from <form> marked with data-plenty-checkout-form="creditCard" and update checkout.
+ * @function saveCreditCard
+ * @private
+ * @return {boolean} the result of form validation
+ */
+ function saveCreditCard()
+ {
+ var form = $( '[data-plenty-checkout-form="creditCard"]' );
+
+ if ( form.validateForm() )
+ {
+
+ var values = form.getFormValues().checkout.paymentInformationCC;
+
+ var creditCard = {
+ Owner : values.owner,
+ Cvv2 : values.cvv2,
+ Number : values.number,
+ Year : values.year,
+ Month : values.month,
+ Provider: values.provider
+ };
+
+ API.post( '/rest/checkout/paymentinformationcreditcard/', creditCard )
+ .done( function()
+ {
+ Checkout.loadCheckout();
+ } );
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ /**
+ * Display a popup containing address suggestions
+ * @param {string} type
+ */
+ function loadAddressSuggestion( type )
+ {
+
+ //check login type
+ if ( Checkout.getCheckout().CustomerInvoiceAddress.LoginType == 2 )
+ {
+ var values = $( '[data-plenty-checkout-form="shippingAddress"]' ).getFormValues();
+ }
+ else
+ {
+ var values = $( '[data-plenty-checkout-form="guestRegistration"]' ).getFormValues();
+ }
+
+ var params = {
+ street : values.Street,
+ houseNo : values.HouseNo,
+ ZIP : values.ZIP,
+ city : values.City,
+ postnummer : values.Postnummer,
+ suggestionType: 'postfinder'
+ };
+
+ CMS.getContainer( 'CheckoutAddressSuggestionResultsList', params ).from( 'Checkout' )
+ .done( function( response )
+ {
+ Modal.prepare()
+ .setContent( response.data[0] )
+ .show();
+ } );
+ }
+
+ /**
+ * Place the order prepared before and finish the checkout process.
+ * Validate required checkboxes in data-plenty-checkout-form="placeOrder"
+ * @function placeOrder
+ * @return {object} jQuery deferred
+ * Object
+ */
+ function placeOrder()
+ {
+ var form = $( '[data-plenty-checkout-form="placeOrder"]' );
+ if ( form.validateForm() )
+ {
+
+ var values = form.getFormValues();
+
+ // if not shown in layout set default 1 for mandatory fields
+ var params = {
+ TermsAndConditionsCheck : values.termsAndConditionsCheck || 0,
+ WithdrawalCheck : values.withdrawalCheck || 0,
+ PrivacyPolicyCheck : values.privacyPolicyCheck || 0,
+ AgeRestrictionCheck : values.ageRestrictionCheck || 0,
+ NewsletterCheck : values.newsletterCheck || 0,
+ KlarnaTermsAndConditionsCheck: values.klarnaTermsAndConditionsCheck || 0,
+ PayoneDirectDebitMandateCheck: values.payoneDirectDebitMandateCheck || 0,
+ PayoneInvoiceCheck : values.payoneInvoiceCheck || 0
+ };
+
+ return API.post( "/rest/checkout/placeorder/", params )
+ .done( function( response )
+ {
+ if ( response.data.MethodOfPaymentRedirectURL != '' )
+ {
+
+ window.location.assign( response.data.MethodOfPaymentRedirectURL );
+
+ }
+ else if ( response.data.MethodOfPaymentAdditionalContent != '' )
+ {
+
+ Modal.prepare()
+ .setContent( response.data.MethodOfPaymentAdditionalContent )
+ .setLabelDismiss( '' )
+ .onDismiss( function()
+ {
+ window.location.assign( form.attr( 'action' ) );
+ } ).onConfirm( function()
+ {
+ window.location.assign( form.attr( 'action' ) );
+ } ).show();
+
+ }
+ else
+ {
+
+ window.location.assign( form.attr( 'action' ) );
+
+ }
+ } );
+ }
+ }
+
+ }, ['APIFactory', 'CMSFactory', 'CheckoutFactory', 'ModalFactory'] );
+}( jQuery, PlentyFramework ));
+/**
+ * Licensed under AGPL v3
+ * (https://github.com/plentymarkets/plenty-cms-library/blob/master/LICENSE)
+ * =====================================================================================
+ * @copyright Copyright (c) 2015, plentymarkets GmbH (http://www.plentymarkets.com)
+ * @author Felix Dausch
+ * =====================================================================================
+ */
+
+/**
+ * @module Services
+ */
+(function( $, pm )
+{
+
+ /**
+ * Listens to window's size and trigger 'sizeChange' event if the Bootstrap interval changes.
+ * @class MediaSizeService
+ * @static
+ * @example
+ * $(window).on('sizeChange', function(newValue, oldValue) {
+ * console.log('The interval changed from ' + oldValue + ' to ' + newValue.');
+ * });
+ */
+ pm.service( 'MediaSizeService', function()
+ {
+
+ var bsInterval;
+
+ // recalculation of the current interval on window resize
+ $( window ).resize( calculateMediaSize );
+
+ // initially calculation of the interval
+ $( document ).ready( calculateMediaSize );
+
+ return {
+ interval : getInterval,
+ isInterval: isInterval
+ };
+
+ /**
+ * Get the currently used Bootstrap interval
+ * @function getInterval
+ * @return {"xs"|"sm"|"md"|"lg"}
+ */
+ function getInterval()
+ {
+ if ( !!bsInterval )
+ {
+ calculateMediaSize();
+ }
+
+ return bsInterval;
+ }
+
+ /**
+ * Calculate the currently used Bootstrap interval
+ * @function calculateMediaSize
+ * @private
+ */
+ function calculateMediaSize()
+ {
+ var size;
+ if ( !!window.matchMedia )
+ { // FIX IE support
+ if ( window.matchMedia( '(min-width:1200px)' ).matches )
+ {
+ size = 'lg';
+ }
+ else if ( window.matchMedia( '(min-width:992px)' ).matches )
+ {
+ size = 'md';
+ }
+ else if ( window.matchMedia( '(min-width:768px)' ).matches )
+ {
+ size = 'sm';
+ }
+ else
+ {
+ size = 'xs';
+ }
+ }
+ else
+ {
+ if ( $( window ).width() >= 1200 )
+ {
+ size = 'lg';
+ }
+ else if ( $( window ).width() >= 992 )
+ {
+ size = 'md';
+ }
+ else if ( $( window ).width() >= 768 )
+ {
+ size = 'sm';
+ }
+ else
+ {
+ size = 'xs';
+ }
+ }
+ if ( size != bsInterval )
+ {
+ var oldValue = bsInterval;
+ bsInterval = size;
+ $( window ).trigger( 'sizeChange', [bsInterval, oldValue] );
+ }
+ }
+
+ function isInterval( interval )
+ {
+ var intervalList = interval.replace( /\s/g, '' ).split( ',' );
+ for ( var i = 0; i < intervalList.length; i++ )
+ {
+ if ( intervalList[i] == bsInterval )
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ } );
+
+}( jQuery, PlentyFramework ));
+/**
+ * Licensed under AGPL v3
+ * (https://github.com/plentymarkets/plenty-cms-library/blob/master/LICENSE)
+ * =====================================================================================
+ * @copyright Copyright (c) 2015, plentymarkets GmbH (http://www.plentymarkets.com)
+ * @author Felix Dausch
+ * =====================================================================================
+ */
+
+/**
+ * @module Services
+ */
+(function( $, pm )
+{
+
+ /**
+ * Handling navigation while checkout processes
+ * @class NavigatorService
+ * @static
+ *
+ */
+ pm.service( 'NavigatorService', function( CMS, Checkout )
+ {
+ var navigation = []; // contains navigation list elements
+ var container = []; // content containers
+ var current = -1; // index of currently shown content container
+ var buttonPrev = {}; // navigation buttons
+ var buttonNext = {};
+ var interceptors = {
+ beforeChange: [],
+ afterChange : []
+ };
+ var checkoutStates = [];
+
+ return {
+ init : init,
+ getCurrentContainer: getCurrentContainer,
+ goTo : goTo,
+ beforeChange : beforeChange,
+ afterChange : afterChange,
+ continueChange : continueChange,
+ next : next,
+ previous : previous,
+ goToID : goToID,
+ fillNavigation : fillNavigation
+ };
+
+ /**
+ * Initialize checkout navigation. Shows first container.
+ * @function init
+ * @example
+ * ```html
+ *
+ *
+ * - Checkout Step 1
+ * - Checkout Step 2
+ * - ...
+ *
+ *
+ *
+ *
+ *
+ * Checkout Step 1 Content
+ *
+ *
+ * Checkout Step 2 Content
+ *
+ *
...
+ *
+ * ```
+ */
+ function init()
+ {
+
+ // get elements from DOM
+ navigation = $( '[data-plenty-checkout="navigation"] > li' );
+ container = $( '[data-plenty-checkout="container"] > div' );
+ buttonNext = $( '[data-plenty-checkout="next"]' );
+ buttonPrev = $( '[data-plenty-checkout="prev"]' );
+
+ if ( navigation.length == container.length && container.length > 0 )
+ {
+ var checkout = Checkout.getCheckout();
+
+ container.hide();
+
+ // initialize navigation
+ navigation.each( function( i, elem )
+ {
+ $( elem ).addClass( 'disabled' );
+ // handle navigation click events
+ $( elem ).click( function()
+ {
+ if ( !$( this ).is( '.disabled' ) )
+ {
+ goTo( i );
+ }
+ } );
+ } );
+
+ buttonNext.attr( "disabled", "disabled" );
+ buttonNext.click( function()
+ {
+ next();
+ } );
+
+ buttonPrev.attr( "disabled", "disabled" );
+ buttonPrev.click( function()
+ {
+ previous();
+ } );
+
+ window.addEventListener( 'hashchange', function()
+ {
+ if ( window.location.hash.length > 0 )
+ {
+ goToID( window.location.hash );
+ }
+ else
+ {
+ goTo( 0 );
+ }
+ }, false );
+
+ // initialize GUI
+ // check url param for jumping to tab
+ $.urlParam = function( name )
+ {
+ var results = new RegExp( '[\?&]' + name + '=([^]*)' ).exec( window.location.href );
+ if ( results == null )
+ {
+ return null;
+ }
+ else
+ {
+ return results[1] || 0;
+ }
+ };
+
+ var param = $.urlParam( 'gototab' );
+ // jump to hash from url param 'gototab'
+ if ( window.location.hash.length == 0 && !!param && $( '[data-plenty-checkout-id="' + param + '"]' ).length > 0 )
+ {
+ window.location.hash = param;
+ }
+ // jump to hash
+ else if ( !goToID( window.location.hash ) && current >= 0 )
+ {
+ goTo( current );
+ }
+ else
+ {
+ goTo( 0 );
+ }
+
+ fillNavigation();
+ $( window ).on( 'sizeChange', fillNavigation );
+ $( window ).resize( function()
+ {
+ if ( pm.getInstance().MediaSizeService.interval() == 'xs' )
+ {
+ fillNavigation();
+ }
+ } );
+
+ }
+ }
+
+ /**
+ * Get the currently active checkout container.
+ * @function getCurrentContainer
+ * @return {{id: string, index: number}}
+ */
+ function getCurrentContainer()
+ {
+ if ( current >= 0 )
+ {
+ return {
+ id : $( container[current] ).attr( 'data-plenty-checkout-id' ),
+ index: current
+ };
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ /**
+ * Register an interceptor called before each tab change.
+ * Tabchange will break if any interceptor returns false.
+ * @param {function} interceptor The interceptor callback to register
+ * @chainable
+ * @returns {NavigatorService}
+ * @example
+ * plenty.NavigatorService.beforeChange( function(targetContainer) {
+ * if( targetContainer.id === 'details' ) {
+ * // stop tabchange if user tries to access checkout container with id "details"
+ * return false;
+ * }
+ * return true;
+ * });
+ */
+ function beforeChange( interceptor )
+ {
+ interceptors.beforeChange.push( interceptor );
+ return pm.getInstance().NavigatorService;
+ }
+
+ /**
+ * Register an interceptor called after each tab change.
+ * @param {function} interceptor The interceptor callback to register
+ * @chainable
+ * @returns {NavigatorService}
+ */
+ function afterChange( interceptor )
+ {
+ interceptors.afterChange.push( interceptor );
+ return pm.getInstance().NavigatorService;
+ }
+
+ /**
+ * Call registered interceptors. Break if any interceptor returns false.
+ * Do not call beforeChange-interceptors on initially tabchange
+ * @function resolveInterceptors
+ * @private
+ * @param {"beforeChange"|"afterChange"} identifier Describe which interceptors should be called
+ * @param {number} index the index of the target container
+ * @returns {boolean} Conjunction of all interceptor return values
+ */
+ function resolveInterceptors( identifier, index )
+ {
+ var continueTabChange = true;
+
+ if ( current >= 0 || identifier === 'afterChange' )
+ {
+
+ var currentContainer = getCurrentContainer();
+ var targetContainer = {
+ index: index,
+ id : $( container[index] ).attr( 'data-plenty-checkout-id' )
+ };
+
+ $.each( interceptors[identifier], function( i, interceptor )
+ {
+ if ( interceptor( currentContainer, targetContainer ) === false )
+ {
+ continueTabChange = false;
+ return false;
+ }
+ } );
+ }
+
+ return continueTabChange;
+ }
+
+ /**
+ * Show checkout tab given by index
+ * @function goTo
+ * @param {number} index Index of target tab, starting at 0
+ * @param {boolean} [ignoreInterceptors=false] Set true to not call registered interceptors and force changing
+ * tab
+ */
+ function goTo( index, ignoreInterceptors )
+ {
+
+ var contentChanged = current !== index;
+
+ if ( contentChanged && !ignoreInterceptors )
+ {
+ if ( !resolveInterceptors( "beforeChange", index ) )
+ {
+ return;
+ }
+ }
+
+ current = index;
+
+ if ( !Object.equals( checkoutStates[current], Checkout.getCheckout( true ) ) && contentChanged && !!$( container[current] ).attr( 'data-plenty-checkout-content' ) )
+ {
+ checkoutStates[current] = Checkout.getCheckout( true );
+ // reload tab content
+ CMS.getCategoryContent( $( container[current] ).attr( 'data-plenty-checkout-content' ) )
+ .done( function( response )
+ {
+ $( container[current] ).html( response.data[0] );
+ // continue tab change
+ proceedTabChange( contentChanged );
+ pm.getInstance().bindDirectives( container[current] );
+ $( window ).trigger( 'contentChanged' );
+ } );
+ }
+ else
+ {
+ // continue tab change without reloading tab content
+ proceedTabChange( contentChanged );
+ //pm.getInstance().bindDirectives();
+ }
+
+ }
+
+ function proceedTabChange( contentChanged )
+ {
+
+ // hide content containers
+ $( container ).hide();
+
+ // refresh navigation elements
+ $( navigation ).each( function( i, elem )
+ {
+ $( elem ).removeClass( 'disabled active' );
+
+ $( elem ).find( '[role="tab"]' ).attr( 'aria-selected', 'false' );
+
+ if ( i < current )
+ {
+ // set current element as active
+ $( elem ).addClass( 'visited' );
+ }
+ else
+ {
+ if ( i == current )
+ {
+ $( elem ).addClass( 'active visited' );
+ $( elem ).find( '[role="tab"]' ).attr( 'aria-selected', 'true' );
+ }
+ else
+ {
+ if ( i > current && !$( elem ).is( '.visited' ) )
+ {
+ // disable elements behind active
+ $( elem ).addClass( 'disabled' );
+ }
+ }
+ }
+ } );
+ fillNavigation();
+
+ // hide "previous"-button if first content container is shown
+ if ( current <= 0 )
+ {
+ $( buttonPrev ).attr( "disabled", "disabled" );
+ }
+ else
+ {
+ $( buttonPrev ).removeAttr( "disabled" );
+ }
+
+ // hide "next"-button if last content container is shown
+ if ( current + 1 == navigation.length )
+ {
+ $( buttonNext ).attr( "disabled", "disabled" );
+ }
+ else
+ {
+ $( buttonNext ).removeAttr( "disabled" );
+ }
+
+ // show current content container
+ $( container[current] ).show();
+
+ // set location hash
+ if ( current > 0 )
+ {
+ window.location.hash = $( container[current] ).attr( 'data-plenty-checkout-id' );
+ }
+ else
+ {
+ if ( window.location.hash.length > 0 )
+ {
+ window.location.hash = '';
+ }
+ }
+
+ if ( contentChanged )
+ {
+ resolveInterceptors( "afterChange", current );
+ }
+ }
+
+ /**
+ * Continue interrupted tabchange. Shorthand for: goTo(targetContainer.index, true)
+ * @function continueChange
+ * @param targetContainer The tab-object received from an interceptor
+ */
+ function continueChange( targetContainer )
+ {
+ goTo( targetContainer.index, true );
+ }
+
+ /**
+ * Show next checkout tab if available. Shorthand for
+ *
+ * if (current < navigation.length - 1) {
+ * goTo(current + 1);
+ * }
+ *
+ * @function next
+ */
+ function next()
+ {
+ if ( current < navigation.length - 1 )
+ {
+ goTo( current + 1 );
+ }
+ }
+
+ /**
+ * Show previous checkout tab if available
+ * @function next
+ */
+ function previous()
+ {
+ if ( current > 0 )
+ {
+ goTo( current - 1 );
+ }
+ }
+
+ /**
+ * Show checkout tab given by ID
+ * @function goToID
+ * @param {string} containerID ID of tab to show. Target tab must be marked with
+ * data-plenty-checkout-id="#..."
+ */
+ function goToID( containerID )
+ {
+ if ( containerID == 'next' )
+ {
+ next();
+ return true;
+ }
+ else if ( containerID == 'prev' )
+ {
+ previous();
+ return true;
+ }
+ else
+ {
+ containerID = containerID.replace( '#', '' );
+ $( container ).each( function( i, elem )
+ {
+ if ( $( elem ).attr( 'data-plenty-checkout-id' ) == containerID )
+ {
+ goTo( i );
+ return true;
+ }
+ } );
+ }
+
+ return false;
+ }
+
+ /**
+ * Calculate navigation's width to match its parent element
+ * by increasing its items padding.
+ * @function fillNavigation
+ */
+ function fillNavigation()
+ {
+ // break if manager has not been initialized
+ var navigationCount = navigation.length;
+ if ( navigationCount <= 0 )
+ {
+ return;
+ }
+
+ // reset inline styles
+ $( navigation ).removeAttr( 'style' );
+ $( navigation ).children( 'span' ).removeAttr( 'style' );
+ $( buttonNext ).removeAttr( 'style' );
+ $( buttonPrev ).removeAttr( 'style' );
+
+ var buttonWidth = ($( buttonPrev ).outerWidth() < $( buttonNext ).outerWidth()) ? $( buttonNext ).outerWidth( true ) + 1 : $( buttonPrev ).outerWidth( true ) + 1;
+ $( buttonNext ).css( {width: buttonWidth + 'px'} );
+ $( buttonPrev ).css( {width: buttonWidth + 'px'} );
+
+ // calculate width to fill
+ var width = $( navigation ).parent().parent().outerWidth( true ) - ( 2 * buttonWidth);
+ width -= parseInt( $( navigation ).parent().css( 'marginLeft' ) ) + parseInt( $( navigation ).parent().css( 'marginRight' ) );
+
+ var padding = width;
+ var tabWidth = [];
+
+ $( navigation ).each( function( i, elem )
+ {
+ padding -= parseInt( $( elem ).css( 'marginLeft' ) );
+ padding -= parseInt( $( elem ).css( 'marginRight' ) );
+
+ tabWidth[i] = $( elem ).children( 'span' ).width();
+ padding -= tabWidth[i];
+
+ padding -= parseInt( $( elem ).children( 'span' ).css( 'marginLeft' ) );
+ padding -= parseInt( $( elem ).children( 'span' ).css( 'marginRight' ) );
+ } );
+
+ var paddingEachItem = parseInt( padding / navigationCount );
+
+ var paddingLeft, paddingRight;
+ if ( paddingEachItem % 2 == 1 )
+ {
+ paddingLeft = ( paddingEachItem / 2 ) + 0.5;
+ paddingRight = ( paddingEachItem / 2 ) - 0.5;
+ }
+ else
+ {
+ paddingLeft = paddingEachItem / 2;
+ paddingRight = paddingEachItem / 2;
+ }
+
+ var paddingLastItem = parseInt( padding - ( ( navigationCount - 1 ) * ( paddingLeft + paddingRight ) ) );
+ var paddingLastLeft, paddingLastRight;
+ if ( paddingLastItem % 2 == 1 )
+ {
+ paddingLastLeft = ( paddingLastItem / 2 ) + 0.5;
+ paddingLastRight = ( paddingLastItem / 2) - 0.5;
+ }
+ else
+ {
+ paddingLastLeft = paddingLastItem / 2;
+ paddingLastRight = paddingLastItem / 2;
+ }
+
+ var diff = width;
+ $( navigation ).each( function( i, elem )
+ {
+ if ( i < navigationCount - 1 )
+ {
+ $( elem ).children( 'span' ).css( {'paddingLeft': paddingLeft + 'px', 'paddingRight': paddingRight + 'px'} ); //.parent().css({ width: ( tabWidth[i] + paddingLeft + paddingRight + parseInt( $(elem).children('span').css('marginLeft') ) + parseInt( $(elem).children('span').css('marginRight') ) )+'px' });
+ }
+ else
+ {
+ $( elem ).children( 'span' ).css( {'paddingLeft': paddingLastLeft + 'px', 'paddingRight': paddingLastRight + 'px'} ); //.parent().css({ width: ( tabWidth[i] + paddingLastLeft + paddingLastRight + parseInt( $(elem).children('span').css('marginLeft') ) + parseInt( $(elem).children('span').css('marginRight') ) )+'px' });
+ }
+ } );
+
+ //$(navigation).parent().css('marginRight', 0);
+ }
+
+ }, ['CMSFactory', 'CheckoutFactory'] );
+
+}( jQuery, PlentyFramework ));
+/**
+ * Licensed under AGPL v3
+ * (https://github.com/plentymarkets/plenty-cms-library/blob/master/LICENSE)
+ * =====================================================================================
+ * @copyright Copyright (c) 2015, plentymarkets GmbH (http://www.plentymarkets.com)
+ * @author Magnus Martin
+ * =====================================================================================
+ */
+
+
+(function( $, pm )
+{
+ pm.service( 'PostfinderService', function( API, Modal, UIFactory )
+ {
+ var packstationID = '';
+ var shippingFields = {};
+ var numberOfResults = {};
+ var result = {};
+
+ return {
+ openPostfinderModal: openPostfinderModal,
+ isPackstation : isPackstation
+ };
+
+ function isPackstation()
+ {
+ var street = $( 'input[name="Street"]' ).val();
+ return ( street.toUpperCase() == "PACKSTATION" || street.toUpperCase() == "POSTFILIALE" );
+ }
+
+ function openPostfinderModal()
+ {
+ shippingFields = {
+ PostfinderItemStreet : $( 'input[name="Street"]', '[data-plenty-checkout-form="shippingAddress"]' ),
+ PostfinderItemZIP : $( 'input[name="ZIP"]', '[data-plenty-checkout-form="shippingAddress"]' ),
+ PostfinderItemCity : $( 'input[name="City"]', '[data-plenty-checkout-form="shippingAddress"]' ),
+ PostfinderItemHouseNo: $( 'input[name="HouseNo"]', '[data-plenty-checkout-form="shippingAddress"]' )
+
+ };
+
+ shippingFields.PostfinderItemStreet.val( '' );
+
+ if ( (shippingFields.PostfinderItemZIP.val().length > 2 || shippingFields.PostfinderItemCity.val().length > 2) )
+ {
+
+ API.get( '/rest/checkout/shippingaddresspostfinderlist/',
+ {
+ suggestionType: "postfinder",
+ zip : shippingFields.PostfinderItemZIP.val(),
+ city : shippingFields.PostfinderItemCity.val()
+ } )
+
+ .done( function( response )
+ {
+ result = response.data;
+ numberOfResults = result.length;
+
+ if ( numberOfResults == 0 )
+ {
+ showErrorMessage();
+ }
+
+ var params = {
+ addresses: []
+ };
+
+ for ( var i = 0; i < numberOfResults; i++ )
+ {
+ var dimension = 'km';
+ var distInMeters = result[i].PostfinderItemDistance;
+ var distInKilometers = distInMeters / 1000;
+ distInKilometers = ((Math.round( distInKilometers * 100 ) / 100).toFixed( 2 )).replace( '.', ',' );
+
+ if ( distInMeters < 1000 )
+ {
+ distInKilometers = distInMeters;
+ dimension = 'm';
+ }
+
+ params.addresses.push( {
+ index : i,
+ dimension: dimension,
+ type : result[i].PostfinderItemIsPackstation ? 'Packstation' : 'Postfiliale',
+ number : result[i].PostfinderItemIsPackstation ? result[i].PostfinderItemPackstationNo : result[i].PostfinderItemPostfilialNo,
+ street : result[i].PostfinderItemStreet,
+ houseNo : result[i].PostfinderItemHouseNo,
+ zip : result[i].PostfinderItemZIP,
+ city : result[i].PostfinderItemCity,
+ district : result[i].PostfinderItemDistrict,
+ distance : distInKilometers,
+ remark : result[i].PostfinderItemRemark
+ } );
+ }
+
+ var html = pm.compileTemplate( 'addressSuggestions/postFinder.html', params );
+
+ Modal.prepare()
+ .setTitle( pm.translate( 'Packstations and post offices in your area' ) )
+ .setContent( html )
+ .setClass( 'checkout' )
+ .onConfirm( function()
+ {
+ shippingFields.PostfinderItemCity.removeClass( 'has-error' ).addClass( 'has-success' );
+ $( 'label[for="' + shippingFields.PostfinderItemCity.attr( 'id' ) + '"]' ).removeClass( 'has-error' ).addClass( 'has-success' );
+
+ shippingFields.PostfinderItemZIP.removeClass( 'has-error' ).addClass( 'has-success' );
+ $( 'label[for="' + shippingFields.PostfinderItemZIP.attr( 'id' ) + '"]' ).removeClass( 'has-error' ).addClass( 'has-success' );
+
+ shippingFields.PostfinderItemStreet.removeClass( 'has-error' ).addClass( 'has-success' );
+ $( 'label[for="' + shippingFields.PostfinderItemStreet.attr( 'id' ) + '"]' ).removeClass( 'has-error' ).addClass( 'has-success' );
+
+ shippingFields.PostfinderItemHouseNo.removeClass( 'has-error' ).addClass( 'has-success' );
+ $( 'label[for="' + shippingFields.PostfinderItemHouseNo.attr( 'id' ) + '"]' ).removeClass( 'has-error' ).addClass( 'has-success' );
+
+ packstationID = $( 'input[type="radio"][name="postfinder"]:checked' ).val();
+
+ if ( result[packstationID].PostfinderItemIsPackstation )
+ {
+ $( shippingFields.PostfinderItemStreet ).val( 'PACKSTATION' );
+ $( shippingFields.PostfinderItemHouseNo ).val( result[packstationID].PostfinderItemPackstationNo );
+ }
+ else
+ {
+ $( shippingFields.PostfinderItemStreet ).val( 'POSTFILIALE' );
+ $( shippingFields.PostfinderItemHouseNo ).val( result[packstationID].PostfinderItemPostfilialNo );
+ }
+ $( shippingFields.PostfinderItemStreet ).trigger( 'change' );
+
+ $( shippingFields.PostfinderItemCity ).val( result[packstationID].PostfinderItemCity );
+ $( shippingFields.PostfinderItemZIP ).val( result[packstationID].PostfinderItemZIP );
+ return true;
+ } )
+ .show()
+ } );
+ }
+ else
+ {
+ showErrorMessage();
+ }
+
+ }
+
+ function showErrorMessage()
+ {
+ UIFactory.throwError( 0, pm.translate( 'Please enter a ZIP code and/or a city.' ) );
+
+ shippingFields.PostfinderItemCity.removeClass( 'has-success' ).addClass( 'has-error' );
+ $( 'label[for="' + shippingFields.PostfinderItemCity.attr( 'id' ) + '"]' ).removeClass( 'has-success' ).addClass( 'has-error' );
+
+ shippingFields.PostfinderItemZIP.removeClass( 'has-success' ).addClass( 'has-error' );
+ $( 'label[for="' + shippingFields.PostfinderItemZIP.attr( 'id' ) + '"]' ).removeClass( 'has-success' ).addClass( 'has-error' );
+
+ shippingFields.PostfinderItemCity.focus(function() {
+ $(this).removeClass('has-error');
+ var inputId = $(this).attr('id');
+ $(this).closest('.form-group').find('[for="' + inputId + '"]').removeClass('has-error');
+ });
+
+ shippingFields.PostfinderItemZIP.focus(function() {
+ $(this).removeClass('has-error');
+ var inputId = $(this).attr('id');
+ $(this).closest('.form-group').find('[for="' + inputId + '"]').removeClass('has-error');
+ });
+ }
+ }, ['APIFactory', 'ModalFactory', 'UIFactory'] );
+
+}( jQuery, PlentyFramework ));
+/**
+ * Licensed under AGPL v3
+ * (https://github.com/plentymarkets/plenty-cms-library/blob/master/LICENSE)
+ * =====================================================================================
+ * @copyright Copyright (c) 2015, plentymarkets GmbH (http://www.plentymarkets.com)
+ * @author Felix Dausch
+ * =====================================================================================
+ */
+
+/**
+ * @module Services
+ */
+(function( $, pm )
+{
+
+ /**
+ * Provide templates for social share providers to inject them dynamically.
+ * @class SocialShareService
+ * @static
+ */
+ pm.service( 'SocialShareService', function()
+ {
+
+ //TODO: move to global variables
+ if ( typeof(socialLangLocale) == 'undefined' )
+ {
+ socialLangLocale = 'en_US';
+ }
+ if ( typeof(socialLang) == 'undefined' )
+ {
+ socialLang = 'en';
+ }
+
+ return {
+ getSocialService: getService
+ };
+
+ /**
+ * Get the template for social media provider
+ * @function getService
+ * @param {string} identifier name of the social media provider to get the template for
+ * @returns {string} the template to inject in DOM
+ */
+ function getService( identifier )
+ {
+ var services = {
+ 'facebook-like': '',
+
+ 'facebook-recommend': '',
+
+ 'twitter': '',
+
+ 'google-plus': ''
+ + '',
+ };
+
+ return services[identifier];
+ }
+
+ /**
+ * get the canonical URL if defined
+ * @function getURL
+ * @private
+ * @return {string} The Canonical URL if defined or the current URI
+ */
+ function getURI()
+ {
+ var uri = document.location.href;
+ var canonical = $( "link[rel=canonical]" ).attr( "href" );
+
+ if ( canonical && canonical.length > 0 )
+ {
+ if ( canonical.indexOf( "http" ) < 0 )
+ {
+ canonical = document.location.protocol + "//" + document.location.host + canonical;
+ }
+ uri = canonical;
+ }
+
+ return uri;
+ }
+
+ /**
+ * returns content of <meta name="" content=""> tags or '' if empty/non existant
+ * @function getMeta
+ * @private
+ * @param {string} name The meta name to get the value of;
+ */
+ function getMeta( name )
+ {
+ var metaContent = $( 'meta[name="' + name + '"]' ).attr( 'content' );
+ return metaContent || '';
+ }
+
+ /**
+ * create tweet text from content of <meta name="DC.title"> and <meta name="DC.creator">
+ * fallback to content of <title> tag
+ * @function getTweetText
+ * @private
+ */
+ function getTweetText()
+ {
+ var title = getMeta( 'DC.title' );
+ var creator = getMeta( 'DC.creator' );
+
+ if ( title.length > 0 && creator.length > 0 )
+ {
+ title += ' - ' + creator;
+ }
+ else
+ {
+ title = $( 'title' ).text();
+ }
+
+ return encodeURIComponent( title );
+ }
+
+ } );
+
+}( jQuery, PlentyFramework ));
+/**
+ * Licensed under AGPL v3
+ * (https://github.com/plentymarkets/plenty-cms-library/blob/master/LICENSE)
+ * =====================================================================================
+ * @copyright Copyright (c) 2015, plentymarkets GmbH (http://www.plentymarkets.com)
+ * @author Felix Dausch
+ * =====================================================================================
+ */
+
+/**
+ * @module Services
+ */
+(function( $, pm )
+{
+
+ /**
+ * Provide methods for client-side form validation.
+ * @class ValidationService
+ * @static
+ */
+ pm.service( 'ValidationService', function()
+ {
+
+ return {
+ validate: validate
+ };
+
+ /**
+ * Check if element is a form element (input, select, textarea) or search for child form elements
+ * @function getFormControl
+ * @private
+ * @param {object} element the element to get the form element from
+ * @return {object} a valid form element (input, select, textarea)
+ */
+ function getFormControl( element )
+ {
+ element = $( element );
+ if ( element.is( 'input' ) || element.is( 'select' ) || element.is( 'textarea' ) )
+ {
+ return element;
+ }
+ else
+ {
+ if ( element.find( 'input' ).length > 0 )
+ {
+ return element.find( 'input' );
+ }
+
+ else if ( element.find( 'select' ).length > 0 )
+ {
+ return element.find( 'select' );
+ }
+
+ else if ( element.find( 'textarea' ).length > 0 )
+ {
+ return element.find( 'textarea' );
+ }
+
+ else
+ {
+ return null;
+ }
+ }
+
+ }
+
+ /**
+ * Check given element has any value
+ * @function validateText
+ * @private
+ * @param {object} formControl the form element to validate
+ * @return {boolean}
+ */
+ function validateText( formControl )
+ {
+ // check if formControl is no checkbox or radio
+ if ( formControl.is( 'input' ) || formControl.is( 'select' ) || formControl.is( 'textarea' ) )
+ {
+ // check if length of trimmed value is greater then zero
+ return $.trim( formControl.val() ).length > 0;
+
+ }
+ else
+ {
+ console.error( 'Validation Error: Cannot validate Text for <' + formControl.prop( "tagName" ) + '>' );
+ return false;
+ }
+ }
+
+ /**
+ * Check given element's value is a valid email-address
+ * @function validateMail
+ * @private
+ * @param {object} formControl the form element to validate
+ * @return {boolean}
+ */
+ function validateMail( formControl )
+ {
+ var mailRegExp = /[a-z0-9!#$%&'*+\/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+\/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?/;
+ if ( validateText( formControl ) )
+ {
+ return mailRegExp.test( $.trim( formControl.val() ) );
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ /**
+ * Check given element's value is a valid number
+ * @function validateNumber
+ * @private
+ * @param {object} formControl the form element to validate
+ * @return {boolean}
+ */
+ function validateNumber( formControl )
+ {
+ if ( validateText( formControl ) )
+ {
+ return $.isNumeric( $.trim( formControl.val() ) );
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ /**
+ * Check given element's value is equal to a references value
+ * @function validateValue
+ * @private
+ * @param {object} formControl the form element to validate
+ * @param {string} reference the required value
+ * @return {boolean}
+ */
+ function validateValue( formControl, reference )
+ {
+ if ( $( reference ).length > 0 )
+ {
+ return $.trim( formControl.val() ) == $.trim( $( reference ).val() );
+ }
+ else
+ {
+ return $.trim( formControl.val() ) == reference;
+ }
+ }
+
+ function visibility( formControl )
+ {
+ return formControl.is( ':visible' );
+ }
+
+ function isEnabled( formControl )
+ {
+ return formControl.is( ':enabled' );
+ }
+
+ /**
+ * Validate a form. Triggers event 'validationFailed' if any element has an invalid value
+ * @function validate
+ * @param {object} form The form element to validate
+ * @returns {boolean}
+ * @example
+ * ```html
+ *
+ *
+ * ```
+ *
+ * @example
+ * $(form).on('validationFailed', function(missingFields) {
+ * // handle missing fields
+ * });
+ */
+ function validate( form, errorClass )
+ {
+ var formControl, formControls, validationKey, currentHasError, group, checked, checkedMin, checkedMax, attrValidate, validationKeys, formControlAttrType;
+ var $form = $( form );
+ errorClass = errorClass || 'has-error';
+ var missingFields = [];
+ var hasError = false;
+
+ // check every required input inside form
+ $form.find( '[data-plenty-validate], input.Required' ).each( function( i, elem )
+ {
+ attrValidate = $( elem ).attr( 'data-plenty-validate' );
+ formControls = getFormControl( elem )
+ // validate text inputs
+ validationKeys = !!attrValidate ? attrValidate : 'text';
+ validationKeys = validationKeys.split( ',' );
+
+ for ( var i = 0, length = formControls.length; i < length; i++ )
+ {
+ formControl = $( formControls[i] );
+ formControlAttrType = formControl.attr( 'type' );
+
+ if ( !visibility( formControl ) || !isEnabled( formControl ) )
+ {
+ return;
+ }
+
+ validationKey = validationKeys[i].trim() || validationKeys[0].trim();
+ currentHasError = false;
+
+ // formControl is textfield (text, mail, password) or textarea
+ if ( (formControl.is( 'input' )
+ && formControlAttrType != 'radio'
+ && formControlAttrType != 'checkbox')
+ || formControl.is( 'textarea' ) )
+ {
+ switch ( validationKey )
+ {
+
+ case 'text':
+ currentHasError = !validateText( formControl );
+ break;
+
+ case 'mail':
+ currentHasError = !validateMail( formControl );
+ break;
+
+ case 'number':
+ currentHasError = !validateNumber( formControl );
+ break;
+
+ case 'value':
+ currentHasError = !validateValue( formControl, $( elem ).attr( 'data-plenty-validation-value' ) );
+ break;
+
+ case 'none':
+ // do not validate
+ break;
+
+ default:
+ console.error( 'Form validation error: unknown validate property: "' + attrValidate + '"' );
+ break;
+ }
+ }
+ else if ( formControl.is( 'input' )
+ && (formControlAttrType == 'radio'
+ || formControlAttrType == 'checkbox') )
+ {
+ // validate radio buttons
+ group = formControl.attr( 'name' );
+ checked = $form.find( 'input[name="' + group + '"]:checked' ).length;
+
+ if ( formControlAttrType == 'radio' )
+ {
+ checkedMin = 1;
+ checkedMax = 1;
+ }
+ else
+ {
+ eval( "var minMax = " + attrValidate );
+ checkedMin = !!minMax ? minMax.min : 1;
+ checkedMax = !!minMax ? minMax.max : 1;
+ }
+
+ currentHasError = ( checked < checkedMin || checked > checkedMax );
+
+ }
+ else if ( formControl.is( 'select' ) )
+ {
+ // validate selects
+ currentHasError = ( formControl.val() == '' || formControl.val() == '-1' );
+ }
+ else
+ {
+ console.error( 'Form validation error: ' + $( elem ).prop( "tagName" ) + ' does not contain an form element' );
+ return;
+ }
+
+ if ( currentHasError )
+ {
+ hasError = true;
+ missingFields.push( formControl );
+
+ if ( formControls.length > 1 )
+ {
+ formControl.addClass( errorClass );
+ $form.find( 'label[for="' + formControl.attr( 'id' ) + '"]' ).addClass( errorClass );
+ }
+ else
+ {
+ $( elem ).addClass( errorClass );
+ }
+ }
+ }
+
+ } );
+
+ // scroll to element on 'validationFailed'
+ $form.on( 'validationFailed', function()
+ {
+ var distanceTop = 50;
+ var $error = $form.find( '.' + errorClass ).first();
+ var errorOffset = $error.offset().top;
+ var $scrollTarget = $( 'html, body' );
+
+ // if form is inside of modal, scroll modal instead of body
+ if ( $form.parents( '.modal' ).length > 0 )
+ {
+ $scrollTarget = $form.parents( '.modal' ).find( '.modal-body' );
+ errorOffset = $scrollTarget.scrollTop() - ( $scrollTarget.offset().top - $error.offset().top );
+
+ }
+ else if ( $form.is( '.modal' ) )
+ {
+ $scrollTarget = $form.find( '.modal-body' );
+ errorOffset = $scrollTarget.scrollTop() - ( $scrollTarget.offset().top - $error.offset().top );
+ }
+
+ // only scroll if error is outside of viewport
+ if ( errorOffset - distanceTop < window.pageYOffset || errorOffset > (window.pageYOffset + window.innerHeight) )
+ {
+ $scrollTarget.animate( {
+ scrollTop: errorOffset - distanceTop
+ } );
+ }
+ } );
+
+ if ( hasError )
+ {
+ // remove error class on focus
+ $form.find( '.' + errorClass ).each( function( i, elem )
+ {
+ formControl = $( getFormControl( elem ) );
+ formControl.on( 'focus click', function()
+ {
+ var $errorElement = $(elem);
+ $errorElement.removeClass( errorClass );
+ $form.find( 'label[for="' + $( this ).attr( 'id' ) + '"]' ).removeClass( errorClass );
+ } );
+ } );
+
+ $form.trigger( 'validationFailed', [missingFields] );
+ }
+
+ var callback = $form.attr( 'data-plenty-callback' );
+
+ if ( !hasError && !!callback && callback != "submit" && typeof window[callback] == "function" )
+ {
+
+ var fields = {};
+ $form.find( 'input, textarea, select' ).each( function()
+ {
+ if ( $( this ).attr( 'type' ) == 'checkbox' )
+ {
+ fields[$( this ).attr( 'name' )] = $( this ).is( ':checked' );
+ }
+ else
+ {
+ fields[$( this ).attr( 'name' )] = $( this ).val();
+ }
+ } );
+
+ window[callback]( fields );
+ return false;
+ }
+ else
+ {
+ return !hasError;
+ }
+ }
+ } );
+
+ /**
+ * jQuery-Plugin to calling {{#crossLink "ValidationService/validate"}}ValidationService.validate{{/crossLink}}
+ * on jQuery wrapped elements.
+ * @return {boolean}
+ */
+ $.fn.validateForm = function()
+ {
+ return pm.getInstance().ValidationService.validate( this );
+ };
+
+ /**
+ * jQuery-Plugin to get the values of contained form elements.
+ * @return {object}
+ */
+ $.fn.getFormValues = function()
+ {
+
+ var form = this;
+ var values = {};
+
+ function inject( position, value )
+ {
+ var match = position.match( /^([^\[]+)(.*)/ );
+
+ if ( !!match[2] )
+ {
+ var exp = /\[([^\]]+)]/g;
+ var child;
+ var children = [];
+ children[0] = match[1];
+ while ( (child = exp.exec( match[2] )) !== null )
+ {
+ children.push( child[1] );
+ }
+
+ for ( var i = children.length - 1; i >= 0; i-- )
+ {
+ var val = {};
+ val[children[i]] = value;
+ value = val;
+ }
+ values = $.extend( true, values, value );
+ }
+ else
+ {
+ values[match[1]] = value;
+ }
+ }
+
+ form.find( 'input, select, textarea' ).each( function( i, elem )
+ {
+ if ( !!$( elem ).attr( 'name' ) )
+ {
+ if ( $( elem ).attr( 'type' ) == "checkbox" )
+ {
+ // get checkbox group
+ var groupValues = [];
+ $( form ).find( '[name="' + $( elem ).attr( 'name' ) + '"]:checked' ).each( function( j, checkbox )
+ {
+ groupValues.push( $( checkbox ).val() );
+ } );
+ inject( $( elem ).attr( 'name' ), groupValues );
+ }
+ else if ( $( elem ).attr( 'type' ) == 'radio' )
+ {
+ if ( $( elem ).is( ':checked' ) )
+ {
+ inject( $( elem ).attr( 'name' ), $( elem ).val() );
+ }
+ }
+ else
+ {
+ inject( $( elem ).attr( 'name' ), $( elem ).val() );
+ }
+ }
+
+ } );
+ return values;
+ }
+}( jQuery, PlentyFramework ));
+/**
+ * Services provide functions to be called from the instanced PlentyFramework.
+ * Services can inject Factories and can be injected into Directives. The are also
+ * available from the global instance of PlentyFramework
+ * @module Services
+ * @main Services
+ * @example
+ * PlentyFramework.service('ServiceName', serviceFunctions() {
+ * return {
+ * functionInService: function() {}
+ * }
+ * });
+ * //...
+ * plenty.ServiceName.functionInService/();
+ */
+/**
+ * Licensed under AGPL v3
+ * (https://github.com/plentymarkets/plenty-cms-library/blob/master/LICENSE)
+ * =====================================================================================
+ * @copyright Copyright (c) 2015, plentymarkets GmbH (http://www.plentymarkets.com)
+ * @author Felix Dausch
+ * =====================================================================================
+ */
+
+(function( $, pm )
+{
+ pm.directive( 'Authentication', function( AuthenticationService )
+ {
+ return {
+ login: login
+ };
+
+ function login( elem )
+ {
+ pm.getRecentEvent().preventDefault();
+ AuthenticationService.customerLogin( $( elem ) );
+ }
+ }, ["AuthenticationService"] );
+
+}( jQuery, PlentyFramework ));
+(function( $, pm )
+{
+ pm.directive( 'Basket', function( BasketService )
+ {
+
+ return {
+ addBasketItem : addBasketItem,
+ changeItemQuantity: changeItemQuantity,
+ setItemQuantity : setItemQuantity
+ };
+
+ function addBasketItem( elem )
+ {
+ pm.getRecentEvent().preventDefault();
+ //init
+ var basketItemsList = {};
+ var $elem = $( elem );
+ var parentForm = $elem.parents( 'form' );
+
+ basketItemsList.BasketItemItemID = parentForm.find( '[name="ArticleID"]' ).val();
+ basketItemsList.BasketItemPriceID = parentForm.find( '[name="SYS_P_ID"]' ).val();
+ basketItemsList.BasketItemQuantity = parentForm.find( '[name="ArticleQuantity"]' ).val();
+ basketItemsList.BasketItemBranchID = parentForm.find( '[name="source_category"]' ).val();
+
+ //attributes
+ var attributeInputsList = parentForm.find( '[name^="ArticleAttribute"]' );
+ var attributesList = [];
+
+ $.each( attributeInputsList, function( idx, elem )
+ {
+ var match = elem.name.match( /^ArticleAttribute\[\d+]\[\d+]\[(\d+)]$/ );
+ if ( match && match[1] )
+ {
+ attributesList.push( {
+ BasketItemAttributeID : match[1],
+ BasketItemAttributeValueID: $( elem ).val()
+ } );
+ }
+ } );
+
+ if ( attributesList.length != 0 )
+ {
+ basketItemsList.BasketItemAttributesList = attributesList;
+ }
+
+ //add basketItem and refresh previewLists
+ BasketService.addItem( [basketItemsList] );
+
+ }
+
+ function changeItemQuantity( elem, increment )
+ {
+ var $elem = $( elem );
+ var $quantityInput = $elem.parent().find( 'input' );
+ var maxLength = parseInt( $quantityInput.attr( 'maxlength' ) ) || 5;
+ var value = parseInt( $quantityInput.val() ) + increment;
+
+ var isBasketView = $elem.parents( '[data-basket-item-id]' ).length > 0;
+
+ if ( isBasketView )
+ {
+ if ( (value + '').length <= maxLength && value >= 0 )
+ {
+ $quantityInput.val( value );
+ }
+
+ var timeout = $elem.data( 'timeout' );
+
+ if ( !!timeout )
+ {
+ window.clearTimeout( timeout );
+ }
+
+ timeout = window.setTimeout( function()
+ {
+ $quantityInput.trigger( 'change' );
+ }, 1000 );
+
+ $elem.data( 'timeout', timeout );
+ }
+ else {
+ if ( (value + '').length <= maxLength && value >= 1 )
+ {
+ $quantityInput.val( value );
+ }
+ }
+ }
+
+ function setItemQuantity( basketItemID, input )
+ {
+ BasketService.setItemQuantity(
+ basketItemID,
+ parseInt( $( input ).val() )
+ ).fail( function()
+ {
+ // reset input's value on cancel
+ var basketItem = BasketService.getItem( basketItemID );
+ $( input ).val( basketItem.BasketItemQuantity );
+ } );
+ }
+
+ }, ['BasketService'] );
+}( jQuery, PlentyFramework ));
+/**
+ * Mobile dropdowns
+ * Toggles dropdowns using css class 'open' instead of pseudo class :hover
+ * Usage:
+ *
+ * ...
+ *
+ *
+ * possible values for CONDITION
+ * "touch" : use 'open'-class if device is touch-device AND media size is 'md' or 'lg'
+ * "toggle-xs-sm-or-touch" : use 'open'-class if device is "touch" (as above) OR media size is 'xs' or 'sm'
+ *
+ */
+(function( $, pm )
+{
+ pm.directive( 'MobileDropdown', function( MediaSize )
+ {
+ // store all dropdown elements
+ var dropdownElements = [];
+
+ // store dropdown elements which should be closed by clicking outside the element itself
+ var closableDropdownElements = [];
+
+ return {
+ initDropdowns: initDropdowns,
+ openDropdown: openDropdown,
+ slideDropdown: slideDropdown
+ };
+
+ function initDropdowns()
+ {
+ $(window).on('orientationchange sizeChange', function() {
+ resetDropdowns( dropdownElements );
+ });
+
+ $( 'html' ).click( function( e ) {
+ resetDropdowns( closableDropdownElements );
+ });
+ }
+
+ function resetDropdowns( dropdownList )
+ {
+
+ for( var i = 0; i < dropdownList.length; i++ )
+ {
+ $( dropdownList[i] ).removeClass('open');
+ }
+
+ }
+
+ function openDropdown( elem, closable )
+ {
+
+ var $elem = $( elem );
+ var $parent = $elem.parent();
+
+ if( Modernizr.touch )
+ {
+ if ( MediaSize.isInterval('md, lg') && !$parent.is( '.open' ) )
+ {
+
+ // avoid redirecting
+ pm.getRecentEvent().preventDefault();
+
+ // hide other dropdowns
+ resetDropdowns( dropdownElements );
+
+ // show dropdown
+ $parent.addClass( 'open' );
+
+ if ( $.inArray( $parent[0], dropdownElements ) < 0 )
+ {
+ dropdownElements.push( $parent[0] );
+ }
+
+ if ( !!closable && $.inArray( $parent[0], closableDropdownElements ) < 0 )
+ {
+ closableDropdownElements.push( $parent[0] );
+ }
+
+ // avoid closing popup by clicking itself
+ $parent.off( 'click' );
+ $parent.on( 'click', function( e )
+ {
+ e.stopPropagation();
+ } );
+ }
+
+ }
+ else
+ {
+ // redirect to href
+ // do nothing
+ }
+
+ }
+
+ function slideDropdown( elem )
+ {
+ var $elem = $( elem );
+ var $elemParent = $elem.parent();
+
+ $elemParent.addClass( 'animating' );
+ $elem.siblings( 'ul' ).slideToggle( 200, function()
+ {
+ if ( $elemParent.is( '.open' ) )
+ {
+ $elemParent.removeClass( 'open' );
+ }
+ else
+ {
+ $elemParent.addClass( 'open' );
+ if( $.inArray( $elemParent[0], dropdownElements) < 0 )
+ {
+ dropdownElements.push( $elemParent[0] );
+ }
+ }
+ $elem.siblings( 'ul' ).removeAttr( 'style' );
+ $elemParent.removeClass( 'animating' );
+ } );
+ }
+
+ }, ['MediaSizeService'] );
+}( jQuery, PlentyFramework ));
+(function( $, pm )
+{
+ pm.directive( 'Redirect', function( MediaSizeService, NavigatorService )
+ {
+
+ return {
+ to : to,
+ toCheckoutTab: toCheckoutTab
+ };
+
+ function to( href )
+ {
+ if ( MediaSizeService.interval() != 'xs' )
+ {
+ if ( $( href ).length > 0 )
+ {
+ window.location.assign( $( href ).attr( 'href' ) );
+ }
+ else
+ {
+ window.location.assign( href );
+ }
+ }
+ }
+
+ function toCheckoutTab( tabID )
+ {
+ NavigatorService.goToID( tabID );
+ }
+
+ }, ['MediaSizeService', 'NavigatorService'] );
+}( jQuery, PlentyFramework ));
+(function( $, pm )
+{
+ pm.directive( 'Tab', function( MediaSize )
+ {
+
+ var tabGroups = {};
+
+ return {
+ showTab : showTab,
+ initRemoteLabel: initRemoteLabel,
+ initRemoteTab : initRemoteTab,
+ showRemoteTab : showRemoteTab
+ };
+
+ function showTab( tabSelector )
+ {
+ $( tabSelector ).tab( 'show' );
+ }
+
+ function initRemoteLabel( $elem, tabID, groupID )
+ {
+ if ( !tabGroups[groupID] )
+ {
+ tabGroups[groupID] = new TabGroup();
+ }
+
+ if ( !tabGroups[groupID].getTab( tabID ) )
+ {
+ tabGroups[groupID].addTab( tabID );
+ }
+
+ tabGroups[groupID].getTab( tabID ).addLabel( $elem );
+ }
+
+ function initRemoteTab( $elem, tabID, groupID )
+ {
+ if ( !tabGroups[groupID] )
+ {
+ tabGroups[groupID] = new TabGroup();
+ }
+
+ if ( !tabGroups[groupID].getTab( tabID ) )
+ {
+ tabGroups[groupID].addTab( tabID );
+ }
+
+ tabGroups[groupID].getTab( tabID ).setContent( $elem );
+ }
+
+ function showRemoteTab( tabID, groupID, interval )
+ {
+ if( MediaSize.isInterval( interval ) )
+ {
+ pm.getRecentEvent().preventDefault();
+
+ if ( !!tabGroups[groupID] && !!tabGroups[groupID].getTab( tabID ) )
+ {
+ tabGroups[groupID].showTab( tabID );
+ }
+
+ }
+ }
+
+ function TabGroup()
+ {
+ var tabs = {};
+ var activeTab;
+
+ return {
+ addTab : addTab,
+ showTab: showTab,
+ getTab : getTab,
+ resetTabs: resetTabs
+ };
+
+ function addTab( tabID )
+ {
+ tabs[tabID] = new Tab( tabID );
+ return tabs[tabID];
+ }
+
+ function showTab( tabID )
+ {
+ var zIndex = 0;
+ if ( !!activeTab )
+ {
+ // activeTab is set
+ zIndex = parseInt( activeTab.getContent().parent().css( 'zIndex' ) );
+ activeTab.hide();
+ activeTab.getContent().parent().css( 'zIndex', zIndex - 1 );
+ }
+ else
+ {
+ // activeTab not set before
+ for ( var tab in tabs )
+ {
+ if( !!tabs[tab].getContent() )
+ {
+ var currentZ = parseInt( tabs[tab].getContent().parent().css( 'zIndex' ) );
+ if ( zIndex == 0 || currentZ < zIndex )
+ {
+ zIndex = currentZ;
+ }
+ tabs[tab].hide();
+ }
+ }
+
+ for ( var tab in tabs )
+ {
+ if( !!tabs[tab].getContent() )
+ {
+ tabs[tab].getContent().parent().css( 'zIndex', zIndex - 1 );
+ }
+ }
+
+ $(window ).on('sizeChange', resetTabs);
+ }
+
+ activeTab = tabs[tabID];
+ activeTab.getContent().parent().css( 'zIndex', zIndex );
+ activeTab.show();
+ }
+
+ function getTab( tabID )
+ {
+ return tabs[tabID];
+ }
+
+ function resetTabs()
+ {
+ for ( var tab in tabs )
+ {
+ if( !!tabs[tab].getContent() )
+ {
+ tabs[tab].show();
+ }
+ }
+
+ activeTab = null;
+ }
+ }
+
+ function Tab( id )
+ {
+ var $labels = [];
+ var $content;
+ var tabID = id;
+
+ return {
+ addLabel : addLabel,
+ setContent: setContent,
+ getContent: getContent,
+ getID : getID,
+ show : show,
+ hide : hide
+ };
+
+ function getID()
+ {
+ return tabID;
+ }
+
+ function addLabel( label )
+ {
+ $labels.push( label );
+ return this;
+ }
+
+ function setContent( content )
+ {
+ $content = content;
+ return this;
+ }
+
+ function getContent()
+ {
+ return $content;
+ }
+
+ function show()
+ {
+ for ( var i = 0; i < $labels.length; i++ )
+ {
+ $labels[i].addClass( 'active' );
+ }
+
+ if ( !!$content )
+ {
+ $content.show().addClass( 'in' );
+ }
+
+ }
+
+ function hide()
+ {
+ for ( var i = 0; i < $labels.length; i++ )
+ {
+ $labels[i].removeClass( 'active' );
+ }
+
+ if ( !!$content )
+ {
+ $content.hide().removeClass( 'in' );
+ }
+ }
+ }
+
+ }, ['MediaSizeService'] );
+})( jQuery, PlentyFramework );
+/**
+ * Add fancy ui modifications - the visual stuff - here.
+ * Respond functionality like 'event':UI.myFunctionality(currentElement)
+ *
+ * Example:
+ *
+ *
+ */
+(function( $, pm )
+{
+ pm.directive( 'UI', function( MediaSizeService, SocialShareService )
+ {
+ // elements to calculate height.
+ var equalHeightElementList = [];
+ var toTopButtonList = [];
+
+ return {
+ initUIWindowEvents : initUIWindowEvents,
+ addContentPageSlider: addContentPageSlider,
+ equalHeight : equalHeight,
+ initToTop : initToTop,
+ initLazyload : initLazyload,
+ initSlideToggle : initSlideToggle,
+ slideDown : slideDown,
+ slideUp : slideUp,
+ slideToggle : slideToggle,
+ toggleHideShow : toggleHideShow,
+ toggleSocialShare : toggleSocialShare,
+ toggleClass : toggleClass,
+ addClass : addClass,
+ removeClass : removeClass
+ };
+
+ function initUIWindowEvents()
+ {
+ // resize elements on window size change.
+ $( window ).on( 'sizeChange contentChanged', function()
+ {
+ fireEqualHeight();
+ } );
+
+ $( window ).on( "scroll resize", function()
+ {
+ if ( toTopButtonList.length > 0 )
+ {
+ if ( $( document ).scrollTop() > 100 )
+ {
+ doToArrayElements( toTopButtonList, "addClass", "visible" );
+ }
+ else
+ {
+ doToArrayElements( toTopButtonList, "removeClass", "visible" );
+ }
+ }
+ } );
+ }
+
+ /**
+ * Adds content page slider (owlCarousel)
+ *
+ * usage:
+ *
+ *
+ * ...
+ *
+ *
+ * ...
+ *
+ * ...
+ *
+ *
+ * Legacy directive selector: data-plenty="contentpageSlider"
+ *
+ * @param elem
+ */
+ function addContentPageSlider( elem )
+ {
+ $( elem ).owlCarousel( {
+ navigation : true,
+ navigationText : false,
+ slideSpeed : 1000,
+ paginationSpeed: 1000,
+ singleItem : true,
+ autoPlay : 6000,
+ stopOnHover : true,
+ afterMove : function( current )
+ {
+ $( current ).find( 'img[data-plenty-rel="lazyload"]' ).trigger( 'appear' );
+ }
+ } );
+ }
+
+ /**
+ * Equal Box height
+ * Calculates equal box height for chosen elements.
+ *
+ * Legacy directive selector: data-plenty-equal
+ *
+ * @param elem
+ * @param elementExists - default false
+ */
+ function equalHeight( elem, mediaSizes, elementExists )
+ {
+ var $elem = $( elem );
+ var maxHeight = 0;
+ var $equalTarget = {};
+ var $equalTargetList = $elem.find( '[data-plenty-rel="equal-target"]' ).length > 0 ? $elem.find( '[data-plenty-rel="equal-target"]' ) : $elem.children();
+
+ // if element wasn't pushed before.
+ if ( elementExists !== true )
+ {
+ equalHeightElementList.push( elem );
+ }
+
+ for ( var i = $equalTargetList.length; i >= 0; i-- )
+ {
+ $equalTarget = $( $equalTargetList[i] );
+ $equalTarget.css( 'height', '' );
+
+ if ( $equalTarget.outerHeight( true ) > maxHeight )
+ {
+ maxHeight = $equalTarget.outerHeight( true );
+ }
+ }
+
+ if ( !mediaSizes || MediaSizeService.isInterval( mediaSizes ) )
+ {
+ $equalTargetList.height( maxHeight );
+ }
+ }
+
+ /**
+ * Scroll page to top.
+ * Just add without events.
+ *
+ * Legacy directive selector: data-plenty="toTop"
+ *
+ * @param elem
+ */
+ function initToTop( elem )
+ {
+ var $elem = $( elem );
+
+ $elem.click( function()
+ {
+ $( 'html, body' ).animate( {
+ scrollTop: 0
+ }, 400 );
+ return false;
+ } );
+
+ if ( !!$.inArray( $elem, toTopButtonList ) )
+ {
+ toTopButtonList.push( $elem );
+ }
+ }
+
+ /**
+ * lazy load on ready.
+ *
+ * Legacy directive selector: img[data-plenty-lazyload]
+ *
+ * @param elem
+ */
+ function initLazyload( elem, effect )
+ {
+ var $elem = $( elem );
+
+ $elem.lazyload( {
+ effect: effect
+ } );
+ $elem.on( "loaded", function()
+ {
+ $elem.css( 'display', 'inline-block' );
+ } );
+ }
+
+ /**
+ * Toggle show and hide animation.
+ *
+ * Legacy directive selector: data-plenty="openCloseToggle"
+ *
+ * @param elem
+ */
+ function toggleHideShow( elem )
+ {
+
+ console.log( elem );
+
+ var $elem = $( elem );
+ var $elemParent = $elem.parent();
+
+ $elemParent.addClass( 'animating' );
+ $elem.siblings( 'ul' ).slideToggle( 200, function()
+ {
+ if ( $elemParent.is( '.open' ) )
+ {
+ $elemParent.removeClass( 'open' );
+ }
+ else
+ {
+ $elemParent.addClass( 'open' );
+ }
+ $elem.siblings( 'ul' ).removeAttr( 'style' );
+ $elemParent.removeClass( 'animating' );
+ } );
+ }
+
+ /**
+ * Toggle target content on click.
+ * Bind to checked-/ unchecked-property of radio buttons
+ *
+ * Legacy directive selector: data-plenty-slidetoggle
+ *
+ * @param elem
+ */
+ function initSlideToggle( elem, checked )
+ {
+ var $elem = $( elem );
+ var $targetElement = $( $elem.attr( 'data-plenty-rel' ) );
+
+ if ( $elem.is( 'input[type="radio"]' ) )
+ {
+ // is radio button
+ var $radioGroupList = $( 'input[type="radio"][name="' + ( $elem.attr( 'name' ) ) + '"]' );
+ var visibleOnChecked = !checked || checked == 'checked';
+
+ $radioGroupList.change( function()
+ {
+ var $self = $( this );
+ $targetElement.parents( '[data-plenty-rel="equal-target"]' ).css( 'height', 'auto' );
+
+ if ( $self.is( ':checked' ) && $self[0] === $elem[0] && visibleOnChecked == true )
+ {
+ // checked
+ $targetElement.slideDown( 400, function()
+ {
+ fireEqualHeight();
+ } );
+ }
+ else
+ {
+ // unchecked (since other radio button has been checked)
+ $targetElement.slideUp( 400, function()
+ {
+ fireEqualHeight();
+ } );
+ }
+ } );
+ }
+ else
+ {
+ // is not radio button
+ $elem.click( function()
+ {
+ //$targetElement.parents( '[data-plenty-rel="equal-target"]' ).css( 'height', 'auto' );
+
+ $elem.addClass( 'animating' );
+ $targetElement.slideToggle( 400, function()
+ {
+ $elem.removeClass( 'animating' );
+ $elem.toggleClass( 'active' );
+ fireEqualHeight();
+ } );
+ } );
+ }
+ }
+
+ function slideDown( target, duration )
+ {
+ duration = duration || 400;
+ $(target).parents( '[data-plenty-rel="equal-target"]' ).css( 'height', 'auto' );
+ $(target).slideDown( duration, function() {
+ fireEqualHeight();
+ });
+ }
+
+ function slideUp( target, duration )
+ {
+ duration = duration || 400;
+ $(target).parents( '[data-plenty-rel="equal-target"]' ).css( 'height', 'auto' );
+ $(target).slideUp( duration, function() {
+ fireEqualHeight();
+ });
+ }
+
+ function slideToggle( target, duration )
+ {
+ duration = duration || 400;
+ $(target).parents( '[data-plenty-rel="equal-target"]' ).css( 'height', 'auto' );
+ $(target).slideToggle( duration, function() {
+ fireEqualHeight();
+ });
+ }
+
+
+ /**
+ * TODO check comment
+ * Social Share Activation
+ * Activate and load share-buttons manually by clicking a separate button
+ * Usage / data-attributes:
+ *
+ * Will be used to activate the service set in
+ * data-plenty-social=""
+ * Will be replaced with loaded share button
+ *
+ *
+ * possible values for data-plenty-social:
+ * "facebook-like" : Load Facebooks "Like"-Button
+ * "facebook-recommend" : Load Facebooks "Recommend"-Button
+ * "twitter" : Load Twitter Button
+ * "google-plus" : Load google "+1"-Button
+ *
+ * Additional Tooltips
+ * You can extend the parent element with a (bootstrap) tooltip by adding data-toggle="tooltip" and
+ * title="TOOLTIP CONTENT" Tooltip will be destroyed after activating a social service
+ * (!) Requires bootstrap.js
+ *
+ * Legacy directive selector: data-plenty-social
+ *
+ * @param elem
+ */
+ function toggleSocialShare( elem, socialShareService )
+ {
+ var $elem = $( elem );
+ var $toggle = $elem.find( '[data-plenty-rel="social-switch"]' );
+
+ // append container to put / delete service.html
+ $elem.append( '' );
+
+ // add "off" class to switch, if neither "off" or "on" is set
+ // replaced hasClass() with is() benchmark: http://jsperf.com/hasclasstest
+ if ( !$toggle.is( 'off, on' ) )
+ {
+ $toggle.addClass( 'off' );
+ }
+
+ // toggle switch
+ $toggle.on( 'click', function()
+ {
+ if ( $toggle.hasClass( 'off' ) )
+ {
+ // TODO remove bootstrap dependency
+ if ( $elem.attr( "data-toggle" ) == "tooltip" )
+ {
+ $elem.tooltip( 'destroy' )
+ }
+ $toggle.removeClass( 'off' ).addClass( 'on' );
+ // hide dummy button
+ $elem.find( '[data-plenty-rel="social-placeholder"]' ).hide();
+ // load HTML defined in 'api'
+ $elem.find( '.social-container' ).append( SocialShareService.getSocialService( socialShareService ) );
+ }
+ // do not disable social medias after activation
+ } );
+ }
+
+ /**
+ * Toggle Class
+ * toggle style-classes on click
+ * Usage / data-attribute:
+ *
+ * target : jQuery selector to toggle the class at.
+ * class : class(es) to toggle at target element
+ * media : only toggle class on given media sizes (optional)
+ *
+ * (!) using data-plenty-toggle on -elements will prevent redirecting to href=""
+ *
+ * Legacy directive selector: data-plenty-toggle
+ *
+ * @param cssClass
+ * @param target
+ * @param interval
+ */
+ function toggleClass( cssClass, target, interval )
+ {
+
+ if ( !!target && !!cssClass && ( !interval || MediaSizeService.isInterval( interval ) ) )
+ {
+ var e = pm.getRecentEvent();
+ if( !!e ) e.preventDefault();
+
+ $( target ).toggleClass( cssClass );
+ return false;
+ }
+ }
+
+ function addClass( cssClass, target, interval )
+ {
+ if ( !!target && !!cssClass && ( !interval || MediaSizeService.isInterval( interval ) ) )
+ {
+ var e = pm.getRecentEvent();
+ if( !!e ) e.preventDefault();
+
+ $( target ).addClass( cssClass );
+ return false;
+ }
+ }
+
+ function removeClass( cssClass, target, interval )
+ {
+ if ( !!target && !!cssClass && ( !interval || MediaSizeService.isInterval( interval ) ) )
+ {
+ var e = pm.getRecentEvent();
+ if( !!e ) e.preventDefault();
+
+ $( target ).removeClass( cssClass );
+ return false;
+ }
+ }
+
+ /*
+ ##### PRIVATE FUNCTIONS ######
+ */
+
+ function fireEqualHeight()
+ {
+ for ( var i = equalHeightElementList.length - 1; i >= 0; i-- )
+ {
+ equalHeight( equalHeightElementList[i], '', true );
+ }
+ }
+
+ function doToArrayElements( array, func, params )
+ {
+ for ( var i = array.length - 1; i >= 0; i-- )
+ {
+ array[i][func]( params );
+ }
+ }
+
+ }, ['MediaSizeService', 'SocialShareService'] );
+}( jQuery, PlentyFramework ));
+(function( $, pm )
+{
+ pm.directive( 'Validator', function( ValidationService )
+ {
+
+ return {
+ validate: validate
+ };
+
+ function validate( form, errorClass )
+ {
+ return ValidationService.validate( form, errorClass );
+ }
+
+ }, ['ValidationService'] );
+}( jQuery, PlentyFramework ));
+/**
+ * Licensed under AGPL v3
+ * (https://github.com/plentymarkets/plenty-cms-library/blob/master/LICENSE)
+ * =====================================================================================
+ * @copyright Copyright (c) 2015, plentymarkets GmbH (http://www.plentymarkets.com)
+ * @author Felix Dausch
+ * =====================================================================================
+ */
+
+PlentyFramework.compile();
+
+// Create global instance of PlentyFramework for usage in Webshop-Layouts
+var plenty = PlentyFramework.getInstance();
+
+/*
+ * initially bind all registered directives
+ *
+ * will not be tested. reasons:
+ * http://stackoverflow.com/questions/29153733/how-to-unit-test-a-document-ready-function-using-jasmine
+ */
+jQuery( document ).ready( function()
+{
+ plenty.bindDirectives();
+} );
\ No newline at end of file
diff --git a/src/services/CheckoutService.js b/src/services/CheckoutService.js
index 9e6274b..bcbd437 100644
--- a/src/services/CheckoutService.js
+++ b/src/services/CheckoutService.js
@@ -132,7 +132,7 @@
}
else if ( shippingAddress.Street == "POSTFILIALE" )
{
- shippingAddress.isPostfiliale = 1;
+ shippingAddress.IsPostfiliale = 1;
shippingAddress.PostfilialNo = shippingAddress.HouseNo;
}
From 5510ae0f2663bb66c1136569cfd5cda308b52b7b Mon Sep 17 00:00:00 2001
From: Maximilian Lauterbach
Date: Wed, 9 Dec 2015 12:05:11 +0100
Subject: [PATCH 08/17] fixed variable name for PostFinder
---
tools/CheckoutManager-migrate.js | 18 ++++++++++++++++++
1 file changed, 18 insertions(+)
create mode 100644 tools/CheckoutManager-migrate.js
diff --git a/tools/CheckoutManager-migrate.js b/tools/CheckoutManager-migrate.js
new file mode 100644
index 0000000..bb503b3
--- /dev/null
+++ b/tools/CheckoutManager-migrate.js
@@ -0,0 +1,18 @@
+CheckoutManager = {};
+
+(function( $, pm )
+{
+ CheckoutManager.init = function()
+ {
+ pm.NavigatorService.init();
+ };
+
+ CheckoutManager.Navigator = {};
+
+ CheckoutManager.Navigator.fillNavigation = function()
+ {
+ pm.NavigatorService.fillNavigation();
+ };
+
+
+})( jQuery, PlentyFramework );
\ No newline at end of file
From e09fc7481245293df83a76a3f3db1676dfdabbc0 Mon Sep 17 00:00:00 2001
From: Maximilian Lauterbach
Date: Wed, 9 Dec 2015 12:05:46 +0100
Subject: [PATCH 09/17] fixed variable name for PostFinder
---
dist/plentymarketsCMStools-1.0.1.min.js | 9 +++++++++
1 file changed, 9 insertions(+)
create mode 100644 dist/plentymarketsCMStools-1.0.1.min.js
diff --git a/dist/plentymarketsCMStools-1.0.1.min.js b/dist/plentymarketsCMStools-1.0.1.min.js
new file mode 100644
index 0000000..82ec69a
--- /dev/null
+++ b/dist/plentymarketsCMStools-1.0.1.min.js
@@ -0,0 +1,9 @@
+/**
+ * Licensed under AGPL v3
+ * (https://github.com/plentymarkets/plenty-cms-library/blob/master/LICENSE)
+ * =====================================================================================
+ * @copyright Copyright (c) 2015, plentymarkets GmbH (http://www.plentymarkets.com)
+ * @author Felix Dausch
+ * =====================================================================================
+*/!function(a,b){"object"==typeof exports&&exports&&"string"!=typeof exports.nodeName?b(exports):"function"==typeof define&&define.amd?define(["exports"],b):(a.Mustache={},b(Mustache))}(this,function(a){function b(a){return"function"==typeof a}function c(a){return p(a)?"array":typeof a}function d(a){return a.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g,"\\$&")}function e(a,b){return null!=a&&"object"==typeof a&&b in a}function f(a,b){return q.call(a,b)}function g(a){return!f(r,a)}function h(a){return String(a).replace(/[&<>"'\/]/g,function(a){return s[a]})}function i(b,c){function e(){if(r&&!s)for(;q.length;)delete o[q.pop()];else q=[];r=!1,s=!1}function f(a){if("string"==typeof a&&(a=a.split(u,2)),!p(a)||2!==a.length)throw new Error("Invalid tags: "+a);h=new RegExp(d(a[0])+"\\s*"),i=new RegExp("\\s*"+d(a[1])),m=new RegExp("\\s*"+d("}"+a[1]))}if(!b)return[];var h,i,m,n=[],o=[],q=[],r=!1,s=!1;f(c||a.tags);for(var y,z,A,B,C,D,E=new l(b);!E.eos();){if(y=E.pos,A=E.scanUntil(h))for(var F=0,G=A.length;G>F;++F)B=A.charAt(F),g(B)?q.push(o.length):s=!0,o.push(["text",B,y,y+1]),y+=1,"\n"===B&&e();if(!E.scan(h))break;if(r=!0,z=E.scan(x)||"name",E.scan(t),"="===z?(A=E.scanUntil(v),E.scan(v),E.scanUntil(i)):"{"===z?(A=E.scanUntil(m),E.scan(w),E.scanUntil(i),z="&"):A=E.scanUntil(i),!E.scan(i))throw new Error("Unclosed tag at "+E.pos);if(C=[z,A,y,E.pos],o.push(C),"#"===z||"^"===z)n.push(C);else if("/"===z){if(D=n.pop(),!D)throw new Error('Unopened section "'+A+'" at '+y);if(D[1]!==A)throw new Error('Unclosed section "'+D[1]+'" at '+y)}else"name"===z||"{"===z||"&"===z?s=!0:"="===z&&f(A)}if(D=n.pop())throw new Error('Unclosed section "'+D[1]+'" at '+E.pos);return k(j(o))}function j(a){for(var b,c,d=[],e=0,f=a.length;f>e;++e)b=a[e],b&&("text"===b[0]&&c&&"text"===c[0]?(c[1]+=b[1],c[3]=b[3]):(d.push(b),c=b));return d}function k(a){for(var b,c,d=[],e=d,f=[],g=0,h=a.length;h>g;++g)switch(b=a[g],b[0]){case"#":case"^":e.push(b),f.push(b),e=b[4]=[];break;case"/":c=f.pop(),c[5]=b[2],e=f.length>0?f[f.length-1][4]:d;break;default:e.push(b)}return d}function l(a){this.string=a,this.tail=a,this.pos=0}function m(a,b){this.view=a,this.cache={".":this.view},this.parent=b}function n(){this.cache={}}var o=Object.prototype.toString,p=Array.isArray||function(a){return"[object Array]"===o.call(a)},q=RegExp.prototype.test,r=/\S/,s={"&":"&","<":"<",">":">",'"':""","'":"'","/":"/"},t=/\s*/,u=/\s+/,v=/\s*=/,w=/\s*\}/,x=/#|\^|\/|>|\{|&|=|!/;l.prototype.eos=function(){return""===this.tail},l.prototype.scan=function(a){var b=this.tail.match(a);if(!b||0!==b.index)return"";var c=b[0];return this.tail=this.tail.substring(c.length),this.pos+=c.length,c},l.prototype.scanUntil=function(a){var b,c=this.tail.search(a);switch(c){case-1:b=this.tail,this.tail="";break;case 0:b="";break;default:b=this.tail.substring(0,c),this.tail=this.tail.substring(c)}return this.pos+=b.length,b},m.prototype.push=function(a){return new m(a,this)},m.prototype.lookup=function(a){var c,d=this.cache;if(d.hasOwnProperty(a))c=d[a];else{for(var f,g,h=this,i=!1;h;){if(a.indexOf(".")>0)for(c=h.view,f=a.split("."),g=0;null!=c&&gi;++i)g=void 0,e=a[i],f=e[0],"#"===f?g=this.renderSection(e,b,c,d):"^"===f?g=this.renderInverted(e,b,c,d):">"===f?g=this.renderPartial(e,b,c,d):"&"===f?g=this.unescapedValue(e,b):"name"===f?g=this.escapedValue(e,b):"text"===f&&(g=this.rawValue(e)),void 0!==g&&(h+=g);return h},n.prototype.renderSection=function(a,c,d,e){function f(a){return g.render(a,c,d)}var g=this,h="",i=c.lookup(a[1]);if(i){if(p(i))for(var j=0,k=i.length;k>j;++j)h+=this.renderTokens(a[4],c.push(i[j]),d,e);else if("object"==typeof i||"string"==typeof i||"number"==typeof i)h+=this.renderTokens(a[4],c.push(i),d,e);else if(b(i)){if("string"!=typeof e)throw new Error("Cannot use higher-order sections without the original template");i=i.call(c.view,e.slice(a[3],a[5]),f),null!=i&&(h+=i)}else h+=this.renderTokens(a[4],c,d,e);return h}},n.prototype.renderInverted=function(a,b,c,d){var e=b.lookup(a[1]);return!e||p(e)&&0===e.length?this.renderTokens(a[4],b,c,d):void 0},n.prototype.renderPartial=function(a,c,d){if(d){var e=b(d)?d(a[1]):d[a[1]];return null!=e?this.renderTokens(this.parse(e),c,d,e):void 0}},n.prototype.unescapedValue=function(a,b){var c=b.lookup(a[1]);return null!=c?c:void 0},n.prototype.escapedValue=function(b,c){var d=c.lookup(b[1]);return null!=d?a.escape(d):void 0},n.prototype.rawValue=function(a){return a[1]},a.name="mustache.js",a.version="2.1.3",a.tags=["{{","}}"];var y=new n;a.clearCache=function(){return y.clearCache()},a.parse=function(a,b){return y.parse(a,b)},a.render=function(a,b,d){if("string"!=typeof a)throw new TypeError('Invalid template! Template should be a "string" but "'+c(a)+'" was given as the first argument for mustache#render(template, view, partials)');return y.render(a,b,d)},a.to_html=function(c,d,e,f){var g=a.render(c,d,e);return b(f)?void f(g):g},a.escape=h,a.Scanner=l,a.Context=m,a.Writer=n}),Object.equals=function(a,b){if(a===b)return!0;if(!(a instanceof Object&&b instanceof Object))return!1;if(a.constructor!==b.constructor)return!1;for(var c in a)if(a.hasOwnProperty(c)){if(!b.hasOwnProperty(c))return!1;if(a[c]!==b[c]){if("object"!=typeof a[c])return!1;if(!Object.equals(a[c],b[c]))return!1}}for(var c in b)if(b.hasOwnProperty(c)&&!a.hasOwnProperty(c))return!1;return!0};var TemplateCache={};TemplateCache["addressSuggestions/addressDoctor.html"]='\n {{#values}}\n - \n \n {{.}}\n \n
\n {{/values}}\n
',TemplateCache["addressSuggestions/postFinder.html"]='{{#addresses}}\n\n
\n \n
\n
\n{{/addresses}}\n',TemplateCache["error/errorMessage.html"]='\n Code {{code}}:\n {{{message}}}\n
\n',TemplateCache["error/errorPopup.html"]='\n
\n
\n
\n
\n',TemplateCache["modal/modal.html"]='\n
\n
\n\n {{#title}}\n \n {{/title}}\n\n
{{{content}}}
\n\n \n
\n
\n
\n',TemplateCache["waitscreen/waitscreen.html"]='',function(a){function b(a,b,c,d){a.on(b,function(a){return g.push(a),c.apply(null,d)})}function c(b){var c=a(b);c.is('input[type="checkbox"]')&&c.on("change",function(){c.is(":checked")?c.trigger("check"):c.trigger("uncheck")}),c.is('input[type="radio"]')&&c.on("change",function(){var b=c.attr("name");a('input[type="radio"][name="'+b+'"]').each(function(b,c){var d=a(c);d.is(":checked")?d.trigger("check"):d.trigger("uncheck")})})}function d(a,b){for(var c=/^(([\w]+):)?([\w]+)\.([\w]+)(\((.*)\))?$/,d=a.split(";"),e=[],f=0;f0)for(var j=h[6].match(/(['][^']+['])|([\w-]+)|(["][^"]+["])/g),k=0;k=0;c--)if(a==g[c].type)return g[c];return null},PlentyFramework.pushEvent=function(a){g.push(a)},PlentyFramework.service=function(a,b,c){return"string"!=typeof a?void console.error("Type mismatch: Expect first parameter to be a 'string', '"+typeof a+"' given."):"function"!=typeof b?void console.error("Type mismatch: Expect second parameter to be a 'function', '"+typeof b+"' given."):(c=c||[],void(e.services[a]={name:a,dependencies:c,compile:function(){var d=PlentyFramework.resolveFactories(c);PlentyFramework.prototype[a]=b.apply(null,d)}}))},PlentyFramework.resolveServices=function(b){var c=[];return a.each(b,function(a,b){if(!PlentyFramework.prototype.hasOwnProperty(b)){if(!e.services.hasOwnProperty(b))return console.error('Cannot inject Service "'+b+'": Service not found.'),!1;e.services[b].compile()}var d=PlentyFramework.prototype[b];c.push(d)}),c},PlentyFramework.factories={},PlentyFramework.factory=function(a,b,c){return"string"!=typeof a?void console.error("Type mismatch: Expect first parameter to be a 'string', '"+typeof a+"' given."):"function"!=typeof b?void console.error("Type mismatch: Expect second parameter to be a 'function', '"+typeof b+"' given."):(c=c||[],void(e.factories[a]={name:a,dependencies:c,compile:function(){var d=PlentyFramework.resolveFactories(c);PlentyFramework.factories[a]=b.apply(null,d)}}))},PlentyFramework.resolveFactories=function(b){var c=[];return a.each(b,function(a,b){if(!PlentyFramework.factories.hasOwnProperty(b)){if(!e.factories.hasOwnProperty(b))return console.error('Cannot inject Factory "'+b+'": Factory not found.'),!1;e.factories[b].compile()}var d=PlentyFramework.factories[b];c.push(d)}),c},PlentyFramework.compileTemplate=function(a,b){return b=b||{},b.translate=function(){return function(a,b){return b(PlentyFramework.translate(a))}},Mustache.render(TemplateCache[a],b)},PlentyFramework.scriptPath="",PlentyFramework.Strings={},PlentyFramework.loadLanguageFile=function(b){a.get(PlentyFramework.scriptPath+b).done(function(a){PlentyFramework.Strings=a})},PlentyFramework.translate=function(a,b){var c;return PlentyFramework.Strings.hasOwnProperty(a)?c=PlentyFramework.Strings[a]:(c=a,console.warn('No translation found for "'+c+'".')),b&&(c=Mustache.render(c,b)),c},PlentyFramework.compile=function(){for(var a in e.factories)PlentyFramework.factories.hasOwnProperty(a)||e.factories[a].compile();for(var b in e.services)PlentyFramework.prototype.hasOwnProperty(b)||e.services[b].compile();for(var c in e.directives)PlentyFramework.directives.hasOwnProperty(c)||e.directives[c].compile();var d=document.getElementsByTagName("SCRIPT");d.length>0&&(PlentyFramework.scriptPath=d[d.length-1].src.match(/(.*)\/(.*)\.js(\?\S*)?$/)[1])}}(jQuery),PlentyFramework.cssClasses={active:"active"},function(a,b){b.partials.Error={init:function(b){a(b).find(".close").click(function(){b.hide(),b.find(".plentyErrorBoxInner").html("")})},addError:function(b,c){var d=a(c).attr("data-plenty-error-code");a(b).find('[data-plenty-error-code="'+d+'"]').length<=0&&a(b).find(".plentyErrorBoxInner").append(c)},show:function(b){a(b).show()}}}(jQuery,PlentyFramework),function(a,b){b.partials.Modal={init:function(a,b){a.on("hidden.bs.modal",function(){b.hide(),a.remove()}),b.timeout>0&&(a.on("hide.bs.modal",b.stopTimeout),a.find(".modal-content").hover(function(){b.pauseTimeout()},function(){a.is(".in")&&b.continueTimeout()}))},show:function(a){a.modal("show")},hide:function(a){a.modal("hide")},isModal:function(b){return a(b).filter(".modal").length+a(b).find(".modal").length>0},getModal:function(b){var c=a(b);return c.length>1&&(c=a(b).filter(".modal")||a(b).find(".modal")),c}}}(jQuery,PlentyFramework),function(a){a(document).on("initPartials",function(b,c){a(c).find('[data-toggle="tooltip"]').tooltip({container:"body"})})}(jQuery),function(a,b){b.partials.WaitScreen={show:function(a){a.addClass("in")},hide:function(a){a.removeClass("in")}}}(jQuery,PlentyFramework),function(a,b){b.factory("APIFactory",function(b){function c(c){try{var d=a.parseJSON(c.responseText);b.printErrors(d.error.error_stack)}catch(e){b.throwError(c.status,c.statusText)}}function d(d,e,f,g,h){return g||b.showWaitScreen(),a.ajax(d,{type:"GET",data:e,dataType:"json",async:!h,error:function(a){f||c(a)}}).always(function(){g||b.hideWaitScreen()})}function e(d,e,f,g){var h={type:"POST",dataType:"json",error:function(a){f||c(a)}};return e&&e.isFile?(h.cache=e.cache,h.processData=e.processData,h.data=e.data,h.contentType=!1):(h.data=JSON.stringify(e),h.contentType="application/json"),g||b.showWaitScreen(),a.ajax(d,h).always(function(){g||b.hideWaitScreen()})}function f(d,e,f,g){return g||b.showWaitScreen(),a.ajax(d,{type:"PUT",data:JSON.stringify(e),dataType:"json",contentType:"application/json",error:function(a){f||c(a)}}).always(function(){g||b.hideWaitScreen()})}function g(d,e,f,g){return g||b.showWaitScreen(),a.ajax(d,{type:"DELETE",data:JSON.stringify(e),dataType:"json",contentType:"application/json",error:function(a){f||c(a)}}).always(function(){g||b.hideWaitScreen()})}function h(){return a.Deferred().resolve()}return{get:d,post:e,put:f,"delete":g,idle:h}},["UIFactory"])}(jQuery,PlentyFramework),function(a){a.factory("CMSFactory",function(a){function b(b,c){function d(d){return a.get("/rest/"+d.toLowerCase()+"/container_"+b.toLowerCase()+"/",c)}return{from:d}}function c(b,c){function d(d){return a.get("/rest/"+d.toLowerCase()+"/"+b.toLowerCase()+"/",c)}return{from:d}}function d(b){return a.get("/rest/categoryview/categorycontentbody/?categoryID="+b)}return{getContainer:b,getParams:c,getCategoryContent:d}},["APIFactory"])}(PlentyFramework),function(a){a.factory("CheckoutFactory",function(b,c,d){function e(){return l}function f(a){return m&&l||g(!0),a?$.extend(!0,{},l):m}function g(a){return b.get("/rest/checkout/",null,!1,!1,a).done(function(a){a?(l=a.data,m=new e):d.throwError(0,'Could not receive checkout data [GET "/rest/checkout/" receives null value]')})}function h(){return b.put("/rest/checkout",m).done(function(a){a?(l=a.data,m=new e):d.throwError(0,'Could not receive checkout data [GET "/rest/checkout/" receives null value]')})}function i(b){return c.getContainer("checkout"+b).from("checkout").done(function(c){$('[data-plenty-checkout-template="'+b+'"]').each(function(b,d){$(d).html(c.data[0]),a.getInstance().bindDirectives(d),$(window).trigger("contentChanged")})})}function j(b){return c.getCategoryContent(b).done(function(c){$('[data-plenty-checkout-catcontent="'+b+'"]').each(function(b,d){$(d).html(c.data[0]),a.getInstance().bindDirectives(d),$(window).trigger("contentChanged")})})}function k(b){return c.getContainer("itemview"+b).from("itemview").done(function(c){$('[data-plenty-itemview-template="'+b+'"]').each(function(b,d){$(d).html(c.data[0]),a.getInstance().bindDirectives(d),$(window).trigger("contentChanged")})})}var l,m;return{getCheckout:f,setCheckout:h,loadCheckout:g,reloadContainer:i,reloadCatContent:j,reloadItemContainer:k}},["APIFactory","CMSFactory","UIFactory"])}(PlentyFramework),function(a,b){b.factory("ModalFactory",function(){function c(a){return PlentyFramework.partials.Modal.isModal(a)}function d(){return new e}function e(){function d(a){return s.title=a,this}function e(a){return s.cssClass=a,this}function f(a){return s.content=a,this}function g(a){return s.labelConfirm=a,this}function h(a){return s.labelDismiss=a,this}function i(a){return s.onConfirm=a,this}function j(a){return s.onDismiss=a,this}function k(a){return s.container=a,this}function l(a){return s.timeout=a,this}function m(){t=c(s.content)?PlentyFramework.partials.Modal.getModal(s.content):a(PlentyFramework.compileTemplate("modal/modal.html",s)),a(s.container).append(t);var b=a(s.content).filter("script");b.length>0&&b.each(function(b,c){var d=document.createElement("script");d.type="text/javascript",d.innerHTML=a(c).text(),a(s.container).append(d)}),PlentyFramework.partials.Modal.init(t,s),t.find('[data-plenty-modal="confirm"]').click(function(){var a=s.onConfirm();"undefined"==typeof a&&(a=!0),a&&n(!0)}),PlentyFramework.partials.Modal.show(t),s.timeout>0&&o()}function n(a){PlentyFramework.partials.Modal.hide(t),a||s.onDismiss()}function o(){w=s.timeout,x=(new Date).getTime(),u=window.setTimeout(function(){window.clearInterval(v),n()},s.timeout),t.find('[data-plenty-modal="timer"]').text(w/1e3),v=window.setInterval(function(){if(!y){var a=w-(new Date).getTime()+x;a=Math.round(a/1e3),t.find('[data-plenty-modal="timer"]').text(a)}},1e3)}function p(){y=!0,w-=(new Date).getTime()-x,window.clearTimeout(u)}function q(){y=!1,x=(new Date).getTime(),u=window.setTimeout(function(){n(),window.clearInterval(v)},w)}function r(){window.clearTimeout(u),window.clearInterval(v)}var s=this;s.title="",s.cssClass="",s.content="",s.labelDismiss=b.translate("Cancel"),s.labelConfirm=b.translate("Confirm"),s.onConfirm=function(){},s.onDismiss=function(){},s.container="body",s.timeout=-1,s.hide=n,s.startTimeout=o,s.stopTimeout=r,s.pauseTimeout=p,s.continueTimeout=q;var t,u,v,w,x,y=!1;return{setTitle:d,setClass:e,setContent:f,setContainer:k,setLabelConfirm:g,setLabelDismiss:h,onConfirm:i,onDismiss:j,setTimeout:l,show:m,hide:n}}return{prepare:d,isModal:c}})}(jQuery,PlentyFramework),function(a,b){b.factory("UIFactory",function(){function c(a,b){d([{code:a,message:b}])}function d(c){(!i||a("body").has(i).length<=0)&&(i=a(b.compileTemplate("error/errorPopup.html")),a("body").append(i),b.partials.Error.init(i)),a.each(c,function(c,d){b.partials.Error.addError(i,a(b.compileTemplate("error/errorMessage.html",d)))}),b.partials.Error.show(i),f(!0)}function e(){return h=h||0,(!g||a("body").has(g).length<=0)&&(g=a(b.compileTemplate("waitscreen/waitscreen.html")),a("body").append(g)),b.partials.WaitScreen.show(g),h++,h}function f(a){return h--,(0>=h||a)&&(h=0,b.partials.WaitScreen.hide(g)),h}var g,h=0,i=null;return{throwError:c,printErrors:d,showWaitScreen:e,hideWaitScreen:f}})}(jQuery,PlentyFramework),function(a,b){b.service("AddressDoctorService",function(c){function d(b){var c=!0;return b=b||"[data-plenty-address-doctor]",a(b).filter("[data-plenty-address-doctor]:visible").each(function(b,d){var f=new e(d),g=a(d).attr("data-plenty-address-doctor").replace(/\s/g,"").split(",");f.isValid(g)||(c=!1)}),c}function e(c){function d(a){return i()?!0:(j=new f(l.getFormValues()),k=a,e(),1==j.getAddresses().length)}function e(){a(".suggestion-list").remove();for(var b=!1,c=0;cc;c++){var d=a.data[c],f=e(d);f?f.HouseNo.push(d.HouseNo):(d.HouseNo=[d.HouseNo],j.push(d))}})}function e(a){for(var b=j.length,c=0;b>c;c++)if(a.Street==j[c].Street&&j.ZIP==j[c].ZIP&&a.City==j[c].City)return j[c];return null}function f(){return j}function g(b){for(var c=[],d=j.length,e=0;d>e;e++){var f=j[e];a.inArray(f[b],c)<0&&c.push(f[b])}return c}function h(a){for(var b=[],c=j.length,d=0;c>d;d++){var e=j[d];(a.Street&&a.Street==e.Street||a.ZIP&&a.ZIP==e.ZIP||a.City&&a.City==e.City)&&b.push(e)}j=b}function i(a){a=parseInt(a);for(var b=j.length,c=0;b>c;c++)for(var d=j[c],e=0;e=f[0]&&a<=f[1])return!0}return!1}var j=[];return d(),{getAddresses:f,getList:g,filter:h,houseNoAllowed:i}}return{validateAddress:d}},["APIFactory"])}(jQuery,PlentyFramework),function(a,b){b.service("AuthenticationService",function(c,d,e){function f(){var b=a('[data-plenty-checkout="lostPasswordForm"]');if(b.validateForm()){var d=b.getFormValues(),e={Email:d.Email};return c.post("/rest/checkout/lostpassword/",e).done(function(b){1==b.data.IsMailSend&&(a('[data-plenty-checkout="lostPasswordTextContainer"]').hide(),a('[data-plenty-checkout="lostPasswordSuccessMessage"]').show())})}}function g(a){if(a.validateForm()){var b=a.getFormValues(),d={Email:b.loginMail,Password:b.loginPassword};return e.showWaitScreen(),c.post("/rest/checkout/login/",d).done(function(){window.location.assign(a.attr("action"))})}}function h(a){return c.post("/rest/checkout/customerinvoiceaddress/",a).done(function(a){d.getCheckout().CustomerInvoiceAddress=a.data})}function i(){var c=a('[data-plenty-checkout-form="customerRegistration"]');if(c.validateForm()&&b.getInstance().AddressDoctorService.validateAddress()){var d=c.getFormValues(),e={LoginType:2,FormOfAddressID:d.FormOfAddressID,Company:d.Company,FirstName:d.FirstName,LastName:d.LastName,Street:d.Street,HouseNo:d.HouseNo,AddressAdditional:d.AddressAdditional,ZIP:d.ZIP,City:d.City,CountryID:d.CountryID,VATNumber:d.VATNumber,Email:d.Email,EmailRepeat:d.EmailRepeat,BirthDay:d.BirthDay,BirthMonth:d.BirthMonth,BirthYear:d.BirthYear,Password:d.Password,PasswordRepeat:d.PasswordRepeat,PhoneNumber:d.PhoneNumber,MobileNumber:d.MobileNumber,FaxNumber:d.FaxNumber,Postnummer:d.Postnummer};return e.CustomerPropertiesList=e.CustomerPropertiesList||[],c.find("[data-plenty-property-id]").each(function(b,c){e.CustomerPropertiesList.push({PropertyID:a(c).attr("data-plenty-property-id"),PropertyValue:a(c).val()})}),h(e).done(function(){window.location.assign(c.attr("action"))})}}return{resetPassword:f,customerLogin:g,setInvoiceAddress:h,registerCustomer:i}},["APIFactory","CheckoutFactory","UIFactory"])}(jQuery,PlentyFramework),function(a,b){b.service("BasketService",function(c,d,e,f,g){function h(d){d&&c.get("/rest/checkout/container_"+"CheckoutOrderParamsList".toLowerCase()+"/",{itemID:d[0].BasketItemItemID,quantity:d[0].BasketItemQuantity},!1,!0).done(function(c){c.data[0].indexOf("form-group")>0?g.prepare().setContent(c.data[0]).setTitle(b.translate("Select order parameters")).setLabelConfirm(b.translate("Save")).onConfirm(function(){return a('[data-plenty-checkout-form="OrderParamsForm"]').validateForm()?(j(i(d)),!0):!1}).show():j(d)})}function i(b){var c,d=a('[data-plenty-checkout-form="OrderParamsForm"]'),e={},f="";return d.find('[name^="ParamGroup"]').each(function(){c=this.name.match(/^ParamGroup\[(\d+)]\[(\d+)]$/),b=m(b,c[1],a(this).val(),a(this).val())}),d.find('[name^="ParamValue"]').each(function(){if(e=a(this),f=e.attr("type"),("checkbox"==f&&e.is(":checked")||"radio"==f&&e.is(":checked")||"radio"!=f&&"checkbox"!=f)&&"file"!=f&&"hidden"!=f){var c=e[0].name.match(/^ParamValue\[(\d+)]\[(\d+)]$/);b=m(b,c[1],c[2],e.val())}else if("file"==f)if(e[0].files&&e[0].files.length>0)b=l(e,b);else{var c=e[0].name.match(/^ParamValueFile\[(\d+)]\[(\d+)]$/),d=a('input[type="hidden"][name="ParamValue['+c[1]+"]["+c[2]+']"]').val();b=m(b,c[1],c[2],d)}}),b}function j(a){c.post("/rest/checkout/basketitemslist/",a,!0).done(function(){f.loadCheckout().done(function(){s(),e.getContainer("ItemViewItemToBasketConfirmationOverlay",{ArticleID:a[0].BasketItemItemID}).from("ItemView").done(function(a){g.prepare().setContent(a.data[0]).setTimeout(5e3).show()})})}).fail(function(a){d.printErrors(JSON.parse(a.responseText).error.error_stack)})}function k(a){c.put("/rest/checkout/basketitemslist/",a).done(function(){f.reloadCatContent(b.getGlobal("basketCatID")),f.loadCheckout().done(function(){s()})})}function l(a,b){var d,e,f=a[0].id,g={},h=[],i={type:"POST",data:{},isFile:!0,cache:!1,dataType:"json",processData:!1,contentType:!1};g[f]=a[0].files,-1==h.indexOf(f)&&h.push(f);for(var j=0,k=h.length;k>j;++j)d=new FormData,e=g[h[j]],d.append("0",e[0],e[0].name),i.data=d,c.post("/rest/checkout/orderparamfile/",i);var l=a[0].name.match(/^ParamValueFile\[(\d+)]\[(\d+)]$/);return m(b,l[1],l[2],a.val())}function m(b,c,d,e){return c>0&&void 0==b[c]&&(b[c]=a.extend(!0,{},b[0]),b[c].BasketItemOrderParamsList=[]),void 0!=b[c]&&(b[c].BasketItemQuantity=1,void 0==b[c].BasketItemOrderParamsList&&(b[c].BasketItemOrderParamsList=[]),e&&b[c].BasketItemOrderParamsList.push({BasketItemOrderParamID:d,BasketItemOrderParamValue:e})),b}function n(b){var c=a('[data-plenty-basket-item="'+b+'"');c.modal("show"),c.find('[data-plenty-modal="confirm"]').on("click",function(){var d=p(b),e=[];c.find('select, .PlentyFormContainer.AttrImage > input[type="hidden"]').each(function(b,c){var d=c.name.match(/^ArticleAttribute\[\d+]\[\d+]\[(\d+)]$/);d&&d[1]&&e.push({BasketItemAttributeID:d[1],BasketItemAttributeValueID:a(c).val()})}),0!=e.length&&(d.BasketItemAttributesList=e),k([d])})}function o(d){var e=p(d);e.BasketItemOrderParamsList=[],c.get("/rest/checkout/container_"+"CheckoutOrderParamsList".toLowerCase()+"/",{itemID:e.BasketItemItemID,quantity:e.BasketItemQuantity,basketItemID:d}).done(function(c){g.prepare().setContent(c.data[0]).setTitle(b.translate("Edit order parameters")).setLabelConfirm(b.translate("Save")).onConfirm(function(){return a('[data-plenty-checkout-form="OrderParamsForm"]').validateForm()?(k(i([e])),!0):!1}).show()})}function p(a){for(var b=f.getCheckout().BasketItemsList,c=0;c"+b.translate('Do you really want to remove "{{item}}" from your basket?',{item:j})+"
").onDismiss(function(){i.reject()}).onConfirm(function(){h()}).setLabelConfirm(b.translate("Delete")).show(),i}function r(d,e){if(0>=e)return q(d);for(var g,h,i=a.Deferred(),j=f.getCheckout().BasketItemsList,k=0;k0&&f.reloadContainer("Totals")}return{addItem:h,removeItem:q,getItem:p,setItemQuantity:r,editItemAttributes:n,editOrderParams:o,addCoupon:t,removeCoupon:u}},["APIFactory","UIFactory","CMSFactory","CheckoutFactory","ModalFactory"])}(jQuery,PlentyFramework),function(a,b){b.service("CheckoutService",function(c,d,e,f){function g(){e.loadCheckout(!0)}function h(){var b=a('[data-plenty-checkout-form="details"]'),d=b.getFormValues();return e.getCheckout().CheckoutCustomerSign||(e.getCheckout().CheckoutCustomerSign=""),e.getCheckout().CheckoutOrderInfoText||(e.getCheckout().CheckoutOrderInfoText=""),e.getCheckout().CheckoutCustomerSign!==d.CustomerSign&&a(b).find('[name="CustomerSign"]').length>0||e.getCheckout().CheckoutOrderInfoText!==d.OrderInfoText&&a(b).find('[name="OrderInfoText"]').length>0?(e.getCheckout().CheckoutCustomerSign=d.CustomerSign,e.getCheckout().CheckoutOrderInfoText=d.OrderInfoText,e.setCheckout()):c.idle()}function i(d){var f=a('[data-plenty-checkout-form="shippingAddress"]');if(!d&&!f.validateForm())return!1;if(!d&&!b.getInstance().AddressDoctorService.validateAddress(f))return!1;var g=f.getFormValues(),h=a('[name="shippingAddressID"]:checked').val();if(a("#shippingAdressSelect").modal("hide"),0>h){var i=g;return k(i,e.getCheckout().CustomerShippingAddress)?c.idle():("PACKSTATION"==i.Street?(i.isPackstation=1,i.PackstationNo=i.HouseNo):"POSTFILIALE"==i.Street&&(i.IsPostfiliale=1,i.PostfilialNo=i.HouseNo),c.post("/rest/checkout/customershippingaddress/",i).done(function(a){e.getCheckout().CheckoutCustomerShippingAddressID=a.data.ID,e.getCheckout().CheckoutShippingCountryID=a.data.CountryID,delete e.getCheckout().CheckoutMethodOfPaymentID,delete e.getCheckout().CheckoutShippingProfileID,e.setCheckout().done(function(){e.reloadContainer("MethodsOfPaymentList"),e.reloadContainer("ShippingProfilesList"),2==e.getCheckout().CustomerInvoiceAddress.LoginType&&e.reloadContainer("CustomerShippingAddress")})}))}return h!=e.getCheckout().CheckoutCustomerShippingAddressID?(e.getCheckout().CheckoutCustomerShippingAddressID=h,delete e.getCheckout().CheckoutMethodOfPaymentID,delete e.getCheckout().CheckoutShippingProfileID,e.setCheckout().done(function(){e.reloadContainer("MethodsOfPaymentList"),e.reloadContainer("ShippingProfilesList"),2==e.getCheckout().CustomerInvoiceAddress.LoginType&&e.reloadContainer("CustomerShippingAddress")})):c.idle()}function j(){var b=a('[data-plenty-checkout-form="guestRegistration"]'),d=b.getFormValues();return d.LoginType=1,d.CustomerPropertiesList=d.CustomerPropertiesList||[],b.find("[data-plenty-property-id]").each(function(b,c){d.CustomerPropertiesList.push({PropertyID:a(c).attr("data-plenty-property-id"),PropertyValue:a(c).val()})}),k(d,e.getCheckout().CustomerInvoiceAddress)?i():c.post("/rest/checkout/customerinvoiceaddress/",d).done(function(a){i().done(function(){e.loadCheckout()})})}function k(a,b){for(var c in a)if(a[c]+""!=b[c]+""&&"EmailRepeat"!==c)return!1;return!0}function l(){var b=a('[data-plenty-checkout-form="shippingProfileSelect"]').getFormValues();return e.getCheckout().CheckoutShippingProfileID=b.ShippingProfileID,delete e.getCheckout().CheckoutCustomerShippingAddressID,delete e.getCheckout().CheckoutMethodOfPaymentID,e.setCheckout().done(function(){e.reloadContainer("MethodsOfPaymentList")})}function m(){return c.post("/rest/checkout/preparepayment/",null).done(function(b){if(""!=b.data.CheckoutMethodOfPaymentRedirectURL)document.location.assign(b.data.CheckoutMethodOfPaymentRedirectURL);else if(b.data.CheckoutMethodOfPaymentAdditionalContent){var c=a(b.data.CheckoutMethodOfPaymentAdditionalContent).find('[data-plenty-checkout-form="bankDetails"]').length>0;f.prepare().setContent(b.data.CheckoutMethodOfPaymentAdditionalContent).onConfirm(function(){return c?p():r()}).show()}})}function n(b){return b=b||a('[data-plenty-checkout-form="methodOfPayment"]').getFormValues().MethodOfPaymentID,e.getCheckout().CheckoutMethodOfPaymentID=b,delete e.getCheckout().CheckoutCustomerShippingAddressID,delete e.getCheckout().CheckoutShippingProfileID,e.setCheckout().done(function(){e.reloadContainer("ShippingProfilesList")})}function o(){d.getContainer("CheckoutPaymentInformationBankDetails").from("Checkout").done(function(b){f.prepare().setContent(b.data[0]).onDismiss(function(){a('input[name="MethodOfPaymentID"]').each(function(b,c){a(c).val()==e.getCheckout().CheckoutMethodOfPaymentID?a(c).attr("checked","checked"):a(c).removeAttr("checked")})}).onConfirm(function(){return p()}).show()})}function p(){var b=a('[data-plenty-checkout-form="bankDetails"]');if(b.validateForm()){var d=b.getFormValues().checkout.customerBankDetails,f={CustomerBankName:d.bankName,CustomerBLZ:d.blz,CustomerAccountNumber:d.accountNo,CustomerAccountOwner:d.accountOwner,CustomerIBAN:d.iban,CustomerBIC:d.bic};return c.post("/rest/checkout/paymentinformationbankdetails/",f).done(function(){e.loadCheckout().done(function(){n(3),e.reloadContainer("MethodsOfPaymentList")})}),!0}return!1}function q(){d.getContainer("CheckoutPaymentInformationCreditCard").from("Checkout").done(function(b){f.prepare().setContent(b.data[0]).onDismiss(function(){a('input[name="MethodOfPaymentID"]').each(function(b,c){a(c).val()==e.getCheckout().CheckoutMethodOfPaymentID?a(c).attr("checked","checked"):a(c).removeAttr("checked")})}).onConfirm(function(){return r()}).show()})}function r(){var b=a('[data-plenty-checkout-form="creditCard"]');if(b.validateForm()){var d=b.getFormValues().checkout.paymentInformationCC,f={Owner:d.owner,Cvv2:d.cvv2,Number:d.number,Year:d.year,Month:d.month,Provider:d.provider};return c.post("/rest/checkout/paymentinformationcreditcard/",f).done(function(){e.loadCheckout()}),!0}return!1}function s(b){if(2==e.getCheckout().CustomerInvoiceAddress.LoginType)var c=a('[data-plenty-checkout-form="shippingAddress"]').getFormValues();else var c=a('[data-plenty-checkout-form="guestRegistration"]').getFormValues();var g={street:c.Street,houseNo:c.HouseNo,ZIP:c.ZIP,city:c.City,postnummer:c.Postnummer,suggestionType:"postfinder"};d.getContainer("CheckoutAddressSuggestionResultsList",g).from("Checkout").done(function(a){f.prepare().setContent(a.data[0]).show()})}function t(){var b=a('[data-plenty-checkout-form="placeOrder"]');if(b.validateForm()){var d=b.getFormValues(),e={TermsAndConditionsCheck:d.termsAndConditionsCheck||0,WithdrawalCheck:d.withdrawalCheck||0,PrivacyPolicyCheck:d.privacyPolicyCheck||0,AgeRestrictionCheck:d.ageRestrictionCheck||0,NewsletterCheck:d.newsletterCheck||0,KlarnaTermsAndConditionsCheck:d.klarnaTermsAndConditionsCheck||0,PayoneDirectDebitMandateCheck:d.payoneDirectDebitMandateCheck||0,PayoneInvoiceCheck:d.payoneInvoiceCheck||0};return c.post("/rest/checkout/placeorder/",e).done(function(a){""!=a.data.MethodOfPaymentRedirectURL?window.location.assign(a.data.MethodOfPaymentRedirectURL):""!=a.data.MethodOfPaymentAdditionalContent?f.prepare().setContent(a.data.MethodOfPaymentAdditionalContent).setLabelDismiss("").onDismiss(function(){window.location.assign(b.attr("action"))}).onConfirm(function(){window.location.assign(b.attr("action"))}).show():window.location.assign(b.attr("action"))})}}return{init:g,setCustomerSignAndInfo:h,registerGuest:j,setShippingProfile:l,saveShippingAddress:i,loadAddressSuggestion:s,preparePayment:m,setMethodOfPayment:n,editBankDetails:o,editCreditCard:q,placeOrder:t}},["APIFactory","CMSFactory","CheckoutFactory","ModalFactory"])}(jQuery,PlentyFramework),function(a,b){b.service("MediaSizeService",function(){function b(){return e&&c(),e}function c(){var b;if(b=window.matchMedia?window.matchMedia("(min-width:1200px)").matches?"lg":window.matchMedia("(min-width:992px)").matches?"md":window.matchMedia("(min-width:768px)").matches?"sm":"xs":a(window).width()>=1200?"lg":a(window).width()>=992?"md":a(window).width()>=768?"sm":"xs",b!=e){var c=e;e=b,a(window).trigger("sizeChange",[e,c])}}function d(a){for(var b=a.replace(/\s/g,"").split(","),c=0;c li'),r=a('[data-plenty-checkout="container"] > div'),u=a('[data-plenty-checkout="next"]'),t=a('[data-plenty-checkout="prev"]'),q.length==r.length&&r.length>0){d.getCheckout();r.hide(),q.each(function(b,c){a(c).addClass("disabled"),a(c).click(function(){a(this).is(".disabled")||j(b)})}),u.attr("disabled","disabled"),u.click(function(){m()}),t.attr("disabled","disabled"),t.click(function(){n()}),window.addEventListener("hashchange",function(){window.location.hash.length>0?o(window.location.hash):j(0)},!1),a.urlParam=function(a){var b=new RegExp("[?&]"+a+"=([^]*)").exec(window.location.href);return null==b?null:b[1]||0};var c=a.urlParam("gototab");0==window.location.hash.length&&c&&a('[data-plenty-checkout-id="'+c+'"]').length>0?window.location.hash=c:j(!o(window.location.hash)&&s>=0?s:0),p(),a(window).on("sizeChange",p),a(window).resize(function(){"xs"==b.getInstance().MediaSizeService.interval()&&p()})}}function f(){return s>=0?{id:a(r[s]).attr("data-plenty-checkout-id"),index:s}:null}function g(a){return v.beforeChange.push(a),b.getInstance().NavigatorService}function h(a){return v.afterChange.push(a),b.getInstance().NavigatorService}function i(b,c){var d=!0;if(s>=0||"afterChange"===b){var e=f(),g={index:c,id:a(r[c]).attr("data-plenty-checkout-id")};a.each(v[b],function(a,b){return b(e,g)===!1?(d=!1,!1):void 0})}return d}function j(e,f){var g=s!==e;(!g||f||i("beforeChange",e))&&(s=e,!Object.equals(w[s],d.getCheckout(!0))&&g&&a(r[s]).attr("data-plenty-checkout-content")?(w[s]=d.getCheckout(!0),c.getCategoryContent(a(r[s]).attr("data-plenty-checkout-content")).done(function(c){a(r[s]).html(c.data[0]),k(g),b.getInstance().bindDirectives(r[s]),a(window).trigger("contentChanged")})):k(g))}function k(b){a(r).hide(),a(q).each(function(b,c){a(c).removeClass("disabled active"),a(c).find('[role="tab"]').attr("aria-selected","false"),s>b?a(c).addClass("visited"):b==s?(a(c).addClass("active visited"),a(c).find('[role="tab"]').attr("aria-selected","true")):b>s&&!a(c).is(".visited")&&a(c).addClass("disabled")}),p(),0>=s?a(t).attr("disabled","disabled"):a(t).removeAttr("disabled"),s+1==q.length?a(u).attr("disabled","disabled"):a(u).removeAttr("disabled"),a(r[s]).show(),s>0?window.location.hash=a(r[s]).attr("data-plenty-checkout-id"):window.location.hash.length>0&&(window.location.hash=""),b&&i("afterChange",s)}function l(a){j(a.index,!0)}function m(){s0&&j(s-1)}function o(b){return"next"==b?(m(),!0):"prev"==b?(n(),!0):(b=b.replace("#",""),a(r).each(function(c,d){return a(d).attr("data-plenty-checkout-id")==b?(j(c),!0):void 0}),!1)}function p(){var b=q.length;if(!(0>=b)){a(q).removeAttr("style"),a(q).children("span").removeAttr("style"),a(u).removeAttr("style"),a(t).removeAttr("style");var c=a(t).outerWidth()c?a(d).children("span").css({paddingLeft:g+"px",paddingRight:h+"px"}):a(d).children("span").css({paddingLeft:j+"px",paddingRight:k+"px"})})}}var q=[],r=[],s=-1,t={},u={},v={beforeChange:[],afterChange:[]},w=[];return{init:e,getCurrentContainer:f,goTo:j,beforeChange:g,afterChange:h,continueChange:l,next:m,previous:n,goToID:o,fillNavigation:p}},["CMSFactory","CheckoutFactory"])}(jQuery,PlentyFramework),function(a,b){b.service("PostfinderService",function(c,d,e){function f(){var b=a('input[name="Street"]').val();return"PACKSTATION"==b.toUpperCase()||"POSTFILIALE"==b.toUpperCase()}function g(){j={PostfinderItemStreet:a('input[name="Street"]','[data-plenty-checkout-form="shippingAddress"]'),PostfinderItemZIP:a('input[name="ZIP"]','[data-plenty-checkout-form="shippingAddress"]'),PostfinderItemCity:a('input[name="City"]','[data-plenty-checkout-form="shippingAddress"]'),PostfinderItemHouseNo:a('input[name="HouseNo"]','[data-plenty-checkout-form="shippingAddress"]')},j.PostfinderItemStreet.val(""),j.PostfinderItemZIP.val().length>2||j.PostfinderItemCity.val().length>2?c.get("/rest/checkout/shippingaddresspostfinderlist/",{suggestionType:"postfinder",zip:j.PostfinderItemZIP.val(),city:j.PostfinderItemCity.val()}).done(function(c){l=c.data,k=l.length,0==k&&h();for(var e={addresses:[]},f=0;k>f;f++){var g="km",m=l[f].PostfinderItemDistance,n=m/1e3;n=(Math.round(100*n)/100).toFixed(2).replace(".",","),1e3>m&&(n=m,g="m"),e.addresses.push({index:f,dimension:g,type:l[f].PostfinderItemIsPackstation?"Packstation":"Postfiliale",number:l[f].PostfinderItemIsPackstation?l[f].PostfinderItemPackstationNo:l[f].PostfinderItemPostfilialNo,street:l[f].PostfinderItemStreet,houseNo:l[f].PostfinderItemHouseNo,zip:l[f].PostfinderItemZIP,city:l[f].PostfinderItemCity,district:l[f].PostfinderItemDistrict,distance:n,remark:l[f].PostfinderItemRemark})}var o=b.compileTemplate("addressSuggestions/postFinder.html",e);d.prepare().setTitle(b.translate("Packstations and post offices in your area")).setContent(o).setClass("checkout").onConfirm(function(){return j.PostfinderItemCity.removeClass("has-error").addClass("has-success"),a('label[for="'+j.PostfinderItemCity.attr("id")+'"]').removeClass("has-error").addClass("has-success"),j.PostfinderItemZIP.removeClass("has-error").addClass("has-success"),a('label[for="'+j.PostfinderItemZIP.attr("id")+'"]').removeClass("has-error").addClass("has-success"),j.PostfinderItemStreet.removeClass("has-error").addClass("has-success"),a('label[for="'+j.PostfinderItemStreet.attr("id")+'"]').removeClass("has-error").addClass("has-success"),j.PostfinderItemHouseNo.removeClass("has-error").addClass("has-success"),a('label[for="'+j.PostfinderItemHouseNo.attr("id")+'"]').removeClass("has-error").addClass("has-success"),i=a('input[type="radio"][name="postfinder"]:checked').val(),l[i].PostfinderItemIsPackstation?(a(j.PostfinderItemStreet).val("PACKSTATION"),a(j.PostfinderItemHouseNo).val(l[i].PostfinderItemPackstationNo)):(a(j.PostfinderItemStreet).val("POSTFILIALE"),a(j.PostfinderItemHouseNo).val(l[i].PostfinderItemPostfilialNo)),a(j.PostfinderItemStreet).trigger("change"),a(j.PostfinderItemCity).val(l[i].PostfinderItemCity),a(j.PostfinderItemZIP).val(l[i].PostfinderItemZIP),!0}).show()}):h()}function h(){e.throwError(0,b.translate("Please enter a ZIP code and/or a city.")),j.PostfinderItemCity.removeClass("has-success").addClass("has-error"),a('label[for="'+j.PostfinderItemCity.attr("id")+'"]').removeClass("has-success").addClass("has-error"),j.PostfinderItemZIP.removeClass("has-success").addClass("has-error"),a('label[for="'+j.PostfinderItemZIP.attr("id")+'"]').removeClass("has-success").addClass("has-error"),j.PostfinderItemCity.focus(function(){a(this).removeClass("has-error");var b=a(this).attr("id");a(this).closest(".form-group").find('[for="'+b+'"]').removeClass("has-error")}),j.PostfinderItemZIP.focus(function(){a(this).removeClass("has-error");var b=a(this).attr("id");a(this).closest(".form-group").find('[for="'+b+'"]').removeClass("has-error")})}var i="",j={},k={},l={};return{openPostfinderModal:g,isPackstation:f}},["APIFactory","ModalFactory","UIFactory"])}(jQuery,PlentyFramework),function(a,b){b.service("SocialShareService",function(){function b(a){var b={"facebook-like":'',"facebook-recommend":'',twitter:'',"google-plus":''};return b[a]}function c(){var b=document.location.href,c=a("link[rel=canonical]").attr("href");return c&&c.length>0&&(c.indexOf("http")<0&&(c=document.location.protocol+"//"+document.location.host+c),b=c),b}function d(b){var c=a('meta[name="'+b+'"]').attr("content");return c||""}function e(){var b=d("DC.title"),c=d("DC.creator");return b.length>0&&c.length>0?b+=" - "+c:b=a("title").text(),encodeURIComponent(b)}return"undefined"==typeof socialLangLocale&&(socialLangLocale="en_US"),"undefined"==typeof socialLang&&(socialLang="en"),{getSocialService:b}})}(jQuery,PlentyFramework),function($,pm){pm.service("ValidationService",function(){function getFormControl(a){return a=$(a),a.is("input")||a.is("select")||a.is("textarea")?a:a.find("input").length>0?a.find("input"):a.find("select").length>0?a.find("select"):a.find("textarea").length>0?a.find("textarea"):null}function validateText(a){return a.is("input")||a.is("select")||a.is("textarea")?$.trim(a.val()).length>0:(console.error("Validation Error: Cannot validate Text for <"+a.prop("tagName")+">"),!1)}function validateMail(a){var b=/[a-z0-9!#$%&'*+\/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+\/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?/;return validateText(a)?b.test($.trim(a.val())):!1}function validateNumber(a){return validateText(a)?$.isNumeric($.trim(a.val())):!1}function validateValue(a,b){return $(b).length>0?$.trim(a.val())==$.trim($(b).val()):$.trim(a.val())==b}function visibility(a){return a.is(":visible")}function isEnabled(a){return a.is(":enabled")}function validate(form,errorClass){var formControl,formControls,validationKey,currentHasError,group,checked,checkedMin,checkedMax,attrValidate,validationKeys,formControlAttrType,$form=$(form);errorClass=errorClass||"has-error";var missingFields=[],hasError=!1;$form.find("[data-plenty-validate], input.Required").each(function(i,elem){attrValidate=$(elem).attr("data-plenty-validate"),formControls=getFormControl(elem),validationKeys=attrValidate?attrValidate:"text",validationKeys=validationKeys.split(",");for(var i=0,length=formControls.length;length>i;i++){if(formControl=$(formControls[i]),formControlAttrType=formControl.attr("type"),!visibility(formControl)||!isEnabled(formControl))return;if(validationKey=validationKeys[i].trim()||validationKeys[0].trim(),currentHasError=!1,formControl.is("input")&&"radio"!=formControlAttrType&&"checkbox"!=formControlAttrType||formControl.is("textarea"))switch(validationKey){case"text":currentHasError=!validateText(formControl);break;case"mail":currentHasError=!validateMail(formControl);break;case"number":currentHasError=!validateNumber(formControl);break;case"value":currentHasError=!validateValue(formControl,$(elem).attr("data-plenty-validation-value"));break;case"none":break;default:console.error('Form validation error: unknown validate property: "'+attrValidate+'"')}else if(!formControl.is("input")||"radio"!=formControlAttrType&&"checkbox"!=formControlAttrType){if(!formControl.is("select"))return void console.error("Form validation error: "+$(elem).prop("tagName")+" does not contain an form element");currentHasError=""==formControl.val()||"-1"==formControl.val()}else group=formControl.attr("name"),checked=$form.find('input[name="'+group+'"]:checked').length,"radio"==formControlAttrType?(checkedMin=1,checkedMax=1):(eval("var minMax = "+attrValidate),checkedMin=minMax?minMax.min:1,checkedMax=minMax?minMax.max:1),currentHasError=checkedMin>checked||checked>checkedMax;currentHasError&&(hasError=!0,missingFields.push(formControl),formControls.length>1?(formControl.addClass(errorClass),$form.find('label[for="'+formControl.attr("id")+'"]').addClass(errorClass)):$(elem).addClass(errorClass))}}),$form.on("validationFailed",function(){var a=50,b=$form.find("."+errorClass).first(),c=b.offset().top,d=$("html, body");$form.parents(".modal").length>0?(d=$form.parents(".modal").find(".modal-body"),c=d.scrollTop()-(d.offset().top-b.offset().top)):$form.is(".modal")&&(d=$form.find(".modal-body"),c=d.scrollTop()-(d.offset().top-b.offset().top)),(c-awindow.pageYOffset+window.innerHeight)&&d.animate({scrollTop:c-a})}),hasError&&($form.find("."+errorClass).each(function(a,b){formControl=$(getFormControl(b)),formControl.on("focus click",function(){var a=$(b);a.removeClass(errorClass),$form.find('label[for="'+$(this).attr("id")+'"]').removeClass(errorClass)})}),$form.trigger("validationFailed",[missingFields]));var callback=$form.attr("data-plenty-callback");if(!hasError&&callback&&"submit"!=callback&&"function"==typeof window[callback]){var fields={};return $form.find("input, textarea, select").each(function(){"checkbox"==$(this).attr("type")?fields[$(this).attr("name")]=$(this).is(":checked"):fields[$(this).attr("name")]=$(this).val()}),window[callback](fields),!1}return!hasError}return{validate:validate}}),$.fn.validateForm=function(){return pm.getInstance().ValidationService.validate(this)},$.fn.getFormValues=function(){function a(a,b){var d=a.match(/^([^\[]+)(.*)/);if(d[2]){var e,f=/\[([^\]]+)]/g,g=[];for(g[0]=d[1];null!==(e=f.exec(d[2]));)g.push(e[1]);for(var h=g.length-1;h>=0;h--){var i={};i[g[h]]=b,b=i}c=$.extend(!0,c,b)}else c[d[1]]=b}var b=this,c={};return b.find("input, select, textarea").each(function(c,d){if($(d).attr("name"))if("checkbox"==$(d).attr("type")){var e=[];$(b).find('[name="'+$(d).attr("name")+'"]:checked').each(function(a,b){e.push($(b).val())}),a($(d).attr("name"),e)}else"radio"==$(d).attr("type")?$(d).is(":checked")&&a($(d).attr("name"),$(d).val()):a($(d).attr("name"),$(d).val())}),c}}(jQuery,PlentyFramework),function(a,b){b.directive("Authentication",function(c){function d(d){b.getRecentEvent().preventDefault(),c.customerLogin(a(d))}return{login:d}},["AuthenticationService"])}(jQuery,PlentyFramework),function(a,b){b.directive("Basket",function(c){function d(d){b.getRecentEvent().preventDefault();var e={},f=a(d),g=f.parents("form");e.BasketItemItemID=g.find('[name="ArticleID"]').val(),e.BasketItemPriceID=g.find('[name="SYS_P_ID"]').val(),e.BasketItemQuantity=g.find('[name="ArticleQuantity"]').val(),e.BasketItemBranchID=g.find('[name="source_category"]').val();var h=g.find('[name^="ArticleAttribute"]'),i=[];a.each(h,function(b,c){var d=c.name.match(/^ArticleAttribute\[\d+]\[\d+]\[(\d+)]$/);d&&d[1]&&i.push({BasketItemAttributeID:d[1],BasketItemAttributeValueID:a(c).val()})}),0!=i.length&&(e.BasketItemAttributesList=i),c.addItem([e])}function e(b,c){var d=a(b),e=d.parent().find("input"),f=parseInt(e.attr("maxlength"))||5,g=parseInt(e.val())+c,h=d.parents("[data-basket-item-id]").length>0;if(h){(g+"").length<=f&&g>=0&&e.val(g);var i=d.data("timeout");i&&window.clearTimeout(i),i=window.setTimeout(function(){e.trigger("change")},1e3),d.data("timeout",i)}else(g+"").length<=f&&g>=1&&e.val(g)}function f(b,d){c.setItemQuantity(b,parseInt(a(d).val())).fail(function(){var e=c.getItem(b);a(d).val(e.BasketItemQuantity)})}return{addBasketItem:d,changeItemQuantity:e,setItemQuantity:f}},["BasketService"])}(jQuery,PlentyFramework),function(a,b){b.directive("MobileDropdown",function(c){function d(){a(window).on("orientationchange sizeChange",function(){e(h)}),a("html").click(function(a){e(i)})}function e(b){for(var c=0;c0?window.location.assign(a(c).attr("href")):window.location.assign(c))}function e(a){c.goToID(a)}return{to:d,toCheckoutTab:e}},["MediaSizeService","NavigatorService"])}(jQuery,PlentyFramework),function(a,b){b.directive("Tab",function(c){function d(b){a(b).tab("show")}function e(a,b,c){j[c]||(j[c]=new h),j[c].getTab(b)||j[c].addTab(b),j[c].getTab(b).addLabel(a)}function f(a,b,c){j[c]||(j[c]=new h),j[c].getTab(b)||j[c].addTab(b),j[c].getTab(b).setContent(a)}function g(a,d,e){c.isInterval(e)&&(b.getRecentEvent().preventDefault(),j[d]&&j[d].getTab(a)&&j[d].showTab(a))}function h(){function b(a){return g[a]=new i(a),g[a]}function c(b){var c=0;if(f)c=parseInt(f.getContent().parent().css("zIndex")),f.hide(),f.getContent().parent().css("zIndex",c-1);else{for(var d in g)if(g[d].getContent()){var h=parseInt(g[d].getContent().parent().css("zIndex"));(0==c||c>h)&&(c=h),g[d].hide()}for(var d in g)g[d].getContent()&&g[d].getContent().parent().css("zIndex",c-1);a(window).on("sizeChange",e)}f=g[b],f.getContent().parent().css("zIndex",c),f.show()}function d(a){return g[a]}function e(){for(var a in g)g[a].getContent()&&g[a].show();f=null}var f,g={};return{addTab:b,showTab:c,getTab:d,resetTabs:e}}function i(a){function b(){return j}function c(a){return i.push(a),this}function d(a){return h=a,this}function e(){return h}function f(){for(var a=0;a0&&(a(document).scrollTop()>100?t(v,"addClass","visible"):t(v,"removeClass","visible"))})}function f(b){a(b).owlCarousel({navigation:!0,navigationText:!1,slideSpeed:1e3,paginationSpeed:1e3,singleItem:!0,autoPlay:6e3,stopOnHover:!0,afterMove:function(b){a(b).find('img[data-plenty-rel="lazyload"]').trigger("appear")}})}function g(b,d,e){var f=a(b),g=0,h={},i=f.find('[data-plenty-rel="equal-target"]').length>0?f.find('[data-plenty-rel="equal-target"]'):f.children();e!==!0&&u.push(b);for(var j=i.length;j>=0;j--)h=a(i[j]),h.css("height",""),h.outerHeight(!0)>g&&(g=h.outerHeight(!0));(!d||c.isInterval(d))&&i.height(g)}function h(b){var c=a(b);c.click(function(){return a("html, body").animate({scrollTop:0},400),!1}),a.inArray(c,v)&&v.push(c)}function i(b,c){var d=a(b);d.lazyload({effect:c}),d.on("loaded",function(){d.css("display","inline-block")})}function j(b){console.log(b);var c=a(b),d=c.parent();d.addClass("animating"),c.siblings("ul").slideToggle(200,function(){d.is(".open")?d.removeClass("open"):d.addClass("open"),c.siblings("ul").removeAttr("style"),d.removeClass("animating")})}function k(b,c){var d=a(b),e=a(d.attr("data-plenty-rel"));if(d.is('input[type="radio"]')){var f=a('input[type="radio"][name="'+d.attr("name")+'"]'),g=!c||"checked"==c;f.change(function(){var b=a(this);e.parents('[data-plenty-rel="equal-target"]').css("height","auto"),b.is(":checked")&&b[0]===d[0]&&1==g?e.slideDown(400,function(){s()}):e.slideUp(400,function(){s()})})}else d.click(function(){d.addClass("animating"),e.slideToggle(400,function(){d.removeClass("animating"),d.toggleClass("active"),s()})})}function l(b,c){c=c||400,a(b).parents('[data-plenty-rel="equal-target"]').css("height","auto"),a(b).slideDown(c,function(){s()})}function m(b,c){c=c||400,a(b).parents('[data-plenty-rel="equal-target"]').css("height","auto"),a(b).slideUp(c,function(){s()})}function n(b,c){c=c||400,a(b).parents('[data-plenty-rel="equal-target"]').css("height","auto"),a(b).slideToggle(c,function(){s()})}function o(b,c){var e=a(b),f=e.find('[data-plenty-rel="social-switch"]');e.append(''),f.is("off, on")||f.addClass("off"),f.on("click",function(){f.hasClass("off")&&("tooltip"==e.attr("data-toggle")&&e.tooltip("destroy"),f.removeClass("off").addClass("on"),e.find('[data-plenty-rel="social-placeholder"]').hide(),e.find(".social-container").append(d.getSocialService(c)))})}function p(d,e,f){if(e&&d&&(!f||c.isInterval(f))){var g=b.getRecentEvent();return g&&g.preventDefault(),a(e).toggleClass(d),!1}}function q(d,e,f){if(e&&d&&(!f||c.isInterval(f))){var g=b.getRecentEvent();return g&&g.preventDefault(),a(e).addClass(d),!1}}function r(d,e,f){if(e&&d&&(!f||c.isInterval(f))){var g=b.getRecentEvent();return g&&g.preventDefault(),a(e).removeClass(d),!1}}function s(){for(var a=u.length-1;a>=0;a--)g(u[a],"",!0)}function t(a,b,c){for(var d=a.length-1;d>=0;d--)a[d][b](c)}var u=[],v=[];return{initUIWindowEvents:e,addContentPageSlider:f,equalHeight:g,initToTop:h,initLazyload:i,initSlideToggle:k,slideDown:l,slideUp:m,slideToggle:n,toggleHideShow:j,toggleSocialShare:o,toggleClass:p,addClass:q,removeClass:r}},["MediaSizeService","SocialShareService"])}(jQuery,PlentyFramework),function(a,b){b.directive("Validator",function(a){function b(b,c){return a.validate(b,c)}return{validate:b}},["ValidationService"])}(jQuery,PlentyFramework),PlentyFramework.compile();var plenty=PlentyFramework.getInstance();jQuery(document).ready(function(){plenty.bindDirectives()});
\ No newline at end of file
From 0b8b031701d93bd2874519f376dd5bda1e882add Mon Sep 17 00:00:00 2001
From: Maximilian Lauterbach
Date: Wed, 9 Dec 2015 13:30:10 +0100
Subject: [PATCH 10/17] additional: fixed variable name for PostFinder
---
src/services/CheckoutService.js | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/services/CheckoutService.js b/src/services/CheckoutService.js
index bcbd437..5d0df6b 100644
--- a/src/services/CheckoutService.js
+++ b/src/services/CheckoutService.js
@@ -127,7 +127,7 @@
{
if ( shippingAddress.Street == "PACKSTATION" )
{
- shippingAddress.isPackstation = 1;
+ shippingAddress.IsPackstation = 1;
shippingAddress.PackstationNo = shippingAddress.HouseNo;
}
else if ( shippingAddress.Street == "POSTFILIALE" )
From 41fe38a9ffab4dfae6cee92381411da9654ffcb2 Mon Sep 17 00:00:00 2001
From: Felix
Date: Wed, 9 Dec 2015 15:42:49 +0100
Subject: [PATCH 11/17] =?UTF-8?q?improve=20dependency=20injection:?=
=?UTF-8?q?=E2=80=A8components=20now=20can=20inject=20any=20component=20wi?=
=?UTF-8?q?th=20equal=20or=20higher=20priority=20(1:=20directives,=202:=20?=
=?UTF-8?q?services,=203:=20factories)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/plentyFramework.js | 173 ++++++++++++++++++++---------------------
1 file changed, 84 insertions(+), 89 deletions(-)
diff --git a/src/plentyFramework.js b/src/plentyFramework.js
index 247636c..a3acd7d 100644
--- a/src/plentyFramework.js
+++ b/src/plentyFramework.js
@@ -130,11 +130,7 @@
components.directives[directiveName] = {
name : directiveName,
dependencies: dependencies,
- compile : function()
- {
- var params = PlentyFramework.resolveServices( dependencies );
- PlentyFramework.directives[directiveName] = directiveFunctions.apply( null, params );
- }
+ setup : directiveFunctions
};
};
@@ -404,50 +400,11 @@
components.services[serviceName] = {
name : serviceName,
dependencies: dependencies,
- compile : function()
- {
- var params = PlentyFramework.resolveFactories( dependencies );
- PlentyFramework.prototype[serviceName] = serviceFunctions.apply( null, params );
- }
+ setup : serviceFunctions
};
};
- /**
- * Returns an array containing required factories given by string identifier
- * @function resolveServices
- * @static
- * @private
- * @param {Array} dependencies Names of required factories
- * @return {Array} Objects to apply to callback function
- */
- PlentyFramework.resolveServices = function( dependencies )
- {
- var compiledServices = [];
-
- $.each( dependencies, function( j, dependency )
- {
-
- // factory not found: try to compile dependent factory first
- if ( !PlentyFramework.prototype.hasOwnProperty( dependency ) )
- {
- if ( components.services.hasOwnProperty( dependency ) )
- {
- components.services[dependency].compile();
- }
- else
- {
- console.error( 'Cannot inject Service "' + dependency + '": Service not found.' );
- return false;
- }
- }
- var service = PlentyFramework.prototype[dependency];
- compiledServices.push( service );
- } );
-
- return compiledServices;
- };
-
/**
* Collection of compiled factories
* @attribute factories
@@ -485,48 +442,9 @@
components.factories[factoryName] = {
name : factoryName,
dependencies: dependencies,
- compile : function()
- {
- var params = PlentyFramework.resolveFactories( dependencies );
- PlentyFramework.factories[factoryName] = factoryFunctions.apply( null, params );
- }
- };
-
- };
-
- /**
- * Returns an array containing required factories given by string identifier
- * @function resolveFactories
- * @static
- * @private
- * @param {Array} dependencies Names of required factories
- * @return {Array} Objects to apply to callback function
- */
- PlentyFramework.resolveFactories = function( dependencies )
- {
- var compiledFactories = [];
-
- $.each( dependencies, function( j, dependency )
- {
-
- // factory not found: try to compile dependent factory first
- if ( !PlentyFramework.factories.hasOwnProperty( dependency ) )
- {
- if ( components.factories.hasOwnProperty( dependency ) )
- {
- components.factories[dependency].compile();
- }
- else
- {
- console.error( 'Cannot inject Factory "' + dependency + '": Factory not found.' );
- return false;
- }
- }
- var factory = PlentyFramework.factories[dependency];
- compiledFactories.push( factory );
- } );
+ setup : factoryFunctions
+ }
- return compiledFactories;
};
/**
@@ -625,7 +543,8 @@
{
if ( !PlentyFramework.factories.hasOwnProperty( factory ) )
{
- components.factories[factory].compile();
+ //components.factories[factory].compile();
+ compileComponent( components.factories[factory], 3 );
}
}
@@ -633,7 +552,8 @@
{
if ( !PlentyFramework.prototype.hasOwnProperty( service ) )
{
- components.services[service].compile();
+ //components.factories[factory].compile();
+ compileComponent( components.services[service], 2 );
}
}
@@ -641,7 +561,8 @@
{
if ( !PlentyFramework.directives.hasOwnProperty( directive ) )
{
- components.directives[directive].compile();
+ //components.factories[factory].compile();
+ compileComponent( components.directives[directive], 1 );
}
}
@@ -653,6 +574,80 @@
};
+ // Level: 1 = directive, 2 = service, 3 = factory
+ function compileComponent( component, componentLevel, dependencyStack )
+ {
+ dependencyStack = dependencyStack || [];
+
+ // resolve dependencies
+ var compiledDependencies = [];
+ for( var i = 0; i < component.dependencies.length; i++ )
+ {
+ var dependency = component.dependencies[i];
+ if ( $.inArray( dependency, dependencyStack ) < 0 )
+ {
+ // add dependency to stack to avoid cyclic injection
+ dependencyStack.push( dependency );
+
+ if ( components.factories.hasOwnProperty( dependency ) )
+ {
+ // required dependency is a factory
+ if ( !PlentyFramework.factories.hasOwnProperty( dependency ) )
+ {
+ // factory is not compiled yet
+ compileComponent( components.factories[dependency], 3, dependencyStack );
+ }
+ compiledDependencies.push( PlentyFramework.factories[dependency] );
+ continue;
+ }
+
+ if ( componentLevel <= 2 && components.services.hasOwnProperty( dependency ) )
+ {
+ // required dependency is a service
+ if ( !PlentyFramework.prototype.hasOwnProperty( dependency ) )
+ {
+ // service is not compiled yet
+ compileComponent( components.services[dependency], 2, dependencyStack );
+ }
+ compiledDependencies.push( PlentyFramework.prototype[dependency] );
+ continue;
+ }
+
+ if ( componentLevel <= 1 && components.directives.hasOwnProperty( dependency ) )
+ {
+ // required dependency is a directive
+ if ( !PlentyFramework.directives.hasOwnProperty( dependency ) )
+ {
+ // directive is not compiled yet
+ compileComponent( components.directives[dependency], 1, dependencyStack );
+ }
+ compiledDependencies.push( PlentyFramework.directives[dependency] );
+ continue;
+ }
+
+ console.error( 'Cannot inject dependency "' + dependency + '": Object not found.' );
+ }
+ else
+ {
+ console.error( 'Cyclic dependency injection: ' + dependencyStack.join( ' -> ' ) + ' -> ' + dependency );
+ }
+ }
+
+ // compile component
+ if( componentLevel == 3 )
+ {
+ PlentyFramework.factories[component.name] = component.setup.apply( null, compiledDependencies );
+ }
+ else if( componentLevel == 2 )
+ {
+ PlentyFramework.prototype[component.name] = component.setup.apply( null, compiledDependencies );
+ }
+ else if( componentLevel == 1 )
+ {
+ PlentyFramework.directives[component.name] = component.setup.apply( null, compiledDependencies );
+ }
+ }
+
}( jQuery ));
From 41a674fa63c7ac7b5ec0b5d79c4e5738d1ac0ad1 Mon Sep 17 00:00:00 2001
From: Maximilian Lauterbach
Date: Thu, 10 Dec 2015 15:21:31 +0100
Subject: [PATCH 12/17] version update
---
dist/plentymarketsCMStools-1.0.1.min.js | 9 -
....0.1.js => plentymarketsCMStools-1.0.2.js} | 302 ++++++++++++------
dist/plentymarketsCMStools-1.0.2.min.js | 10 +
package.json | 2 +-
4 files changed, 223 insertions(+), 100 deletions(-)
delete mode 100644 dist/plentymarketsCMStools-1.0.1.min.js
rename dist/{plentymarketsCMStools-1.0.1.js => plentymarketsCMStools-1.0.2.js} (96%)
create mode 100644 dist/plentymarketsCMStools-1.0.2.min.js
diff --git a/dist/plentymarketsCMStools-1.0.1.min.js b/dist/plentymarketsCMStools-1.0.1.min.js
deleted file mode 100644
index 82ec69a..0000000
--- a/dist/plentymarketsCMStools-1.0.1.min.js
+++ /dev/null
@@ -1,9 +0,0 @@
-/**
- * Licensed under AGPL v3
- * (https://github.com/plentymarkets/plenty-cms-library/blob/master/LICENSE)
- * =====================================================================================
- * @copyright Copyright (c) 2015, plentymarkets GmbH (http://www.plentymarkets.com)
- * @author Felix Dausch
- * =====================================================================================
-*/!function(a,b){"object"==typeof exports&&exports&&"string"!=typeof exports.nodeName?b(exports):"function"==typeof define&&define.amd?define(["exports"],b):(a.Mustache={},b(Mustache))}(this,function(a){function b(a){return"function"==typeof a}function c(a){return p(a)?"array":typeof a}function d(a){return a.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g,"\\$&")}function e(a,b){return null!=a&&"object"==typeof a&&b in a}function f(a,b){return q.call(a,b)}function g(a){return!f(r,a)}function h(a){return String(a).replace(/[&<>"'\/]/g,function(a){return s[a]})}function i(b,c){function e(){if(r&&!s)for(;q.length;)delete o[q.pop()];else q=[];r=!1,s=!1}function f(a){if("string"==typeof a&&(a=a.split(u,2)),!p(a)||2!==a.length)throw new Error("Invalid tags: "+a);h=new RegExp(d(a[0])+"\\s*"),i=new RegExp("\\s*"+d(a[1])),m=new RegExp("\\s*"+d("}"+a[1]))}if(!b)return[];var h,i,m,n=[],o=[],q=[],r=!1,s=!1;f(c||a.tags);for(var y,z,A,B,C,D,E=new l(b);!E.eos();){if(y=E.pos,A=E.scanUntil(h))for(var F=0,G=A.length;G>F;++F)B=A.charAt(F),g(B)?q.push(o.length):s=!0,o.push(["text",B,y,y+1]),y+=1,"\n"===B&&e();if(!E.scan(h))break;if(r=!0,z=E.scan(x)||"name",E.scan(t),"="===z?(A=E.scanUntil(v),E.scan(v),E.scanUntil(i)):"{"===z?(A=E.scanUntil(m),E.scan(w),E.scanUntil(i),z="&"):A=E.scanUntil(i),!E.scan(i))throw new Error("Unclosed tag at "+E.pos);if(C=[z,A,y,E.pos],o.push(C),"#"===z||"^"===z)n.push(C);else if("/"===z){if(D=n.pop(),!D)throw new Error('Unopened section "'+A+'" at '+y);if(D[1]!==A)throw new Error('Unclosed section "'+D[1]+'" at '+y)}else"name"===z||"{"===z||"&"===z?s=!0:"="===z&&f(A)}if(D=n.pop())throw new Error('Unclosed section "'+D[1]+'" at '+E.pos);return k(j(o))}function j(a){for(var b,c,d=[],e=0,f=a.length;f>e;++e)b=a[e],b&&("text"===b[0]&&c&&"text"===c[0]?(c[1]+=b[1],c[3]=b[3]):(d.push(b),c=b));return d}function k(a){for(var b,c,d=[],e=d,f=[],g=0,h=a.length;h>g;++g)switch(b=a[g],b[0]){case"#":case"^":e.push(b),f.push(b),e=b[4]=[];break;case"/":c=f.pop(),c[5]=b[2],e=f.length>0?f[f.length-1][4]:d;break;default:e.push(b)}return d}function l(a){this.string=a,this.tail=a,this.pos=0}function m(a,b){this.view=a,this.cache={".":this.view},this.parent=b}function n(){this.cache={}}var o=Object.prototype.toString,p=Array.isArray||function(a){return"[object Array]"===o.call(a)},q=RegExp.prototype.test,r=/\S/,s={"&":"&","<":"<",">":">",'"':""","'":"'","/":"/"},t=/\s*/,u=/\s+/,v=/\s*=/,w=/\s*\}/,x=/#|\^|\/|>|\{|&|=|!/;l.prototype.eos=function(){return""===this.tail},l.prototype.scan=function(a){var b=this.tail.match(a);if(!b||0!==b.index)return"";var c=b[0];return this.tail=this.tail.substring(c.length),this.pos+=c.length,c},l.prototype.scanUntil=function(a){var b,c=this.tail.search(a);switch(c){case-1:b=this.tail,this.tail="";break;case 0:b="";break;default:b=this.tail.substring(0,c),this.tail=this.tail.substring(c)}return this.pos+=b.length,b},m.prototype.push=function(a){return new m(a,this)},m.prototype.lookup=function(a){var c,d=this.cache;if(d.hasOwnProperty(a))c=d[a];else{for(var f,g,h=this,i=!1;h;){if(a.indexOf(".")>0)for(c=h.view,f=a.split("."),g=0;null!=c&&gi;++i)g=void 0,e=a[i],f=e[0],"#"===f?g=this.renderSection(e,b,c,d):"^"===f?g=this.renderInverted(e,b,c,d):">"===f?g=this.renderPartial(e,b,c,d):"&"===f?g=this.unescapedValue(e,b):"name"===f?g=this.escapedValue(e,b):"text"===f&&(g=this.rawValue(e)),void 0!==g&&(h+=g);return h},n.prototype.renderSection=function(a,c,d,e){function f(a){return g.render(a,c,d)}var g=this,h="",i=c.lookup(a[1]);if(i){if(p(i))for(var j=0,k=i.length;k>j;++j)h+=this.renderTokens(a[4],c.push(i[j]),d,e);else if("object"==typeof i||"string"==typeof i||"number"==typeof i)h+=this.renderTokens(a[4],c.push(i),d,e);else if(b(i)){if("string"!=typeof e)throw new Error("Cannot use higher-order sections without the original template");i=i.call(c.view,e.slice(a[3],a[5]),f),null!=i&&(h+=i)}else h+=this.renderTokens(a[4],c,d,e);return h}},n.prototype.renderInverted=function(a,b,c,d){var e=b.lookup(a[1]);return!e||p(e)&&0===e.length?this.renderTokens(a[4],b,c,d):void 0},n.prototype.renderPartial=function(a,c,d){if(d){var e=b(d)?d(a[1]):d[a[1]];return null!=e?this.renderTokens(this.parse(e),c,d,e):void 0}},n.prototype.unescapedValue=function(a,b){var c=b.lookup(a[1]);return null!=c?c:void 0},n.prototype.escapedValue=function(b,c){var d=c.lookup(b[1]);return null!=d?a.escape(d):void 0},n.prototype.rawValue=function(a){return a[1]},a.name="mustache.js",a.version="2.1.3",a.tags=["{{","}}"];var y=new n;a.clearCache=function(){return y.clearCache()},a.parse=function(a,b){return y.parse(a,b)},a.render=function(a,b,d){if("string"!=typeof a)throw new TypeError('Invalid template! Template should be a "string" but "'+c(a)+'" was given as the first argument for mustache#render(template, view, partials)');return y.render(a,b,d)},a.to_html=function(c,d,e,f){var g=a.render(c,d,e);return b(f)?void f(g):g},a.escape=h,a.Scanner=l,a.Context=m,a.Writer=n}),Object.equals=function(a,b){if(a===b)return!0;if(!(a instanceof Object&&b instanceof Object))return!1;if(a.constructor!==b.constructor)return!1;for(var c in a)if(a.hasOwnProperty(c)){if(!b.hasOwnProperty(c))return!1;if(a[c]!==b[c]){if("object"!=typeof a[c])return!1;if(!Object.equals(a[c],b[c]))return!1}}for(var c in b)if(b.hasOwnProperty(c)&&!a.hasOwnProperty(c))return!1;return!0};var TemplateCache={};TemplateCache["addressSuggestions/addressDoctor.html"]='\n {{#values}}\n - \n \n {{.}}\n \n
\n {{/values}}\n
',TemplateCache["addressSuggestions/postFinder.html"]='{{#addresses}}\n\n
\n \n
\n
\n{{/addresses}}\n',TemplateCache["error/errorMessage.html"]='\n Code {{code}}:\n {{{message}}}\n
\n',TemplateCache["error/errorPopup.html"]='\n
\n
\n
\n
\n',TemplateCache["modal/modal.html"]='\n
\n
\n\n {{#title}}\n \n {{/title}}\n\n
{{{content}}}
\n\n \n
\n
\n
\n',TemplateCache["waitscreen/waitscreen.html"]='',function(a){function b(a,b,c,d){a.on(b,function(a){return g.push(a),c.apply(null,d)})}function c(b){var c=a(b);c.is('input[type="checkbox"]')&&c.on("change",function(){c.is(":checked")?c.trigger("check"):c.trigger("uncheck")}),c.is('input[type="radio"]')&&c.on("change",function(){var b=c.attr("name");a('input[type="radio"][name="'+b+'"]').each(function(b,c){var d=a(c);d.is(":checked")?d.trigger("check"):d.trigger("uncheck")})})}function d(a,b){for(var c=/^(([\w]+):)?([\w]+)\.([\w]+)(\((.*)\))?$/,d=a.split(";"),e=[],f=0;f0)for(var j=h[6].match(/(['][^']+['])|([\w-]+)|(["][^"]+["])/g),k=0;k=0;c--)if(a==g[c].type)return g[c];return null},PlentyFramework.pushEvent=function(a){g.push(a)},PlentyFramework.service=function(a,b,c){return"string"!=typeof a?void console.error("Type mismatch: Expect first parameter to be a 'string', '"+typeof a+"' given."):"function"!=typeof b?void console.error("Type mismatch: Expect second parameter to be a 'function', '"+typeof b+"' given."):(c=c||[],void(e.services[a]={name:a,dependencies:c,compile:function(){var d=PlentyFramework.resolveFactories(c);PlentyFramework.prototype[a]=b.apply(null,d)}}))},PlentyFramework.resolveServices=function(b){var c=[];return a.each(b,function(a,b){if(!PlentyFramework.prototype.hasOwnProperty(b)){if(!e.services.hasOwnProperty(b))return console.error('Cannot inject Service "'+b+'": Service not found.'),!1;e.services[b].compile()}var d=PlentyFramework.prototype[b];c.push(d)}),c},PlentyFramework.factories={},PlentyFramework.factory=function(a,b,c){return"string"!=typeof a?void console.error("Type mismatch: Expect first parameter to be a 'string', '"+typeof a+"' given."):"function"!=typeof b?void console.error("Type mismatch: Expect second parameter to be a 'function', '"+typeof b+"' given."):(c=c||[],void(e.factories[a]={name:a,dependencies:c,compile:function(){var d=PlentyFramework.resolveFactories(c);PlentyFramework.factories[a]=b.apply(null,d)}}))},PlentyFramework.resolveFactories=function(b){var c=[];return a.each(b,function(a,b){if(!PlentyFramework.factories.hasOwnProperty(b)){if(!e.factories.hasOwnProperty(b))return console.error('Cannot inject Factory "'+b+'": Factory not found.'),!1;e.factories[b].compile()}var d=PlentyFramework.factories[b];c.push(d)}),c},PlentyFramework.compileTemplate=function(a,b){return b=b||{},b.translate=function(){return function(a,b){return b(PlentyFramework.translate(a))}},Mustache.render(TemplateCache[a],b)},PlentyFramework.scriptPath="",PlentyFramework.Strings={},PlentyFramework.loadLanguageFile=function(b){a.get(PlentyFramework.scriptPath+b).done(function(a){PlentyFramework.Strings=a})},PlentyFramework.translate=function(a,b){var c;return PlentyFramework.Strings.hasOwnProperty(a)?c=PlentyFramework.Strings[a]:(c=a,console.warn('No translation found for "'+c+'".')),b&&(c=Mustache.render(c,b)),c},PlentyFramework.compile=function(){for(var a in e.factories)PlentyFramework.factories.hasOwnProperty(a)||e.factories[a].compile();for(var b in e.services)PlentyFramework.prototype.hasOwnProperty(b)||e.services[b].compile();for(var c in e.directives)PlentyFramework.directives.hasOwnProperty(c)||e.directives[c].compile();var d=document.getElementsByTagName("SCRIPT");d.length>0&&(PlentyFramework.scriptPath=d[d.length-1].src.match(/(.*)\/(.*)\.js(\?\S*)?$/)[1])}}(jQuery),PlentyFramework.cssClasses={active:"active"},function(a,b){b.partials.Error={init:function(b){a(b).find(".close").click(function(){b.hide(),b.find(".plentyErrorBoxInner").html("")})},addError:function(b,c){var d=a(c).attr("data-plenty-error-code");a(b).find('[data-plenty-error-code="'+d+'"]').length<=0&&a(b).find(".plentyErrorBoxInner").append(c)},show:function(b){a(b).show()}}}(jQuery,PlentyFramework),function(a,b){b.partials.Modal={init:function(a,b){a.on("hidden.bs.modal",function(){b.hide(),a.remove()}),b.timeout>0&&(a.on("hide.bs.modal",b.stopTimeout),a.find(".modal-content").hover(function(){b.pauseTimeout()},function(){a.is(".in")&&b.continueTimeout()}))},show:function(a){a.modal("show")},hide:function(a){a.modal("hide")},isModal:function(b){return a(b).filter(".modal").length+a(b).find(".modal").length>0},getModal:function(b){var c=a(b);return c.length>1&&(c=a(b).filter(".modal")||a(b).find(".modal")),c}}}(jQuery,PlentyFramework),function(a){a(document).on("initPartials",function(b,c){a(c).find('[data-toggle="tooltip"]').tooltip({container:"body"})})}(jQuery),function(a,b){b.partials.WaitScreen={show:function(a){a.addClass("in")},hide:function(a){a.removeClass("in")}}}(jQuery,PlentyFramework),function(a,b){b.factory("APIFactory",function(b){function c(c){try{var d=a.parseJSON(c.responseText);b.printErrors(d.error.error_stack)}catch(e){b.throwError(c.status,c.statusText)}}function d(d,e,f,g,h){return g||b.showWaitScreen(),a.ajax(d,{type:"GET",data:e,dataType:"json",async:!h,error:function(a){f||c(a)}}).always(function(){g||b.hideWaitScreen()})}function e(d,e,f,g){var h={type:"POST",dataType:"json",error:function(a){f||c(a)}};return e&&e.isFile?(h.cache=e.cache,h.processData=e.processData,h.data=e.data,h.contentType=!1):(h.data=JSON.stringify(e),h.contentType="application/json"),g||b.showWaitScreen(),a.ajax(d,h).always(function(){g||b.hideWaitScreen()})}function f(d,e,f,g){return g||b.showWaitScreen(),a.ajax(d,{type:"PUT",data:JSON.stringify(e),dataType:"json",contentType:"application/json",error:function(a){f||c(a)}}).always(function(){g||b.hideWaitScreen()})}function g(d,e,f,g){return g||b.showWaitScreen(),a.ajax(d,{type:"DELETE",data:JSON.stringify(e),dataType:"json",contentType:"application/json",error:function(a){f||c(a)}}).always(function(){g||b.hideWaitScreen()})}function h(){return a.Deferred().resolve()}return{get:d,post:e,put:f,"delete":g,idle:h}},["UIFactory"])}(jQuery,PlentyFramework),function(a){a.factory("CMSFactory",function(a){function b(b,c){function d(d){return a.get("/rest/"+d.toLowerCase()+"/container_"+b.toLowerCase()+"/",c)}return{from:d}}function c(b,c){function d(d){return a.get("/rest/"+d.toLowerCase()+"/"+b.toLowerCase()+"/",c)}return{from:d}}function d(b){return a.get("/rest/categoryview/categorycontentbody/?categoryID="+b)}return{getContainer:b,getParams:c,getCategoryContent:d}},["APIFactory"])}(PlentyFramework),function(a){a.factory("CheckoutFactory",function(b,c,d){function e(){return l}function f(a){return m&&l||g(!0),a?$.extend(!0,{},l):m}function g(a){return b.get("/rest/checkout/",null,!1,!1,a).done(function(a){a?(l=a.data,m=new e):d.throwError(0,'Could not receive checkout data [GET "/rest/checkout/" receives null value]')})}function h(){return b.put("/rest/checkout",m).done(function(a){a?(l=a.data,m=new e):d.throwError(0,'Could not receive checkout data [GET "/rest/checkout/" receives null value]')})}function i(b){return c.getContainer("checkout"+b).from("checkout").done(function(c){$('[data-plenty-checkout-template="'+b+'"]').each(function(b,d){$(d).html(c.data[0]),a.getInstance().bindDirectives(d),$(window).trigger("contentChanged")})})}function j(b){return c.getCategoryContent(b).done(function(c){$('[data-plenty-checkout-catcontent="'+b+'"]').each(function(b,d){$(d).html(c.data[0]),a.getInstance().bindDirectives(d),$(window).trigger("contentChanged")})})}function k(b){return c.getContainer("itemview"+b).from("itemview").done(function(c){$('[data-plenty-itemview-template="'+b+'"]').each(function(b,d){$(d).html(c.data[0]),a.getInstance().bindDirectives(d),$(window).trigger("contentChanged")})})}var l,m;return{getCheckout:f,setCheckout:h,loadCheckout:g,reloadContainer:i,reloadCatContent:j,reloadItemContainer:k}},["APIFactory","CMSFactory","UIFactory"])}(PlentyFramework),function(a,b){b.factory("ModalFactory",function(){function c(a){return PlentyFramework.partials.Modal.isModal(a)}function d(){return new e}function e(){function d(a){return s.title=a,this}function e(a){return s.cssClass=a,this}function f(a){return s.content=a,this}function g(a){return s.labelConfirm=a,this}function h(a){return s.labelDismiss=a,this}function i(a){return s.onConfirm=a,this}function j(a){return s.onDismiss=a,this}function k(a){return s.container=a,this}function l(a){return s.timeout=a,this}function m(){t=c(s.content)?PlentyFramework.partials.Modal.getModal(s.content):a(PlentyFramework.compileTemplate("modal/modal.html",s)),a(s.container).append(t);var b=a(s.content).filter("script");b.length>0&&b.each(function(b,c){var d=document.createElement("script");d.type="text/javascript",d.innerHTML=a(c).text(),a(s.container).append(d)}),PlentyFramework.partials.Modal.init(t,s),t.find('[data-plenty-modal="confirm"]').click(function(){var a=s.onConfirm();"undefined"==typeof a&&(a=!0),a&&n(!0)}),PlentyFramework.partials.Modal.show(t),s.timeout>0&&o()}function n(a){PlentyFramework.partials.Modal.hide(t),a||s.onDismiss()}function o(){w=s.timeout,x=(new Date).getTime(),u=window.setTimeout(function(){window.clearInterval(v),n()},s.timeout),t.find('[data-plenty-modal="timer"]').text(w/1e3),v=window.setInterval(function(){if(!y){var a=w-(new Date).getTime()+x;a=Math.round(a/1e3),t.find('[data-plenty-modal="timer"]').text(a)}},1e3)}function p(){y=!0,w-=(new Date).getTime()-x,window.clearTimeout(u)}function q(){y=!1,x=(new Date).getTime(),u=window.setTimeout(function(){n(),window.clearInterval(v)},w)}function r(){window.clearTimeout(u),window.clearInterval(v)}var s=this;s.title="",s.cssClass="",s.content="",s.labelDismiss=b.translate("Cancel"),s.labelConfirm=b.translate("Confirm"),s.onConfirm=function(){},s.onDismiss=function(){},s.container="body",s.timeout=-1,s.hide=n,s.startTimeout=o,s.stopTimeout=r,s.pauseTimeout=p,s.continueTimeout=q;var t,u,v,w,x,y=!1;return{setTitle:d,setClass:e,setContent:f,setContainer:k,setLabelConfirm:g,setLabelDismiss:h,onConfirm:i,onDismiss:j,setTimeout:l,show:m,hide:n}}return{prepare:d,isModal:c}})}(jQuery,PlentyFramework),function(a,b){b.factory("UIFactory",function(){function c(a,b){d([{code:a,message:b}])}function d(c){(!i||a("body").has(i).length<=0)&&(i=a(b.compileTemplate("error/errorPopup.html")),a("body").append(i),b.partials.Error.init(i)),a.each(c,function(c,d){b.partials.Error.addError(i,a(b.compileTemplate("error/errorMessage.html",d)))}),b.partials.Error.show(i),f(!0)}function e(){return h=h||0,(!g||a("body").has(g).length<=0)&&(g=a(b.compileTemplate("waitscreen/waitscreen.html")),a("body").append(g)),b.partials.WaitScreen.show(g),h++,h}function f(a){return h--,(0>=h||a)&&(h=0,b.partials.WaitScreen.hide(g)),h}var g,h=0,i=null;return{throwError:c,printErrors:d,showWaitScreen:e,hideWaitScreen:f}})}(jQuery,PlentyFramework),function(a,b){b.service("AddressDoctorService",function(c){function d(b){var c=!0;return b=b||"[data-plenty-address-doctor]",a(b).filter("[data-plenty-address-doctor]:visible").each(function(b,d){var f=new e(d),g=a(d).attr("data-plenty-address-doctor").replace(/\s/g,"").split(",");f.isValid(g)||(c=!1)}),c}function e(c){function d(a){return i()?!0:(j=new f(l.getFormValues()),k=a,e(),1==j.getAddresses().length)}function e(){a(".suggestion-list").remove();for(var b=!1,c=0;cc;c++){var d=a.data[c],f=e(d);f?f.HouseNo.push(d.HouseNo):(d.HouseNo=[d.HouseNo],j.push(d))}})}function e(a){for(var b=j.length,c=0;b>c;c++)if(a.Street==j[c].Street&&j.ZIP==j[c].ZIP&&a.City==j[c].City)return j[c];return null}function f(){return j}function g(b){for(var c=[],d=j.length,e=0;d>e;e++){var f=j[e];a.inArray(f[b],c)<0&&c.push(f[b])}return c}function h(a){for(var b=[],c=j.length,d=0;c>d;d++){var e=j[d];(a.Street&&a.Street==e.Street||a.ZIP&&a.ZIP==e.ZIP||a.City&&a.City==e.City)&&b.push(e)}j=b}function i(a){a=parseInt(a);for(var b=j.length,c=0;b>c;c++)for(var d=j[c],e=0;e=f[0]&&a<=f[1])return!0}return!1}var j=[];return d(),{getAddresses:f,getList:g,filter:h,houseNoAllowed:i}}return{validateAddress:d}},["APIFactory"])}(jQuery,PlentyFramework),function(a,b){b.service("AuthenticationService",function(c,d,e){function f(){var b=a('[data-plenty-checkout="lostPasswordForm"]');if(b.validateForm()){var d=b.getFormValues(),e={Email:d.Email};return c.post("/rest/checkout/lostpassword/",e).done(function(b){1==b.data.IsMailSend&&(a('[data-plenty-checkout="lostPasswordTextContainer"]').hide(),a('[data-plenty-checkout="lostPasswordSuccessMessage"]').show())})}}function g(a){if(a.validateForm()){var b=a.getFormValues(),d={Email:b.loginMail,Password:b.loginPassword};return e.showWaitScreen(),c.post("/rest/checkout/login/",d).done(function(){window.location.assign(a.attr("action"))})}}function h(a){return c.post("/rest/checkout/customerinvoiceaddress/",a).done(function(a){d.getCheckout().CustomerInvoiceAddress=a.data})}function i(){var c=a('[data-plenty-checkout-form="customerRegistration"]');if(c.validateForm()&&b.getInstance().AddressDoctorService.validateAddress()){var d=c.getFormValues(),e={LoginType:2,FormOfAddressID:d.FormOfAddressID,Company:d.Company,FirstName:d.FirstName,LastName:d.LastName,Street:d.Street,HouseNo:d.HouseNo,AddressAdditional:d.AddressAdditional,ZIP:d.ZIP,City:d.City,CountryID:d.CountryID,VATNumber:d.VATNumber,Email:d.Email,EmailRepeat:d.EmailRepeat,BirthDay:d.BirthDay,BirthMonth:d.BirthMonth,BirthYear:d.BirthYear,Password:d.Password,PasswordRepeat:d.PasswordRepeat,PhoneNumber:d.PhoneNumber,MobileNumber:d.MobileNumber,FaxNumber:d.FaxNumber,Postnummer:d.Postnummer};return e.CustomerPropertiesList=e.CustomerPropertiesList||[],c.find("[data-plenty-property-id]").each(function(b,c){e.CustomerPropertiesList.push({PropertyID:a(c).attr("data-plenty-property-id"),PropertyValue:a(c).val()})}),h(e).done(function(){window.location.assign(c.attr("action"))})}}return{resetPassword:f,customerLogin:g,setInvoiceAddress:h,registerCustomer:i}},["APIFactory","CheckoutFactory","UIFactory"])}(jQuery,PlentyFramework),function(a,b){b.service("BasketService",function(c,d,e,f,g){function h(d){d&&c.get("/rest/checkout/container_"+"CheckoutOrderParamsList".toLowerCase()+"/",{itemID:d[0].BasketItemItemID,quantity:d[0].BasketItemQuantity},!1,!0).done(function(c){c.data[0].indexOf("form-group")>0?g.prepare().setContent(c.data[0]).setTitle(b.translate("Select order parameters")).setLabelConfirm(b.translate("Save")).onConfirm(function(){return a('[data-plenty-checkout-form="OrderParamsForm"]').validateForm()?(j(i(d)),!0):!1}).show():j(d)})}function i(b){var c,d=a('[data-plenty-checkout-form="OrderParamsForm"]'),e={},f="";return d.find('[name^="ParamGroup"]').each(function(){c=this.name.match(/^ParamGroup\[(\d+)]\[(\d+)]$/),b=m(b,c[1],a(this).val(),a(this).val())}),d.find('[name^="ParamValue"]').each(function(){if(e=a(this),f=e.attr("type"),("checkbox"==f&&e.is(":checked")||"radio"==f&&e.is(":checked")||"radio"!=f&&"checkbox"!=f)&&"file"!=f&&"hidden"!=f){var c=e[0].name.match(/^ParamValue\[(\d+)]\[(\d+)]$/);b=m(b,c[1],c[2],e.val())}else if("file"==f)if(e[0].files&&e[0].files.length>0)b=l(e,b);else{var c=e[0].name.match(/^ParamValueFile\[(\d+)]\[(\d+)]$/),d=a('input[type="hidden"][name="ParamValue['+c[1]+"]["+c[2]+']"]').val();b=m(b,c[1],c[2],d)}}),b}function j(a){c.post("/rest/checkout/basketitemslist/",a,!0).done(function(){f.loadCheckout().done(function(){s(),e.getContainer("ItemViewItemToBasketConfirmationOverlay",{ArticleID:a[0].BasketItemItemID}).from("ItemView").done(function(a){g.prepare().setContent(a.data[0]).setTimeout(5e3).show()})})}).fail(function(a){d.printErrors(JSON.parse(a.responseText).error.error_stack)})}function k(a){c.put("/rest/checkout/basketitemslist/",a).done(function(){f.reloadCatContent(b.getGlobal("basketCatID")),f.loadCheckout().done(function(){s()})})}function l(a,b){var d,e,f=a[0].id,g={},h=[],i={type:"POST",data:{},isFile:!0,cache:!1,dataType:"json",processData:!1,contentType:!1};g[f]=a[0].files,-1==h.indexOf(f)&&h.push(f);for(var j=0,k=h.length;k>j;++j)d=new FormData,e=g[h[j]],d.append("0",e[0],e[0].name),i.data=d,c.post("/rest/checkout/orderparamfile/",i);var l=a[0].name.match(/^ParamValueFile\[(\d+)]\[(\d+)]$/);return m(b,l[1],l[2],a.val())}function m(b,c,d,e){return c>0&&void 0==b[c]&&(b[c]=a.extend(!0,{},b[0]),b[c].BasketItemOrderParamsList=[]),void 0!=b[c]&&(b[c].BasketItemQuantity=1,void 0==b[c].BasketItemOrderParamsList&&(b[c].BasketItemOrderParamsList=[]),e&&b[c].BasketItemOrderParamsList.push({BasketItemOrderParamID:d,BasketItemOrderParamValue:e})),b}function n(b){var c=a('[data-plenty-basket-item="'+b+'"');c.modal("show"),c.find('[data-plenty-modal="confirm"]').on("click",function(){var d=p(b),e=[];c.find('select, .PlentyFormContainer.AttrImage > input[type="hidden"]').each(function(b,c){var d=c.name.match(/^ArticleAttribute\[\d+]\[\d+]\[(\d+)]$/);d&&d[1]&&e.push({BasketItemAttributeID:d[1],BasketItemAttributeValueID:a(c).val()})}),0!=e.length&&(d.BasketItemAttributesList=e),k([d])})}function o(d){var e=p(d);e.BasketItemOrderParamsList=[],c.get("/rest/checkout/container_"+"CheckoutOrderParamsList".toLowerCase()+"/",{itemID:e.BasketItemItemID,quantity:e.BasketItemQuantity,basketItemID:d}).done(function(c){g.prepare().setContent(c.data[0]).setTitle(b.translate("Edit order parameters")).setLabelConfirm(b.translate("Save")).onConfirm(function(){return a('[data-plenty-checkout-form="OrderParamsForm"]').validateForm()?(k(i([e])),!0):!1}).show()})}function p(a){for(var b=f.getCheckout().BasketItemsList,c=0;c"+b.translate('Do you really want to remove "{{item}}" from your basket?',{item:j})+"").onDismiss(function(){i.reject()}).onConfirm(function(){h()}).setLabelConfirm(b.translate("Delete")).show(),i}function r(d,e){if(0>=e)return q(d);for(var g,h,i=a.Deferred(),j=f.getCheckout().BasketItemsList,k=0;k0&&f.reloadContainer("Totals")}return{addItem:h,removeItem:q,getItem:p,setItemQuantity:r,editItemAttributes:n,editOrderParams:o,addCoupon:t,removeCoupon:u}},["APIFactory","UIFactory","CMSFactory","CheckoutFactory","ModalFactory"])}(jQuery,PlentyFramework),function(a,b){b.service("CheckoutService",function(c,d,e,f){function g(){e.loadCheckout(!0)}function h(){var b=a('[data-plenty-checkout-form="details"]'),d=b.getFormValues();return e.getCheckout().CheckoutCustomerSign||(e.getCheckout().CheckoutCustomerSign=""),e.getCheckout().CheckoutOrderInfoText||(e.getCheckout().CheckoutOrderInfoText=""),e.getCheckout().CheckoutCustomerSign!==d.CustomerSign&&a(b).find('[name="CustomerSign"]').length>0||e.getCheckout().CheckoutOrderInfoText!==d.OrderInfoText&&a(b).find('[name="OrderInfoText"]').length>0?(e.getCheckout().CheckoutCustomerSign=d.CustomerSign,e.getCheckout().CheckoutOrderInfoText=d.OrderInfoText,e.setCheckout()):c.idle()}function i(d){var f=a('[data-plenty-checkout-form="shippingAddress"]');if(!d&&!f.validateForm())return!1;if(!d&&!b.getInstance().AddressDoctorService.validateAddress(f))return!1;var g=f.getFormValues(),h=a('[name="shippingAddressID"]:checked').val();if(a("#shippingAdressSelect").modal("hide"),0>h){var i=g;return k(i,e.getCheckout().CustomerShippingAddress)?c.idle():("PACKSTATION"==i.Street?(i.isPackstation=1,i.PackstationNo=i.HouseNo):"POSTFILIALE"==i.Street&&(i.IsPostfiliale=1,i.PostfilialNo=i.HouseNo),c.post("/rest/checkout/customershippingaddress/",i).done(function(a){e.getCheckout().CheckoutCustomerShippingAddressID=a.data.ID,e.getCheckout().CheckoutShippingCountryID=a.data.CountryID,delete e.getCheckout().CheckoutMethodOfPaymentID,delete e.getCheckout().CheckoutShippingProfileID,e.setCheckout().done(function(){e.reloadContainer("MethodsOfPaymentList"),e.reloadContainer("ShippingProfilesList"),2==e.getCheckout().CustomerInvoiceAddress.LoginType&&e.reloadContainer("CustomerShippingAddress")})}))}return h!=e.getCheckout().CheckoutCustomerShippingAddressID?(e.getCheckout().CheckoutCustomerShippingAddressID=h,delete e.getCheckout().CheckoutMethodOfPaymentID,delete e.getCheckout().CheckoutShippingProfileID,e.setCheckout().done(function(){e.reloadContainer("MethodsOfPaymentList"),e.reloadContainer("ShippingProfilesList"),2==e.getCheckout().CustomerInvoiceAddress.LoginType&&e.reloadContainer("CustomerShippingAddress")})):c.idle()}function j(){var b=a('[data-plenty-checkout-form="guestRegistration"]'),d=b.getFormValues();return d.LoginType=1,d.CustomerPropertiesList=d.CustomerPropertiesList||[],b.find("[data-plenty-property-id]").each(function(b,c){d.CustomerPropertiesList.push({PropertyID:a(c).attr("data-plenty-property-id"),PropertyValue:a(c).val()})}),k(d,e.getCheckout().CustomerInvoiceAddress)?i():c.post("/rest/checkout/customerinvoiceaddress/",d).done(function(a){i().done(function(){e.loadCheckout()})})}function k(a,b){for(var c in a)if(a[c]+""!=b[c]+""&&"EmailRepeat"!==c)return!1;return!0}function l(){var b=a('[data-plenty-checkout-form="shippingProfileSelect"]').getFormValues();return e.getCheckout().CheckoutShippingProfileID=b.ShippingProfileID,delete e.getCheckout().CheckoutCustomerShippingAddressID,delete e.getCheckout().CheckoutMethodOfPaymentID,e.setCheckout().done(function(){e.reloadContainer("MethodsOfPaymentList")})}function m(){return c.post("/rest/checkout/preparepayment/",null).done(function(b){if(""!=b.data.CheckoutMethodOfPaymentRedirectURL)document.location.assign(b.data.CheckoutMethodOfPaymentRedirectURL);else if(b.data.CheckoutMethodOfPaymentAdditionalContent){var c=a(b.data.CheckoutMethodOfPaymentAdditionalContent).find('[data-plenty-checkout-form="bankDetails"]').length>0;f.prepare().setContent(b.data.CheckoutMethodOfPaymentAdditionalContent).onConfirm(function(){return c?p():r()}).show()}})}function n(b){return b=b||a('[data-plenty-checkout-form="methodOfPayment"]').getFormValues().MethodOfPaymentID,e.getCheckout().CheckoutMethodOfPaymentID=b,delete e.getCheckout().CheckoutCustomerShippingAddressID,delete e.getCheckout().CheckoutShippingProfileID,e.setCheckout().done(function(){e.reloadContainer("ShippingProfilesList")})}function o(){d.getContainer("CheckoutPaymentInformationBankDetails").from("Checkout").done(function(b){f.prepare().setContent(b.data[0]).onDismiss(function(){a('input[name="MethodOfPaymentID"]').each(function(b,c){a(c).val()==e.getCheckout().CheckoutMethodOfPaymentID?a(c).attr("checked","checked"):a(c).removeAttr("checked")})}).onConfirm(function(){return p()}).show()})}function p(){var b=a('[data-plenty-checkout-form="bankDetails"]');if(b.validateForm()){var d=b.getFormValues().checkout.customerBankDetails,f={CustomerBankName:d.bankName,CustomerBLZ:d.blz,CustomerAccountNumber:d.accountNo,CustomerAccountOwner:d.accountOwner,CustomerIBAN:d.iban,CustomerBIC:d.bic};return c.post("/rest/checkout/paymentinformationbankdetails/",f).done(function(){e.loadCheckout().done(function(){n(3),e.reloadContainer("MethodsOfPaymentList")})}),!0}return!1}function q(){d.getContainer("CheckoutPaymentInformationCreditCard").from("Checkout").done(function(b){f.prepare().setContent(b.data[0]).onDismiss(function(){a('input[name="MethodOfPaymentID"]').each(function(b,c){a(c).val()==e.getCheckout().CheckoutMethodOfPaymentID?a(c).attr("checked","checked"):a(c).removeAttr("checked")})}).onConfirm(function(){return r()}).show()})}function r(){var b=a('[data-plenty-checkout-form="creditCard"]');if(b.validateForm()){var d=b.getFormValues().checkout.paymentInformationCC,f={Owner:d.owner,Cvv2:d.cvv2,Number:d.number,Year:d.year,Month:d.month,Provider:d.provider};return c.post("/rest/checkout/paymentinformationcreditcard/",f).done(function(){e.loadCheckout()}),!0}return!1}function s(b){if(2==e.getCheckout().CustomerInvoiceAddress.LoginType)var c=a('[data-plenty-checkout-form="shippingAddress"]').getFormValues();else var c=a('[data-plenty-checkout-form="guestRegistration"]').getFormValues();var g={street:c.Street,houseNo:c.HouseNo,ZIP:c.ZIP,city:c.City,postnummer:c.Postnummer,suggestionType:"postfinder"};d.getContainer("CheckoutAddressSuggestionResultsList",g).from("Checkout").done(function(a){f.prepare().setContent(a.data[0]).show()})}function t(){var b=a('[data-plenty-checkout-form="placeOrder"]');if(b.validateForm()){var d=b.getFormValues(),e={TermsAndConditionsCheck:d.termsAndConditionsCheck||0,WithdrawalCheck:d.withdrawalCheck||0,PrivacyPolicyCheck:d.privacyPolicyCheck||0,AgeRestrictionCheck:d.ageRestrictionCheck||0,NewsletterCheck:d.newsletterCheck||0,KlarnaTermsAndConditionsCheck:d.klarnaTermsAndConditionsCheck||0,PayoneDirectDebitMandateCheck:d.payoneDirectDebitMandateCheck||0,PayoneInvoiceCheck:d.payoneInvoiceCheck||0};return c.post("/rest/checkout/placeorder/",e).done(function(a){""!=a.data.MethodOfPaymentRedirectURL?window.location.assign(a.data.MethodOfPaymentRedirectURL):""!=a.data.MethodOfPaymentAdditionalContent?f.prepare().setContent(a.data.MethodOfPaymentAdditionalContent).setLabelDismiss("").onDismiss(function(){window.location.assign(b.attr("action"))}).onConfirm(function(){window.location.assign(b.attr("action"))}).show():window.location.assign(b.attr("action"))})}}return{init:g,setCustomerSignAndInfo:h,registerGuest:j,setShippingProfile:l,saveShippingAddress:i,loadAddressSuggestion:s,preparePayment:m,setMethodOfPayment:n,editBankDetails:o,editCreditCard:q,placeOrder:t}},["APIFactory","CMSFactory","CheckoutFactory","ModalFactory"])}(jQuery,PlentyFramework),function(a,b){b.service("MediaSizeService",function(){function b(){return e&&c(),e}function c(){var b;if(b=window.matchMedia?window.matchMedia("(min-width:1200px)").matches?"lg":window.matchMedia("(min-width:992px)").matches?"md":window.matchMedia("(min-width:768px)").matches?"sm":"xs":a(window).width()>=1200?"lg":a(window).width()>=992?"md":a(window).width()>=768?"sm":"xs",b!=e){var c=e;e=b,a(window).trigger("sizeChange",[e,c])}}function d(a){for(var b=a.replace(/\s/g,"").split(","),c=0;c li'),r=a('[data-plenty-checkout="container"] > div'),u=a('[data-plenty-checkout="next"]'),t=a('[data-plenty-checkout="prev"]'),q.length==r.length&&r.length>0){d.getCheckout();r.hide(),q.each(function(b,c){a(c).addClass("disabled"),a(c).click(function(){a(this).is(".disabled")||j(b)})}),u.attr("disabled","disabled"),u.click(function(){m()}),t.attr("disabled","disabled"),t.click(function(){n()}),window.addEventListener("hashchange",function(){window.location.hash.length>0?o(window.location.hash):j(0)},!1),a.urlParam=function(a){var b=new RegExp("[?&]"+a+"=([^]*)").exec(window.location.href);return null==b?null:b[1]||0};var c=a.urlParam("gototab");0==window.location.hash.length&&c&&a('[data-plenty-checkout-id="'+c+'"]').length>0?window.location.hash=c:j(!o(window.location.hash)&&s>=0?s:0),p(),a(window).on("sizeChange",p),a(window).resize(function(){"xs"==b.getInstance().MediaSizeService.interval()&&p()})}}function f(){return s>=0?{id:a(r[s]).attr("data-plenty-checkout-id"),index:s}:null}function g(a){return v.beforeChange.push(a),b.getInstance().NavigatorService}function h(a){return v.afterChange.push(a),b.getInstance().NavigatorService}function i(b,c){var d=!0;if(s>=0||"afterChange"===b){var e=f(),g={index:c,id:a(r[c]).attr("data-plenty-checkout-id")};a.each(v[b],function(a,b){return b(e,g)===!1?(d=!1,!1):void 0})}return d}function j(e,f){var g=s!==e;(!g||f||i("beforeChange",e))&&(s=e,!Object.equals(w[s],d.getCheckout(!0))&&g&&a(r[s]).attr("data-plenty-checkout-content")?(w[s]=d.getCheckout(!0),c.getCategoryContent(a(r[s]).attr("data-plenty-checkout-content")).done(function(c){a(r[s]).html(c.data[0]),k(g),b.getInstance().bindDirectives(r[s]),a(window).trigger("contentChanged")})):k(g))}function k(b){a(r).hide(),a(q).each(function(b,c){a(c).removeClass("disabled active"),a(c).find('[role="tab"]').attr("aria-selected","false"),s>b?a(c).addClass("visited"):b==s?(a(c).addClass("active visited"),a(c).find('[role="tab"]').attr("aria-selected","true")):b>s&&!a(c).is(".visited")&&a(c).addClass("disabled")}),p(),0>=s?a(t).attr("disabled","disabled"):a(t).removeAttr("disabled"),s+1==q.length?a(u).attr("disabled","disabled"):a(u).removeAttr("disabled"),a(r[s]).show(),s>0?window.location.hash=a(r[s]).attr("data-plenty-checkout-id"):window.location.hash.length>0&&(window.location.hash=""),b&&i("afterChange",s)}function l(a){j(a.index,!0)}function m(){s0&&j(s-1)}function o(b){return"next"==b?(m(),!0):"prev"==b?(n(),!0):(b=b.replace("#",""),a(r).each(function(c,d){return a(d).attr("data-plenty-checkout-id")==b?(j(c),!0):void 0}),!1)}function p(){var b=q.length;if(!(0>=b)){a(q).removeAttr("style"),a(q).children("span").removeAttr("style"),a(u).removeAttr("style"),a(t).removeAttr("style");var c=a(t).outerWidth()c?a(d).children("span").css({paddingLeft:g+"px",paddingRight:h+"px"}):a(d).children("span").css({paddingLeft:j+"px",paddingRight:k+"px"})})}}var q=[],r=[],s=-1,t={},u={},v={beforeChange:[],afterChange:[]},w=[];return{init:e,getCurrentContainer:f,goTo:j,beforeChange:g,afterChange:h,continueChange:l,next:m,previous:n,goToID:o,fillNavigation:p}},["CMSFactory","CheckoutFactory"])}(jQuery,PlentyFramework),function(a,b){b.service("PostfinderService",function(c,d,e){function f(){var b=a('input[name="Street"]').val();return"PACKSTATION"==b.toUpperCase()||"POSTFILIALE"==b.toUpperCase()}function g(){j={PostfinderItemStreet:a('input[name="Street"]','[data-plenty-checkout-form="shippingAddress"]'),PostfinderItemZIP:a('input[name="ZIP"]','[data-plenty-checkout-form="shippingAddress"]'),PostfinderItemCity:a('input[name="City"]','[data-plenty-checkout-form="shippingAddress"]'),PostfinderItemHouseNo:a('input[name="HouseNo"]','[data-plenty-checkout-form="shippingAddress"]')},j.PostfinderItemStreet.val(""),j.PostfinderItemZIP.val().length>2||j.PostfinderItemCity.val().length>2?c.get("/rest/checkout/shippingaddresspostfinderlist/",{suggestionType:"postfinder",zip:j.PostfinderItemZIP.val(),city:j.PostfinderItemCity.val()}).done(function(c){l=c.data,k=l.length,0==k&&h();for(var e={addresses:[]},f=0;k>f;f++){var g="km",m=l[f].PostfinderItemDistance,n=m/1e3;n=(Math.round(100*n)/100).toFixed(2).replace(".",","),1e3>m&&(n=m,g="m"),e.addresses.push({index:f,dimension:g,type:l[f].PostfinderItemIsPackstation?"Packstation":"Postfiliale",number:l[f].PostfinderItemIsPackstation?l[f].PostfinderItemPackstationNo:l[f].PostfinderItemPostfilialNo,street:l[f].PostfinderItemStreet,houseNo:l[f].PostfinderItemHouseNo,zip:l[f].PostfinderItemZIP,city:l[f].PostfinderItemCity,district:l[f].PostfinderItemDistrict,distance:n,remark:l[f].PostfinderItemRemark})}var o=b.compileTemplate("addressSuggestions/postFinder.html",e);d.prepare().setTitle(b.translate("Packstations and post offices in your area")).setContent(o).setClass("checkout").onConfirm(function(){return j.PostfinderItemCity.removeClass("has-error").addClass("has-success"),a('label[for="'+j.PostfinderItemCity.attr("id")+'"]').removeClass("has-error").addClass("has-success"),j.PostfinderItemZIP.removeClass("has-error").addClass("has-success"),a('label[for="'+j.PostfinderItemZIP.attr("id")+'"]').removeClass("has-error").addClass("has-success"),j.PostfinderItemStreet.removeClass("has-error").addClass("has-success"),a('label[for="'+j.PostfinderItemStreet.attr("id")+'"]').removeClass("has-error").addClass("has-success"),j.PostfinderItemHouseNo.removeClass("has-error").addClass("has-success"),a('label[for="'+j.PostfinderItemHouseNo.attr("id")+'"]').removeClass("has-error").addClass("has-success"),i=a('input[type="radio"][name="postfinder"]:checked').val(),l[i].PostfinderItemIsPackstation?(a(j.PostfinderItemStreet).val("PACKSTATION"),a(j.PostfinderItemHouseNo).val(l[i].PostfinderItemPackstationNo)):(a(j.PostfinderItemStreet).val("POSTFILIALE"),a(j.PostfinderItemHouseNo).val(l[i].PostfinderItemPostfilialNo)),a(j.PostfinderItemStreet).trigger("change"),a(j.PostfinderItemCity).val(l[i].PostfinderItemCity),a(j.PostfinderItemZIP).val(l[i].PostfinderItemZIP),!0}).show()}):h()}function h(){e.throwError(0,b.translate("Please enter a ZIP code and/or a city.")),j.PostfinderItemCity.removeClass("has-success").addClass("has-error"),a('label[for="'+j.PostfinderItemCity.attr("id")+'"]').removeClass("has-success").addClass("has-error"),j.PostfinderItemZIP.removeClass("has-success").addClass("has-error"),a('label[for="'+j.PostfinderItemZIP.attr("id")+'"]').removeClass("has-success").addClass("has-error"),j.PostfinderItemCity.focus(function(){a(this).removeClass("has-error");var b=a(this).attr("id");a(this).closest(".form-group").find('[for="'+b+'"]').removeClass("has-error")}),j.PostfinderItemZIP.focus(function(){a(this).removeClass("has-error");var b=a(this).attr("id");a(this).closest(".form-group").find('[for="'+b+'"]').removeClass("has-error")})}var i="",j={},k={},l={};return{openPostfinderModal:g,isPackstation:f}},["APIFactory","ModalFactory","UIFactory"])}(jQuery,PlentyFramework),function(a,b){b.service("SocialShareService",function(){function b(a){var b={"facebook-like":'',"facebook-recommend":'',twitter:'',"google-plus":''};return b[a]}function c(){var b=document.location.href,c=a("link[rel=canonical]").attr("href");return c&&c.length>0&&(c.indexOf("http")<0&&(c=document.location.protocol+"//"+document.location.host+c),b=c),b}function d(b){var c=a('meta[name="'+b+'"]').attr("content");return c||""}function e(){var b=d("DC.title"),c=d("DC.creator");return b.length>0&&c.length>0?b+=" - "+c:b=a("title").text(),encodeURIComponent(b)}return"undefined"==typeof socialLangLocale&&(socialLangLocale="en_US"),"undefined"==typeof socialLang&&(socialLang="en"),{getSocialService:b}})}(jQuery,PlentyFramework),function($,pm){pm.service("ValidationService",function(){function getFormControl(a){return a=$(a),a.is("input")||a.is("select")||a.is("textarea")?a:a.find("input").length>0?a.find("input"):a.find("select").length>0?a.find("select"):a.find("textarea").length>0?a.find("textarea"):null}function validateText(a){return a.is("input")||a.is("select")||a.is("textarea")?$.trim(a.val()).length>0:(console.error("Validation Error: Cannot validate Text for <"+a.prop("tagName")+">"),!1)}function validateMail(a){var b=/[a-z0-9!#$%&'*+\/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+\/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?/;return validateText(a)?b.test($.trim(a.val())):!1}function validateNumber(a){return validateText(a)?$.isNumeric($.trim(a.val())):!1}function validateValue(a,b){return $(b).length>0?$.trim(a.val())==$.trim($(b).val()):$.trim(a.val())==b}function visibility(a){return a.is(":visible")}function isEnabled(a){return a.is(":enabled")}function validate(form,errorClass){var formControl,formControls,validationKey,currentHasError,group,checked,checkedMin,checkedMax,attrValidate,validationKeys,formControlAttrType,$form=$(form);errorClass=errorClass||"has-error";var missingFields=[],hasError=!1;$form.find("[data-plenty-validate], input.Required").each(function(i,elem){attrValidate=$(elem).attr("data-plenty-validate"),formControls=getFormControl(elem),validationKeys=attrValidate?attrValidate:"text",validationKeys=validationKeys.split(",");for(var i=0,length=formControls.length;length>i;i++){if(formControl=$(formControls[i]),formControlAttrType=formControl.attr("type"),!visibility(formControl)||!isEnabled(formControl))return;if(validationKey=validationKeys[i].trim()||validationKeys[0].trim(),currentHasError=!1,formControl.is("input")&&"radio"!=formControlAttrType&&"checkbox"!=formControlAttrType||formControl.is("textarea"))switch(validationKey){case"text":currentHasError=!validateText(formControl);break;case"mail":currentHasError=!validateMail(formControl);break;case"number":currentHasError=!validateNumber(formControl);break;case"value":currentHasError=!validateValue(formControl,$(elem).attr("data-plenty-validation-value"));break;case"none":break;default:console.error('Form validation error: unknown validate property: "'+attrValidate+'"')}else if(!formControl.is("input")||"radio"!=formControlAttrType&&"checkbox"!=formControlAttrType){if(!formControl.is("select"))return void console.error("Form validation error: "+$(elem).prop("tagName")+" does not contain an form element");currentHasError=""==formControl.val()||"-1"==formControl.val()}else group=formControl.attr("name"),checked=$form.find('input[name="'+group+'"]:checked').length,"radio"==formControlAttrType?(checkedMin=1,checkedMax=1):(eval("var minMax = "+attrValidate),checkedMin=minMax?minMax.min:1,checkedMax=minMax?minMax.max:1),currentHasError=checkedMin>checked||checked>checkedMax;currentHasError&&(hasError=!0,missingFields.push(formControl),formControls.length>1?(formControl.addClass(errorClass),$form.find('label[for="'+formControl.attr("id")+'"]').addClass(errorClass)):$(elem).addClass(errorClass))}}),$form.on("validationFailed",function(){var a=50,b=$form.find("."+errorClass).first(),c=b.offset().top,d=$("html, body");$form.parents(".modal").length>0?(d=$form.parents(".modal").find(".modal-body"),c=d.scrollTop()-(d.offset().top-b.offset().top)):$form.is(".modal")&&(d=$form.find(".modal-body"),c=d.scrollTop()-(d.offset().top-b.offset().top)),(c-awindow.pageYOffset+window.innerHeight)&&d.animate({scrollTop:c-a})}),hasError&&($form.find("."+errorClass).each(function(a,b){formControl=$(getFormControl(b)),formControl.on("focus click",function(){var a=$(b);a.removeClass(errorClass),$form.find('label[for="'+$(this).attr("id")+'"]').removeClass(errorClass)})}),$form.trigger("validationFailed",[missingFields]));var callback=$form.attr("data-plenty-callback");if(!hasError&&callback&&"submit"!=callback&&"function"==typeof window[callback]){var fields={};return $form.find("input, textarea, select").each(function(){"checkbox"==$(this).attr("type")?fields[$(this).attr("name")]=$(this).is(":checked"):fields[$(this).attr("name")]=$(this).val()}),window[callback](fields),!1}return!hasError}return{validate:validate}}),$.fn.validateForm=function(){return pm.getInstance().ValidationService.validate(this)},$.fn.getFormValues=function(){function a(a,b){var d=a.match(/^([^\[]+)(.*)/);if(d[2]){var e,f=/\[([^\]]+)]/g,g=[];for(g[0]=d[1];null!==(e=f.exec(d[2]));)g.push(e[1]);for(var h=g.length-1;h>=0;h--){var i={};i[g[h]]=b,b=i}c=$.extend(!0,c,b)}else c[d[1]]=b}var b=this,c={};return b.find("input, select, textarea").each(function(c,d){if($(d).attr("name"))if("checkbox"==$(d).attr("type")){var e=[];$(b).find('[name="'+$(d).attr("name")+'"]:checked').each(function(a,b){e.push($(b).val())}),a($(d).attr("name"),e)}else"radio"==$(d).attr("type")?$(d).is(":checked")&&a($(d).attr("name"),$(d).val()):a($(d).attr("name"),$(d).val())}),c}}(jQuery,PlentyFramework),function(a,b){b.directive("Authentication",function(c){function d(d){b.getRecentEvent().preventDefault(),c.customerLogin(a(d))}return{login:d}},["AuthenticationService"])}(jQuery,PlentyFramework),function(a,b){b.directive("Basket",function(c){function d(d){b.getRecentEvent().preventDefault();var e={},f=a(d),g=f.parents("form");e.BasketItemItemID=g.find('[name="ArticleID"]').val(),e.BasketItemPriceID=g.find('[name="SYS_P_ID"]').val(),e.BasketItemQuantity=g.find('[name="ArticleQuantity"]').val(),e.BasketItemBranchID=g.find('[name="source_category"]').val();var h=g.find('[name^="ArticleAttribute"]'),i=[];a.each(h,function(b,c){var d=c.name.match(/^ArticleAttribute\[\d+]\[\d+]\[(\d+)]$/);d&&d[1]&&i.push({BasketItemAttributeID:d[1],BasketItemAttributeValueID:a(c).val()})}),0!=i.length&&(e.BasketItemAttributesList=i),c.addItem([e])}function e(b,c){var d=a(b),e=d.parent().find("input"),f=parseInt(e.attr("maxlength"))||5,g=parseInt(e.val())+c,h=d.parents("[data-basket-item-id]").length>0;if(h){(g+"").length<=f&&g>=0&&e.val(g);var i=d.data("timeout");i&&window.clearTimeout(i),i=window.setTimeout(function(){e.trigger("change")},1e3),d.data("timeout",i)}else(g+"").length<=f&&g>=1&&e.val(g)}function f(b,d){c.setItemQuantity(b,parseInt(a(d).val())).fail(function(){var e=c.getItem(b);a(d).val(e.BasketItemQuantity)})}return{addBasketItem:d,changeItemQuantity:e,setItemQuantity:f}},["BasketService"])}(jQuery,PlentyFramework),function(a,b){b.directive("MobileDropdown",function(c){function d(){a(window).on("orientationchange sizeChange",function(){e(h)}),a("html").click(function(a){e(i)})}function e(b){for(var c=0;c0?window.location.assign(a(c).attr("href")):window.location.assign(c))}function e(a){c.goToID(a)}return{to:d,toCheckoutTab:e}},["MediaSizeService","NavigatorService"])}(jQuery,PlentyFramework),function(a,b){b.directive("Tab",function(c){function d(b){a(b).tab("show")}function e(a,b,c){j[c]||(j[c]=new h),j[c].getTab(b)||j[c].addTab(b),j[c].getTab(b).addLabel(a)}function f(a,b,c){j[c]||(j[c]=new h),j[c].getTab(b)||j[c].addTab(b),j[c].getTab(b).setContent(a)}function g(a,d,e){c.isInterval(e)&&(b.getRecentEvent().preventDefault(),j[d]&&j[d].getTab(a)&&j[d].showTab(a))}function h(){function b(a){return g[a]=new i(a),g[a]}function c(b){var c=0;if(f)c=parseInt(f.getContent().parent().css("zIndex")),f.hide(),f.getContent().parent().css("zIndex",c-1);else{for(var d in g)if(g[d].getContent()){var h=parseInt(g[d].getContent().parent().css("zIndex"));(0==c||c>h)&&(c=h),g[d].hide()}for(var d in g)g[d].getContent()&&g[d].getContent().parent().css("zIndex",c-1);a(window).on("sizeChange",e)}f=g[b],f.getContent().parent().css("zIndex",c),f.show()}function d(a){return g[a]}function e(){for(var a in g)g[a].getContent()&&g[a].show();f=null}var f,g={};return{addTab:b,showTab:c,getTab:d,resetTabs:e}}function i(a){function b(){return j}function c(a){return i.push(a),this}function d(a){return h=a,this}function e(){return h}function f(){for(var a=0;a0&&(a(document).scrollTop()>100?t(v,"addClass","visible"):t(v,"removeClass","visible"))})}function f(b){a(b).owlCarousel({navigation:!0,navigationText:!1,slideSpeed:1e3,paginationSpeed:1e3,singleItem:!0,autoPlay:6e3,stopOnHover:!0,afterMove:function(b){a(b).find('img[data-plenty-rel="lazyload"]').trigger("appear")}})}function g(b,d,e){var f=a(b),g=0,h={},i=f.find('[data-plenty-rel="equal-target"]').length>0?f.find('[data-plenty-rel="equal-target"]'):f.children();e!==!0&&u.push(b);for(var j=i.length;j>=0;j--)h=a(i[j]),h.css("height",""),h.outerHeight(!0)>g&&(g=h.outerHeight(!0));(!d||c.isInterval(d))&&i.height(g)}function h(b){var c=a(b);c.click(function(){return a("html, body").animate({scrollTop:0},400),!1}),a.inArray(c,v)&&v.push(c)}function i(b,c){var d=a(b);d.lazyload({effect:c}),d.on("loaded",function(){d.css("display","inline-block")})}function j(b){console.log(b);var c=a(b),d=c.parent();d.addClass("animating"),c.siblings("ul").slideToggle(200,function(){d.is(".open")?d.removeClass("open"):d.addClass("open"),c.siblings("ul").removeAttr("style"),d.removeClass("animating")})}function k(b,c){var d=a(b),e=a(d.attr("data-plenty-rel"));if(d.is('input[type="radio"]')){var f=a('input[type="radio"][name="'+d.attr("name")+'"]'),g=!c||"checked"==c;f.change(function(){var b=a(this);e.parents('[data-plenty-rel="equal-target"]').css("height","auto"),b.is(":checked")&&b[0]===d[0]&&1==g?e.slideDown(400,function(){s()}):e.slideUp(400,function(){s()})})}else d.click(function(){d.addClass("animating"),e.slideToggle(400,function(){d.removeClass("animating"),d.toggleClass("active"),s()})})}function l(b,c){c=c||400,a(b).parents('[data-plenty-rel="equal-target"]').css("height","auto"),a(b).slideDown(c,function(){s()})}function m(b,c){c=c||400,a(b).parents('[data-plenty-rel="equal-target"]').css("height","auto"),a(b).slideUp(c,function(){s()})}function n(b,c){c=c||400,a(b).parents('[data-plenty-rel="equal-target"]').css("height","auto"),a(b).slideToggle(c,function(){s()})}function o(b,c){var e=a(b),f=e.find('[data-plenty-rel="social-switch"]');e.append(''),f.is("off, on")||f.addClass("off"),f.on("click",function(){f.hasClass("off")&&("tooltip"==e.attr("data-toggle")&&e.tooltip("destroy"),f.removeClass("off").addClass("on"),e.find('[data-plenty-rel="social-placeholder"]').hide(),e.find(".social-container").append(d.getSocialService(c)))})}function p(d,e,f){if(e&&d&&(!f||c.isInterval(f))){var g=b.getRecentEvent();return g&&g.preventDefault(),a(e).toggleClass(d),!1}}function q(d,e,f){if(e&&d&&(!f||c.isInterval(f))){var g=b.getRecentEvent();return g&&g.preventDefault(),a(e).addClass(d),!1}}function r(d,e,f){if(e&&d&&(!f||c.isInterval(f))){var g=b.getRecentEvent();return g&&g.preventDefault(),a(e).removeClass(d),!1}}function s(){for(var a=u.length-1;a>=0;a--)g(u[a],"",!0)}function t(a,b,c){for(var d=a.length-1;d>=0;d--)a[d][b](c)}var u=[],v=[];return{initUIWindowEvents:e,addContentPageSlider:f,equalHeight:g,initToTop:h,initLazyload:i,initSlideToggle:k,slideDown:l,slideUp:m,slideToggle:n,toggleHideShow:j,toggleSocialShare:o,toggleClass:p,addClass:q,removeClass:r}},["MediaSizeService","SocialShareService"])}(jQuery,PlentyFramework),function(a,b){b.directive("Validator",function(a){function b(b,c){return a.validate(b,c)}return{validate:b}},["ValidationService"])}(jQuery,PlentyFramework),PlentyFramework.compile();var plenty=PlentyFramework.getInstance();jQuery(document).ready(function(){plenty.bindDirectives()});
\ No newline at end of file
diff --git a/dist/plentymarketsCMStools-1.0.1.js b/dist/plentymarketsCMStools-1.0.2.js
similarity index 96%
rename from dist/plentymarketsCMStools-1.0.1.js
rename to dist/plentymarketsCMStools-1.0.2.js
index 85181f0..61783c5 100644
--- a/dist/plentymarketsCMStools-1.0.1.js
+++ b/dist/plentymarketsCMStools-1.0.2.js
@@ -271,11 +271,7 @@ TemplateCache["waitscreen/waitscreen.html"] = " ' ) + ' -> ' + dependency );
+ }
+ }
+
+ // compile component
+ if( componentLevel == 3 )
+ {
+ PlentyFramework.factories[component.name] = component.setup.apply( null, compiledDependencies );
+ }
+ else if( componentLevel == 2 )
+ {
+ PlentyFramework.prototype[component.name] = component.setup.apply( null, compiledDependencies );
+ }
+ else if( componentLevel == 1 )
+ {
+ PlentyFramework.directives[component.name] = component.setup.apply( null, compiledDependencies );
+ }
+ }
+
}( jQuery ));
@@ -3298,7 +3293,7 @@ PlentyFramework.cssClasses = {
{
if ( shippingAddress.Street == "PACKSTATION" )
{
- shippingAddress.isPackstation = 1;
+ shippingAddress.IsPackstation = 1;
shippingAddress.PackstationNo = shippingAddress.HouseNo;
}
else if ( shippingAddress.Street == "POSTFILIALE" )
@@ -3763,6 +3758,133 @@ PlentyFramework.cssClasses = {
* =====================================================================================
*/
+/**
+ * @module Services
+ */
+(function($, pm) {
+
+ pm.service('FeedbackService', function( API ) {
+
+ return {
+ getFeedbacks: getFeedbacks,
+ addFeedback: addFeedback,
+ ArticleTypes: articleTypes(),
+ FeedbackTypes: feedbackTypes()
+ };
+
+ /*
+ FeedbackService
+ .getFeedbacks().between('2014-12-03', '2015-07-01')
+ .for( FeedbackService.ArticleTypes.ITEM, 2732, FeedbackService.FeedbackTypes.COMMENTS_ONLY );
+ */
+ function getFeedbacks() {
+ var feedbackInterval = {
+ dateStart: null,
+ dateEnd: null
+ };
+
+ return {
+ between: setFeedbackInterval,
+ for: listFeedbacks
+ };
+
+ function setFeedbackInterval( start, end ) {
+ feedbackInterval.dateStart = start;
+ feedbackInterval.dateEnd = end;
+ return this;
+ }
+
+ function listFeedbacks( articleType, referenceId, feedbackType ) {
+
+ var params = {
+ ReferenceId: referenceId,
+ FromDate: feedbackInterval.dateStart,
+ ToDate: feedbackInterval.dateEnd,
+ FeedbackType: feedbackType || feedbackTypes().COMMENTS_AND_RATINGS
+ };
+ return API.get( '/rest/feedback/'+articleType+'/', params );
+
+ }
+ }
+
+ /*
+ FeedbackService
+ .addFeedback()
+ .withRating( 5 )
+ .withComment( 'Hallo' )
+ .withAuthor( 'Felix', 'felix.dausch@plentymarkets.com', 123456 )
+ .to( FeedbackService.ArticleTypes.ITEM, 2732 );
+ */
+ function addFeedback() {
+
+ var params = {
+ Rating: 1.0,
+ Text: '',
+ Author: '',
+ Email: '',
+ CustomerId: 0
+ };
+
+ return {
+ withRating: withRating,
+ withComment: withComment,
+ withAuthor: withAuthor,
+ to: sendFeedback
+ };
+
+ function withRating( rating ) {
+ params.Rating = rating;
+ return this;
+ }
+
+ function withComment( comment ) {
+ params.Text = comment;
+ return this;
+ }
+
+ function withAuthor( author, mail, customerID ) {
+ params.Author = author;
+ if( !!mail ) params.Email = mail;
+ if( !!customerID ) params.CustomerId = customerID;
+ return this;
+ }
+
+ function sendFeedback( articleType, referenceId ) {
+ return API.post( '/rest/feedback/'+articleType+'/', params );
+
+ }
+
+ }
+
+ function feedbackTypes() {
+ return {
+ COMMENTS_ONLY: 'comments_only',
+ RATINGS_ONLY: 'ratings_only',
+ COMMENTS_AND_RATINGS: 'comments_with_ratings'
+ }
+ }
+
+ function articleTypes() {
+ return {
+ ITEM: 'item',
+ CATEGORY: 'category',
+ BLOG: 'blog'
+ }
+ }
+
+
+
+ }, ['APIFactory']);
+}(jQuery, PlentyFramework));
+/**
+ * Licensed under AGPL v3
+ * (https://github.com/plentymarkets/plenty-cms-library/blob/master/LICENSE)
+ * =====================================================================================
+ * @copyright Copyright (c) 2015, plentymarkets GmbH (http://www.plentymarkets.com)
+ * @author Felix Dausch
+ * =====================================================================================
+ */
+
/**
* @module Services
*/
diff --git a/dist/plentymarketsCMStools-1.0.2.min.js b/dist/plentymarketsCMStools-1.0.2.min.js
new file mode 100644
index 0000000..52dc104
--- /dev/null
+++ b/dist/plentymarketsCMStools-1.0.2.min.js
@@ -0,0 +1,10 @@
+/**
+ * Licensed under AGPL v3
+ * (https://github.com/plentymarkets/plenty-cms-library/blob/master/LICENSE)
+ * =====================================================================================
+ * @copyright Copyright (c) 2015, plentymarkets GmbH (http://www.plentymarkets.com)
+ * @author Felix Dausch
+ * =====================================================================================
+*/!function(a,b){"object"==typeof exports&&exports&&"string"!=typeof exports.nodeName?b(exports):"function"==typeof define&&define.amd?define(["exports"],b):(a.Mustache={},b(Mustache))}(this,function(a){function b(a){return"function"==typeof a}function c(a){return p(a)?"array":typeof a}function d(a){return a.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g,"\\$&")}function e(a,b){return null!=a&&"object"==typeof a&&b in a}function f(a,b){return q.call(a,b)}function g(a){return!f(r,a)}function h(a){return String(a).replace(/[&<>"'\/]/g,function(a){return s[a]})}function i(b,c){function e(){if(r&&!s)for(;q.length;)delete o[q.pop()];else q=[];r=!1,s=!1}function f(a){if("string"==typeof a&&(a=a.split(u,2)),!p(a)||2!==a.length)throw new Error("Invalid tags: "+a);h=new RegExp(d(a[0])+"\\s*"),i=new RegExp("\\s*"+d(a[1])),m=new RegExp("\\s*"+d("}"+a[1]))}if(!b)return[];var h,i,m,n=[],o=[],q=[],r=!1,s=!1;f(c||a.tags);for(var y,z,A,B,C,D,E=new l(b);!E.eos();){if(y=E.pos,A=E.scanUntil(h))for(var F=0,G=A.length;G>F;++F)B=A.charAt(F),g(B)?q.push(o.length):s=!0,o.push(["text",B,y,y+1]),y+=1,"\n"===B&&e();if(!E.scan(h))break;if(r=!0,z=E.scan(x)||"name",E.scan(t),"="===z?(A=E.scanUntil(v),E.scan(v),E.scanUntil(i)):"{"===z?(A=E.scanUntil(m),E.scan(w),E.scanUntil(i),z="&"):A=E.scanUntil(i),!E.scan(i))throw new Error("Unclosed tag at "+E.pos);if(C=[z,A,y,E.pos],o.push(C),"#"===z||"^"===z)n.push(C);else if("/"===z){if(D=n.pop(),!D)throw new Error('Unopened section "'+A+'" at '+y);if(D[1]!==A)throw new Error('Unclosed section "'+D[1]+'" at '+y)}else"name"===z||"{"===z||"&"===z?s=!0:"="===z&&f(A)}if(D=n.pop())throw new Error('Unclosed section "'+D[1]+'" at '+E.pos);return k(j(o))}function j(a){for(var b,c,d=[],e=0,f=a.length;f>e;++e)b=a[e],b&&("text"===b[0]&&c&&"text"===c[0]?(c[1]+=b[1],c[3]=b[3]):(d.push(b),c=b));return d}function k(a){for(var b,c,d=[],e=d,f=[],g=0,h=a.length;h>g;++g)switch(b=a[g],b[0]){case"#":case"^":e.push(b),f.push(b),e=b[4]=[];break;case"/":c=f.pop(),c[5]=b[2],e=f.length>0?f[f.length-1][4]:d;break;default:e.push(b)}return d}function l(a){this.string=a,this.tail=a,this.pos=0}function m(a,b){this.view=a,this.cache={".":this.view},this.parent=b}function n(){this.cache={}}var o=Object.prototype.toString,p=Array.isArray||function(a){return"[object Array]"===o.call(a)},q=RegExp.prototype.test,r=/\S/,s={"&":"&","<":"<",">":">",'"':""","'":"'","/":"/"},t=/\s*/,u=/\s+/,v=/\s*=/,w=/\s*\}/,x=/#|\^|\/|>|\{|&|=|!/;l.prototype.eos=function(){return""===this.tail},l.prototype.scan=function(a){var b=this.tail.match(a);if(!b||0!==b.index)return"";var c=b[0];return this.tail=this.tail.substring(c.length),this.pos+=c.length,c},l.prototype.scanUntil=function(a){var b,c=this.tail.search(a);switch(c){case-1:b=this.tail,this.tail="";break;case 0:b="";break;default:b=this.tail.substring(0,c),this.tail=this.tail.substring(c)}return this.pos+=b.length,b},m.prototype.push=function(a){return new m(a,this)},m.prototype.lookup=function(a){var c,d=this.cache;if(d.hasOwnProperty(a))c=d[a];else{for(var f,g,h=this,i=!1;h;){if(a.indexOf(".")>0)for(c=h.view,f=a.split("."),g=0;null!=c&&gi;++i)g=void 0,e=a[i],f=e[0],"#"===f?g=this.renderSection(e,b,c,d):"^"===f?g=this.renderInverted(e,b,c,d):">"===f?g=this.renderPartial(e,b,c,d):"&"===f?g=this.unescapedValue(e,b):"name"===f?g=this.escapedValue(e,b):"text"===f&&(g=this.rawValue(e)),void 0!==g&&(h+=g);return h},n.prototype.renderSection=function(a,c,d,e){function f(a){return g.render(a,c,d)}var g=this,h="",i=c.lookup(a[1]);if(i){if(p(i))for(var j=0,k=i.length;k>j;++j)h+=this.renderTokens(a[4],c.push(i[j]),d,e);else if("object"==typeof i||"string"==typeof i||"number"==typeof i)h+=this.renderTokens(a[4],c.push(i),d,e);else if(b(i)){if("string"!=typeof e)throw new Error("Cannot use higher-order sections without the original template");i=i.call(c.view,e.slice(a[3],a[5]),f),null!=i&&(h+=i)}else h+=this.renderTokens(a[4],c,d,e);return h}},n.prototype.renderInverted=function(a,b,c,d){var e=b.lookup(a[1]);return!e||p(e)&&0===e.length?this.renderTokens(a[4],b,c,d):void 0},n.prototype.renderPartial=function(a,c,d){if(d){var e=b(d)?d(a[1]):d[a[1]];return null!=e?this.renderTokens(this.parse(e),c,d,e):void 0}},n.prototype.unescapedValue=function(a,b){var c=b.lookup(a[1]);return null!=c?c:void 0},n.prototype.escapedValue=function(b,c){var d=c.lookup(b[1]);return null!=d?a.escape(d):void 0},n.prototype.rawValue=function(a){return a[1]},a.name="mustache.js",a.version="2.1.3",a.tags=["{{","}}"];var y=new n;a.clearCache=function(){return y.clearCache()},a.parse=function(a,b){return y.parse(a,b)},a.render=function(a,b,d){if("string"!=typeof a)throw new TypeError('Invalid template! Template should be a "string" but "'+c(a)+'" was given as the first argument for mustache#render(template, view, partials)');return y.render(a,b,d)},a.to_html=function(c,d,e,f){var g=a.render(c,d,e);return b(f)?void f(g):g},a.escape=h,a.Scanner=l,a.Context=m,a.Writer=n}),Object.equals=function(a,b){if(a===b)return!0;if(!(a instanceof Object&&b instanceof Object))return!1;if(a.constructor!==b.constructor)return!1;for(var c in a)if(a.hasOwnProperty(c)){if(!b.hasOwnProperty(c))return!1;if(a[c]!==b[c]){if("object"!=typeof a[c])return!1;if(!Object.equals(a[c],b[c]))return!1}}for(var c in b)if(b.hasOwnProperty(c)&&!a.hasOwnProperty(c))return!1;return!0};var TemplateCache={};TemplateCache["addressSuggestions/addressDoctor.html"]='\n {{#values}}\n - \n \n {{.}}\n \n
\n {{/values}}\n
',TemplateCache["addressSuggestions/postFinder.html"]='{{#addresses}}\n\n
\n \n
\n
\n{{/addresses}}\n',TemplateCache["error/errorMessage.html"]='\n Code {{code}}:\n {{{message}}}\n
\n',TemplateCache["error/errorPopup.html"]='\n
\n
\n
\n
\n',TemplateCache["modal/modal.html"]='\n
\n
\n\n {{#title}}\n \n {{/title}}\n\n
{{{content}}}
\n\n \n
\n
\n
\n',TemplateCache["waitscreen/waitscreen.html"]='',function(a){function b(a,b,c,d){a.on(b,function(a){return h.push(a),c.apply(null,d)})}function c(b){var c=a(b);c.is('input[type="checkbox"]')&&c.on("change",function(){c.is(":checked")?c.trigger("check"):c.trigger("uncheck")}),c.is('input[type="radio"]')&&c.on("change",function(){var b=c.attr("name");a('input[type="radio"][name="'+b+'"]').each(function(b,c){var d=a(c);d.is(":checked")?d.trigger("check"):d.trigger("uncheck")})})}function d(a,b){for(var c=/^(([\w]+):)?([\w]+)\.([\w]+)(\((.*)\))?$/,d=a.split(";"),e=[],f=0;f0)for(var j=h[6].match(/(['][^']+['])|([\w-]+)|(["][^"]+["])/g),k=0;k=c&&f.services.hasOwnProperty(i)){PlentyFramework.prototype.hasOwnProperty(i)||e(f.services[i],2,d),g.push(PlentyFramework.prototype[i]);continue}if(1>=c&&f.directives.hasOwnProperty(i)){PlentyFramework.directives.hasOwnProperty(i)||e(f.directives[i],1,d),g.push(PlentyFramework.directives[i]);continue}console.error('Cannot inject dependency "'+i+'": Object not found.')}else console.error("Cyclic dependency injection: "+d.join(" -> ")+" -> "+i)}3==c?PlentyFramework.factories[b.name]=b.setup.apply(null,g):2==c?PlentyFramework.prototype[b.name]=b.setup.apply(null,g):1==c&&(PlentyFramework.directives[b.name]=b.setup.apply(null,g))}var f={factories:{},services:{},directives:{}};PlentyFramework=function(){};var g=null;PlentyFramework.getInstance=function(){return g=g||new PlentyFramework},PlentyFramework.partials={},PlentyFramework.globals={},PlentyFramework.setGlobal=function(a,b){return PlentyFramework.globals.hasOwnProperty(a)?(console.error('Global variable "'+a+'" already exists and cannot be overridden.'),null):(PlentyFramework.globals[a]=b,PlentyFramework.globals[a])},PlentyFramework.getGlobal=function(a){return PlentyFramework.globals[a]},PlentyFramework.directives={},PlentyFramework.directive=function(a,b,c){return"string"!=typeof a?void console.error("Type mismatch: Expect first parameter to be a 'string', '"+typeof a+"' given."):"function"!=typeof b?void console.error("Type mismatch: Expect second parameter to be a 'function', '"+typeof b+"' given."):(c=c||[],void(f.directives[a]={name:a,dependencies:c,setup:b}))},PlentyFramework.prototype.bindDirectives=function(e){e=e||"html",a(e).find("[data-plenty]").each(function(e,f){var g=d(a(f).attr("data-plenty"),a(f));if(!(g.length<=0)){c(f);for(var e=0;e=0;c--)if(a==h[c].type)return h[c];return null},PlentyFramework.pushEvent=function(a){h.push(a)},PlentyFramework.service=function(a,b,c){return"string"!=typeof a?void console.error("Type mismatch: Expect first parameter to be a 'string', '"+typeof a+"' given."):"function"!=typeof b?void console.error("Type mismatch: Expect second parameter to be a 'function', '"+typeof b+"' given."):(c=c||[],void(f.services[a]={name:a,dependencies:c,setup:b}))},PlentyFramework.factories={},PlentyFramework.factory=function(a,b,c){return"string"!=typeof a?void console.error("Type mismatch: Expect first parameter to be a 'string', '"+typeof a+"' given."):"function"!=typeof b?void console.error("Type mismatch: Expect second parameter to be a 'function', '"+typeof b+"' given."):(c=c||[],void(f.factories[a]={name:a,dependencies:c,setup:b}))},PlentyFramework.compileTemplate=function(a,b){return b=b||{},b.translate=function(){return function(a,b){return b(PlentyFramework.translate(a))}},Mustache.render(TemplateCache[a],b)},PlentyFramework.scriptPath="",PlentyFramework.Strings={},PlentyFramework.loadLanguageFile=function(b){a.get(PlentyFramework.scriptPath+b).done(function(a){PlentyFramework.Strings=a})},PlentyFramework.translate=function(a,b){var c;return PlentyFramework.Strings.hasOwnProperty(a)?c=PlentyFramework.Strings[a]:(c=a,console.warn('No translation found for "'+c+'".')),b&&(c=Mustache.render(c,b)),c},PlentyFramework.compile=function(){for(var a in f.factories)PlentyFramework.factories.hasOwnProperty(a)||e(f.factories[a],3);for(var b in f.services)PlentyFramework.prototype.hasOwnProperty(b)||e(f.services[b],2);for(var c in f.directives)PlentyFramework.directives.hasOwnProperty(c)||e(f.directives[c],1);var d=document.getElementsByTagName("SCRIPT");d.length>0&&(PlentyFramework.scriptPath=d[d.length-1].src.match(/(.*)\/(.*)\.js(\?\S*)?$/)[1])}}(jQuery),PlentyFramework.cssClasses={active:"active"},function(a,b){b.partials.Error={init:function(b){a(b).find(".close").click(function(){b.hide(),b.find(".plentyErrorBoxInner").html("")})},addError:function(b,c){var d=a(c).attr("data-plenty-error-code");a(b).find('[data-plenty-error-code="'+d+'"]').length<=0&&a(b).find(".plentyErrorBoxInner").append(c)},show:function(b){a(b).show()}}}(jQuery,PlentyFramework),function(a,b){b.partials.Modal={init:function(a,b){a.on("hidden.bs.modal",function(){b.hide(),a.remove()}),b.timeout>0&&(a.on("hide.bs.modal",b.stopTimeout),a.find(".modal-content").hover(function(){b.pauseTimeout()},function(){a.is(".in")&&b.continueTimeout()}))},show:function(a){a.modal("show")},hide:function(a){a.modal("hide")},isModal:function(b){return a(b).filter(".modal").length+a(b).find(".modal").length>0},getModal:function(b){var c=a(b);return c.length>1&&(c=a(b).filter(".modal")||a(b).find(".modal")),c}}}(jQuery,PlentyFramework),function(a){a(document).on("initPartials",function(b,c){a(c).find('[data-toggle="tooltip"]').tooltip({container:"body"})})}(jQuery),function(a,b){b.partials.WaitScreen={show:function(a){a.addClass("in")},hide:function(a){a.removeClass("in")}}}(jQuery,PlentyFramework),function(a,b){b.factory("APIFactory",function(b){function c(c){try{var d=a.parseJSON(c.responseText);b.printErrors(d.error.error_stack)}catch(e){b.throwError(c.status,c.statusText)}}function d(d,e,f,g,h){return g||b.showWaitScreen(),a.ajax(d,{type:"GET",data:e,dataType:"json",async:!h,error:function(a){f||c(a)}}).always(function(){g||b.hideWaitScreen()})}function e(d,e,f,g){var h={type:"POST",dataType:"json",error:function(a){f||c(a)}};return e&&e.isFile?(h.cache=e.cache,h.processData=e.processData,h.data=e.data,h.contentType=!1):(h.data=JSON.stringify(e),h.contentType="application/json"),g||b.showWaitScreen(),a.ajax(d,h).always(function(){g||b.hideWaitScreen()})}function f(d,e,f,g){return g||b.showWaitScreen(),a.ajax(d,{type:"PUT",data:JSON.stringify(e),dataType:"json",contentType:"application/json",error:function(a){f||c(a)}}).always(function(){g||b.hideWaitScreen()})}function g(d,e,f,g){return g||b.showWaitScreen(),a.ajax(d,{type:"DELETE",data:JSON.stringify(e),dataType:"json",contentType:"application/json",error:function(a){f||c(a)}}).always(function(){g||b.hideWaitScreen()})}function h(){return a.Deferred().resolve()}return{get:d,post:e,put:f,"delete":g,idle:h}},["UIFactory"])}(jQuery,PlentyFramework),function(a){a.factory("CMSFactory",function(a){function b(b,c){function d(d){return a.get("/rest/"+d.toLowerCase()+"/container_"+b.toLowerCase()+"/",c)}return{from:d}}function c(b,c){function d(d){return a.get("/rest/"+d.toLowerCase()+"/"+b.toLowerCase()+"/",c)}return{from:d}}function d(b){return a.get("/rest/categoryview/categorycontentbody/?categoryID="+b)}return{getContainer:b,getParams:c,getCategoryContent:d}},["APIFactory"])}(PlentyFramework),function(a){a.factory("CheckoutFactory",function(b,c,d){function e(){return l}function f(a){return m&&l||g(!0),a?$.extend(!0,{},l):m}function g(a){return b.get("/rest/checkout/",null,!1,!1,a).done(function(a){a?(l=a.data,m=new e):d.throwError(0,'Could not receive checkout data [GET "/rest/checkout/" receives null value]')})}function h(){return b.put("/rest/checkout",m).done(function(a){a?(l=a.data,m=new e):d.throwError(0,'Could not receive checkout data [GET "/rest/checkout/" receives null value]')})}function i(b){return c.getContainer("checkout"+b).from("checkout").done(function(c){$('[data-plenty-checkout-template="'+b+'"]').each(function(b,d){$(d).html(c.data[0]),a.getInstance().bindDirectives(d),$(window).trigger("contentChanged")})})}function j(b){return c.getCategoryContent(b).done(function(c){$('[data-plenty-checkout-catcontent="'+b+'"]').each(function(b,d){$(d).html(c.data[0]),a.getInstance().bindDirectives(d),$(window).trigger("contentChanged")})})}function k(b){return c.getContainer("itemview"+b).from("itemview").done(function(c){$('[data-plenty-itemview-template="'+b+'"]').each(function(b,d){$(d).html(c.data[0]),a.getInstance().bindDirectives(d),$(window).trigger("contentChanged")})})}var l,m;return{getCheckout:f,setCheckout:h,loadCheckout:g,reloadContainer:i,reloadCatContent:j,reloadItemContainer:k}},["APIFactory","CMSFactory","UIFactory"])}(PlentyFramework),function(a,b){b.factory("ModalFactory",function(){function c(a){return PlentyFramework.partials.Modal.isModal(a)}function d(){return new e}function e(){function d(a){return s.title=a,this}function e(a){return s.cssClass=a,this}function f(a){return s.content=a,this}function g(a){return s.labelConfirm=a,this}function h(a){return s.labelDismiss=a,this}function i(a){return s.onConfirm=a,this}function j(a){return s.onDismiss=a,this}function k(a){return s.container=a,this}function l(a){return s.timeout=a,this}function m(){t=c(s.content)?PlentyFramework.partials.Modal.getModal(s.content):a(PlentyFramework.compileTemplate("modal/modal.html",s)),a(s.container).append(t);var b=a(s.content).filter("script");b.length>0&&b.each(function(b,c){var d=document.createElement("script");d.type="text/javascript",d.innerHTML=a(c).text(),a(s.container).append(d)}),PlentyFramework.partials.Modal.init(t,s),t.find('[data-plenty-modal="confirm"]').click(function(){var a=s.onConfirm();"undefined"==typeof a&&(a=!0),a&&n(!0)}),PlentyFramework.partials.Modal.show(t),s.timeout>0&&o()}function n(a){PlentyFramework.partials.Modal.hide(t),a||s.onDismiss()}function o(){w=s.timeout,x=(new Date).getTime(),u=window.setTimeout(function(){window.clearInterval(v),n()},s.timeout),t.find('[data-plenty-modal="timer"]').text(w/1e3),v=window.setInterval(function(){if(!y){var a=w-(new Date).getTime()+x;a=Math.round(a/1e3),t.find('[data-plenty-modal="timer"]').text(a)}},1e3)}function p(){y=!0,w-=(new Date).getTime()-x,window.clearTimeout(u)}function q(){y=!1,x=(new Date).getTime(),u=window.setTimeout(function(){n(),window.clearInterval(v)},w)}function r(){window.clearTimeout(u),window.clearInterval(v)}var s=this;s.title="",s.cssClass="",s.content="",s.labelDismiss=b.translate("Cancel"),s.labelConfirm=b.translate("Confirm"),s.onConfirm=function(){},s.onDismiss=function(){},s.container="body",s.timeout=-1,s.hide=n,s.startTimeout=o,s.stopTimeout=r,s.pauseTimeout=p,s.continueTimeout=q;var t,u,v,w,x,y=!1;return{setTitle:d,setClass:e,setContent:f,setContainer:k,setLabelConfirm:g,setLabelDismiss:h,onConfirm:i,onDismiss:j,setTimeout:l,show:m,hide:n}}return{prepare:d,isModal:c}})}(jQuery,PlentyFramework),function(a,b){b.factory("UIFactory",function(){function c(a,b){d([{code:a,message:b}])}function d(c){(!i||a("body").has(i).length<=0)&&(i=a(b.compileTemplate("error/errorPopup.html")),a("body").append(i),b.partials.Error.init(i)),a.each(c,function(c,d){b.partials.Error.addError(i,a(b.compileTemplate("error/errorMessage.html",d)))}),b.partials.Error.show(i),f(!0)}function e(){return h=h||0,(!g||a("body").has(g).length<=0)&&(g=a(b.compileTemplate("waitscreen/waitscreen.html")),a("body").append(g)),b.partials.WaitScreen.show(g),h++,h}function f(a){return h--,(0>=h||a)&&(h=0,b.partials.WaitScreen.hide(g)),h}var g,h=0,i=null;return{throwError:c,printErrors:d,showWaitScreen:e,hideWaitScreen:f}})}(jQuery,PlentyFramework),function(a,b){b.service("AddressDoctorService",function(c){function d(b){var c=!0;return b=b||"[data-plenty-address-doctor]",a(b).filter("[data-plenty-address-doctor]:visible").each(function(b,d){var f=new e(d),g=a(d).attr("data-plenty-address-doctor").replace(/\s/g,"").split(",");f.isValid(g)||(c=!1)}),c}function e(c){function d(a){return i()?!0:(j=new f(l.getFormValues()),k=a,e(),1==j.getAddresses().length)}function e(){a(".suggestion-list").remove();for(var b=!1,c=0;cc;c++){var d=a.data[c],f=e(d);f?f.HouseNo.push(d.HouseNo):(d.HouseNo=[d.HouseNo],j.push(d))}})}function e(a){for(var b=j.length,c=0;b>c;c++)if(a.Street==j[c].Street&&j.ZIP==j[c].ZIP&&a.City==j[c].City)return j[c];return null}function f(){return j}function g(b){for(var c=[],d=j.length,e=0;d>e;e++){var f=j[e];a.inArray(f[b],c)<0&&c.push(f[b])}return c}function h(a){for(var b=[],c=j.length,d=0;c>d;d++){var e=j[d];(a.Street&&a.Street==e.Street||a.ZIP&&a.ZIP==e.ZIP||a.City&&a.City==e.City)&&b.push(e)}j=b}function i(a){a=parseInt(a);for(var b=j.length,c=0;b>c;c++)for(var d=j[c],e=0;e=f[0]&&a<=f[1])return!0}return!1}var j=[];return d(),{getAddresses:f,getList:g,filter:h,houseNoAllowed:i}}return{validateAddress:d}},["APIFactory"])}(jQuery,PlentyFramework),function(a,b){b.service("AuthenticationService",function(c,d,e){function f(){var b=a('[data-plenty-checkout="lostPasswordForm"]');if(b.validateForm()){var d=b.getFormValues(),e={Email:d.Email};return c.post("/rest/checkout/lostpassword/",e).done(function(b){1==b.data.IsMailSend&&(a('[data-plenty-checkout="lostPasswordTextContainer"]').hide(),a('[data-plenty-checkout="lostPasswordSuccessMessage"]').show())})}}function g(a){if(a.validateForm()){var b=a.getFormValues(),d={Email:b.loginMail,Password:b.loginPassword};return e.showWaitScreen(),c.post("/rest/checkout/login/",d).done(function(){window.location.assign(a.attr("action"))})}}function h(a){return c.post("/rest/checkout/customerinvoiceaddress/",a).done(function(a){d.getCheckout().CustomerInvoiceAddress=a.data})}function i(){var c=a('[data-plenty-checkout-form="customerRegistration"]');if(c.validateForm()&&b.getInstance().AddressDoctorService.validateAddress()){var d=c.getFormValues(),e={LoginType:2,FormOfAddressID:d.FormOfAddressID,Company:d.Company,FirstName:d.FirstName,LastName:d.LastName,Street:d.Street,HouseNo:d.HouseNo,AddressAdditional:d.AddressAdditional,ZIP:d.ZIP,City:d.City,CountryID:d.CountryID,VATNumber:d.VATNumber,Email:d.Email,EmailRepeat:d.EmailRepeat,BirthDay:d.BirthDay,BirthMonth:d.BirthMonth,BirthYear:d.BirthYear,Password:d.Password,PasswordRepeat:d.PasswordRepeat,PhoneNumber:d.PhoneNumber,MobileNumber:d.MobileNumber,FaxNumber:d.FaxNumber,Postnummer:d.Postnummer};return e.CustomerPropertiesList=e.CustomerPropertiesList||[],c.find("[data-plenty-property-id]").each(function(b,c){e.CustomerPropertiesList.push({PropertyID:a(c).attr("data-plenty-property-id"),PropertyValue:a(c).val()})}),h(e).done(function(){window.location.assign(c.attr("action"))})}}return{resetPassword:f,customerLogin:g,setInvoiceAddress:h,registerCustomer:i}},["APIFactory","CheckoutFactory","UIFactory"])}(jQuery,PlentyFramework),function(a,b){b.service("BasketService",function(c,d,e,f,g){function h(d){d&&c.get("/rest/checkout/container_"+"CheckoutOrderParamsList".toLowerCase()+"/",{itemID:d[0].BasketItemItemID,quantity:d[0].BasketItemQuantity},!1,!0).done(function(c){c.data[0].indexOf("form-group")>0?g.prepare().setContent(c.data[0]).setTitle(b.translate("Select order parameters")).setLabelConfirm(b.translate("Save")).onConfirm(function(){return a('[data-plenty-checkout-form="OrderParamsForm"]').validateForm()?(j(i(d)),!0):!1}).show():j(d)})}function i(b){var c,d=a('[data-plenty-checkout-form="OrderParamsForm"]'),e={},f="";return d.find('[name^="ParamGroup"]').each(function(){c=this.name.match(/^ParamGroup\[(\d+)]\[(\d+)]$/),b=m(b,c[1],a(this).val(),a(this).val())}),d.find('[name^="ParamValue"]').each(function(){if(e=a(this),f=e.attr("type"),("checkbox"==f&&e.is(":checked")||"radio"==f&&e.is(":checked")||"radio"!=f&&"checkbox"!=f)&&"file"!=f&&"hidden"!=f){var c=e[0].name.match(/^ParamValue\[(\d+)]\[(\d+)]$/);b=m(b,c[1],c[2],e.val())}else if("file"==f)if(e[0].files&&e[0].files.length>0)b=l(e,b);else{var c=e[0].name.match(/^ParamValueFile\[(\d+)]\[(\d+)]$/),d=a('input[type="hidden"][name="ParamValue['+c[1]+"]["+c[2]+']"]').val();b=m(b,c[1],c[2],d)}}),b}function j(a){c.post("/rest/checkout/basketitemslist/",a,!0).done(function(){f.loadCheckout().done(function(){s(),e.getContainer("ItemViewItemToBasketConfirmationOverlay",{ArticleID:a[0].BasketItemItemID}).from("ItemView").done(function(a){g.prepare().setContent(a.data[0]).setTimeout(5e3).show()})})}).fail(function(a){d.printErrors(JSON.parse(a.responseText).error.error_stack)})}function k(a){c.put("/rest/checkout/basketitemslist/",a).done(function(){f.reloadCatContent(b.getGlobal("basketCatID")),f.loadCheckout().done(function(){s()})})}function l(a,b){var d,e,f=a[0].id,g={},h=[],i={type:"POST",data:{},isFile:!0,cache:!1,dataType:"json",processData:!1,contentType:!1};g[f]=a[0].files,-1==h.indexOf(f)&&h.push(f);for(var j=0,k=h.length;k>j;++j)d=new FormData,e=g[h[j]],d.append("0",e[0],e[0].name),i.data=d,c.post("/rest/checkout/orderparamfile/",i);var l=a[0].name.match(/^ParamValueFile\[(\d+)]\[(\d+)]$/);return m(b,l[1],l[2],a.val())}function m(b,c,d,e){return c>0&&void 0==b[c]&&(b[c]=a.extend(!0,{},b[0]),b[c].BasketItemOrderParamsList=[]),void 0!=b[c]&&(b[c].BasketItemQuantity=1,void 0==b[c].BasketItemOrderParamsList&&(b[c].BasketItemOrderParamsList=[]),e&&b[c].BasketItemOrderParamsList.push({BasketItemOrderParamID:d,BasketItemOrderParamValue:e})),b}function n(b){var c=a('[data-plenty-basket-item="'+b+'"');c.modal("show"),c.find('[data-plenty-modal="confirm"]').on("click",function(){var d=p(b),e=[];c.find('select, .PlentyFormContainer.AttrImage > input[type="hidden"]').each(function(b,c){var d=c.name.match(/^ArticleAttribute\[\d+]\[\d+]\[(\d+)]$/);d&&d[1]&&e.push({BasketItemAttributeID:d[1],BasketItemAttributeValueID:a(c).val()})}),0!=e.length&&(d.BasketItemAttributesList=e),k([d])})}function o(d){var e=p(d);e.BasketItemOrderParamsList=[],c.get("/rest/checkout/container_"+"CheckoutOrderParamsList".toLowerCase()+"/",{itemID:e.BasketItemItemID,quantity:e.BasketItemQuantity,basketItemID:d}).done(function(c){g.prepare().setContent(c.data[0]).setTitle(b.translate("Edit order parameters")).setLabelConfirm(b.translate("Save")).onConfirm(function(){return a('[data-plenty-checkout-form="OrderParamsForm"]').validateForm()?(k(i([e])),!0):!1}).show()})}function p(a){for(var b=f.getCheckout().BasketItemsList,c=0;c"+b.translate('Do you really want to remove "{{item}}" from your basket?',{item:j})+"").onDismiss(function(){i.reject()}).onConfirm(function(){h()}).setLabelConfirm(b.translate("Delete")).show(),i}function r(d,e){if(0>=e)return q(d);for(var g,h,i=a.Deferred(),j=f.getCheckout().BasketItemsList,k=0;k0&&f.reloadContainer("Totals")}return{addItem:h,removeItem:q,getItem:p,setItemQuantity:r,editItemAttributes:n,editOrderParams:o,addCoupon:t,removeCoupon:u}},["APIFactory","UIFactory","CMSFactory","CheckoutFactory","ModalFactory"])}(jQuery,PlentyFramework),function(a,b){b.service("CheckoutService",function(c,d,e,f){function g(){e.loadCheckout(!0)}function h(){var b=a('[data-plenty-checkout-form="details"]'),d=b.getFormValues();return e.getCheckout().CheckoutCustomerSign||(e.getCheckout().CheckoutCustomerSign=""),e.getCheckout().CheckoutOrderInfoText||(e.getCheckout().CheckoutOrderInfoText=""),e.getCheckout().CheckoutCustomerSign!==d.CustomerSign&&a(b).find('[name="CustomerSign"]').length>0||e.getCheckout().CheckoutOrderInfoText!==d.OrderInfoText&&a(b).find('[name="OrderInfoText"]').length>0?(e.getCheckout().CheckoutCustomerSign=d.CustomerSign,e.getCheckout().CheckoutOrderInfoText=d.OrderInfoText,e.setCheckout()):c.idle()}function i(d){var f=a('[data-plenty-checkout-form="shippingAddress"]');if(!d&&!f.validateForm())return!1;if(!d&&!b.getInstance().AddressDoctorService.validateAddress(f))return!1;var g=f.getFormValues(),h=a('[name="shippingAddressID"]:checked').val();if(a("#shippingAdressSelect").modal("hide"),0>h){var i=g;return k(i,e.getCheckout().CustomerShippingAddress)?c.idle():("PACKSTATION"==i.Street?(i.IsPackstation=1,i.PackstationNo=i.HouseNo):"POSTFILIALE"==i.Street&&(i.IsPostfiliale=1,i.PostfilialNo=i.HouseNo),c.post("/rest/checkout/customershippingaddress/",i).done(function(a){e.getCheckout().CheckoutCustomerShippingAddressID=a.data.ID,e.getCheckout().CheckoutShippingCountryID=a.data.CountryID,delete e.getCheckout().CheckoutMethodOfPaymentID,delete e.getCheckout().CheckoutShippingProfileID,e.setCheckout().done(function(){e.reloadContainer("MethodsOfPaymentList"),e.reloadContainer("ShippingProfilesList"),2==e.getCheckout().CustomerInvoiceAddress.LoginType&&e.reloadContainer("CustomerShippingAddress")})}))}return h!=e.getCheckout().CheckoutCustomerShippingAddressID?(e.getCheckout().CheckoutCustomerShippingAddressID=h,delete e.getCheckout().CheckoutMethodOfPaymentID,delete e.getCheckout().CheckoutShippingProfileID,e.setCheckout().done(function(){e.reloadContainer("MethodsOfPaymentList"),e.reloadContainer("ShippingProfilesList"),2==e.getCheckout().CustomerInvoiceAddress.LoginType&&e.reloadContainer("CustomerShippingAddress")})):c.idle()}function j(){var b=a('[data-plenty-checkout-form="guestRegistration"]'),d=b.getFormValues();return d.LoginType=1,d.CustomerPropertiesList=d.CustomerPropertiesList||[],b.find("[data-plenty-property-id]").each(function(b,c){d.CustomerPropertiesList.push({PropertyID:a(c).attr("data-plenty-property-id"),PropertyValue:a(c).val()})}),k(d,e.getCheckout().CustomerInvoiceAddress)?i():c.post("/rest/checkout/customerinvoiceaddress/",d).done(function(a){i().done(function(){e.loadCheckout()})})}function k(a,b){for(var c in a)if(a[c]+""!=b[c]+""&&"EmailRepeat"!==c)return!1;return!0}function l(){var b=a('[data-plenty-checkout-form="shippingProfileSelect"]').getFormValues();return e.getCheckout().CheckoutShippingProfileID=b.ShippingProfileID,delete e.getCheckout().CheckoutCustomerShippingAddressID,delete e.getCheckout().CheckoutMethodOfPaymentID,e.setCheckout().done(function(){e.reloadContainer("MethodsOfPaymentList")})}function m(){return c.post("/rest/checkout/preparepayment/",null).done(function(b){if(""!=b.data.CheckoutMethodOfPaymentRedirectURL)document.location.assign(b.data.CheckoutMethodOfPaymentRedirectURL);else if(b.data.CheckoutMethodOfPaymentAdditionalContent){var c=a(b.data.CheckoutMethodOfPaymentAdditionalContent).find('[data-plenty-checkout-form="bankDetails"]').length>0;f.prepare().setContent(b.data.CheckoutMethodOfPaymentAdditionalContent).onConfirm(function(){return c?p():r()}).show()}})}function n(b){return b=b||a('[data-plenty-checkout-form="methodOfPayment"]').getFormValues().MethodOfPaymentID,e.getCheckout().CheckoutMethodOfPaymentID=b,delete e.getCheckout().CheckoutCustomerShippingAddressID,delete e.getCheckout().CheckoutShippingProfileID,e.setCheckout().done(function(){e.reloadContainer("ShippingProfilesList")})}function o(){d.getContainer("CheckoutPaymentInformationBankDetails").from("Checkout").done(function(b){f.prepare().setContent(b.data[0]).onDismiss(function(){a('input[name="MethodOfPaymentID"]').each(function(b,c){a(c).val()==e.getCheckout().CheckoutMethodOfPaymentID?a(c).attr("checked","checked"):a(c).removeAttr("checked")})}).onConfirm(function(){return p()}).show()})}function p(){var b=a('[data-plenty-checkout-form="bankDetails"]');if(b.validateForm()){var d=b.getFormValues().checkout.customerBankDetails,f={CustomerBankName:d.bankName,CustomerBLZ:d.blz,CustomerAccountNumber:d.accountNo,CustomerAccountOwner:d.accountOwner,CustomerIBAN:d.iban,CustomerBIC:d.bic};return c.post("/rest/checkout/paymentinformationbankdetails/",f).done(function(){e.loadCheckout().done(function(){n(3),e.reloadContainer("MethodsOfPaymentList")})}),!0}return!1}function q(){d.getContainer("CheckoutPaymentInformationCreditCard").from("Checkout").done(function(b){f.prepare().setContent(b.data[0]).onDismiss(function(){a('input[name="MethodOfPaymentID"]').each(function(b,c){a(c).val()==e.getCheckout().CheckoutMethodOfPaymentID?a(c).attr("checked","checked"):a(c).removeAttr("checked")})}).onConfirm(function(){return r()}).show()})}function r(){var b=a('[data-plenty-checkout-form="creditCard"]');if(b.validateForm()){var d=b.getFormValues().checkout.paymentInformationCC,f={Owner:d.owner,Cvv2:d.cvv2,Number:d.number,Year:d.year,Month:d.month,Provider:d.provider};return c.post("/rest/checkout/paymentinformationcreditcard/",f).done(function(){e.loadCheckout()}),!0}return!1}function s(b){if(2==e.getCheckout().CustomerInvoiceAddress.LoginType)var c=a('[data-plenty-checkout-form="shippingAddress"]').getFormValues();else var c=a('[data-plenty-checkout-form="guestRegistration"]').getFormValues();var g={street:c.Street,houseNo:c.HouseNo,ZIP:c.ZIP,city:c.City,postnummer:c.Postnummer,suggestionType:"postfinder"};d.getContainer("CheckoutAddressSuggestionResultsList",g).from("Checkout").done(function(a){f.prepare().setContent(a.data[0]).show()})}function t(){var b=a('[data-plenty-checkout-form="placeOrder"]');if(b.validateForm()){var d=b.getFormValues(),e={TermsAndConditionsCheck:d.termsAndConditionsCheck||0,WithdrawalCheck:d.withdrawalCheck||0,PrivacyPolicyCheck:d.privacyPolicyCheck||0,AgeRestrictionCheck:d.ageRestrictionCheck||0,NewsletterCheck:d.newsletterCheck||0,KlarnaTermsAndConditionsCheck:d.klarnaTermsAndConditionsCheck||0,PayoneDirectDebitMandateCheck:d.payoneDirectDebitMandateCheck||0,PayoneInvoiceCheck:d.payoneInvoiceCheck||0};return c.post("/rest/checkout/placeorder/",e).done(function(a){""!=a.data.MethodOfPaymentRedirectURL?window.location.assign(a.data.MethodOfPaymentRedirectURL):""!=a.data.MethodOfPaymentAdditionalContent?f.prepare().setContent(a.data.MethodOfPaymentAdditionalContent).setLabelDismiss("").onDismiss(function(){window.location.assign(b.attr("action"))}).onConfirm(function(){window.location.assign(b.attr("action"))}).show():window.location.assign(b.attr("action"))})}}return{init:g,setCustomerSignAndInfo:h,registerGuest:j,setShippingProfile:l,saveShippingAddress:i,loadAddressSuggestion:s,preparePayment:m,setMethodOfPayment:n,editBankDetails:o,editCreditCard:q,placeOrder:t}},["APIFactory","CMSFactory","CheckoutFactory","ModalFactory"])}(jQuery,PlentyFramework),function(a,b){b.service("FeedbackService",function(a){function b(){function b(a,b){return e.dateStart=a,e.dateEnd=b,this}function c(b,c,f){var g={ReferenceId:c,FromDate:e.dateStart,ToDate:e.dateEnd,FeedbackType:f||d().COMMENTS_AND_RATINGS};return a.get("/rest/feedback/"+b+"/",g)}var e={dateStart:null,dateEnd:null};return{between:b,"for":c}}function c(){function b(a){return f.Rating=a,this}function c(a){return f.Text=a,this}function d(a,b,c){return f.Author=a,b&&(f.Email=b),c&&(f.CustomerId=c),this}function e(b,c){return a.post("/rest/feedback/"+b+"/",f)}var f={Rating:1,Text:"",Author:"",Email:"",CustomerId:0};return{withRating:b,withComment:c,withAuthor:d,to:e}}function d(){return{COMMENTS_ONLY:"comments_only",RATINGS_ONLY:"ratings_only",COMMENTS_AND_RATINGS:"comments_with_ratings"}}function e(){return{ITEM:"item",CATEGORY:"category",BLOG:"blog"}}return{getFeedbacks:b,addFeedback:c,ArticleTypes:e(),FeedbackTypes:d()}},["APIFactory"])}(jQuery,PlentyFramework),function(a,b){b.service("MediaSizeService",function(){function b(){return e&&c(),e}function c(){var b;if(b=window.matchMedia?window.matchMedia("(min-width:1200px)").matches?"lg":window.matchMedia("(min-width:992px)").matches?"md":window.matchMedia("(min-width:768px)").matches?"sm":"xs":a(window).width()>=1200?"lg":a(window).width()>=992?"md":a(window).width()>=768?"sm":"xs",b!=e){var c=e;e=b,a(window).trigger("sizeChange",[e,c])}}function d(a){for(var b=a.replace(/\s/g,"").split(","),c=0;c li'),r=a('[data-plenty-checkout="container"] > div'),u=a('[data-plenty-checkout="next"]'),t=a('[data-plenty-checkout="prev"]'),q.length==r.length&&r.length>0){d.getCheckout();r.hide(),q.each(function(b,c){a(c).addClass("disabled"),a(c).click(function(){a(this).is(".disabled")||j(b)})}),u.attr("disabled","disabled"),u.click(function(){m()}),t.attr("disabled","disabled"),t.click(function(){n()}),window.addEventListener("hashchange",function(){window.location.hash.length>0?o(window.location.hash):j(0)},!1),a.urlParam=function(a){var b=new RegExp("[?&]"+a+"=([^]*)").exec(window.location.href);return null==b?null:b[1]||0};var c=a.urlParam("gototab");0==window.location.hash.length&&c&&a('[data-plenty-checkout-id="'+c+'"]').length>0?window.location.hash=c:j(!o(window.location.hash)&&s>=0?s:0),p(),a(window).on("sizeChange",p),a(window).resize(function(){"xs"==b.getInstance().MediaSizeService.interval()&&p()})}}function f(){return s>=0?{id:a(r[s]).attr("data-plenty-checkout-id"),index:s}:null}function g(a){return v.beforeChange.push(a),b.getInstance().NavigatorService}function h(a){return v.afterChange.push(a),b.getInstance().NavigatorService}function i(b,c){var d=!0;if(s>=0||"afterChange"===b){var e=f(),g={index:c,id:a(r[c]).attr("data-plenty-checkout-id")};a.each(v[b],function(a,b){return b(e,g)===!1?(d=!1,!1):void 0})}return d}function j(e,f){var g=s!==e;(!g||f||i("beforeChange",e))&&(s=e,!Object.equals(w[s],d.getCheckout(!0))&&g&&a(r[s]).attr("data-plenty-checkout-content")?(w[s]=d.getCheckout(!0),c.getCategoryContent(a(r[s]).attr("data-plenty-checkout-content")).done(function(c){a(r[s]).html(c.data[0]),k(g),b.getInstance().bindDirectives(r[s]),a(window).trigger("contentChanged")})):k(g))}function k(b){a(r).hide(),a(q).each(function(b,c){a(c).removeClass("disabled active"),a(c).find('[role="tab"]').attr("aria-selected","false"),s>b?a(c).addClass("visited"):b==s?(a(c).addClass("active visited"),a(c).find('[role="tab"]').attr("aria-selected","true")):b>s&&!a(c).is(".visited")&&a(c).addClass("disabled")}),p(),0>=s?a(t).attr("disabled","disabled"):a(t).removeAttr("disabled"),s+1==q.length?a(u).attr("disabled","disabled"):a(u).removeAttr("disabled"),a(r[s]).show(),s>0?window.location.hash=a(r[s]).attr("data-plenty-checkout-id"):window.location.hash.length>0&&(window.location.hash=""),b&&i("afterChange",s)}function l(a){j(a.index,!0)}function m(){s0&&j(s-1)}function o(b){return"next"==b?(m(),!0):"prev"==b?(n(),!0):(b=b.replace("#",""),a(r).each(function(c,d){return a(d).attr("data-plenty-checkout-id")==b?(j(c),!0):void 0}),!1)}function p(){var b=q.length;if(!(0>=b)){a(q).removeAttr("style"),a(q).children("span").removeAttr("style"),a(u).removeAttr("style"),a(t).removeAttr("style");var c=a(t).outerWidth()c?a(d).children("span").css({paddingLeft:g+"px",paddingRight:h+"px"}):a(d).children("span").css({paddingLeft:j+"px",paddingRight:k+"px"})})}}var q=[],r=[],s=-1,t={},u={},v={beforeChange:[],afterChange:[]},w=[];return{init:e,getCurrentContainer:f,goTo:j,beforeChange:g,afterChange:h,continueChange:l,next:m,previous:n,goToID:o,fillNavigation:p}},["CMSFactory","CheckoutFactory"])}(jQuery,PlentyFramework),function(a,b){b.service("PostfinderService",function(c,d,e){function f(){var b=a('input[name="Street"]').val();return"PACKSTATION"==b.toUpperCase()||"POSTFILIALE"==b.toUpperCase()}function g(){j={PostfinderItemStreet:a('input[name="Street"]','[data-plenty-checkout-form="shippingAddress"]'),PostfinderItemZIP:a('input[name="ZIP"]','[data-plenty-checkout-form="shippingAddress"]'),PostfinderItemCity:a('input[name="City"]','[data-plenty-checkout-form="shippingAddress"]'),PostfinderItemHouseNo:a('input[name="HouseNo"]','[data-plenty-checkout-form="shippingAddress"]')},j.PostfinderItemStreet.val(""),j.PostfinderItemZIP.val().length>2||j.PostfinderItemCity.val().length>2?c.get("/rest/checkout/shippingaddresspostfinderlist/",{suggestionType:"postfinder",zip:j.PostfinderItemZIP.val(),city:j.PostfinderItemCity.val()}).done(function(c){l=c.data,k=l.length,0==k&&h();for(var e={addresses:[]},f=0;k>f;f++){var g="km",m=l[f].PostfinderItemDistance,n=m/1e3;n=(Math.round(100*n)/100).toFixed(2).replace(".",","),1e3>m&&(n=m,g="m"),e.addresses.push({index:f,dimension:g,type:l[f].PostfinderItemIsPackstation?"Packstation":"Postfiliale",number:l[f].PostfinderItemIsPackstation?l[f].PostfinderItemPackstationNo:l[f].PostfinderItemPostfilialNo,street:l[f].PostfinderItemStreet,houseNo:l[f].PostfinderItemHouseNo,zip:l[f].PostfinderItemZIP,city:l[f].PostfinderItemCity,district:l[f].PostfinderItemDistrict,distance:n,remark:l[f].PostfinderItemRemark})}var o=b.compileTemplate("addressSuggestions/postFinder.html",e);d.prepare().setTitle(b.translate("Packstations and post offices in your area")).setContent(o).setClass("checkout").onConfirm(function(){return j.PostfinderItemCity.removeClass("has-error").addClass("has-success"),a('label[for="'+j.PostfinderItemCity.attr("id")+'"]').removeClass("has-error").addClass("has-success"),j.PostfinderItemZIP.removeClass("has-error").addClass("has-success"),a('label[for="'+j.PostfinderItemZIP.attr("id")+'"]').removeClass("has-error").addClass("has-success"),j.PostfinderItemStreet.removeClass("has-error").addClass("has-success"),a('label[for="'+j.PostfinderItemStreet.attr("id")+'"]').removeClass("has-error").addClass("has-success"),j.PostfinderItemHouseNo.removeClass("has-error").addClass("has-success"),a('label[for="'+j.PostfinderItemHouseNo.attr("id")+'"]').removeClass("has-error").addClass("has-success"),i=a('input[type="radio"][name="postfinder"]:checked').val(),l[i].PostfinderItemIsPackstation?(a(j.PostfinderItemStreet).val("PACKSTATION"),a(j.PostfinderItemHouseNo).val(l[i].PostfinderItemPackstationNo)):(a(j.PostfinderItemStreet).val("POSTFILIALE"),a(j.PostfinderItemHouseNo).val(l[i].PostfinderItemPostfilialNo)),a(j.PostfinderItemStreet).trigger("change"),a(j.PostfinderItemCity).val(l[i].PostfinderItemCity),a(j.PostfinderItemZIP).val(l[i].PostfinderItemZIP),!0}).show()}):h()}function h(){e.throwError(0,b.translate("Please enter a ZIP code and/or a city.")),j.PostfinderItemCity.removeClass("has-success").addClass("has-error"),a('label[for="'+j.PostfinderItemCity.attr("id")+'"]').removeClass("has-success").addClass("has-error"),j.PostfinderItemZIP.removeClass("has-success").addClass("has-error"),a('label[for="'+j.PostfinderItemZIP.attr("id")+'"]').removeClass("has-success").addClass("has-error"),j.PostfinderItemCity.focus(function(){a(this).removeClass("has-error");var b=a(this).attr("id");a(this).closest(".form-group").find('[for="'+b+'"]').removeClass("has-error")}),j.PostfinderItemZIP.focus(function(){a(this).removeClass("has-error");var b=a(this).attr("id");a(this).closest(".form-group").find('[for="'+b+'"]').removeClass("has-error")})}var i="",j={},k={},l={};return{openPostfinderModal:g,isPackstation:f}},["APIFactory","ModalFactory","UIFactory"])}(jQuery,PlentyFramework),function(a,b){b.service("SocialShareService",function(){function b(a){var b={"facebook-like":'',"facebook-recommend":'',twitter:'',"google-plus":''};return b[a]}function c(){var b=document.location.href,c=a("link[rel=canonical]").attr("href");return c&&c.length>0&&(c.indexOf("http")<0&&(c=document.location.protocol+"//"+document.location.host+c),b=c),b}function d(b){var c=a('meta[name="'+b+'"]').attr("content");return c||""}function e(){var b=d("DC.title"),c=d("DC.creator");return b.length>0&&c.length>0?b+=" - "+c:b=a("title").text(),encodeURIComponent(b)}return"undefined"==typeof socialLangLocale&&(socialLangLocale="en_US"),"undefined"==typeof socialLang&&(socialLang="en"),{getSocialService:b}})}(jQuery,PlentyFramework),function($,pm){pm.service("ValidationService",function(){function getFormControl(a){return a=$(a),a.is("input")||a.is("select")||a.is("textarea")?a:a.find("input").length>0?a.find("input"):a.find("select").length>0?a.find("select"):a.find("textarea").length>0?a.find("textarea"):null}function validateText(a){return a.is("input")||a.is("select")||a.is("textarea")?$.trim(a.val()).length>0:(console.error("Validation Error: Cannot validate Text for <"+a.prop("tagName")+">"),!1)}function validateMail(a){var b=/[a-z0-9!#$%&'*+\/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+\/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?/;return validateText(a)?b.test($.trim(a.val())):!1}function validateNumber(a){return validateText(a)?$.isNumeric($.trim(a.val())):!1}function validateValue(a,b){return $(b).length>0?$.trim(a.val())==$.trim($(b).val()):$.trim(a.val())==b}function visibility(a){return a.is(":visible")}function isEnabled(a){return a.is(":enabled")}function validate(form,errorClass){var formControl,formControls,validationKey,currentHasError,group,checked,checkedMin,checkedMax,attrValidate,validationKeys,formControlAttrType,$form=$(form);errorClass=errorClass||"has-error";var missingFields=[],hasError=!1;$form.find("[data-plenty-validate], input.Required").each(function(i,elem){attrValidate=$(elem).attr("data-plenty-validate"),formControls=getFormControl(elem),validationKeys=attrValidate?attrValidate:"text",validationKeys=validationKeys.split(",");for(var i=0,length=formControls.length;length>i;i++){if(formControl=$(formControls[i]),formControlAttrType=formControl.attr("type"),!visibility(formControl)||!isEnabled(formControl))return;if(validationKey=validationKeys[i].trim()||validationKeys[0].trim(),currentHasError=!1,formControl.is("input")&&"radio"!=formControlAttrType&&"checkbox"!=formControlAttrType||formControl.is("textarea"))switch(validationKey){case"text":currentHasError=!validateText(formControl);break;case"mail":currentHasError=!validateMail(formControl);break;case"number":currentHasError=!validateNumber(formControl);break;case"value":currentHasError=!validateValue(formControl,$(elem).attr("data-plenty-validation-value"));break;case"none":break;default:console.error('Form validation error: unknown validate property: "'+attrValidate+'"')}else if(!formControl.is("input")||"radio"!=formControlAttrType&&"checkbox"!=formControlAttrType){if(!formControl.is("select"))return void console.error("Form validation error: "+$(elem).prop("tagName")+" does not contain an form element");currentHasError=""==formControl.val()||"-1"==formControl.val()}else group=formControl.attr("name"),checked=$form.find('input[name="'+group+'"]:checked').length,"radio"==formControlAttrType?(checkedMin=1,checkedMax=1):(eval("var minMax = "+attrValidate),checkedMin=minMax?minMax.min:1,checkedMax=minMax?minMax.max:1),currentHasError=checkedMin>checked||checked>checkedMax;currentHasError&&(hasError=!0,missingFields.push(formControl),formControls.length>1?(formControl.addClass(errorClass),$form.find('label[for="'+formControl.attr("id")+'"]').addClass(errorClass)):$(elem).addClass(errorClass))}}),$form.on("validationFailed",function(){var a=50,b=$form.find("."+errorClass).first(),c=b.offset().top,d=$("html, body");$form.parents(".modal").length>0?(d=$form.parents(".modal").find(".modal-body"),c=d.scrollTop()-(d.offset().top-b.offset().top)):$form.is(".modal")&&(d=$form.find(".modal-body"),c=d.scrollTop()-(d.offset().top-b.offset().top)),(c-awindow.pageYOffset+window.innerHeight)&&d.animate({scrollTop:c-a})}),hasError&&($form.find("."+errorClass).each(function(a,b){formControl=$(getFormControl(b)),formControl.on("focus click",function(){var a=$(b);a.removeClass(errorClass),$form.find('label[for="'+$(this).attr("id")+'"]').removeClass(errorClass)})}),$form.trigger("validationFailed",[missingFields]));var callback=$form.attr("data-plenty-callback");if(!hasError&&callback&&"submit"!=callback&&"function"==typeof window[callback]){var fields={};return $form.find("input, textarea, select").each(function(){"checkbox"==$(this).attr("type")?fields[$(this).attr("name")]=$(this).is(":checked"):fields[$(this).attr("name")]=$(this).val()}),window[callback](fields),!1}return!hasError}return{validate:validate}}),$.fn.validateForm=function(){return pm.getInstance().ValidationService.validate(this)},$.fn.getFormValues=function(){function a(a,b){var d=a.match(/^([^\[]+)(.*)/);if(d[2]){var e,f=/\[([^\]]+)]/g,g=[];for(g[0]=d[1];null!==(e=f.exec(d[2]));)g.push(e[1]);for(var h=g.length-1;h>=0;h--){var i={};i[g[h]]=b,b=i}c=$.extend(!0,c,b)}else c[d[1]]=b}var b=this,c={};return b.find("input, select, textarea").each(function(c,d){if($(d).attr("name"))if("checkbox"==$(d).attr("type")){var e=[];$(b).find('[name="'+$(d).attr("name")+'"]:checked').each(function(a,b){e.push($(b).val())}),a($(d).attr("name"),e)}else"radio"==$(d).attr("type")?$(d).is(":checked")&&a($(d).attr("name"),$(d).val()):a($(d).attr("name"),$(d).val())}),c}}(jQuery,PlentyFramework),function(a,b){b.directive("Authentication",function(c){function d(d){b.getRecentEvent().preventDefault(),c.customerLogin(a(d))}return{login:d}},["AuthenticationService"])}(jQuery,PlentyFramework),function(a,b){b.directive("Basket",function(c){function d(d){b.getRecentEvent().preventDefault();var e={},f=a(d),g=f.parents("form");e.BasketItemItemID=g.find('[name="ArticleID"]').val(),e.BasketItemPriceID=g.find('[name="SYS_P_ID"]').val(),e.BasketItemQuantity=g.find('[name="ArticleQuantity"]').val(),e.BasketItemBranchID=g.find('[name="source_category"]').val();var h=g.find('[name^="ArticleAttribute"]'),i=[];a.each(h,function(b,c){var d=c.name.match(/^ArticleAttribute\[\d+]\[\d+]\[(\d+)]$/);d&&d[1]&&i.push({BasketItemAttributeID:d[1],BasketItemAttributeValueID:a(c).val()})}),0!=i.length&&(e.BasketItemAttributesList=i),c.addItem([e])}function e(b,c){var d=a(b),e=d.parent().find("input"),f=parseInt(e.attr("maxlength"))||5,g=parseInt(e.val())+c,h=d.parents("[data-basket-item-id]").length>0;if(h){(g+"").length<=f&&g>=0&&e.val(g);var i=d.data("timeout");i&&window.clearTimeout(i),i=window.setTimeout(function(){e.trigger("change")},1e3),d.data("timeout",i)}else(g+"").length<=f&&g>=1&&e.val(g)}function f(b,d){c.setItemQuantity(b,parseInt(a(d).val())).fail(function(){var e=c.getItem(b);a(d).val(e.BasketItemQuantity)})}return{addBasketItem:d,changeItemQuantity:e,setItemQuantity:f}},["BasketService"])}(jQuery,PlentyFramework),function(a,b){b.directive("MobileDropdown",function(c){function d(){a(window).on("orientationchange sizeChange",function(){e(h)}),a("html").click(function(a){e(i)})}function e(b){for(var c=0;c0?window.location.assign(a(c).attr("href")):window.location.assign(c))}function e(a){c.goToID(a)}return{to:d,toCheckoutTab:e}},["MediaSizeService","NavigatorService"])}(jQuery,PlentyFramework),function(a,b){b.directive("Tab",function(c){function d(b){a(b).tab("show")}function e(a,b,c){j[c]||(j[c]=new h),j[c].getTab(b)||j[c].addTab(b),j[c].getTab(b).addLabel(a)}function f(a,b,c){j[c]||(j[c]=new h),j[c].getTab(b)||j[c].addTab(b),j[c].getTab(b).setContent(a)}function g(a,d,e){c.isInterval(e)&&(b.getRecentEvent().preventDefault(),j[d]&&j[d].getTab(a)&&j[d].showTab(a))}function h(){function b(a){return g[a]=new i(a),g[a]}function c(b){var c=0;if(f)c=parseInt(f.getContent().parent().css("zIndex")),f.hide(),f.getContent().parent().css("zIndex",c-1);else{for(var d in g)if(g[d].getContent()){var h=parseInt(g[d].getContent().parent().css("zIndex"));(0==c||c>h)&&(c=h),g[d].hide()}for(var d in g)g[d].getContent()&&g[d].getContent().parent().css("zIndex",c-1);a(window).on("sizeChange",e)}f=g[b],f.getContent().parent().css("zIndex",c),f.show()}function d(a){return g[a]}function e(){for(var a in g)g[a].getContent()&&g[a].show();f=null}var f,g={};return{addTab:b,showTab:c,getTab:d,resetTabs:e}}function i(a){function b(){return j}function c(a){return i.push(a),this}function d(a){return h=a,this}function e(){return h}function f(){for(var a=0;a0&&(a(document).scrollTop()>100?t(v,"addClass","visible"):t(v,"removeClass","visible"))})}function f(b){a(b).owlCarousel({navigation:!0,navigationText:!1,slideSpeed:1e3,paginationSpeed:1e3,singleItem:!0,autoPlay:6e3,stopOnHover:!0,afterMove:function(b){a(b).find('img[data-plenty-rel="lazyload"]').trigger("appear")}})}function g(b,d,e){var f=a(b),g=0,h={},i=f.find('[data-plenty-rel="equal-target"]').length>0?f.find('[data-plenty-rel="equal-target"]'):f.children();e!==!0&&u.push(b);for(var j=i.length;j>=0;j--)h=a(i[j]),h.css("height",""),h.outerHeight(!0)>g&&(g=h.outerHeight(!0));(!d||c.isInterval(d))&&i.height(g)}function h(b){var c=a(b);c.click(function(){return a("html, body").animate({scrollTop:0},400),!1}),a.inArray(c,v)&&v.push(c)}function i(b,c){var d=a(b);d.lazyload({effect:c}),d.on("loaded",function(){d.css("display","inline-block")})}function j(b){console.log(b);var c=a(b),d=c.parent();d.addClass("animating"),c.siblings("ul").slideToggle(200,function(){d.is(".open")?d.removeClass("open"):d.addClass("open"),c.siblings("ul").removeAttr("style"),d.removeClass("animating")})}function k(b,c){var d=a(b),e=a(d.attr("data-plenty-rel"));if(d.is('input[type="radio"]')){var f=a('input[type="radio"][name="'+d.attr("name")+'"]'),g=!c||"checked"==c;f.change(function(){var b=a(this);e.parents('[data-plenty-rel="equal-target"]').css("height","auto"),b.is(":checked")&&b[0]===d[0]&&1==g?e.slideDown(400,function(){s()}):e.slideUp(400,function(){s()})})}else d.click(function(){d.addClass("animating"),e.slideToggle(400,function(){d.removeClass("animating"),d.toggleClass("active"),s()})})}function l(b,c){c=c||400,a(b).parents('[data-plenty-rel="equal-target"]').css("height","auto"),a(b).slideDown(c,function(){s()})}function m(b,c){c=c||400,a(b).parents('[data-plenty-rel="equal-target"]').css("height","auto"),a(b).slideUp(c,function(){s()})}function n(b,c){c=c||400,a(b).parents('[data-plenty-rel="equal-target"]').css("height","auto"),a(b).slideToggle(c,function(){s()})}function o(b,c){var e=a(b),f=e.find('[data-plenty-rel="social-switch"]');e.append(''),f.is("off, on")||f.addClass("off"),f.on("click",function(){f.hasClass("off")&&("tooltip"==e.attr("data-toggle")&&e.tooltip("destroy"),f.removeClass("off").addClass("on"),e.find('[data-plenty-rel="social-placeholder"]').hide(),e.find(".social-container").append(d.getSocialService(c)))})}function p(d,e,f){if(e&&d&&(!f||c.isInterval(f))){var g=b.getRecentEvent();return g&&g.preventDefault(),a(e).toggleClass(d),!1}}function q(d,e,f){if(e&&d&&(!f||c.isInterval(f))){var g=b.getRecentEvent();return g&&g.preventDefault(),a(e).addClass(d),!1}}function r(d,e,f){if(e&&d&&(!f||c.isInterval(f))){var g=b.getRecentEvent();return g&&g.preventDefault(),a(e).removeClass(d),!1}}function s(){for(var a=u.length-1;a>=0;a--)g(u[a],"",!0)}function t(a,b,c){for(var d=a.length-1;d>=0;d--)a[d][b](c)}var u=[],v=[];return{initUIWindowEvents:e,addContentPageSlider:f,equalHeight:g,initToTop:h,initLazyload:i,initSlideToggle:k,slideDown:l,slideUp:m,slideToggle:n,toggleHideShow:j,toggleSocialShare:o,toggleClass:p,addClass:q,removeClass:r}},["MediaSizeService","SocialShareService"])}(jQuery,PlentyFramework),function(a,b){b.directive("Validator",function(a){function b(b,c){return a.validate(b,c)}return{validate:b}},["ValidationService"])}(jQuery,PlentyFramework),PlentyFramework.compile();var plenty=PlentyFramework.getInstance();
+jQuery(document).ready(function(){plenty.bindDirectives()});
\ No newline at end of file
diff --git a/package.json b/package.json
index adf88bc..a9b3085 100644
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
{
"name": "plentymarketsCMStools",
"license": "AGPL-3.0",
- "version": "1.0.1",
+ "version": "1.0.2",
"repository": "https://github.com/plentymarkets/plenty-cms-library.git",
"devDependencies": {
"grunt": "^0.4.5",
From adacce3a87ffa2b8d7cdd2e702790c692caaaa1e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Matthias=20Bro=CC=88cker?=
Date: Mon, 14 Dec 2015 15:12:47 +0100
Subject: [PATCH 13/17] Fix mobile dropdown (separate 2 different cases for
main-navigation and top-navbar)
---
src/directives/MobileDropdown.js | 108 ++++++++++++++++++++++---------
1 file changed, 77 insertions(+), 31 deletions(-)
diff --git a/src/directives/MobileDropdown.js b/src/directives/MobileDropdown.js
index dd2023c..2e66f31 100644
--- a/src/directives/MobileDropdown.js
+++ b/src/directives/MobileDropdown.js
@@ -31,68 +31,114 @@
{
$(window).on('orientationchange sizeChange', function() {
resetDropdowns( dropdownElements );
+ resetDropdowns( closableDropdownElements );
});
$( 'html' ).click( function( e ) {
- resetDropdowns( closableDropdownElements );
+ resetDropdowns( closableDropdownElements, e );
});
}
- function resetDropdowns( dropdownList )
+ function resetDropdowns( dropdownList, event )
{
for( var i = 0; i < dropdownList.length; i++ )
{
- $( dropdownList[i] ).removeClass('open');
+ if ( !! event )
+ {
+ if ( ! $( dropdownList[i] ).is( $(event.target).closest('li') ) )
+ {
+ $( dropdownList[i] ).removeClass('open');
+ }
+ }
+ else
+ {
+ $( dropdownList[i] ).removeClass('open');
+ }
}
}
- function openDropdown( elem, closable )
+ function openDropdown( elem, alwaysClickable )
{
var $elem = $( elem );
var $parent = $elem.parent();
- if( Modernizr.touch )
+ // case 1: xs || sm || ( touch && ( md || lg ) ) -> open/close via click on small devices, open/close via css-hover on desktop, open/close via click on touch-desktop (e.g. top navigation)
+
+ if ( !! alwaysClickable && ( MediaSize.isInterval('xs, sm') || ( Modernizr.touch && MediaSize.isInterval('md, lg') ) ) )
{
- if ( MediaSize.isInterval('md, lg') && !$parent.is( '.open' ) )
+ if ( ! $parent.is('.open') )
{
+ showDropdownHideOthers ( $elem, $parent );
- // avoid redirecting
- pm.getRecentEvent().preventDefault();
-
- // hide other dropdowns
- resetDropdowns( dropdownElements );
-
- // show dropdown
- $parent.addClass( 'open' );
-
- if ( $.inArray( $parent[0], dropdownElements ) < 0 )
+ // if href
+ if ( ! $elem.attr('href') )
{
- dropdownElements.push( $parent[0] );
+ avoidRedirectinStopPropagation ( $parent.not($elem) );
}
-
- if ( !!closable && $.inArray( $parent[0], closableDropdownElements ) < 0 )
+ }
+ else
+ {
+ if ( ! $elem.attr('href') )
{
- closableDropdownElements.push( $parent[0] );
+ // hide dropdown
+ $parent.removeClass( 'open' );
}
-
- // avoid closing popup by clicking itself
- $parent.off( 'click' );
- $parent.on( 'click', function( e )
- {
- e.stopPropagation();
- } );
}
+ }
+ // case 2: touch && ( md || lg ) -> open via 1st click on touch-desktop, return false (e.g. main navigation)
+
+ if ( ! alwaysClickable && ( Modernizr.touch && MediaSize.isInterval('md, lg') ) )
+ {
+ if ( ! $parent.is('.open') )
+ {
+ showDropdownHideOthers ( $elem, $parent );
+
+ avoidRedirectinStopPropagation ( $parent );
+ }
+ else
+ {
+ // redirect to href if dropdown is already open
+ // do nothing
+ }
}
- else
+
+ }
+
+ function showDropdownHideOthers ( elem, parent )
+ {
+ var $elem = $( elem );
+ var $parent = $( parent );
+
+ // hide other dropdowns
+ resetDropdowns( closableDropdownElements );
+
+ // remember opened dropdown
+ if ( $.inArray( $parent[0], closableDropdownElements ) < 0 )
{
- // redirect to href
- // do nothing
+ closableDropdownElements.push( $parent[0] );
}
+ // show dropdown
+ $parent.addClass( 'open' );
+ }
+
+ function avoidRedirectinStopPropagation ( elem )
+ {
+ var $elem = $( elem );
+
+ // avoid redirecting
+ pm.getRecentEvent().preventDefault();
+
+ // avoid closing popup by clicking itself
+ $elem.off( 'click' );
+ $elem.on( 'click', function( e )
+ {
+ e.stopPropagation();
+ } );
}
function slideDropdown( elem )
@@ -101,7 +147,7 @@
var $elemParent = $elem.parent();
$elemParent.addClass( 'animating' );
- $elem.siblings( 'ul' ).slideToggle( 200, function()
+ $elem.siblings( 'ul' ).slideToggle( 400, function()
{
if ( $elemParent.is( '.open' ) )
{
From e59bd8e5edb779e570dfaad880d2b87705c77ba2 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Matthias=20Bro=CC=88cker?=
Date: Tue, 15 Dec 2015 10:34:45 +0100
Subject: [PATCH 14/17] Fix slideDropdown() for use on document ready for
initial opening mobile navigation.
---
src/directives/MobileDropdown.js | 32 ++++++++++++++++++--------------
1 file changed, 18 insertions(+), 14 deletions(-)
diff --git a/src/directives/MobileDropdown.js b/src/directives/MobileDropdown.js
index 2e66f31..cd9011d 100644
--- a/src/directives/MobileDropdown.js
+++ b/src/directives/MobileDropdown.js
@@ -146,24 +146,28 @@
var $elem = $( elem );
var $elemParent = $elem.parent();
- $elemParent.addClass( 'animating' );
- $elem.siblings( 'ul' ).slideToggle( 400, function()
+ // size interval query is required since function is used on document ready to initial open active navigation (on small devices)
+ if ( MediaSize.isInterval('xs, sm') )
{
- if ( $elemParent.is( '.open' ) )
+ $elemParent.addClass( 'animating' );
+ $elem.siblings( 'ul' ).slideToggle( 400, function()
{
- $elemParent.removeClass( 'open' );
- }
- else
- {
- $elemParent.addClass( 'open' );
- if( $.inArray( $elemParent[0], dropdownElements) < 0 )
+ if ( $elemParent.is( '.open' ) )
{
- dropdownElements.push( $elemParent[0] );
+ $elemParent.removeClass( 'open' );
}
- }
- $elem.siblings( 'ul' ).removeAttr( 'style' );
- $elemParent.removeClass( 'animating' );
- } );
+ else
+ {
+ $elemParent.addClass( 'open' );
+ if( $.inArray( $elemParent[0], dropdownElements) < 0 )
+ {
+ dropdownElements.push( $elemParent[0] );
+ }
+ }
+ $elem.siblings( 'ul' ).removeAttr( 'style' );
+ $elemParent.removeClass( 'animating' );
+ } );
+ }
}
}, ['MediaSizeService'] );
From c71cc4eda90602c1214c69e24b02246087342358 Mon Sep 17 00:00:00 2001
From: Maximilian Lauterbach
Date: Tue, 15 Dec 2015 11:51:05 +0100
Subject: [PATCH 15/17] fix for mobile navigation.
---
dist/plentymarketsCMStools-1.0.2.js | 225 ++++++++++++++++--------
dist/plentymarketsCMStools-1.0.2.min.js | 4 +-
src/directives/MobileDropdown.js | 69 ++++----
src/directives/UI.js | 64 +++++--
4 files changed, 237 insertions(+), 125 deletions(-)
diff --git a/dist/plentymarketsCMStools-1.0.2.js b/dist/plentymarketsCMStools-1.0.2.js
index 61783c5..9f0d009 100644
--- a/dist/plentymarketsCMStools-1.0.2.js
+++ b/dist/plentymarketsCMStools-1.0.2.js
@@ -5502,101 +5502,154 @@ PlentyFramework.cssClasses = {
return {
initDropdowns: initDropdowns,
- openDropdown: openDropdown,
+ openDropdown : openDropdown,
slideDropdown: slideDropdown
};
function initDropdowns()
{
- $(window).on('orientationchange sizeChange', function() {
+ $( window ).on( 'orientationchange sizeChange', function()
+ {
resetDropdowns( dropdownElements );
- });
-
- $( 'html' ).click( function( e ) {
resetDropdowns( closableDropdownElements );
- });
+ } );
+
+ // handle "close menu on click outside"
+ $( 'html' ).on( "click touchstart", function( event )
+ {
+ resetDropdowns( closableDropdownElements, event );
+ } );
}
- function resetDropdowns( dropdownList )
+ function resetDropdowns( dropdownList, event )
{
-
- for( var i = 0; i < dropdownList.length; i++ )
+ var $current;
+ for ( var i = 0; i < dropdownList.length; i++ )
{
- $( dropdownList[i] ).removeClass('open');
+ $current = $( dropdownList[i] );
+ if ( !!event )
+ {
+ if ( $current.find( $( event.target ) ).length === 0 )
+ {
+ $current.removeClass( 'open' );
+ }
+ }
+ else
+ {
+ $current.removeClass( 'open' );
+ }
}
}
- function openDropdown( elem, closable )
+ function openDropdown( elem, alwaysClickable )
{
-
- var $elem = $( elem );
+ var $elem = $( elem );
var $parent = $elem.parent();
- if( Modernizr.touch )
+ // case 1: xs || sm || ( touch && ( md || lg ) ) -> open/close via click on small devices, open/close via
+ // css-hover on desktop, open/close via click on touch-desktop (e.g. top navigation)
+
+ if ( !!alwaysClickable && ( MediaSize.isInterval( 'xs, sm' ) || ( Modernizr.touch && MediaSize.isInterval( 'md, lg' ) ) ) )
{
- if ( MediaSize.isInterval('md, lg') && !$parent.is( '.open' ) )
+ if ( !$parent.is( '.open' ) )
{
+ showDropdownHideOthers( $elem, $parent );
- // avoid redirecting
- pm.getRecentEvent().preventDefault();
-
- // hide other dropdowns
- resetDropdowns( dropdownElements );
-
- // show dropdown
- $parent.addClass( 'open' );
-
- if ( $.inArray( $parent[0], dropdownElements ) < 0 )
+ // if href
+ if ( !$elem.attr( 'href' ) )
{
- dropdownElements.push( $parent[0] );
+ avoidRedirectinStopPropagation( $parent.not( $elem ) );
}
-
- if ( !!closable && $.inArray( $parent[0], closableDropdownElements ) < 0 )
+ }
+ else
+ {
+ if ( !$elem.attr( 'href' ) )
{
- closableDropdownElements.push( $parent[0] );
+ // hide dropdown
+ $parent.removeClass( 'open' );
}
-
- // avoid closing popup by clicking itself
- $parent.off( 'click' );
- $parent.on( 'click', function( e )
- {
- e.stopPropagation();
- } );
}
+ }
+
+ // case 2: touch && ( md || lg ) -> open via 1st click on touch-desktop, return false (e.g. main navigation)
+
+ if ( !alwaysClickable && ( Modernizr.touch && MediaSize.isInterval( 'md, lg' ) ) )
+ {
+ if ( !$parent.is( '.open' ) )
+ {
+ showDropdownHideOthers( $elem, $parent );
+ avoidRedirectinStopPropagation( $parent );
+ }
+ else
+ {
+ // redirect to href if dropdown is already open
+ // do nothing
+ }
}
- else
+ }
+
+ function showDropdownHideOthers( elem, parent )
+ {
+ var $parent = $( parent );
+
+ // hide other dropdowns
+ resetDropdowns( closableDropdownElements );
+
+ // remember opened dropdown
+ if ( $.inArray( $parent[0], closableDropdownElements ) < 0 )
{
- // redirect to href
- // do nothing
+ closableDropdownElements.push( $parent[0] );
}
+ // show dropdown
+ $parent.addClass( 'open' );
}
- function slideDropdown( elem )
+ function avoidRedirectinStopPropagation( elem )
{
var $elem = $( elem );
+
+ // avoid redirecting
+ pm.getRecentEvent().preventDefault();
+
+ // avoid closing popup by clicking itself
+ $elem.off( 'click' );
+ $elem.on( 'click', function( e )
+ {
+ e.stopPropagation();
+ } );
+ }
+
+ function slideDropdown( elem )
+ {
+ var $elem = $( elem );
var $elemParent = $elem.parent();
- $elemParent.addClass( 'animating' );
- $elem.siblings( 'ul' ).slideToggle( 200, function()
+ // size interval query is required since function is used on document ready to initial open active
+ // navigation (on small devices)
+ if ( MediaSize.isInterval( 'xs, sm' ) )
{
- if ( $elemParent.is( '.open' ) )
- {
- $elemParent.removeClass( 'open' );
- }
- else
+ $elemParent.addClass( 'animating' );
+ $elem.siblings( 'ul' ).slideToggle( 400, function()
{
- $elemParent.addClass( 'open' );
- if( $.inArray( $elemParent[0], dropdownElements) < 0 )
+ if ( $elemParent.is( '.open' ) )
{
- dropdownElements.push( $elemParent[0] );
+ $elemParent.removeClass( 'open' );
}
- }
- $elem.siblings( 'ul' ).removeAttr( 'style' );
- $elemParent.removeClass( 'animating' );
- } );
+ else
+ {
+ $elemParent.addClass( 'open' );
+ if ( $.inArray( $elemParent[0], dropdownElements ) < 0 )
+ {
+ dropdownElements.push( $elemParent[0] );
+ }
+ }
+ $elem.siblings( 'ul' ).removeAttr( 'style' );
+ $elemParent.removeClass( 'animating' );
+ } );
+ }
}
}, ['MediaSizeService'] );
@@ -6112,32 +6165,28 @@ PlentyFramework.cssClasses = {
function slideDown( target, duration )
{
- duration = duration || 400;
- $(target).parents( '[data-plenty-rel="equal-target"]' ).css( 'height', 'auto' );
- $(target).slideDown( duration, function() {
- fireEqualHeight();
- });
+ slideAction($( target ), duration, 'slideDown');
}
function slideUp( target, duration )
{
- duration = duration || 400;
- $(target).parents( '[data-plenty-rel="equal-target"]' ).css( 'height', 'auto' );
- $(target).slideUp( duration, function() {
- fireEqualHeight();
- });
+ slideAction($( target ), duration, 'slideUp');
}
function slideToggle( target, duration )
{
+ slideAction($( target ), duration, 'slideToggle');
+ }
+
+ function slideAction ($target, duration, callbackString) {
duration = duration || 400;
- $(target).parents( '[data-plenty-rel="equal-target"]' ).css( 'height', 'auto' );
- $(target).slideToggle( duration, function() {
+ $target.parents( '[data-plenty-rel="equal-target"]' ).css( 'height', 'auto' );
+ $target[callbackString]( duration, function()
+ {
fireEqualHeight();
- });
+ } );
}
-
/**
* TODO check comment
* Social Share Activation
@@ -6218,13 +6267,39 @@ PlentyFramework.cssClasses = {
*/
function toggleClass( cssClass, target, interval )
{
+ var $target = $( target );
+ /* FIXME
+ * Callisto 3.1 Design adaption:
+ * NavigationCategoriesList
+ * Line 8
+ * BEFORE:
+ *