Looking For Some Suggestions on How To Go About Refactoring My Code

Hey, everyone. I’ve been creating a pizza builder using velo and I’m trying to figure out a way to refactor my code so I’m not repeating a ton of functions.

I’ve got this function I wrote to handle showing/hiding the topping images on the pizza. There will be quite a few toppings option so repeating this 20 times or whatnot will be super inefficient.


    $w('#pepperoniCheckbox').onChange(() => {
        if ($w('#pepperoniCheckbox').checked) {
            $w('#pepperoni').show();
        } else {
            $w('#pepperoni').hide();
        }
    });

I also have this function which handles selecting the pizza size, transitioning to the toppings container and presenting a message to show what size was chosen.

    $w('#pizzaSizeSmall').onClick(() => {
		let buttonText = $w('#pizzaSizeSmall').label;
        let fadeOptions = {
			"duration": 250,
			"delay": 0
		};
        $w('#toppingsContainer').show("fade", fadeOptions);
        $w('#pizzaSizesContainer').hide("fade", fadeOptions);
		$w('#pizzaSizeMsg').text = `Your selected size is ${buttonText}!`;
    });

Like I said, I don’t think repeating all these functions is the best way to go about this. I figure there has to be a way to refactor this to be more efficient. I’m pretty new to javascript so I’m not sure how to go about it.

Anyone have any suggestions?

https://community.wix.com/velo/forum/velo-pro-discussion/is-there-a-way-to-get-this-more-flexible-variable-and-more-compressed

Thanks for your reply @russian-dima . I took a look at that post and it I think that this all might be just a bit above my head currently. I took a shot at it though.

Here was my unsuccessful attempt at creating a refactored version of one of the code snippets:

$w('#pizzaSizeSmall').onClick(sizesToToppings);

function sizesToToppings(event) {
    const element = event.target;
    let fadeOptions = {
        "duration": 250,
        "delay": 0
    };
    $w('#pizzaSizesContainer').show('fade', fadeOptions);
    $w('#toppingsContainer').hide('fade', fadeOptions);
    console.log('Its working');

}

The message is logging to the console but nothing else seems to be working. What am I doing wrong?

$w('#pizzaSizeSmall').onClick((event)=>{
	console.log(event.target.id+"-clicked !!!);
	myFunction(event)
});

$w('#pizzaSizeMedium').onClick((event)=>{
	console.log(event.target.id+"-clicked !!!);
	myFunction(event)
});

$w('#pizzaSizeBig').onClick((event)=>{
	console.log(event.target.id+"-clicked!!!");
	myFunction(event)
});

function myFunction(event){
	console.log("MyFunction running...);
	const element=event.target; 
	console.log("Clicked-Element-Data: ", element);
	const elementID = event.target.id
	console.log("Clicked-Element-ID: ", elementID);
	let options={"duration":250,"delay":0};
	$w('#pizzaSizesContainer').show('fade', options);
	$w('#toppingsContainer').hide('fade', options);
}

Read this for more improving potential / possibilities…

!!! Good-luck and happy coding !!!

Oh man I figured it out. I’m a massive idiot. I really have no idea how I did this but I managed to somehow switch which element was being hidden and which was being shown. I had it reversed.

I’m sorry if I wasted your time. I did learn a bunch in the process though! So I thank you for that and your willingness to help me!

I didn’t realize you could select multiple elements with the $w api just by separating the IDs by commas. That’s super helpful!

Hey @russian-dima - I’ve been looking over the two threads you’ve provided as I try to refactor the onClick function from my original post and I’m trying to figure out a way to make it as dynamic and flexible as possible. This is the idea I have:

I have two tasks I need to achieve. 1) listen to the checkboxes for a change (checked or not checked) and 2) change whether an element is hidden or shown based on that change. So if myCheckbox is checked then myElement will be shown, and visa versa. What I’m struggling with is linking these two tasks. An idea I had was to somehow use the partial ID of the checkbox and check it against an array of elements to see if any of the IDs of those elements contain that part of the checkbox ID. For example:

checkbox with the ID of ‘#pepperoniCheckbox’ would use ‘pepperoni’ to search for the corresponding element in the array which could have an ID of ‘#pepperoniIMG’.

Do you know if that possible with Velo? I’ve been searching the reference documentation looking for some kind of way to implement this idea but I can’t seem to come up with anything.

I think you can select an element using a partial id with pure javascript using:
querySelectorAll([ID^="string");

Is this something I would have to use an external js file for?

The more dynamic you want to make it → the more you will have to use complex coding —> the more complex coding you want to use → the more knowledge you will need about JS and it’s coding techniques.

Normaly i do not give learning lessons if it comes to complex-coding, but let’s do an exception.

How to generate complex coding (dynamic functions) in your case?

  1. Well, first you will have to make clear, what exactly is/are your tasks ???

  2. Which functions you will have to generate for ???

  3. Where to place that complex generated codings???

  4. So, for the first checkpoint you already have defined your tasks…

I have two tasks I need to achieve.

  1. listen to the checkboxes for a change (checked or not checked) and
  1. change whether an element is hidden or shown based on that change.

But let’s dive even deeper!!! Are these 2-tasks already enough?
What about → how to detect all checkboxes on your page automatically?
Let’s start with this task…

A good programmer is not just able to code, he is also able to turn normal spoken speechtext into code.

What about → how to detect all checkboxes on your page automatically?
What you can read here in this quote? And which thoughts do you already have → if it comes to coding? How you would code this short piece of text-quote?
Which information you can get out of this short quote?

This is what i would do, if i would start to generate a code, accordingly to this quote…

  1. function = detect_Checkboxes()
  2. used elements = $w(‘#page1’) + $w(‘#checkbox’)
  3. technique → looping trough (for loop or foreach-loop)
  4. task(s) →
    a) getting all pages elements
    b) searching for all CHECKBOXES or CHECKBOX-GROUPS
    c) Collecting all CHECKBOX-ELEMENTS into an ARRAY
    d) doing the same for checkbox-groups
    e) paying attention onto the fact, that that elements could be placed on several different level.

