Making of my project calculator (2/3)

We continue with part 2, this time in English.
Wir machen weiter mit Teil 2, diesmal auf Englisch.

Again I made some adjustments to the JSON file to make it on the one hand comply to standards (and not have weird data conversion in the code), while on the other hand keep it easy to use. That’s why I made one exception to the otherwise „flawless“ JSON and titled the three examples with A, B and C, cause they are automatically sorted alphabetically. I could have sorted it in the code using the ID of each element, but that way saved me a few lines of pretty ugly sorting, so simplicity wins here. Finally I started to work on the actual code. I tied it to the window.load event and fetch the JSON, „load“ in my „templates“, both in quotes cause I actually don’t load anything, but it’s easier to understand what happens here, if you imagined I would load some smarty-like template file. In the screenshot you can see, the templating part does work as expected, but the JSON part does not yet. On top I have to find a way to deal with some Options having a single value, while others have an array of values, but each array value should be displayed repeadately with it’s key, like this: „Additional Option“: „foo“, „Additional Option“: „bar“, … while JSON doesn’t allow for repetition of keys. I’ll fix the issues and we should be finished with that part – then we can start working on the calculator.

On the next day, with a fresh mind, it only took me about 30min to make a few more adjustments to the JSON file and adjusting the JavaScript code as well. And now we have, with very little code, using the art of Functional Programming (bit of ES6 Promisse is also involved) generated the complete list. It’s exceptionally clean, from my point of view, probably less than a Kilobyte of code and data (no bulky framework involved), very easy to adapt, extend and to move forward from here.
Now you may ask, why did I need more than a day just for this little bit of code? Most of this for me is not just „coding away“ – there’s a bit of research involved, trial and error to find THE solution and not just A solution (or copy random stuff from StackExchange). And it’s been almost a year since I last did Functional Programming and modern JavaScript app development. But after a slow start I usually gain a bit of speed 😉

I still have one last problem to solve as mentioned before, the list of additional services now is just one point on the lower right of the „Pixel Perfekt“ box, but I want them as individual items.

One typeof check if the current Key is another object (there’s no real arrays in JavaScript) and not just a string, we can iterate over that as well and get the desired result. Last thing missing for the static example lists is adding the id „most-popular“ to one of the items, fixing this problem actually made the code a bit shorter again. At this point, the code is not made „safe“ at any point. I do that on purpose. This is not the security-type of „not safe“, but just the fact that the code could break, if e.g. the JSON is not in the proper format. Regarding the type of application and the fact that a JSON provided not in our format would lead to the same endresult anyway, a non-working app, I decided to keep the code clean from those checks yet, but may add them later if I feel it’s the right thing to do. There’s a little bit of duplicate code (planList += listTemplate…), but technically that’s just one line, so I don’t bother right now making a new function for that. In the next section we will add an eventlistener for the button-click, write a cookie with the predefined values and serve that to the actual customizer. For the customizer I planed to move 2 boxes out of the way and provide a clean interface for changing each value, along with a calculator that takes all factors into account to calculate the total duration and possible cost.

First I added the eventlistener ES6 style to the link button – I also went back to the Template and added a data-attribute to the link as well as changed the function replace() to replaceAll() so I can easily access the name of the clicked profile. I also passed the JSON object on to the event. This part is another source for a few mistakes, e.g. we could accidently pass the event object instead of the JSON object (independent of the actual name we type) – if that happens, beginner often retreat to using globals. But as you can see, this is not neccessary here (and most of the time you code, it is not). And once more, important is not what we know right of the bat, but HOW we work. I wasn’t sure how to get the data from the clicked element, so I simply logged the „e“ and checked in the console, what I have available. I found there’s e.g. e.originalTarget, but this wouldn’t let me access the getAttribute(data) method. Via StackOverflow I found out that JQuery uses instead, so I used that one too, and it worked reliably.

I will move off from „generic“ now a bit, cause I want to save a bit of time and it’s no problem to adapt the code later either way. But if I wanted to keep it mostly generic, I would have added a meta-section in the JSON to provide me with additional IDs and class names, which we will be using next to hide the other two plans.

In this version quite a bit has changed, in fact another 10h workday lay in between this code and the previous version. Experienced JavaScript coders may have noticed one initial mistake I made, using anonymous functions as eventlistener callbacks only worked out as long as I didn’t try to remove them – which I eventually had to. I also had to go into the JSON file again and do couple of retouches, mainly typos or not labeling some things consistently.

But therefor we now have a fully working UI without any glitches in pure, vanilla JavaScript. Why do that anyway? I’ve coded my first UI in Borland Pascal at the age of 12, a painting programm. Back then we simply didn’t HAVE any visual builders, Windows Forms or frameworks for Web UIs. Coding all UI elements and behaviour yourself is a bit of work, and nothing I would do on a bigger client project, just to get this straight. But it’s a skill super-valuable on every-day Website projects – My last Website was also heavy on JavaScript, that was before JS came to the world-wide fame it has now.

My last project I made with Node.js and JQuery in the frontend. So I thought: If I can do it with JQuery instead of, say, something like Angular.js, I can do it without any third-party-framework. Yeah, that took a bit more time, but I also learned a lot. For a project bigger than this, I wouldn’t recommend this method. The code has, besides all efforts, become a bit too long for a vanilla JS project (imo), although roughly 200 lines is not too shabby for such an app.

I only lag 3 more things, but these should go rather quick:
1.) The ability to add or remove the „Additional Services (Zusatzleistungen)“ elements
2.) The actual calculations for time and price
3.) The „Get Quote“ button which will be tied to PayPal, cause these quotes will cost money. Why am I doing that? I got a lot of fake requests in the last couple of years, and no serious company will take offense in charging for a quote, on a 5000-25000€ project anyways.

Follow-up in part 3, where we will build in the Paygate, finalize the project and wrap it into a WordPress plugin.
Es folgt Teil 3, in dem wir das Paygate einbauen, das Projekt zu Ende bringen und in ein WordPress-Plugin packen.

Manuel Geissinger, zertifizierter IT-Sicherheitsexperte, Webedesigner aus Freiburg, Webentwickler, Administrator und Digitalkünstler.
Ihr freiburger Webentwickler Nr. 1 auf LinkedIn Zertifizierter IT Sicherheits-Experte & Webdesigner auf Xing