REVIEW: Xamarin for Cross Platform Mobile Development

Xamarin-Logo

Software developers have been looking for “Write once – run everywhere” technology for a long time, but we never really NEEDED it before.

In practice we’ve been able to write software based on where we expected it to be used (meaning what platform). For any server side application, we could live with the operating system best supported the development technology we selected.

Targeting desktop apps for Windows, Mac or Linux was platform specific because, for the most part, our target audiences didn’t span platforms. Business users ran Windows, creative types used a Mac, geeks ran Linux.

But “Mobile” has ruined all that.

Well, not really. The trend that has changed everything is really more subtle.

The nature of computer use has migrated from task oriented business functions to lifestyle integration. More importantly what that means is that WHO uses computing devices has changed.

The audience, which was once the functional processional, has expanded (in the way a goldfish is swallowed by a whale) to include the “consumer”.

For many, many companies that are building applications, this change represents an inversion of the market relative to the success of their software product(s).

Conventionally, one leveraged some subject matter expertise and created a product with some anticipation of how much of the potential audience might be enticed to purchasing that product.

There are some software products that will still succeed using this model. Single Player Games are the obvious example. Build a great game and sell it for a couple of dollars to as many people as possible.

Of course, even that model is declining. The emerging revenue model for games (and many other types of apps) is to offer a free version that uses some advertising or in-app sales mechanism to generate revenue. The success of this model depends on the broadest possible adoption of the application.

This is similar to the application use case that most non software companies have for their apps. It’s not about selling licenses, it’s about getting the largest possible segment of their users to engage with their app.

Think, for example, of an airline that creates an app. The app is always free. The purpose of the app is to increase customer use of their services (and therefore increase revenue) and increase customer satisfaction by allowing users to troubleshoot their own travel experience (and thereby decrease customer service costs by letting the customers solve their own problems without talking to a customer service representative.)

Since, unlike the PC market, the mobile market (phone and tablet) has no clear leader in market share. If you want to reach most of your customers on their devices you MUST reach them on both Apple and Android devices.

And, for an organization like an airline, retail operation, health care provider, etc who has a large percentage of business customers, you probably need to cater to Windows Mobile users too (yes, even at it’s current state of adoption.)

As an alternative to building the same app three times (Android, iOS, Windows Phone) there have been efforts like PhoneGap and HTML5 variants to let us write the app once and distribute to multiple targets, but they haven’t really worked very well.

First, they reduce you application to the lowest common denominator (that functionality which is common to all devices). In practice this means inevitably writing lots of code that says “if Android” do this, “if Apple” do that.

For non-trivial apps this gets ugly fast. We just can’t avoid the fact that the three different mobile platforms we need to support have real differences.

So, there is this guy Miguel de Icaza.

Miguel is not just super smart, he’s super clever.

First, he was the primary author of the GNU Midnight Commander, a text-mode file manager for Linux similar to Norton Commander, without which I may have given up on becoming a Linux user. He went on to start the GNOME project (if you’ve never heard of GNOME why are you reading my blog ?:), and became an early contributor to WINE (for running Windows binaries on Linux).

I use those three every day :)

If you’re a .NET developer you probably know that Miguel was also the founder of the Mono project to bring .NET to Open Source. (Yes, I opposed Mono while I was at Microsoft – and yes I hope Miguel has forgiven me. )

In 2011 Miguel co-founded Xamarin to solve exactly the problem I described above.

DISCLAIMER: I haven’t talked to Miguel since before he started Xamarin so my enthusiasm is entirely independent.

Xamarin has done several things that I consider very clever and, especially with the release of version 3, has a very interesting offering to solve the multi-platform mobile development problem.

First = C#. One language, all three platforms (more really, if you include Windows, Mac & Linux implementations). Even if C# is not your favorite language, yo have to concede that “C” based syntax has become relatively ubiquitous, is a public standard, and is supported and evolved by a stable corporate entity. And, Xamarin just added support for the F# languag as well.

Visual Studio Support.

You can use Xamarin Studio (a fine IDE in it’s own right) on Mac or Windows. Or you can use Xamarin Extensions for Visual Studio, which is generally considered to be the bast IDE available on any platform.

Of course, in Xamarin IDE and in Visual Studio, Xamarin gives you a user interface builder.

XBuilder

But then I think it really starts to get interesting.

Xamarin is not trying to solve the UN-SOLVABLE problem of trying to provide tooling that developer will use to build an application once and deliver a great application on all three platforms.

What they are doing instead is (as I see it) identifying which artifacts in our apps can be defined commonly and abstracting as many of those as possible into a single model while accepting that fact that some artifacts will always remain unique to the target platform and providing facilities to make it as easy as possible to work with those platform specifics.

Take, for example, SHARED PROJECTS.

Microsoft announced support for shared projects in Visual Studio 2013 Update 2 and Xamarin subsequently added support in Xamarin Studio. 

XSharedProjects

If you click on the above image and view the full size version you will see a graphical representation of the shared model.

Common or “SHARED” code and project specific sections for Android, iOS and Windows front ends.

What you can’t see in the image is that the IDE “just gets it” so we don’t have to play all kinds of directory games to keep shared inclusions working.

New in version 3 of Xamarin includes Xamarin.Forms.

Xamarin_Forms

 

Xamarin.Forms is cool enough on it’s own but what I find really interesting is this slide from a recent Xamarin webcast on Xamarin 3 which highlights Xamarin.Forms but, for me, serves as a graphical representation of Xamarin’s excellent strategy of moving as much developer functionality as possible into functionality that can be shared across all run-time targets WITHOUT requiring the developer to reduce the experiential quality of his or her app to the “lowest common denominator”.

You can watch the webinar mentioned above [ HERE]

And you can get the slides from the Webinar [ HERE ]

There are a couple of items the detractors point to when discussing Xamarin and I’ll take a moment to address those concerns before I conclude.

The first objection you might hear is cost. “It costs two thousand dollars per seat!!!’

This isn’t actually true. The starter version for individuals is FREE and comes with everything you need to use Xamarin Studio to develop small apps and deploy them to the various marketplaces. (But without Xamarin.Forms)

To step up to the version that can create apps of unlimited size it’s $299 per year (…. and you get Xamarin.Forms)

If you want to use Visual Studio, do in house / enterprise deployment, or use System.Data.SqlClient or Windows communication Foundation (WCF) in your app the price bumps to $999.

Only if you want “Enterprise” level support (like a one day SLA), is the price $1899.

While I am an open source fan (or fanatic) I firmly believe that some forms of software can really only be successful as commercial products.

At $299, or even $999 for Visual Studio and Advanced .NET feature support – the price is only a minor consideration for commercial development (yes, I know, X-Code and Android Studio are free and individual developers don’t like to pay for anything.)

I read a survey recently that suggested the AVERAGE cost for a company to employ a developer for one hour is $100 (which seems conservative to me.)

Therefore, to recover the cost of the Business Edition of Xamarin ($999) it only needs to save me 10 hours of labor. It seems impossible to me that ANY non-trivial application effort wouldn’t easily recover that cost. (Especially since Java & Objective-C have never been primary languages for me.)

There other objection I sometimes hear about is that Xamarin apps are “bigger” so they load slower and take longer to download.

To that I say, so what?

If there is a size difference, it’s usually no more than a couple of megabytes (referring to version 2 examples).

My iPad has a 64bit processor and 128 gig of storage. I just purchased an Android tablet for $299 and it has a quad core processor. (It came with 16 gig of RAM to which I added a 64Gig Micro-SD card).

