/*! jQuery v3.4.1 | (c) JS Foundation and other contributors | jquery.org/license */ !function(e,t){"use strict";"object"==typeof module&&"object"==typeof module.exports?module.exports=e.document?t(e,!0):function(e){if(!e.document)throw new Error("jQuery requires a window with a document");return t(e)}:t(e)}("undefined"!=typeof window?window:this,function(C,e){"use strict";var t=[],E=C.document,r=Object.getPrototypeOf,s=t.slice,g=t.concat,u=t.push,i=t.indexOf,n={},o=n.toString,v=n.hasOwnProperty,a=v.toString,l=a.call(Object),y={},m=function(e){return"function"==typeof e&&"number"!=typeof e.nodeType},x=function(e){return null!=e&&e===e.window},c={type:!0,src:!0,nonce:!0,noModule:!0};function b(e,t,n){var r,i,o=(n=n||E).createElement("script");if(o.text=e,t)for(r in c)(i=t[r]||t.getAttribute&&t.getAttribute(r))&&o.setAttribute(r,i);n.head.appendChild(o).parentNode.removeChild(o)}function w(e){return null==e?e+"":"object"==typeof e||"function"==typeof e?n[o.call(e)]||"object":typeof e}var f="3.4.1",k=function(e,t){return new k.fn.init(e,t)},p=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g;function d(e){var t=!!e&&"length"in e&&e.length,n=w(e);return!m(e)&&!x(e)&&("array"===n||0===t||"number"==typeof t&&0+~]|"+M+")"+M+"*"),U=new RegExp(M+"|>"),X=new RegExp($),V=new RegExp("^"+I+"$"),G={ID:new RegExp("^#("+I+")"),CLASS:new RegExp("^\\.("+I+")"),TAG:new RegExp("^("+I+"|[*])"),ATTR:new RegExp("^"+W),PSEUDO:new RegExp("^"+$),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+M+"*(even|odd|(([+-]|)(\\d*)n|)"+M+"*(?:([+-]|)"+M+"*(\\d+)|))"+M+"*\\)|)","i"),bool:new RegExp("^(?:"+R+")$","i"),needsContext:new RegExp("^"+M+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+M+"*((?:-\\d)?\\d*)"+M+"*\\)|)(?=[^-]|$)","i")},Y=/HTML$/i,Q=/^(?:input|select|textarea|button)$/i,J=/^h\d$/i,K=/^[^{]+\{\s*\[native \w/,Z=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,ee=/[+~]/,te=new RegExp("\\\\([\\da-f]{1,6}"+M+"?|("+M+")|.)","ig"),ne=function(e,t,n){var r="0x"+t-65536;return r!=r||n?t:r<0?String.fromCharCode(r+65536):String.fromCharCode(r>>10|55296,1023&r|56320)},re=/([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g,ie=function(e,t){return t?"\0"===e?"\ufffd":e.slice(0,-1)+"\\"+e.charCodeAt(e.length-1).toString(16)+" ":"\\"+e},oe=function(){T()},ae=be(function(e){return!0===e.disabled&&"fieldset"===e.nodeName.toLowerCase()},{dir:"parentNode",next:"legend"});try{H.apply(t=O.call(m.childNodes),m.childNodes),t[m.childNodes.length].nodeType}catch(e){H={apply:t.length?function(e,t){L.apply(e,O.call(t))}:function(e,t){var n=e.length,r=0;while(e[n++]=t[r++]);e.length=n-1}}}function se(t,e,n,r){var i,o,a,s,u,l,c,f=e&&e.ownerDocument,p=e?e.nodeType:9;if(n=n||[],"string"!=typeof t||!t||1!==p&&9!==p&&11!==p)return n;if(!r&&((e?e.ownerDocument||e:m)!==C&&T(e),e=e||C,E)){if(11!==p&&(u=Z.exec(t)))if(i=u[1]){if(9===p){if(!(a=e.getElementById(i)))return n;if(a.id===i)return n.push(a),n}else if(f&&(a=f.getElementById(i))&&y(e,a)&&a.id===i)return n.push(a),n}else{if(u[2])return H.apply(n,e.getElementsByTagName(t)),n;if((i=u[3])&&d.getElementsByClassName&&e.getElementsByClassName)return H.apply(n,e.getElementsByClassName(i)),n}if(d.qsa&&!A[t+" "]&&(!v||!v.test(t))&&(1!==p||"object"!==e.nodeName.toLowerCase())){if(c=t,f=e,1===p&&U.test(t)){(s=e.getAttribute("id"))?s=s.replace(re,ie):e.setAttribute("id",s=k),o=(l=h(t)).length;while(o--)l[o]="#"+s+" "+xe(l[o]);c=l.join(","),f=ee.test(t)&&ye(e.parentNode)||e}try{return H.apply(n,f.querySelectorAll(c)),n}catch(e){A(t,!0)}finally{s===k&&e.removeAttribute("id")}}}return g(t.replace(B,"$1"),e,n,r)}function ue(){var r=[];return function e(t,n){return r.push(t+" ")>b.cacheLength&&delete e[r.shift()],e[t+" "]=n}}function le(e){return e[k]=!0,e}function ce(e){var t=C.createElement("fieldset");try{return!!e(t)}catch(e){return!1}finally{t.parentNode&&t.parentNode.removeChild(t),t=null}}function fe(e,t){var n=e.split("|"),r=n.length;while(r--)b.attrHandle[n[r]]=t}function pe(e,t){var n=t&&e,r=n&&1===e.nodeType&&1===t.nodeType&&e.sourceIndex-t.sourceIndex;if(r)return r;if(n)while(n=n.nextSibling)if(n===t)return-1;return e?1:-1}function de(t){return function(e){return"input"===e.nodeName.toLowerCase()&&e.type===t}}function he(n){return function(e){var t=e.nodeName.toLowerCase();return("input"===t||"button"===t)&&e.type===n}}function ge(t){return function(e){return"form"in e?e.parentNode&&!1===e.disabled?"label"in e?"label"in e.parentNode?e.parentNode.disabled===t:e.disabled===t:e.isDisabled===t||e.isDisabled!==!t&&ae(e)===t:e.disabled===t:"label"in e&&e.disabled===t}}function ve(a){return le(function(o){return o=+o,le(function(e,t){var n,r=a([],e.length,o),i=r.length;while(i--)e[n=r[i]]&&(e[n]=!(t[n]=e[n]))})})}function ye(e){return e&&"undefined"!=typeof e.getElementsByTagName&&e}for(e in d=se.support={},i=se.isXML=function(e){var t=e.namespaceURI,n=(e.ownerDocument||e).documentElement;return!Y.test(t||n&&n.nodeName||"HTML")},T=se.setDocument=function(e){var t,n,r=e?e.ownerDocument||e:m;return r!==C&&9===r.nodeType&&r.documentElement&&(a=(C=r).documentElement,E=!i(C),m!==C&&(n=C.defaultView)&&n.top!==n&&(n.addEventListener?n.addEventListener("unload",oe,!1):n.attachEvent&&n.attachEvent("onunload",oe)),d.attributes=ce(function(e){return e.className="i",!e.getAttribute("className")}),d.getElementsByTagName=ce(function(e){return e.appendChild(C.createComment("")),!e.getElementsByTagName("*").length}),d.getElementsByClassName=K.test(C.getElementsByClassName),d.getById=ce(function(e){return a.appendChild(e).id=k,!C.getElementsByName||!C.getElementsByName(k).length}),d.getById?(b.filter.ID=function(e){var t=e.replace(te,ne);return function(e){return e.getAttribute("id")===t}},b.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&E){var n=t.getElementById(e);return n?[n]:[]}}):(b.filter.ID=function(e){var n=e.replace(te,ne);return function(e){var t="undefined"!=typeof e.getAttributeNode&&e.getAttributeNode("id");return t&&t.value===n}},b.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&E){var n,r,i,o=t.getElementById(e);if(o){if((n=o.getAttributeNode("id"))&&n.value===e)return[o];i=t.getElementsByName(e),r=0;while(o=i[r++])if((n=o.getAttributeNode("id"))&&n.value===e)return[o]}return[]}}),b.find.TAG=d.getElementsByTagName?function(e,t){return"undefined"!=typeof t.getElementsByTagName?t.getElementsByTagName(e):d.qsa?t.querySelectorAll(e):void 0}:function(e,t){var n,r=[],i=0,o=t.getElementsByTagName(e);if("*"===e){while(n=o[i++])1===n.nodeType&&r.push(n);return r}return o},b.find.CLASS=d.getElementsByClassName&&function(e,t){if("undefined"!=typeof t.getElementsByClassName&&E)return t.getElementsByClassName(e)},s=[],v=[],(d.qsa=K.test(C.querySelectorAll))&&(ce(function(e){a.appendChild(e).innerHTML="",e.querySelectorAll("[msallowcapture^='']").length&&v.push("[*^$]="+M+"*(?:''|\"\")"),e.querySelectorAll("[selected]").length||v.push("\\["+M+"*(?:value|"+R+")"),e.querySelectorAll("[id~="+k+"-]").length||v.push("~="),e.querySelectorAll(":checked").length||v.push(":checked"),e.querySelectorAll("a#"+k+"+*").length||v.push(".#.+[+~]")}),ce(function(e){e.innerHTML="";var t=C.createElement("input");t.setAttribute("type","hidden"),e.appendChild(t).setAttribute("name","D"),e.querySelectorAll("[name=d]").length&&v.push("name"+M+"*[*^$|!~]?="),2!==e.querySelectorAll(":enabled").length&&v.push(":enabled",":disabled"),a.appendChild(e).disabled=!0,2!==e.querySelectorAll(":disabled").length&&v.push(":enabled",":disabled"),e.querySelectorAll("*,:x"),v.push(",.*:")})),(d.matchesSelector=K.test(c=a.matches||a.webkitMatchesSelector||a.mozMatchesSelector||a.oMatchesSelector||a.msMatchesSelector))&&ce(function(e){d.disconnectedMatch=c.call(e,"*"),c.call(e,"[s!='']:x"),s.push("!=",$)}),v=v.length&&new RegExp(v.join("|")),s=s.length&&new RegExp(s.join("|")),t=K.test(a.compareDocumentPosition),y=t||K.test(a.contains)?function(e,t){var n=9===e.nodeType?e.documentElement:e,r=t&&t.parentNode;return e===r||!(!r||1!==r.nodeType||!(n.contains?n.contains(r):e.compareDocumentPosition&&16&e.compareDocumentPosition(r)))}:function(e,t){if(t)while(t=t.parentNode)if(t===e)return!0;return!1},D=t?function(e,t){if(e===t)return l=!0,0;var n=!e.compareDocumentPosition-!t.compareDocumentPosition;return n||(1&(n=(e.ownerDocument||e)===(t.ownerDocument||t)?e.compareDocumentPosition(t):1)||!d.sortDetached&&t.compareDocumentPosition(e)===n?e===C||e.ownerDocument===m&&y(m,e)?-1:t===C||t.ownerDocument===m&&y(m,t)?1:u?P(u,e)-P(u,t):0:4&n?-1:1)}:function(e,t){if(e===t)return l=!0,0;var n,r=0,i=e.parentNode,o=t.parentNode,a=[e],s=[t];if(!i||!o)return e===C?-1:t===C?1:i?-1:o?1:u?P(u,e)-P(u,t):0;if(i===o)return pe(e,t);n=e;while(n=n.parentNode)a.unshift(n);n=t;while(n=n.parentNode)s.unshift(n);while(a[r]===s[r])r++;return r?pe(a[r],s[r]):a[r]===m?-1:s[r]===m?1:0}),C},se.matches=function(e,t){return se(e,null,null,t)},se.matchesSelector=function(e,t){if((e.ownerDocument||e)!==C&&T(e),d.matchesSelector&&E&&!A[t+" "]&&(!s||!s.test(t))&&(!v||!v.test(t)))try{var n=c.call(e,t);if(n||d.disconnectedMatch||e.document&&11!==e.document.nodeType)return n}catch(e){A(t,!0)}return 0":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace(te,ne),e[3]=(e[3]||e[4]||e[5]||"").replace(te,ne),"~="===e[2]&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),"nth"===e[1].slice(0,3)?(e[3]||se.error(e[0]),e[4]=+(e[4]?e[5]+(e[6]||1):2*("even"===e[3]||"odd"===e[3])),e[5]=+(e[7]+e[8]||"odd"===e[3])):e[3]&&se.error(e[0]),e},PSEUDO:function(e){var t,n=!e[6]&&e[2];return G.CHILD.test(e[0])?null:(e[3]?e[2]=e[4]||e[5]||"":n&&X.test(n)&&(t=h(n,!0))&&(t=n.indexOf(")",n.length-t)-n.length)&&(e[0]=e[0].slice(0,t),e[2]=n.slice(0,t)),e.slice(0,3))}},filter:{TAG:function(e){var t=e.replace(te,ne).toLowerCase();return"*"===e?function(){return!0}:function(e){return e.nodeName&&e.nodeName.toLowerCase()===t}},CLASS:function(e){var t=p[e+" "];return t||(t=new RegExp("(^|"+M+")"+e+"("+M+"|$)"))&&p(e,function(e){return t.test("string"==typeof e.className&&e.className||"undefined"!=typeof e.getAttribute&&e.getAttribute("class")||"")})},ATTR:function(n,r,i){return function(e){var t=se.attr(e,n);return null==t?"!="===r:!r||(t+="","="===r?t===i:"!="===r?t!==i:"^="===r?i&&0===t.indexOf(i):"*="===r?i&&-1:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i;function j(e,n,r){return m(n)?k.grep(e,function(e,t){return!!n.call(e,t,e)!==r}):n.nodeType?k.grep(e,function(e){return e===n!==r}):"string"!=typeof n?k.grep(e,function(e){return-1)[^>]*|#([\w-]+))$/;(k.fn.init=function(e,t,n){var r,i;if(!e)return this;if(n=n||q,"string"==typeof e){if(!(r="<"===e[0]&&">"===e[e.length-1]&&3<=e.length?[null,e,null]:L.exec(e))||!r[1]&&t)return!t||t.jquery?(t||n).find(e):this.constructor(t).find(e);if(r[1]){if(t=t instanceof k?t[0]:t,k.merge(this,k.parseHTML(r[1],t&&t.nodeType?t.ownerDocument||t:E,!0)),D.test(r[1])&&k.isPlainObject(t))for(r in t)m(this[r])?this[r](t[r]):this.attr(r,t[r]);return this}return(i=E.getElementById(r[2]))&&(this[0]=i,this.length=1),this}return e.nodeType?(this[0]=e,this.length=1,this):m(e)?void 0!==n.ready?n.ready(e):e(k):k.makeArray(e,this)}).prototype=k.fn,q=k(E);var H=/^(?:parents|prev(?:Until|All))/,O={children:!0,contents:!0,next:!0,prev:!0};function P(e,t){while((e=e[t])&&1!==e.nodeType);return e}k.fn.extend({has:function(e){var t=k(e,this),n=t.length;return this.filter(function(){for(var e=0;e\x20\t\r\n\f]*)/i,he=/^$|^module$|\/(?:java|ecma)script/i,ge={option:[1,""],thead:[1,"","
"],col:[2,"","
"],tr:[2,"","
"],td:[3,"","
"],_default:[0,"",""]};function ve(e,t){var n;return n="undefined"!=typeof e.getElementsByTagName?e.getElementsByTagName(t||"*"):"undefined"!=typeof e.querySelectorAll?e.querySelectorAll(t||"*"):[],void 0===t||t&&A(e,t)?k.merge([e],n):n}function ye(e,t){for(var n=0,r=e.length;nx",y.noCloneChecked=!!me.cloneNode(!0).lastChild.defaultValue;var Te=/^key/,Ce=/^(?:mouse|pointer|contextmenu|drag|drop)|click/,Ee=/^([^.]*)(?:\.(.+)|)/;function ke(){return!0}function Se(){return!1}function Ne(e,t){return e===function(){try{return E.activeElement}catch(e){}}()==("focus"===t)}function Ae(e,t,n,r,i,o){var a,s;if("object"==typeof t){for(s in"string"!=typeof n&&(r=r||n,n=void 0),t)Ae(e,s,n,r,t[s],o);return e}if(null==r&&null==i?(i=n,r=n=void 0):null==i&&("string"==typeof n?(i=r,r=void 0):(i=r,r=n,n=void 0)),!1===i)i=Se;else if(!i)return e;return 1===o&&(a=i,(i=function(e){return k().off(e),a.apply(this,arguments)}).guid=a.guid||(a.guid=k.guid++)),e.each(function(){k.event.add(this,t,i,r,n)})}function De(e,i,o){o?(Q.set(e,i,!1),k.event.add(e,i,{namespace:!1,handler:function(e){var t,n,r=Q.get(this,i);if(1&e.isTrigger&&this[i]){if(r.length)(k.event.special[i]||{}).delegateType&&e.stopPropagation();else if(r=s.call(arguments),Q.set(this,i,r),t=o(this,i),this[i](),r!==(n=Q.get(this,i))||t?Q.set(this,i,!1):n={},r!==n)return e.stopImmediatePropagation(),e.preventDefault(),n.value}else r.length&&(Q.set(this,i,{value:k.event.trigger(k.extend(r[0],k.Event.prototype),r.slice(1),this)}),e.stopImmediatePropagation())}})):void 0===Q.get(e,i)&&k.event.add(e,i,ke)}k.event={global:{},add:function(t,e,n,r,i){var o,a,s,u,l,c,f,p,d,h,g,v=Q.get(t);if(v){n.handler&&(n=(o=n).handler,i=o.selector),i&&k.find.matchesSelector(ie,i),n.guid||(n.guid=k.guid++),(u=v.events)||(u=v.events={}),(a=v.handle)||(a=v.handle=function(e){return"undefined"!=typeof k&&k.event.triggered!==e.type?k.event.dispatch.apply(t,arguments):void 0}),l=(e=(e||"").match(R)||[""]).length;while(l--)d=g=(s=Ee.exec(e[l])||[])[1],h=(s[2]||"").split(".").sort(),d&&(f=k.event.special[d]||{},d=(i?f.delegateType:f.bindType)||d,f=k.event.special[d]||{},c=k.extend({type:d,origType:g,data:r,handler:n,guid:n.guid,selector:i,needsContext:i&&k.expr.match.needsContext.test(i),namespace:h.join(".")},o),(p=u[d])||((p=u[d]=[]).delegateCount=0,f.setup&&!1!==f.setup.call(t,r,h,a)||t.addEventListener&&t.addEventListener(d,a)),f.add&&(f.add.call(t,c),c.handler.guid||(c.handler.guid=n.guid)),i?p.splice(p.delegateCount++,0,c):p.push(c),k.event.global[d]=!0)}},remove:function(e,t,n,r,i){var o,a,s,u,l,c,f,p,d,h,g,v=Q.hasData(e)&&Q.get(e);if(v&&(u=v.events)){l=(t=(t||"").match(R)||[""]).length;while(l--)if(d=g=(s=Ee.exec(t[l])||[])[1],h=(s[2]||"").split(".").sort(),d){f=k.event.special[d]||{},p=u[d=(r?f.delegateType:f.bindType)||d]||[],s=s[2]&&new RegExp("(^|\\.)"+h.join("\\.(?:.*\\.|)")+"(\\.|$)"),a=o=p.length;while(o--)c=p[o],!i&&g!==c.origType||n&&n.guid!==c.guid||s&&!s.test(c.namespace)||r&&r!==c.selector&&("**"!==r||!c.selector)||(p.splice(o,1),c.selector&&p.delegateCount--,f.remove&&f.remove.call(e,c));a&&!p.length&&(f.teardown&&!1!==f.teardown.call(e,h,v.handle)||k.removeEvent(e,d,v.handle),delete u[d])}else for(d in u)k.event.remove(e,d+t[l],n,r,!0);k.isEmptyObject(u)&&Q.remove(e,"handle events")}},dispatch:function(e){var t,n,r,i,o,a,s=k.event.fix(e),u=new Array(arguments.length),l=(Q.get(this,"events")||{})[s.type]||[],c=k.event.special[s.type]||{};for(u[0]=s,t=1;t\x20\t\r\n\f]*)[^>]*)\/>/gi,qe=/\s*$/g;function Oe(e,t){return A(e,"table")&&A(11!==t.nodeType?t:t.firstChild,"tr")&&k(e).children("tbody")[0]||e}function Pe(e){return e.type=(null!==e.getAttribute("type"))+"/"+e.type,e}function Re(e){return"true/"===(e.type||"").slice(0,5)?e.type=e.type.slice(5):e.removeAttribute("type"),e}function Me(e,t){var n,r,i,o,a,s,u,l;if(1===t.nodeType){if(Q.hasData(e)&&(o=Q.access(e),a=Q.set(t,o),l=o.events))for(i in delete a.handle,a.events={},l)for(n=0,r=l[i].length;n")},clone:function(e,t,n){var r,i,o,a,s,u,l,c=e.cloneNode(!0),f=oe(e);if(!(y.noCloneChecked||1!==e.nodeType&&11!==e.nodeType||k.isXMLDoc(e)))for(a=ve(c),r=0,i=(o=ve(e)).length;r").attr(n.scriptAttrs||{}).prop({charset:n.scriptCharset,src:n.url}).on("load error",i=function(e){r.remove(),i=null,e&&t("error"===e.type?404:200,e.type)}),E.head.appendChild(r[0])},abort:function(){i&&i()}}});var Vt,Gt=[],Yt=/(=)\?(?=&|$)|\?\?/;k.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var e=Gt.pop()||k.expando+"_"+kt++;return this[e]=!0,e}}),k.ajaxPrefilter("json jsonp",function(e,t,n){var r,i,o,a=!1!==e.jsonp&&(Yt.test(e.url)?"url":"string"==typeof e.data&&0===(e.contentType||"").indexOf("application/x-www-form-urlencoded")&&Yt.test(e.data)&&"data");if(a||"jsonp"===e.dataTypes[0])return r=e.jsonpCallback=m(e.jsonpCallback)?e.jsonpCallback():e.jsonpCallback,a?e[a]=e[a].replace(Yt,"$1"+r):!1!==e.jsonp&&(e.url+=(St.test(e.url)?"&":"?")+e.jsonp+"="+r),e.converters["script json"]=function(){return o||k.error(r+" was not called"),o[0]},e.dataTypes[0]="json",i=C[r],C[r]=function(){o=arguments},n.always(function(){void 0===i?k(C).removeProp(r):C[r]=i,e[r]&&(e.jsonpCallback=t.jsonpCallback,Gt.push(r)),o&&m(i)&&i(o[0]),o=i=void 0}),"script"}),y.createHTMLDocument=((Vt=E.implementation.createHTMLDocument("").body).innerHTML="
",2===Vt.childNodes.length),k.parseHTML=function(e,t,n){return"string"!=typeof e?[]:("boolean"==typeof t&&(n=t,t=!1),t||(y.createHTMLDocument?((r=(t=E.implementation.createHTMLDocument("")).createElement("base")).href=E.location.href,t.head.appendChild(r)):t=E),o=!n&&[],(i=D.exec(e))?[t.createElement(i[1])]:(i=we([e],t,o),o&&o.length&&k(o).remove(),k.merge([],i.childNodes)));var r,i,o},k.fn.load=function(e,t,n){var r,i,o,a=this,s=e.indexOf(" ");return-1").append(k.parseHTML(e)).find(r):e)}).always(n&&function(e,t){a.each(function(){n.apply(this,o||[e.responseText,t,e])})}),this},k.each(["ajaxStart","ajaxStop","ajaxComplete","ajaxError","ajaxSuccess","ajaxSend"],function(e,t){k.fn[t]=function(e){return this.on(t,e)}}),k.expr.pseudos.animated=function(t){return k.grep(k.timers,function(e){return t===e.elem}).length},k.offset={setOffset:function(e,t,n){var r,i,o,a,s,u,l=k.css(e,"position"),c=k(e),f={};"static"===l&&(e.style.position="relative"),s=c.offset(),o=k.css(e,"top"),u=k.css(e,"left"),("absolute"===l||"fixed"===l)&&-1<(o+u).indexOf("auto")?(a=(r=c.position()).top,i=r.left):(a=parseFloat(o)||0,i=parseFloat(u)||0),m(t)&&(t=t.call(e,n,k.extend({},s))),null!=t.top&&(f.top=t.top-s.top+a),null!=t.left&&(f.left=t.left-s.left+i),"using"in t?t.using.call(e,f):c.css(f)}},k.fn.extend({offset:function(t){if(arguments.length)return void 0===t?this:this.each(function(e){k.offset.setOffset(this,t,e)});var e,n,r=this[0];return r?r.getClientRects().length?(e=r.getBoundingClientRect(),n=r.ownerDocument.defaultView,{top:e.top+n.pageYOffset,left:e.left+n.pageXOffset}):{top:0,left:0}:void 0},position:function(){if(this[0]){var e,t,n,r=this[0],i={top:0,left:0};if("fixed"===k.css(r,"position"))t=r.getBoundingClientRect();else{t=this.offset(),n=r.ownerDocument,e=r.offsetParent||n.documentElement;while(e&&(e===n.body||e===n.documentElement)&&"static"===k.css(e,"position"))e=e.parentNode;e&&e!==r&&1===e.nodeType&&((i=k(e).offset()).top+=k.css(e,"borderTopWidth",!0),i.left+=k.css(e,"borderLeftWidth",!0))}return{top:t.top-i.top-k.css(r,"marginTop",!0),left:t.left-i.left-k.css(r,"marginLeft",!0)}}},offsetParent:function(){return this.map(function(){var e=this.offsetParent;while(e&&"static"===k.css(e,"position"))e=e.offsetParent;return e||ie})}}),k.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(t,i){var o="pageYOffset"===i;k.fn[t]=function(e){return _(this,function(e,t,n){var r;if(x(e)?r=e:9===e.nodeType&&(r=e.defaultView),void 0===n)return r?r[i]:e[t];r?r.scrollTo(o?r.pageXOffset:n,o?n:r.pageYOffset):e[t]=n},t,e,arguments.length)}}),k.each(["top","left"],function(e,n){k.cssHooks[n]=ze(y.pixelPosition,function(e,t){if(t)return t=_e(e,n),$e.test(t)?k(e).position()[n]+"px":t})}),k.each({Height:"height",Width:"width"},function(a,s){k.each({padding:"inner"+a,content:s,"":"outer"+a},function(r,o){k.fn[o]=function(e,t){var n=arguments.length&&(r||"boolean"!=typeof e),i=r||(!0===e||!0===t?"margin":"border");return _(this,function(e,t,n){var r;return x(e)?0===o.indexOf("outer")?e["inner"+a]:e.document.documentElement["client"+a]:9===e.nodeType?(r=e.documentElement,Math.max(e.body["scroll"+a],r["scroll"+a],e.body["offset"+a],r["offset"+a],r["client"+a])):void 0===n?k.css(e,t,i):k.style(e,t,n,i)},s,n?e:void 0,n)}})}),k.each("blur focus focusin focusout resize scroll click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup contextmenu".split(" "),function(e,n){k.fn[n]=function(e,t){return 0this.$items.length-1||t<0))return this.sliding?this.$element.one("slid.bs.carousel",function(){e.to(t)}):i==t?this.pause().cycle():this.slide(idocument.documentElement.clientHeight;this.$element.css({paddingLeft:!this.bodyIsOverflowing&&t?this.scrollbarWidth:"",paddingRight:this.bodyIsOverflowing&&!t?this.scrollbarWidth:""})},s.prototype.resetAdjustments=function(){this.$element.css({paddingLeft:"",paddingRight:""})},s.prototype.checkScrollbar=function(){var t=window.innerWidth;if(!t){var e=document.documentElement.getBoundingClientRect();t=e.right-Math.abs(e.left)}this.bodyIsOverflowing=document.body.clientWidth
',trigger:"hover focus",title:"",delay:0,html:!1,container:!1,viewport:{selector:"body",padding:0},sanitize:!0,sanitizeFn:null,whiteList:t},m.prototype.init=function(t,e,i){if(this.enabled=!0,this.type=t,this.$element=g(e),this.options=this.getOptions(i),this.$viewport=this.options.viewport&&g(document).find(g.isFunction(this.options.viewport)?this.options.viewport.call(this,this.$element):this.options.viewport.selector||this.options.viewport),this.inState={click:!1,hover:!1,focus:!1},this.$element[0]instanceof document.constructor&&!this.options.selector)throw new Error("`selector` option must be specified when initializing "+this.type+" on the window.document object!");for(var o=this.options.trigger.split(" "),n=o.length;n--;){var s=o[n];if("click"==s)this.$element.on("click."+this.type,this.options.selector,g.proxy(this.toggle,this));else if("manual"!=s){var a="hover"==s?"mouseenter":"focusin",r="hover"==s?"mouseleave":"focusout";this.$element.on(a+"."+this.type,this.options.selector,g.proxy(this.enter,this)),this.$element.on(r+"."+this.type,this.options.selector,g.proxy(this.leave,this))}}this.options.selector?this._options=g.extend({},this.options,{trigger:"manual",selector:""}):this.fixTitle()},m.prototype.getDefaults=function(){return m.DEFAULTS},m.prototype.getOptions=function(t){var e=this.$element.data();for(var i in e)e.hasOwnProperty(i)&&-1!==g.inArray(i,o)&&delete e[i];return(t=g.extend({},this.getDefaults(),e,t)).delay&&"number"==typeof t.delay&&(t.delay={show:t.delay,hide:t.delay}),t.sanitize&&(t.template=n(t.template,t.whiteList,t.sanitizeFn)),t},m.prototype.getDelegateOptions=function(){var i={},o=this.getDefaults();return this._options&&g.each(this._options,function(t,e){o[t]!=e&&(i[t]=e)}),i},m.prototype.enter=function(t){var e=t instanceof this.constructor?t:g(t.currentTarget).data("bs."+this.type);if(e||(e=new this.constructor(t.currentTarget,this.getDelegateOptions()),g(t.currentTarget).data("bs."+this.type,e)),t instanceof g.Event&&(e.inState["focusin"==t.type?"focus":"hover"]=!0),e.tip().hasClass("in")||"in"==e.hoverState)e.hoverState="in";else{if(clearTimeout(e.timeout),e.hoverState="in",!e.options.delay||!e.options.delay.show)return e.show();e.timeout=setTimeout(function(){"in"==e.hoverState&&e.show()},e.options.delay.show)}},m.prototype.isInStateTrue=function(){for(var t in this.inState)if(this.inState[t])return!0;return!1},m.prototype.leave=function(t){var e=t instanceof this.constructor?t:g(t.currentTarget).data("bs."+this.type);if(e||(e=new this.constructor(t.currentTarget,this.getDelegateOptions()),g(t.currentTarget).data("bs."+this.type,e)),t instanceof g.Event&&(e.inState["focusout"==t.type?"focus":"hover"]=!1),!e.isInStateTrue()){if(clearTimeout(e.timeout),e.hoverState="out",!e.options.delay||!e.options.delay.hide)return e.hide();e.timeout=setTimeout(function(){"out"==e.hoverState&&e.hide()},e.options.delay.hide)}},m.prototype.show=function(){var t=g.Event("show.bs."+this.type);if(this.hasContent()&&this.enabled){this.$element.trigger(t);var e=g.contains(this.$element[0].ownerDocument.documentElement,this.$element[0]);if(t.isDefaultPrevented()||!e)return;var i=this,o=this.tip(),n=this.getUID(this.type);this.setContent(),o.attr("id",n),this.$element.attr("aria-describedby",n),this.options.animation&&o.addClass("fade");var s="function"==typeof this.options.placement?this.options.placement.call(this,o[0],this.$element[0]):this.options.placement,a=/\s?auto?\s?/i,r=a.test(s);r&&(s=s.replace(a,"")||"top"),o.detach().css({top:0,left:0,display:"block"}).addClass(s).data("bs."+this.type,this),this.options.container?o.appendTo(g(document).find(this.options.container)):o.insertAfter(this.$element),this.$element.trigger("inserted.bs."+this.type);var l=this.getPosition(),h=o[0].offsetWidth,d=o[0].offsetHeight;if(r){var p=s,c=this.getPosition(this.$viewport);s="bottom"==s&&l.bottom+d>c.bottom?"top":"top"==s&&l.top-dc.width?"left":"left"==s&&l.left-ha.top+a.height&&(n.top=a.top+a.height-l)}else{var h=e.left-s,d=e.left+s+i;ha.right&&(n.left=a.left+a.width-d)}return n},m.prototype.getTitle=function(){var t=this.$element,e=this.options;return t.attr("data-original-title")||("function"==typeof e.title?e.title.call(t[0]):e.title)},m.prototype.getUID=function(t){for(;t+=~~(1e6*Math.random()),document.getElementById(t););return t},m.prototype.tip=function(){if(!this.$tip&&(this.$tip=g(this.options.template),1!=this.$tip.length))throw new Error(this.type+" `template` option must consist of exactly 1 top-level element!");return this.$tip},m.prototype.arrow=function(){return this.$arrow=this.$arrow||this.tip().find(".tooltip-arrow")},m.prototype.enable=function(){this.enabled=!0},m.prototype.disable=function(){this.enabled=!1},m.prototype.toggleEnabled=function(){this.enabled=!this.enabled},m.prototype.toggle=function(t){var e=this;t&&((e=g(t.currentTarget).data("bs."+this.type))||(e=new this.constructor(t.currentTarget,this.getDelegateOptions()),g(t.currentTarget).data("bs."+this.type,e))),t?(e.inState.click=!e.inState.click,e.isInStateTrue()?e.enter(e):e.leave(e)):e.tip().hasClass("in")?e.leave(e):e.enter(e)},m.prototype.destroy=function(){var t=this;clearTimeout(this.timeout),this.hide(function(){t.$element.off("."+t.type).removeData("bs."+t.type),t.$tip&&t.$tip.detach(),t.$tip=null,t.$arrow=null,t.$viewport=null,t.$element=null})},m.prototype.sanitizeHtml=function(t){return n(t,this.options.whiteList,this.options.sanitizeFn)};var e=g.fn.tooltip;g.fn.tooltip=function i(o){return this.each(function(){var t=g(this),e=t.data("bs.tooltip"),i="object"==typeof o&&o;!e&&/destroy|hide/.test(o)||(e||t.data("bs.tooltip",e=new m(this,i)),"string"==typeof o&&e[o]())})},g.fn.tooltip.Constructor=m,g.fn.tooltip.noConflict=function(){return g.fn.tooltip=e,this}}(jQuery),function(n){"use strict";var s=function(t,e){this.init("popover",t,e)};if(!n.fn.tooltip)throw new Error("Popover requires tooltip.js");s.VERSION="3.4.1",s.DEFAULTS=n.extend({},n.fn.tooltip.Constructor.DEFAULTS,{placement:"right",trigger:"click",content:"",template:''}),((s.prototype=n.extend({},n.fn.tooltip.Constructor.prototype)).constructor=s).prototype.getDefaults=function(){return s.DEFAULTS},s.prototype.setContent=function(){var t=this.tip(),e=this.getTitle(),i=this.getContent();if(this.options.html){var o=typeof i;this.options.sanitize&&(e=this.sanitizeHtml(e),"string"===o&&(i=this.sanitizeHtml(i))),t.find(".popover-title").html(e),t.find(".popover-content").children().detach().end()["string"===o?"html":"append"](i)}else t.find(".popover-title").text(e),t.find(".popover-content").children().detach().end().text(i);t.removeClass("fade top bottom left right in"),t.find(".popover-title").html()||t.find(".popover-title").hide()},s.prototype.hasContent=function(){return this.getTitle()||this.getContent()},s.prototype.getContent=function(){var t=this.$element,e=this.options;return t.attr("data-content")||("function"==typeof e.content?e.content.call(t[0]):e.content)},s.prototype.arrow=function(){return this.$arrow=this.$arrow||this.tip().find(".arrow")};var t=n.fn.popover;n.fn.popover=function e(o){return this.each(function(){var t=n(this),e=t.data("bs.popover"),i="object"==typeof o&&o;!e&&/destroy|hide/.test(o)||(e||t.data("bs.popover",e=new s(this,i)),"string"==typeof o&&e[o]())})},n.fn.popover.Constructor=s,n.fn.popover.noConflict=function(){return n.fn.popover=t,this}}(jQuery),function(s){"use strict";function n(t,e){this.$body=s(document.body),this.$scrollElement=s(t).is(document.body)?s(window):s(t),this.options=s.extend({},n.DEFAULTS,e),this.selector=(this.options.target||"")+" .nav li > a",this.offsets=[],this.targets=[],this.activeTarget=null,this.scrollHeight=0,this.$scrollElement.on("scroll.bs.scrollspy",s.proxy(this.process,this)),this.refresh(),this.process()}function e(o){return this.each(function(){var t=s(this),e=t.data("bs.scrollspy"),i="object"==typeof o&&o;e||t.data("bs.scrollspy",e=new n(this,i)),"string"==typeof o&&e[o]()})}n.VERSION="3.4.1",n.DEFAULTS={offset:10},n.prototype.getScrollHeight=function(){return this.$scrollElement[0].scrollHeight||Math.max(this.$body[0].scrollHeight,document.documentElement.scrollHeight)},n.prototype.refresh=function(){var t=this,o="offset",n=0;this.offsets=[],this.targets=[],this.scrollHeight=this.getScrollHeight(),s.isWindow(this.$scrollElement[0])||(o="position",n=this.$scrollElement.scrollTop()),this.$body.find(this.selector).map(function(){var t=s(this),e=t.data("target")||t.attr("href"),i=/^#./.test(e)&&s(e);return i&&i.length&&i.is(":visible")&&[[i[o]().top+n,e]]||null}).sort(function(t,e){return t[0]-e[0]}).each(function(){t.offsets.push(this[0]),t.targets.push(this[1])})},n.prototype.process=function(){var t,e=this.$scrollElement.scrollTop()+this.options.offset,i=this.getScrollHeight(),o=this.options.offset+i-this.$scrollElement.height(),n=this.offsets,s=this.targets,a=this.activeTarget;if(this.scrollHeight!=i&&this.refresh(),o<=e)return a!=(t=s[s.length-1])&&this.activate(t);if(a&&e=n[t]&&(n[t+1]===undefined||e .active"),n=i&&r.support.transition&&(o.length&&o.hasClass("fade")||!!e.find("> .fade").length);function s(){o.removeClass("active").find("> .dropdown-menu > .active").removeClass("active").end().find('[data-toggle="tab"]').attr("aria-expanded",!1),t.addClass("active").find('[data-toggle="tab"]').attr("aria-expanded",!0),n?(t[0].offsetWidth,t.addClass("in")):t.removeClass("fade"),t.parent(".dropdown-menu").length&&t.closest("li.dropdown").addClass("active").end().find('[data-toggle="tab"]').attr("aria-expanded",!0),i&&i()}o.length&&n?o.one("bsTransitionEnd",s).emulateTransitionEnd(a.TRANSITION_DURATION):s(),o.removeClass("in")};var t=r.fn.tab;r.fn.tab=e,r.fn.tab.Constructor=a,r.fn.tab.noConflict=function(){return r.fn.tab=t,this};var i=function(t){t.preventDefault(),e.call(r(this),"show")};r(document).on("click.bs.tab.data-api",'[data-toggle="tab"]',i).on("click.bs.tab.data-api",'[data-toggle="pill"]',i)}(jQuery),function(l){"use strict";var h=function(t,e){this.options=l.extend({},h.DEFAULTS,e);var i=this.options.target===h.DEFAULTS.target?l(this.options.target):l(document).find(this.options.target);this.$target=i.on("scroll.bs.affix.data-api",l.proxy(this.checkPosition,this)).on("click.bs.affix.data-api",l.proxy(this.checkPositionWithEventLoop,this)),this.$element=l(t),this.affixed=null,this.unpin=null,this.pinnedOffset=null,this.checkPosition()};function i(o){return this.each(function(){var t=l(this),e=t.data("bs.affix"),i="object"==typeof o&&o;e||t.data("bs.affix",e=new h(this,i)),"string"==typeof o&&e[o]()})}h.VERSION="3.4.1",h.RESET="affix affix-top affix-bottom",h.DEFAULTS={offset:0,target:window},h.prototype.getState=function(t,e,i,o){var n=this.$target.scrollTop(),s=this.$element.offset(),a=this.$target.height();if(null!=i&&"top"==this.affixed)return nfront, false->rear * @param boolean r: if enabled remove right zeros */ Number.prototype.formatAsPrice = function(n, x, s, c, p, r) { var re = '\\d(?=(\\d{' + (x || 3) + '})+' + (n > 0 ? '\\D' : '$') + ')', num = this.toFixed(Math.max(0, ~~n)), sep = '%%', formatted, numericPrice, symbol = '' + settings.currencies['currency' + settings.currencyId].SYMBOL + ''; num = num.replace('.', sep).replace(new RegExp(re, 'g'), '$&' + s); numericPrice = num.replace(sep, '.'); num = num.split('%%'); formatted = '' + num[0]+''; if (n > 0) { var dec = num[1]; if (r && Number(dec) > 0){ // dec = dec.toString(); dec = (dec[1] == 0) ? dec[0] : dec; formatted += '' + c + dec + ''; } else if (!r){ formatted += '' + c + dec + ''; } } if (p) { formatted = symbol + formatted; } else { formatted = formatted + symbol; } return formatted; }; outputFormattedCurrency = function(price) { switch (settings.currencyFormat) { /*TODO: create all cases*/ case "$___,___,___,__0.00": price = price.formatAsPrice(2, 3, ',', '.', true); break; case "___,___,___,__0.00$": price = price.formatAsPrice(2, 3, ',', '.', false); break; case "$___.___.___.__0,00": price = price.formatAsPrice(2, 3, '.', ',', true); break; case "___.___.___.__0,00$": price = price.formatAsPrice(2, 3, '.', ',', false); break; case "0 00$": price = price.formatAsPrice(2, 0, '', ' ', false); break; case "$0 00": price = price.formatAsPrice(2, 0, '', ' ', true); break; case "0$": price = price.formatAsPrice(0, 0, '', '', false); break; case "$0": price = price.formatAsPrice(0, 0, '', '', true); break; case "0 __$": price = price.formatAsPrice(2, 0, '', ' ', false, true); break; case "$0 __": price = price.formatAsPrice(2, 0, '', ' ', true, true); break; case "$___,___,___,__0.__": price = price.formatAsPrice(2, 3, ',', '.', false, true); break; case "___,___,___,__0.__$": price = price.formatAsPrice(2, 3, ',', '.', false, true); break; case "$___.___.___.__0,__": price = price.formatAsPrice(2, 3, '.', ',', true, true); break; case "___.___.___.__0,__$": price = price.formatAsPrice(2, 3, '.', ',', false, true); break; default: price = price.formatAsPrice(2, 3, ',', '.', false); }; return price; } Object.getLength = function(obj){return Object.keys(obj).length;}; /** * Get style on DOM elements * @param {String} style Style property * @param {object} elements Optional, default: ALL * @return {array} Array of values from style property on elements. */ window.getStyles = function(style, elements){ if (!elements) elements = F('*',true); var result = []; for (var i=0; i < elements.length; i++){ var $el = $(elements[i]); if ($el.css(style)) result.push($el.css(style)); } return result; }; /** * Load web fonrs * @param {string} basePath base path to fonts */ window.loadWebFonts = function(basePath) { // Get all font-family parameters for all elements in the document and init other stuff var allFonts = getStyles('font-family'), baseFonts = ['monospace', 'sans-serif', 'serif', 'cursive', 'helvetica neue', 'fontawesome'], webFonts = [], cssCode = ''; // Create an array of unique font families allFonts.forEach(function(fonts) { fonts.split(',').forEach(function(font) { font = font.trim().replace(/'|"/g, '').toLowerCase(); if(webFonts.indexOf(font) == -1 && baseFonts.indexOf(font) == -1) webFonts.push(font); }); }); if(webFonts.length) { // Define font types depending on the client browser if (navigator.userAgent.indexOf("Safari") > 0){ var extension = '.ttf', format = 'truetype'; } else if(navigator.userAgent.indexOf("MSIE") > 0){ var extension = '.eot', format = 'eot'; } else{ var extension = '.woff', format = 'woff'; } /* Init font detector by Lalit Patel (http://www.lalit.org/lab/javascript-css-font-detect) */ var testString = 'mmmmmmmmmmlli', testSize = '72px', defaultWidth = {}, defaultHeight = {}, h = document.getElementsByTagName("body")[0], s = document.createElement("span"); s.style.visibility = 'hidden'; s.style.fontSize = testSize; s.innerHTML = testString; for(var index in baseFonts) { s.style.fontFamily = baseFonts[index]; h.appendChild(s); defaultWidth[baseFonts[index]] = s.offsetWidth; defaultHeight[baseFonts[index]] = s.offsetHeight; h.removeChild(s); } detectFont = function(font) { var detected = false; for(var index in baseFonts) { s.style.fontFamily = font + ',' + baseFonts[index]; h.appendChild(s); var matched = (s.offsetWidth != defaultWidth[baseFonts[index]] || s.offsetHeight != defaultHeight[baseFonts[index]]); h.removeChild(s); detected = detected || matched; } return detected; }; /* End font detector by Lalit Patel */ // Add bootstrap glyphicon when htmlFramework is bootstrap if (htmlFramework == 'bootstrap') cssCode += '@font-face { font-family: "Glyphicons Halflings";src: url("' + basePath + 'glyphicons-halflings-regular' + extension +'") format("' + format + '"); font-style: normal; font-weight: normal; }\n'; // Create @font-face declarations for every unique font not detected on the client browser/system webFonts.forEach(function(font) { if(!detectFont(font)) cssCode += '@font-face { font-family:"' + font + '"; src:url("'+ basePath + font.replace(/ /g, '-') + extension + '") format("' + format + '"); font-style: normal; font-weight: normal; }\n'; }); // Finally, if there's any new @font-face declarations add them to the document if(cssCode.length) { if (navigator.userAgent.indexOf("Chrome") > 0) cssCode = '@media screen { ' + cssCode + ' }'; var head = document.head || document.getElementsByTagName('head')[0], style = document.createElement('style'); style.type = 'text/css'; head.appendChild(style); if(style.styleSheet) // Workaround for IE style.styleSheet.cssText = cssCode; else style.appendChild(document.createTextNode(cssCode)); } } }; //determines if a variable is defined an not null $.defined = function(a){ if(typeof a === 'undefined') return false; if(a == null) return false; return true; };/*! * Fluid Library v1.0.2 | (C) 2019 TLG Commerce | License */ /** * Fluid JavaScript Library * * @file * * @version v1.0.2 * @author TLG Commerce http://tlgcommerce.com * @requires jQuery.js * @date 2019-04-15 */ ; /** * Fluid Main * @namespace Fluid */ var Fluid = window.Fluid = {}; /** * Fluid Version * @property {string} VERSION Fluid version * @memberOf Fluid */ Fluid.VERSION = '0.0.1'; /** * Fluid Validate Form Configuration */ Fluid.validateFormConf = { borderColorOnError : '', addValidClassOnAll : true, scrollToTopOnError : false }; Fluid.validateFormConf.onError = function ($form) { $('.form-message').removeClass('alert alert-success alert-danger').text(''); if (Fluid.validateFormConf.scrollToTopOnError){ $('html, body').animate({ scrollTop: ($('.has-error').offset().top) },500); } }; /** * Fluid Main Config */ Fluid.config = { showModalBasket: true, showModalComparerBasket: true, notify: { type : 'notes' }, notifyMode : true, orderRefundReload: true }; Fluid.notifyConf = Fluid.config.notify; // Fluid Require files // ----------------------------------------------------------------------------- Fluid.require = { /** * Fluid.require.css * @param {string} source Path to source * @return {void} */ css : function(source){ var cssfile = document.createElement("link"); cssfile.setAttribute("rel", "stylesheet"); cssfile.setAttribute("type", "text/css"); cssfile.setAttribute("href", source); if (typeof cssfile!="undefined") document.getElementsByTagName("head")[0].appendChild(cssfile); }, /** * Fluid.require.js * @param {string} source Path to source * @param {object} options * @return {void} */ js : function(source, load){ // Prepare load if (!load) load = function(){}; // Call $.getScript(source, load); }, cachedJs : function( url, options ) { // Allow user to set any option except for dataType, cache, and url options = $.extend( options || {}, { dataType: "script", cache: true, url: url }); // Use $.ajax() since it is more flexible than $.getScript // Return the jqXHR object so we can chain callbacks return jQuery.ajax( options ); } }; // FI Fluid Require files ------------------------------------------------------ /** * @method Fluid.extend * @memberOf Fluid * * @description * This function extends the mixin's functions into our "Class" * * Clona un element i el retorna amb les propietats que s'han volgut modificar. * Ideal per a crear objectes Tipus nous * * @param {object} protoProps Prototype data * @param {object} staticProps Static properties * @return {object} returns variable */ Fluid.extend = function(protoProps, staticProps) { var parent = this; var child; if (protoProps && protoProps.hasOwnProperty('constructor')) child = protoProps.constructor; else child = function(){return parent.apply(this, arguments);}; $.extend(child, parent); var Surrogate = function(){ this.constructor = child; }; Surrogate.prototype = parent.prototype; child.prototype = new Surrogate; if (protoProps) $.extend(child.prototype, protoProps, staticProps); child.__super__ = parent.prototype; return child; }; /** * Generate unique integer id (valid only on navigator "request") * @param {number} prefix Prefix name for id * @return {string} Returns uniqueId */ Fluid.idCounter = 0; Fluid.objPrefixes = {}; Fluid.uniqueId = function(prefix) { if (prefix in Fluid.objPrefixes) Fluid.objPrefixes[prefix]++; else Fluid.objPrefixes[prefix] = 1; // var id = ++Fluid.idCounter + ''; var id = Fluid.objPrefixes[prefix] + ''; return prefix ? prefix + id : id; }; Fluid.carryMethod = function(path, carry) { if (!path) return false; carry = carry || window; var arrCall = path.split("."); for (var i = 0; i < arrCall.length; i++) { if (!carry[arrCall[i]]) return false; if (typeof carry[arrCall[i]] === 'function') return carry[arrCall[i]]; carry = carry[arrCall[i]]; } return false; } Fluid.pluginEvents = []; /** * @property {object} Fluid.resources It has main prototyping functions * @memberOf Fluid */ Fluid.resources = { initialize : function(){}, /** * Return parent object (pseudo super) * @return {Object} */ parent : function(){return this.constructor.__super__;}, /** * Super Call * @param {string} method Name of method to call * @param {any} "noname" Others params are accepted * @return {void} Call method directly */ superForm : function(method){ // Prevent call this method without arguments if (!method) return; // Get all arguments without the first (method) var args = Array.prototype.slice.call(arguments, 1); // Get main "class" (super constructor) var obj = this.constructor.__super__; // Invoke method if exists and is a function if(obj && $.isFunction(obj[method])) obj[method].apply(this, args); }, /** * Trigger Events * @param {String} triggerName Function added on "addEvent" or "addTrigger" * @param {"MULTIPLE"} * Multiple params... it are not required * @return {Boolean} */ trigger : function(triggerName) { var result = false; // Get function var functionTrigger = this["custom_" + triggerName]; // Arguments var args = Array.prototype.slice.call(arguments, 1); // Call function if(this && $.isFunction(functionTrigger)){ result = true; functionTrigger.apply(this, args); } return result; }, /** * Add Plugin Listener * @param {string} listener Listener name * @param {Function} fn Function to call * @return {Boolean} */ addPluginListener : function(listener, method, force) { var allowedListeners = ["onAddProduct","onProductClick","setPaymentSystem","setShippingSection","deleteProduct", "beforeSubmitEndOrder", "initializePaymentsBefore", "initializePaymentsCallback"]; if (allowedListeners.indexOf(listener) < 0) return false; if (!$.isFunction(method)) return false; if (Fluid.pluginEvents.indexOf(listener) < 0) { Fluid.pluginEvents.push(listener); Fluid.pluginEvents[listener] = []; } forceLoad = force || false; avt = avoidTrackings || false; avoid = forceLoad ? false : avt; if (!avoid) Fluid.pluginEvents[listener].push(method); return true; }, /** * Plugin Listener * @param {string} listener Listener name * @param {"MULTIPLE"} * Multiple params... it are not required */ pluginListener : function(listener) { var allowedListeners = ["onAddProduct","onProductClick","setPaymentSystem","setShippingSection","deleteProduct", "beforeSubmitEndOrder", "initializePaymentsBefore", "initializePaymentsCallback"]; if (allowedListeners.indexOf(listener) < 0) return false; if (!Fluid.pluginEvents[listener] || Fluid.pluginEvents.length == 0) return false; var args = Array.prototype.slice.call(arguments, 1); Fluid.pluginEvents[listener].forEach(function(el, index){ if ($.isFunction(el)) el.apply(this, args); }); } }; /** * Fluid.Form * @class Fluid.Form * @memberOf Fluid * * @param {object} form DOM form */ Fluid.Form = function(form){ //Main vars this.name = this.name || 'form'; //DOM Basic Elements this.el = { form : form, $form : $(form), }; if (this.el.form){ // Get message container this.el.$message = this.el.$form.children('.form-message'); if (!this.el.$message.length) this.el.$message = $('
', { "class":"form-message" }).prependTo(this.el.$form); // Add Submit event if (this.submit) this.el.$form.on('submit', this.submit.bind(this)); // Find Reload captcha and add it an event var reloadCaptchas = this.el.$form.find('img.reloadCaptchaImage'); if (reloadCaptchas.length){ this.el.$reloadCaptcha = $(reloadCaptchas[0]); var captchaData = this.el.$reloadCaptcha.data('captcha'); this.el.$reloadCaptcha.on('click', this.reloadCaptcha.bind(this, captchaData.position, captchaData.id, captchaData.length)); } } //INITIALIZE this.initialize.apply(this, [form] ); }; //Extend Public Methods on Fluid.Form $.extend(true, Fluid.Form.prototype, Fluid.resources,{ submit : function(event){ //Get method, continue default event if (this.el.form.method.toLowerCase() == 'get') return; event.preventDefault(); //Validate form if (!this.el.$form.isValid()) return false; if (this.el.$form.data("fluidFormdata")) { this.postFormData(event); return; } //Get form data var arrDataForm = this.el.$form.serializeArray(); //Fills dataForm this.dataForm = {}; for (var i = 0; i < arrDataForm.length; i++){ if(!(arrDataForm[i].name in this.dataForm)) this.dataForm[arrDataForm[i].name] = []; this.dataForm[arrDataForm[i].name].push(arrDataForm[i].value); } for (var i in this.dataForm) this.dataForm[i] = this.dataForm[i].join(); //Avoid mutiple submit this.el.$form.find('button[type="submit"], input[type="submit"]').attr('disabled',true); //Post if (this.el.form.method.toLowerCase() == 'post') $.post(this.el.form.action, JSON.stringify(this.dataForm), this.onReceive.bind(this), "json") .fail(this.onFail.bind(this)) .always(this.onComplete(this)); }, onFail : function(error){ // Allow submit this.el.$form.find('button[type=submit], input[type=submit]').attr('disabled',false); // Callback if (this.callback && typeof this.callback === 'function') this.callback(error.responseJSON); }, onReceive : function(result){ // Allow submit this.el.$form.find('button[type=submit], input[type=submit]').attr('disabled', false); // Callback if (this.callback && typeof this.callback === 'function') this.callback(result); }, onComplete : function(result){ // Allow submit //this.el.$form.find('button[type=submit], input[type=submit]').attr('disabled', false); }, reloadCaptcha : function(position, element, length){ if (!this.el.imageCaptcha) this.el.imageCaptcha = F('#' + element, this.el.form); var objParams = new urlParameterEncoder() .addParameter('position',position) .addParameter('length',length); $.get('/user/reloadCaptcha' + objParams.getParameters(), this.reloadCaptchaCallback.bind(this)); }, reloadCaptchaCallback : function(data){ this.el.imageCaptcha.src = data }, callback : function(result){ if (typeof result === 'undefined') return; if (!result.response) { var message = result.errorDetail? result.errorDetail : 'Error'; var success = 0; } else { var message = result.response.MESSAGE; var success = result.response.SUCCESS? result.response.SUCCESS : 0; } this.el.$message.text(message); if (success){ this.el.$message .removeClass('alert-danger') .addClass('alert alert-success'); } else this.el.$message .removeClass('alert-success') .addClass('alert alert-danger'); }, showMessage : function(message, type, notifyMode){ if (!type) type = 'danger'; if (typeof notifyMode !== "boolean") notifyMode = Fluid.config.notifyMode; if (notifyMode) Fluid.notify(message, {type:type}); else this.el.$message.html(message).removeClass('alert-danger alert-success alert-info').addClass('alert alert-'+type); // always remove classes previously }, postFormData: function(event){ event.preventDefault(); //Get form data var arrDataForm = this.el.$form.serializeArray(); //Create FormData var formData = new FormData(this.el.$form[0]); for (var i = 0; i < arrDataForm.length; i++) { formData.append(arrDataForm[i].name, arrDataForm[i].value); } //Check input files length and accept formats. var isValidFormInput = true; this.el.$form.find("input:file").each(function(index, el){ if (el.files.length > 0) { var suffixes = $(el).data('fluidAccept'); joinedSuffixes = suffixes.split(',').join('|'); var re = new RegExp(".*\.(" + joinedSuffixes + ")", "i"); if (!re.test(el.value)) { isValidFormInput = false this.showMessage(languageSheet.VALIDEXTENSIONS + ' ' + suffixes.split(',').join(', ')) } maxFileSize = $(el).data('fluidMaxSize'); if (el.files[0].size/(1024*1024) > maxFileSize) { isValidFormInput = false this.showMessage(languageSheet.VALIDSIZE + ' ' + maxFileSize +'Mb') } formData.append(el.name, el.files[0], el.value); } }.bind(this)); if (!isValidFormInput) return; var callback = this.onReceive.bind(this); $.ajax({ url: this.el.form.action, data: formData, async: true, mimeType: 'multipart/form-data', processData: false, contentType: false, type:'POST', success: function(data) { callback($.parseJSON(data)); } }); } }); /** * Extend Fluid Form for create "superClass" */ Fluid.Form.extend = Fluid.extend; /** * @method Fluid.Form.addMethod * @memberOf Fluid.Form * @description Add Methods to Form * * @param {string} name Name of method * @param {function()} method Function * @return {boolean} */ Fluid.Form.addMethod = function(name, method){ if (typeof name !== 'string' || typeof method !== 'function') return false; this.prototype["custom_"+name] = method; return true; }; /* Others methods that do the same */ Fluid.Form.addEvent = Fluid.Form.addMethod; Fluid.Form.addListener = Fluid.Form.addMethod /** * UserForm Resources * It has userForm prototyping functions for userForm & userAddressBookForm * @property {object} Fluid.userFormResources * @memberOf Fluid */ Fluid.userFormResources = { /** * Ensures this.prefix is filled * @return {void} */ getPrefix : function(){ this.prefix = this.prefix || 'user'; }, /** * Show fields and prepare validation for different kinds of view, particular * business or freelance. * @param {number} userType 1:particular, 2:business, 3:freelance * @param {array} formFields array of fields * @param {object} fieldsMainContainer DOM container */ setFormFields : function(userType, formFields, fieldsMainContainer){ // Ensures prefix exists this.getPrefix(); // Initialize vars var i, formField, $container, $currentFieldsContainer, fieldInformation, dataValidation, $countriesSelector; // Define userType // Set DOM data only when form is userForm or is userAddressBookForm if (this.prefix == 'user' || this.prefix == 'userAddressBook') { this.el.$form.data('userType', userType); if(this.prefix == 'userAddressBook') this.el.$userAddressBookTypeField.val(userType); else this.el.$userTypeField.val(userType); } // Otherwise, forces userType=1 else { userType = 1; } this.userType = userType; // Remove required fields this.removeRequiredFields(formFields, fieldsMainContainer); // Destroying help block fieldsMainContainer.find('span.help-block').remove(); // Destroying old blocks fieldsMainContainer.find('div.'+this.prefix+'FormFields').remove(); // Creating a new fields block $currentFieldsContainer = $('
', { 'class':'formFields '+this.prefix+'FormFields' }).appendTo(fieldsMainContainer); // Iterate formFields for(i = 0; i < formFields[userType].length; i++) { //Get field information fieldInformation = formFields[userType][i]; // Discriminate "BLOCK" if(fieldInformation.name.toUpperCase() == 'BLOCK') { $currentFieldsContainer = $('
', { 'class':'formFields '+this.prefix+'FormFields' }).appendTo(fieldsMainContainer); } else { // Get DOM elements formField = F('#'+this.prefix+fieldInformation.name+'Field'); $container = $('#'+this.prefix+'Field'+fieldInformation.name+'Container'); // Check field exists and is required if(formField && fieldInformation.required){ dataValidation = this.setValidationData($(formField), true); $(formField).data('validation', dataValidation); //Add validation formField.setAttribute('data-validation', dataValidation); } // Check container exists if($container) { $container.show(); $countriesSelector = $('#'+this.prefix+'FieldCountryContainer .countriesSelector'); if ($countriesSelector.length && $.inArray(fieldInformation.name, ["State","City","Zip"]) >= 0) $countriesSelector.append($container); else $currentFieldsContainer.append($container); if(fieldInformation.required) $container.find('span.required').show(); } } } //Country Fields if (this.countryUserFields && this.countryUserFields['country']) this.setCountryFormFields(this.countryUserFields['country'].state,'country'); }, /** * Prepare country fields * @memberOf Fluid.UserForm * @param {number} state 1: visible 0:hidden * @param {string} fieldName Name of field */ setCountryFormFields : function(state, fieldName){ // Check arguments if (!fieldName) return; if (!state) state = 0; // state 1: visible - 0: hidden // Ensures prefix exists this.getPrefix(); if (this.countryUserFields) { this.countryUserFields[fieldName].state = state; if (this.countryUserFields[fieldName].formFields) { var countryUserFields = this.countryUserFields[fieldName].formFields; for (var i = 0; i < countryUserFields.length; i++) { var fieldContainer = F('#'+this.prefix+'Field'+countryUserFields[i]+'Container'); if (fieldContainer) fieldContainer.style.display = state? 'block' : 'none'; } } } }, /** * Remove required fields, for each view * @memberOf Fluid.UserForm * @param {array} formFields array of fields * @param {object} fieldsMainContainer DOM element */ removeRequiredFields : function(formFields, fieldsMainContainer){ // Ensures prefix exists this.getPrefix(); // Init vars var i, dataValidation, formField, $formField, $container; for (i = 0; i < formFields[0].length; i++) { formField = F('#'+this.prefix+formFields[0][i]+'Field'); $formField = $(formField); $container = $('#'+this.prefix+'Field'+formFields[0][i]+'Container'); if(formField){ dataValidation = this.setValidationData($formField, false); $formField.data('validation', dataValidation); formField.setAttribute('data-validation', dataValidation); $formField.removeClass('error').css({'borderColor': ''}); } if($container) { $container.hide(); //moving fields fieldsMainContainer.append($container); $container.find('span.required').hide(); } }; }, /** * setValidationData * @param {object} $formField jQuery DOM Element * @param {boolean} required set required field */ setValidationData : function($formField, required){ var i, dataValidation, arrElements, arrValidation; dataValidation = $formField.data('validation') || ""; arrElements = ["email", "phone", "vat", "idcard"]; arrValidation = required? ["required"] : []; for (i = 0; i < arrElements.length; i++) if (dataValidation.toLowerCase().indexOf(arrElements[i]) >= 0) arrValidation.push(arrElements[i]); return arrValidation.join(","); }, /** * Select Postal Code Callback * @param {String} type userInfo | shippingAddress * @param {Function} callback * @return {void} */ selectPostalCodeCallback : function(type, callback){ if (!$.isFunction(callback)) return; // Type: userInfo | shippingAddress | addressBook if (type === 'userInfo') localizeEvents.selectPostalCode = callback.bind(this); else if (type === 'shippingAddress') localizeEvents.selectShippingPostalCode = callback.bind(this); else if (type === 'addressBook') localizeEvents.selectAddressBookPostalCode = callback.bind(this); } }; /** * @class Fluid.MiniBasketClass * @memberOf Fluid */ Fluid.MiniBasketClass = function(){ this.el = {}; this.events = { before : null, callback : null }; //INITIALIZE this.initialize.apply(this); }; //Extend Public Methods on Fluid.MiniBasketClass $.extend(true, Fluid.MiniBasketClass.prototype, { /** * Initialize minibasket * @memberOf Fluid.MiniBasketClass */ initialize : function(){ this.el.$container = $("#miniBasket"); this.el.$miniBasketContent = this.el.$container.find('#miniBasketContent'); this.data = this.el.$miniBasketContent.data('minibasket'); // Add Event this.el.$container.on('click',"[data-minibasket-delete]", function(event){ event.stopPropagation(); this.deleteItem($(event.currentTarget).data("minibasketDelete")); }.bind(this)); this.initializeQuantityElements(); }, initializeQuantityElements : function() { try { this.el.$container.find('input[data-fluid-quantity]').quantity(); } catch(err) { // Pray God's will call quantity plugin } this.el.quantityElements = this.el.$container.find('input.basketQuantity:text'); // Select box if (!this.el.quantityElements.length) this.el.quantityElements = this.el.$container.find('select.basketQuantity'); this.el.quantityElements.on('click', function(ev){ ev.stopPropagation(); }); this.el.quantityElements.on('change', this.onChangeQuantity.bind(this) ); }, exists : function() { return typeof this.data === 'object'; }, /** * Add events for customize the shop performance * @memberOf Fluid.MiniBasketClass * @param {String} name Name of type of function * @param {Function} fn Function to call */ addEvent : function(name, fn){ if ((name == 'before' || name == 'callback') && fn && typeof fn === 'function') this.events[name] = fn; }, /** * Change quantity * @memberOf Fluid.CheckoutForm * @param {object} eventData */ onChangeQuantity:function(eventData) { //Call before this.before(); var data = {}; data[eventData.currentTarget.name] = eventData.currentTarget.value; var qtText = 'quantity-'; try { var inputData = JSON.parse(eventData.currentTarget.name.substring(qtText.length)); var prodCombinationInput = $('form.buyForm input[data-fluid-product-hash="'+ inputData.productHash +'"]').get(0); } catch(e) { // not valid JSON } if(prodCombinationInput){ var itemForm = prodCombinationInput.closest('form'); itemForm.module.updateCombinationsFields([inputData.productHash], eventData.currentTarget.value); itemForm.module.updateCombinationsFormType(); } $.ajax({ url: '/minibasket/recalculate/', type: 'POST', dataType: 'json', data: JSON.stringify(data) }) .done(this.oneStepCheckoutRefresh.bind(this)) .always(this.reload.bind(this)); }, /** * Refresh minibasket view * @memberOf Fluid.MiniBasketClass */ reload : function(callback){ //Call before this.before(); // force reload changing minibasket data on checkout var bodyClasses = $('body').attr('class') if($('form.basketForm').length && (bodyClasses.indexOf('fluidContent-basket') != -1 || bodyClasses.indexOf('fluidContent-paymentAndShipping') != -1)){ $('html,body').animate({ scrollTop: 0 }, 'slow', function(){window.location.reload();} ); } //No cache param var ncParam = 'nc=' + Math.floor(100 + Math.random() * 899); //Action if (!this.el.$container) this.el.$container = $("#miniBasket"); this.el.$container.load('/minibasket?nc='+ncParam+' #miniBasketContent', this.loadComplete.bind(this, callback)); }, /** * Delete product from minibasket * @memberOf Fluid.MiniBasketClass * @param {number} position Product position from minibasket */ deleteItem : function(position){ //Call before this.before(); //No cache param var ncParam = 'nc=' + Math.floor(100 + Math.random() * 899); this.deleteProduct = position; //Reload minibasket if (!this.el.container) this.el.container = $("#miniBasket"); this.el.container.load('/minibasket?deleteProduct='+this.deleteProduct+'&'+ncParam+' #miniBasketContent', function(){ this.oneStepCheckoutRefresh(); this.loadComplete(); }.bind(this)); }, /** * Hide minibasket * @memberOf Fluid.MiniBasketClass * @todo Please, implement this function */ hide : function(){ //TODO Hide minibasket }, /** * Event trigger before post to server * @memberOf Fluid.MiniBasketClass */ before : function(){ if (!this.el.container) this.el.container = $("#miniBasket"); // Add loadingClass this.el.$container.addClass('miniBasketLoading'); if (this.events.before && typeof this.events.before === 'function') this.events.before.bind(this)(); }, /** * Callback function * @memberOf Fluid.MiniBasketClass */ loadComplete : function(callback){ if (this.el.$container && this.el.$container.hasClass('miniBasketLoading')) this.el.$container.removeClass('miniBasketLoading'); this.el.$miniBasketContent = this.el.$container.find('#miniBasketContent'); this.data = this.el.$miniBasketContent.data('minibasket'); var saveBasketForm = this.el.$miniBasketContent.find('form'); if(saveBasketForm && saveBasketForm.data('fluidForm') == 'saveBasketForm') new Fluid.saveBasketForm(saveBasketForm[0]); // Callbacks if (this.events.callback && typeof this.events.callback === 'function') this.events.callback.bind(this)(); Fluid.initializeCountdowns(); Fluid.basketExpiration.checkNewExpirationDate(); if(this.deleteProduct && this.deleteProduct.length){ var hashes = this.deleteProduct.split('-'); this.deleteProduct = ''; var prodCombinationInput = $('form.buyForm input[data-fluid-product-hash="'+ hashes[0] +'"]').get(0); if(prodCombinationInput){ var itemForm = prodCombinationInput.closest('form'); itemForm.module.updateCombinationsFields(hashes, 0); itemForm.module.updateCombinationsFormType(); } } this.initializeQuantityElements(); if (callback && typeof callback === 'function'){ callback(); } }, /** * On Recieve * @memberOf Fluid.MiniBasketClass */ onReceive : function(result){ if (!this.el.container) this.el.container = $("#miniBasket"); this.el.container.replaceWith(result); //Update this.el.container this.el.container = $("#miniBasket"); if (this.events.callback && typeof this.events.callback === 'function') this.events.callback(result); }, oneStepCheckoutRefresh : function(){ if (this.oneStepCheckoutCallback && typeof this.oneStepCheckoutCallback === 'function') this.oneStepCheckoutCallback(this); } }); // Generate miniBasket Object /** * Fluid.miniBasket * @type {Fluid.MiniBasketClass} */ Fluid.miniBasket = new Fluid.MiniBasketClass(); /** * @class Fluid.comparerBasketClass * @memberOf Fluid */ Fluid.comparerBasketClass = function(){ this.nameId = "#comparerBasket", this.nameContentId = "#comparerBasketContent", this.nameContentLayerId = "#comparerBasketLayer", this.el = {}; this.events = { before : null, callback : null }; //INITIALIZE this.initialize.apply(this); }; //Extend Public Methods on Fluid.comparerBasketClass $.extend(true, Fluid.comparerBasketClass.prototype, { /** * Initialize comparerBasket * @memberOf Fluid.comparerBasketClass */ initialize : function(){ this.el.$container = $(this.nameId); this.el.$comparerBasketContent = this.el.$container.find(this.nameContentId); // Add Event this.el.$container.on('click',"[data-comparer-basket-delete]", function(event){ event.stopPropagation(); this.deleteItem($(event.currentTarget).data("comparerBasketDelete")); }.bind(this)); }, /** * Add events for customize the shop performance * @memberOf Fluid.comparerBasketClass * @param {String} name Name of type of function * @param {Function} fn Function to call */ addEvent : function(name, fn){ var boolCheckEventName = (name == 'before' || name == 'callback' || name == "beforeReloadBadge" || name == "callbackReloadBadge"); if (boolCheckEventName && fn && typeof fn === 'function') this.events[name] = fn; }, /** * Refresh notificationComparer view * @memberOf Fluid.comparerBasketClass */ reload : function(){ //Call before this.before(); // Reload Container if (!this.el.$container) this.el.$container = $(this.nameId); this.el.$container.load('/comparerBasket ' + this.nameId, this.loadComplete.bind(this)); }, /** * Refresh notificationComparer view * @memberOf Fluid.comparerBasketClass */ reloadBadge : function(intQtItems){ //Actions if (this.events.beforeReloadBadge && typeof this.events.beforeReloadBadge === 'function') this.events.beforeReloadBadge.bind(this)(intQtItems); $("#comparerNotificationBasket").find(".badge").html(intQtItems); if (this.events.callbackReloadBadge && typeof this.events.callbackReloadBadge === 'function') this.events.callbackReloadBadge.bind(this)(intQtItems); }, /** * Delete product from notificationComparer * @memberOf Fluid.comparerBasketClass * @param {number} position Product position from minibasket */ deleteItem : function(productId){ //Call before this.before(); //Reload minibasket if (!this.el.$container) this.el.$container = $(this.nameId); this.el.$container.load('/comparerBasket?productId=' + productId + " " + this.nameContentId, this.loadComplete.bind(this)); }, /** * Display comparerbasket * @memberOf Fluid.comparerBasketClass */ display : function(){ //TODO Hide minibasket $(this.nameContentLayerId).addClass('open'); }, /** * Hide comparerbasket * @memberOf Fluid.comparerBasketClass */ hide : function(){ //TODO Hide comparerbasket $(this.nameContentLayerId).removeClass('open'); }, /** * Event trigger before post to server * @memberOf Fluid.comparerBasketClass */ before : function(){ if (!this.el.$container) this.el.$container = $(this.nameId); if (this.events.before && typeof this.events.before === 'function') this.events.before.bind(this)(); }, /** * Callback function * @memberOf Fluid.comparerBasketClass */ loadComplete : function(){ this.el.$comparerBasketContent = this.el.$container.find(this.nameContentId); // var intItemsCount = this.el.$comparerBasketContent.find("[data-comparer-basket-delete]").length; var intItemsCount = $("#comparerNotificationBasket").data("comparerBasketItems"); this.reloadBadge(intItemsCount); if (this.events.callback && typeof this.events.callback === 'function') this.events.callback.bind(this)(); } }); // Generate comparerBasket Object /** * Fluid.comparerBasket * @type {Fluid.comparerBasketClass} */ Fluid.comparerBasket = new Fluid.comparerBasketClass(); Fluid.setConfirmOrder = function(element){ $el = $(element); var data = $el.data('fluidConfirmorder'); $el.load('/checkout/setConfirmOrder/?'+data, {}, function(result, status, xhrResponse){} ); } Fluid.initializeIncrementCounter = function(){ var listIds = []; $('[data-fluid-incrementCounter-data]').each(function(){ var info = $(this).data("fluid-incrementcounter-data") switch(info.type){ case 1: //take all id's to count the impressions if(!listIds.hasOwnProperty(info.item)){ listIds[info.item] = info.id + "," } else{ listIds[info.item] += info.id + "," } break; case 2: //add the event click to count the clicks and redirect to a URL $(this).on('click mousedown', function(e){ e.preventDefault(); if(e.type == 'mousedown' && e.which == 1){//to prevent double event and double click counter return; } var redirect = 0; if( e.which == 1 ) { //only redirect if the click is with the left mouse button redirect = 1; } var url = "/incrementCounter/" + info.type + "/" + info.id + "/" + info.item + "/" + redirect + "?target=" + encodeURIComponent($(this).attr("href")); if(redirect){ $(location).attr('href',url); } else{ $.get(url, function(){});//get doing ajax to don't reload the nav } }); break; default: } }); for (var key in listIds){ if(listIds.hasOwnProperty(key) && listIds[key].length){ Fluid.objIncrementCounter(1, listIds[key], key); } } } Fluid.initializeCountdowns = function(){ if(!('localServerOffsetTime' in settings)) settings.localServerOffsetTime = moment().unix() - moment(settings.serverTime).unix(); // Initialize Product Count Down $('[data-fluid-countdown]').each(function(index, element) { new Fluid.productCountDown(element.id); }); $(document.body).removeClass('basket-check-availability'); $('[data-lock-countdown]').each(function(index, element) { if(!element.basketLockCountDown) element.basketLockCountDown = new Fluid.basketLockCountDown(element); }); $('[data-basket-expires]').each(function(index, element) { if(!element.basketCountDown) element.basketCountDown = new Fluid.basketCountDown(element); }); } /** * Fluid jQuery Interactor. * Generate plugin for DOM interactions * * @method Fluid.fn * @memberOf Fluid * * @param {string} name Name of plugin * @param {object} o Object of plugin * * @example * //Create plugin: * Fluid.fn('pluginName',{ * options : { * enableAnimations : true, * }, * Constructor : function(element, options){ * * //Public methods * this.init = function() { // it is not necessary * //initialize * }; * * // This public method, also removes his dataset. * this.destroy = function() { * element.remove(); * }; * this.clean = function() { * element.html(''); * }; * * //Private methods * function _dummy(){ * //I will return nothing. * }; * } * }); * * // Initialize * $('#element').pluginName(); * * // Destroy or call other public methods * $('#element').pluginName('destroy'[, func arguments]); */ Fluid.fn = function(name, o) { ;(function($) { o.options = $.extend(o.options, {}); if (!o.Constructor || typeof o.Constructor !== 'function'){ throw 'Constructor is not defined!'; return; } //Create plugin $.fn[name] = function(options) { //Clone object // Object Deep copy (Also you can use JSON.parse(JSON.stringify(o.options))); but then you'll lose the functions var defaults = $.extend(true, {}, o.options); // method calling if( typeof options === 'string') { var args = Array.prototype.slice.call(arguments, 1); var res; this.each(function() { var obj = $.data(this, name); if(obj && $.isFunction(obj[options])) { var r = obj[options].apply(obj, args); if(res === undefined) res = r; if(options == 'destroy') $.removeData(this, name); } else if(obj && obj[options]) res = obj[options]; }); if(res !== undefined) return res; return this; } options = $.extend(defaults, options || {}); this.each(function(i, _element) { var element = $(_element); // Object Deep copy (Also you can use JSON.parse(JSON.stringify(options))); but then you'll lose the functions var obj = new o.Constructor(element, $.extend(true, {}, options)); element.data(name, obj); if (obj.init && typeof obj.init === 'function') obj.init(); }); return this; }; })(jQuery); }; /** * @class Fluid.Queue (FIFO) * @memberOf Fluid */ Fluid.Queue = function(){ /** * lst Variable List * @type {Array} */ var lst = []; /** * Returns queue * @return {Array} */ this.getQueue = function(){ return lst; }; /** * Cleans queue * @return {Boolean} */ this.clear = function(){ lst = []; return true; }; /** * Enqueues item to list * @param {any} item * @return {Boolean} for (var i=0; i priority){ break; } auxLst.push(lst.shift()); } auxLst.push({item:item, priority:priority}); for (var i=0; i>lst.length; i++){ auxLst.push(lst[i]); } lst = auxLst; }else{ lst.push({item:item, priority:priority}); } return true; }; /** * Dequeues item from list and returns it * @return {any} */ this.dequeue = function(){ return lst.pop(); }; /** * Destacks item from list and returns it * @return {any} */ this.destack = function(){ return lst.shift(); }; /** * Iterate queue without dequeue it. Each item is lanched by callback * @param {Function} c Callback function * @return {void} */ this.iterate = function(c){ if (c && typeof c === 'function') for (var i = 0; i < lst.length; i++) c(lst[i].item); }; /** * Returns size of list * @return {Integer} */ this.size = function(){ return lst.length; }; }; /** * Create Queue object to queue functions for call on domready * @type {Fluid.Queue} */ Fluid.initQueue = new Fluid.Queue(); /** * Call queued functions on document ready */ jQuery(document).ready(function() { while (Fluid.initQueue.size()) { Fluid.initQueue.destack().item.apply(); } }); //------------------------------------------------------------------------------ // FI. No afegir res al final del document. Posem-ho a on toqui :) //------------------------------------------------------------------------------ ;/** * Classes que extenen de Fluid.Form */ /** * @class Fluid.PackBuyForm * @memberOf Fluid * @extends {Fluid.Form} */ Fluid.PackBuyForm = Fluid.Form.extend({ name : 'PackBuyForm', options : {}, visibleStock : 0, /** * Initialize * @memberOf Fluid.BuyForm */ initialize:function(form){ if(this.el.form.initialized) return; this.el.form.initialized = true; this.trigger('initializeBefore'); this.data = JSON.parse(this.el.$form.attr("data-pack")); this.quantityField = this.el.$form.find('input[data-fluid-field="quantity"]').get(0); this.alternativeImageField = this.el.$form.find('input[data-fluid-field="alternativeImage"]').get(0); this.vinculatedProductsField = this.el.$form.find('input[data-fluid-field="vinculatedProducts"]').get(0); this.el.$buyFormSubmit = this.el.$form.find('button[type="submit"]'); this.callback = this.callback.bind(this); }, getFormData:function(){ return { id:this.data.id, quantity:this.quantityField ? this.quantityField.value : 1, alternativeImage:this.alternativeImageField ? this.alternativeImageField.value : '', vinculatedProducts:this.vinculatedProductsField ? this.vinculatedProductsField.value : '' }; }, submit : function(event) { event.preventDefault(); // Before trigger this.trigger('submitBefore', event); if(!this.el.$form.isValid()) return false; $.post('/basket/addPack/', JSON.stringify([this.getFormData()]), this.callback , 'json'); // Disable buy button this.el.$buyFormSubmit.prop('disabled', true); // Callback trigger this.trigger('submitCallback', event); }, callback:function(result){ // Reload minibasket Fluid.miniBasket.reload(); // Enable buy button this.el.$buyFormSubmit.prop('disabled', false); if(window.TEA && result.response.basket) TEA.updateBasket(result.response.basket); if (Fluid.config.showModalBasket && (settings.isMobile == 1 || window.innerWidth < 992)){ var buttonClass = htmlFramework == 'bootstrap' ? ' btn btn-default btn-block' : 'modalBasketEndOrderButton'; var submitButtonClass = htmlFramework == 'bootstrap' ? ' btn-primary' : ''; var localPath = (settings && settings.checkoutPath)? settings.checkoutPath : "/checkout/basket"; var modalContent = ''; if(result.response.stockLock){ modalContent += '
'+languageSheet.LOCKEDSTOCKREMAININGTIME+'
'+languageSheet.LOCKEDSTOCKEXPIREDTIME+'
'; } modalContent += '' this.el.$buyFormSubmit.box({ uid : 'mobileBasketModal', source: modalContent, showFooter : false, triggerOnClick : false, type : 'text' }); } } }); /** * @class Fluid.BuyForm * @memberOf Fluid * @extends {Fluid.Form} * @description Form extended from Fluid.Form */ Fluid.BuyForm = Fluid.Form.extend({ name : 'buyForm', options : {}, visibleStock : 0, /** * Initialize * @memberOf Fluid.BuyForm */ initialize:function(form){ if(this.el.form.initialized) return; this.el.form.initialized = true; this.el.form.module = this; this.data = JSON.parse(this.el.$form.attr("data-product")); this.quantityField = this.el.$form.find('input[data-fluid-field="quantity"]').get(0); this.alternativeImageField = this.el.$form.find('input[data-fluid-field="alternativeImage"]').get(0); this.vinculatedProductsField = this.el.$form.find('input[data-fluid-field="vinculatedProducts"]').get(0); this.addVinculated = this.el.$form.find('input[data-fluid-field="addVinculated"]').get(0); this.disallowGrid = $(this.el.$form.find('input[name="disallowGrid"]').get(0)).val(); if(!this.disallowGrid){ this.disallowGrid = false; } // Before trigger this.trigger('initializeBefore'); if (!this.quantityField){ this.quantityField = this.el.$form.find('input[name=quantity]').get(0); }else{ this.quantityField = this.el.$form.find('select[name=quantity]').get(0); } this.el.$priceByQuantityBox = this.el.$form.find('div.priceByQuantity'); /*adding 1 unit prices to price by quantity*/ this.data.priceByQuantity.unshift({from:1, optionValueId:0, basePrice:this.data.definition.productBasePrice, retailPrice:this.data.definition.productRetailPrice}); // Stock Alerts var productSubscribe = $('#productSubscribeStock' + this.data.id); //20160701BVFL-01 if (!this.stockSubscriptionForm && productSubscribe.length > 0) { this.stockSubscriptionForm = {}; this.stockSubscriptionForm.$htmlModule = productSubscribe; this.stockSubscriptionForm.$form = productSubscribe.find('Form'); this.stockSubscriptionForm.data = this.stockSubscriptionForm.$form.data('productStock'); } this.productAvailabilities = []; if(this.data.availabilityId && productAvailabilities['availability'+this.data.availabilityId]) this.productAvailabilities = productAvailabilities['availability'+this.data.availabilityId]; this.el.$productOptionAttachment = this.el.$form.find('div.fluidProductOptionAttachment'); this.callback = this.callback.bind(this); this.initOptions(); // Init trigger this.trigger('init'); // Wishlist this.el.$wishlist = this.el.$form.find('[data-wishlist]'); if (this.el.$wishlist) this.wishlist(); // Initialize // Delete wishlist item this.el.$wishlistItems = this.el.$form.find('[data-wishlist-item]'); if (this.el.$wishlistItems.length) this.el.$wishlistItems.on('click', this.deleteWishlistItem.bind(this)); // available discounts this.el.$availableDiscounts = this.el.$form.find('button.productDiscountsButton'); if (this.el.$availableDiscounts) this.el.$availableDiscounts.on('click', this.availableDiscounts.bind(this)); //Init calendar //$(this.el.form).find('input[rel="calendarField"]').ionDatePicker(); var dateFields = this.el.$form.find('div[data-datetimepicker]').each(function(index,el) { var $calendar = $(el); // Options var language = $calendar.data('language'); var format = $calendar.data('format'); var startDate = $calendar.data('startdate'); var endDate = $calendar.data('enddate'); $calendar.datetimepicker({ locale : language ? language : 'en', format : format ? format : 'DD/MM/YYYY', startDate : startDate, endDate : endDate }); }); // Callback trigger this.trigger('initializeCallback'); //Pseudo Buttons this.el.$pseudoSubmits = this.el.$form.find('[data-fluid-formButton="addSpecialProduct"]'); this.el.$pseudoSubmits.on('click', function(e){ e.preventDefault(); this.custom_callback = function(){ $('html,body').animate({ scrollTop: 0 }, 'slow', function(){ window.location.reload(); }); } this.submit(e); }.bind(this)); this.el.$ePointsSubmits = this.el.$form.find('[data-fluid-formButton="ePointsPurchase"]'); this.el.$ePointsSubmits.on('click', [this], function(e){ e.preventDefault(); this.ePointId = $(e.currentTarget).data('fluidEpointspurchase').ePointId; this.submit(e); }.bind(this)); if (typeof pgSDK != "undefined") { try { pgSDK.simulator.reload(pgid); } catch (err) {} } }, /** * Init options * @memberOf Fluid.BuyForm */ initOptions:function() { // Before trigger this.trigger('initOptionsBefore'); // get combination grid quantity inputs this.el.$gridCombinations = this.el.$form.find('input[data-fluid-product-hash][name^=quantity-]'); if(this.el.$productOptionAttachment.length) this.attachmentFields(this.el.$productOptionAttachment); this.el.$gridOption = this.el.$form.find('[data-fluid-grid-options]'); if(this.el.$gridOption.length){ var num = this.el.$gridOption.data('fluid-grid-options'); if (num == 1){ this.el.gridOptionsIds = [this.el.$gridOption.data('fluid-product-option').id]; this.el.gridOptionValues1 = this.el.$form.find('.gridOptionsInfo').data('grid-options1'); } else { this.el.gridOptionsIds = [this.el.$gridOption.data('fluid-product-option').id1,this.el.$gridOption.data('fluid-product-option').id2]; this.el.gridOptionValues1 = this.el.$form.find('.gridOptionsInfo').data('grid-options1'); this.el.gridOptionValues2 = this.el.$form.find('.gridOptionsInfo').data('grid-options2'); } } this.el.$options = this.el.$form.find('select.productOptionSelectValue, input.productOptionRadioValue, input.productOptionCheckboxValue, input.productOptionBooleanValue, input.productOptionTextValue, textarea.productOptionLongTextValue, input.productOptionDateValue'); this.el.$options.change(this.changeOption.bind(this)); this.el.$comments = this.el.$form.find('input.basketProductCommentInput'); this.el.$comments.blur(this.changeOption.bind(this)); this.el.$form.find('img.productOptionValueImage').each( function(a,b){ $(this).click(function(a,b,c){ $(a.target).parent('label').click(); }); }); if (typeof this.quantityField === 'undefined') { this.quantityField = this.el.$form.find('select[name=quantity]').get(0); } $(this.quantityField).change(this.changeQuantity.bind(this)); // Change event quantity /*getting required options*/ this.requiredOptions = []; this.requiredGridOptions = []; for (var option in this.data.options) { if (this.data.options[option].required) { if ([10].indexOf(this.data.options[option].valueType) > -1) { this.requiredOptions.push(this.data.options[option].id); } else { var showAsGrid = this.data.options[option].showAsGrid && !this.disallowGrid; if ([3,4,5,6,7].indexOf(this.data.options[option].valueType) > -1 && !showAsGrid) this.requiredOptions.push(this.data.options[option].id); else if ([3,4,5,6,7].indexOf(this.data.options[option].valueType) > -1 && showAsGrid) this.requiredGridOptions.push(this.data.options[option].id); } } /*adding 1 unit prices to price by quantity*/ for (var key in this.data.options[option].values) { var optionValue = this.data.options[option].values[key]; this.data.priceByQuantity.unshift({from:1, optionValueId:optionValue.id, basePrice:optionValue.basePrice, retailPrice:optionValue.retailPrice}); } } if (this.el.$gridOption.length != 0) { //When there are grid options this.el.$gridOptions = this.el.$form.find('input.productGridQuantityValue'); this.el.$gridOptions.change(this.changeGridOption.bind(this)); this.el.$options.change(this.changeGridOption.bind(this)); } if (this.el.$gridCombinations.length != 0){ //When there are grid combinations if(this.quantityField) this.quantityField.remove(); this.el.$gridCombinations.change(this.changeGridCombinations.bind(this)); this.el.$gridCombinationsType = this.el.$form.find('input[name=gridCombinationsType]'); } this.onChange(true); this.el.$form.find('input.productOptionRadioValue:checked').parent('div.productOptionRadioValue').addClass('productOptionSelected'); this.el.$form.find('input.productOptionCheckboxValue:checked').parent('div.productOptionCheckboxValue').addClass('productOptionSelected'); // Callback trigger this.trigger('initOptionsCallback'); }, /** * Change grid options * @memberOf Fluid.BuyForm * @param {object} eventData */ changeGridOption:function(eventData) { this.trigger('changeOptionBefore'); // Callback trigger this.trigger('changeOptionCallback', eventData.target); this.onChange(); }, /** * Change grid combinations * @memberOf Fluid.BuyForm * @param {object} eventData */ changeGridCombinations:function(eventData) { this.trigger('changeCombinationBefore'); // Callback trigger this.trigger('changeCombinationCallback', eventData.target); this.onChange(); }, /** * Change options * @memberOf Fluid.BuyForm * @param {object} eventData */ changeOption:function(eventData) { // Before trigger this.trigger('changeOptionBefore'); if( $(eventData.target).hasClass('productOptionRadioValue') ) { $(eventData.target).parents('div.productOptionValues').find('div.productOptionRadioValue').removeClass('productOptionSelected'); $(eventData.target).parent('div.productOptionRadioValue').addClass('productOptionSelected'); } if( $(eventData.target).hasClass('productOptionCheckboxValue') ) { if(eventData.target.checked) $(eventData.target).parent('div.productOptionCheckboxValue').addClass('productOptionSelected'); else $(eventData.target).parent('div.productOptionCheckboxValue').removeClass('productOptionSelected'); } if( $(eventData.target).hasClass('productOptionAttachmentValue') ) this.uploadFile(eventData.target); // Callback trigger this.trigger('changeOptionCallback', eventData.target); this.onChange(true); }, /** * Change quantity * @memberOf Fluid.BuyForm * @param {object} eventData */ changeQuantity:function(eventData) { var quantityValue = $(this.quantityField).val(); // Before trigger this.trigger('changeQuantityBefore'); this.quantityField.value = quantityValue; // Callback trigger this.trigger('changeQuantityCallback', {quantity:quantityValue}); this.onChange(true); }, /** * Get form values * @memberOf Fluid.BuyForm */ getFormValues:function() { var formValues; if (this.el.$options.length) { /*product detail (options in form)*/ formValues = this.el.$options.serializeArray(); } else { /*list of products (default options selection)*/ formValues = []; var selectedOptions = []; /*getting first available combination*/ if (settings.stockManagement && this.data.definition.stockManagement) { for (var key in this.data.stocks) { if (this.data.stocks[key] > 0) { var optionValues = key.split('_'); if (optionValues.length == 1) { break; } optionValues = optionValues[1].split('-'); for (var i=0; i 0) totalQty += qty; } } for(var i=0; i 0) { stockMatch = '(' + availableWarehouses + ')+_'; } if (validateCombinationStock) { for (var key in this.data.combinations) { if ( key.match('PC_'+selectedStockValues+'$') ) { sku = this.data.combinations[key].sku; ean = this.data.combinations[key].ean; combinationId = this.data.combinations[key].id; break; } } if (settings.stockManagement && this.data.definition.stockManagement) { stock = 0, backorderPrevision = 0, combinationFound = false; for (var key in this.data.stocks) { if ( key.match(stockMatch+selectedStockValues+'$') ) { if(stockKeys.indexOf(key) == -1) stockKeys.push(key); // Collect used stock keys stock += this.data.stocks[key]; combinationFound = true; } } var emptyStock = stock == 0; // adding stock previsions for (i=0;i retailPrice /**&& retailPrice > 0**/) { price = retailPrice; alternativePrice = alternativeRetailPrice; this.el.$form.find('.product-basePrice').show(); this.el.$form.find('.product-alternativeBasePrice').show(); this.el.$form.find('.product-saving').show(); var saving = basePrice-retailPrice; this.el.$form.find('.product-saving .price').html( outputFormattedCurrency(saving) ); this.el.$form.find('.product-saving .percent').html( (saving*100/basePrice).toFixed(0) ); } else { price = basePrice; alternativePrice = alternativeBasePrice; this.el.$form.find('.product-basePrice').hide(); this.el.$form.find('.product-alternativeBasePrice').hide(); this.el.$form.find('.product-saving').hide(); } this.el.$form.find('.product-price .price').html( outputFormattedCurrency(price) ); this.el.$form.find('.product-alternativePrice .price').html( outputFormattedCurrency(alternativePrice) ); this.el.$form.find('.product-basePrice .price').html( outputFormattedCurrency(basePrice) ); this.el.$form.find('.product-alternativeBasePrice .price').html( outputFormattedCurrency(alternativeBasePrice) ); if (stock >= 0) { this.el.$form.find('.product-stock .stock').html(stock); if (stock > 0) { this.el.$form.find('.product-stock').removeClass('no-stock').addClass('stock-ok').show(); if (stock == 1) { this.el.$form.find('.product-stock .stock').html(stock); this.el.$form.find('.stockText').html(languageSheet.STOCKSINGULAR.replace("%stock%", stock)); } else { this.el.$form.find('.product-stock .stock').html(stock); this.el.$form.find('.stockText').html(languageSheet.STOCKPLURAL.replace("%stock%", stock)); } if (stockPrevisionIncomingDate) { var elStockPrevisionIncomingDate = this.el.$form.find('.product-stock .stockPrevisionIncomingDate'); if (elStockPrevisionIncomingDate) { elStockPrevisionIncomingDate.html(moment(stockPrevisionIncomingDate).format(settings.dateFormat.toUpperCase())); } } } else { this.el.$form.find('.product-stock').removeClass('stock-ok').addClass('no-stock').show(); this.el.$form.find('.stockText').html(languageSheet.STOCKNONE.replace("%stock%", stock)); } } else { this.el.$form.find('.product-stock').hide(); } if (sku.length > 0) this.el.$form.find('.product-combinations-sku').html(sku); if (ean.length > 0) this.el.$form.find('.product-combinations-ean').html(ean); /*getting availability interval*/ var availabilityInterval; for (var i=this.productAvailabilities.length-1; i>-1; i--) { if ( this.productAvailabilities[i].stock < stock) break; availabilityInterval = this.productAvailabilities[i]; } /*printing availability*/ if (availabilityInterval) { this.el.$form.find('.product-stock .availabilityImage').html(''); this.el.$form.find('.product-stock .availabilityName').html(availabilityInterval.name); this.el.$form.find('.product-stock .availabilityDescription').html(availabilityInterval.description); } else { this.el.$form.find('.product-stock .availabilityImage').hide(); this.el.$form.find('.product-stock .availabilityName').hide(); this.el.$form.find('.product-stock .availabilityDescription').hide(); } // Buy Button properties var buyButtonProps = {}; var displaySubscription = null; if('countdown' in this) this.countdown.destroy(); this.el.$form.find('.fluidStockLock').removeClass('visible'); this.el.$form.find('.fluidStockLockText').empty(); var lsBUY = languageSheet.BUY; if(this.el.$gridCombinationsType && this.el.$gridCombinationsType.val() == 'update'){ lsBUY = languageSheet.UPDATE; } if (requiredOptions.length) { buyButtonProps.className = 'selectOption'; buyButtonProps.name = languageSheet.SELECTOPTION.replace('%option%', this.data.options['id'+requiredOptions[0]].name); buyButtonProps.disabled = true; displaySubscription = 'none'; } else if (!validateCombinationStock && totalQty==0) { // grid options buyButtonProps.className = 'selectOption'; buyButtonProps.name = languageSheet.SELECTOPTION.replace('%option%', this.data.options['id'+this.requiredGridOptions[0]].name); buyButtonProps.disabled = true; displaySubscription = 'none'; } else if(this.data.definition.onRequest){ // onRequest products will be always available buyButtonProps.className = 'buy'; buyButtonProps.name = lsBUY; buyButtonProps.disabled = false; displaySubscription = 'none'; } else if (stock < 0) { buyButtonProps.className = 'notAvailable'; buyButtonProps.name = languageSheet.NOTAVAILABLE; buyButtonProps.disabled = true; displaySubscription = 'none'; } else if (stock == 0 || quantityValue > stock) { if(settings.reserveAllowed && this.data.definition.backorder){ if((this.data.definition.backorder == 2 && (backorderPrevision+stock) >= quantityValue) || (this.data.definition.backorder == 1 || this.data.definition.backorder == 3)){ // allow reserve buyButtonProps.className = 'reserve'; buyButtonProps.name = languageSheet.RESERVE; buyButtonProps.disabled = false; }else{ // disallow reserve buyButtonProps.className = 'notAvailable'; buyButtonProps.name = languageSheet.NOTAVAILABLE; buyButtonProps.disabled = true; if (baseStockForSubscription && stock == 0) displaySubscription = 'block'; else displaySubscription = 'none'; } if (baseStockForSubscription && stock == 0) displaySubscription = 'block'; else displaySubscription = 'none'; } else { buyButtonProps.className = 'notAvailable'; buyButtonProps.name = languageSheet.NOTAVAILABLE; buyButtonProps.disabled = true; if (baseStockForSubscription && stock == 0) displaySubscription = 'block'; else displaySubscription = 'none'; } } else if(stock-lockedStock <= 0){ buyButtonProps.className = 'notAvailable reserved'; buyButtonProps.name = languageSheet.STOCKRESERVED; buyButtonProps.disabled = true; displaySubscription = 'none'; this.el.$form.find('.fluidStockLock').addClass('visible'); if(lockedStockExpiration){ this.countdown = new Fluid.combinationCountDown({endDate:lockedStockExpiration.expires, quantity:lockedStockExpiration.quantity}); this.el.$form.find('.fluidStockLockText').append( this.countdown.$container ); } else{ this.el.$form.find('.fluidStockLockText').append( languageSheet.STOCKRESERVEDUSERTEXT ); } } else { buyButtonProps.className = 'buy'; buyButtonProps.name = lsBUY; buyButtonProps.disabled = false; displaySubscription = 'none'; } this.el.$buyFormSubmit = this.el.$form.find('button[type="submit"]'); this.updateButton(this.el.$buyFormSubmit, buyButtonProps); // show ePoints prices for(var i=0; i= 0 ? epointsPrices[i].price : 0); additionalBuyFormSubmit = this.el.$form.find('button[type="submit"].ePointsBuyFormSubmit' + epointsPrices[i].ePointId); // disable button if((!this.data.userEpoints || !this.data.userEpoints['ePoint_'+epointsPrices[i].ePointId] || !this.data.userEpoints['ePoint_'+epointsPrices[i].ePointId].AVAILABLE) || (additionalBuyFormSubmit && !additionalBuyFormSubmit.attr('disabled') && (epointsPrices[i].price <= 0 || this.data.userEpoints['ePoint_'+epointsPrices[i].ePointId].AVAILABLE < (epointsPrices[i].price * quantityValue))) ){ this.updateButton(additionalBuyFormSubmit, {className:'notEnoughEpoints', name:(epointsPrices[i].price <= 0 ? languageSheet.NOTAVAILABLE : languageSheet.NOTENOUGHEPOINTS.replace(/%%/g, '%').replace('%ePoints%', epointsPrices[i].name)), disabled:true}); } } this.enabledButtons = this.el.$buyFormSubmit.filter(':enabled'); if (this.stockSubscriptionForm) this.stockSubscriptionForm.$htmlModule.css('display', displaySubscription); this.updateEpointsView(price); this.updatePriceByQuantity(selectedValues); var offsetContainer = this.el.$form.find('.productOffsetMessage').get(0), stcStockOffset = {}; if(offsetContainer && stockKeys.length && warehousesStructures.length){ $(offsetContainer).html(''); var acumulatedStock = 0, offsetDays = 0, requestOffset = 0, previsionDate = new Date(), productData = this.data; if(this.data.definition.onRequest) requestOffset = this.data.definition.onRequestDays; $.each(warehousesStructures, function(i, wStructure){ for(i=0;i offsetDays) offsetDays = wStructure.offsetDays; } } if(acumulatedStock >= quantityValue){ return false; // left loop } } }); previsionDate.setDate(previsionDate.getDate()+offsetDays); if(acumulatedStock < quantityValue){ // We need to use the previsions var auxPrevisionDate = new Date(); productData.stockPrevisions.sort(function(a,b){ return new Date(a.incomingDate) > new Date(b.incomingDate) }) // sort the previsions by the incoming date $.each(productData.stockPrevisions, function(i, prevision){ for(i=0;i 0){ acumulatedStock += prevision.stock; offsetDays = stcStockOffset[prevision.warehousesStructureId] || offsetDays; auxPrevisionDate = new Date(prevision.incomingDate); } if(acumulatedStock >= quantityValue){ return false; // left loop } } }); auxPrevisionDate.setDate(auxPrevisionDate.getDate()+offsetDays); if(auxPrevisionDate > previsionDate) previsionDate = auxPrevisionDate; } if(acumulatedStock < quantityValue && settings.reserveAllowed && this.data.definition.backorder){ // We need to use the backorder previsions if we have them var auxPrevisionDate = new Date(); productData.backorderPrevisions.sort(function(a,b){ return new Date(a.incomingDate) > new Date(b.incomingDate) }) // sort the previsions by the incoming date $.each(productData.backorderPrevisions, function(i, prevision){ for(i=0;i 0){ acumulatedStock += prevision.stock; offsetDays = stcStockOffset[prevision.warehousesStructureId] || offsetDays; auxPrevisionDate = new Date(prevision.incomingDate); } if(acumulatedStock >= quantityValue){ return false; // left loop } } }); auxPrevisionDate.setDate(auxPrevisionDate.getDate()+offsetDays); if(auxPrevisionDate > previsionDate) previsionDate = auxPrevisionDate; } if(acumulatedStock >= quantityValue && previsionDate.setHours(0,0,0,0) > new Date().setHours(0,0,0,0)){ var formattedDate = moment(previsionDate).format(settings.dateFormat.toUpperCase()); $(offsetContainer).html(languageSheet.WAREHOUSEOFFSETMESSAGE.replace('%offsetDays%', formattedDate).replace('%previsionDate%', formattedDate)); } else if(acumulatedStock < quantityValue && requestOffset) $(offsetContainer).html(languageSheet.ONREQUESTPRODUCTMESSAGE.replace('%days%', requestOffset)); } // Callback Pmt if exists if (settings.showTaxInclude == 0) var sendPrice = alternativePrice * quantityValue; else var sendPrice = price * quantityValue; this.getPagaMasTarde(sendPrice, this.data.id); this.updateSequra(sendPrice, this.data.id); this.updateAplazame(sendPrice, this.data.id); if(this.data.restrictions && this.data.restrictions.length) { this.setOptionRestrictions(); } // Callback trigger this.trigger('onChangeCallback', { price: price, basePrice: basePrice, requiredOptions: requiredOptions, selectedOptions: selectedOptions, stock: stock, quantity: quantityValue, stockKeys: stockKeys }); }, setOptionRestrictions:function() { var form = this.el.$form; var getField = function(valueId) { return form.find('*[value='+valueId+']'); }; var getChecked = function(valueId) { var field = getField(valueId).first(); return field.length ? field[0].checked || field[0].selected : false; }; var disableField = function(valueId) { var field = getField(valueId); var ind,i,k; if(!field) return; field.addClass('_restricted_').attr('disabled',1).css('display','none').removeAttr('checked'); if(field.parents('tr.productOptionValueTable').length == 1){ field.parents('tr.productOptionValueTable').css('display','none').removeClass('productOptionSelected'); } else if(field[0].tagName.toLowerCase()!='option') parentNode = field.parent('.productOptionValue').css('display','none').removeClass('productOptionSelected'); }; var disableOption = function(optionId) { var option = form.find('.productOption'+optionId) option.addClass('_restricted_').css('display','none'); option.find('select').addClass('_restricted_').attr('disabled',1).attr('selectedIndex',-1); //option.find('option').addClass('_restricted_').attr('disabled',1).attr('selected',0); option.find('input.productOptionRadioValue').addClass('_restricted_').attr('disabled',1).removeAttr('checked').parent('.productOptionRadioValue').removeClass('productOptionSelected'); }; /*reset all options*/ form.find('._restricted_').removeClass('_restricted_').removeAttr('disabled').css('display','').css('display','').each( function(index, field){ if(field.tagName.toLowerCase()!='option') { $(field).parent('.productOptionValue').css('display',''); if($(field).parents('tr.productOptionValueTable').length == 1){ $(field).parents('tr.productOptionValueTable').css('display',''); } } } ); if(this.data.restrictionsMain && this.data.restrictionsMain.length) { for(var ind=0; ind pricesArray[i].retailPrice && pricesArray[i].retailPrice != 0) price = pricesArray[i].retailPrice; table += ''+label+''+outputFormattedCurrency(price)+''; } table += ''; this.el.$priceByQuantityBox.html(table).show(); }, getPrices:function( optionValues ) { optionValues = optionValues || []; optionValues.unshift(0); var prices = {}; for (var i=0; i -1 ) { prices['p'+priceData.from] = prices['p'+priceData.from] || {from:priceData.from, basePrice:0, retailPrice:0}; } } for (var key in prices) { for (var i=0; i-1 ; i--) { if (this.data.priceByQuantity[i].from > from) continue; if (this.data.priceByQuantity[i].optionValueId != optionValueId) continue; return this.data.priceByQuantity[i]; } return {from:from, basePrice:0, retailPrice:0}; }, /** * Get form data * @memberOf Fluid.BuyForm */ getFormData:function() { var formValues = this.getFormValues(); var options = {}, optionsArray = []; for(var i=0; i 0) { response.gridValues = {}; this.el.$gridOptions.each(function(i,e) { var val = $(e).val(); if (val.length == 0) val = 0; response.gridValues[$(e).attr('name')] = val; }); response.gridOptionsIds = this.el.gridOptionsIds; response.gridOptionValues1 = this.el.gridOptionValues1; if (this.el.gridOptionValues2) { response.gridOptionValues2 = this.el.gridOptionValues2; } } if (this.el.$gridCombinations.length > 0) { response.gridCombinationsValues = {}; this.el.$gridCombinations.each(function(i,e) { response.gridCombinationsValues[$(e).attr('name')] = parseInt($(e).val()); }); } return response; }, /** * Submit event * @memberOf Fluid.BuyForm * @param {object} event */ submit : function(event) { event.preventDefault(); // Before trigger this.trigger('submitBefore', event); if(!this.formIsValid()) return false; var data = this.getFormData(); // Before submit this.pluginListener('onAddProduct', event, data); // Send form $.post('/basket/addProduct/', JSON.stringify([data]), this.callback , 'json'); // Disable buy button this.el.$buyFormSubmit.prop('disabled', true); // Callback trigger this.trigger('submitCallback', event); }, formIsValid : function() { if(!this.el.$form.isValid()) return false; if (this.el.$gridCombinationsType && this.el.$gridCombinationsType.val() == 'buy') { var sumCombination = 0; this.el.$gridCombinations.each(function(i,e) { sumCombination += parseInt($(e).val()); }); if (sumCombination === 0) return false; } return true; }, /** * Callback * @memberOf Fluid.BuyForm */ callback:function(result) { //refresh chat this.updateChatBasket(result); // Callback trigger this.trigger('callbackBefore', result.response); var bodyClasses = $('body').attr('class') if(this.addVinculated && this.addVinculated.value.toString() == "true" && (bodyClasses.indexOf('fluidContent-basket') != -1 || bodyClasses.indexOf('fluidContent-paymentAndShipping') != -1)){ $('html,body').animate({ scrollTop: 0 }, 'slow', function(){window.location.reload();} ); } // Reload minibasket Fluid.miniBasket.reload(); if(window.TEA && result.response.basket) TEA.updateBasket(result.response.basket); //reload OSC if buying from OSC switch(location.pathname){ case '/checkout': case '/checkout/oneStepCheckout': fluidOneStepCheckout.moduleCalls('refreshModule'); } // Enable buy button this.enabledButtons.prop('disabled', false); if (this.el.$gridCombinations.length > 0) { var qtText = 'quantity-'; this.el.$gridCombinations.each(function(i,e) { var $e = $(e); var inputData = JSON.parse($e.attr('name').substring(qtText.length)); this.updateCombinationsFields([inputData.productHash], parseInt($e.val())); }.bind(this)); totalProdsInBasket = this.getCombinationsFormTotalQuantity(); this.updateCombinationsFormType(totalProdsInBasket); } // Callback trigger this.trigger('callback', result.response); if (Fluid.config.showModalBasket && (settings.isMobile == 1 || window.innerWidth < 992)){ var buttonClass = htmlFramework == 'bootstrap' ? ' btn btn-default btn-block' : 'modalBasketEndOrderButton'; var submitButtonClass = htmlFramework == 'bootstrap' ? ' btn-primary' : ''; var localPath = (settings && settings.checkoutPath)? settings.checkoutPath : "/checkout/basket"; var modalContent = ''; if(result.response.stockLock){ modalContent += '
'+languageSheet.LOCKEDSTOCKREMAININGTIMEPOPUP+'
'+languageSheet.LOCKEDSTOCKEXPIREDTIMEPOPUP+'
'; } modalContent += '' this.el.$buyFormSubmit.box({ uid : 'mobileBasketModal', source: modalContent, showFooter : false, triggerOnClick : false, type : 'text' }); } }, /** * updateCombinationsFields method * @memberOf Fluid.BuyForm * @param {array} hashes * @param {numeric} value */ updateCombinationsFields : function(hashes, value){ if(hashes.length){ $('[id="buyForm' + this.data.id + '"]').each(function(index, buyForm) { var qtText = 'quantity-'; if(buyForm.module.el.$gridCombinations.length){ buyForm.module.el.$gridCombinations.each(function(index, inputCombination) { var $inputCombination = $(inputCombination); var hash = $inputCombination.data("fluidProductHash"); if($.inArray(hash, hashes) != -1){ var inputData = JSON.parse($inputCombination.attr('name').substring(qtText.length)); inputData.quantity = value; $inputCombination.attr('name', qtText + JSON.stringify(inputData)); $inputCombination.val(value); } }); } }); } }, /** * getCombinationsFormTotalQuantity method * @memberOf Fluid.BuyForm */ getCombinationsFormTotalQuantity : function(){ var totalQuantity = 0; this.el.$gridCombinations.each(function(i,e) { totalQuantity += parseInt($(e).val()); }); return totalQuantity; }, /** * updateCombinationsFormType method * @memberOf Fluid.BuyForm * @param {numeric} totalProdsInBasket */ updateCombinationsFormType : function(totalProdsInBasket){ var getCombinationsFormType = function(totalProdsInBasket){ if(totalProdsInBasket > 0) return 'update'; return 'buy'; } if(totalProdsInBasket == null){ totalProdsInBasket = this.getCombinationsFormTotalQuantity($('#buyForm' + this.data.id).get(0)); } $('[id="buyForm' + this.data.id + '"]').each(function(index, buyForm) { if(buyForm.module.el.$gridCombinationsType){ buyForm.module.el.$gridCombinationsType.val(getCombinationsFormType(totalProdsInBasket)); buyForm.module.onChange(); } }); }, wishlist: function() { // Before trigger this.trigger('wishlistBefore'); var $this = this.el.$wishlist; var type = $this.data('wishlist'); switch(type) { case 'accountRequired': $this.box({ uid : 'wishlistAccountRequiredModal', showFooter : false, source : '
'+languageSheet.WISHLISTACCOUNTREQUIRED+'
', type : 'text', showClose : false, size : 'small', callback : 'wishlistAccountRequired' }); break; case 'setWishlist': var data = $this.data('wishlistData'); $this.on('click', function(event) { $this.attr('disabled', 'disabled'); var data = $this.data('wishlistData'); var typeSetWishlist = data.type; /*blueknow*/ if (data.type == 'add' && window.BlueknowTracker) BlueknowTracker.trackExamined(data.itemId); if (data.type == 'add') data.type = 'remove'; else data.type = 'add'; // Post $.post( '/user/setWishlist/', JSON.stringify({type: typeSetWishlist, itemId:data.itemId, itemType:data.itemType}), this.wishlistCallback.bind(this, data, $this), "json"); }.bind(this)); break; } }, wishlistCallback: function(data, $this, dataResult, textStatus, xhr) { $this.removeAttr('disabled'); if (dataResult.response && dataResult.response.SUCCESS) { var isInput = $this[0].nodeName.toLowerCase() == "input"; //Update data $this.data('wishlistData', data); // Classes and label if (data.type == 'remove') { var label = data.labelAdded; $this.addClass('wishlistButtonAdded wishlistButtonRemove'); this.showMessage(languageSheet.WISHLISTADDED, 'success'); } else { var label = data.labelRemoved; $this.removeClass('wishlistButtonAdded wishlistButtonRemove'); this.showMessage(languageSheet.WISHLISTDELETED, 'danger'); } // Change label if (data.showLabel) { if (isInput) $this.val(label); else $this.text(label); } } // Callback trigger this.trigger('wishlistCallback', data, $this, dataResult, textStatus, xhr); }, deleteWishlistItem: function(event) { event.preventDefault(); // Before trigger this.trigger('deleteWishlistItemBefore'); $.post('/user/setWishlist/', JSON.stringify({type:'remove', itemId:this.data.id, itemType:1}), this.deleteWishlistItemCallback.bind(this), "json"); }, deleteWishlistItemCallback: function(data, textStatus, xhr) { // Callback trigger if (!this.trigger('deleteWishlistItemBefore')) { window.location.reload(); } }, availableDiscounts: function(event) { event.preventDefault(); var $this = this.el.$availableDiscounts; $this.attr('disabled', 'disabled'); // Before trigger this.trigger('availableDiscountsBefore'); $this.box({ uid: 'modalAvailableDiscounts', triggerOnClick: false, showFooter: false, source: '/product/discounts/', type: 'url', params: {productId:this.data.id} }); $this.removeAttr('disabled'); }, attachmentFields: function(element){ var me=this; this.target = element; var parentDiv = this.target.parents('div.productOption').get(0); this.targetOptionId = $(parentDiv).data('fluidProductOption').id; if(!this.target) return; this.options = {}; this.options = JSON.parse(element.attr("data-options")); if(this.options.minValues > this.options.maxValues) { var aux = this.options.maxValues; this.options.maxValues = this.options.minValues; this.options.minValues = aux; } if(this.options.maxValues == 0) this.options.maxValues = 100; this.fieldName = element.attr("data-optionValue"); this.createUploadField = function(){ if (me.options.maxValues > 0 && me.target.parent().find('div.productOptionAttachedValue').length >= me.options.maxValues) { this.showMessage(languageSheet.VALIDMAX + ' ' + me.options.maxValues, 'danger'); return; } else { var div = $('
', { class:me.options.className, style:'position: absolute; top: 0; right: 0; cursor: pointer; opacity: .01;' }).appendTo(me.target); var input = $('', { type:'file', class:me.options.className, autocomplete:'off', }).on('change', me.changeOption.bind(this)).appendTo(div); //To enable changeOption events, 'change' redirects to changeOption instead to uploadFile directly } } this.deleteFile = function(field){ field.remove(); if (me.options.maxValues > me.target.parent().find('div.productOptionAttachedValue').length) { me.createUploadField(); } if (me.options.minValues == 0 || me.options.minValues > me.target.parent().find('div.productOptionAttachedValue').length) { // re-add the option as required me.requiredOptions.push(me.targetOptionId); me.onChange(); } } this.uploadFile = function(field){ field.setAttribute('name', 'file'); var id = "frame" + new Date().getMilliseconds(); var frame = $('