Dabble Week Three

Last week I said I was going to focus on product design. And I did. For at least a few days.

Monday

I explored ways to work with plots and subplots. Many writers use 3×5″ note cards to help craft and organize their plots. Many writing products give you note card feature to mimic this. Note cards work great. They really help to organize the main plot of a story.

Note cards aren’t as great at organizing and tracking subplots in relation to the main plot. J.K. Rowling used a hand-drawn grid to help her track subplots for at least one of the Harry Potter books. So I spent time thinking through how Dabble might help you track multiple plot lines throughout a story.

I worked out what it might look like if I were to arrange note cards into a grid.

plotsketch1I didn’t like it. This would require a lot of scrolling, up and down, left and right. It might be fine for a macbook pro with that nice trackpad, but not for many other laptops. I continued to mull over the problem.

Tuesday

I considered the different hats we wear as writers. Plotting, writing, and editing are the three main hats you wear when creating you work of art. After the creation is publishing and marketing, but I don’t know if I’ll touch those hats. Dabble will help you focus on the role you are in, without distracting you with the other roles. For example, when plotting, Dabble will focus you on the architecture of your story. When writing, Dabble will focus you on the words. You will be in scene with your characters. When editing Dabble will focus you on eliminating adverbs, or polishing dialog.

Next, I thought through several interface design problems. I considered a tabbed interface (like the browser) to work with multiple documents at once. I thought through how to store the text (as HTML, markdown, plain text). I thought through how undo/redo should work (per document, across the whole manuscript, how it should work in a product where documents can be looked at from scene, chapter, or the book level). I made some good decisions.

Ideally, none of this work will be apparent to you in the end. Dabble should make it easy to do what you need and just work the way you would expect. My job is to make the tool disappear leaving only your novel.

Wednesday

I had a nice brainstorm session with my twin Tyler. A huge shout out to him (thanks Tyler!) because I ended up with some great stuff. We discussed a lot about how he would like Dabble to work. I got some great ideas on how you might work with the manuscript and how you could deal with subplots. I also had affirmation on the direction I was going overall. I will share about what we came up with as the features are implemented.

Thursday

I went back to coding. I should have continued with product design, but hey, I’m a programmer. I added the concept of placeholder text to the navigation. You can name each book, chapter, and scene. But before you  name things you should get helpful placeholder names. This is one from Tyler.

Screen Shot 2015-08-19 at 11.30.28 AM

Your scenes will show the first few words which can help identify a scene before naming it. You may never decide to name scenes if this works good enough.

I also added the ability to edit your scene text. Up until Thursday you couldn’t actually write your book (and have it save). I added a stop-gap implementation for writing the words. It doesn’t support undo/redo the way Dabble will, but it works for now. I typed up the beginning of a popular book and things worked out fine.

Screen Shot 2015-08-20 at 10.48.20 AM

Friday

I added filtering to the navigation. Perhaps this was a bit premature, since there are more important features waiting to be done. But I had the itch to do it, so I did.

Screen Shot 2015-08-24 at 11.14.11 AM

You can find scenes that mention a particular person or thing.

Perhaps this week I’ll prioritize my backlog so I can work on the most important pieces first.

Saturday

I added support for creating new scenes and chapters in-line! When you write, you don’t want to take your hands off the keyboard, even to create a new scene or chapter.

When you hit Cmd+Enter on Mac or Ctrl+Enter on Windows (the standard shortcut for a page break) you will get a new scene. If you hit Cmd+Enter twice you will get a new chapter, as show below. Hopefully the video is the right format for your browser.

Summary

Great progress this week in terms of product design (most of which I have not disclosed) and some features. I may continue doing a bit of both each week.

 

Second Week on Dabble

Apparently one post is a precedence (according to Ryan Tyer). Now I must write another. You can catch up with my first week with Dabble.

This week there was less visibly done. But nonetheless important stuff.

Monday

As a writer, you’ll likely have many projects, completed, in the works, or just placeholders for an idea you have. You don’t want to scroll to the bottom of an alphabetical list to work on your “Zenocide” smash hit. Nor do you want to write down manuscript ideas on paper just because adding them to Dabble ordered by creation date will push your current novel to the bottom.