Significant apps get downloaded once (who really cares how long it takes) and update periodically.

Those minor differences in download and start-up times (if they exist in a noticeable fashion at all) are immaterial as they pertain to real commercial applications.

I don’t think Xamarin expects to displace the use of X-Code or eclipse (etc) for EVERY developer, but if you’re building non-trivial apps and need to get to your customers on whatever devices they choose to own and use, Xamarin is really worth a look. (Especially if you haven’t looked yet at version #3).

I’ll keep you updated on my continuing evaluation.

MITRE – An amazing new professional adventure!

1214_best-work-mitre-logo_485x340

I’m thrilled to share that I’ve accepted a position as “Computer Science Principal” at MITRE Corporation.

MITRE is a federally funded non-profit organization that performs technology centric research and development for the United States Government. Technically, MITRE operates multiple Federally Funded Research and Development Centers (FFRDC).

From the mission statement, “As a public-interest company, MITRE’s mission is to work in partnership with the government applying systems engineering and advanced technology to address issues of critical national importance.”

I’ll working on the design of Mission Planning Systems for the foreseeable future.

And yes, I’ll continue to blog ! (Hopefully even more !)

The specifics of my work will be classified, but my use of software development technologies and practices won’t b, so I’ll continue to blog about them.

MITRE is an amazing center of software development technology and MITRE has encouraged me to continue blogging. This can say / can’t talk about filtering won’t be anything new for me. Blogging has always required the sorting of what was public information and what was NDA.

What technology stack will I be using ?

If you’ve been reading my blog for a while you probably know that as a developer, I’m not religiously bound to any specific language, platform, or philosophy. If you browse the open positions at MITRE you’ll find .NET, Java, Python, Ruby RoR, iOS, NodeJS, C/C++, PHP, Android, MatLab, NoSQL, Hadoop and a lot of other technologies. MITRE uses whatever is the right stack for the task at hand.

Part of my job will include working with the MITRE Advanced Technology group to determine the right tools for a given application, but I’m expecting, at least for the foreseeable future to be deep in C#/.NET, iOS, and C/C++

Where ?

So, after over 15 years of living in New England, working from a home based office and traveling to the west coast to my employer – I’ll be joining the Greater Boston area commute.

MITRE has a flexible work environment but my role will really require a lot of face time with my team at MITRE and stakeholders from the US Government, so I’ll be spending a couple of hours in the car most days.

To ease the pain of the commute (and cut a few hundred dollars a week from my gas bill) I bought a new car with a good media system, BlueTooth & XM radio. I also reactivated my subscription at Audible.com – so I’m open to audio book recommendations !! (Or anything else to ease the commute !)

So ?

Being out of work is painful (at least for me). Being in the job market when you’re over 50 is a challenge and the more senior you are in your career the fewer potential positions there are in the job pool.

With the exception of two young software developers recruited straight form college , everyone I met with at MITRE had been there a long time. The shortest tenure was almost 10 years, the longer ones almost 35 years. So, it must be a great place to work, perhaps somewhere I could spend a couple of decades.

Just as a side note : the interview was epic !

Rick Spiewak, who I met at Microsoft events when I was at Microsoft, contacted me on Twitter after see a post about my leaving Zend Technology. Rick is a Lead Software Engineer at MITRE on the Mission Planning effort and an authoritative voice inside MITRE on .NET technologies. Rick suggested I consider joining MITRE (THANKS RICK, dinner is on me when I see you !)

Huge Kudos to Joe Hurley in Talent Acquisition at MITRE who was on the ball, easy to work with, moved the process quickly and communicated effectively from first contact through the offer. (It’s SO MUCH rarer than you might think.)

After a couple of phone screenings I was scheduled to visit MITRE to interview.

My interview lasted NINE HOURS and included delivering a technical presentation on a topic of my choice (I presented on a massively scalable use-case in NodeJS)!

A nine hour interview might sound like a drag but it was really a blast – it’s awesome to “talk tech” with a room full of really bright people.

One of the things I loved about working at Microsoft was getting to work with the really smart people in the Developer Division. MITRE will offer me the same kind of intellectually challenging people.

Needless to say – I’m VERY excited :)

A guide to the technical job search for the “over 50“ professional.

Man with help wanted sign.

I left my software related position on Feb 21st of this year due to my company’s strategic realignment (which I enthusiastically support).

The last time I was in the “job market”, I was in my early 30s. I’m now 52 years old and this job search has been a very different experience than any other during my career.

After three months of actively searching for a great fit (two and a half months longer than any other job search I’ve engaged in) I thought that this was a good time to share the experience. (Yes I expect to have a job announcement to make soon.)

First, lets address the elephant in the room for we “seasoned” professionals.

There ABSOLUTELY IS age discrimination in the software industry, especially since I was looking for technical (as opposed to management) positions.

Code phrases for age concerns include :

  1. You’re over qualified
  2. We don’t feel it’s a good fit
  3. We don’t think we can challenge you based on your experience
  4. You’ll be a perfect match for us in a year.

Of course, these things could be true, but I’ve never heard them before in my career.

I interviewed with several interesting small companies with interesting senior management (and I had great meetings with them) but when it came time to meet the teams I would be working with, I discovered I was much older than the rest of the team.

Some of the teams were very honest.

  1. We don’t want someone with lots more experience coming in and telling us what to do.
  2. We don’t use agile or unit testing or any of that stuff and we don’t want someone who will encourage management to change the way we work.
  3. After Microsoft Mozilla & Zend you’ll get bored here and leave in 6 months.
  4. We’re like a family, we hang out together after work.  (Implying that an old guy won’t fit into the social scene.)

My experience in developer community didn’t help.

I interviewed with some big companies like Microsoft who clearly wanted a young guy or gal to focus on young app developers (and college aged developer).

Red Hat told me relative to a position building developer community programs that I “had been too evangelism focused”. (Which apparently is different than developer community engagement.)

Twilio told me I wasn’t technical enough for developer evangelism :) (Mmmmm ….)

So, what did I learn that can help YOU streamline the process if you find yourself looking for a new software development related gig after you’ve turned 50 ?

Recruiters are useless.

Well, there are great recruiters out there and like a great bartender, chiropractor, mechanic, etc. the really good ones are worth their weight in gold – the problem is that for every great one there are hundreds of useless ones.

Many years ago I worked with Robert Half and had great experiences as a job seeker and as an employer. In this go-around I found 2 of the 3 recruiters I interacted with at Robert Half to be completely useless. Terse unprofessional communication, illiterate email exchanges, etc.

CyberCoders was even worse. Though I did talk to one or two CyberCoders reps who seemed OK, most were terrible. I even posted on Twitter that I didn’t think CyberCoders even read resumes and they tweeted back “Yes we do”. No inquiry at all. About 2/3 of the voice mail messages I received from CyberCoders reps were entirely unintelligible. I finally got to the point where I just stopped submitting to any job listed by CyberCoders.

Many in house recruiters take weeks to respond to your submission, many do not bother to acknowledge receipt at all.

So, here are my tips for getting past the recruiter to the interview.

1.) Many, many recruiters simply do not know about the skills of the position they are hiring for. They lack the technical foundation to map your work history to the skills and responsibilities of the position that you submit to.

THEY DO KEYWORD MATCHING !