So, now when we know what exactly is our task, let’s start to code it…

CODE : → find all page-elements…

function get_pageElements2(page) {console.log("Page: ", page);
    let foundButtons=[], foundSubButtons=[], foundLevel3Buttons=[];
    let mainChildElements=[], subChildElements=[], level3ChildElements=[];

    find_MainElements(page);
    
    function find_MainElements(page) {
        mainChildElements = page.children   ;
        find_SubElements(mainChildElements);    
    }

    function find_SubElements(mainChildElements) {
        for (let i=0; i<mainChildElements.length; i++) {
            const mainChild=mainChildElements[i]; //console.log("Main-Child-Element: ", mainChild);
            const subChilds=mainChild.children; //console.log("Sub-Child-Elements: ",subChilds);
            if(mainChild.children) {
                subChildElements.push(subChilds);
            }
            if(i===mainChildElements.length-1) {
                //console.log("Sub-Child-Elements", subChildElements);
                find_level3Elements(subChildElements);
            }           
        }   
    }
    function find_level3Elements(subChildElements) {
        for (let i=0; i<subChildElements.length; i++) {
            const subChild=subChildElements[i]; //console.log("Sub-Child: ", subChild);
            const level3Childs=subChild[0].children; //console.log("Level3-Childs: ", level3Childs);
            if(subChild.children) {
                if (subChild.children[0].length>0) {}
                    level3ChildElements.push(level3Childs[0]);
                }
                else {level3ChildElements.push(level3Childs);}
            if(i===subChildElements.length-1) {//console.log("Level3-Child-Elements", level3ChildElements);
                //find_level3Elements(mainChildElements);
            }           
        }   
    }   
}

…so running this code on a page…
it will find all elements on 3 different levels.

  1. Main-Level
  2. Sub-Level
  3. Sub-Sub-Level (Level-3)

Let’s see what we get, when running this code…


As we can see, our created function found all elements on the page (in a depth of 3-level). But what exactly does it mean, when we say in a depth of 3-levels?

Well, when placing the buttons directly onto our page → it will be → LEVEL-1.

Placing our buttons into a → BOX → which is on our page → our buttons will go to —> LEVEL-2.

Placing a → BUTTON ← into a → ColumnStrip ← will create automatically a → 3-level stacked BUTTON.

So, we are able now, to find all elements on different levels of our page.

What else do we need?
Of course !!! → We have to find only the elements we need, in our case → BUTTONS.

That means we will need to expand our code, giving it more intelligence…
…adding to it something like…

if(subChildElement.type==="$w.Button") {
    foundButtons.push(subChildElement);
}
if(subChildElement.type==="$w.Box") {
    foundGroups.push(subChildElement);
    if(subChildElement.children) {
        subChildElement.children.forEach(subSubChildren=> {
            if(subSubChildren.type==="$w.Button") {
                foundSubButtons.push(subSubChildren);
             }
        });
    }
}

…and so on…

So when our function would be ready → it would be able to find only BUTTONS on all different LEVELS of our PAGE.

