https://blog.bradleygore.com/Ghost 0.11Sat, 14 Sep 2019 06:09:17 GMT60https://blog.bradleygore.com/2018/04/10/causing-gridlock-a-css-tale/ecdcdacd-13ac-4428-8606-b652e1a7fb94Tue, 10 Apr 2018 15:02:23 GMTNow that CSS Grid has excellent browser support, and the projects I'm working on are targeting newer browsers, I've been using it more and more for doing layouts. Along the way, I've noticed a couple interesting things about it and thought I'd share :)

Single Grid - Simple Layout

One of the first things I needed was a very simple (with CSS Grid anyways) "fixed" header/footer with content taking up the remaining available space and scrolling vertically if needed. Super simple, we just have to set up 3 rows and have the first and third rows auto and the second row 1fr (available space after first and third rows get whatever space they need) and overflow-y: auto. Here's a quick example:

Notice here that it is the <main> element that is told to take up 1fr and also has to have the overflow-y: auto. If we take the overflow style off that element and try to apply it to the inner <div class="bigly"> instead, nothing scrolls except for the entire body... Even though the <main> element is only supposed to be 1fr. Not really a big deal, just threw me a bit off at first, but it gets even more interesting if we add in another grid:

Grid-in-Grid - Slightly Less Simple Layout

The next thing we want to do is achieve the same as above, with one minor addition. Instead of the full inner content scrolling vertically between the nav and the footer, we want to have a left sidebar that scrolls vertically if needed and remainder of the inner area containing the actual content and being able to scroll between the nav and footer.

All we have to do is add in a nested grid, right? Well, it's at this point that it kind of magnifies the nuance shown above. Here's another example:

Notice here that in order to keep <main> from scrolling, and to keep its content from outgrowing the grid (i.e. locking it to our grid definitions), the overflow rules seem a bit non-intuitive:

<main>

height is already supposed to be 1fr due to grid row definition on the parent element

overflow is set to auto - even though we don't actually want this element to scroll!

.ads, .content

overflow is set to auto because we do want these elements to scroll vertically - we just don't want the elements to grow beyond the 1fr.

If we remove the overflow from the .ads and .content elements, the <main> element will just scroll - but it will scroll the sidebar and content area together vs allowing them to scroll independently :(

If we remove the overflow from the <main> element, then it allows its content to grow beyond the 1fr vertical size it is supposed to be!

I've gone through several tutorials on using CSS Grid and haven't seen anything explaining why this is - so, I'm certainly open to me doing something wrong or just missing something =)

Any feedback or tips on the approaches shown in the examples - feel free to drop a comment below or reach out on twitter!

]]>https://blog.bradleygore.com/2018/01/14/easy-image-upload-previews/6ff8796a-1119-4cef-9f32-06c8d55fc346Sun, 14 Jan 2018 22:30:53 GMTIf your app has an image upload mechanism, one way to add some polish is to show a preview of the uploaded image. Fortunately, with FileReader this is super easy. Let's take a look!

Technologies Used

I've been using React and MobX a lot lately, and have really come to enjoy both (especially together). This demo will utilize those for keeping the view in sync with the state of a model, however any other ui framework could be used here. The key components we'll cover in this blog post are:

The Input Element

The first thing we'll need to do is set up our input element to be of type file, and to tell it what types of files we accept. Also, we need to add our event handler for when changes occur to that input.

The event handler for the file's change event is pretty straight-forward. We need to check if there is a file (only allowing single upload in this scenario, but could easily modify for multiple), and then create a new FormData to house the data. If you're allowing file uploads, the way to send those to some backend is via FormData, so we'll use that here also. The actual image preview mechanism itself doesn't care about FormData, it just needs the file that was uploaded.

//event handler inside the component
onImgFileChange = evt => {
const { files } = evt.target,
hasFile = files && files.length > 0;
if (hasFile) {
//create a FormData to put the file and its name into
//also, if we were to persist to some backend, FormData is what we'd send
let fd = new FormData();
fd.append('file', files[0]);
fd.append('name', files[0].name);
//here, do something with that form data
//such as update the model with it, etc..
this.uploadedImgFormData = fd;
} else {
//there was no file, so user must've cleared it
//then we need to make sure our reference to
//any prior FormData is cleared
this.uploadedImgFormData = null;
}
}

Get The Preview URL

Once we have a FormData with a file in it, we can use the FileReader to convert that to a data uri to use as an image's src. Here's what that looks like:

//assuming we have access to the FormData via same component
//however, the demo uses a model to manage that state
let {uploadImgFormData: fd} = this;
//check if browser support FileReader
if (window.FileReader && fd && fd.get('file')) {
try {
//See https://developer.mozilla.org/en-US/docs/Web/API/FileReader
let fr = new FileReader();
//here's where the magic happens - the FileReader can read a file input as a DataURL,
//which can then be used as an image's src
fr.onload = action(() => this.imgPreviewUrl = fr.result);
fr.readAsDataURL(fd.get('file'));
} catch (e) { }
}

Displaying The Preview

Once we have the preview url, we should display that as a preview. However, if there is no file uploaded, we should gracefully display some fallback. Let's use some simple getters to retrieve the preview url and file name, and feed those to an img element:

Demo

Given that there's a demo, I just covered the most important parts here. To see the MobX stuff in action, check out the demo and the files in the sandbox. If you've not used MobX before, I highly recommend it as it really simplifies state management in React (and other) apps!

-Bradley

]]>https://blog.bradleygore.com/2017/08/23/what-is-vacation/19cf92af-cad0-43c8-9c3c-975d0f9012deWed, 23 Aug 2017 06:22:29 GMTUnfortunately, I've been a bit absent from the blogging, open-source world, and twitter this year (2017), and even in the latter months of 2016. While it seems people have continued to visit my blog (thanks, and I hope you found something helpful!), I think I've dropped the ball here by not giving an explanation...

I have had the opportunity to pick up some solid work as a consultant on my own. After many months of doing that along-side my full-time job, I decided to go full time with that! (here's my new company's site if interested)

As I write this, that statement seems so simple - as though I just woke up one morning and started a company and the entire world noticed and made way... However, I can assure you that it has been anything but. I hope to put down some clear thoughts and start blogging a bit about that in the near future, but here are some quick and unrefined ones on a few things I've learned thus far:

Juggling multiple contracts is incredibly challenging!

I have 3 current contracts - 1 "primary" and two that are smaller/secondary. However, the primary one has me working with like 5 different technologies, and one of the secondary ones is on a completely different tech stack than any others... Context switching will kill you - you have been warned!

Never, ever, be afraid to talk openly to your current employer!

PSA: If you are afraid to talk openly about goals/dreams to your current employer, maybe that's a clue that something needs to change?

Not meaning to brag here, but I've been recognized as a "real asset" by every company I've worked for (at least, as far as doing software work... I sucked at sales :). So, when I told my employer that I was resigning in order to start my own company, they really wow'd me by letting me know that they would be willing to work with me as a direct consultant (i.e. business-to-business arrangement between my company and them). They indeed became one of my clients, giving me one of my secondary contracts! I had already signed the primary contract, which is why they became a secondary vs my primary. A good company will work to retain a good asset, even going so far as to help them realize an entrepreneurial dream to do so!

FYI: The company referenced above is Unicon. They are based out of Gilbert, AZ and hire both on-site and remote software engineers. I honestly cannot recommend them enough! The truth is that if trying my hand at starting/running a business wasn't on my bucket list, I'd likely have never resigned as an employee. I don't get anything for mentioning/recommending them, etc... they've just been that awesome to work with :)

No lack of motivation here!

I sometimes see posts/tweets/etc... where people talk about having trouble staying motivated, or can't get motivated in the first place. Folks, start a business! I invoice monthly, so when a new month starts I see a big fat zero ($0) sitting there in front of me. I can't feed my family on zero, so at the start of every single month I'm motivated to get to work and bring that number up!

Wait - wasn't this post supposed to be about vacation as a business owner??