So, create a customized version of your resume for each position you submit to that highlights the job titles, technologies, and responsibilities that match the job description in the posting that you’re responding to. Within the confines of telling the truth, make your resume look as much like the job description (and the hiring company) as possible. Make the match so obvious that even a new recruiter can obviously see that you are a match for the position you are applying for.

2.) Write a specific cover letter for each  submission and target it to the RECRUITER. Specify in your cover letter why you are the right choice for the position. Call out a couple of unique matching points in your resume. Remember, recruiters work on commission, the less work that they have to do to make the match, the better it is for them – and you.

3.) Look at EVERY ad and see if you can determine the actual company that is hiring. If you can, submit directly to them.

4.) In my opinion CyberCoders is the worst! Lots of great listings but they don’t run like a professional placement / recruiting firm – they work like a dating site / matchmaker. CyberCoders forms have skills set ratings & a Q&A section. My suspicion is that if you rate yourself less than advanced in any of the skills sections they probably don’t even look at your resume.

When you have to do that, make the best use you can of the Q&A section to try to convince the recruiter to make a connection for you. I submitted to a dozen positions listed by “Peter” on CyberCoders and emailed him directly to ask for a phone call. Though he looked at my LinkedIn profile, he never even paid me the courtesy of a single reply.

5.) Many local recruiters will want you to come meet with them in person. You’ll go sit with a kid half your age who will ask you “what are you looking for” and “what motives you” and a bunch of other apparently silly questions that you would expect to be obvious from your resume. Yes it will feel like a waste of time, but this is your opportunity to cultivate an advocate in your job search.

Yes, bad recruiters suck and there are tons of them but good recruiters are worth their weight in gold !

Your Resume

1.) 2 Pages MAX !!!!!

I know, we old guys (and gals) have tons of great experience, but find a way to sell yourself with a TWO PAGE resume. Anything after the second page won’t get read anyway and many hiring managers tell me that a resume longer than two pages DECREASES your attractiveness.

2.) Trim your work history. I know this sucks to do. I’m proud of my experience, but 30 years of experience on your resume just highlights your antiquity.

3.) Have MULTIPLE versions that are specifically tailored to the different roles (CTO, Architect), companies or even specific jobs that you are submitting to. Make identifying you as an exact match easy.

4.) Consider using a professional resume writer. They are not that expensive and they can be worth the money !

5.) Use a unique professional design (I’ll post mine shortly). The economy and therefore the job market is bad so every job opening gets lots of resumes submitted, make yours stand out.

 

Use the web – Old School versus New School

1.) Old School – Monster, Indeed, Traditional “Head Hunters” etc. still get lots of listings and you can use a resume submission service to list you and your resume. (I think I paid $30 for a bulk submission.) It’s worth a try. Note, you may want to use a throwaway email address and a burner phone just for your job search because you WILL get junk calls and email if you list your availability publicly.

2.) New School – For software professionals (in my opinion) the two best resources on he web for your career search are LinkedIn.com an careers.stackoverflow.com

3.) LinkedIn, LinkedIn, LinkedIn – make sure your resume and profile are complete. Get a premium membership (for a dozen reasons.) Post on linked in and announce your availability.

Be Prepared

1.) If, like me, it’s been a decade or more since you found yourself in the job market, you may be surprised (as I was) by how much more slowly things move then they did back in the dot com days. Have at least six months financial buffer on hand  so that you don’t have to take something less than you really want just to pay the bills.

2.) Start building the experience for the job you want now.

Here’s what I mean. I REALLY wanted to go to work at Acquia. (The folks that make Drupal) I applied for several technical and management positions at Acquia and went to their headquarters to interview. The place is cool, the products are cool and all the people that I met (including the corporate recruiter) were AWESOME ! But I just didn’t have enough presence in the Drupal community or enough Drupal specific experience to compete successfully against other applicants.

In hindsight, I should have made the time in recent years to submit code to Drupal and increase my visibility on Drupal.org.

The more visible the company that you are applying to – the more competition there will likely be for the position that you want.

Build and Work your Social Network

Your Blog (you should have one) LinkedIn, Twitter, FaceBook, Google+, StackOverflow, etc.

Virtually all of the best / most interesting leads that I’ve had have come from the people in my social network – invest in YOURS !

The Interview.

Since most of my blog readers are professionals I would hope that these tips will all fall into the “obvious” category but I’ve heard LOTS of stories about interview stupidity so I thought them worth including.

1.) If you can’t be on time – don’t bother at all. Get a GPS, Print out directions from Google Maps, Print out directions from the company’s website, print out the email confirmation with contact info for the person you are interviewing with. Consider the traffic you will encounter on the drive and leave AN HOUR early (and wait in the parking lot if you are early.)  Being late for an interview (unless you show up bleeding) nearly guarantees you won’t get the job. It shows that you are unreliable, a poor planner and / or researcher, that you aren’t REALLY interested in the position and that you don’t respect the time of others.

2.) Find out the names and titles of the people you will be interviewing with and them find them on the web. Look for blogs, LinkedIn profiles, press releases etc. Know who you are speaking to.

3.) Research the company and brush up on all the technology and the market segment(s) the job will include. This can help to prove that you are both motivated and interested as well as resourceful.

4.) Overdress !  I don’t care if the company has a casual dress code. Show that you can present yourself as a professional.

5.) Use your spare time to get in shape. Be well groomed. Health & fitness projects motivation, energy and certain approach to life that is attractive to employers.

6.) De-emphasize salary discussions but be prepared to have them. It’s not all about money, but the financial discussion can be difficult to have. As a senior / experienced professional, especially if you are coming from a well known company, there may be an assumption that your salary expectations will be beyond the companies salary range. If you are primarily focused on the salary you will likely find yourself  a bad match anyway. Find a job that you will love with people you really want to work with and then work out the salary issues.

7.) Follow up. Without being pushy, keep yourself in the conversation.

8.) Say “I want this job” out loud.

What’s HOT and what’s not !

What Programming Languages are “hot”.

I’m in the greater Boston area and specifically searching in this geography. Engineering trends tend to have some geo-specific leaning, so take these observations with that in mind.

Here’s my impression of what programming languages are most in demand at the moment in rough order by popularity.

1.) Java (Enterprise/Web)  – yup, this was a surprise to me, but there are lots of Java Dev, Architect and Dev Manager positions and they seem to pay a bit higher than other technologies.

2.) JavaScript – I know, REAL programmers don’t write JavaScript but it’s the NEW thing. There are lots of openings for experienced JavaScript professionals, both front end (AngularJS, Ember, jQuery, ExtJS) and server side NodeJS.

3.) Objective-C and Java for Android – but you knew that !

3.) Python and Ruby On Rails. Python is a bit more popular, but not by a really large amount. Of additional interest is that the Python & RoR ecosystems seem to be the most in tune with distributed teams so if you are interested in working from home, I’d invest in becoming an expert in one of these.

4.) C# – Note to .NET developers. It appears that the Microsoft Windows Language wars are over. I have not seen a single position doing new development with VB, though I did see a few positions migrating VB6 and VB.NET to C#. There are still more Web Forms jobs than MVC jobs. WPF is hot and SilverLight (and WinForms) is not.

5.) PHP – A good number of positions but mostly “ham & egg” development and lower salary ranges. (Which made me sad since I really like PHP.) For PHP Developers Laravel & Zend Framework are most popular.

6.) C/C++ for Linux internals and embedded are fairly popular.

7.) COBOL – Yep, there are still COBOL jobs available.

