# Looking for a bubble plugin developer!

**URL:** <https://forum.bubble.io/t/looking-for-a-bubble-plugin-developer/363905>\
**Category:** Plugins\
**Created:** [March 20, 2025, 7:06am UTC](https://forum.bubble.io/t/looking-for-a-bubble-plugin-developer/363905 "2025-03-20T07:06:17Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![nocodejordan](https://sea1.discourse-cdn.com/bubble/user_avatar/forum.bubble.io/nocodejordan/32/123255_2.png) [@nocodejordan](https://forum.bubble.io/u/nocodejordan)\
**Post date:** [March 20, 2025, 7:06am UTC](https://forum.bubble.io/t/looking-for-a-bubble-plugin-developer/363905/1 "2025-03-20T07:06:17Z")

</div>

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

---

<div class="post-metadata">

**Author:** ![Jici](https://sea1.discourse-cdn.com/bubble/user_avatar/forum.bubble.io/jici/32/30722_2.png) [@Jici](https://forum.bubble.io/u/Jici)\
**Post date:** [March 20, 2025, 1:28pm UTC](https://forum.bubble.io/t/looking-for-a-bubble-plugin-developer/363905/2 "2025-03-20T13:28:20Z")

</div>

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?

---

<div class="post-metadata">

**Author:** ![nocodejordan](https://sea1.discourse-cdn.com/bubble/user_avatar/forum.bubble.io/nocodejordan/32/123255_2.png) [@nocodejordan](https://forum.bubble.io/u/nocodejordan)\
**Post date:** [March 20, 2025, 3:06pm UTC](https://forum.bubble.io/t/looking-for-a-bubble-plugin-developer/363905/3 "2025-03-20T15:06:15Z")

</div>

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?

---

<div class="post-metadata">

**Author:** ![nocodejordan](https://sea1.discourse-cdn.com/bubble/user_avatar/forum.bubble.io/nocodejordan/32/123255_2.png) [@nocodejordan](https://forum.bubble.io/u/nocodejordan)\
**Post date:** [March 20, 2025, 3:08pm UTC](https://forum.bubble.io/t/looking-for-a-bubble-plugin-developer/363905/4 "2025-03-20T15:08:42Z")

</div>

This is the element code:

```auto
<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:

```auto
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

```auto
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");*/
        });
    });

}

```

---

<div class="post-metadata">

**Author:** ![Jici](https://sea1.discourse-cdn.com/bubble/user_avatar/forum.bubble.io/jici/32/30722_2.png) [@Jici](https://forum.bubble.io/u/Jici)\
**Post date:** [March 20, 2025, 3:11pm UTC](https://forum.bubble.io/t/looking-for-a-bubble-plugin-developer/363905/5 "2025-03-20T15:11:24Z")

</div>

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:

```auto
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…

---

<div class="post-metadata">

**Author:** ![nocodejordan](https://sea1.discourse-cdn.com/bubble/user_avatar/forum.bubble.io/nocodejordan/32/123255_2.png) [@nocodejordan](https://forum.bubble.io/u/nocodejordan)\
**Post date:** [March 20, 2025, 4:13pm UTC](https://forum.bubble.io/t/looking-for-a-bubble-plugin-developer/363905/6 "2025-03-20T16:13:46Z")

</div>

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

---

<div class="post-metadata">

**Author:** ![Jici](https://sea1.discourse-cdn.com/bubble/user_avatar/forum.bubble.io/jici/32/30722_2.png) [@Jici](https://forum.bubble.io/u/Jici)\
**Post date:** [March 20, 2025, 5:07pm UTC](https://forum.bubble.io/t/looking-for-a-bubble-plugin-developer/363905/7 "2025-03-20T17:07:19Z")

</div>

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)