So Dabble now sorts by last opened date in the manuscripts view. The projects you haven’t touched in forever will be nicely collecting dust at the bottom (I have yet to add the dust effects) and your fresh new novels will sparkle and gleam at the top (yet to add sparkle and gleam effects). A screenshot you may imagine is sorted in order of last opened.

Screen Shot

Tuesday

Nothing. I slacked. I let you down. I failed!

But!

I got to sleep in.

Wednesday

Navigation day. I prettied up the navigation. I wanted the fonts to match in order to make it easier to find what you’re looking for. The book nav is now the same font as the book title. The chapter nav is the same font as chapter headings. Scenes are now the same font as your manuscript.

navigation

I made the nav less “deep”, meaning, your scene is now indented a quarter of the way from the left edge instead of half way, giving you more room to have a meaningful title.

You can also now open and close the sections, because hey, who doesn’t like opening and closing things?

I cleaned up code and added CDN support. That means the files are hosted on a fast server instead of a slow one. Yay!

BY THE WAY! Did I tell you I’ve been building this for and testing this in the browser? Well, I have been. I glossed over it pretty quick last week, but Dabble will have a desktop app for working from the comfort of your own lappy, AND it will have a browser version (pretty much identical) that will allow you to continue writing during your lunch break. Huh-mazing, I know, right? This feature will be part of the paid plans which include cloud storage and syncing between devices.

Thursday

Thursday, the day I put in book-title/author/chapter-title editing. Since these portions didn’t need any great programming genius (in contrast to the scene editing) I was able to get them in easy enough. It was good to be able to rename my book. No more Untitled by Unknown (might be an interesting name for a book, but not for every book).

doc-editFriday

I did a bunch of code and visual cleanup that my week of coding left behind. Gotta keep up on those things or you find yourself going slower and slower as time goes on (and you make more bugs, and you hate your work, and life sucks, and it’s just better to keep up some basic house keeping).

Saturday

A special day. The day I added navigation between documents. Up until this day when you opened a manuscript you would get the full book and when you clicked on the navigational pieces on the left, it would scroll to that location in your book. This is better than Word where you have to scroll and scroll and scroll. And scroll. But I want to focus solely on one chapter. Or even one scene. So now, when you click on a navigation item it opens that one item up solo. All by itself. You can look at the whole book, a complete chapter, or a single scene. You have the choice now. I may add a toggle setting to switch between scroll and select, but I don’t think it will make the cut. Focus is much better this way. Focus is essential to a writer.

I also made the folder arrows hide unless you hover over the nav item. Cleans up the nav IMO. The screenshot below didn’t capture the mouse, but I was hovering over “Characters”. I may change my mind and decide it is nicer to know at a glance what is open/closed. But for now, I like having less visual clutter.

arrows

Summary

The first week was some initial design and getting screens up. The second week was more under-the-hood programming and making stuff work.

This week, I am putting off tackling the hard problem of the text editor (procrastination is one of my best skills), and hitting product design. I find that when wearing my programming hat, I have a hard time keeping the vision of Dabble at the forefront. So I’m getting it planned out and written down. This week I’m wearing my product design hat.

As writers we have several hats. Hats for plotting, writing, and editing. This concept informs my product design and plays a big role in how Dabble will work for you. You generally only where one hat at a time. Whether you are a plotter or a pantser. And Dabble will help you focus on the role you are playing at a given moment. More on this later.

First Week on Dabble

Last week I began work in earnest on Dabble, a writing app for novelists. This is my week at a glance.

Monday

I started creating a logo, because hey, it’s got to look gooood. I want to this product to be fun to use, to have personality. I’m taking inspiration from Slack.

I looked through a bunch of fonts on Google Fonts typing in “Dabble” to the preview and picked my 3 favorites. Then after consulting with my lovely assistant/wife, Brittany, I chose Comfortaa.

dabble-comfortaa

I didn’t like the ligature on the L so rounded that off, tilted the E because I thought it looked nice, and gave it some coloring that makes it more fun, less utilitarian. Between the font, the color, and the E, I thought this conveyed a good sense of mischief.

dabble-logo1