And what about certifications you ask ?

Language certifications seem to be only of nominal value to potential employers but there are some certifications that make a real difference.

1.) Anything SCRUM. Scrum is very popular and many organizations have moved or are moving to SCRUM. SCRUM certification seems very much in demand.

2.) PMP – Project management certification seems pretty in demand as well.

Being out of work, even when it happens for all the right reasons, is difficult. I’ve been picking up bits of consulting work but I’m very much a mission oriented guy and being part of a team is central to my makeup. It’s a bit like holding your breath while waiting for to find the RIGHT THING !

Stay Calm and Carry On – It’s nothing personal. 

Even when your sure your age was a determining factor that kept you from getting an offer, don’t let it get to you. A number of the organizations that told me “I wasn’t a fit”, even tough I felt like a TECHNICAL match, forced me to agree, if THEY had an issue with the age difference between me and the rest of their team – I probably WOULD be unhappy with their culture.

Hopefully some of the tips above will help other folks – especially the more senior professionals in my readership.

At 52 I don’t feel AT ALL like I’m in the late stages of my career, quite the opposite.  I have young children at home so I’m planning on at least an other 20 years building great software solutions.

I’d love to spend them all 20 at my next employer, but you never know what the future will bring.  Building your parachute now will help you land softly if you even find yourself back in the job market – especially if your “over 50“.

My dev stack is better than your dev stack !

JerseyDev

I’m preparing a presentation for a large consulting firm on architectural options for a massively scalable, bi-directional real time application.

I’ll post about the technology and the architectural choices in the near future but I’ve been chuckling at most of the content that I’ve been reviewing and though I’d spill a few thoughts about it.

Specifically I’ve been looking at “alternative” choices that might be uniquely ideal for this particular use case.

As a basis for understanding the challenge…. Up to half a billion users (yes, billion with a B) sending an update to the server once every 3 minutes and retrieving a stat structure every one or two minutes.

About six months ago I started mapping this use case scenario to Node.JS and NoSQL (Redit or MongoDB).

There are  a few pretty big / high profile on-line properties already using Node.JS in production.

But, mining through articles and on line conversations has reminded me to the religious zeal with which many developers defend their choice of developer stack.

Node.JS is not SINGULARLY unique in it’s non-blocking architecture but it is somewhat unique in that it it’s FUNDAMENTAL PREMISE is non blocking, that it’s syntax is JavaScript (the Google V8 engine) and that it is INNATELY web (not requiring a separate http server.

What’s I’ve been chuckling at is how threatened certain camps of mainstream developers seem so threatened by the emergence of any new technology in their space.

In response to article on Node.JS .NET developers jump in to try to convince you that you can do the same thing in .NET using Async, Threads and customizing the IIS pipeline (just follow these 40 steps.)

Java developers start talking about NIO as though it’s the same thing as Node.JS.

PHP devs point you at ReactPHP

Python developers start talking about Async I/O and threads, etc, etc, etc.

But what’s wrong with just accepting that there is a new technology that’s very good at a specific category of use-case?

Ok, I’ll admit I never loved programming in Java, but I spent a decade at Microsoft digging C#. I also did PHP there and ended up Zend (“The PHP Company”). I spent a year and a half at Mozilla with is mostly a Python shop and I still like all three.

But I don’t need any of those to be the right answer for every software development challenge.

Too often I see dialog from a .NET developer who needs every solution to be only .NET  or from a Java developer who needs every answer to be Java.

For the last 13 years I’ve worked for organizations that manufacture a specific set of developer technologies. I frequently donned my “application/solutions architect” hat to help companies answer the question “what is the right approach for solving THIS business problem”. Even when I was working for a company who’s success was based on a technically bias answer to those sorts of questions, sometimes I answered in the alternative. (How fun it was to explain to my Microsoft management that I recommended PHP for a project :) )

It’s my personal opinion that many folks close their minds to this “best mapped use case” approach because technology grows and evolves so rapidly many of us just give up on the idea of staying on the “front edge”  of  of the software development industry. In some ways we’ve gone from looking for that silver bullet to trying to convince folks that the stuff we are already good at IS THE SILVER BULLET.

All of this I suppose by way of encouraging you to open your mind and spend a little time looking at how emerging technologies might provide better solutions to some of the problems you solve in your day job.

I’ll post the technical blueprint for the above referenced architecture using Node.JS and NoSQL in the near future.

Fight Score Single Page UI App

I asked a question on Twitter last week about jQuery and async calls (thanks @jeefy & @codepo8) – a few folks asked me to post the code I was working on so here it goes.

The app is an HTML page for scoring boxing and MMA fights.

You can play with the UI here : http://koscience.com/apps/scorecard/

This is a mile stone of code samples I’ve posted recently on Dynamic jQuery Accordions and Event Handler Delegation for Dynamic Content.

scorecard-1

The events represented in the application’s UI are data driven by the retrieved JSON file (sample data below)


data.json


[code lang="javascript" htmlscript="true"]
[
{
"bluefighter" : "Fighter 1",
"blueimage" : "images/silhouette.jpg",
"redfighter" : "Fighter 2",
"redimage" : "images/silhouette.jpg",
"numberofrounds" : "10"
},
{
"bluefighter" : "Fighter 3",
"blueimage" : "images/silhouette.jpg",
"redfighter" : "Fighter 4",
"redimage" : "images/silhouette.jpg",
"numberofrounds" : "3"
},
{
"bluefighter" : "Fighter 5",
"blueimage" : "images/silhouette.jpg",
"redfighter" : "Fighter 6",
"redimage" : "images/silhouette.jpg",
"numberofrounds" : "5"
},
{
"bluefighter" : "Fighter 7",
"blueimage" : "images/silhouette.jpg",
"redfighter" : "Fighter 8",
"redimage" : "images/silhouette.jpg",
"numberofrounds" : "12"
}
]
[/code]


You’ll note that the number of bouts in the event are not determined until run time.

Also, for each bout, the number of rounds is not fixed. Each is determined by an entry in the JSON data.

Since each bout will have a VARIABLE number of inputs and outputs, if you think about the mechanics of accomplishing this, it’s an interesting HTML issue.

There are lots of other, perhaps more elegant ways I might have done this (whenever I post code someone comments to tell me I suck :) )

I didn’t use MVC, Event Delegation, or an Object Oriented Data Model. Each of those that I considered just didn’t seem to offer the value in return for the added abstraction or complexity.

(I used to do some work for the SIG Sauer Firearms Academy where we used the acronym SIG = Simple Is Good !)

So I took the simple route. The loop that iterates through the JSON data dynamically adds each content section and since I’m not using event delegation, each “bout” (accordion tab) gets it’s own version of the event handling code to score the bout.

Since the number of bouts is relatively small (less than 15) the performance hit won’t ever be an issue, but if we were dealing with a large number of sections we would need to use delegation of some sort to attach a single event handler at the containing element or document level to avoid unnecessarily duplicating code by hooking the click event for every object / button.


index.html


[code lang="javascript" htmlscript="true"]
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Fight Card</title>
<link rel="stylesheet"
href="http://code.jquery.com/ui/1.10.4/themes/smoothness/jquery-ui.css">
<script src="http://code.jquery.com/jquery-1.9.1.js"></script>
<script src="http://code.jquery.com/ui/1.10.4/jquery-ui.js"></script>
<link rel="stylesheet" href="css/style.css">
<style>
/* IE has layout problems when sorting accordion items */
.group { zoom: 1 }
</style>