So, now that we've covered the fact that I've started a business and transitioned to working full-time on that business we may talk about being on vacation as a business owner.

This week (Aug 22-30) my family is staying on the beach in Amelia Island, FL. My 3 year old son has never seen the beach and ocean in person, and we're all super excited to be part of this grand first in his life :)

However, for better or worse, I can't put down business-related stuff for an entire week. Hell, I drove about 11 hours down here today and am up writing this while everyone else is asleep... It's that "no lack of motivation" thing I mentioned above.

What's on my mind?

While I'm doing next to zero contract-related work this week, I see many other things I can do to help my business:

Write a new blog post - at least to let folks know I'm not dead :p

Look up local businesses in the industry that strike me as interesting, and try to connect!

While I'm not currently looking to gain any new clients (see the statement on context-switching above!), I'm always interested in building new relationships!

The [sad] truth is that I've already gotten a short list of 10 such companies together - will be calling them during the week :)

Maybe spend a bit on one of my NativeScript projects...

Watch educational/motivational business/financial/etc... material (I know many people prefer books for those things, but I just can't stay into them in book format...)

So, is it REALLY a vacation?

I don't know... I guess it's a vacation from the constant urge to crank out billable hours (which is comparable to the unending urge zombies have to eat brainz IMHO). Maybe there is no vacation from a business - and I don't mean that negatively, I absolutely love what I'm doing and am looking forward to seeing where this goes! - especially one that's still young?

Don't get me wrong - I will be focusing heavily on my family this week. I can't wait to see my son's reaction to the beach and the ocean tomorrow morning! However, there will be work done to help further the business and/or my community involvement - even if it means I sleep a few hours less than everyone else while we're here (which, is pretty normal wherever we are :p)!

Anyone have any other thoughts, or maybe advice from experience? Should I force myself to turn it completely off, or is this just part of it? I'd love some feedback, and honestly I've been so absent from blogging, twitter, etc... that I'd welcome any community interactions at the moment :-)

]]>https://blog.bradleygore.com/2017/01/02/dynamic-custom-svg-cursors/a3cd547b-c9c9-4d13-bb7a-90d214f2638eMon, 02 Jan 2017 23:26:24 GMTUsing custom cursors in browsers isn't new or complicated. There are already extremely well-written articles on how to do this with static PNGs, for instance this one from David Walsh Blog. However, I recently ran into a situation that added a bit of a different twist to the notion of custom cursors and thought I'd share one solution I implemented.

The Scenario

I'm building a ui-widget for an application that is a web-based epub reader. This widget allows users to draw on a canvas overlaying the epub pages, but the colors are configurable so each epub could specify different colors rather than using the defaults. Nothing too complicated yet, but the twist comes in when the requirements state that we'll need to provide a custom cursor matching the selected color!

The Solution

We really don't want to have to create a billion png files for all the possible colors and have the at the ready, nor do we want to force consumers of the app to provide them either. So, enter SVG template turned into a data-uri, and using JS to dynamically insert style rules as needed!

CSSStyleSheet

The first thing we need to do is to create a new style element to gain access to its CSSStyleSheet. Then we can manipulate its CSSRule entries. We could just grab an existing style element from the page, but I prefer creating a separate one so we don't accidentally modify/remove rules from another StyleSheet. Also, in some browsers, you will run into issues trying to access rules from a sheet from another domain than the page.

Manipulating Rules

The parts of the CSSStyleSheet API that we'll be using are really simple. We'll work with the insertRule and deleteRule methods.

To insert a rule, we need two things:

CSSText - this is a string of the rule we want to insert. This contains the entire rule - selector and properties. i.e. 'h1 { font-weight: 800; }'

index - this is the number defining where in the list of rules this new one should go. It is mandatory; there will be an error if it is not provided.

To delete a rule, we only need the index of the rule we want to delete.

To examine existing rules, we can simply access the CSSStyleSheet's cssRules property. They are a collection, even if only one rule is defined, and each CSSRule exposes a pretty simple api - but for this post we're just going to use the CSSText property. Here are some examples:

The SVG Template

Now that we know how to work with CSS Styles in our javascript, we need a template to modify as needed and then create a data-uri from. We'll use SVG for this, as it easily allows us to add interpolation points into the template (i.e. instead of specifying a specific fill, we could do fill="{{fillColor}}" in the SVG. Let's take a simple SVG of a bullseye where we want the inner circle to be colored based on user input.

Putting It Together

Now we simply have to populate the SVG template's interpolation point fill="{{bullseyeFillColor}}" with an actual color, and then we can convert the SVG template to a data-uri and add the appropriate css rule!

Quick Demo

Let's take our bullseye svg and the HTML5 color picker <input type="color"> and see how this works. Select the color you want, then hover over the silver box below!

NOTE HTML5 Color Input doesn't work in IE, but neither do custom cursors without using .cur files so I'm not concerned with that for this pot :p Safari also doesn't support it. In these cases, just type in a valid hex or named-color (i.e. red, black, blue) value as I'm not checking if the data is a valid color in the demo.

Bullseye Color

The Catch(es)

So, as with everything in browser land, there are some catches to this.

First off, as mentioned earlier, this won't work in IE or Edge. Neither support data-uri for cursors, and both require the use of .cur files to do custom cursors. Needing super dynamic cursors in those browsers? May not be possible :(

Secondly, SVG cursors show up kind of blurry on high-res devices! There are already open bugs about this, such as this one, so it's a known issue. But, it's best to know these things before putting the time into implementing them!!

Have a better solution, or an improvement to this one? I'd love to hear about it! Leave a comment below or hit me up on twitter!

-Bradley

]]>https://blog.bradleygore.com/2016/05/23/nativescript-repeater-swipe-to-edit-delete/9237f01d-6edb-48da-b5f6-c9305906ff68Mon, 23 May 2016 13:29:53 GMTIn a previous post I went over how to add some simple animations to the NativeScript Repeater. In this post, I'd like to take a look at how we can add some nice swipe-based functionality to items in the Repeater. Specifically, we'll be creating a Repeater whose items have two layers: a background layer containing edit and delete buttons, and a foreground layer that will contain the data-item info to display.

If you're not familiar with the Repeater, I encourage you to check out the post mentioned above before continuing as it contains some basic info we'll be building on.

Video Tutorial:

The ItemTemplate

Believe it or not, the most tricky part about this is going to be the template. In order to pull this off, we'll need to employ NativeScript's AbsoluteLayout. This layout is entirely different from the StackLayout in that it stacks its children via the Z axis instead of either X or Y. If you want an item moved along the X axis (left/right), or along the Y axis (up/down), you have to specify this explicitly. Our usage won't need to worry about X or Y at first, just need to get our elements stacking atop one another. Here is a breakdown of the components:

Background View
GridLayout with 3 columns, the one in the middle taking up as much space as possible. The ones on left and right will act as our Edit and Delete action items. This grid will have two rows - the second of which will span across all columns and act as a list item divider.

Foreground View
StackLayout housing some info we want users to see about each item in the list. We'll use a simple set of data that is a list of People, each having a name and a position.

There are a couple very important things going on here with regards to sizing. Take a look at the XML tag where I've declared the GridLayout: <GridLayout ... rows="60, auto" columns="80, *, 80">. This means that my first row will be 60 units tall (it will contain the 3 columns: Edit Button, Spacer, Delete Button) while my second row (which is the item divider) will be whatever height it needs (i.e. I could set its height to 2 or to 10 and it would take up whatever specified). The next important thing to note is the columns: Column 1 takes up 80 units wide, Column 3 takes up 80 units wide, and Column 2 takes up the full remaining width. Here in a minute we'll need to think about the bounds when panning the foreground view, so these values here give us exactly what we'll need.

Also notice that we've declared some event handlers for the tap events of our Edit/Delete Labels, as well as the pan event of the foreground view.