I also threw up some files into an Amazon S3 bucket for a website, www.dabblewriter.com, so I could show off my logo to Tyler, the twin. And I posted to my friends and family on Facebook about the new company and product. I’m that excited about it.

Tuesday

Unfortunately I discovered my subconscious must have been working hard on Monday. Because when double checking I wasn’t stepping on any copyright toes for writing tools with the name Dabble, I saw I very well may be stepping on toes with my logo design. Hello dabble.co! I must have seen you earlier when vetting the name.

dabble-co-logo

The fonts were too similar, and even the E was slanted. Back to the drawing board. The runner up fonts were Baumans and Megrim. I ended up with the latter because Brittany liked the A and Baumans was still similar-ish to Comfortaa. I present you the Dabble logo.

I also put together a quick attempt at marketing and an email capture so people could sign up for updates. Facebook friends were interested in the progress, and I wanted to be sure to get emails for those who want to be part of a beta.

Wednesday

I spent some time doing product design.

FullSizeRender

Thursday

I made the Project List view, which I changed names to Manuscripts view. These are not just projects after all, they are manuscripts.

I started off wanting to make a single novel look like a book and with series looking like a boxed set. I followed http://srobbin.com/blog/3d-css-book-covers/ and had something ok looking, but it didn’t feel right.

I ditched the book idea and went with a simple pile-of-papers approach, since these are unfinished/unpublished works. I think it turned out nicely.

Screen Shot

The piles of paper are different from each other, and when you mouse over them they straighten out a bit and raise off the page, like you’re picking it up. I love making little UI interactions delightful. This was very fulfilling.

Friday

The day I made it a web app instead of just HTML. I brought in Chip for keeping the HTML in-sync with the data and PouchDB to store the database in the browser (also supports syncing with a server when online). This was just beginning work.

I also added loading messages, again inspired from Slack. Unlike Slack, I leave the message up long enough to read it, allowing a click anywhere to close it immediately. I always want to read those slack messages but too often they disappear before I can. Thank you Writer’s Digest for a compilation of quotes from famous authors.

Screen Shot2

Saturday

I set up my base model classes and the loading/saving mechanisms so when a manuscript (actually all manuscripts currently) gets loaded all the objects get linked together by id, and when an object is saved those links turn into ids. Because I want to save sort-order in my manuscripts, I’m storing the data like this:

{
  "_id": "abc",
  "type": "book",
  "title": "Escape from Waterfall",
  "chapters": [
    { "_id": "def" },
    { "_id": "ghi" }
  ]
}

I got Manuscript creation/deleting working. I added saving of lastOpened date so old manuscripts naturally sort to the bottom (useful if you have a lot of manuscripts).

I also hooked up my manuscript editor page (the one thing I had coming into this week) to display manuscript data.

I imported a 10k word script into the tool to test out a bunch of chapters. Then I did the same 99 more times to test load. It took 8 seconds for the page to load all that data in (in the future I’ll only load the manuscripts when they’re opened) and it still worked like a charm. Page scroll was fast. Everything was snappy.

Google ChromeI’m not including a shot of the full script I imported since I haven’t had permission from the author to do so.

Lastly I added scrolling to the book/chapter/scene you click on so you can jump to that place in your script.

Summary

I feel really good about what I was able to do in just one week. I’ve only been spending a few hours a day on this outside of my day job. Today I wasted my few hours writing this blog post (ok ok, you’re not a waste), but I’m too excited about this project and my progress to keep it to myself. I feel really good about the product I have envisioned and the direction I’m going.

If you’re interested in beta-testing Dabble, or just want to keep up on its progress, sign up for the newsletter on dabblewriter.com. I have much more on its way.

Starting at Riot Games

I am excited to announce that I will be starting work at Riot Games on Monday. I just got my laptop so I suppose it is really happening. Good thing too, because I’ve already given leave at TeamSnap.

First I want to say that TeamSnap has been the best company I’ve ever worked for. The team is fun, talented, and just great people. The management knows how to guide without micro-managing. Every employee’s voice is heard. There are no office politics. The dev team is all remote, so working through github while lounging on my couch is awesome. The tech is interesting. The leadership is solid. I am very sad to be leaving.