<script>

//-----------------------------------------------------------------------+
// addBout() - Add a single node to the accordion
//-----------------------------------------------------------------------+

function addBout(bout, key){

//-----------------------------------------------------------------------+
// Build the display element for the the scoring display based on the
// number of rounds for this bout.
//-----------------------------------------------------------------------+
var round_numbers = "";
var round_scores = "";
var round_totals = "";
for (var i=0; i < bout.numberofrounds; i++)
{
round_numbers += "<td id='roundTitle_" + (key+1) + "_" + (i+1)
+ "'>Round #" + (i+1) + "</td>";
round_scores += "<td id='bout_" + (key+1) + "_round_" + (i+1)
+ "_roundbox'><span id='bout_" + (key+1) + "_round_"
+ (i+1) + "_blueScore'>00</span>-<span id='bout_"
+ (key+1) + "_round_" + (i+1)
+ "_redScore'>00</span></td>";

round_totals += "<td id='bout_" + (key+1) + "_round_" + (i+1)
+ "_totalbox'><span id='bout_" + (key+1) + "_round_"
+ (i+1) + "_blueTotal'>00</span>-<span id='bout_"
+ (key+1) + "_round_" + (i+1)
+ "_redTotal'>00</span></td>";
}

//-----------------------------------------------------------------------+
// Build the display element for the rest of the current bout.
//-----------------------------------------------------------------------+
var bout =
"<div id=\"bout_" + (key+1) + "\" class=\"group\">" +
"<span class=\"handle\"> " +
"<div class=\"table\">" +
"<div class=\"row\">" +
"<span class=\"cell width33pct align-left\">" +
"<strong>" + bout.bluefighter + "</strong>" +
"</span>" +
"<span class=\"cell align-center valign-middle\">" +
"vs." +
"</span>" +
"<span class=\"cell width33pct align-right\">" +
"<strong>" + bout.redfighter + "</strong>" +
"</span>" +
"</div>" +
"</div>" +
"</span>" +
"<div>" +
"<div class=\"table\">" +
"<div class=\"row\">" +
"<span class=\"cell width150 align-center\">" +
"<img src=\"" + bout.blueimage
+ "\" alt=\"\" style='border:2px solid blue'>"
+ "<br />" +
"</span>" +
"<span id=\"test\" " +
"class=\"cell align-center valign-middle\">" +
"<h2>" +
"<span id='roundLabel_" + (key+1) +
"'>Round</span><br />" +
"<span id=\"current_round_" + (key+1) +
"\">1</span><br />" +
"<input type='number' id='blueRoundScore_" +
(key+1) + "' size='2' max='10' min='0' " +
"value='10' " +
"style='border:2px solid blue'>" +
"<input type='number' id='redRoundScore_" +
(key+1) + "' size='2' max='10' min='0' " +
"value='10' style='border:2px solid red'>" +
"<br /><br />" +
"<button id='btnScore_" + (key+1) +
"' class='score_button'>Score</button>" +
"<span id='boutResult_" + (key+1)+ "' " +
"class='boutResultClass'></span>" +
"</h2>" +
"</span>" +
"<span class=\"cell width150 align-center\">" +
"<img src=\"" + bout.redimage + "\" alt=\"\" " +
"style='border:2px solid red'>" +
"</span>" +
"</div>" +
"</div>" +
"<div align=\"center\">" +
"<table>" +
"<tr>" +
round_numbers +
"</tr>" +
"<tr>" +
round_scores +
"</tr>" +
"<tr>" +
round_totals +
"</tr>" +
"</table>" +
"</div>" +
"</div>" +
"</div>";
return bout;
}

//--------------------------------------------------------------------------+
// DOM READY()
//--------------------------------------------------------------------------+
$(function() {
//----------------------------------------------------------------------+
// Wire up the accordion div, specify the header/handle and make
// the sections sortable.
//----------------------------------------------------------------------+
$( "#accordion" )
.accordion({
header: "> .group > .handle",
heightStyle: "content"
})
.sortable({
axis: "y",
handle: ".handle",
stop: function( event, ui ) {
// IE doesn't register the blur event when sorting
// so trigger focusout handler to remove .ui-state-focus
ui.item.children(".handle").triggerHandler("focusout");
}
});

//----------------------------------------------------------------------+
// Fetch the JSON configuration file and use it to build the
// accordion sections
//----------------------------------------------------------------------+
$.getJSON("data/event.json", function (data) {
$.each(data, function (key, val) {
$("#accordion").append(addBout(val, key)).accordion("refresh");

//--------------------------------------------------------------+
// For each bout - dynamically bind the score button event
// handler to this dynamic method
//--------------------------------------------------------------+
var BlueTotal = 0;
var RedTotal = 0;
var BoutNumber = (key+1);
$( "#boutResult_"+(BoutNumber) ).hide();
$( "#btnScore_"+(BoutNumber) ).click(function() {
// Get the current round number.
var currentRound = 0;
currentRound = $("#current_round_" + (BoutNumber)).text();

//----------------------------------------------------------+
// Fetch the score for the current round and post to
// scoring table
//----------------------------------------------------------+
var BlueScoreThisRound = $("#blueRoundScore_" +
BoutNumber).val();
var RedScoreThisRound = $("#redRoundScore_" +
BoutNumber).val();
$("#bout_" + (BoutNumber) + "_round_" + currentRound +
"_blueScore").text(BlueScoreThisRound);
$("#bout_" + (BoutNumber) + "_round_" + currentRound +
"_redScore").text(RedScoreThisRound);
// If it's the FIRST round.
if (currentRound == 1) {
$("#bout_" + (BoutNumber) + "_round_" + currentRound +
"_blueTotal").text(BlueScoreThisRound);
$("#bout_" + (BoutNumber) + "_round_" + currentRound +
"_redTotal").text(RedScoreThisRound);
BlueTotal = BlueScoreThisRound;
RedTotal = RedScoreThisRound;
}
// All except the first round.
else {

BlueTotal = parseInt($("#bout_" + (BoutNumber) +
"_round_" + (currentRound-1) +
"_blueTotal").text());
BlueTotal += parseInt(BlueScoreThisRound);
$("#bout_" + (BoutNumber) +
"_round_" + (currentRound) +
"_blueTotal").text(BlueTotal);

RedTotal = parseInt($("#bout_" + (BoutNumber) +
"_round_" + (currentRound-1) +
"_redTotal").text());
RedTotal += parseInt(RedScoreThisRound);
$("#bout_" + (BoutNumber) + "_round_" +
(currentRound) + "_redTotal").text(RedTotal);
}

// Blue wins the round.
if (BlueScoreThisRound < RedScoreThisRound) {
$("#bout_" + (BoutNumber) + "_round_" + currentRound +
"_roundbox").css("border", "2px solid blue");
}
// Red wins the round.
else if (BlueScoreThisRound > RedScoreThisRound) {
$("#bout_" + (BoutNumber) + "_round_" + currentRound +
"_roundbox").css("border", "2px solid red");
}
// Round is a draw
else if (BlueScoreThisRound == RedScoreThisRound) {
$("#bout_" + (BoutNumber) + "_round_" + currentRound +
"_roundbox").css("border", "2px solid green");
}

// Who's winning the fight after this round ?
if(RedTotal == BlueTotal) {
$("#roundTitle_" + (BoutNumber) + "_" +
currentRound).css("border", "2px solid green");
$("#bout_" + (BoutNumber) + "_round_" +
currentRound +
"_totalbox").css("border", "2px solid green");
}
if(BlueTotal < RedTotal) {
$("#roundTitle_" + (BoutNumber) + "_" +
currentRound).css("border", "2px solid red");
$("#bout_" + (BoutNumber) + "_round_" +
currentRound + "_totalbox").css("border", "2px solid red");
}
if (BlueTotal > RedTotal) {
$("#roundTitle_" + (BoutNumber) + "_" +
currentRound).css("border", "2px solid blue");
$("#bout_" + (BoutNumber) + "_round_" +
currentRound +
"_totalbox").css("border", "2px solid blue");
}

//----------------------------------------------------------+
// Reset current round scores t 10-10, hide button if all
// rounds scored
//----------------------------------------------------------+
$("#blueRoundScore_" + BoutNumber).val(10);
$("#redRoundScore_" + BoutNumber).val(10);
currentRound++;
// The fight is over.
if (currentRound > val.numberofrounds) {
$("#blueRoundScore_" + BoutNumber).val(BlueTotal);
$("#blueRoundScore_" + BoutNumber).prop('disabled', true);
$("#redRoundScore_" + BoutNumber).val(RedTotal);
$("#redRoundScore_" + BoutNumber).prop('disabled', true);
$( "#btnScore_"+(BoutNumber)).hide();
if(BlueTotal == RedTotal) {
$( "#boutResult_"+(BoutNumber) ).text("<<< Draw >>>");
}
else if (BlueTotal > RedTotal) {
$( "#boutResult_"+(BoutNumber) ).html("&larr; WINNER");
$( "#boutResult_"+
(BoutNumber) ).css("background-color", "blue");
$( "#boutResult_"+(BoutNumber) ).css("color", "white");
}
else if (RedTotal > BlueTotal) {
$( "#boutResult_"+(BoutNumber) ).html("WINNER &rarr;");
$( "#boutResult_"+
(BoutNumber) ).css("background-color", "red");
$( "#boutResult_"+(BoutNumber) ).css("color", "white");
}

$( "#roundLabel_"+(BoutNumber) ).text("Fight");
$( "#current_round_"+(BoutNumber) ).text("Complete");
$( "#boutResult_"+(BoutNumber) ).show();

}
// On to another round.
else {
$("#current_round_" + (key+1)).text(currentRound);
}
});
});

});

});