Finally - we'll use CSS to style the background colors of the button-cells in the first row, style the divider, and set the height of our foreground view to match the height of the background view's first row (remember, that's 60 units in height). That is an important aspect to this approach - you have to set explicit heights so that you don't get funky overlap where a foreground row takes up more or less than a single background view's height and result in all teh sadz.

Wiring Up Events

Our code file for this page will need to implement all the functions declared in the view. Here's a breakdown of what these are, and their purposes:

navigatingTo: This event is fired when our page is being navigated to. It's where we can wire up the data source (aka bindingContext) for our page.

editPerson: The background view exposes a UI element that should initiate some edit functionality when tapped. For this demo, we'll just console log the info of the Person being edited as our primary focus is on the panning of the foreground ;-)

deletePerson: The background view also exposes a UI element that should delete a Person from the list when tapped. Here again, we'll just console log the info of the Person.

onForegroundPan: This function is called while the foreground view is being "panned" (i.e. tap and drag). It's the focus of this post - just took us a minute to get there ;)

Knowing that this is the API of our Page's code file, let's go ahead and scaffold that out:

Okay, now we're cookin'! We just need to handle the pan event. This is actually super easy, but there's some setup we need to do first.

Remember how I pointed out the widths of the UI elements for editing/deleting a Person? If not, it's 80 units - and one is on the left of the screen, the other on the right, and in the middle is an empty spacer that just takes as much room as is available between them. If you recall, we also have to explicitly set the X and Y coordinate for our absolutely-positioned items if we want them to move from 0,0. These pieces of info give is the minimum X that the foreground should ever be allowed to move to, -80, and the maximum X that it should ever be allowed to move to, +80.

Notice here that the AbsoluteLayout, actually any View object, has a translateX property - this is how we can set the X coordinate of our absolutely-positioned view! Also notice that the PanGestureEventData interface has this deltaX property. This tells you the actual amount the user has moved the item regardless of where they started panning. When the pan starts, it starts at 0 and goes up or down from there depending on if the user pans left or right.

And it's that simple! But, have you seen the big flaw that we're left with? What happens if a user only pans part of the way? Wouldn't it be nice if we could anticipate which direction they were heading, and finish the transition for them or reset it back to 0? Fortunately, this is also super easy.

Let's create another const called THRESHOLD - this is going to be the percentage of the way the user needs to swipe the element in order for our code to complete the swipe instead of resetting to 0. Let's go ahead and set it to 0.5 - meaning the user has to swipe >= 1/2 of the way in either direction before letting go for us to take it the rest of the way, otherwise we'll push it back the opposite way until it hits the min, max, or zero.

Now that we have our threshold, we need to be able to tell when the user is done with their swiping, and we can take it from there. Fortunately, the PanGestureEventData interface has a state property that tells us exactly that! Let's update our onForegroundPan function to make sure we don't leave the user stuck between actions!

]]>https://blog.bradleygore.com/2016/05/06/nativescript-repeater-animated-add-remove/d149acc7-4ed7-4c57-bbc8-375358b57079Fri, 06 May 2016 06:41:32 GMTNativeScript has a couple different components for working with lists of items: the ListView and the Repeater. ListView is the beast of the two, handling scrolling, infinite item loading as you scroll, etc... in addition to repeating a set of items over a view template. The Repeater is less feature-packed, but is a solid choice if all you need is to repeat a view template for some items and the list won't be(come) large enough to have to scroll.

Video Tutorial

I've done many tutorials on my blog, but this is the first video tutorial I've done and I'm super pleased to have finally done this. I'm new to editing so it's not perfect, but good enough for attempt number one. Enjoy!

Wiring Up The Repeater

We're going to get started by creating a project based on a template by running these commands:

tns create repeaterDemo --template tns-template-hello-world-tscd repeaterDemotns platform add androidyou can also add ios platform the same way as android above

This will scaffold out a starter "hello world" project that uses TypeScript. We're going to modify the app/main_page.ts and app/main_page.xml files.

Let's add a repeater to a page and wire it up to a simple view model. We'll have a button on the page that adds a new item to the list on tap, and each list item will have a delete button on the right side for deleting them. The Repeater has an items property that tells what its data source is, and it can also accept a child Repeater.itemTemplate element that defines what each item's view should look like.

Okay, this is pretty straight-forward. We're binding our repeater's items to an "items" property that will be on our view model, we have an item template for each item to inflate, and we have some buttons - 1 for adding a new item, and 1 per item for deleting the item. Now we just need to wire up the functions and view model!

Tap Events in Repeater

We have an empty removeItem function, so we just need to fill it in. When a tap event happens, there's an argument that is passed into the handler that contains an object property. This is the View for the item (or a child view, as is our button) and it will have a binding context, which will be the single item bound to that specific repeater item. So, in order to know which item we need to remove, we can just retrieve it by using indexOf on the bindingContext.items of the page:

//add a new import
import {View} from 'ui/core/view';
export function removeItem(arg: EventData) {
//arg.object.bindingContext will be the individual item it is bound to
let index = thisPage.bindingContext.items.indexOf((<View>arg.object).bindingContext);
thisPage.bindingContext.items.splice(index, 1);
}

Animating Item Add/Remove

So, now that we're adding/removing items it would be great to add some animations to our items. Fortunately for us, NativeScript views have sweet animation capabilities baked right in. Let's start with animating the item being deleted first, as it will actually be a bit simpler:

Remember that object property on the arg parameter? This is the reference to the button that was clicked. So, we can grab its parent (which, in this case, is the top-most element for the item) and animate it out of the repeated list. Once the animation is done we can remove the corresponding item from our repeater's data source. Implementing this is actually as simple as it sounds - we'll translate the X coordinate by -500 to animate it sliding left off screen:

The animations functionality in NativeScript is slick. It's easy to reason about, and uses promises - so if you want to do some action as soon as an animation is finished, it is just as easy as a .then(someFunctionToRun)!

Okay, now we want to animate the new items being added. Let's do a zoom-in effect here instead of a slide. The only slightly involved part here is that we need to animate the last item in the repeater, but it's not as convenient as when we remove items - as we aren't in a function that is conveniently given access to the view in question. So, before we can do that, we need to do some learnin' and see just how this Repeater thing works.

Looking at the source code, we can see that the Repeater actually only has one direct child element: itemsLayout and it defaults to a StackLayout. This makes sense, as each item's view will just be stacked atop another. While you can customize this, we're sticking with the default in this scenario. Seeing that our individual items aren't added directly to the Repeater, but rather to a StackLayout, it gives us what we need in order to get the last (newest) item in the list and animate it in:

And that's it - we now have a list of items that animate when adding and removing them. With NativeScript, building rich animations into your views just couldn't be simpler and those native transitions just couldn't be smoother :)

-Bradley

]]>https://blog.bradleygore.com/2016/04/18/my-first-nativescript-plugin/f4a3c62a-803a-4633-8a20-cd91760c5aeaMon, 18 Apr 2016 15:11:44 GMTAbout a couple months back, I started taking a look at NativeScript as a potential framework for my next mobile app. I'm the type of person that tends to get excited and just dive in and starts building what I want to be building vs building the hello world starter apps, so I started working on an input form that this app will need. Right away I realized I would want to use a native Android TextInputLayout widget - essentially a text field with a placeholder that "floats" up to become the label, and supports an error message. This isn't part of the core Android runtime (it's part of the design support library for material design) and isn't directly exposed via NativeScript. However, NativeScript's documentation boasts of the ease of accessing native runtimes, and rightfully so in my opinion, so I thought I'd put that to the test and make a plugin. Let's take a look at some of the hurdles I ended up facing and some of the resources that helped me build my first NativeScript plugin (actually, first NativeScript project altogether) - nativescript-textinputlayout.

Resources

I'll start with the resources that helped me through this as it's where I started when building the plugin. As with doing anything one has never done before, there is one tried-and-true method of pushing forward - finding where someone else did it (or similar) and building on top of that! These are the giant resources whose shoulders I built upon:

Specifically Nathanael Anderson - this guy is super knowledgeable and really helped me with differences between some of the core NativeScript Layout/View components.

NativeScript source - although, the source is large and considering I was building the plugin with next to no NativeScript experience it was a bit overwhelming at times :)

Hurdles

Picking a base class

If your plugin has any UI component at all, which mine did, the first thing you'll likely be doing is sub-classing one of the NativeScript components so that your component integrates with the runtime as automatically as possible. I looked at a few different plugins as well as the NativeScript source, and realized that there are actually a bunch of different components to pick from. Here's a list of the different components I tried with before finally getting it right, as well as some reasons they don't work:

EditableTextBase: The TextInputLayout is essentially a text field, right? So why not inherit from this and just have all the text input functionality already right there?

After further review into the android TextInputLayout spec, I realized it actually is just a wrapper for an android EditText component. In order to have continued on with this approach I would have had to create a NativeScript TextField under the hood anyways, and then I wasn't sure how I'd keep bindings in sync, etc... so this approach seemed out...

LayoutBase: Well, the Android TextInputLayout inherits from android.widget.LinearLayout, so I should probably use a Layout-ish component as my base class, right?

This approach actually worked - my component rendered just fine and my bindings worked. However, if you went away from the view to another, and then navigated back to the view using the navigation history (back button), then the bindings were broken and I couldn't figure out how to reconnect them. Nooo! After asking some folks on slack, LayoutBase should only be used if I'm actually "laying out", or positioning, child elements and setting their bounds, etc... Admittedly, I should've paid better attention to the source on this, but just didn't catch it until it was explained to me. (Thanks Nathanael!)

ContentView: My element isn't doing any layout stuff, so maybe it's just a View that gets one child (remember, it's a wrapper for a single text field). ContentView is allowed to have only one child element, so that works - right?

On the surface, it looks like this would work. However, if you look into the Android TextInputLayout documentation, you'll notice that it adds padding at the top for the label, and potentially adds padding to the bottom for an error and/or a counter, while the text field sits between all that. Examining the ContentView closely, we can see that it only takes the measurements of its one child into account when getting rendered (see the layoutViewgetter function), so this actually won't work either because our TextInputLayout takes up some space, as well as the text field that gets added as its child.

View: This is a base class for all kinds of different things in NativeScript, and appears to be the right choice for our component.

Now we have a base class that seems to fit our needs. We can add a child element and it can have its own measurements (border, padding, etc...) apart from its child's size. Now, how do we handle rendering it, or children (or in this case one child) getting added to it, lifecycle events, etc?

Rendering your component

So we're going to sub-class off of NativeScript's core View, but the first thing we need to do is render the component. It doesn't really matter what kind of sweet functionality we have in mind if the component doesn't get rendered to the screen. Fortunately for us, the Viewdefinition shows that there's a _createUI method. As it turns out, any time NativeScript wants to create the UI of a View, this is the method it calls. Go figure :p Also, if your component correlates to a native object, this is the time to instantiate it. The View definition shows a _nativeViewgetter, so be sure to implement that also - else your view won't render! Let's sub-class from View and populate that method:

Working with children

At this point, we have an implementation of a View and it knows how to create its UI, now we just need to be able to add a child element to it. Fortunately, NativeScript's View component has some pretty nice mechanisms baked in to make this fairly trivial - it just takes some digging in the source to start seeing how it all comes together :).

Firstly, we need to make our View capable of having children. In the source, we can find an interface named AddChildFromBuilder and it dictates that anything implementing it will need to have a _addChildFromBuilder method. So, when we are declaring our component, we need to implement that interface (if not using TypeScript, you simply just have to supply the function and don't worry about declaring interface implementations). NativeScript builds up the object tree for the view based on the XML using various builder thingies (yeah, that's the technical term :p), and we want the NativeScript runtime to know that our component can handle child XML elements. Here's how we do this:

Since the TextInputLayout is only compatible with text fields, one thing we need to do is do some checking on the child. So let's update the _addChildFromBuilder method to do this, and add some more imports to get the types of children we want to accept:

//new imports
import {TextView} from 'ui/text-view';
import {TextField} from 'ui/text-field';
//update _addChildFromBuilder to only accept those children
//notice I changed the second param from "any" type to either TextField or TextView
public _addChildFromBuilder(name: string, child: TextField | TextView): void {
if (!(child instanceof TextView || child instanceof TextField)) {
throw new Error('TextInputLayout may only have a <TextView> or <TextField> as a child');
}
//do something with the child here
}

Since the allowed child elements in this case are all sub-classed from View, we can even listen for certain events, such as 'loaded', to fire and then react accordingly:

When an element is loaded, its native counterpart (i.e. child.android or child.ios) will be populated also. If you're building a component that allows children to be added, you want to make sure that the child's native counterpart gets added to your component's native counterpart. This may look something like this:

//remember earlier, we set the _android property in the _createUI method
//now, we can use the android getter to get a handle to it and add the
//*native* correlation of a child to our *native* component!
child.on(View.loadedEvent, () => this.android.addView(child.android));

Now the NativeScript runtime knows that we can have child elements in our XML, it can add those child elements using the builder, and our native component can get that child's native correlation added super easily. Here's an example of how you'd use the TextInputLayout plugin (which is available on npm):

Lessons Learned

There are two things I'd probably do differently in hindsight.

Gain a clear understanding of some of the core NativeScript classes first. While I learned a lot manually trying multiple classes to base-class off of, it would've certainly been easier in building the plugin had I started there :p

Probably would've went ahead and built one or two of the small tutorial apps. As excited as I was to dive right in, there's a lot to NativeScript and learning a bit more up front about view lifecycles, etc... would've been helpful.

Once I better understood what to sub-class off of and how it worked, getting the plugin wrapped up was really easy. Hopefully this post can help someone else that may be hitting those same hurdles :)

-Bradley

]]>https://blog.bradleygore.com/2016/03/28/font-icons-in-nativescript/1d389ebe-a702-4434-a68a-acbae527625dMon, 28 Mar 2016 14:03:00 GMTGetting set up to use Icon Fonts in a NativeScript app is fairly straight-forward. NativeScript documentation covers it, and Nathanael Anderson has a tutorial covering things in more depth. However, there's one annoyance I have with using them in NativeScript and this post will cover that and one way to resolve it.

The Annoyance

Once you're set up to use icon fonts, you'll typically have a CSS rule defined to set the font-family when a certain class is used:

.fa {
font-family: FontAwesome;
}

But, as you can see in the above referenced getting started docs/tutorial, CSS is not what sets the content as it would be if we were using HTML and Icon Fonts. We have to find the unicode and set the text property of our element to use that:

<Label class="fa" text="\uf293" />

So you must either memorize the unicode for your font icons or be resigned to looking them up every time.

One solution

NativeScript has a feature baked into it called Converters - essentially functions you can pipe an input to and have it converted to a different output without changing the source (i.e. a property on a model). You can also have application-wide converters by adding them to your application's resources, which is what we'll be using to make it easier to use our icon fonts!.

Create our Converter Function

The first thing we'll want to do is to create the function that will be our converter. Let's create a new directory: app/utils/ and create a new TypeScript file within named fontIconConverter.ts. This converter is actually really simple - it just has a hash map of all the icons we want to use and their unicode value, then provides a function for converting strings, or parts of strings, to the appropriate unicode value. Notice below that we're also handling cases where an icon may be passed in within a string of text.

Make the converter accessible application-wide

Now that we've defined a converter function, we just need to add it to our application resources to make it available application-wide. Simply navigate to your app/app.ts file, and make the following additions:

Use the converter in your view

Is it still clunky/ugly? Yep. But, I find it easier to remember the actual names of the icons over their unicode values. So, in an app where a lot of different icons are being used, this may just be helpful. If you're only using one or two icons then maybe it wouldn't be worth it - you'd have to decide :)

Quick Caveat