I am very excited, however, to be joining Riot Games. Their flagship product, League of Legends, is said to be the most played game in the world. If you haven’t heard of Riot or League of Legends, don’t be surprised. They’ve spread through word of mouth and it just hasn’t reached you yet. It’s a very fun team-based game with plenty of strategy and room to grow and enjoy the game for a long time. Riot puts a lot of effort into the game itself, as well as other creatives like music videos (such as one of my favorites below).

And my twin brother works at Riot, so I’ll get to work with Tyler again! That will be a lot of fun.

Scrollable Calendar Widget

Scrolling Calendar

See the Demo.

Update: I built and tested this on Chrome using my macbook’s trackpad. It scrolls very smoothly, however I’ve heard reports that a scroll wheel jumps from month to month, but can cut off dates half-way. Needs to be updated for scroll wheels. Also touch events for mobile.

I haven’t been on Dribbble in awhile, but last night I was poking around and found a bit of inspiration. A little calendar widget design by Dribbble user Cat Noone caught my eye, but what really sparked my interest was the fisrt comment below it:

Really love this widget! Quick question how do you change the month? Or is the intention that you can only pick a day during a specific month?

I started thinking how the calendar might work if you used scrolling to change the month. From Cat’s design it seems there is a window of delivery, so she may not need to change months. But most apps I’ve used do.

Several hours later I ended up with my own Scrolling Calendar widget. It is just a prototype and could use work to make it more robust, but it will give you a feel for the scrolling interaction.

Building the Scrolling Calendar

I started building the calendar by setting up the HTML I thought I would use and styling it (borrowing from Cat’s color scheme). The initial HTML looked something like:

<div class="date-picker">
  <header>December 2014</header>
  <table class="calendar">
    <thead>
      <tr>
        <th>Su</th>
        <th>Mo</th>
        <th>Tu</th>
        <th>We</th>
        <th>Th</th>
        <th>Fr</th>
        <th>Sa</th>
      </tr>
    </thead>
    <tbody>
      <tr>
        <td class="disabled">30</td>
        <td>1</td>
        <td>2</td>
        <td>3</td>
        <td>4</td>
        <td>5</td>
        <td>6</td>
      </tr>
      <!-- etc. -->
    </tbody>
  </table>
  <section class="controls">
    <button>Select Date</button>
  </section>
</div>

Many calendar components use tables to display, with each week being a row in the table. The dates which are not part of the current month but show because they are on the current week, they get a “disabled” look.

I wanted my scrolling calendar to show the current month’s dates in the highlighted blue color, and the other dates with the disabled look, but I didn’t feel like iterating over each date cell to add and remove classes was my favorite method. Couldn’t I use CSS to toggle whole months at a time instead? (It seems like Cat’s company, Liberio, actually has specific date ranges, in which case doing it by day makes the most sense.)

So I threw out the table. That always gives me a good feeling when I get rid of a table—I don’t know why. And instead of using spans and divs, I thought I’d get all HTML5ey and use custom elements. So <week>, <day>, <month>, and <date> were created.

Custom elements

This screenshot didn’t include it, but inside <week> would be <day>Su</day><day>Mo</day>, etc. The day and date elements became inline-blocks with a set width and height, and their containers got a set width so they would automatically wrap every 7th item.

Once I had the HTML and styles I wanted, I started to code it. I pulled in the trusted moment.js library to populate the dates, and since I was using a date library I auto-generated the weekdays with Moment as well (that’s why the screenshot above is missing the weekdays). The calendar will support multiple locales now!

When I was using the table-based HTML my thought was as the user scrolled up or down, rows would be added at the top or bottom of the table as needed. Now I would be creating months at a time. So the initial population of the calendar contains 3+ months. The current month, the previous month, and the next month. The “+” comes in because I need the “filler” dates from the month before the previous (e.g. January 2015 would show 28, 29, 30, and 31 from December). I can’t just leave these out because I am no longer using a row-based layout, so they are needed to make sure the dates are in the correct place.

At first I tried the “scroll” event, but it was the “wheel” event that I needed. You can’t get the wheel event’s delta change, and you can prevent it’s default action. When the user scrolls over the calendar, I use the delta to know where the screen should be, add a month to the front or back of the calendar if needed, and set the current month if needed. Scrolling up and down will change months very quickly. Try it out.

