Looking for a bubble plugin developer!

Hi Bubblers,

I am looking for a plugin developer who can fix my plugin and advise on plugin development . Willing to pay for what should be a 3-5 hour job.

Do DM me, thanks!

Regards,
Jordan

Which type of plugins is it? Element VS action VS API are very different…
What is your issue with your plugin? What your plugin do?

Hey @Jici ,

The plugin is a menu bar plugin. When I put 2 of them in a page, the second element does not appear. Somehow, both elements get linked and the first element shows the data of the second element.

Have you encountered such an issue before? Is there something I can do to ensure each element do not affect each other?

This is the element code:

<style> 
    .text {
    	display: block;
    	text-align: center;
	}

	.listMobile {
    	display: flex;
    	flex-direction: column;
    	align-items: center;
    	gap: 8px;
    	padding: 8px 64px;
	}

	.listDesktop {
    	display: flex;
    	gap: 12px;
    	padding: 8px 4px;
    	min-width: fit-content;
	}

	.selector {
    	display: block;
    	position: absolute;
    	height: calc(100% - 8px);
    	/* To account for padding */
    	top: 4px;
    	left: 0;
    	transform: translateY(0);
    	transition: all 0.3s ease;
    	z-index: 0;
    	border-radius: 100px;
        box-shadow: 2px 2px 4px #FFFFFF30 inset;
	}

	.menu.active {
    	cursor: pointer;
    	position: relative;
    	z-index: 1;
    	padding: 4px 16px;
	}

	.menu.active.selected {
    	font-weight: 600;
	}

	.menu.hidden {
    	display: none;
	}
    
</style>

Initialize:

function(instance, context) {
    
    $(instance.canvas).append(`<div class="menu-container">
        <div class="listMobile" id="menu-list">
            <div class="selector"></div>
            <div class="menu" data-index="0"><span class="text"></span></div>
            <div class="menu" data-index="1"><span class="text"></span></div>
            <div class="menu" data-index="2"><span class="text"></span></div>
            <div class="menu" data-index="3"><span class="text"></span></div>
            <div class="menu" data-index="4"><span class="text"></span></div>
            <div class="menu" data-index="5"><span class="text"></span></div>
            <div class="menu" data-index="6"><span class="text"></span></div>
            <div class="menu" data-index="7"><span class="text"></span></div>
            <div class="menu" data-index="8"><span class="text"></span></div>
            <div class="menu" data-index="9"><span class="text"></span></div>
        </div>
        </div>`)
    
    const menuList = document.getElementById("menu-list");
    const container = document.querySelector(".menu-container");
    
    if (document.documentElement.clientWidth < 500){
        menuList.classList = "listMobile";
        container.style.borderRadius = "16px";
    }
    else {
        menuList.classList = "listDesktop";
        container.style.borderRadius = "100px";
    }
    

}

update