Any time that you are using the binding syntax {{ ... }} your view must have a binding context or it won't interpolate. Even if all you're doing is taking a static string, such as is the case with the font icon converter, and running it through a converter. If needed, you can just set the binding context to an empty object and that works, but kinda feels hacky to me.

It's certainly not a perfect/elegant solution, but as far as I can find it's either typing in the unicode directly to the label or some converter like this when it comes to using font icons. If you know of a better approach, feel free to share in the comments!

These past couple weeks I've been digging into the NativeScript mobile framework, and am just super impressed by the flexibility baked into it. That flexibility makes it crazy simple for you to create custom, and potentially reusable, UI components.

Getting Started

While this post won't go deep into getting started, we'll hit the high points. If you want a deeper walkthrough, NativeScript has an excellent Getting Started tutorial.

Install NativeScriptnpm install -g nativescript

Navigate to a directorycd some/path/to/projects/folder/
* Don't create the child directory (i.e. myAwesomeApp/) yet - NativeScript will do this when it scaffolds our project

Initialize a NativeScript project
In version 1.6 the CLI was updated so that you can initialize projects based off of templates. For this post, we'll use tns-template-hello-world-ts. This is a simple 'hello world' type app that uses TypeScript. *I found that it was easier to read through the NativeScript source code once I started using TypeScripttns create demoApp --template tns-template-hello-world-ts

Navigate to demoApp directorycd demoApp

Add Platformtns platform add android
You can also add iOS if you want, but for this post we'll just deal with Android.

Creating the component

Creating a basic custom component is simple, so we'll start there and then add some stuff to it as we go. If you look in your current directory, you'll see an app/ directory. We want to add our application's code, including our custom component, in there. So let's add these directories and files:

We're essentially after a label that gives the heading text on the left, and an image on the right. This post is about working with custom components, so I won't spend much time on the xml attributes, but here are some high points:

GridLayout lays things out in, well, a grid (surprise!). Cool aspect of this layout is that you can set sizes of your rows or columns (if you've ever worked with XAML, this will look kind of familiar). Since we have 1 row with 2 columns, we told it to auto-size the first row, set the first column to * and the second column to auto-size. This means the first column will take up all available space left after the second column gets just what it needs.

Attributes such as paddingTop, verticalAlignment, and marginLeft are style attributes. NativeScript also supports a subset of CSS that can be used to style your elements - I'm just doing inline for the sake of this post.

Using the component

When you had NativeScript scaffold out the app, it generated the "main" view files for you. You should see the file app/main-page.xml - open it up, and let's pull in our custom component!

We do this by doing these 2 simple things:

Declaring the namespace that our component resides in by using the path that holds our custom component's files: xmlns:appHeader="widgets/app-header"

Using the component in the view by referencing the namespace and the filename: <appHeader:header />

NativeScript uses the value given after the namespace to know which file(s) to retrieve. If our file was named appHeader.xml instead, then we'd use it like this: <appHeader:appHeader />

Now, if we run the app (tns emulate android, optionally specify an image to use via --avd someImageYouHave) we should see that header component right at the top! But, that isn't much fun... so let's add some functionality to our component!

Enhancing the component

Having some sort of 'reusable' header that has hard-coded header text is pretty useless, and not exactly reusable. Let's update our component so that you can use a headerText attribute in the XML to pass in whatever you want the header to be! This will require us to have a 'code behind' for our UI element, so let's create this file: app/widgets/app-header/header.ts and populate it with an event our <GridLayout> can call once it's loaded:

import view = require("ui/core/view");
import label = require("ui/label");
//not exporting this, just creating the class so that TypeScript can understand
// that our custom component has a 'headingText' property
class HeadingView extends view.View {
headingText: string;
}
// this will get called when our <GridLayout> is loaded
export function onLoad(args: any) {
//args.object is a reference to the view, and every View instance has a "loaded" event
let thisView: HeadingView = <HeadingView>args.object;
//only change the label's text if we were given some custom headingText
if (thisView.headingText) {
let label = <label.Label>thisView.getViewById('lblHeadingText');
label.text = thisView.headingText;
}
}

Now, we just need to wire it up to call the onLoad event in the app/widgets/app-header/header.xml file. Simply add the loaded="onLoad" attribute:

<GridLayout loaded="onLoad">

* omitted all other existing attributes for brevity - do not delete anything from this file, only add the new attribute.

Finally, we simply need to pass a headingText value in our app/main-page.xml file:

<appHeader:header headingText="Main View" />

Now, run the livesync command tns livesync android --emulator --watch and see your custom header using the text you passed into it!

Going Further

This is certainly just the start of what kind of awesomez you can make with custom components! For instance, NativeScript provides Observables where you could have components that are data-bound instead of just passing in a static string. Hopefully this is enough to whet your appetite and get you started!

I've recently started working with a couple new tools: JSPM, and Angular Material. I won't go into much detail on using JSPM here, will save that for future posts, but I do mention it because it is what I'm using in order to use ES6 features. It uses a javascript compiler, such as Babel, and can take care of bundling your scripts, managing dependencies, etc... I happen to find it more to my liking that the current alternatives. In this post I will, however, focus on Angular Material, specifically the sidenav component.

Getting Started

The team building Angular Material made it very easy to get a sidenav up-and-running. A couple of very nice pieces of functionality is that you can specify when the sidenav is "locked" open - such as on screens larger than a certain number of pixels. The markup is very simple, having a primary directive and a few attributes to pass in:

md-sidenav - the primary directive. It has to be an element, not just an attribute.

md-is-locked-open (optional) - an expression for when the sidenav should remain locked open. You can reference the $mdMedia service in the expression if you want to use a specific breakpoint, etc...

md-component-id (optional) - a unique identifier for this instance of a sidenav so that you can use the $mdSidenav service to get a direct handle to it

Notice the expression in the md-is-locked-open attribute: $mdMedia('gt-sm') This is taking advantage of the built-in media query service and specify that the sidenav should remain locked open any time the screen is greater than the small breakpoint. It's pretty handy that they take care of injecting that service when parsing the expression so that you can use the md-sidenav outside of any controller instances, etc... However, if you wanted to do something more custom, you'd likely want to use an expression that is specific to a controller for that view.

Additionally, you can use specific CSS classes to provide depth for the sidenav: md-whiteframe-Xdp - You can use this format to provide various depths from 1 to 24 (i.e. md-whiteframe-3dp) via box-shadows.

A Handy Directive

When I was first playing around with the sidenav and saw how it automatically locks open when the expression provided evaluates to, and then hides when the expression provided evaluates to false, I realized that I hadn't actually planned for handling a hidden sidenav. I had a menu icon in the <header> element that would display only when the screen size was less than or equal to the small breakpoint, but I didn't have any controller created for that part of the view, and honestly didn't feel it was warranted. So, in order to make a linkage between the toggle button and the sidenav, I made a really simple directive to let an element act as a toggle for any sidenav specified.

The API for the directive is just one simple attribute:

side-nav-toggle - the component ID of the sidenav you want the element to act as a toggle for.

One convenience of the $mdSidenav service is that it ignores calls to close or toggle the sidenav instance when it is locked open, so you don't have to worry about checking that yourself in the toggle directive. Of course, you can if you want to by using the isLockedOpen method.

So far, I'm pretty impressed by how well thought through things seem to be in Angular Material. I'm currently digging into various aspects of their theming functionality and hope to continue to learn and write more about Angular Material in the coming couple of months! I also plan to write a bit about JSPM as I get more knowledgeable with it - I'm finding it pretty well-documented and not really difficult to get started with it.

This talk was mind-bending - not just for me, but for other folks as well:

Before I get into the mind-bending stuff that he talked about, which the majority was over my head :p, I'd like to start out with how the talk started.

Kyle's first slide was mentioning a topic he is passionate about - #PrivilegeAwareness. The way he presented it, I feel, was non-confrontational and non-militant - just sharing something that was important to him, take it or leave it. Essentially, he just said it's important to recognize and be aware of the privileges we have had in life that have helped us get where we are.

This hit home with me. Even though I come from a family with a history of drugs, violence, domestic issues, etc... there are breaks that I've received that helped me to be different and to treat my family better. I doubt I'd be where I am without these breaks - although I'm highly self-motivated and driven, that wouldn't have done it alone. Recognizing the privileges you've had doesn't in any way mean that you've had it easy, which is a misconception I have had, it just means you acknowledge that you've had these breaks and are thus empowered to: a) Show empathy to others who may not have had those breaks and b) Be mindful to provide those breaks to others where you can.
These two items, to me, are intertwined - without empathy you will not be inclined to help give breaks to others, and if you don't try to give breaks to others then your empathy does no good.

