Taking the Slow Road

The JS30 course from master instructor Wes Bos is really cool.  It includes 30 small* projects that really only involve JS/HTML/CSS- no libraries, frameworks, etc.  I’ve been working as a developer for long enough that I know some of the info already, but even if I see the title of a video and say “Awesome- I know that one!”, I can still learn something useful.  That’s part of the beauty of coding- once you get past the basics of syntax and making things run, there are many different ways one program can be written (and with JS, even the syntax can be a point of departure: semicolons anyone?).  It’s always good to see how someone else does it- you’ll almost always learn something new.

Generally, I’ll check out the first part of the video to see what we’re building, stop it, and go try to implement myself.  Then, I’ll watch the rest after either: A) I finish my version, or B) I get to a point where I’m not sure where to go next.

Example: one of the videos covers creating a cool sliding panel full screen image viewer.  My original version worked (using simple colors instead of images as a background), but I did not know you could animate the flex property on an element.  That’s how Wes did it in the rest of the video, so when I went back to re-do the project, I tried that instead.  It made the code much cleaner- in my original version, the css width values for the panel, grow, and shrink classes would have to be updated if I wanted to have 4 panels instead of 3- and the transition never quite had the exact width property (if you switch hover fast enough, you see the background image).  Also, I know animating width is generally not a great idea for performance as it triggers the unholy trinity of layout, paint, and compositing in the browser.  A quick check of https://csstriggers.com/ tells me flex does the same, but I tried using a more performance-friendly transform (scale) and it just did not look right, so a little less than 60fps will have to do!

If there’s one takeaway from this post, it should be that there are many paths to a working program.  I definitely don’t always find the best way on the first try- but if I approach the problem with the mindset of getting it working, then iterating until it works really well, I usually get the best results.

If there’s another takeaway, it’s that Wes’ courses are awesome (I learned most of what I know about React from his great course on that topic).  Some are free, some are paid- all are well worth doing.

But the final takeaway (I know, that’s three now) involves that asterisk from the very beginning of this post.  The idea behind JS30 is to do one project per day for 30 days.  And if you stick to just the parameters of what Wes lays out, you can definitely do that.  But it’s so easy to get carried away.  Is a program ever really done?  Eventually, you get to a point where it works and works well and you ship it- but it seems like there are always improvements that can be made or new techniques to be learned.  At work, you usually have someone reminding you that there is a deadline for a project, but with side projects, it’s easy to give in to scope creep.

Sometimes it’s not too bad.  For my updated version of the sliding panels gallery project above, I did a little mobile version that simply switches the flex direction to column and transforms to horizontal.  I also added a slight ‘screen’ effect over each image to allow for the text to show a bit better on the images I chose (learned this can be accomplished using a linear gradient as the background image).

//creates a soft darkening on the bg image without affecting the text color as opacity would
background-image: linear-gradient(rgba(0,0,0,0.3),rgba(0,0,0,0.3)), url('./img/tree.jpg');

On that same project, I decided I wanted a user to be able to click/tap any panel to have it open and have all others close (even if one is already open)- more of an accordion effect.  That was just a matter of adding a simple JS function:

function removeClassFromArray(elementArray, className) {
    elementArray.forEach(function(ele) {
        ele.classList.remove(className);
    });
}

I added it to the click handler for each, before the line where I set the ‘open-active’ class to the panel that should be in focus. This ensures only one panel is open at a time.

So, nothing too crazy- still a one day project.  But then there was the Fetch API project.  I feel like I know Promises and working with async code pretty well, so initially this one was going quickly.  However, as I finished up, I realized there was so much left to do!  A user can get the city population, sure- but what then?  Well, adding the total result count and total population wasn’t too hard.  But the total population number looked off.  There were no commas- so I created a function to add them (likely point for future optimization):

function numWithCommas(num) {
    let strArray = String(num).split('');
    let withCommas = [];

    var count = 0;
    for(let i = strArray.length - 1; i >= 0; i -= 1) {
        if(count === 3) {
            withCommas.unshift(',');
            count = 0;
        }
        withCommas.unshift(strArray[i]);
        count += 1;
    }
    return withCommas.join('');
}

Cool, so now we have a running total of results and the total population from all the results.  That’s not super useful though.  Wikipedia has a pretty cool API, why not grab info from that if they click on any result.  That will provide a blurb and link to the full article.  And we should have some kind of notification or feedback when info loads or something goes wrong. And stick the input to the header if they scroll down a huge list of results.  And if we put a listener on the scroll event, we will need a debounce function to not harm performance (that one’s very interesting- might dig into it next week).

You see where this is headed.  The todo list on the Fetch project is still growing to this day (mobile, better animations, etc)- though I’ve moved on to other projects for now.  JS30 has become more like JS300, but I feel like I’m still abiding by the spirit of the exercise.  That is, daily exercise for your coding muscles.

Advertisements

Form Autofill Follies

Been a bit lazy lately, but trying to get back in the groove of writing this thing.  Had a lot of failures lately, so let’s talk about one of those!