function(instance, properties, context) {
    
    const container = document.querySelector(".menu-container");
    const selector = document.querySelector(".selector");
    const menuItems = document.querySelectorAll(".menu");
    const menuTexts = document.querySelectorAll(".text");
    
    const menuList = document.getElementById("menu-list");
    
    var currentNav = "";
        
    let length = properties.tab.length(),
        tabText = properties.tab.get(0, length),
        tabColor = properties.tab_color,
        containerColor = properties.container_color;
    
    selector.style.backgroundColor = tabColor;
    container.style.backgroundColor = containerColor;
    
    
    /*function toggleClass() {
        
        if (menuList.classList.contains("show")){
            menuList.classList.remove("show");
            console.log("remove show");
        } 
        else {
            menuList.classList.add("show");
            console.log("show");
        }
	}*/
    
    function updateSelectorPosition(item){
        const itemRect = item.getBoundingClientRect();
        const listRect = document.querySelector(".listDesktop").getBoundingClientRect();
        
        selector.style.width = `${itemRect.width}px`;
        selector.style.top = `${4}px`;
        selector.style.height = `${listRect.height - 8}px`;
        selector.style.left = `${itemRect.left - listRect.left}px`;
    }
    
    function updateSelectorPositionM(item){
        const itemRect = item.getBoundingClientRect();
        const listMRect = document.querySelector(".listMobile").getBoundingClientRect();
        
        selector.style.width = `${listMRect.width - 44}px`;
        selector.style.height = `${itemRect.height + 8}px`;
        selector.style.top = `${itemRect.top - 4}px`;
        selector.style.left = `${listMRect.left + 4}px`;
    }
    
    // actively trace window size
	window.addEventListener("resize", () => {
        
        if (document.documentElement.clientWidth < 500){
            menuList.classList = "listMobile";
            container.style.borderRadius = "16px";
        }
        
        else {
            menuList.classList = "listDesktop";
            container.style.borderRadius = "100px";
        }
    });
    
    // Save references to original functions
	/*const originalPushState = history.pushState;
	const originalReplaceState = history.replaceState;

	// Override pushState
	history.pushState = function (...args) {
  		originalPushState.apply(history, args);
  		window.dispatchEvent(new Event("urlChange"));
	};

	// Override replaceState
	history.replaceState = function (...args) {
  		originalReplaceState.apply(history, args);
  		window.dispatchEvent(new Event("urlChange"));
	};*/
    
    window.addEventListener("popstate", () => {
        currentNav = window.location.pathname;     
        const strings = currentNav.split("/");
        currentNav = strings[3];
        
        menuItems.forEach((i) => i.classList.remove("selected"));
        
        for (let i = 0; i < length; i++){
        	const urlPath = menuTexts[i].textContent;
            const lowerCasePath = urlPath.toLowerCase();
            
        	if (currentNav == lowerCasePath){
                menuItems[i].classList.add("selected");
                updateSelectorPosition(menuItems[i]);
                instance.publishState('path', menuItems[i].textContent.toLowerCase());
                console.log(menuItems[i].textContent.toLowerCase())
            }
    	}
        
	});
    
    /* menuHamBurger.addEventListener("click", () => {
        
        if (menuList.classList.contains("show")){
            menuList.classList.remove("show");
            console.log("remove show");
        } 
        else {
            menuList.classList.add("show");
            console.log("show");
        }
    });*/
    
    for (let i = 0; i < length; i++){
        menuItems[i].classList.add("active");
        menuTexts[i].textContent = tabText[i];
    }
    
    for (let i = length; i < 10; i++){
        menuItems[i].classList.add("hidden");
    }
    
    const noSelector = document.querySelector(".menu.selected");
    
    if (noSelector===null){
        menuItems[0].classList.add("selected");
        
        menuTexts.forEach((i) => {
        const textRect = i.getBoundingClientRect();
        i.style.width = `${textRect.width + 8}px`;
    	});
             
    }
    
    if (document.documentElement.clientWidth >= 500)
        updateSelectorPosition(document.querySelector(".menu.selected"));
    else
        updateSelectorPositionM(document.querySelector(".menu.selected"));
    
    menuItems.forEach((item) => {
        item.addEventListener("click", () => {
            // Remove .active from all menu item
            menuItems.forEach((i) => i.classList.remove("selected"));
            
            // Add .active into clicked menu item
            item.classList.add("selected");
            
            // Update the selector position and size
            if (document.documentElement.clientWidth >= 500)
            	updateSelectorPosition(item);           
            else
            	updateSelectorPositionM(item);
            
            if (document.documentElement.clientWidth < 500)
                menuList.classList.remove("show");
            
            instance.publishState('path', item.textContent.toLowerCase());

            instance.triggerEvent('click');
            
            /*console.log("test")
            
            currentNav = window.location.pathname;     
        	const strings = currentNav.split("/");
        	strings[3] = item.textContent;
            
            const joinString = strings.join("/");
            
            console.log(joinString)
            
            window.history.pushState({}, "", joinString);
            console.log("Redirected to /new-path");*/
        });
    });

}

Each element need to have a unique ID so you can reference this element using the unique ID instead of a “static” element id (or class)
Show example:

function(instance, context) {
  instance.data.divName = "id"+Math.round(Math.random()*1000000) + 1;
  var newDiv = $('<div id="'+instance.data.divName+'"></div>');
	instance.canvas.append(newDiv);
    instance.data.savedcanvas = instance.canvas

}

You will need to consider modifying your other reference to any element to also reference the “top” div unique id. Not just “menu-list” for example…

1 Like

I see…could you advise on one more question please?

After i give the div a Name using instance.data.myvariable in function “initialize”, in the function “update”, how can I indicate which div to update?

@Jici

instance.data is a stored value that you can use after in all code part (initialize, update…) so you can use jquery or JS to the element like
document.getElementById(instance.data.divname) and if you want list mobile for example
var listmobile= instance.data.divname+“.listMobile”
document.getElementById(listmobile) should work I guess

For menu element, you may need to use a foreach (but I think you may already have this in your script)