A few weeks back Ryan Stewart posted on his idea for PhoneGap Starter projects. They were designed to take some of the grief out of getting started with various aspects of PhoneGap and PhoneGap Build projects. I've contributed a project based on one of pet peeves with PhoneGap Build: the lack of productivity.
Don't get me wrong. I love PhoneGap Build. I love not having to open multiple IDEs to work on mobile apps. I love working on HTML apps in HTML tools - but you lose a few things in the trade. You lose being able to click one button and have your work available on your device. You miss being able to click and get a pop up that says your work is ready to view on the device.
These things seem small, but having tried to build actual projects in PhoneGap Build, I found them critical. I would go kick off a build, and then have to wait for the build to be complete. I'd open a browser windows while I waited. 20 minutes later, I would cycle through my Chrome windows and remember that I was waiting for a build to complete.
A few months back I tried my hand and solving this and came up with a shell script that handled this for Android. Over the past few weeks, I've added to, improved, and modified it. I now have a solution in ANT that does the following:
Uploads files to PhoneGap Build triggering a rebuild
Polls for IOS and Android to be finished
Downloads ipa and apk files when ready
Installs them onto connected iOS and Android devices
Uses the "say" command to let you know when things are done.
It takes the form of an ANT build file, some properties, and 2 shell scripts. I've posted the whole thing as PhoneGap Starter Productivity on github. As far as I know this will only work on OS X, which I hope isn't a huge problem for anyone, and I'm willing to collaborate with someone to make them more cross platform friendly.
Also I feel it's important to note, that while these scripts mean you don't have to use the IDE to accomplish these tasks, you still have to have Xcode and the Android SDK on your machine to use them.
Next week, I'll be speaking at D2WC, a designer/developer workflow conference in Kansas City, Missouri.
I'll be talking about Using PhoneGap Build to simplify your mobile development life. One of the great things about PhoneGap is that it allows you to use HTML JS and CSS to build your applications, but you still have to use native tools to build your apps. PhoneGap Build helps immensely with this, but you make some productivity sacrifices. This session will show you how to maximize your work, and touch as little of the IDE as possible.
First time for me at this conference, but from what I understand it's a great conference that tackles a specific topic: getting development and design to work together better. Great goal, really looking forward to it.
D2WC May 16-18 Kansas City Marriott Country Club Plaza 4445 Main Street Kansas City, Missouri 64111 USA
If you were not aware of them CSS Regions are proposal to CSS3 that would allow for some magazine like layouts in HTML pages. Adobe has been leading the charge on getting them into WebKit. They are currently available in Chrome. (Also I think IE10)
Now the way they work:
You create a bit of content in an element like an article
You designate that article as the source of a "flow"
You designate other elements as the recipients of the "flow" (We'll call them "regions")
Then when the browser renders the content
The element designated as the "flow" is not shown
The content of the "flow" pours into the "regions"
Assuming this HTML:
And this CSS:
You get something like this:
I have a demo. It only works in Chrome. Resize the screen to see the flowing of the content.
I was presenting on them the other night and I got asked a pretty good question.
Have you thought about how these degrade?
I made a bad joke, then mumbled something about if the browser doesn't support CSS Regions then the original "flow" element gets displayed and all is well.
I tested it today. And all is not well. Because I still created those region elements. And they show up down at the bottom and add whitespace.
Check out the demo on any browser bu Chrome and you'll see what I'm talking about all the way at the bottom.
So after some experimentation I decided that the best way to handle this was to create my four regions with CSS exactly how I had but only inject the region holders if the browser supports regions, like so:
Hello antipodeans and antipodiphiles, I will be speaking at webDU 2012 in Sydney, Australia in a few weeks. If you have never heard of webDU, it is an absolutely fantastic web conference. It provides a great environment for honest open conversations and learning about the field.
I'll be giving two talks:
Semantic HTML5
A foray into the geekier elements of internet HTML plumbing.
The Future of HTML5 Motion Design
Talking about Adobe Edge, and showing off some of the cool things we are doing with browser technology.
It looks like I'm going to be speaking at MoDevUX outside Washington, DC later this month.
I'll be talking about how to make great user experiences in mobile applications with PhoneGap.
It's a new event and group for me, and it looks great. It's a UX and UI focused conference with a focus on mobile. Better yet, here it is in their words:
MoDevUX will bring together leading mobile developers, UX/UI designers, architects and managers to break the mold on user experience and design. Attendees will discover the latest in mobile UX/design methods and meet likeminded people at the edge of the mobile frontier. Be sure to check out the workshops available on the 19th and the hackathon on the 21st!
I'm working on a little demo mobile application for an upcoming project, and I wanted to add sliding transitions between pages. Pretty simple, right? You just use jQuery, jQuery Mobile, zepto, or one of a bunch of other frameworks, and they handle this for you. I didn't want to. Part of my goal with this particular project is to challenge myself to work without a framework so that I can see how this stuff works by hand. Also I wanted to keep the HTML as slim and uncrufted as possible
Googling found very little to go on - except a micro solution for page transitions by FASW. I like it, but it's still using someone else's work, and I didn't like adding even the little bit of HTML cruft that it needed.
So I rolled my own.
The solution I came up with actually is pretty lightweight and is powered by a little AJAX, some CSS transitions, and CSS transition events. It's also important to note that this only works with WebKit. (My personal use case is for a mobile application with PhoneGap targeting Android and iOS, so I only need WebKit compatibility.)
First thing is to set the CSS of the body to have a transition on it, so when I move it around it's animated.
Next thing I do is fire off a function when the page loads to replace all links with a function that will create the effect. I use some techniques I learned from a great article named From jQuery to JavaScript: A Reference to handle these operations without jQuery.
Next step is to use AJAX to get the linked page.
Now comes the transitions. What I need to do to accomplish this page slide is:
Slide the page off the screen to the left.
Instantaneously move the page to the right side off screen
Replace the contents of the body with the new content
Slide the page on to the screen from the right.
I have to do it in that order. If you replace the contents independent of the animation, you get weird effects like the page changing then the animation happening, which looks jarring. Or you get the opposite, the transition happening, then the contents changing. Looks ugly. Trying to time these proved problematic. The best thing to do would be to wait for the transition offscreen to happen, then change the content, then move it back on screen. I was able to do this by using a transition event.
Basically as far as I can tell there is only one transition event "transitionEnd" regardless of browser manufacturer. I haven't been able to figure that out. Animation events appear similarly limited. So here's how I did it:
I moved the body to the left side of the screen.
There is an event listener that handles making it transparent while I move it to the other side of the screen.
I then replace the content, make it visible again, adjust the browser history, and move it back to the center.
Then to be thorough, I make sure that I reverse the process if the user hits the back button.
Is this the best way to do this? I have no idea. But it works for me and I couldn't find a comparable solution via Google.
Several incidents in the past few weeks, both public and private, have led me to the conclusion that we all suck at apologies when we have offended people. I'd like to try and start a conversation to see if we can fix that. I feel like I am qualified to give advice here, as I spent my 20's as an angry and often offensive guy, who had to apologize quite a bit. Because of this, I've learned a little of what works and what doesn't.
Let's start with a premise. You said something that offended someone somewhere. They are angry, and they have called you out on it in some fashion. (It's vague, but every example I could come up with might have been offensive.)
"Why should I apologize, what I said (or did) was right?"
This here is the major problem we have with apologizing. We think that apologizing means that we are saying "I was wrong, and you were right." It doesn't. When you offend someone, you have damaged your relationship with them. Whether you are an individual offending another individual or a company who offended a potential market, your actions have damaged the relationship. The true purpose of an apology is to try and fix the damage in the relationship between you and the offended party. That should be your goal.
"I didn't mean to offend you."
Actions have consequences, intentions do not matter. Actually, it would be better to say, intentions can mitigate consequences, but they cannot erase them. Suppose I hit a young man with my car. That my intention was to drive home has no impact on the consequence that the young man's leg is broken. Now the fact that I was soberly driving home, and did my best to swerve out of the way can maybe mitigate what the law says about my culpability, but it cannot fix the man's leg.
So, good on ya, that you didn't want to offend anyone. Unless you're a deliberate provocateur I don't assume anyone believes you did. If you were deliberately offending people, I assume you don't have any interest in apologizing. So if you are apologizing, shut up about your intentions. You just sound like you are trying to excuse yourself.
"I don't see what you are getting so upset about."
This is a shitty, defensive way of saying "I don't understand how I offended you." That's fine. It is perfectly acceptable to not understand how you have been offensive. If you were able to wrap your mind perfectly around the thoughts and considerations of the offended party, you probably wouldn't have taken the action that offended them. It's perfectly fine to ask for clarification and an explanation. Just try not to phrase that request like an asshole.
"I'm having trouble wrapping my mind around this, can you explain where you're coming from?" Good.
"Can you tell me why a person like you is offended by this?" - Bad.
"I can't have said something homophobic, I have quite a few gay friends."
Repeat after me: There is no such thing as a "ghetto pass." That you have gay/female/minority friends does not mean you can't say homophobic/sexist/racist things. It means that you probably shouldn't say them, and perhaps you should check to see if you still have those friends.
"You're overly sensitive."
This encapsulates a lot of things but at the core of it you are denying the reasonableness of the person taking offense. The thought here being there are thoughts that while controversial, reasonable people can talk about without taking offense. There are two problems with this.
The first problem with the reasonableness trope is that it assumes offense is an intellectual response. It's not, it's an emotional response. Therefore reasonableness of the offense is irrelevant as offense in this case is not a product of the reason. You can tell someone to stop being sad because their life is overall great, but if a personal tragedy has occurred, you can't stop them from being sad. Likewise whether or not it is reasonable to be offended is irrelevant in the face of actual offense.
The second problem with reasonableness is that it doesn't matter. Because reasonableness is part of the right/wrong discussion. "It is not reasonable to be offended over this, therefore you are wrong and I am right." --which is irrelevant, because apologies aren't about right and wrong, they're are about repairing the damage to the relationship.
"140 characters/email/IM is not enough to have a proper conversation about this."
You're right. Happy? Now stop wasting time and move to a higher bandwidth form of communication.
"That's not what I meant."
Okay, this is a tough one, and it's different from "I didn't mean to be offensive." It happens when what they think you said and what you think you said are two different things. It could be because of someone mishearing you. It's also perfectly possible that someone is reading into what you have said or done, and giving it a context that makes it offensive to them. It's also possible that you were not communicating well.
Again it's time to remember what's important, fixing the damage. So apologize first, get acceptance that you want to fix the damage, then start to talk about the misunderstanding. Ask what language you could have use to make your intended meaning come through.
So how should you apologize?
Start with "I am sorry I offended you." No qualifiers. No "If I offended anyone." You're sorry that the relationship is damaged and that you caused the damage. Start from there.
Seek an understanding of what you did that caused offense, and acknowledge it.
No excuses. Unless you were kidnapped, drugged and slammed down in front of a keyboard or phone, you are responsible for whatever you did to offend someone. Even if it is a "not what I meant" incident. You're responsible at least in part for the misunderstanding.
Don't apologize angry. When we are criticized, it's easy to get angry and emotional ourselves, and therefore get in the way of a real apology. If the criticism you receive makes you angry or defensive, then wait and calm down. Very little relationship damage can be fixed with anger.
There you have it, apology advice from someone who's had to do a lot of it. It's not about winning an argument, it's about saving a relationship.
Let me first say that I think it's awesome that the W3C is taking this on. I think that variables in CSS will ultimately be a good thing. It will make it easy to reuse colors and other CSS properties. It will make large amounts of redundancy go away. It will make CSS files smaller, and therefore give less toe-holds to bugs.
That being said I have a major complaint with the implementation--in a word "data."
See, here is how CSS variables are supposed to work according to the draft.
I create a property in the root named "data-header-color."
Then to refer to that color elsewhere, I use a construct that looks like a function named "data()" to retrieve it as so:
As far as I can tell, the only explanation in the draft for why this is, is that it is trying to match the HTML specification for "data":
The naming here is loosely based on the form of custom data attributes in HTML5. However, as defined here, the syntax for variable usage is different from the syntax for variable definition (i.e. data-foo for definition, data(foo) for usage). Some have suggested that the syntaxes should should match, using functional syntax in both cases. Others have suggested using a prefixed symbol instead of functional syntax (e.g. $foo) for both the property and usage.
Well at least they are aware that some might object to this format. So let me add my voice. I object. Variables are a pretty standard construct, people know how they work. Make them work like variables in other languages. I have a bunch of reasons here:
Two different syntaxes for creation and consumption seems confusing
It looks like you're calling a function, but you're not. You're referring to a variable. That's confusing.
CSS and HTML don't have a lot of overlap in syntax, why is adding some a good thing?
My preference here is that I can just use plain old words as a variable, then consume them as plain old words. That being said I would be okay with a prefixed symbol, like a $ if it comes down to some sort of parsing issue.
That's my major problem with the draft, but I have one other issue with the behavior on invalid variables. Like if you set the margin to #FFFFFF. Basically if you have this code:
Then the p comes out as red, but if you have this code:
The p comes out transparent.
This sort of change in behavior might be pretty confusing. The explanation makes some sense:
The invalid at computed-value time concept exists because variables can't "fail early" like other syntax errors can, so by the time the user agent realizes a property value is invalid, it's already thrown away the other cascaded values. I think "attr()" needs to rely on it as well, as its behavior is almost identical to variables.
But I imagine this is something that browser manufacturers can handle as they control the behavior of "throw[ing] away the other cascaded values." They could hold on to cascaded values until they are done computing variables. But maybe I'm missing something here. But it's also worth considering if this will make invalid CSS easier to track down. I doubt it, but until a browser implements these, it will be hard to determine if that is true.
Anyway. The good news here is that this is the editor's draft, not the recommendation. This means that now is the time to start analyzing this spec and commenting on it. So what do you think?
Being a content site, it was pretty important that whichElement.com have search--which was pretty hard considering that I didn't want to have any server-side components involved.
At first I thought I would just let Google index the site, and hook up a Google search box on the site to solve the problem. That was certainly an option. I thought I would have to do some SEO magic to make it happen correctly, but it was doable. In fact, Ray had solved this problem already.
But then I got to thinking, wouldn't be cooler to rise to the challenge of a search without a server? Why, yes, yes it would. I broke up my needs into two parts:
An index of the site's content
A mechanism for searching the index and displaying the results.
I kicked around a few ideas, but finally settled on the idea of creating a JSON file that had an array of objects with title, url, summary, and condensed content info. If I had such a file, all I would have to do is search through the JSON to find results. So the second part of my search was a snap. All I had to do was:
Pull down the JSON file
Run searches against that JSON file
Present the results
All of this was pretty easy to do, and not revolutionary.
The difficult part was making the index in the first place. The added difficulty is that I wanted to use JavaScript for everything. So I couldn't just use a shell script or some other easy way of indexing the files. Basically I wanted to remove barriers to entry, so an OS X shell script would create an obstacle for Windows based HTML developers to get involved.
Trying to do this with JavaScript in a browser was very hard. While there is a File API for the browser, you can't use it to point at arbitrary directories on the file system like the site itself, you can only really point it at a sandboxed space. This made indexing kinda impossible.
I said I had to use JavaScript; but I didn't say I had to use a browser. Enter Rhino the Java interpreter for JavaScript. Rhino gave me the ability to call Java File IO classes from JavaScript. This allowed for easy indexing of the content. Now this might be a bit of a cheat since I am basically calling Java, which is a decidedly server-side technology in this case. I rationalized my way out of it. ANT is required to build the project, but knowing how to fire off an ANT build and being forced to right full Java are two different things. I'd love to hear if any of you are put off by this.
Rhino gave me the ability to run JavaScript from the command line, or from ANT. Since we publish whatever gets checked in to the github repository, and we publish that code through ANT, I could just reindex as part of the build whenever new content comes in. New content causes a reindex, the index is always up to date, and generated on my terms - only JavaScript.
What it actually does:
Reads in all HTML files in the site
Filters ones that I don't want in search results.
Grabs the title, url, and content from each
Writes out this content to JSON on disk
It's not perfect. Search is pretty primitive - I don't know how far it will scale. But for now, I have a pretty cool solution to my problem.