I was working to redesign our login screen.  It works fine, but is very basic.  Time to add some jQuery flash!

The idea was to absoultely position the form labels (username and password) over the input fields (which were styled to appear just as underlines).  When a user clicks on a field (or focuses there via tab), the label animates to the right of the input field and shrinks down.  If the input blurs, there are two options: 1) if the user entered something, the label stays small and out of the way.  2) if the user didn’t enter anything, the label grows and moves back into place.

And it worked great!  Took some tweaking to work properly, but I thought it was a cool little trick.  But in my testing, I finally used a browser that had stored credentials for the login screen and everything fell apart.

Different browsers have different events when they autofill fields, and it seems none really broadcast those events to hook into.  As a result, if a user stored their credentials, they were greeted with text on text (their credentials, overlaid with the input labels).  The focus events didn’t fire.

So I scrapped all that and just went with a simple setup of labels over basic input fields with some useful placeholder text.  It’s really fun to create cool looking interfaces, and when it finally works, I always get a rush from the accomplishment.  But it’s important to remember that users don’t care about your rush.  They just want to log in to the damn site, so make it as easy as possible!

If you’re curious about what might have been, I cooked up a quick codepen to show a general idea.  Check it out at http://codepen.io/joedriscoll79/pen/NNoGrv

Feel free to tell me how ugly it is- I though it was kind of cool.  Have an idea for how it might work better (or at all with autofill)?  Let’s discuss!

 

Grunt with the Effort

I was tasked to find a good service to concatenate/minify our javascript and css files.  Of course, I’d heard of these words before, but never actually used the techniques.  My other major project involved some very old practices, including inserting php directly into a css file (and rarely, a js file), so minifying would absolutely not work.

But I’d heard of a couple- Gulp and Grunt for example- so I took on the project.  I checked out Grunt first, for that time-honored reason: the alphabet.

And it’s awesome.  It was a little intimidating at first, but after going through the initial setup (pretty easy with npm) and taking a little bit to learn about the two core files (package.json and the gruntfile), I found it to be really friendly to work with.  After all, it’s really just a bunch of javascript, and I like working with that!

The stumbling would come later, when I realized that our new project was built in Angular JS by many different developers.  With no current js or css style guide, I started to run into trouble.  The minifier doesn’t like Angular’s syntax on some things, particularly templateUrl within a directive, but setting the ‘mangle’ config option to false seemed to help.

Minifying was working, but concatenating is still not.  There are errors or unclosed tags somewhere in a directive (not written by me!  I never make mistakes- really boss!).  Somehow, they work in a full sized file, but it does not survive the minification process.  So now it’s time to check each directive, and each template html file to see where we’ve gone astray.  Not looking forward to that.

Speaking of things I’m not looking forward to: we’re trying to push the latest version of the Angular-Django app from our local machine (running the default Django dev server- where it runs perfectly) to the remove dev testing server (where it doesn’t run at all).  This also looks to be an issue with Angular- the templateUrl isn’t getting the right path, which is throwing a very unhelpful error in the console and blocking almost everything from loading.  I know hunting bugs is a major part of the job, but it might be my least favorite.

It has, however, convinced me of the need for a style guide.  It’s not really up to me, but it will be suggested at our next meeting.  There are plenty of good ones out there to emulate (copy).

Zeroed In… or out

New project: bringing our photo albums feature into the 21st century!  I know, it’s been around for a while now.  The current setup grabs the album info (title, description) from the database and uses php to generate simple text links to each album.  A user sees very small images and can click each one to view a larger image.  That larger image has links to view previous or next, but all links make a full round trip to the server for the next image.  They also don’t resize the image to the screen, so we’ve got a good deal of work to do.

We started with the basics – Instead of simple text links for each album, we’ve switched to a nice large div with the album title and main description (might add the first image of the album as background later as well).  A user clicks on the album ‘cover’, and is taken to a grid view of all pics in that album.  Click on any image and (eventually to be added) a nice modal pops up with that picture (and you can scroll through at that point).

We kept running into a problem with the grid.  We wanted 5 pics across in each, but not to use a table (so we don’t get made fun of by the internet).  Using percentages on inline-block elements seemed like the best way to go, but the last div kept ‘falling’ down to the next line.

Some googling (and help from the awesome css-tricks.com site) led us to the answer- it’s just how inline-block works.  There is a space after each div that “can’t” be removed- though, of course, inventive developers have found about 7 ways to do it at this point.  The most straightforward seemed to be setting font-size: 0 on the grid element.  The default spacing is so that you have separation between words in your individual divs.  What could be the harm?  There’s no text in these elements- they’re just pictures.

And it did fix the alignment issue but, as often happens, another popped right up.  Each image also serves as a link to open the slideshow modal.  When we clicked on that link, the picture appeared properly, but no text (each picture can have a title and caption, and needs ‘left’ and ‘right’ buttons).

