/* * Main.js OpenShop custom javascript. For external javascript, edit site.json and add the uri. */ var OpenShop = { // vars name: "OpenShop javascript library", version: "1.15", instanceid: 1e5, messagecode: 1e5, csp: ["Access-Control-Allow-Origin","*"], tinyEvents: function(ev) { switch(ev) { case 'categories': document.addEventListener("DOMContentLoaded", categoryEvents); break; case 'navigation': document.addEventListener("DOMContentLoaded", navigationEvents); break; } return; }, xhr: function() { var objxml = null; var ProgID = ["Msxml2.XMLHTTP.6.0", "Msxml2.XMLHTTP.3.0", "Microsoft.XMLHTTP"]; try { objxml = new XMLHttpRequest(); } catch (e) { for (var i = 0; i < ProgID.length; i++) { try { objxml = new ActiveXObject(ProgID[i]); } catch (e) { continue; } } } return objxml; }, message: function(str) { window.alert(this.htmlspecialchars(str,'full') + '\n' + '-'.repeat(32) + '\n' + '#TS-MSGC-' + this.messagecode); if(this.messagecode < this.math('maxint')) { this.messagecode++; } }, htmlspecialchars: function(str,method='full',encoding='utf-8') { switch(method) { case 'full': f = ['<','>','!','$','%','\'','(',')','*','+',':','=','`','{','}','[',']']; r = ['<','>','"','$','%',''','(',')','*','+',':','=','`','{','}','[',']']; break; case 'uri': f = ['<','>','\'']; r = ['<','>',''']; break; } for (var i = 0; i < f.length; i++) { str = String(str).replace(f[i], r[i]); } return str; }, duplicatearray: function(a,b) { a.length = 0; a.push.apply(a, b); return a; }, redirect: function(uri,dir=0) { if(dir==1) { window.reload(); } else { if(!uri) { document.location = OpenShop.htmlspecialchars(location.href,'uri'); } else { document.location = OpenShop.htmlspecialchars(uri,'uri'); } } }, math: function(method,e=1,mod=1) { var result; let i = 0; switch(method) { case 'int': if(mod > 1) { while(mod > i) { this.math('int',e,mod); this.result = parseInt(e); mod--; } } else { this.result = parseInt(e); } break; case 'float': this.result = parseFloat(e); break; case 'fixed': this.result = e.toFixed(mod); break; case 'rand': this.result = Math.random(1,Number.MAX_SAFE_INTEGER); break; case 'maxint': this.result = Number.MAX_SAFE_INTEGER; break; case 'uuid': this.result = Math.random().toString(16).slice(2, 10); break; } return this.result; }, rnd: function(method='rand',e=null,len=null,seed=null) { let r = null; switch(method) { case 'rand': this.r = Math.random(1,Number.MAX_SAFE_INTEGER); break; case 'uuid': this.r = Math.random().toString(16).slice(2, 14); break; case 'bytes': this.r = Math.random(); break; } return this.r; }, togglecartmsg: function(method) { if(method == 'open') { this.dom('ts-shop-result-message','display','block'); } else if(method =='close') { this.dom('ts-shop-result-message','display','none'); } else { this.dom('ts-shop-result-message','display','inline-block'); } }, toggle: function(id, counter) { for (i = 0; i < counter; i++) { try { this.dom('toggle' + i,'display','none'); this.dom('cat' + i,'fontWeight','100'); } catch (e) { continue; } } this.dom('toggle' + id,'display','block'); this.dom('cat' + id,'fontWeight','bold'); }, dom: function(id,method,value='') { try { if(id) { switch(method) { case 'get': return document.getElementById(id).value; break; case 'set': document.getElementById(escape(id)).value = this.htmlspecialchars(value,'full'); break; case 'html': document.getElementById(escape(id)).innerHTML = this.htmlspecialchars(value,'full'); break; case 'gethtml': document.getElementById(escape(id)).innerHTML; break; case 'display': document.getElementById(id).style.display = value; break; case 'fontWeight': document.getElementById(id).style.fontWeight = value; break; case 'className': document.getElementById(escape(id)).style.fontWeight = this.htmlspecialchars(value,'full'); break; } } else { this.message('DOM constructor could not populate the requested action.'); } } catch(e) { //this.message(this.htmlspecialchars(e,'full')); } }, returner: function(data) { window.alert(this.htmlspecialchars(data,'full')); return this.htmlspecialchars(data,'full'); }, json: function(uri) { OpenShop.fetchJSON(uri,function(response) { var obj = JSON.parse(response); return obj; }); }, caller: function(action,method,opts=[],data=[],uri) { if(action == 'POST') { if(data != null) { var requestMethod = 'POST'; } } else { var requestMethod = 'GET'; } if(!uri) { switch(method) { case 'shipping': var uri = 'server/config/shipping.conf.json'; break; case 'inventory': var uri = 'inventory/shop.json'; break; case 'settings': var uri = 'server/config/site.conf.json'; break; case 'currencies': var uri = 'server/config/currencies.conf.json'; break; case 'pages': var uri = 'inventory/pages.json'; break; case 'articles': var uri = 'inventory/articles.json'; break; case 'blog': var uri = 'inventory/blog.json'; break; case 'messages': var uri = 'server/config/messages.conf.json'; break; case 'conf': var uri = 'server/config/shop.conf.json'; break; case 'cart': var uri = 'inventory/cart.json'; break; case 'customer': var uri = 'inventory/customer.json'; break; case 'orders': var uri = 'server/config/orders.conf.json'; break; } } var func = method; var req = OpenShop.xhr(); req.onreadystatechange = returncall; req.open(requestMethod, uri + '?cache-control=' + this.instanceid, true); req.withCredentials = true; req.setRequestHeader('Access-Control-Allow-Origin', '*'); if(requestMethod == 'POST' ) { req.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8'); req.send(JSON.stringify(data)); } else { req.setRequestHeader("Content-Type", "application/json;charset=UTF-8"); req.send(); } function returncall() { if (req.readyState == 4) { // add a switch case for each file we need to process. switch(func) { case 'inventory': OpenShop.getinventory(this.responseText); break; case 'settings': OpenShop.getsettings(this.responseText); break; case 'shipping': OpenShop.getshipping(this.responseText,opts); break; case 'shippinglist': OpenShop.getshippinglist(this.responseText); break; case 'currencies': OpenShop.getcurrencies(this.responseText,opts); break; case 'pages': OpenShop.getpages(this.responseText,opts); break; case 'articles': OpenShop.getarticles(this.responseText,opts); break; case 'blog': OpenShop.getblog(this.responseText,opts); break; case 'messages': OpenShop.getmessages(this.responseText,opts); break; case 'conf': OpenShop.getconf(this.responseText,opts); break; case 'cart': OpenShop.getcart(this.responseText,opts); break; case 'customer': OpenShop.getcustomer(this.responseText,opts); break; case 'orders': OpenShop.getorders(this.responseText,opts); break; } } }; }, fetchJSON: function(uri,callback) { var req = OpenShop.xhr(); req.open("GET", uri, true); req.withCredentials = true; req.setRequestHeader('Access-Control-Allow-Origin', '*'); req.setRequestHeader("Content-Type", "application/json;charset=UTF-8"); req.onreadystatechange = function() { if (req.readyState == 4 && req.status == 200) { callback(req.responseText); } } req.send(null); }, fetchHTML: function(method,uri,data=[],id,r=false) { var req = this.xhr(); var res = ''; if(method == 'POST') { if(data != null) { var requestMethod = 'POST'; } } else { var requestMethod = 'GET'; } req.open(requestMethod, uri, true); req.withCredentials = true; req.setRequestHeader('Access-Control-Allow-Origin', '*'); if(requestMethod == 'POST' ) { req.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8'); req.send(data); req.onreadystatechange = function() { if (req.readyState == 4 && req.status == 200) { this.res = req.responseText; if(id) { OpenShop.dom(id,'html',this.res); } if(r) { OpenShop.redirect(r); } } } } else { req.setRequestHeader("Content-Type", "application/json;charset=UTF-8"); req.send(null); } }, //--> end of OpenShop javascript logic. /* * Site specific functions */ addtocart: function(productId,qtyformId,token,path) { if(!token) { var token = 'invalid'; } var quantity = this.dom(qtyformId,'get'); var vrs1 = this.dom('variant1','get'); var vrs2 = this.dom('variant2','get'); var vrs3 = this.dom('variant3','get'); querypart =''; if(vrs1) { querypart = querypart + '&vrs1=' + vrs1; } if(vrs2) { querypart = querypart + '&vrs2=' + vrs2; } if(vrs3) { querypart = querypart + '&vrs3=' + vrs3; } if(!quantity || quantity.isNaN) { var quantity = 1; } if(!path) { //var path = 'shop'; } this.id = this.math('int',productId,1); this.qty = this.math('int',quantity, 1); this.fetchHTML('POST', path + '/cart/addtocart/' + this.instanceid + '/', 'action=addtocart&id='+this.id+'&qty='+this.qty+'&token='+token+querypart, 'ts-shop-result-message'); this.togglecartmsg('open'); }, deletefromcart: function(id,token,path) { if(!path) { var path = '/shop/'; } if(!token) { this.dom('ts-shop-result-message','Token was not set.'); } this.fetchHTML('POST', 'delete/' + this.instanceid + '/', 'action=deletefromcart&id='+this.math('int',id)+'&token='+token,false,'/'+path+'/cart/'); }, updatecart: function(id,qtyId,token,path) { if(!path) { //var path = 'shop'; } if(!token) { this.dom('ts-shop-result-message','Token was not set.'); } if(qtyId) { qty = this.dom(qtyId,'get'); } else { qty = 1; } this.id = this.math('int',id,1); this.qty = this.math('int',qty, 1); this.fetchHTML('POST', 'update/' + this.instanceid + '/', 'action=updatecart&id='+this.id+'&qty='+this.qty+'&token='+token,false,''); }, updateprices: function(productId,priceformId,token,path='/cart/addtocart/',boxid,box=false) { if(!token) { var token = 'invalid'; } if(!productId) { return false; } this.productId = this.math('int',productId,1); this.id = priceformId; this.bid = this.dom(boxid,'get'); this.fetchHTML('POST', path + this.instanceid + '/', 'action=updatecartprice&id='+this.id+'&productid='+productId+'&bid='+btoa(this.bid)+'&box='+box+'&token='+token,this.id,''); }, checkform: function() { var shipping_country = this.dom('ts-form-cart-shipping-country-select','get'); var payment_gateway = this.dom('ts-form-cart-payment-gateway-select','get'); if(shipping_country == '') { this.message('Shipping country cannot be empty. Please select a shipping country.'); return false; } if(payment_gateway == '') { this.message('Payment Gateway cannot be empty. Please select a payment method.'); return false; } return; }, checkPayPalform: function(token) { var first_name = this.dom('first_name','get'); var last_name = this.dom('last_name','get'); var address1 = this.dom('address1','get'); var city = this.dom('city','get'); var state = this.dom('state','get'); var zip = this.dom('zip','get'); var email = this.dom('email','get'); if(first_name == '') { this.message('First name cannot be empty.'); return false; } if(last_name == '') { this.message('Last name cannot be empty.'); return false; } if(address1 == '') { this.message('Address cannot be empty.'); return false; } if(city == '') { this.message('City cannot be empty.'); return false; } if(state == '') { this.message('State cannot be empty.'); return false; } if(zip == '') { this.message('Zip cannot be empty.'); return false; } if(email == '') { this.message('Email cannot be empty.'); return false; } else { var result = this.fetchHTML('GET', '../../instance/Query.php?cache=' + this.instanceid + '&action=prepayment&email='+btoa(email)+'&token='+token, false); return; } return; }, /* * PayPal functions. */ calculateTotalPayPal: function(amount) { var price = this.dom('item_price','get'); var shipping = this.dom('shipping','get'); var handling = this.dom('handling','get'); var total_amount = this.dom('total_amount','get'); var pre = this.math('int',this.math('int',shipping) + this.math('int',handling)); var sub_total = this.math('int',price * amount); var total = this.math('int',this.math('int',pre) + this.math('int',sub_total)); this.dom('total_amount','set',total); return true; }, /* * Functions to retrieve JSON files. These are called by the caller function. * Example: OpenShop.caller('GET','settings',[opt1,opt2,opt3],data={},'server/config/site.conf.json'); * The 3rd and 4th param is optional, as it is constructed from the 1st. the 3rd takes a data object for POST. * This retrieves the site.json file, and prints the object out in html. */ getsettings: function(jsonData) { var arr = []; var col = []; arr = JSON.parse(jsonData); for (var i = 0; i < arr.length; i++) { for (var key in arr[i]) { if (col.indexOf(key) === -1) { col.push(key); } } } for (var i = 0; i < arr.length; i++) { for (var j = 0; j < col.length; j++) { if(arr[i][col[j]] == '' || arr[i][col[j]] == null) { } else { document.write(col[j] + ':'); document.write(arr[i][col[j]]); document.write('
'); } } } }, getinventory: function(jsonData) { var arr = []; var col = []; arr = JSON.parse(jsonData); for (var i = 0; i < arr.length; i++) { for (var key in arr[i]) { if (col.indexOf(key) === -1) { col.push(key); } } } for (var i = 0; i < arr.length; i++) { for (var j = 0; j < col.length; j++) { if(arr[i][col[j]] == '' || arr[i][col[j]] == null) { } else { document.write(col[j] + ':'); document.write(arr[i][col[j]]); document.write('
'); } } } }, getshippinglist: function(jsonData) { var arr = []; var col = []; var ret = ''; return ret; }, getshipping: function(jsonData,opts) { if(jsonData=false) { this.message('Shipping country is not set, cannot calculate shipping cost.'); } else { var arr = []; var col = []; var verzendmethode = this.htmlspecialchars(opts[0],'full'); var totaal = opts[1]; var country = this.htmlspecialchars(opts[2],'full'); var parentId = this.htmlspecialchars(opts[3],'full'); var sc = 'shipping.' + this.htmlspecialchars(country,'full'); arr = JSON.parse(jsonData); for (var i = 0; i < arr.length; i++) { for (var key in arr[i]) { if (col.indexOf(key) === -1) { col.push(key); } } } for (var i = 0; i < arr.length; i++) { for (var j = 0; j < col.length; j++) { if(col[j] == sc) { var sp = arr[i][col[j]]; // shipping price var totals = this.math('float',totaal) + this.math('float',sp); this.dom(parentId,'html',"€" + this.math('float',totals,2)); } } } } }, wishlist: function(method, product, g) { var req = this.xhr(); req.open("GET", '/wishlist/' + this.rnd() + '/' + method + '/' + this.htmlspecialchars(product,'full') + '&tr=' + this.htmlspecialchars(g,'uri'), true); req.onreadystatechange = function() { if (req.readyState == 4 && req.status == 200) { var text = req.responseText.split('|'); if (text[0].replace(' ', '') == 'O') { if (g != '0') { OpenShop.dom('fhs' + product,'html',text[1]); OpenShop.dom('favheart' + product,'className','heartfull_png'); } else { OpenShop.dom('fhs' + product,'html',text[1]); OpenShop.dom('favheart' + product,'className','favheart_fixed'); } return false; } else if (text[0].replace(' ', '') == 'X') { if (g != '0') { OpenShop.dom('fhs' + product,'html',text[1]); OpenShop.dom('favheart' + product,'className','heart_png'); } else { OpenShop.dom('fhs' + product,'html',text[1]); OpenShop.dom('favheart' + product,'className','favheart'); } return false; } else { return false; } } } req.send(null); }, redeemVoucher: function() { var voucher = this.dom('voucher','get'); if (voucher == '') { this.message('Please enter voucher code. This code is a sequence of numbers and letters.'); } else { var req = this.xhr(); req.open("GET", '/query/' + this.rnd() + '/voucher/' + this.htmlspecialchars(voucher) + '/', true); req.onreadystatechange = function() { if (req.readyState == 4 && req.status == 200) { if (req.responseText) { var check = req.responseText.split('|'); if (check[0].replace(' ', '') == 'OK') { var tot = this.dom('total','gethtml'); tot = tot.replace('€', '').replace(/\u20ac/g, '').replace(',', '.').replace(' ', ''); var totals = this.math('float',tot); if (check[1] != '') { var t = check[1]; var ta = this.math('float',t); var totalsx = (totals - ta); } else if (check[2] != '' && check[2] != '|') { var totals_sub = (totals / 100 * check[2]); var totalsx = (totals - totals_sub); } else {} if (totals < 0) { this.message('The amount is too tow to redeem the voucher.'); } else { if (totalsx.toFixed(2) == 'NaN') { this.dom('total','html',"€" + totalsx); } else { this.dom('total','html',"€" + totalsx.toFixed(2)); } } } else if (check[0].replace(' ', '') == 'ERR') { this.message('Code has already been redeemed, or is wrong.'); } else { this.message('There was a problem with redeeming the voucher code. Please check if the code is correct.'); } } else { this.message('There was a problem with redeeming. Please check if the code is correct.'); } } } req.send(null); } }, }; /* Cache-control. * Setting a fixed instanceid when main.js is loaded. * the instanceid prevents json caching for recently updated files, * but also prevents caching too much on individual json files. */ OpenShop.instanceid = OpenShop.rnd('uuid');