{"version":3,"sources":["../../dev/j/product-home-v11.js"],"names":["detectInitScreen","window","getComputedStyle","document","body","getPropertyValue","setStickyHeight","screenSize","stickyHeight","sysReqOsVer","version","ua","navigator","userAgent","toLowerCase","supportedVersions","detect","avm","require","os","isWindows","i","length","name","indexOf","Abdata","cache","options","pricelistApi","avastGlobals","web","RootPath","pricelistApiB","vatLocales","init","this","$","extend","cacheDelimiter","xhrPool","abortAll","each","idx","jqXHR","abort","getPriceData","createCacheId","parameters","elem","el","data","p","collectAjaxParams","_","abtype","internalId","campaign","maintenance","computers","lic","appendix","priceData","params","ajaxParams","priceLink","cacheId","paramQuery","match","multiyear","avast","locale","campaignMarker","apiHash","installments","provider","selectFromCache","trigger","ajax","type","url","dataType","context","beforeSend","push","success","parseData","error","textStatus","errorThrown","internalid","additional2","delim","abDataInstance","re","RegExp","updateCache","products","cId","replace","maintenanceLimits","computersLimits","priceInNumber","price","priceFormatted","realPriceInNumber","stripDecimals","realPrice","precision","realPriceFormatted","totalPrice","getTotalPrice","$this","key","prices","min","parseInt","parseFloat","quant","_price","_quant","_vat","vat","link","foreignId","flatDiscount","discount","discountType","minQuantity","maxQuantity","priceFormat","currency","currencySymbol","thousandSeparator","decimalSeparator","number","regex","toString","Number","getDataByInternalId","props","cacheData","test","id","index","priceList","JSON","parse","dataset","pricelist","console","log","Actionbox","defaults","abProductsSelector","overlaySelector","abBoxSelector","autoLoadData","installmentTemplate","customCurrency","currencySwitch","opts","build","on","proxy","loopBoxes","countTimeout","abEl","find","first","preRender","handleKeyPress","updateInputs","updateInputsData","pullData","append","resetInputs","boxClass","box","closest","valEl","valContent","text","isEmpty","trim","priceEqual","addClass","parent","removeClass","get","fn","abdata","evt","msg","nextBox","root","fillData","filter","boxInternalId","boxInternalIdObj","buildInternalId","internalIdToObj","currentMaintenance","nextMaintenance","removeData","formatedData","pcs","mainInternalId","priceDivider","pricing","val","seats","formatPrice","installmentPrice","realPriceTotal","priceyTypo","typoPrice","typoPriceParts","split","markupPrice","join","customId","renderData","renderValue","decSep","thSep","formatedPrice","number_format","numberOfDecimals","symbol","cssSelector","attr","findClass","has","html","yrs","current","currentTarget","siblings","newVal","pcsString","pad","btn","clearTimeout","updateInternalIds","num","size","s","newId","idObj","_idObj","map","prop","idParts","renewal","prodEl","prefix","c","lastIndexOf","allowedValues","max","limits","values","len","counting","setTimeout","speed","maxSpeed","speedup","inputId","input","increase","hasClass","originalEvent","preventDefault","countIndex","call","off","updateCount","count","triggerMsg","_clearTimeout","message","updatePrice","Array","prototype","fun","TypeError","t","Object","res","thisArg","arguments","searchElement","fromIndex","undefined","Math","abs","Infinity","create","obj","F","ready","ab","actionbox","apply","abconfig","osVer","hide","show","e","sysreq","sh","outerHeight","h","height","css","min-height","animate","fadeOut","fadeIn","selfParent","nextExpandBox","nextAll","slideUp","slideDown","numberPattern","divider","noDiscount","discountText","noDiscountText","discountPrice","noDiscountPrice"],"mappings":"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","file":"product-home-v11.js","sourcesContent":["/**\n * Pricing API request.\n *\n * @version 0.10.1\n * @author Ales Gabriel\n * @requires jquery\n * @copyright Avast Software s.r.o\n */\n\nvar Abdata = {\n cache : {},\n options: {\n pricelistApi: avastGlobals.web.RootPath + 'api/v2/pricing/business-pricelist?',\n pricelistApiB: avastGlobals.web.RootPath + 'api/v2/pricing/pricelist?',\n // These regions has prices with VAT\n vatLocales: {}\n },\n\n /**\n * init Merge options with defaults, build ajax pool and start ajax\n * @param {Object} options Options\n * @return {Object} Abdata instance\n */\n init: function(options){\n this.options = $.extend({}, this.options, options);\n this.cache = {};\n this.cacheDelimiter = ',';\n\n // Ajax pool\n if(typeof $.xhrPool === 'undefined'){\n $.xhrPool = [];\n\n $.xhrPool.abortAll = function() {\n $.each(this, function(idx, jqXHR) {\n jqXHR.abort();\n });\n };\n }\n // initial price data\n this.getPriceData();\n\n return this;\n },\n\n /**\n * createCacheId Generate cacheId\n * @param {Object} parameters InternalId and other data\n * @return {String} Cache key\n */\n createCacheId: function(parameters){\n var elem = this.options.el,\n data = elem ? elem.data() : null,\n p = (parameters) ? parameters : this.collectAjaxParams(data),\n _ = this.cacheDelimiter,\n cacheId;\n\n if (p.abtype === 'multiyear') {\n cacheId = p.internalId + '-' + p.campaign + _ + p.maintenance + _;\n } else {\n cacheId = p.internalId + '-' + p.campaign + _ + p.maintenance + _ + p.computers + _ + p.lic + _ + p.appendix;\n }\n\n return cacheId;\n },\n\n /**\n * getPriceData Collect parameters and send AJAX request or read from cache.\n */\n // TODO: How about accept additional parameter here, which point to the element from which to collect AJAX params?\n getPriceData: function(el){\n var elem = el || this.options.el,\n data = elem ? elem.data() : null,\n params = this.ajaxParams = this.collectAjaxParams(data),\n priceLink = (params.abtype === 'multiyear') ? this.options.pricelistApi : this.options.pricelistApiB, // TODO : Update condition and path according to v2 API\n cacheId = this.createCacheId(params),\n priceData,\n paramQuery ='productId=' + params.internalId.match(/[^-]*-[^-]*/) +\n '&internalId=' + params.internalId +\n '&maintenance=' + params.multiyear +\n '&seats=' + params.computers +\n '&locale=' + avast.locale +\n '&campaignMarker=' + params.campaignMarker +\n '&platform=web' +\n '&h=' + params.apiHash;\n\n if (params.installments) {\n paramQuery += '&installments=' + params.installments;\n }\n if (params.campaign) {\n paramQuery += '&campaign=' + params.campaign;\n }\n if (params.provider) {\n paramQuery += '&provider=' + params.provider;\n }\n\n // make ajax call\n //console.log(\"cacheId: %s\", cacheId);\n //console.log(\"cache: %o\", this.cache);\n\n if(!this.cache[cacheId]){\n $.ajax({\n type: \"GET\",\n url: priceLink + paramQuery,\n dataType: \"json\",\n context: this,\n beforeSend: function(jqXHR){\n //$.xhrPool.abortAll(); // Kill all pending requests\n $.xhrPool.push(jqXHR);\n },\n success: function(data){\n this.parseData(cacheId, data);\n priceData = this.selectFromCache(cacheId);\n $(elem).trigger('data.ab.avast', [priceData ? 'data sent' : 'no data', priceData]);\n },\n error: function(jqXHR, textStatus, errorThrown){\n if(textStatus !== \"abort\"){\n $(elem).trigger('data.ab.avast', ['ajax error', textStatus, errorThrown]);\n }\n }\n });\n } else {\n priceData = this.selectFromCache(cacheId);\n $(elem).trigger('data.ab.avast', [priceData ? 'data sent' : 'no data', priceData]);\n }\n },\n\n /**\n * collectAjaxParams Read jQuery.data from element\n * data {Object} parameters for AJAX request\n * @return {Object} Ajax parameters\n */\n collectAjaxParams: function(data){\n var params = {};\n\n if(data){\n params = {\n abtype : (typeof data.abtype === 'string' && data.abtype.indexOf('business') > -1) ? 'multiyear' : '', // Can be solved only with different XML structure?\n internalId : data.internalid || '',\n campaign : data.campaign || '',\n maintenance : data.maintenance || '12', // Maintenance should be skipped if multiyear is called\n computers : data.computers || '1',\n lic : data.lic || '1',\n appendix : '', // TODO: This polute cacheId with hypen on the end\n multiyear : data.multiyear || '12,24,36',\n provider : data.provider || null,\n installments: data.installments || null,\n additional2 : data.additional2 || null,\n apiHash : data.apiHash || null,\n campaignMarker : data.campaignMarker || 'WDS'\n };\n }\n return params;\n },\n\n /**\n * parseData Convert data from AJAX response to object\n * @param {String} cacheId Cache key\n * @param {Object} data JSON data\n */\n parseData: function(cacheId, data){\n // parsing should create\n var delim = this.cacheDelimiter,\n abDataInstance = this,\n re = new RegExp(this.cacheDelimiter + '(.+?)' + this.cacheDelimiter);\n\n /*\n * Update cache with new cacheId, put empty object as value.\n * If request is correct, it will be replaced with approp data.\n * Creating cacheId - even from incorrect ID - prevents calling AJAX requests repeatedly.\n */\n abDataInstance.updateCache(cacheId, {});\n\n if(data && !data.products) {\n // HOME\n $.each(data, function() {\n var cId = cacheId.replace(re, delim + this.maintenance + delim);\n\n this.maintenanceLimits = [12,24,36];\n this.computersLimits = [1, 3, 5, 10];\n this.priceInNumber = '' + this.price;\n this.price = this.priceFormatted;\n this.realPriceInNumber = '' + abDataInstance.stripDecimals(this.realPrice, this.precision);\n this.realPrice = this.realPriceFormatted;\n this.totalPrice = abDataInstance.getTotalPrice(this.internalId);\n\n abDataInstance.updateCache(cId, this);\n });\n } else if (data.products && data.products.length !== 0) {\n // BUSINESS\n $.each(data.products, function() {\n // Update cacheId\n var priceData = {};\n var price = [];\n var realPrice = [];\n var $this = $(this)[0];\n var cId = cacheId.replace(re, delim + $this.maintenance + delim);\n\n for (var key in $this.prices) {\n price.push({\n 'min': parseInt(key, 10),\n 'price' : parseFloat($this.prices[key])\n });\n realPrice.push({\n 'min': parseInt(key, 10),\n 'price' : parseFloat($this.prices[key])\n });\n }\n\n priceData.price = function(quant){\n var _quant = parseInt(quant, 10),\n _vat = (data.vat && abDataInstance.options.vatLocales[avast.locale]) ? data.vat : 1,\n _price;\n\n for (var i = 0; price.length > i; i++){\n if(_quant >= price[i].min){\n _price = price[i].price;\n }\n }\n return _price * _quant * _vat;\n };\n priceData.realPrice = function(quant){\n var _quant = parseInt(quant, 10),\n _vat = (data.vat && abDataInstance.options.vatLocales[avast.locale]) ? data.vat : 1,\n _price;\n\n for (var i = 0; realPrice.length > i; i++){\n if(_quant >= realPrice[i].min){\n _price = realPrice[i].price;\n }\n }\n return _price * _quant * _vat;\n };\n priceData.link = function(quant){\n return data.link.replace('{PID}', $this.foreignId).replace('{QUANT}', quant);\n };\n //priceData.discount = $this.attr('real-discount');\n priceData.flatDiscount = data.discount; // Flat discount not related to number of devices\n priceData.discountType = data.discountType;\n priceData.minQuantity = data.minQuantity;\n priceData.maxQuantity = data.maxQuantity;\n priceData.maintenance = $this.maintenance;\n priceData.maintenanceLimits = [12,24,36];\n priceData.priceFormat = data.priceFormat;\n priceData.currency = data.currencySymbol;\n priceData.thousandSeparator = data.thousandSeparator;\n priceData.decimalSeparator = data.decimalSeparator;\n priceData.precision = data.precision;\n priceData.priceFormat = data.priceFormat;\n\n abDataInstance.updateCache(cId, priceData);\n });\n } else {\n var msg = 'no data';\n $(elem).trigger('data.ab.avast', [msg]);\n }\n },\n\n /**\n * stripDecimals Remove additional decimals over precision limit\n * @param {number} number A number to be stripped\n * @param {integer} precision Number of decimals in returned float\n * @return {number} Stripped number\n */\n stripDecimals: function(number, precision){\n var decimalSeparator = '\\\\.',\n regex = new RegExp(\"^-?\\\\d+(?:\" + decimalSeparator + \"\\\\d{0,\" + precision + \"})?\");\n\n if (precision) {\n number = number.toString().match(regex)[0];\n }\n\n return Number(number);\n },\n\n /**\n * updateCache Store data in cache to specific key\n * @param {String} cacheId Cache key\n * @param {Object} data Price data\n */\n updateCache: function(cacheId, data){\n this.cache[cacheId] = data;\n },\n\n /**\n * Get price data from cache\n * @param {String} cacheId Unique identifier. Look to createCacheId method from what is created.\n * @return {Object} Price data\n */\n selectFromCache : function(cacheId){\n return this.cache[cacheId];\n },\n\n /**\n * getDataByInternalId Select all matched entries in cache. Match can be partial.\n * @param {String} internalId Internal ID of product\n * @param {Object} props Additional properties which can modify cache ID identificator (campaign, maintenance, pcs, etc.)\n * @return {Array} Price objects\n */\n getDataByInternalId : function(internalId, props){\n var cache = this.cache,\n params = $.extend({}, {internalId: internalId}, props),\n ajaxParams = this.collectAjaxParams(params),\n cacheId = this.createCacheId(ajaxParams),\n cacheData = this.selectFromCache(cacheId),\n re = new RegExp('^' + internalId),\n data = [];\n\n if(props) {\n if(cacheData){\n data.push(cacheData);\n }\n } else {\n for(var key in cache){\n // console.log('Match: %s', re.test(key))\n if(re.test(key)) {\n data.push(cache[key]);\n }\n }\n }\n\n return data;\n },\n /**\n * getTotalPrice Collect prices from data attributes.\n * @description Method assumes there is a `data-pricelist` attribute in the markup \n * with prices without installment divider. Pricelist should expose all seats prices for maintenance variant.\n * @param {string} id InternalId\n * @return {string} Price\n */\n getTotalPrice: function(id) {\n var price = null;\n\n $('[data-pricelist]').each(function(index) {\n var priceList;\n\n try {\n priceList = JSON.parse(this.dataset.pricelist);\n } catch(error) {\n console.log(error);\n }\n\n if (priceList && priceList[id]) {\n price = priceList[id].realPriceFormatted;\n }\n });\n\n return price;\n }\n};\n\n/**\n * Actionbox object: Product Actionbox with prerendered prices.\n *\n * @version 0.4.0\n * @author Ales Gabriel\n * @copyright Avast Software s.r.o ©2016\n * @requires src/j/producthome/product-home-abdata.js\n *\n */\n\nvar Actionbox = {\n defaults: {\n abProductsSelector : '[data-internalid]', // Context element selector\n overlaySelector : '#overlay', // Dim page with this element.\n abBoxSelector : '.box', // boxes class \n autoLoadData : false, // Request AJAX price data with first render. It will rewrite prices, links which are set in html \n installments : 0,\n installmentTemplate : '',\n customCurrency : '',\n currencySwitch : ''\n },\n /**\n * Init plugin and register global listeners\n * @param {Object} opts Config options\n * @param {DOM Node} elem Element where plugin is initiated \n */\n init: function(opts, elem){\n this.options = $.extend({},this.defaults,opts);\n this.build(elem);\n\n // Register default events\n $(document).on('data.ab.avast', $.proxy(this.loopBoxes, this));\n },\n /**\n * Register UI events, open and call for price data\n * @param {Event} evt Event called for popup \n */\n build: function(elem){\n // Count timeout\n this.countTimeout = '';\n\n // If custom template replace default popup with different element\n this.context = $(elem);\n // abEl can be in elements on which actionbox is initialized, but must have data-internalid set. \n // Or can be any first-child with data-internalid set.\n this.abEl = this.context.data('internalid') ? this.context : this.context.find('[data-internalid]').first();\n\n // Prerender\n this.preRender();\n \n // Register close events \n $(document).on('keydown.ab.avast', $.proxy(this.handleKeyPress, this));\n\n // Register button events\n this.abEl.find('.add:not(.disabled)').on('mousedown.ab.avast', $.proxy(this.updateInputs, this));\n this.abEl.find('.add:not(.disabled)').on('mouseup.ab.avast', $.proxy(this.updateInputsData, this));\n\n // Only if it is autoLoadData ask for data during with build. Otherwise wait for user interaction. \n if(this.options.autoLoadData){\n this.pullData();\n }\n },\n /**\n * Correct display, reset inputs.\n */\n preRender : function() {\n // Prerender\n this.abEl.append('
');\n this.resetInputs();\n var boxClass = this.options.abBoxSelector;\n\n // Hide Regular price label if price missing or price is same as price. \n this.abEl.find('.no-discount').each(function(){\n var $this = $(this),\n box = $this.closest(boxClass),\n valEl = $this.find('.value'),\n valContent = valEl.text(),\n isEmpty = !$.trim(valContent),\n priceEqual = ($(box).find('a.button > span').text() === valContent ) ? 1 : 0;\n \n if(isEmpty || priceEqual) {\n $this.addClass('hidden');\n }\n });\n\n // Disable selector plus/minus buttons if there is only one PC option to select\n if(this.abEl.data('computers-limits') && this.abEl.data('computers-limits').length === 1){\n this.abEl.find('.select .add').addClass('disabled'); \n }\n },\n /**\n * pullData Ask for data \n * @return {[type]} [description]\n */\n pullData: function(){\n var opts = this.options || {}\n // DOM changes - Add spinner\n // TODO: move to own function \n this.abEl.addClass('spinning');\n this.abEl.find('.box .button').addClass('spinning');\n this.abEl.parent('div').find('.ab-overlay').removeClass('hidden');\n\n // Ask for data. \n if($.data(this.abEl.get(0), 'abdata')){\n this.abEl.data('abdata').getPriceData();\n } else {\n // If no instance of abdata on element, revoke abdata plugin initialization.\n if(typeof $.fn.abdata === 'function'){\n opts.el = this.abEl;\n this.abEl.abdata(opts);\n }\n }\n },\n /**\n * loopBoxes Incrementaly loop boxes, create specific cacheId and call for price data update.\n * @param {Event} evt Internal data.ab.avast event\n * @param {String} msg Message from event\n * @param {Object} data Prices, links, formats etc.\n */\n loopBoxes: function(evt, msg, data){\n\n var nextInternalId,\n nextBox;\n\n if(data && data.maintenance) {\n var root = this;\n // load prices, links etc. to current box\n this.fillData(evt, msg, data);\n // TODO: Try harder to indentify next box.\n // This doesn't work if some maintanence box is missing ... check siblings in DOM or something like this\n // Prepare next maintenance\n this.abEl.data('maintenance', parseInt(data.maintenance, 10) + 12);\n \n nextBox = this.abEl.find('[data-internalid]').filter(function(){\n var boxInternalId = $(this).data('internalid');\n var nextInternalId = root.buildInternalId(boxInternalId, {maintenance: parseInt(data.maintenance, 10) + 12});\n\n var boxInternalIdObj = root.internalIdToObj(boxInternalId);\n var currentMaintenance = boxInternalIdObj.maintenance;\n var nextMaintenance = parseInt(data.maintenance, 10) + 12;\n \n // return $(this).data('internalid') === nextInternalId;\n return parseInt(currentMaintenance, 10) === nextMaintenance;\n });\n\n if($.data(this.abEl.get(0), 'abdata') && nextBox.length > 0){\n // Ask for data only if next box exists\n this.pullData();\n } else {\n // Publish price update is finished\n \n $(document).trigger('priceUpdate.ab.avast', ['actionbox prices updated']);\n }\n this.abEl.removeData('maintenance');\n }\n },\n\n /**\n * fillData Update DOM with data\n * @param {Event} evt Internal data.ab.avast event\n * @param {String} msg Message from event\n * @param {Object} data Prices, links, formats etc. \n */\n // TODO: Last param should be last.\n fillData: function(evt, msg, data) {\n var formatedData = {},\n pcs = this.abEl.find('#computers'),\n mainInternalId = this.abEl.data('internalid'),\n root = this,\n itemInternalId,\n context,\n priceDivider = (this.options.pricing === 'monthly' && data && data.maintenance) ? data.maintenance : 1,\n currencySymbol = data.currencySymbol ? data.currencySymbol : data.currency;\n\n if (data){\n // Reduce input values to min/max if set.\n if(data.minQuantity){\n if(parseInt(pcs.val(), 10) <= parseInt(data.minQuantity, 10)) {\n pcs.val(data.minQuantity);\n }\n }\n if(data.maxQuantity){\n if(parseInt(pcs.val(), 10) >= parseInt(data.maxQuantity, 10)){\n pcs.val(data.maxQuantity);\n }\n }\n\n // TODO: Where to triger validation message HAS_PRICE = 1\n\n // Computers quantity in input\n var quant = pcs.val();\n\n // Prices\n formatedData.link = (typeof data.link === 'function') ? data.link(quant) : data.link;\n formatedData.realPrice = (typeof data.realPrice === 'function') ? data.realPrice(quant) : data.realPrice;\n formatedData.price = (typeof data.price === 'function') ? data.price(quant) : data.price;\n formatedData.discount = data.discount;\n formatedData.totalPrice = data.totalPrice;\n formatedData.seats = pcs.val();\n\n // Formating prices\n if(typeof data.price === 'function'){\n formatedData.price = this.formatPrice(formatedData.price, data.priceFormat, data.currency, data.precision, data.decimalSeparator, data.thousandSeparator);\n formatedData.realPrice = this.formatPrice(formatedData.realPrice, data.priceFormat, data.currency, data.precision, data.decimalSeparator, data.thousandSeparator);\n }\n\n // Formating installments prices\n if(this.options.installments){\n var installmentPrice = this.formatPrice((data.realPriceInNumber) , data.priceFormat, currencySymbol, data.precision, data.decimalSeparator, data.thousandSeparator);\n formatedData.realPriceTotal = formatedData.realPrice;\n formatedData.realPrice = this.options.installmentTemplate.replace('#p', this.options.installments) + installmentPrice;\n }\n\n if(this.options.priceyTypo){\n var typoPrice = this.formatPrice((data.realPriceInNumber / priceDivider) , data.priceFormat, currencySymbol, data.precision, data.decimalSeparator, data.thousandSeparator);\n typoPrice = typoPrice.replace(' ', '');\n\n var typoPriceParts = typoPrice.split(data.decimalSeparator);\n var markupPrice = [];\n \n // Open price wrapper\n markupPrice.push('');\n // Paste currency before price\n if(typoPrice.indexOf(currencySymbol) === 0){\n markupPrice.push('' + currencySymbol + '');\n }\n // Paste price\n markupPrice.push('' + typoPriceParts[0].replace(currencySymbol, '') + '');\n \n // Decimal price if any\n if(typoPriceParts[1]){\n markupPrice.push('' + data.decimalSeparator + typoPriceParts[1].replace(currencySymbol, '') + '');\n } \n // Paste currency symbol after price \n if(typoPrice.indexOf(currencySymbol) !== 0){\n markupPrice.push('' + currencySymbol + '');\n }\n // Close price wrapper\n markupPrice.push('');\n \n formatedData.realPriceTotal = formatedData.realPrice;\n formatedData.realPrice = markupPrice.join('');\n }\n\n if(this.options.pricing === 'monthly'){\n formatedData.link = formatedData.link.replace(/\\/CustomID.(.*?)\\//, '/CustomID.' + this.options.customId + '/');\n }\n\n // Set only data values, leave DOM data attributes without change.\n if(data.computersLimits && !this.abEl.data('computers-limits')){\n this.abEl.data('computers-limits', data.computersLimits);\n }\n if(data.maintenanceLimits && !this.abEl.data('maintenance-limits')){\n this.abEl.data('maintenance-limits', data.maintenanceLimits);\n }\n if(data.minQuantity){\n this.abEl.data('min-quantity', data.minQuantity);\n }\n if(data.maxQuantity){\n this.abEl.data('max-quantity', data.maxQuantity);\n }\n \n if(data.maintenance && mainInternalId){\n itemInternalId = this.buildInternalId( mainInternalId, {maintenance: parseInt(data.maintenance, 10)});\n // Get context element by comparing maintenance in internalId for each box and data.maintenance \n context = this.abEl.find('[data-internalid]').filter(function(){\n var boxInternalId = $(this).data('internalid'),\n boxInternalIdObj = root.internalIdToObj(boxInternalId),\n currentMaintenance = boxInternalIdObj.maintenance,\n nextMaintenance = parseInt(data.maintenance, 10);\n\n return parseInt(currentMaintenance, 10) === nextMaintenance;\n });\n }\n \n if(context){\n this.renderData(context, formatedData);\n }\n }\n },\n /**\n * renderData Update DOM with changes\n * @param {DOMElement} context Ancestor element\n * @param {Object} formatedData Data to render\n */\n renderData: function(context, formatedData){\n // Render prices and link values\n this.renderValue('.button > span', context, formatedData.realPrice);\n this.renderValue('.discounted > span:first-child', context, formatedData.realPrice);\n this.renderValue('.discount', context, formatedData.realPriceTotal);\n this.renderValue('.no-discount', context, (formatedData.discount) ? formatedData.price : '');\n this.renderValue('.save', context, formatedData.discount);\n this.renderValue('.button', context, formatedData.link, 'href');\n this.renderValue('.cart', context, formatedData.link, 'href');\n this.abEl.removeClass('spinning');\n this.abEl.find('.box .button').removeClass('spinning');\n this.abEl.find('.ab-overlay').addClass('hidden');\n this.renderValue('.no-installments', context, (formatedData.totalPrice ? formatedData.totalPrice : ''));\n this.renderValue('.cart', context, formatedData.seats, 'data-seats');\n },\n //WUT\n /**\n * formatPrice Format price with currency, correct precision, decimal thousand separator and currency\n * @param {[type]} price [description]\n * @param {[type]} priceFormat [description]\n * @param {[type]} currency [description]\n * @param {[type]} precision [description]\n * @param {[type]} decSep [description]\n * @param {[type]} thSep [description]\n * @return {String} Price with correct format with currency\n */\n formatPrice: function(price, priceFormat, currency, precision, decSep, thSep){\n var formatedPrice;\n\n if(typeof $().number_format === 'function') {\n formatedPrice = $().number_format(price,\n {\n numberOfDecimals: precision,\n decimalSeparator: decSep,\n thousandSeparator: thSep,\n symbol: \"\"\n });\n }\n if(formatedPrice){\n return priceFormat.replace(\"#c\",currency).replace(\"#p\",formatedPrice);\n }\n },\n /**\n * renderValue Output specific value to DOM. If Element has child with css class \".value\", value will be rendered in this child. \n * @param {[type]} cssSelector Element selector\n * @param {DOMElement} context Search for cssSelector in specified context \n * @param {String} val Value \n * @param {String} attr Load value to element attribute\n */\n renderValue: function(cssSelector, context, val, attr){\n var elem = (cssSelector) ? $(context).find(cssSelector) : '';\n if(val){\n elem.removeClass('hidden');\n // Update attributes \n if (attr && attr !== 'class') {\n elem.attr(attr, val);\n } else if (attr && attr === 'class'){\n elem.removeClass(this.findClass(elem, 'avast-').join(''));\n elem.addClass(val);\n } else {\n if(elem.has('.value').length > 0){\n elem.find('.value').html(val);\n } else {\n elem.html(val);\n }\n }\n } else {\n elem.addClass('hidden');\n }\n },\n /**\n * [updateInputsData description]\n * @param {Event} evt Mouse event when encrease, decrease pcs or maintenance \n */\n updateInputsData: function(evt) {\n var pcs = this.abEl.find('#computers'),\n yrs = this.abEl.find('#maintenance'),\n current = ($(evt.currentTarget).siblings('.amount').find('#computers').length > 0) ? pcs : yrs,\n newVal = parseInt(current.val(), 10), // TODO: value based on minQuantity, maxQuantity\n newIndex,\n pcsString = this.pad(pcs.val(), 3),\n btn = $(evt.currentTarget);\n\n // Break if custom behavior\n if(btn.data('behavior') === 'custom'){\n return;\n }\n\n // Stop event input updates.\n clearTimeout(this.countTimeout);\n\n \n if(current === yrs){\n if(parseInt(newVal, 10) >= 12){\n // Convert months to years\n newVal = parseInt(newVal, 10) / 12;\n } else {\n // Months are not currently in use.\n }\n }\n\n // Update data with value from input \n this.abEl.data('computers', pcs.val());\n \n // Inputs and data config done. Call for prices.\n if(evt.type === 'mouseup' || (evt.type === 'mouseout' && btn.data('flag-outbound') === 'mouseout')){\n btn.removeData('flag-outbound');\n $(document).trigger('quantityChange.avast:ab');\n this.updateInternalIds({pcs: pcsString});\n this.pullData();\n }\n },\n //WUT\n /**\n * pad Leading zeros\n * @param {Number} num Number to which add leading zeros\n * @param {Number} size From what size prepend zeros\n * @return {String} [description]\n */\n pad: function(num, size) {\n var s = num+\"\";\n while (s.length < size) s = \"0\" + s;\n return s;\n },\n /**\n * updateInternalIds Loop elements with data-internalid attribute and update its internalId. \n * @param {Objec} props Properties to be updated ( Available props: name | version | pcs | maintenance | renewal )\n */\n updateInternalIds: function(props){\n var root = this;\n\n /** \n * There must be internalId updated for home.\n * But mustn't be updated for business.\n */\n var context = (this.abEl.data('abtype') !== 'business') ? this.abEl.parent() : this.abEl;\n\n context.find('[data-internalid]').each(function(){\n var $this = $(this);\n var newId = root.buildInternalId($this.data('internalid'), props);\n $this.data('internalid', newId);\n });\n },\n\n //WUT\n /**\n * buildInternalId Build new internal ID by merge former internalid and props from parameter\n * @param {String} id Internal ID to update \n * @param {Object} props Properties to be updated ( Available props: name | version | pcs | maintenance | renewal )\n * @return {String} New Internal ID\n */\n buildInternalId: function(id, props){\n var newId,\n idObj = this.internalIdToObj(id),\n _idObj = {};\n if(props){\n $.extend(_idObj, idObj, props);\n }\n newId = $.map(_idObj, function(prop){return prop;}).join('-');\n \n return newId;\n },\n\n //WUT\n /**\n * internalIdToObj description\n * @param {String} internalId Internal ID (eg. ISE-08-001-12-MR).\n * @return {Object} Internal ID converted to object\n */\n internalIdToObj: function(internalId){\n var idObj = {},\n idParts = internalId.split('-');\n\n // TODO: This one only works for new internalId strings format (eg. ISE-08-001-12-MR). \n idObj.name = idParts[0];\n idObj.version = idParts[1];\n idObj.pcs = idParts[2];\n idObj.maintenance = idParts[3];\n idObj.renewal = idParts[4];\n\n return idObj;\n },\n\n /**\n * resetInputs Set elements data to default values PCs: 1, Maintenance: 12\n */\n resetInputs: function(){\n var pcs = this.abEl.find('#computers'),\n yrs = this.abEl.find('#maintenance'),\n prodEl = this.abEl;\n\n pcs.val(1);\n yrs.val(1);\n\n // Change data\n prodEl.data('computers', 1);\n prodEl.data('maintenance', 12);\n if(prodEl.data('internalid-default')){\n prodEl.data('internalid', prodEl.data('internalid-default'));\n }\n\n // Enable disabled buttons\n this.abEl.find('.add.disabled').removeClass('disabled');\n },\n //WUT\n /**\n * findClass Find class by prefix\n * @param {DOMElement} el In Element\n * @param {String} prefix Search for prefix \n * @return {Boolean} \n */\n findClass: function(el, prefix) {\n var classes = $(el).attr(\"class\").split(\" \").filter(function(c) {\n return c.lastIndexOf(prefix, 0) === 0;\n });\n return classes;\n },\n //WUT\n /**\n * allowedValues Return allowed values in selector. Limits higher importance over min, max \n * @param {Number} min Minimal value\n * @param {Number} max Maximal value\n * @param {Array} limits Ordering has holes - send exact values in Array\n * @return {Array}\n */\n allowedValues: function(min, max, limits){\n var values = [],\n len = (min && max) ? max - min + 1 : false;\n\n if(!limits && len){\n for(var i = 0; len > i; i++){\n values.push(min + i);\n }\n } else {\n values = limits;\n }\n return values;\n },\n\n /**\n * updateInputs Button click handler. Manage increase/decrease on inputs and update data attributes\n * @param {Event} evt Mouse event\n */\n updateInputs: function(evt){\n var btn = $(evt.currentTarget),\n speed = 300, // Initial speed of counting\n speedup = 0.5, // next loop will be shorter then previous about this amount\n maxSpeed = 50, // max speed in which counting is repeated (in miliseconds) \n root = this,\n inputId = btn.closest('.select').find('input').attr('id'),\n input = this.abEl.find('#' + inputId),\n increase = (btn.hasClass('plus')) ? 1 : -1;\n\n\n var min = parseInt(this.abEl.data('min-quantity'), 10),\n max = parseInt(this.abEl.data('max-quantity'), 10),\n limits = (inputId === 'computers') ? this.abEl.data('computers-limits') : this.abEl.data('maintenance-limits'),\n // Create array from min max, or limits.\n values = this.allowedValues(min, max, limits);\n\n // Break if custom behavior\n if($(evt.currentTarget).hasClass('disabled')){\n return;\n }\n \n if(typeof evt.originalEvent.preventDefault === \"function\"){\n evt.originalEvent.preventDefault(); // Disable Chrome set cursor to text while dragging\n }\n\n if(values) {\n maxSpeed = 150; // Slowdown max speed if values are limited. \n this.countIndex = values.indexOf((inputId === 'computers') ? parseInt(input.val(), 10) : parseInt(input.val(), 10) * 12);\n } else {\n this.countIndex = (inputId === 'computers') ? parseInt(input.val(), 10) : parseInt(input.val(), 10) * 12;\n }\n\n // bind/unbind mouseout event on each attempt\n if (btn.data('flag-outbound') !== 'mouseout'){\n btn.on('mouseout.ab.avast', function(evt){\n clearTimeout(root.countTimeout);\n root.updateInputsData.call(root, evt);\n btn.off('mouseout.ab.avast');\n btn.removeData('flag-outbound');\n });\n btn.data('flag-outbound', 'mouseout');\n }\n\n counting(function(){\n root.updateCount(values, root.countIndex, inputId, increase, min, max);\n });\n\n // Update speed of incrementing \n function counting(fn){\n fn();\n root.countTimeout = setTimeout(function(){counting(fn);}, speed);\n speed = (speed > maxSpeed) ? speed * speedup : maxSpeed;\n }\n },\n /**\n * updateCount Make changes to DOM data attributes and input values on each counting step\n * @param {Array} values Array of allowed values, which can be dispalyed in selector\n * @param {Integer} countIndex Index of allowed value, which have to be displayed\n * @param {String} inputId Identify which selector should be updated\n * @param {Integer} increase 1|-1\n */\n updateCount: function(values, countIndex, inputId, increase, min, max){\n var msg;\n // Counting in virtual steps\n if(values){\n if((countIndex + increase) >= 0 && (countIndex + increase) < values.length){\n this.countIndex = countIndex + increase;\n } else {\n msg = (countIndex === 0) ? 4 : 3;\n if(msg === 4) {\n this.countIndex = values.length - 1;\n }\n if (msg === 3) {\n this.countIndex = 0;\n }\n }\n this.abEl.find('#' + inputId).val((inputId === 'computers') ? values[this.countIndex] : values[this.countIndex] / 12);\n // Plain increment\n } else {\n var input = this.abEl.find('#' + inputId);\n var count = parseInt(input.val(), 10) + increase;\n // TODO: check why stops working if counting under zero !!\n if(count > 0){\n input.val(count);\n }\n if(count > max ) {\n msg = 3;\n }\n if(count <= min ) {\n msg = 4;\n }\n }\n // Triger validation message here TOO_MANY = 3, TOO_SMALL = 4. and decide what to do\n // TODO: Can be performance expensive to trigger event here.\n // On the other hand this is the right place to publish message, that limit was reached, buttons can be disabled and so.\n // Other solution could be set min, max variables besides limits and check it only when user release mouse \n // But it should looks wierd to count in different steps until limit is reached and then follow with incrementing by 1.\n if(msg){\n this.triggerMsg('validation.avast', msg);\n }\n },\n _clearTimeout: function(){\n clearTimeout(this.countTimeout);\n },\n /**\n * triggerMsg Publish event on document \n * @param {String} type Event type\n * @param {String} msg Event message\n */\n triggerMsg: function (type, msg){\n $(document).trigger(type, [{message: msg}]);\n },\n /**\n * updatePrice Facade code for $('#abox-home-boxes').ab('updatePrice');\n * @return {[type]} [description]\n */\n updatePrice: function (){\n var opts = this.options || {};\n if(typeof $.fn.abdata === 'function'){\n opts.el = this.abEl;\n this.abEl.abdata(opts);\n }\n // TODO !!! or use this.pullData();\n }\n};\n\n///////////////////////////////////////////////////////////////////\n\n// Array.prototype.filter polyfill\nif (!Array.prototype.filter)\n{\n Array.prototype.filter = function(fun /*, thisArg */) {\n\n if (this === void 0 || this === null)\n throw new TypeError();\n\n var t = Object(this);\n var len = t.length >>> 0;\n if (typeof fun !== \"function\")\n throw new TypeError();\n\n var res = [];\n var thisArg = arguments.length >= 2 ? arguments[1] : void 0;\n for (var i = 0; i < len; i++)\n {\n if (i in t)\n {\n var val = t[i];\n \n if (fun.call(thisArg, val, i, t))\n res.push(val);\n }\n }\n\n return res;\n };\n}\n\n// Array.prototype.indexOf polyfill\nif (!Array.prototype.indexOf) {\n Array.prototype.indexOf = function (searchElement, fromIndex) {\n if ( this === undefined || this === null ) {\n throw new TypeError( '\"this\" is null or not defined' );\n }\n\n var length = this.length >>> 0; // Hack to convert object.length to a UInt32\n\n fromIndex = +fromIndex || 0;\n\n if (Math.abs(fromIndex) === Infinity) {\n fromIndex = 0;\n }\n\n if (fromIndex < 0) {\n fromIndex += length;\n if (fromIndex < 0) {\n fromIndex = 0;\n }\n }\n\n for (;fromIndex < length; fromIndex++) {\n if (this[fromIndex] === searchElement) {\n return fromIndex;\n }\n }\n\n return -1;\n };\n}\n\n// Object create\nif (typeof Object.create !== 'function') {\n Object.create = function (obj) {\n function F(){}\n F.prototype = obj;\n return new F();\n };\n}\n\n// Init Abdata and actionbox jQuery plugins\n$(document).ready(function() {\n\n // Enable popup actionboxes\n $.fn.ab = $.fn.actionbox = function(options){\n if (this.length > 0) {\n if(Actionbox[options] && $(this).data('actionbox')){\n // TODO: support legacy code $('#abox-home-boxes').ab('updatePrice'); \n $(this).data('actionbox')[options].apply($(this).data('actionbox'));\n return;\n }\n if(typeof options === 'object' || !options){\n return this.each(function(){\n var actionbox = Object.create(Actionbox);\n actionbox.init(options, this);\n\n $.data(this, 'actionbox', actionbox);\n });\n }\n }\n };\n\n // Load price data plugin\n $.fn.abdata = function(options){\n if (this.length > 0) {\n return this.each(function(){\n var abdata = Object.create(Abdata);\n abdata.init(options);\n\n $.data(this, 'abdata', abdata);\n });\n }\n };\n\n \n // Init actionbox\n // Call directly on actionbox wrapper -> $('#abox-home-boxes-v10').actionbox() and find #main internally.\n // Actually do not rely on #main, but look for the first element with data-internalid attribute set. \n // Sken not only childs but also root element itself for data-internalid attribute.\n var abconfig = {};\n\n if($('#abox-home-color-v10').length > 0){\n abconfig.priceyTypo = true;\n }\n\n if($('#abox-home-color-v10 [data-pricing=\"monthly\"]').length > 0){\n abconfig.priceyTypo = true;\n abconfig.pricing = 'monthly';\n abconfig.customId = 'PPMONTH';\n }\n\n if(locale === 'pt-br'){\n abconfig.installments = 3;\n abconfig.priceyTypo = false;\n }\n\n // Init actionboxes\n // Standard actionbox\n $('#abox-home-boxes-v10').actionbox(abconfig);\n // actionbox 2015\n $('#abox-home-color-v10').actionbox(abconfig);\n});\n\n/**\n * PRODUCT HOME COMMON\n */\n\n // Top height\nfunction detectInitScreen(){\n var scrn = (window.getComputedStyle) ? window.getComputedStyle(document.body,':after').getPropertyValue('content') : '';\n return scrn;\n}\nfunction setStickyHeight() {\n var screenSize = detectInitScreen();\n var stickyHeight = 72;\n if (screenSize == 'mobile'){\n stickyHeight = 0;\n }\n if (screenSize == 'tablet') {\n stickyHeight = 0;\n }\n return stickyHeight;\n}\n\n$(document).ready(function() {\n var osVer = sysReqOsVer();\n \n if(!osVer){\n $('#sysreq .supported').hide();\n $('#sysreq .not-supported').show();\n }\n // toggle sysreq \n $('.sysreq-toggle-link').on('click', function(e){\n e.preventDefault();\n var sysreq = $('#sysreq');\n var sh = sysreq.outerHeight();\n var h = sh - $('#sysreq .supported').outerHeight() + $('#sysreq .not-supported').height();\n \n sysreq.css({'min-height' : sh + 'px'});\n sysreq.animate({'min-height' : h}, 200);\n $('#sysreq .supported').fadeOut(300, function(){\n $('#sysreq .not-supported').fadeIn(300);\n });\n });\n\n if(osVer){\n $('#sysreq .sysreq-os-ver').text(osVer);\n }\n});\n\n\nfunction sysReqOsVer(){\n var ua = navigator.userAgent.toLowerCase();\n var supportedVersions = ['XP', 'Vista', '7', '8', '10'];\n var version;\n var detect = avm.require('avast.detect')();\n\n if(typeof detect === 'object' && detect.os.isWindows){\n for(var i = 0; supportedVersions.length > i; i++){\n if(detect.os.version === supportedVersions[i]){\n version = detect.os.name + ' ' + detect.os.version;\n }\n }\n }\n \n if(ua.indexOf(' arm;') > -1){\n return false;\n }\n\n return version;\n}\n\n// Custom function for animation on page\n(function () {\n 'use strict';\n var jsExpandLinkSpan = $('.js-expand-link span');\n jsExpandLinkSpan.on('click', function () {\n var selfParent = $(this).parent(),\n nextExpandBox = selfParent.nextAll('.js-expand-box');\n if (selfParent.hasClass('active')) {\n selfParent.removeClass('active');\n nextExpandBox.first().slideUp();\n } else {\n selfParent.addClass('active');\n nextExpandBox.first().slideDown();\n }\n });\n})();\n\n// FIX WCS-1003: Show price without discount if differs from discounted price\n(function () {\n 'use strict';\n\n $('.box[data-internalid]').each(function(i){\n var box = $(this),\n numberPattern = /\\d+/g,\n discount = box.find('.discounted'),\n divider = box.find('.divider'),\n noDiscount = box.find('.no-discount'),\n discountText = divider.text() + discount.text(),\n noDiscountText = noDiscount.text(),\n discountPrice = discountText ? discountText.match(numberPattern) : null,\n noDiscountPrice = noDiscountText ? noDiscountText.match(numberPattern) : null;\n\n if(discountPrice && noDiscountPrice){\n if(discountPrice.join('') !== noDiscountPrice.join('')){\n noDiscount.removeClass('hidden');\n }\n }\n });\n})();\n"]}