</script>
</head>

<body>
<div id="main-container" class="main-container">
<div id="accordion">
<!-- Bouts will be inserted here -->
</div>

</div>
</body>
</html>

[/code]


style.css


[code lang="css"]
body {
font-family: "Trebuchet MS","Helvetica","Arial","Verdana","sans-serif";
font-size: 62.5%;
background: url('../images/background.gif') repeat;
}

td {
text-align: center;
vertical-align: middle;
border: 1px solid black;
width: 90px;
}

input {
text-align: center;
}

.main-container {
width: 96%;
max-width: 960px;
min-width: 300px;
height: 100px;
position: absolute;
top:20px;
left: 0;
right: 0;
margin: auto;
}

/*---------------------------------------*/
/* Styles for table like formatting. */
/*---------------------------------------*/
.table {
display: table;
width: 100%;
}
.row {
display: table-row;
}
.cell {
display: table-cell;
}

/*---------------------------------------*/
/* Styles for score area. */
/*---------------------------------------*/

.score_box {
border:2px solid black;
padding: 5px;
}

.score_button {
width: 130px;
height: 40px;
}

.boutResultClass {
border: 2px solid black;
background-color: yellow;
padding-left: 20px;
padding-right: 20px;
padding-top: 10px;
padding-bottom: 10px;
}

/*---------------------------------------*/
/* Styles for width specification. */
/*---------------------------------------*/
.width150 {
width: 150px;
}

.width33pct {
width: 33%;
}

.width34pct {
width: 34%;
}

.width100pct {
width: 100%;
}

/*---------------------------------------*/
/* Styles for various alignments. */
/*---------------------------------------*/
.align-right {
text-align: right;
}
.align-left {
text-align: left;
}
.align-center {
text-align: center;
}

.valign-middle {
vertical-align: middle;
}

/*-------------------------------------------*/
/* Style overrides for jQuery accordion. */
/*-------------------------------------------*/
.ui-state-default{
background-color: #3173a5;
background-image: none;
}
.ui-accordion-header {
background-color: #333333;
color: #BDC3C7;
font-size: 16;
}

.ui-accordion-header.ui-state-active {
background-color: #BDC3C7;
color: #333333;
font-size: 16;
}
[/code]


You can download a .zip file without the funky source code formatting that my blog requires [ HERE ]


So what’s next ?

Next I’ll create services so that users can all score an event in real time, collaboratively while the event is happening live.

After I create the services and update the client to send scores, I’ll build iOS, Android & Windows clients !

Thoughts: What is a technical evangelist?

I’m in between jobs after spending 15 years as a developer evangelist.

Last week I lost out on a position for a REST API Developer Evangelist role that I had interviewed for primarily because I lacked in-depth knowledge of a specific PHP API that I had never used.

I’m not going to name the company because I like their product and the well known developer that I interviewed with, but it started me thinking about the role of technical evangelist and how technophiles often confuse the nature of the role and it’s success.

A number of other people with extensive developer evangelism experience have shared with me in the past that they were rejected out of hand for what they believed was a lack of “bit level” experience.

Lets start with understanding what a Technical Evangelist is (and from here on in I’ll be specifically referring to Developer Evangelism). The Technical Evangelist’s role ( for a software vendor as opposed to a consultancy) is to produce two sets of results.

1.) Net New Adoption
2.) Increased Customer Satisfaction & Dependence

Technical Evangelists that represent consulting companies have a bit of a mission. That of presenting the technical expertise of their firm in the hopes of selling its services.

Even technical evangelists that don’t represent a specific company still have the goal of encouraging adoption of the technologies that they evangelise (usually because it’s the one THEY have chosen).

You will often hear Developer Evangelists describe themselves as “Impartial Trusted Advisors”, and becoming “trusted” is a great way for a technical evangelist to increase their influence but in actuality, there is no such thing as a truly “impartial” technical advisor.

So this bears the question, what does it take to be a really successful Technical Evangelist and how does that translate to a really valuable technical evangelism program?

Sure, a technical evangelist need a strong technical acumen. When I joined Microsoft to do Technical Evangelism for .NET it was an unreleased product. I’d played with it for about a week before I started the interview process at Microsoft. When I joined Mozilla to catalyze HTML5 App Evangelism I was far from a client side expert. After all, one of the fundamental tenants of ASP.NET (before MVC and Razor) was that you didn’t do client side work. It was all drag and drop.

So in taking various evangelism roles that focused on technologies in which I was not omnipotent, how did I succeed?

The dictionary includes a definition of an evangelist as : “a zealous advocate of a cause”.

This is true of Technical Advocates as well.

Remember that I suggested the primary goals of a technical evangelist are to deliver “net new” adoption and increased user (customer) satisfaction.

The technical evangelist has secondary goals as well, like product feedback, support costs reduction, customer specific problem solving, direct sales opportunity support, etc. and some of those can be facilitated by low level expertise, but in general – bits and bytes hacking is of secondary value.

I mean, once you have written a for loop, they are pretty much in the same whether you’re writing C#, PHP,JavaScript, Python, etc.