I played around with the “break point” in the middle of the calendar to determine when to switch the active month. It turned out that directly in the middle wasn’t quite right. It always looked like the break point was too low, because of the amount of visible text above and below. Also, the breakpoint couldn’t be a line, but a margin, otherwise you could get jitter when scrolling slowly between two months.

The final touch was the date selection. Handling the click on a date wasn’t difficult, but I ran into a usability issue when clicking on one of those “disabled” dates. I wanted to allow it so you didn’t have to scroll all the way when you saw the date you needed, but I also didn’t want the top of the calendar showing “January 2015” when you just clicked on the December 28, 2014 date.

To fix this, I selected the month for the date when you click on it. This highlights those dates in blue and shows the correct month in the title bar. You can still scroll after that, but when you click you get confirmation of the date you selected.

Because I’m using moment.js with locales the calendar should work correctly for you, with Sunday being the first day of the week in the US and Monday in many other countries.

Things to Improve

This isn’t ready for prime time as it is just a proof of concept. If you wanted to go the distance you would want to add < and > buttons on the month line. Just because a user can scroll through the months, doesn’t mean that they will know they can. You’ll have to give them the training wheels and let them discover the scroll feature for themselves.

Currently I only create one month in front or back when scrolling past the break point. Using my track pad it is pretty smooth until I try to flick it very fast. It halts the flow. In my prototype you can still get years down the road very quickly, so I didn’t fix this, but to make it a smooth experience you would want to use the delta to add/remove several months when needed instead of just the one at a time.

You could add other features, such as selecting a range of dates, adding time selectors like Cat’s original design, providing maximum and minimum dates available, giving some sort of visual indication that scrolling is possible (without an ugly scrollbar hopefully), and packing it up for reuse of course.

What do you think, would this be useful and intuitive?

A Better jQuery by Extending the DOM

Not very long ago creating your own custom HTML was considered A Bad Thing™. If you deviate from standards you’re just as bad as table-based layouts and the <blink> tag. Now we have Custom Elements, Angular.js and Ember.js and Polymer. It’s alright now because it’s a standard. But before it was a standard I was trying to hack support for custom elements in Simpli5 with the __proto__ element. IE didn’t support __proto__ so it came to a halt. Note: Polymer’s Custom Element polyfill relies on the __proto__ property, and IE11 supports it now, even though it is non-standard. Oh, and we can look forward to using Object.setPrototypeOf.

What about extending the DOM? jQuery makes things really nice, but it must wrap everything to accomplish this, adding memory and slowing down (not significantly, so this may be a lame argument) access. Why can’t we just extend the DOM to add all the useful functionality we need? Prototype.js does it. Here are a bunch of easy wins, along with suggestions for some of the more in-depth ones. This won’t work with really old browsers such as IE8.

How to Extend

Before we get started, here’s a quick note on how you ought to extend the DOM. Make sure you use Object.defineProperty or Object.defineProperties on the prototypes of the DOM elements. This allows you to define getters and setters if needed, but it you can also leave the enumerable setting at its default of false so that for-i-in loops don’t see your methods. Otherwise you can mess up other libraries. To match the other methods, set configurable and writable to true. I’ll be using Element.prototype.method = xxx in my examples for brevity, but know that it really means

Object.defineProperty(Element.prototype, 'method', {
  configurable: true,
  writable: true,
  value: xxx
})

Also, remember to always return this from your methods if you’re not returning a value. That way they can be chainable like jQuery.

Finding Elements

document.querySelector(selector) and document.querySelectorAll(selector) return an element or all elements respectively, using the CSS selector provided. You don’t need jQuery to do this anymore, and you don’t even need to extend anything to have this. These same methods exist on every element, searching their children for the selector provided. And if you want to shorten the call, set Document.prototype.find = Document.prototype.querySelectorAll and Element.prototype.find = Element.prototype.querySelectorAll.

You’ve already got the built-in element.nextElementSibling, but if you really want it to be shorter, you can make a getter on Element.prototype.next to return this.nextElementSibling.

We can make sure the built-in element.matches exists without prefix by using a pollyfill:

if (!Element.prototype.matches) {
  Element.prototype.matches = Element.prototype.webkitMatchesSelector ||
  Element.prototype.mozMatchesSelector ||
  Element.prototype.msMatchesSelector ||
  Element.prototype.oMatchesSelector
}

which allows an element.closest method to match jQuery’s method of the same name.

Events

Why not add Element.prototype.on = Element.prototype.addEventListener and Element.prototype.off = Element.prototype.removeEventListener (and the same to Document and Window) to shorten our event listening? Or to really shine we make the on method accept a selector and use event.target.matches to optionally call the listener, like jQuery, but built in.

You can add a trigger method if you don’t like dispatchEvent. It can take a string and make a MouseEvent, KeyboardEvent, CustomEvent, etc. for you.

Lists of Things

jQuery is nice because you can do one action to a whole list of elements at a time. What about extending NodeList? You know, that non-array you get back from calls like element.children, and document.querySelectorAll. We could add a bunch of methods to NodeList.prototype that have the same name as methods we add to Element.prototype except that the NodeList versions iterate over their elements and call the element method of the same name. This would allow element.children.on('click', onClick) or document.find('.tag').removeClass('tag').

Dealing with Nulls

One things jQuery does nicely is it handles nicely when the thing you’re looking for doesn’t exist. $(‘dummy-element’).on(‘event’, function(){}) won’t break, even though there is no dummy-element. When we’re getting back NodeLists it’s not a big deal because iterating over 0 elements won’t cause any errors. But you may want to create a dummy element class to return from calls to next() or prev() which only return one element, so that you can continue to chain without breaking. I’ll let you figure out how this could best be done, but one idea is you might think of returning an empty NodeList from document.createElement('div').children or something.

More Complex Settings

Creating elements from strings of HTML is one thing that takes a little more doing. Fortunately, jQuery has already done the work for us and we can just add the method to Document.prototype.create or something. If you don’t want to go looking through the jQuery source, Krasimir has already done the work for you.

Another heavier item is setting a bunch of CSS properties at once, taking into account browser prefixes. Here is one solution that I’ve come up with which extends the style property of your elements.

// Allows setting a lot of CSS styles at once, doing translations for vendor-
// prefixed styles.
// E.g. element.style.set({ color: red, transform: 'rotate(7deg)' })
var prefixes = ['webkit', 'moz', 'ms', 'o']
Object.defineProperty(CSSStyleDeclaration.prototype, 'set', {
  configurable: true,
  value: function(properties) {
    var style = this
    Object.keys(properties).forEach(function(property) {
      var value = properties[property]
      if (typeof style[property] == 'string') {
        style[property] = value
      } else {
        var capitalized = property.charAt(0).toUpperCase() + property.slice(1)
        for (var i = 0; i < prefixes.length; i++) {
          property = prefixes[i] + capitalized
          if (typeof style[property] == 'string') {
            style[property] = value
            break
          }
        }
      }
    })
  }
})

The Rest

Now that you’ve got the hang of it, you can see how you might easily add append(), prepend(), addClass(), and any number of things that you need from jQuery. Even if you only use the library for pet projects, it will be a good exercise in learning the DOM methods and build your understanding of how jQuery works internally as well.

Extending the DOM is a lot of fun and it can be quite enjoyable to work with native objects everywhere, sprinkled with your own helper methods. I don’t know if something like this will ever become mainstream, but you shouldn’t have any issues doing it with your own applications.

Because of potential conflicts (the main reason for not going this route), it is best to avoid extending the DOM in libraries that you want to load on other websites. Imagine if Facebook used a library like this in their Facebook Like button, and Google did the same in their Google Plus button. One of them would likely break the other, and they are so often on the same page that it would always be broken.

MyStickies Uses it Minimally

I use element prototype extension for MyStickies, but only to pollyfill missing functionality such as element.remove, element.matches, and element.classList. This way I won’t conflict with any other libraries (the MyStickies script is loaded on every page you browse when you install the extension), but I can still rely on the useful functionality that is standardized, but not implemented yet in every browser I support.

What say you? Is extending the DOM the epitome of all evil? Or would you do it for your own applications?

Next Page »