But wait, do we really have to code all that function?
Isn’t there a better and much easier way of doing the same, like described above?

What about…

$w('Button').onClick((event) =>{
    console.log(event.target.id+"- has been clicked!!!");
});

…already tried it?

Try it out!!!

  1. Place several buttons on different LEVELS on your page.
  2. Add the above code.
  3. Click onto the buttons
  4. See results inside → CONSOLE !!!

  1. Start your brainstorming !!!

Maybe you would now say → But wait you are doing it for → BUTTONS <— and not for —> Checkboxes <—.

Let’s do it for CHECKBOXES…

$w('Checkbox').onChange((event) =>{
    console.log(event.target.id+"- has been clicked!!!");
});

Let’s do it for CHECKBOX-GROUPS…

$w('CheckboxGroup').onChange((event) =>{
    console.log(event.target.id+"- has been clicked!!!");
});

And also do not forget to change the trigger…
onClick()
onChange()
onDoubleClick
…and so on

Which elements else, do support this functionality?
Try it out and test it!!!

!!! Solution in 1-3 code-lines !!!

Thank you @russian-dima for your time and patience. I appreciate your willingness to help me and I am grateful that you’ve made an exception to give me a lesson in how you go about creating complex functions. It’s very helpful as I am still very much in the learning process.

I see what you’re doing here, for the most part and I will use this knowledge you have bestowed upon me to try and find a solution.

So far I’ve been able to come up with this, which almost works:

$w('Checkbox').onChange((event) => {
        console.log(event.target.id);
        const checkID = event.target;
        const label = checkID.label;
        console.log(label);

        let toppingImage = $w('#toppingImages').children;

        for (let i = 0; i <= toppingImage.length; i++) {
            if (toppingImage[i].hidden === true) {
                console.log('working');
                console.log(toppingImage[i]);

                if (toppingImage[i].id === label) {

                    console.log('working also');
                    if (toppingImage[i].hidden === true) {
                        toppingImage[i].show();
                        console.log('working also 2');
                        console.log(toppingImage[i].hidden);
                    } else if (toppingImage[i].hidden === false) {
                        toppingImage[i].hide();
                        console.log('working also 3');
                    }
                }
            }
        }
    }
);

the only issue i have with this is the else if at the end of the function doesn’t work.

Thank you for your assistance with all this. I’ve been learning a lot and I do very much appreciate it.

So far I’ve been able to come up with this, which almost works:

Almost working <----> sounds good!

I also can see that you have learned to use → THE CONSOLE (console-logs)!!!
Maybe the most important part of coding.

Go ahead, understand whats happening at each of code-line.
Learn, improve, or even generate your own coding techniques.

Some tips?

  1. Try always to code → DYNAMIC (no fixed coding)!!!
    Do not code the way, so if you change once an element or just an element-ID, so that all your code breaks. Code it the stable way → so no matter what you do on your page —> but the code (system) never breaks.

  2. Try always to code → SYSTEMATICALLY (no up-down-coding)
    a) for example using systematic ELEMENT-IDS…

    Button ------> ID=btn+NAME → btn Submission
    Button ------> ID=btn+NAME → btn Next
    Button ------> ID=btn+NAME → btn Previous
    Button ------> ID=btn+NAME → btn Whatever…

    Checkbox → ID=cbx+NAME → cbx MyCheckbox1
    Checkbox → ID=cbx+NAME → cbx MyCities
    Checkbox → ID=cbx+NAME → cbx Whatever…

    …and so on… —> for all of used elements…

At this point just ask yourself, why this systematic coding could help you and how? Also ask yourself → why using a 3-digit-prefix insted of a 1, or 2-digit-prefix?
But also why not using a 4, 5, or more digit-prefix?

What the hell is a prefix? → “btn” / “cbx” / “cgb” / “rtb” ???
What for could stand this prefixes for?
1) btn —> you already know!
2) cbx —> you also already know!
3) cbg —> ???
4) rtb ----> ???
5) and so on…

Why not change the order and trying to use something like… “SubmissionBtn” ?
Or even worse…—> “Submissionbutton”

And why you never should mix the prefixLength inside your code?

b)... 

c)...and so on.... 
  1. Using EXPORTED-FUNCTIONS, either on Public JS-Files, or on Backend (depending on the security-level of the functions)

  2. There a even many more checkpoints… but that would break my time-limit, if i would start to talk about all my already memorized and self-generated coding techniques.

5) —> The more you code —> the more you will get and generate your own coding technique(s)!

There is so much to learn → There are so much improving techniques out there in the Worl-Wide-Web!