I suggest that you don’t think about Technical Evangelism as “here’s what my product can do”, but rather “look what you can do with my product”. It may sound like a semantic nuance at first blush, but it’s not.

Let me share a couple of examples.

In 2001 when I started working to drive ASP.NET adoption (.NET was in Beta havng been previewd at the 2000 PDC) I focused on Web Services. The big deal about Web Services was not the technical details of building or calling a service in ASP.NET becuase ASP.NET and Visual Studio made the syntax pretty much the same as working with any .NET object.

What resonated most with the (literally) thousands of developers I presented .NET to was not the new / diferent ways they could do things with Microsoft’s shiny new technology, it was how the simplicity of .NET would let them change the KIND of development they could do. How they could build features and applications that were impractical or impossible with earlier tool sets.

In 2008 we (Microsoft) released the ASP.NET AJAX extensions and the initial uptake from developers was “different” than we expected. The reason, I felt, was that while we were showing developers “how” to use the new “APIs”, we weren’t really doing anything to help change their thought process in regards to ASP.NET based problem solving.

After all, ASP.NET developers weren’t used to thinking in terms of how world wide web apps really work, their model at the time was really designed to emulate the “client server” paradigm. The idea that an application could have functionality apart from “full server round trips” was foreign.

So I built a series of 30 or 40 concise videos with sample code that demonstrated “AJAX Patterns”. Patterns like “Predictive Fetch” , “Partial Page Updates”, “Display Paging”, “Incremental Display”, “After Processing” and “Persistent Communications” (http://www.asp.net/web-forms/videos/aspnet-ajax). What mad people excited was not new ways to do old things, it was NEW THINGS that could do in general.

The right content, demonstrations and sample code made people say “I need to move to .NET because I can easily build great apps (or great features into my apps) with that tool set.

While some amount of technical expertise was prerequisite, it wasn’t a deep expertise that made the evangelists on my team successful. To the contrary, I think only a couple of the folks on my team of a dozen or so ever developed really deep expertise. What made them great technical evangelists was their mix of technical aptitude and exceptional communication skills.

As a team we learned to answer the questions prospective customers had, even if they were as yet unasked. We learned to match customers needs with the capabilities that our products could provide and we learned to “shorten” the learning curve by creating content and giving presentations made complex problems and solutions simpler – rather than getting lost in the weeds of technical minuta.

So (IMO) Technical Developer Evangelists are …..

– Engaging speakers and recruiters
– Pre Sales Engineers
– Post Sales Support Engineers
– Solutions Consultants
– Cheerleaders
– Coaches
– Social Directors
– Authors
– Organizers
– Managers (or events or projects)
– Applications Developers

Have you even met great developer evangelist ?

What made him or her great in your eyes ?

PATTERN : Dynamic HTML elements and context specific access via jQuery.

I think all web developers have a love / hate relationship with HTML.

HTML is by it’s very definition a MARKUP language. Markup meaning it’s category of utility is to represent data. HTML is fine for representing data for display but less perfect when it comes to use case’s that require the manipulation of that data once it’s been rendered. As a “markup” language, the semantic values are not innately coupled to the markup items that contain them.

The software development industry continuously invents new ways to improve the ways that we solve this relationship problem.

I’ve been working on a Single Page HTML App which will be data drivel via a JSON file retrieved from the server.

That JSON file will contain some number of data records and the app will need to create one container div for each of those records. Since the number of those records is variable, the App won’t know until run time (when the page is loaded) how many of those sections will be needed.

Each of the container divs will contain HTML elements that will need to be manipulated at run time. (In fact, in the app I’m forking on each container will have a variable number elements, also dynamically created at run-time but for the purposes of this sample we’ll keep thinks to a single level of dynamics).

Dynamically naming elements can quickly become complex with dynamic HTML pages and, as is always there are many ways to solve the same problem. (Yes, I know, your way is better :) )

Here is a documented example of ONE way to accomplish this content / data dynamics using jQuery (though you could use the same pattern in plain old JavaScript).

It takes very little code, but several people have questioned me as to how to do this so I thought I’m post a sample.


[code lang="javascript" htmlscript="true"]
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title></title>
<script
src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js">
</script>

<script>
var numberOfDivsToCreate=10;
//---------------------------------------------------------------------------+
// Note the id of the div to be appended is dynamic comprised of the static
// text "DIV-NUMBER" and the current value of the i variable of the for loop.
//---------------------------------------------------------------------------+
$(document).ready(function () {
//-----------------------------------------------------------------------+
// for loop create the total number of divs specified in the
// numberOfDivsToCreate variable above. In a real app this would probably
// be determined at run time
//-----------------------------------------------------------------------+
for (var i = 1; i <= numberOfDivsToCreate; i++) {
$('#mainpage').append("<div id='DIV-NUMBER-" + i + "'>" +
"<span id='myInput''>" + i + "</span>" +
"&nbsp;--&nbsp;<span id='myVal'></span></div>");
}

//-----------------------------------------------------------------------+
// Use the jQuery.on method to specify an event delegate to handle click
// events for all the divs inside the div who's id="mainpage"
// Note: In this sample we arw catching the click event for ALL divs
// In a real world app your mainpage div may contain divs that you do not
// want to fire a click event on, In that case use a class on the
// clickable ones and change the jQuery selector below accordingly,
//-----------------------------------------------------------------------+
$( "#mainpage" ).on( "click", "div", function() {

//-------------------------------------------------------------------+
// The for loop above creates 10 divs and this click event delegate
// is a SINGLE method (lives in memory once) to handle the click
// events for all 10 divs
// $this is a jQuery reference to the element that threw the click
// event in our case one of the 10 divs
//-------------------------------------------------------------------+
// we'll use .find() to look inside the div that threw the click
// event and find the elements we wish to manipulate, note that
// those elements are not dynamically named (myInput & myVal) so
// there are 10 of each on our page and we are using context to
// determine which to manipulate
//-------------------------------------------------------------------+
// jQuery .find() can be a performance problem if misused, make
// sure to minimise the find scope as much as possible
//-------------------------------------------------------------------+
var MyInput =$(this).find("#myInput");
var MyDisplay = $(this).find("#myVal");

//-------------------------------------------------------------------+
// Note that MyInput & MyDisplay local variables that we cast to
// jQuery objects on order to access the text properties via jQuery
// syntax.
//-------------------------------------------------------------------+
$(MyDisplay).text($(this).attr("id") +
" - Value = " + $(MyInput).text())
});
});
</script>

</head>
<body>
<div id="mainpage">
</div>
</body>
</html>
[/code]


Life is a series of near misses !

“I believe life is a series of near misses. A lot of what we ascribe to luck is not luck at all. It’s seizing the day and accepting responsibility for your future. It’s seeing what other people don’t see and pursuing that vision.” – Howard Schultz, founder of Starbucks

jQuery Accordion and Dynamic Runtime Population

As I mentioned in my last post I’m playing with this idea of building a scoring application for boxing / mma events.

I want it to be a single page web application that scales to fit phones, tablets, etc.

An event contains a number of “bouts” and each bout will be a section in a jQuery UI Accordion control.

However, as is often the case, there are a couple of real world conditions that I couldn’t find documentation of sample to demonstrate.

1.) Event event can have a different number bouts.

This means that the accordion sections have to be dynamically built at runtime in the html page.

2.) The order of the events can change right up to the event time.

This means that the USER needs to be able to change the visual sequence of the bouts.

3.) The click-able header needs to be multiple elements.