Now, on to the technical part of the talk :) He started out talking about concurrency vs parallelism:

Concurrency: More than one higher level task happening at the same slice of time

Parallelism: More than one higher level task happening at exactly the same moment

He went into how coordination is the difficult part - running separate tasks on separate threads is easy, but running separate tasks that communicate with each other in separate threads is difficult. So, we've gone through an evolutionary period in javascript where we've tried to coordinate concurrency and even simulate parallelism (javascript is single-threaded, so no true parallelism in accordance with the definition given): callbacks, then promises, now generators, soon(ish) async await, and a little thing called Communicating Sequential Processes to help reason about it all! I won't even attempt to go deeper than that, as it's certainly over my head at the moment, but I highly recommend checking out the video that will be posted from the conference!

This was a solid talk that went over some solid techniques for both making your code debuggable, and doing the debugging. Most items are aimed at Node specifically, but some are applicable to client-side js also. Here are some high points:

Bryan is a local (to Nashville, TN) and an all-around awesome guy. I've been following him on twitter for a while now, and when seeing his tweets on functional programming and Erlang I'm generally thinking "Oh yeah, I need to look into that sometime". In this talk, he convinced me - I have to look into this Erlang and Elixir stuff! Here are some general points and some comparisons he made between NodeJS and Elixir that I find astounding:

With Node, it is a recommendation to not write any blocking code - after all, Node is single threaded with a single event loop.

Max went over how PhoenixJS can help make it easy to communicate back to an Elixir backend with WebSockets. He went through the obligatory WebSockets demo of making a chat application, and his talk was great. However, what I think folks will remember the most is that someone from the crowd sent a chat message that was an alert(...), and it totally popped up a browser alert b/c he wasn't sanitizing the messages! One of the most memorable events in any of the sessions! #amirite

This talk was interesting, and took a turn I didn't expect - static site generators. Robert started out by talking about how things have kind of made a circle:
The first static site generator was Dreamweaver
Then we hit the explosion of data-driven sites and generators lost a ton of popularity
Now, many are expecting generators to be the next big thing

Given the rich server-side rendering capability that React has, it seems to be a really good fit for ushering in a new era of static site generators! So, he has started a project on github called react-static and he gave a demo of it. Definitely worth checking out!

Michael gave some excellent observations during this talk, my favorite one being "The future is crafted by pain". We tend to focus our energies on solving our pain-points. He went on to describe one such pain point, one which I think all web dev folk can commiserate with: CSS

Pain points (main points from his talk and in bold, supporting scenarios my own as I can't remember his specific ones):

You have to hunt down styles that are affecting an element The more classes applied to the element, the merrier the hunting...

Recognizing state-specific styles isn't always intuitive - i.e. what does a class of danger actually mean for a given element? It could have different non-apparent meanings for different elements in different contexts, all on the same page...

Separation of component and CSS for reusability IS A LIE Agreed - aside from some utility-type classes, the bulk of the styles applied to a component are tied to that component, and that component alone.

So, he walked through what happens if you move the styles over into the javascript. Here are a few pros and cons he gave:

Pros

Component-specific styling is right with the component

Styles are testable - if the data's state dictates a certain style should be applied, you can render the component to a string and have your unit tests verify it is correct!

Minimal CSS files :)

Cons

Browser events are more difficult to style - i.e. :hover and :active

Media Queries are more difficult

But, for the cons, he gave a few libraries and tools that are in the works to help with these problems.

Aside from the technical content, Michael's presentation style is very enjoyable. He used some very clever images and has a great sense of humor - when the videos get posted, watch the one from this talk and you'll be glad you did :)

I want to start off by saying two things:
a) Seif is pronounced safe
b) Most of this talk was a bit out of my league. Douglas is a brilliant engineer, so I expected that :) Thus, I'll try to be light on opinions, and you can take my opinions lightly ;-)

The talk was very interesting, to say the least. We heard thoughts ranging from "everything is terrible" to "I haven't found anything better". In a nutshell, Douglas pointed out some of the harsh realities regarding security, or the lack thereof, with the interwebs as it stands today. He has a plan to change that. Let's hit some highlights:

First things first, the transition plan...
If we harken back to the days where there was going to be a switch from analog TV to digital, we can see some specific points that helped make this transition a success in America:

Broadcasters and Producers forced to purchase updated equipment, with no new revenue sources, to support broadcasting in HD and creating content for HD.

Consumers that needed it were provided boxes that would take the soon-to-be digital signal and make it still work on their current televisions.

The focus here was on making the transition as painless as possible for the consumers. This is reasonable given the pain-points being at the broadcaster and producer level is orders of magnitude fewer pain-points than if every consumer had a pain-point. We need to take the same approach when upgrading the web to be more secure.

Then he laid out his plan. I won't go over all the details, but the bottom line is that all URLs you visit would have your unique ID, based off of a private key, as part of the URL to any resource you may go to - i.e. banking, retail, medical, etc... Honestly, I was left a little fuzzy on whether you would have 1 private key per resource, or if you'd have 1 key alone that you allowed each provider to use in signing the public key you'd use for their site/app. But, here are the high points:

Use "helper apps" that the browser kicks off at appropriate times (I totally didn't even know this was a thing)

Convince 1 progressive browser to integrate

Make 1 secure site to require that browser

Risk mitigation will compel the other secure sites

Competitive pressure will move the other browser providers

World will follow for imroved security and faster app dev

We'll no longer have to rely on cert authorities, as is the case for SSL. This is good b/c they can't haz teh trusts.

Unique ID will be made with uber-encryption and hashing algorithms - ECC 521, AES 256, SHA 3-256 - so will be extremely secure and, given that private key will exist on the device, seems impossible to socially hack.

If your device dies or is lost/stolen and you haven't made a redundant copy of your private key(s), then you're SOL.

Folks that currently share a device (i.e. a shared cell phone) will need to stop doing that. Actually, they should probably stop doing that now if at all possible..

Minimal pain-points for consumers, relatively speaking

It will take some radical changes to upgrade the security of the web - so for him to have a plan and be willing to put it out there, I think it's pretty brave and respectable. There are also some points of concern, as you can see on twitter, the biggest one being anonymity. I definitely recommend watching the video when it's posted.

If I've said anything inaccurate about his talk, feel free to correct me - again, a lot of this was over my head :)

That's it - now on to some personal remarks about the entire weekend :)

Nodevember was absolutely a pleasure and privilige to attend. My brain is overloaded "and loving it", as Maxwell Smart would say. I got to meet some people that have influenced me from afar, and got to reconnect with others. Big shout out to some fellow Nashville folks, who you should totally follow on twitter if you aren't already, Jonathan Creamer, Jeremy McDuffie, and Elijah Manor - was great to catch up with you guys again!

Finally, my most sincere thanks to all of the organizers, volunteers, speakers, and sponsors. Thanks for giving of your time, your energy, your selves :)

Yehuda started off talking about how there is so much pessimism in the technical community. So many people complaining about the problems we face, rather than being positive about what has already been accomplished and what amazing things we have yet to do. This, to me, was the highlight of the talk.

He then went on to talk about how one such positive is frameworks and that they free up a developer, or team, to focus on the specifics of the specific problem domain(s) they are trying to solve. This part of the talk then went into more of a "pitch" on Ember, which I feel was a bit of a missed opportunity that could have been put towards some more 'keynote-ish' topics. However, I'll choose to focus on the positive and accept the Ember focus as being in the spirit of how frameworks in general are a positive thing :)