Turns out, the content within the modal is a ‘child’ of the div that opens it- so we were getting tripped up by the ‘C’ in ‘CSS’.  Font-size: 0 was cascading down to the modal and eliminating the text.  Of course, it took about 45 minutes for us to remember what we’d done, so in the meantime, many fingers were pointed at the code (everything from font color of the modal wrapper, to the php generated text that serves as the caption within a modal).

The moral: CSS stands for Cascading Style Sheet.  Try not to forget it!  Tricks to fix the little quirks are great, just know that they can have unintended consequences.

Check that box

The checkbox field type on our custom request forms feature is acting up.  And by ‘acting up’ I mean ‘a major part of the advertised functionality doesn’t work at all’.  Acting up sounds better.

When an admin is setting up their form, they can choose the field type, add a label, and choose if it should be a required field to submit the form.  The checkbox type wasn’t recognizing the required tag- end users could just submit the form without choosing a checkbox.

Easy fix, right- just check for input[type=checkbox]:checked.length (I know that doesn’t work as typed, don’t worry- just shorthand).  If it === 0, return false.  But there were a couple complications.  Besides my own incompetence, for once.

The feature was coded back in 2003 and is a mixup of php and js- with the js validation checks being generated by (and depending on variables pulled from a database by), quite a bit of php code.  The other main issue is that there’s a different checkbox-driven field type admins can add- a ‘copy self on form’ option.  We didn’t want to include that with the validation on a required checkbox field, as it’s technically a different type.

As usual, I’m sure my answer wasn’t the best.  Or the prettiest.  But it seems to work (and I’ll try to pretty it up a bit before release).  We use the php variable (pulled from the db) to set the ‘required’ property on the field (php print the result of a conditional on the variable- if required, $required = ‘required’, else, $required = ”).  Then, we use the same php variable to add a class to the element’s label.  That way, I can use js to check if the element has the ‘required’ class.  If so, we do the :checked.length check.  That way, we’re only checking the correct set of checkboxes.

A roundabout way to do a simple task, but when you don’t know the fields that the form will include, it becomes a bit more complex.  Now let’s make it pretty…

Mobile madness

Finished and released latest system enhancements at work.  The idea is to make our cms-built sites mobile friendly, and overall, it was a success.  But there’s a lot more work to do.

I’m still pretty new to the webdev world, and was in the ‘if tables work, why not just use them for layout’ camp.  Out system, originally coded in 2003, depends heavily on tables for layout.  The limitations of tables as layout, however, becomes very clear when trying to retrofit for mobile devices.  Tables do not seem to play well on phones at all.

I briefly tried floating divs, but it just wasn’t working quite right.  Using display: inline-block; in addition to setting percentage widths for each column seems to work quite nicely.  I still find that I’m leaving a gap of 2-3% to account for margins, but it looks pretty ok (not willing to go any higher with the praise than that…).  A simple media query at phone width to switch the width percentage for each to 100 ensures a nice flow on both full size and phones.

Of course, there’s still a lot of work to do removing tables from the basic structure of the cms system.  And many clients have gone off and used tables on their own sites for layout, so we will have to work with them to best get the look they want but also allow for mobile responsiveness.  Oh yeah, and we abused the !important declaration way too much.  It’s some ugly code, but was necessary to override the inline code inserted by the cms system.

It’s not pretty code, but it’s a pretty ok start.

Google on the go

As I’m sure everyone knows, google recently changed it’s search ranking algorithm to take ‘mobile-friendliness’ into account.  Sites that pass their test will be bumped up (or, at least, not penalized).  It seems like a good idea- and gave us the push we needed to finally start upgrading our system to play nice with today’s mobile devices.

Our system was originally created in 2002-2003, and it really is quite good.  But back then, people just didn’t (very often) view websites on their phones.  You simply didn’t (really) have to account for screen width, horizontal scrolling, etc.  It would be nice to take this opportunity to completely rewrite the layout of the system, switching to floats and divs and all that nice stuff, instead of using tables for layout (I know, we suck).  But there just isn’t time for that right now, so the order of the day shall be shoehorning media queries into the existing structure.

And it’s going ok so far.  Got the width and font size changes down, reduced image size to 100% max, and even found an easy way to reduce the size of a Google Map (many are embedded in our system’s sites) down to the correct width (just grab the css tag for iframe and make it 100% max).  We’re finishing up with a nice mobile menu that folds down/up and will integrate with the existing menu items already created (though it only works for the vertical menu option for now).

The main issue is due to the fact that we’re just too lazy to rewrite the structure to remove tables right now.  Depending on how a client has set up their site, we used php variables to determine the colspan of different table columns.  For example, if they have a logo (upper left of screen) and header (top middle/right), but are using the horizontal menu layout (which spans the full screen width), the main body text and footer both have a colspan of 2.  But switching to mobile rearranges it so everything is one column- the logo is hidden to save space and the image is moved into the header area.  Mostly works, but still leaves an odd ‘cut off’ section because the table still expects colspan=2 at that point.

Haven’t quite figured out that one yet, but once we do, we’re about home free (with stage 1, anyway).