Tabs randomly switch to accordions

Search
Other Bug Reports questions
Forum

Tabs randomly switch to accordions

Michael Melson's Avatar Michael Melson
I'm facing a strange behaviour of the tabs and accordions on a site using Virtuemart.
Virtuemart is configured to parse Joomla Plugins.
Tabs are used to show different productinformations.
On the first attempt everything shows up correct.
Then, using the product navigation, they become accordions that can't be opened anymore.

Confidential information:
(hidden)


Thank you!
Peter van Westen's Avatar Peter van Westen ADMIN
The navigation loads new content via ajax, and does not re-initiate the Tabs & Accordions scripts.
So unless VM gives you a possibility to trigger scripts when loading new content, you won't be able to use Tabs & Accordions in its content.
Please post a rating at the Joomla! Extensions Directory
Michael Melson's Avatar Michael Melson
Hi Peter,
thank you I've been too busy in other projects and have been on winter-holiday.

Now this challenge comes back to me. I had contact to Max Milbers from the VM Project. He redirected my question to you 😉

He told me, that they are firing their tabs (used in orderview e.g.) with
$().trigger("ready");

I added this in the dynupdate.js of virtuemart as Max told me - but unfortunately it doesn't work. Then he gave me the tip to try
$('body').trigger("ready");

But it doesn't work either.

Can you offer me a (paid) individual solution?

This is the view we are talking about:

www.sapodoris.de/shop-kategorien/fuer-le...s/saposan-l-3-detail

Thanks in advance and kind regards
Michael
Peter van Westen's Avatar Peter van Westen ADMIN
Ask them for the code snippet to trigger this javascript function:
RegularLabs.TabsAccordions.init(null);
Please post a rating at the Joomla! Extensions Directory
Michael Melson's Avatar Michael Melson
Thank you - I handed over to Max.
Michael Melson's Avatar Michael Melson
Adding your Info to the one I got from Max the problem was solved as you can see here:

www.sapodoris.de/shop-kategorien/eiweiss...oteinhappen-1-detail

Thanks a lot
Michael Melson's Avatar Michael Melson
Hi again. We moved the shop to a new server.

The solution worked under Php 7.4

Now we're under Php 8 and it stopped working.

Your code has been added to the attached to the dynupdate.js ov virtemart in line 53

Do you have an idea, why this doesn't work in Php 8?
/**
 * dynupdate.js: Dynamic update of product content for VirtueMart
 *
 * @package	VirtueMart
 * @subpackage Javascript Library
 * @author Max Galt
 * @copyright Copyright (c) 2014 - 2022 VirtueMart Team. All rights reserved.
 * @license http://www.gnu.org/copyleft/gpl.html GNU/GPL
 */

if (typeof Virtuemart === "undefined")
	var Virtuemart = {};