Firstly, I'd like to say that this was my first time hearing Rey speak and I found him to be both a bit of a class act and a class clown :) He's good humored, witty, and a naturally good presenter. Before I go over what I found interesting about his talk, I'd like to talk about an experience I had during the first several minutes of his talk.

As all presenters do, Rey had spoken directly into the mic to kick off his talk and make it clear to everyone he was starting. Everyone, or nearly everyone, understood and became quiet to let things proceed as they are supposed to - with 1 person talking and all other people listening... Except for this guy right behind me that decided he could "whisper" and continue the conversation he was having.

At first, I just ignored it and tried to listen to the presenter over the loud whispers in my left ear. After giving it a couple minutes, in the hopes he would stop talking, I turned around and asked him if it would be ok if I just listened to the presenter. I wasn't a jerk about it, but made it clear that he wasn't whispering as quietly as he obviously thought he was.

I only mention this situation for this one point: Please be respectful to the other 2 types of people in the room - which are 1) the person trying to speak on a topic and 2) the person(s) who are actually interested in hearing what the speaker is saying. Now, back to the points of the talk that I found meaningful :)

Rey took an interesting approach to his talk. He essentially went over the pain-points he's hit while learning NodeJS. What I found cool about this is that he's a seasoned developer who has established a solid reputation in the industry, but he had no problem openly admitting that this has been difficult for him and he nearly threw in the towel a couple of times.

I know that I've found learning new technologies/concepts difficult at times, and had assumed that the problem was me - maybe I'm not as good as all the other devs who seemed to easily grok the concept, or maybe I haven't put in enough time studying, etc... But, maybe this line of thinking is incorrect. Here's the advice that Rey gave based on his experiences with learning Node:

Find a mentor - just because you're already strong in one technology doesn't mean you get a free pass to just jump into a new technology at senior status.

Real-world examples are of utmost importance - many Node tutorials are building a real-time stock-ticker or chat application. What about tutorials showing session management, or building node services? While some do exist, they are harder to find.

Immediately start working with some abstractions like Express - while you may eventually need to know how to handle routing and parsing route params yourself, there's no need to be that close to the metal when first starting out.

Learn the debugging story immediately - he went quite a while before he found that you can use node-inspector to debug node apps. Being able to debug your application makes the building process much better - whether you're N00B or expert...

This talk was about the amazing things you can do with a little library called Redux. Tim's talk was pretty fast-moving (30 minute duration on all the talks), and he covered a ton of ground. Admittedly, much of it was over my head as I've not worked with flux (which redux is based on) and didn't know a lot of the terms he was mentioning. However, I can confidently say that looking into using more unidirectional data flows is something that is hot on my radar now :)

This talk was loaded with so much info - but presented in a way that was easy to follow and digest. I really love the approach Jeff took with presenting the pros and risks of microservices, as well as some strategy points for moving towards them. I appreciate an honest review that lists the hurdles you'll have to jump rather than ignoring them as if the architecture pattern is full of magical unicorns that simple solve all your problems :p Here are some high points:

Pros

Disperate hosts for programs and different languages/technologies for each service

Composability - think how you can pipe output from one thing to another in linux

Rapid change cycles - only the service(s) that relate to the problem area(s) need updated

Risks

Siloed knowledge - a service that's built in technology X will require someone knowledgeable in technology X, and since microservices are independent and can be written in entirely different stacks, this can become more pronounced than in monoliths

More difficult deployments and versioning (monolith first is good idea)

Difficult to know where boundaries are at first (i.e. what should be split into a separate service - again, monolith first may be the way to go)

I also learned that Redis is capable of far, far more than just a cache storage - it can handle message queues (think RabbitMQ, but "easier to set up" according to Jeff)

Mike gave a really solid talk about how we have the power right now to give as good an offline experience as we want to put the effort into providing. He talked about some of the (many) pitfalls you'll run into when working with HTML5 Application Cache and how to handle them. He also gave a great breakdown of the different sections of the Cache Manifest file. I have used app cache a bit, so I didn't learn any new concepts - but it was a fantastic refresher :)

This was a gem of a talk. Not so much due to the overall topic or presentation style, but one thing that Jacques said that struck me as quite special - I'll share it after these high points :p

Username and Password are cumbersome on mobile

Applications (whether it be banking sites or retail shop sites) implement policies that actually make it harder to set a secure password

Computational power has increased such that brute-forcing isn't hard or as lengthy a process at it was yesteryear

Wearables are the future and they are orders of magnitude harder to hack - can't exactly socially engineer them the same way you can to gain a network login, etc...

2-factor auth is the way to go - a phone # (each one being unique) that you can use to get a pin code to use to access a site - the code only being good for a set amount of time after it is issued

While all of this sounds spot on and 'easy enough' - I appreciate that he gave some real-world things you have to think about when implementing this, such as:

What if a person switches numbers or their phone is stolen?

If person A switches numbers and person B gets that number, how to keep person B from ever trying to access the site, getting a pin code sent to what once was person A's number and logging into person A's account?

Fallback - do not rely on this information of phone number and email address alone! Capture some other info that the customer can use to change the number on their acct, etc... but this should be more stringent than normal password recovery.

And here's the thing that he said that I thought was just great:

You ought to have a "can I do it while driving" policy when it comes to UX. If you can't do it while driving, then it is likely too complex/cumbersome. However, don't actually go try it while driving...

This talk was the one where I feel I learned the most today. I loved several of the talks today, as you can likely tell by this writing, but I think that what I learned in this talk will have some pretty significant impact on my workflow in very short order.

Firstly, I went into this talk thinking it would be about best practices around scaling an application; after all, the title starts out as "Scaling Best Practices"... But, I was pleasantly surprised at how it turned out! He actually talked about how you can scale the way you communicate the "best practices" for a project or team!

I'm big on communication - I try to study people and learn their communication styles, make sure I communicate effectively, and make sure my communication style is easily understood. I like the details - not just that something was done a certain way, but why that way versus another way - this is just how I'm wired and how I learn best. So, when he started talking about strengthening how you communicate the best practices to follow on a project - it really hit home with me. I've been the new guy on an established project before, and found out in code review that there was a "known" best practice for something like structure, method positioning, naming convention, etc.... that I wasn't following - except I wasn't following it b/c those "known" things were never made known to me...

The way to do this is to use a pluggable linter that allows you to define your own rules - and this linter is ESLint. ESLint essentially looks for patterns you provide it, and it runs functions on items matching that pattern - but gives you the nodes in the form of syntax trees. These trees are easily traversed, so you can look for things like if blocks that are nested and could be combined, such as this:

Oh, and dig this, you can then create unit tests that show passing and failing cases so it's crystal clear what the "best practice" in that situation is for the given project. It's just awesome, and it's highly likely to be the next thing I dig into during my off hours :p

Did you attend Nodevember and have any feedback on my observations? Feel free to comment or hit me up on twitter!

In a previous post I introduced Git Hooks and how to make them a seamless part of the frontend dev's workflow. I'd like to build on that and talk about how to make our git hooks smarter - by using the --porcelain flag.

General Workflow

If you recall from the "Git Hooks for the Front End Developer" post, we walked through using Git + NodeJS + Gulp to make our git hooks moar awesum. We're going to follow that same workflow here, so the majority of this post will be detailing how a gulp task (and helpers) may look:

Git Some Help with a "Git Helper" file

One thing to keep in mind when using gulp tasks for git hooks is that most gulp tasks are set up to examine the entire set of files. For instance, when you run a jshint or eslint task, you're typically looking at all of the *.js files in your application. This, however, may not be desirable in a git hook. What if only 3 JS files changed - should you still check the styling of all files? What if your codebase is huge - then won't that make the commit process obnoxious? Fear not, my friends, for this can be overcome - let's create a helper to solve this for us :)

