PageSourceSearch

https://shop.acticareuk.com/themes/activerehab/js/productgroup.js?ver=1

js acticareuk.com collected 2026-10-08 04:27:03 UTC 22,204 bytes, 673 lines download raw bytes

1DEBUG = false;
2if (typeof console == 'undefined') {
3    DEBUG = false;
4}
5
6$(function() {
7    $('#lockdownmessage').click(function(e) {
8        e.preventDefault();
9        $('#lockdown-group-form').submit();
10        return false;
11    })
12})
13
14var ProductGroup = function (data) {
15    if (!data) {
16        data = {}
17    }
18
19
20    this.defaultPriceText = '';
21    this.defaultStcodeText = '';
22    this.defaultAvailText = '';
23
24    this.category = data.category || '';
25    this.products = data.products || [];
26    this.availability = data.availability || [];
27    this.levels = data.levels || [];
28    this.leadtimes = data.leadtimes || [];
29
30    this.supplierleadtimes = data.supplierleadtimes || [];
31    this.supplierleadtimestext = data.supplierleadtimestext || [];
32
33    this.showPhysicalStockLevels = data.showPhysicalStockLevels || [];
34    this.showOutOfStockDueDays = data.showOutOfStockDueDays || [];
35    this.stockLevelInStockText = data.stockLevelInStockText || [];
36    this.stockLevelOutOfStockText = data.stockLevelOutOfStockText || [];
37    this.availabilityFactorDueDays = data.availabilityFactorDueDays || [];
38    this.checkPhysicalStockShowIsSetInWebopts = data.checkPhysicalStockShowIsSetInWebopts || [];
39
40    this.prices = data.prices || [];
41    this.pricesIncExVat = data.pricesIncExVat || [];
42    this.minord = data.minord || [];
43    this.soincr = data.soincr || [];
44    this.splitpack = data.splitpack || [];
45    this.packquan = data.packquan || [];
46    this.combinations = data.combinations || [];
47    this.selectedOptions = data.selectedOptions || [];
48    this.images = data.images || [];
49    this.prodlink = data.prodlink || [];
50    this.ga4data = data.ga4data || [];
51
52    this.lockeddown = data.lockeddown || [];
53    this.loyalty_points_value = data.loyalty_points_value || [];
54    this.loyalty_points_earn = data.loyalty_points_earn || [];
55
56    this.selectedProduct = null;
57    this.priceElement = null;
58    this.stcodeElement = null;
59    this.availElement = null;
60    this.addButton = null;
61    this.wishlistButton = null;
62    this.quoteButton = null;
63
64    this.prodtitle = data.prodtitle || [];
65	
66    /**
67     * callbacks for various events
68     * simply add a function to one and it will
69     * be called at the appropriate point
70     */
71    this.onProductSelected = null;
72    this.onNoProductSelected = null;
73
74    var scope = this;
75
76    this.init = function () {
77        this.addButton = $('#addtobasket').Button();
78        this.wishlistButton = $('#wishlistsubmitinput').Button();
79        this.quoteButton = $('#quotesubmitinput').Button();
80
81        this.selects = $('select.groupedProduct');
82        this.selectCount = scope.selects.length;
83        this.selects.change(function (e) {
84            scope.selectChanged(e)
85        });
86        this.priceElement = $('.addtobasket .price');
87        this.AltpriceElement = $('.alt-unit-price .price');
88        this.stcodeElement = $('.addtobasket .stcode');
89        this.availElement = $('.addtobasket .availability');
90        this.quanElement = $('.addtobasket .ordquan');
91        this.defaultPriceText = this.priceElement.html();
92        this.defaultStcodeText = this.stcodeElement.html();
93        this.defaultAvailText = this.availElement.html();
94        this.clearProduct(true);
95        this.addtowishlistgroup = $('.addtowishlistgroup');
96        this.addtoquotegroup = $('.addtoquotegroup');
97        $(".loyalty_points_paywithpoints").hide(); // initial hide
98
99        this.loyalty_points_value_elem = $('.loyalty_points .loyalty_points_value');
100        this.loyalty_points_earn_elem = $('.loyalty_points .loyalty_points_earn');
101
102        /**
103         * only one select with only one option
104         * shouldnt happen if data if ok, but can't hurt to check
105         */
106        if (this.selectCount == 1 && this.selects[0].children.length == 2) {
107            this.selects[0].selectedIndex = 1;
108            $(this.selects[0]).change();
109        }
110
111
112        /*
113         * Check the selects and reload the product if all of them are set.
114         * This code will work if back is hit in the browser.
115         */
116        var allSet = true;
117        var selections = [];
118        for (var i = 0; i < this.selectCount; i++) {
119            if (this.selects[i].selectedIndex === 0) {
120                allSet = false;
121                break;
122            }
123            selections[selections.length] = this.selects[i].selectedIndex;
124        }
125        if (allSet) {
126            for (var i = 0; i < this.selectCount; i++) {
127                this.selects[i].selectedIndex = selections[i];
128                $(this.selects[i]).change();
129            }
130        }
131
132    };
133
134    this.addFavourites = function (prod) {
135        $('#addstockcode').val(this.products[prod]);
136    }
137
138    this.selectChanged = function (e) {
139
140
141        var select = e.target,
142            option = select.selectedIndex,
143            selno = this.selects.index(select);
144
145		// Nothing has been selected in one of the dropdowns so load the category image
146		if(option===0){
147            updateFavouritesButton("");
148			showProductImage("");
149		}
150
151        if(option===0){
152            updateReviewLink("");
153        }
154
155        this.clearAhead(selno);
156
157        if (option == 0) {
158            this.selectedOptions[selno] = null;
159        }
160
161        this.selectedOptions[selno] = select.options[option].text;
162
163        var nextSel = this.selects[selno + 1];
164
165        var valid = this.findValidProducts();
166
167        if (!valid) {
168            this.clearProduct();
169            this.onNoProductSelectedCallback();
170            this.loyalty_points_earn_elem.hide();
171            //this.addtowishlistgroup.hide();
172            //this.addtoquotegroup.hide();
173            return;
174        }
175
176        // we have a winner
177        if (valid.length == 1) {
178            this.setProduct(this.findProduct());
179            this.addtowishlistgroup.show();
180            this.addtoquotegroup.show();
181        }
182
183        // more than one match, populate the next select
184        if (nextSel) {
185            this.populateSelect(nextSel, valid);
186            nextSel.disabled = false;
187            debug("Triggered select change");
188            debug(select);
189
190            if($(select).hasClass("grp-colour")){
191                debug("Triggered select change on COLOUR, start next SIZE select");
192                debug(nextSel);
193                debug("Preselecting next block to swap image");
194                 if($(nextSel).hasClass("grp-size")){
195                     // it has a size selection, preselect it to set the colour image
196                     $(nextSel).addClass('active');
197                     $('.grp-size>option:eq(1)').attr('selected', true);
198                     $('.grp-size').trigger('change');
199                 }
200
201
202
203            }
204
205        }
206    }
207
208    this.populateSelect = function (select, options) {
209        // keep the first line (choose a...)
210        var first = $(select).find(':first-child');
211
212        // find the select number
213        var ix = this.selects.index(select);
214
215        $(select).html(first);
216
217        var done = [];
218
219		
220        for (var i = 0; i < options.length; i++) {
221            opt = $('<option>');
222            val = options[i][ix];
223
224            if ($.inArray(val, done) == -1) {
225                opt.val(val);
226                opt.text(val);
227                $(select).append(opt);
228            }
229
230            done.push(val);
231        }
232
233        if (options.length == 1) {
234            opt.attr('selected', 'selected')
235            $(select).change();
236        }
237
238    }
239
240    this.findValidProducts = function () {
241        debug('findValidProducts');
242
243        var options = this.selectedOptions;
244
245        if (options.length == 0) {
246            debug('nothing selected');
247            return false;
248        }
249
250        /**
251         * go through all the combinations
252         * and see if they match what we have selected so far
253         * if so, add to valid array
254         */
255        var valid = $.grep(this.combinations, function (product, ix) {
256            for (var i = 0, len = options.length; i < len; i++) {
257                if (product[i] != options[i]) {
258                    return false;
259                }
260            }
261
262            return true;
263        });
264
265        debug(valid);
266
267        if (!valid.length) {
268            return false;
269        }
270        return valid;
271    }
272
273    /**
274     * clear all selects ahead of selno
275     */
276    this.clearAhead = function (selno) {
277        debug('clearAhead(' + selno + ')');
278
279        if (selno + 1 >= this.selectCount) {
280            return;
281        }
282
283        var scope = this;
284
285        for (var i = selno + 1; i < this.selects.length; i++) {
286            var select = this.selects[i];
287            if (select.disabled) {
288                return;
289            }
290
291            debug('clearing select ' + i);
292            debug(select);
293
294            select.selectedIndex = 0;
295            scope.selectedOptions.splice(i - 1, 1);
296
297			if(i!==selno+1){
298				select.disabled = true;
299			}
300			
301        };
302
303        this.clearProduct();
304    }
305
306
307    this.setProduct = function (prod) {
308        debug('setProduct');
309
310        this.priceElement.html(this.prices[prod] + this.pricesIncExVat[prod]);
311
312        if(typeof this.altunits !== "undefined" && typeof this.altunits[prod] !== "undefined" ){
313            this.AltpriceElement.html(this.altunits[prod]);
314        }
315
316
317        this.selectedProduct = this.products[prod];
318        this.stcodeElement.html( "<strong>" + this.prodtitle[prod] + "</strong></br>" +   "Stock Code: <a href='" + this.prodlink[prod] + "'>" + this.selectedProduct + "</a>");
319
320
321
322        if (this.selectedProduct!=='N/A'){
323            updateFavouritesButton(this.selectedProduct);
324            showProductImage(this.selectedProduct);
325            updateReviewLink(this.selectedProduct);
326		}
327
328
329        /*
330        if(typeof this.selectedProduct !== undefined){
331            $('select.groupedProduct').on("change", function(){
332                if($('div > form > div.code > span.stcode').text()==='Please select from the options above.'){
333                    $('#accordian-reviews > div > div > div.review').html('There are no reviews for this product yet.');
334                }
335                else{
336                    $('#accordian-reviews > div > div > div.review').html('There are no reviews for this product yet. <a href="/addreview.p
336hp?product=' + this.selectedProduct + '&category=' + $('input[name="returntoargcategory"]').val() + '">Be the first to add one!</a>');            
337                }
338            });        
339        }
340        */
341
342        var avail = this.levels[prod];
343        var supplierleadtime = this.supplierleadtimes[prod];
344        var availabilityfactor = this.availability[prod];
345
346        if (supplierleadtime > 0) {
347            //avail = 'Out Of Stock';
348            avail += ' <i class="fa fa-truck"></i>' + this.supplierleadtimestext[prod];
349        }
350        if (supplierleadtime == 0) {
351            if (avail > 0 ) {
352                if ( this.showPhysicalStockLevels == true || this.checkPhysicalStockShowIsSetInWebopts == true ){
353                    avail = '<i class="fa fa-check"></i>' + ' ' + avail + ' ' + this.stockLevelInStockText;
354                } else {
355                    avail = '<i class="fa fa-check"></i>' + ' ' + this.stockLevelInStockText;
356                }
357            } else {
358                if (typeof this.availabilityFactorDueDays[availabilityfactor] != "undefined") {
359                    avail = '<i class="fa fa-truck"></i>' + ' ' + this.availabilityFactorDueDays[availabilityfactor];
360                } else {
361                    if ( (this.showPhysicalStockLevels == true || this.checkPhysicalStockShowIsSetInWebopts == true) && this.showOutOfStockDueDays == true ) {
362                        avail = '<i class="fa fa-truck"></i>' + ' ' + this.stockLevelOutOfStockText;
363                    } else {
364                        avail = '<i class="fa fa-close"></i>' + ' ' +  this.stockLevelOutOfStockText;
365                    }
366                }
367            }
368        } else {
369            if (avail > 0 ) {
370                if ( this.showPhysicalStockLevels == true || this.checkPhysicalStockShowIsSetInWebopts == true ){
371                    avail = '<i class="fa fa-check"></i>' + avail + ' ' + this.stockLevelInStockText;
372                } else {
373                    avail = '<i class="fa fa-check"></i>' + ' ' + this.stockLevelInStockText;
374                }
375            } else {
376                if (typeof this.availabilityFactorDueDays[availabilityfactor] != "undefined") {
377                    avail = '<i class="fa fa-truck"></i>' + ' ' + this.availabilityFactorDueDays[availabilityfactor];
378                } else {
379                    if ( (this.showPhysicalStockLevels == true || this.checkPhysicalStockShowIsSetInWebopts == true) && this.showOutOfStockDueDays == true ) {
380                        avail = '<i class="fa fa-truck"></i>' + ' ' + this.supplierleadtimestext[prod];
381                    } else {
382                        avail = '<i class="fa fa-close"></i>' + ' ' + this.stockLevelOutOfStockText;
383                    }
384                }
385            }
386        }
387
388        this.availElement.html(avail);
389
390        var qt = this.getQuantityText(prod);
391
392        this.quanElement.html(qt);
393        $('#prodqty').val("1");
394
395        $(".loyalty_points_paywithpoints").hide();
396        if(this.loyalty_points_value[prod] > 0 ){
397            this.loyalty_points_value_elem.html(this.loyalty_points_earn[prod] );
398
399            // If logged in Pay with points option
400            sStr = '<input name="withpoints" id="withpointscheck" type="checkbox" value="true" /> <span>Pay with points</span>';
401            $(".loyalty_points_paywithpoints").html(sStr);
402            $(".loyalty_points_paywithpoints").fadeIn();
403        }
404
405        // If logged in earn else you could earn
406        if(this.loyalty_points_earn[prod]){
407
408            var currentqty = $(document).find("input[class*='qty']").val();
409
410            this.loyalty_points_earn_elem.html(this.loyalty_points_earn[prod]);
411            this.loyalty_points_earn_elem.show();
412        }
413
414
415
416        $('.groupedbasketformaddstockcode_').val(this.selectedProduct);
417        $('#wishliststockcode').val(this.selectedProduct);
418        $('input[name=addstockcode]').val(this.selectedProduct);
419
420        // Managed baskets add stockcode ect for grouped products - hide normal group product info
421        if ($(".managedbasketform").length > 0) {
422            $(".manged-basket-stockcode").val(this.selectedProduct);
423            $(".manged-basket-stockcode").fadeOut().html("Stock Code: " + this.selectedProduct).fadeIn();
424            $(".manged-basket-stocklevel").fadeOut().html(avail).fadeIn();
425            $(".manged-basket-price").fadeOut().html("Price: " + this.prices[prod] + this.pricesIncExVat[prod]).fadeIn();
426
427            // In stock check?
428            if (avail == 'Out Of Stock') {
429                $("#managedbasket-addtobasket").attr("disabled", true);
430            } else {
431                $("#managedbasket-addtobasket").attr("disabled", false);
432            }
433        }
434
435        this.addButton.Enable();
436	this.addButton.show();
437        this.wishlistButton.Enable();
438        this.quoteButton.Enable();
439
440        if (this.lockeddown[prod] == 1) {
441            $("#grp-prod-stcode").hide();
442            $("#grp-prod-stocklevel").hide();
443            $("#grp-prod-qty").hide();
444            $("#grp-prod-basketbtn").hide();
445            $("#grp-prod-wishlist").hide();
446            $("#grp-prod-lockeddown").show();
447            $('#lockdownemail').val('Request for ' + this.prodtitle[prod] + ' to be added to the approved list (' + this.products[prod] + ')');
448            $('#lockdownmessage').val('Request for ' + this.products[prod] + ' to be added to the approved list');
449	    this.addButton.hide();
450	    this.addButton.Disable();
451	
452        } else {
453            $("#grp-prod-stcode").show();
454            $("#grp-prod-stocklevel").show();
455            $("#grp-prod-qty").show();
456            $("#grp-prod-basketbtn").show();
457            $("#grp-prod-wishlist").show();
458            $("#grp-prod-lockeddown").hide();
459        }
460
461        // Alt unit select fix
462        $('select.altunitselect').change(function(){
463
464            var price = $('.pricespan');
465            var priceinc = $('.pricespaninc');
466            var opt = $(this).find('option:selected');
467            var prc = opt.data('price');
468            var prcinc = opt.data('priceinc');
469            price.text(prc);
470            priceinc.text("£" + prcinc.toFixed(2));
471
472            //changes a hidden form element inside the actual form.
473            $(this).parent().parent().find('input#unit').val(opt.val());
474        });
475
476        this.onProductSelectedCallback(prod);
477
478        if (this.ga4data.length) {
479            $.ajax({
480                type: 'POST',
481                url: '/ajaxGA4.php',
482                data: {action: 'view_item', codes: [this.ga4data[prod]]},
483                success: function (response) {
484                    var $el = $(response);
485                    $('body').append($el);
486                }
487            });
488        }
489
490        return true;
491    }
492
493    this.getQuantityText = function (prod) {
494        var mintext, inctext, showmintext = true, showinctext = true;
495
496        if(typeof this.altunits !== "undefined" && typeof this.altunits[prod] !== "undefined" ){
497            showmintext = false;
498            showinctext = false;
499        }
500
501        if (this.minord[prod] > 1 && showmintext) {
502            mintext = 'A minimum order quantity of ' + this.minord[prod] + ' applies to this product.';
503        }
504        if (this.soincr[prod] > 1 && showinctext) {
505            inctext = 'This product must be ordered in multiples of ' + this.soincr[prod] + ', quantities will be rounded up as you add them.';
506        }
507
508        if (!isNaN(this.minord[prod])){
509            $("#minorder").val(this.minord[prod]);
510        }else{
511            $("#minorder").val(0);
512        }
513        if (!isNaN(this.soincr[prod])) {
514            $("#soincrtmp").val(this.soincr[prod]);
515        } else {
516            $("#soincrtmp").val(0);
517        }
518
519        var quantext = '';
520
521        if (mintext) {
522            quantext = mintext;
523        }
524        if (inctext) {
525            quantext = quantext + '<br/>' + inctext;
526        }
527
528        return quantext;
529    }
530
531    /**
532     * no product was selected
533     */
534    this.clearProduct = function (startup) {
535        debug('clearProduct');
536
537        this.stcodeElement.html(this.defaultStcodeText);
538        this.priceElement.html(this.defaultPriceText);
539        this.availElement.html(this.defaultAvailText);
540        this.quanElement.html('');
541        this.selectedProduct = null;
542        this.addButton.Disable();
543	this.addButton.hide();
544        this.wishlistButton.Disable();
545        this.quoteButton.Disable();
546
547        return false;
548    }
549
550    this.findProduct = function () {
551        debug('findProduct');
552
553        var num = this.selectedOptions.length;
554        var combo, match;
555
556        if (num < this.selectCount) {
557            return null;
558        }
559
560        for (var i = 0, len = this.combinations.length; i < len; i++) {
561            combo = this.combinations[i];
562            match = true;
563
564            for (var j = 0; j < num; j++) {
565                if (combo[j] != this.selectedOptions[j]) {
566                    match = false;
567                    break;
568                }
569            }
570
571            if (match) {
572                return i;
573            }
574        }
575
576        return null;
577    }
578
579    /**
580     * if a callback has been defined, calls it
581     * when a product is selected and passes
582     * in the stockcode and the index
583     */
584    this.onProductSelectedCallback = function (prod) {
585        if (typeof this.onProductSelected === 'function') {
586            this.onProductSelected(this.selectedProduct, prod);
587        }
588    }
589
590    this.onNoProductSelectedCallback = function () {
591        if (typeof this.onNoProductSelected === 'function') {
592            this.onNoProductSelected();
593        }
594    }
595
596}
597
598function debug(message) {
599    if (DEBUG) {
600        console.log(message);
601    }
602}
603
604
605function showProductImage(stockcode){
606	
607	var category=$('#categoryid').val();
608    var show_preview_images=$('#preview_image').val();
609
610    if(show_preview_images==='true'){
611    	if (typeof stockcode != 'undefined'){
612    	
613    		$.ajax({
614    			type: 'POST',
615    			url: '/productGroupImage.php',
616    			data: {'action':'getImage', 'stockcode':stockcode, 'category':category},
617    			dataType: 'json',
618    			beforeSend:function(){
619    			// this is where we append a loading image
620                    $('.image-section .image .main-product-image').html('<div style="margin-top:40px;" class="loading"><i class="fa fa-spinner fa-spin fa-4x"></i></div>').fadeIn(100);
621    		},
622    			cache: false,
623    			
624    			success:function(data){
625    				$('.image-section .image .main-product-image').html(data);
626    				$(".lightbox").colorbox({photo: true, width: "80%", height: "80%"});
627    			},
628    			
629    			error:function(data){
630    			}
631    		});
632    	}
633    }
634}
635
636
637function updateFavouritesButton(stockCode){
638
639    if(typeof stockCode !== 'undefined'){
640
641        $.ajax({
642            type: 'POST',
643            format: 'json',
644            url: '/ajaxFavourites.php',
645            data: {stockCode : stockCode, action : 'checkStatus'},
646
647            success:function(data){
648
649                if(data.indexOf("isFavourite")!== -1){
650                    $('#wishlistsubmitinput').html('Remove from Favourites <i title="Remove from Favourites" class="fa fa-star"></i>');
651                }
652                else if(data.indexOf("isNotFavourite")!== -1){
653                    $('#wishlistsubmitinput').html('Add to Favourites <i title="Add to Favourites" class="fa fa-star-o"></i>');
654                }
655            }
656        });
657    }
658}
659
660
661
662
663function updateReviewLink(stockcode){
664    if ( stockcode != ""){
665        $('#accordian-reviews > div > div > div.review').html('There are no reviews for this product yet. <a href="/addreview.p
665hp?p=' + stockcode + '&c=' + $('input[name="returntoargcategory"]').val() + '">Be the first to add one!</a>');              
666    }
667    else{
668        $('#accordian-reviews > div > div > div.review').html('Please select a product to add a review to.');            
669    }
670}
671
672
673

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.