jQuery(function($) {

    // Add to cart and other scripts may check this variable and return while
    // the content is being updated.
    Virtuemart.isUpdatingContent = false;
	Virtuemart.recalculate = false;
	Virtuemart.setBrowserState = true;

    Virtuemart.updateContent = function(url, callback) {

        if(Virtuemart.isUpdatingContent) return false;
        Virtuemart.isUpdatingContent = true;
        urlSuf='tmpl=component&format=html&dynamic=1';
        var glue = '&';
        if(url.indexOf('&') == -1 && url.indexOf('?') == -1){
			glue = '?';
        }
        url += glue+urlSuf;
		$(this).vm2front("startVmLoading");
		$.ajax({
            url: url,
            dataType: 'html',
            success: function(data) {
				var title = $(data).filter('title').text();
				$('title').text(title);
				var el = $(data).find(Virtuemart.containerSelector);
				if (! el.length) el = $(data).filter(Virtuemart.containerSelector);
				if (el.length) {
					Virtuemart.container.html(el.html());
$().trigger("ready");
					Virtuemart.updateCartListener();
					Virtuemart.updateDynamicUpdateListeners();

					if (Virtuemart.updateImageEventListeners) Virtuemart.updateImageEventListeners();
					if (Virtuemart.updateChosenDropdownLayout) Virtuemart.updateChosenDropdownLayout();
					if (typeof vm2tabs === 'function') {
						vm2tabs($("#ui-tabs .tabs"));
					}
					//Virtuemart.product($("form.product"));
$('body').trigger("ready");
RegularLabs.TabsAccordions.init(null);
					if(Virtuemart.recalculate) {
						$("form.js-recalculate").each(function(){
							if ($(this).find(".product-fields").length && !$(this).find(".no-vm-bind").length) {
								var id= $(this).find('input[name="virtuemart_product_id[]"]').val();
								Virtuemart.setproducttype($(this),id);
							}
						});
					}
				}
				Virtuemart.isUpdatingContent = false;
				if (callback && typeof(callback) === "function") {
					callback();
				}
				$(this).vm2front("stopVmLoading");
            },
			error: function(datas) {
				alert('Error updating page');
				Virtuemart.isUpdatingContent = false;
				$(this).vm2front("stopVmLoading");
			},
			statusCode: {
				404: function() {
					Virtuemart.isUpdatingContent = false;
					$(this).vm2front("stopVmLoading");
					alert( "page not found" );
				}
			}
        });
        Virtuemart.isUpdatingContent = false;
    }

    // GALT: this method could be renamed into more general "updateEventListeners"
    // and all other VM init scripts placed in here.
    Virtuemart.updateCartListener = function() {
        // init VM's "Add to Cart" scripts should be in a function registered for the trigger, so long, just quickn dirty
		if (typeof Virtuemart.product !== "undefined"){
			Virtuemart.product($(".product"));
		}
		$('body').trigger('updateVirtueMartProductDetail');
    }

    Virtuemart.updL = function (event) {
        event.preventDefault();
        var url = $(this).attr('href');
        Virtuemart.setBrowserNewState(url);
        Virtuemart.updateContent(url);
    }

    Virtuemart.upd = function(event) {
        event.preventDefault();
        var url = $(this).attr('url');//console.log("Url "+url,$(this));
        if(url == 'value'){
			url = $(this).val(); //console.log("Url by value");
		} else if (typeof url === typeof undefined || url === false) {
			url = $(this).closest('form').attr('action');
			if (typeof url === typeof undefined || url === false || url === "#") {
				url = $(this).val();
			}
        }

        if(url!=null){
			url = url.replace(/amp;/g, '');
            Virtuemart.setBrowserNewState(url);
            Virtuemart.updateContent(url);
        }
    };

	Virtuemart.updForm = function(event) {

		cartform = $("#checkoutForm");
		carturl = cartform.attr('action');
		if (typeof carturl === typeof undefined || carturl === false) {
			carturl = $(this).attr('url');
			console.log('my form no action url, try attr url ',cartform);
			if (typeof carturl === typeof undefined || carturl === false) {
				carturl = 'index.php?option=com_virtuemart&view=cart'; console.log('my form no action url, tried attr url ',carturl);
			}
		}
		urlSuf='tmpl=component&task=checkout&redirect=0';
		carturlcmp = carturl;
		if(carturlcmp.indexOf(urlSuf) == -1){
			var glue = '&';
			if(carturlcmp.indexOf('&') == -1 && carturlcmp.indexOf('?') == -1){
				glue = '?';
			}
			carturlcmp += glue+urlSuf;
		}

		cartform.submit(function() {
			if(Virtuemart.isUpdatingContent) return false;
			Virtuemart.isUpdatingContent = true;
			$(this).vm2front("startVmLoading");

			$.ajax({
				type: "POST",
				url: carturlcmp,
				dataType: "html",
				data: cartform.serialize(), // serializes the form's elements.
				success: function(datas) {

					if (typeof window._klarnaCheckout !== "undefined"){
						window._klarnaCheckout(function (api) {
							//console.log(' updateSnippet suspend');
							api.suspend();
						});
					}


					var el = $(datas).find(Virtuemart.containerSelector);
					if (! el.length) el = $(datas).filter(Virtuemart.containerSelector);
					if (el.length) {
						Virtuemart.container.html(el.html());
						//Virtuemart.updateCartListener();
						//Virtuemart.updDynFormListeners();
						//Virtuemart.updateCartListener();

						if (Virtuemart.updateImageEventListeners) Virtuemart.updateImageEventListeners();
						if (Virtuemart.updateChosenDropdownLayout) Virtuemart.updateChosenDropdownLayout();
					}
					jQuery('body').trigger('updateVirtueMartCartModule');
					Virtuemart.setBrowserNewState(carturl);
					Virtuemart.isUpdatingContent = false;
					$(this).vm2front("stopVmLoading");
					if (typeof window._klarnaCheckout !== "undefined"){
						window._klarnaCheckout(function (api) {
							//console.log(' updateSnippet suspend');
							api.resume();
						});
					}
				},
				error: function(datas) {
					alert('Error updating cart');
					Virtuemart.isUpdatingContent = false;
					$(this).vm2front("stopVmLoading");
				},
				statusCode: {
					404: function() {
						Virtuemart.isUpdatingContent = false;
						$(this).vm2front("stopVmLoading");
						alert( "page not found" );
					}
				}
			});
			return false; // avoid to execute the actual submit of the form.
		});
	};

	Virtuemart.updFormS = function(event) {
		Virtuemart.updForm();
		$("#checkoutForm").submit();
	}

	Virtuemart.updDynFormListeners = function() {

		$('#checkoutForm').find('*[data-dynamic-update=1]').each(function(i, el) {
			var nodeName = el.nodeName;
			el = $(el);
			//console.log('updDynFormListeners ' + nodeName, el);
			switch (nodeName) {
				case 'BUTTON':
					el[0].onchange = null;
					el.off('click',Virtuemart.updForm);
					el.on('click',Virtuemart.updForm);
				default:
					el[0].onchange = null;
					el.off('click',Virtuemart.updFormS);
					el.on('click',Virtuemart.updFormS);
					break;
			}
		});
	}

    Virtuemart.updateDynamicUpdateListeners = function() {
        $('*[data-dynamic-update=1]').each(function(i, el) {
            var nodeName = el.nodeName;
            el = $(el);
            //console.log('updateDynamicUpdateListeners '+nodeName, el);
            switch (nodeName) {
                case 'A':
					el[0].onclick = null;
                    el.off('click',Virtuemart.updL);
                    el.on('click',Virtuemart.updL);
                    break;
                default:
					el[0].onchange = null;
                    el.off('change',Virtuemart.upd);
                    el.on('change',Virtuemart.upd);
            }
        });
    }

    var everPushedHistory = false;
    var everFiredPopstate = false;
    Virtuemart.setBrowserNewState = function (url) {
    	if(!Virtuemart.setBrowserState) return false;

        if (typeof window.onpopstate == "undefined")
            return;
        var stateObj = {
            url: url
        }
        everPushedHistory = true;
        try {
            history.pushState(stateObj, "", url);
        }
        catch(err) {
            // Fallback for IE
            window.location.href = url;
            return false;
        }
    }

    Virtuemart.browserStateChangeEvent = function(event) {
        // Fix. Chrome and Safari fires onpopstate event onload.
        // Also fix browsing through history when mixed with Ajax updates and
        // full updates.
        if (!everPushedHistory && event.state == null && !everFiredPopstate)
            return;

        everFiredPopstate = true;
        var url;
        if (event.state == null) {
            url = window.location.href;
        } else {
            url = event.state.url;
        }
        Virtuemart.updateContent(url);
    }
    window.onpopstate = Virtuemart.browserStateChangeEvent;

});
Peter van Westen's Avatar Peter van Westen ADMIN
Sorry, but this is a VM question. Ask them about it.
Please post a rating at the Joomla! Extensions Directory
Michael Melson's Avatar Michael Melson
Okay I'll do.
Have a nice weekend.
Michael Melson's Avatar Michael Melson
Hi again Peter.
Finally I solved it by adding some code to the override of the productdetails template within the buyer area:
<script>
// Funktion zum Neuladen der JS-Datei
function loadScript(url, callback) {
    var script = document.createElement('script');
    script.type = 'text/javascript';
    script.src = url;

    // Cross-Browser-Kompatibilität für das Ladenereignis des Skripts
    script.onreadystatechange = callback;
    script.onload = callback;

    // Entferne das alte Skript, falls vorhanden, und füge das neue hinzu
    var oldScript = document.querySelector('script[src="' + url + '"]');
    if (oldScript) {
        document.head.removeChild(oldScript);
    }
    document.head.appendChild(script);
}

// URL der zu ladenden Skriptdatei
var scriptUrl = '/media/tabsaccordions/js/script.min.js';

// Funktion zum Aufrufen der init-Funktion, nachdem das Skript geladen wurde
function initAfterLoad() {
    if (typeof RegularLabs !== 'undefined' && RegularLabs.TabsAccordions && RegularLabs.TabsAccordions.init) {
        RegularLabs.TabsAccordions.init(null);
    } else {
        console.error('RegularLabs.TabsAccordions ist nicht definiert.');
    }
}

// Laden des Skripts und Ausführen der Initialisierungsfunktion
loadScript(scriptUrl, initAfterLoad);
</script>

See it in action:

sapodoris.de/shop-kategorien/magen-darm/herbagast-6-detail

Have a nice day!

Regards
Michael
You can only post on this forum if you log in