Here's a bit of a project structure we'll work with for this post:
/js
/gulp-tasks
/gulp-utils

In the /gulp-utils directory, let's create a file named gitHelper.js. This file will utilize the Q and gulp-git libs to make it easy to interact with git from within our gulp tasks:

The purpose of this util is pretty simple. It exposes a list of all possible status codes (exports.STATUSES) and provides a then-able function for getting a list of modified file descriptors (exports.getModifiedFiles). To make things easy for consumers, the file descriptors look like this: {status: ' M ', path: 'js/app.js'}.

Notice that the only reason we are able to get the path and status for each modified file is because we are using git's --porcelain flag1.

Using the Git Helper

Next, let's build a gulp task that can use this helper to make our git hook smarter in that it only lints the modified JS files instead of all of them!

In the /gulp-tasks directory, create a file named pre-commit.js. The thought here being that our pre-commit hook script will kick this off as a child process by spawning gulp with "pre-commit" as the argument (if you're not following that, please read the introductory article):

Notice that we are utilizing the helper, and easily filtering out any file descriptors we do not want. We then take what's left, feed it to gulp.src and pipe through jshint just as we would if linting all of the application's JS files - but we are only linting the modified files here! This makes for a smart git hook that only assesses the files that actually need an updated assessment!

I've also updated the github repo demo project to use --porcelain and only run unit tests, lints, etc.. on only modified files!

-Bradley

Maybe you've also used the -s flag to see a shorter list like this, but --porcelain is preferred for getting easily parsed output for scripts - git status documentation. ↩

A while back, I wrote a post on Getting started with Cordova Sqlite. As I've been working on a hybrid mobile app (more about that coming very soon!), I've found that it is not exactly straightforward how to gracefully handle database migrations... and it took me a bit to get a decent plan in place.

This plan builds off of what we covered in the getting started tutorial mentioned above, so you may want to read through it first to have the context.

DB Versioning with PRAGMA

In sqlite, there are special commands you can execute to get or set some metadata about a database. Coming from MSSQL background, as far as databases go, I'd not heard of these PRAGMA commands, so I am happy to have essentially stumbled upon the documentation for them when looking for info on sqlite migration techniques. One piece of metadata in particular, user_version, is what we'll use for this.

As you may recall from the Getting Started tutorial, we have all of our db initialization in a seedDb function. But, what happens if we need to add/update columns, migrate data, etc... as time goes by and features are added? We could probably get by with parsing the table_info, another PRAGMA command, to perform logic such as if column 'x' exists, rename to column 'y', but that could get clunky and unmanageable very quickly. A better approach is to batch up your changes into what are called migrations - essentially self-contained chunks of changes that should only be ran one time, and for a very specific purpose. Let's create a variable to hold our migrations in the same file that houses our seedDb function:

//widgits.js
var migrations = [];

Notice that our migrations variable is an array - this is important. We need a way to track which migrations have already ran vs those that have not. A very clean way to do this is to use the array's indexes as our guideposts. This is where the user_version can help us - it defaults to 0, the first index in a javascript array, and can be updated to any integer we need (i.e. incremented by 1 as each migration completes). Let's kick off the migrations by checking what our user_version is, and then running the migration at that index, if there is one. This will go at the bottom of our seedDb function so that we can pass in the same transaction it is using - this way if any part of the script fails, there's a full transaction rollback.

//widgits.js seedDb()
function seedDb() {
//all data init stuff - i.e. object collections to use, etc...
widgetsDb.transaction(function(trans) {
//db init stuff - i.e. create tables if they don't exist, etc...
//finally, after all initial seeding of the db, start our migrations
trans.executeSql('PRAGMA user_version', function(t, res) {
var version = res.rows.item(0).user_version;
//call only the migration matching the version
// if the version is currently 6, then 0-5 have already ran
// and SHOULD NOT be ran again
kickOffMigration(version, trans);
});
});
}
//helper function used to check for the existence of a migration for a version number
//and then kick it off if one exists
function kickOffMigration(version, trans) {
if (migrations[version] && typeof migrations[version] === 'function'){
migrations[version](trans);
}
}

Writing a Migration

You may have realized that we don't currently have any migrations to run - we simply have a variable placeholder for them. Now that we understand how to use PRAGMA user_version to see which migration needs ran, it's time to write a migration!

Each migration has a single responsibility of continuing on the migration process, but that can be broken down into 3 key steps:

Perform DB manipulations the migration is built for

Increment the user_version property by 1

Kick off next migration (if there is one)

The first two steps are important, but let's take a minute to think about the 3rd step. This is something that I almost overlooked, so I think it's worth pointing out its importance.

Let's say a user has installed your app at the very beginning, the db was seeded and life was good. Then, after some time goes by, you release an update with a migration for the db - the seedDb function checks out our current user_version and runs the one migration appropriate for the current version - and life's still good. Same thing happens again, so we have 2 migrations present. Now, a brand new user wants to download your app. Their db gets seeded, the user_version checked, and the first migration is ran. Then the app breaks because your objects and views were expecting the data to look how it should after the second migration. If each migration doesn't fire off the next one, then it can be bad news for someone who is getting all of the migrations at one time! So, let's look at the code:

I'm working on building my first hybrid mobile application of substance and am using Cordova and a nifty sqlite plugin - cordova-sqlite-storage. This allows me to use one (or more) sqlite database files as my data storage. There are a few tips and such that I've found handy and thought I'd share here.

First DB File

Now that we have the plugin installed, let's create a javascript file that will act as a service layer of sorts over our database file. We'll call it widgets.db.js, and in this file we'll tap into the deviceready event so that we know we can access the sqlite plugin.

Good deal, we've initiated our database file, and have some variables set up to help us later. One thing to point out here is that seedDb() function call. I actually prefer seeding sqlite databases inside the javascript file, as opposed to having a file named the same (i.e. 'widgets.db') that contains SQL for seeding the database. This is for instances where I have a collection of items to seed - it's much more handy to loop over those items to seed the DB than to write them all out in SQL. Here's an example of seeding the database. Note the use of promise library, Q, here. We're making our dbLoaded variable a promise - this will come in handy later to avoid any potential race conditions of querying for items before the seeding is done.

Querying the data

Remember seeing that window.widgetDbService = {}; line in the first code snippet? That's how we're going to expose this simple service to the rest of our app. Typically one would prefer something like CommonJS Modules, instead of adding to global scope, but we'll keep it super simple here. Let's add a method to get all of the widgets, and another to delete a widget by its id. Note: We'll also use the Q library so we don't have to deal with icky callbacks

And it's that easy - you now have a service module that abstracts away working with sqlite data, and even promise-ifies all the interactions so you don't have to deal with callbacks.

Stuff I wish I knew up front...

This project gave me my first opportunity to use sqlite, so there are some things I've learned the hard way and really wish I'd have known up front. Here's some of those things:

Error codes suck A 1 typically means you've got an issue in your SQL and a 19 means you've got a constraint violation. The 1 is the worst, as I never saw any accompanying data on what, specifically, the error was. Anyways, here is a handy list of the codes and their purposes.

Each DB File Connection is Mutually Exclusive This on really annoyed me when I realized what was going on. Any time you call window.sqlitePlugin.openDatabase(..), it's creating a database that is mutually exclusive from any other(s) that you create. Again, my first time using it and I didn't see that anywhere in the parts of documentation I read, so it blew me away when I created a new file and its DB connection couldn't see any tables that were created in another connection... In hindsight it certainly makes sense - but I would've saved a few hours researching if I'd known this up front. If you're needing to separate stuff out into multiple files but use FK constraints and such, make a singular db connection that they all share.

FK Relationships are not enforced by default In sqlite v3, you have to run a PRAGMA command in order to turn on FK enforcement - db.executeSql('PRAGMA foreign-keys=ON;', []);

That's it for now - I'll be posting more as I continue building this app. I'm using the ionic framework, so I'm sure I'll be writing some more about it soon :)