All the demos I found assumed the headers were simple H3 elements.

You can play with a working version by clicking the image below.

Note that you can not only open and close the “bouts” but you can re-order them using drag-n-drop on the title bars.

– – – THIS IS A UI PROTOTYPE – – –

FightCard- 001

Built this way I can now add the AJAX logix fo recieve a JSON package that contains the event detail and use that data to populate the event.

Here is the code as it exists so far.

[code lang="javascript" htmlscript="true"]
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Fight Card</title>
<link rel="stylesheet"
href="http://code.jquery.com/ui/1.10.4/themes/smoothness/jquery-ui.css">
<script src="http://code.jquery.com/jquery-1.9.1.js"></script>
<script src="http://code.jquery.com/ui/1.10.4/jquery-ui.js"></script>
<link rel="stylesheet" href="css/style.css">
<style>
/* IE has layout problems when sorting */
.group { zoom: 1 }
</style>

<script>

//-----------------------------------------------------------+
// addBout() - Add a single node to the accordian
// TODO: add JSON object as input parameter and build the
// bout with that data,
//-----------------------------------------------------------+
function addBout(){
var bout =
"<div class=\"group\">" +
"<span class=\"handle\"> " +
"<div class=\"table\">" +
"<div class=\"row\">" +
"<span class=\"cell width33pct align-left\">" +
"<strong>Blue Fighter TBD</strong>" +
"</span>" +
"<span class=\"cell align-center valign-middle\">" +
"vs." +
"</span>" +
"<span class=\"cell width33pct align-right\">" +
"<strong>Red Fighter TBD</strong>"+
"</span>" +
"</div>" +
"</div>" +
"</span>" +
"<div>" +
"<div class=\"table\">" +
"<div class=\"row\">" +
"<span class=\"cell width150 align-center\">" +
"<img src=\"images/silhouette.jpg\" alt=\"\">" +
"</span>" +
"<span class=\"cell align-center valign-middle\">" +
"Round<br />0" +
"</span>" +
"<span class=\"cell width150 align-center\">" +
"<img src=\"images/silhouette.jpg\" alt=\"\">" +
"</span>" +
"</div>" +
"</div>" +
"<span>" +
"Mauris mauris ante, blandit et, ultrices a, suscipit , " +
"quam. Integerut neque. <br /> Vivamus nisi metus molestie" +
" vel, gravida in, condimentum sit amet, nunc. Nam a nibh." +
"accordion .ui- iconDonec suscipit eros. Nam mi. Proin " +
" viverra leo ut odio. Curabitur malesuada. Vestibulum a " +
"velit eu ante scelerisque vulputate." +
"</span>" +
"</div>" +
"</div>";
return bout;
}

$(function() {

$( "#accordion" )
.accordion({
header: "> .group > .handle",
heightStyle: "content"
})
.sortable({
axis: "y",
handle: ".handle",
stop: function( event, ui ) {
// IE doesn't register the blur event when sorting
// so trigger focusout handler to remove .ui-state-focus
ui.item.children(".handle").triggerHandler("focusout");
}
});

//-----------------------------------------------------------+
// This for loop is just for testing.
// The real app will iterate a JSON collection and send
// each bout node to the addBout function for insertion
// into the accordion
//-----------------------------------------------------------+
for (var i=0;i<5;i++) {
$("#accordion").append(addBout()).accordion("refresh");
}
});
</script>

</head>

<body>

<div id="main-container" class="main-container">
<div id="accordion">
<!-- Bouts will be inserted here -->
</div>
</div>

</body>
</html>
[/code]

And the CSS

[code lang="css"]
body {
font-family: "Trebuchet MS","Helvetica","Arial","Verdana","sans-serif";
font-size: 62.5%;
background: url('../images/background.gif') repeat;
}

.main-container {
width: 96%;
max-width: 960px;
min-width: 300px;
height: 100px;
position: absolute;
top:20px;
left: 0;
right: 0;
margin: auto;
}

/*---------------------------------------*/
/* Styles for table like formatting. */
/*---------------------------------------*/
.table {
display: table;
width: 100%;
}
.row {
display: table-row;
}
.cell {
display: table-cell;
}

/*---------------------------------------*/
/* Styles for width specification. */
/*---------------------------------------*/
.width150 {
width: 150px;
}

.width33pct {
width: 33%;
}

.width34pct {
width: 34%;
}

/*---------------------------------------*/
/* Styles for various alignments. */
/*---------------------------------------*/
.align-right {
text-align: right;
}
.align-left {
text-align: left;
}
.align-center {
text-align: center;
}

.valign-middle {
vertical-align: middle;
}

/*-------------------------------------------*/
/* Style overrides for jQuery accordion. */
/*-------------------------------------------*/
.ui-state-default{
background-color: #3173a5;
background-image: none;body {
font-family: "Trebuchet MS","Helvetica","Arial","Verdana","sans-serif";
font-size: 62.5%;
background: url('../images/background.gif') repeat;
}

.main-container {
width: 96%;
max-width: 960px;
min-width: 300px;
height: 100px;
position: absolute;
top:20px;
left: 0;
right: 0;
margin: auto;
}

/*---------------------------------------*/
/* Styles for table like formatting. */
/*---------------------------------------*/
.table {
display: table;
width: 100%;
}
.row {
display: table-row;
}
.cell {
display: table-cell;
}

/*---------------------------------------*/
/* Styles for width specification. */
/*---------------------------------------*/
.width150 {
width: 150px;
}

.width33pct {
width: 33%;
}

.width34pct {
width: 34%;
}

/*---------------------------------------*/
/* Styles for various alignments. */
/*---------------------------------------*/
.align-right {
text-align: right;
}
.align-left {
text-align: left;
}
.align-center {
text-align: center;
}

.valign-middle {
vertical-align: middle;
}

/*-------------------------------------------*/
/* Style overrides for jQuery accordion. */
/*-------------------------------------------*/
.ui-state-default{
background-color: #3173a5;
background-image: none;
}
.ui-accordion-header {
background-color: #333333;
color: #BDC3C7;
font-size: 16;
}

.ui-accordion-header.ui-state-active {
background-color: #BDC3C7;
color: #333333;
font-size: 16;
}

}
.ui-accordion-header {
background-color: #333333;
color: #BDC3C7;
font-size: 16;
}

.ui-accordion-header.ui-state-active {
background-color: #BDC3C7;
color: #333333;
font-size: 16;
}
[/code]

A simple HTML/CSS adaptive container.

So if you’ve been reading me for a while or you follow me on Twitter you probably know I’m a fight fan.

I’ve started building a sports app related to fighting sports and I’m starting with an HTLM5 app that will run adaptively in any size browser.

I didn’t find an example that did what I want.

My desire was to place the functionality inside a DIV that would take up most of the width of the screen, scale with the size of the screen but ONLY up to 960 pixels.

Like this is the browser window is greater that 960px.

adapt-proto-1

And like this when the browser window is less than 960px.

adapt-proto-2

Here’s the code I came up with.

Simple, but meets my needs.

[code htmlscript="true" language="css"]
<html>
<head>
<title></title>
<style type="text/css">
body {
background-color:#b0c4de;
}

div {
width: 96%;
max-width: 960px;
height: 100px;
background-color: white;
position: absolute;
top:20px;

left: 0;
right: 0;
margin: auto;

}
</style>
</head>
<body>
<div>
--- app content ----
</div>
</body>
</html>

[/code]