Thursday, December 26, 2013

bower returns EMALFORMED

It turns out that in bower.json file, there is no // comments. It is true as JSON doesn't allow comments.

Suppose you are using JSON to keep configuration files, which you would like to annotate. Go ahead and insert all the comments you like. Then pipe it through JSMin before handing it to your JSON parser.

or check out

Saturday, December 21, 2013

Christmas Light Tour

Some great light houses I visited this year:

2056 Cirone Wy, San Jose, CA

1135 McBain Ave, Campbell, CA

1785 Patio Dr, San Jose, CA

1851 Cherry Ave, San Jose, CA

Minnesota Ave @37.301680, -121.901360

Camino Ramon @37.307483, -121.909806

Glen Eyrie Ave

2014 I found new list from

1086 Glen Brook Ave
1257 Britton Ave
1140 Newport Ave
Cherry Ave & Pine Ave
1851 Cherry Ave, San Jose, CA

1182 Laurie Ave
1062 Byerley Ave
1240 Madrona Ave

2160 Newport Ave
1638 Mulberry Ln

1900 Campbell Ave - light
1135 McBain Ave - Holiday Train display

2056 Cirone Wy, San Jose, CA
1785 Patio Dr, San Jose, CA

Friday, December 20, 2013

Takeaways from dailyjs survey

  1. Javascript is everywhere (browser, server, native, mobile)
  2. Javascript has pre-compilable languages (Coffeescript, Typescript, ClojureScript)
  3. Javascript needs code conventions 
  4. Javascript needs unit test (QUnit, Jasmine, Karma, Mocha, NodeUnit, tape)
  5. Javascript needs continuous integration (Jenkins, Tarvis CI, Hudson, TeamCity)
  6. Javascript needs static code analysis (JShint, JSLint)
  7. Javascript needs dependency management (AMD/requirejs, CommonJS, Browserify)
  8. Javascript needs build (Grunt, Browserify, NPM scripts)
  9. Javascript has many frameworks (AngularJS, Backbone, Knockout, Ember, Meteor, KendoUI)
  10. Javascript has versions (ES5, ES6) 

Tuesday, December 3, 2013

Remote working tools from

How we collaborate when working remote

  • Google Hangout - for daily standup and face to face conversations.
  • Campfire - for persistent chat throughout the day
  • Screenhero - for screensharing / working on code together
  • Balsamiq - Planning UI to build
  • Asana - Managing tasks
  • Google Docs - Communicating in longer written docs / stats in spreadsheet form
  • Email - Everything else

Monday, December 2, 2013

Javascript memory leak

Here are some links talking about Javascript memory leak.

Saturday, November 16, 2013

May I ask?

Ask interviewers

1.) What's the process like? How do you build software? Do you describe yourself as "lean", "agile", or "scrum"?
2.) How do designers work with developers?
3.) What's the state of automated testing? Continuous integration?
4.) What *exactly* will I be working on? What's the tech stack?
5.) How big are the teams? How big will my team be?
6.) Is there any allowance for remote work?
7.) Are there core business hours?
8.) Why are you hiring? Is this a new product? Scaling? Did someone recently quit?
9.) What's the coolest thing you've built here, personally?
10.) What do you wish you had known about the company before working here? What's the worst part of this job?

Thursday, October 24, 2013

i18n and L10N

i18n and L10N are more difficult than I image. After some research, I understand more why it is hard.

W3C defines i18n and L10N as below.

Internationalization is the design and development of a product, application or document content that enables easy localization for target audiences that vary in culture, region, or language.

Localization refers to the adaptation of a product, application or document content to meet the language, cultural and other requirements of a specific target market (a locale).

wikipedia also has explanation about them and list out their scope. 

Internationalization is the process of designing a software application so that it can be adapted to various languages and regions without engineering changes. 

Localization is the process of adapting internationalized software for a specific region or language by adding locale-specific components and translating text. 

Sometimes g12n (globalization) means the process of i18n + L10N.

During i18n and L10N process, we also need understand Locale, Language, Timezone.

Locale settings control how numbers, dates, and times, Currency, Measurement units display for your region - which may be a country, or a portion of country or may not even honor country boundaries.
The locale settings are about formatting output given a locale.
A locale, on the other hand, is a specific international market where a target user is working. A locale encompasses many of the issues discussed earlier when I defined localization: the conventions, culture, language, and preferences of typical users in the environment. This includes issues that are crucial to applications, such as number, currency, date/time formats, and date/time separators. 

Language, on the other hand, is what we speak, read, and write. Language settings control in what language text appears independently of the locale settings.

Language is a term that just about everybody is familiar with; it is a grouping of sounds and symbols that are organized into combinations and patterns S that enable people to communicate. 

Most of the time zones on land are offset from Coordinated Universal Time (UTC) by a whole number of hours (UTC−12 to UTC+14), but a few are offset by 30 or 45 minutes (for example: Nepal Standard Time, NPT). Some higher latitude countries use daylight saving time for part of the year, typically by changing clocks by an hour.

Friday, October 18, 2013

7 browser client side storage

This blog is very good and useful for reference.

  1. JavaScript Variables (Past, Present and Future)
  2. Cookies (Past, Present and Future)  SSL/HttpOnly
  3. (Past and Present)
  4. HTML5 Web SQL Database (Past)
  5. HTML5 Web Storage (Present and Future) sessionStorage/localStorage
  6. HTML5 IndexedDB (Future)
  7. HTML5 File API (Future)

Email template is hard

Email template is hard as there are tons of email client from mobile, desktop and browsers. We need use old school table design and inline CSS with a comprehensive compatibility table to cover different email clients.

We need tools and services to help Email template building. We also need best practice and Email boilerplate when writing Email templates.

outline is unsupported
max-width is unsupported
unaligned td cell is unsupported
3-character hex code is unsupported
style tag in head is unsupported
display is unsupported
Subject limit to 25 characters

Typical structure is one big background table, then one div, then one main table, and nested tables if needed. So table, tr, td and div are the main elements used in Email templates.

Wednesday, October 16, 2013

Change Browser Language Preference

This week I am doing i18n for our web app using requirejs/i18n plugin, after I get translation done, I need test out by changing my browser language. Browser uses Accept-Language request-header to indicate its preference language. Some browser only has one language in the header, some browser has a list of preference languages with qvalues (quality value). One example is Accept-Language: zh-cn,zh;q=0.5

However, i18n is different from L10N which is more region related.

Internet Explorer
Windows only, go to Tools > Internet Options > General (tab) > Languages > Language preference.

Tools > Options (Windows) or Firefox > Preferences (Mac OS X), and select Content (tab) > Languages > Choose (button).

about:config, using intl.accept_languages if want custom language tags

Mac OS X only. The browser language is that specified in the OS X system language preferences. Go to System Preferences > Language & text > Language.

Safari will only send the top item with the Accept-Language header. You can't create custom language tags.

Options (Windows) or Chrome > Preferences (Mac OS X), and select Web Content > Languages & Spellchecker settings.

You can't create custom language tags. Not sure if there is hidden setting for this.

Menu > Settings > Preferences > General > Language > Details (Windows).
On Mac OS X, similar to Safari, it is the language specified in OS X. If you have a long list of languages in this dialog box, Opera sends all of them with the Accept-Language header.

opera:config and the Network > HTTP Accept Language setting if want custom language tags.

Sunday, October 6, 2013

Links from "The future of Javascript Tooling" talk

This was an amazing talk from Ariya Hidayat. I just listed the links here, for details, refer to his deck.

Saturday, October 5, 2013

SVCC 2013

Here are the key takeaway from Saturday's sessions.

1. Functional programming gets fun when Douglas Crockford teaches this using Javascript
2. TCP/IP networking needs tools like wireshark, fiddler and of course ISO layering models (
3. How to startup pitch (Elevator pitch, Executive Summary, PPT 10-20-30 rules, Detailed plan/roadmap)
4. Start business is easy in USA, you can register in one day
5. RegExp cheat sheet explains regular expression match/capture of character set, group, options from a string.

Some sponsors I remember:
Dice - the linkedIn for tech
Pivotal - the new company from VMWare/EMC, brings up Spring, RabbitMQ etc open source
Telerik - the one brings us Kendo UI
LeadTools - the world leader in imaging SDKs, OCR, PDF, PACS (medical image) etc
Snapp - Elastic cloud hosting for .NET application (How about Windows Azure?)
infragistics - User interface components

Of course, for lunch, I had one slice of Pizza Sponsored by Pivotal, one Sandwich Sponsored by Google

Tuesday, September 24, 2013

text-size-adjust in Email template

In our email, we see the footer font-size is not as we expected even if I specified !important in inline style. After google a bit, it turns out there is property called text-size-adjust to controle this. By default, Apple Mail’s minimum font size comes into play on the iPhone and iPad. By adding the this property to your CSS styles (text-size-adjust: 100% or none), you can override the default font sizes on Webkit-based email clients, thus avoiding layout glitches on the iPhone and iPad:

As this property is non-standard, it must be used prefixed: -moz-text-size-adjust, -webkit-text-size-adjust, and -ms-text-size-adjust.

If -webkit-text-size-adjust is explicitely set to none, Webkit-based desktop and tablet browsers, like Chrome or Safari, instead of ignoring the property, will prevent the user to zoom in or out the Web page.

Email template seems a piece of cake, but it is indeed not. We should be patient to use old school HTML coding skills and use popular email campaign tools to verify and test it.

Don't forget the followings:
1. Image styles
2. W3C HTML validator
3. Table for structures
4. Inline styles, no short-cut CSS
5. Testing across email clients

Monday, September 9, 2013

Javascript replace all line breaks in a string with

  1. str = str.replace('\n', '<br />');  -> However, this only replace the first ocurrence
  2. str = str.replace(/\n/g, '<br />'); -> use regexp to do global match
  3. str.replace(new RegExp('\n','g'), '<br />') -> similar to #2, but use constructor to build RegExp
  4. str = str.split("\n").join("<br />"); -> split and join, another way to do replace
  5. String.prototype.replaceAll = function(needle, replacement) {return this.split(needle).join(replacement||"");}; -> similar to #4, but added to String prototype
Btw, probably we need take care of \r\n case.

ssh or scp to EC2

ssh -i ~/key.pem

scp -i ~/key.pem file.txt

netstat -an |find /i "listening"

netstat -na | grep 443 | grep 66.151.139

tcpdump port 443

More tcpdump commands:
dump to file for wireshark analysis
sudo tcpdump -w tcp.dump2 net 66.151

dump to console for grep
sudo tcpdump -i en0 host 66.151.139

Thursday, September 5, 2013


I met this error when set data to sessionStorage. It means the data exceeded the browser limit. Most browsers have 2.5M or 5M limit per domain. Many developers assume that one character equals one byte, but this is not a safe assumption. Strings in JavaScript are UTF-16, so each character requires two bytes of memory. This means that while many browsers have a 5 MB limit, you can only store 2.5 M characters. recommends a 5M limit, but as of writing, Chrome 29, Safari 6 still use 2.5M limit, Firefox/Opera are ok. Also Firefox/Opera allows user to adjust the default value (about:config - search quota), Chrome/Safari/IE do not allow.

The practice is to handle this error in Javascript, and fallback to browser memory.

The error might look like as below
Uncaught QuotaExceededError: An attempt was made to add something to storage that exceeded the quota.

Browser storage

There are the following storage types in browser side when do Javascript based web app.
  • Cookie: there is # of cookies per domain limit, and size limit (around 4K limit)
  • Memory: limit by system (?), data lost during browser refresh
  • WebStorage: (sessionStorage, or localStorage) -
  • AppCache:  It is to store the whole web-app (pages, images, css, JavaScript) in the browser to make it available offline.
  • Web SQL: relational database, SQLlite on browser, deprecated
  • IndexedDB: NoSQL DB on browser side. IndexedDB which is already available on Chrome 12+ and Firefox 5+, and, soon, in IE 10 as well.
  • GlobalStorage - deprecated

Tuesday, September 3, 2013

Cross Site Scripting (XSS)

Today Salesforce rejected our app due to several security issues. One of these was Cross Site Scripting (XSS). This is a common issue in security domain, and we need employ the changes to prevent XSS. The problem, and possible fix solution from Salesforce is very clear, so I copied and pasted here for future reference.


The attack involves reflecting user provided data into the browser, without any modification at the server's end. Cross Site Scripting attacks can be scripted in any browser scripting technology. There are 3 different types of Cross Site Scripting attacks. The first, being the most simple, in which the data entered is reflected back. The attack is temporary and is least risky. The second, called Persistent Cross Site Scripting is very common on bulletin boards and various social networking sites. The malicious input is stored on the server and each time a user accesses the data, the code is interpreted. And finally, the third form, called DOM based Cross Site Scripting, is perpetrated by exploiting the accessibility of the DOM of HTML page the user is viewing, and then running scripts with the user's privileges on his/her machine.
The developers of the application need to have strong input validation in place. This can be done using either blacklists or whitelists of characters. Similarly, the developers need to ensure that output is well sanitized. This can be implemented by escaping all the content being directed to the browser. Methods to boost cookie security should be employed.


Consider performing a combination of input filtering and context-appropriate output encoding, such as HTML entity encoding for all the data that could be provided by external data sources like databases, users or web services if that data is included in the application’s output. Sanitize all user input. Enforce input validation checks on the server side. Include data type checks, data size and range checks. Check user input against whitelist values, check against other data values for logical accuracy and data integrity based on business rules.
An example of a blacklist would be where any input that contains characters that are considered “invalid” for web applications, such as “ < > & ‘ `;. Despite efforts to authoritatively identify all such characters, some characters are likely to be left out. A better way of validating input would be to define a list of allowed characters, also referred to as a whitelist.


Sunday, September 1, 2013

Object in ES-5

ES5 adds more features to Object.

Object.preventExtensions(obj) makes it impossible to add properties to obj. You can still change and delete properties. 
Object.isExtensible(obj) is to check whether obj is extensible.

Object.seal(obj) prevents extensions and makes all properties “unconfigurable”. The latter means that the attributes of properties can’t be changed, any more. Read-only properties stay read-only, enumerable properties stay enumerable, etc. But You can still change the property.
Object.isSealed(obj) is to check whether obj is sealed.

Object.getOwnPropertyDescriptor(obj, 'foo')
Object.defineProperty(obj, 'foo', { enumerable: false });

Object.freeze(obj) makes all properties non-writable and seals obj. 
Object.isFrozen(obj) is to check whether obj is frozen.


Thursday, August 29, 2013

Apple Mail adds link to span content

I don't know the root cause, but the problem is Apple Mail somehow adds hyperlink to span content. It will show hyperlink for To fix this, I use


During the testing, if I put All rights reserved., the reserved will be changed to hyperlink, strange. So the simple conclusion is: use p instead of span.

SVN update 403 error

Once in a while, when I update codes from SVN, I get the following error: Server sent unexpected return value (403 Forbidden) in response to OPTIONS request for '' If I go to command line to run svn up, I get the following error: svn: E155036: Please see the 'svn upgrade' command svn: E155036: Working copy '/Users/jimz/Workshop/dev' is too old (format 10, created by Subversion 1.6) I might imply the SVN GUI tool uses different version from svn command line. I could not figure out the root cause of 403 Forbidden, but after I delete local Working copy, and checkout the whole folder, then it works. No root cause, but solution for quick turnaround.

Sunday, August 18, 2013

Lessons - startup

  1. Make most decisions by consensus, but have a single CEO whose decisions are final. Make it clear from day one.
  2. Pick the initial team very carefully. Everyone should be pleasant to work with, have at least one skill relevant to the business they’re spectacular at, be extremely effective and pragmatic. Everyone should have product sense and a shared vision for the product and the company.
  3. The standard you walk past is the standard you accept. Pick a small set of non-negotiable rules that matter to you most and enforce them ruthlessly.
  4. Most investor advice is very good for optimizing and scaling a working business. Listen to it.
  5. Most investor advice isn’t very good for building a magical product. Nobody can help you build a magical product — that’s your job.
  6. Product sense is everything. Learn it as quickly as you can. Being good at engineering has nothing to do with being good at product management.
  7. Product comes first. If people love your product, the tiniest announcements will get attention. If people don’t love your product, no amount of marketing effort will help.
  8. Don’t guess. Measure.
  9. Market to your users. Getting attention from people who won’t buy your product is a waste of time and money.
  10. Product comes first. Selling a product everyone wants is easy and rewarding. Selling a product no one wants is an unpleasant game of numbers.
  11. Inbound is easier than outbound. If possible, build the product in a way where customers reach out to you and ask to pay.
  12. Minimize complexity. The simpler the product, the more likely you are to actually ship it, and the more likely you are to fix problems quickly.
  13. Pick implementations that give 80% of the benefit with 20% of the work.
  14. Every once in a while, get away. Go hiking, visit family in another city, go dancing, play chess, tennis, anything. It will make you more effective and make the people around you happier.

Browser developer tool

Built-in browser developer tool really helps Web development, the all-in-one development environment is getting better and better from desktop browsers.

Chrome: This is my favorite
Firefox: Firebug extension, but I think Firefox 23 built-in tool is cool and promising
Opera: Dragonfly, very clear and easy of use
Safari: Xcode style, hard to use. I seldom use it unless I need debug iOS safari (mobile web remote debug)
IE9: F12. So hard to use, but IE11 is getting much better based on .NET magazine. Hope it will catch up Chrome/Firefox.

Usually the features available from these browser developer tools are similar, and they should Element inspector, Style box model, Resource browser, network activity, Performance, profile, Console etc.

Here are some tips I just learned or I don't use frequently:
  • Don't forget right click in developer tool - the contextmenu has some surprises
  • Debugging Minified JavaScript
  • Emulate a User Agent
  • Checking DOMContentLoad and Load Event
  • Incrementing CSS Values - Simply use the up and down cursor keys to increment/decrement by a unit of 1.
  • console.log() for outputting debug info, will work printf style. like console.log("The flower is %s.", "red")
  • console.assert() can be used to test whether expressions are true or false.
  • console.table() can be used to output data from an array of arrays or a list of objects in a sortable, tabular format.
  • You can automatically create a breakpoint in your code by adding the following line to your JavaScript: debugger;

Tuesday, August 13, 2013

Versioning main.js in requirejs

        var require = {
              paths: {
                'main': 'main.js?v=MD5_MAIN'
<script data-main="js/main" src="js/lib/require/require-2.1.5.min.js"></script>

This is one way, and need make sure require config is before require.js script tag.

Another way mentioned in the issue by requirejs author jrburke is using directory. This is a better way than querystring.
<script data-main="v1/js/main" src="v1/js/require.js"></script>

Thursday, August 1, 2013

Flash acoustic echo cancellation

Acoustic echo cancellation (AEC) is required for voice-over-IP (VoIP) applications to provide headset-free talk. AEC is available in messenger applications (such as Skype and Google Talk) and softphones (such as Xlite).

In Flash, to use acoustic echo cancellation, call the Microphone.getEnhancedMicrophone() method to get a reference to a Microphone instance. Set Microphone.enhancedOptions to an instance of the MicrophoneEnhancedOptions class to configure settings. When AEC is not supported, Microphone.getEnhancedMicrophone() returns null.

Here are sample codes:
var mic:Microphone = Microphone.getEnhancedMicrophone();
var options:MicrophoneEnhancedOptions = new MicrophoneEnhancedOptions();
options.mode = MicrophoneEnhancedMode.FULL_DUPLEX;
options.echoPath = 128;
options.nonLinearProcessing = true;
mic.enhancedOptions = options;
There are two other settings similar but not exactly for acoustic echo cancellation.
  1. setUseEchoSuppression - this method can reduce, but not eliminate, the risk of feedback amplification. When enhanced audio is used, this echo suppression functionality is ignored.
  2. noiseSuppressionLevel - Maximum attenuation of the noise in dB (negative number) used for Speex encoder. If enabled, noise suppression is applied to sound captured from Microphone before Speex compression. Set to 0 to disable noise suppression. Noise suppression is enabled by default with maximum attenuation of -30 dB. Ignored when Nellymoser codec is selected.

Monday, July 29, 2013

Why my image is rotated?

When you take a picture using iPhone, there are 4 possible orientation, namely 1, 3, 6, 8. The most common values are 1 (landscape) and 6 (portrait).

When you take a picture holding iPhone in portrait mode, the image orientation will be 6. In iOS and Mac OSX, most softwares (applications) recognize this orientation Flag and display image correctly on screen. It seems windows 7 does the same thing (not fully test).
The original image was saved in a "Rotated 90 CCW" (back to Camera View with orientation 1) , so when display this image, we need rotate 90 clockwise (reverse the CCW).

This behavior is true in preview, browsers etc. However, there is a difference in browsers, if I refer the image directly (file:///Users/jimz/Downloads/1323-bike-rotate.jpeg), it is auto-rotated clockwise 90 degree. If I refer the image using <img src="1323-bike-rotate.jpeg"> in HTML, it is not auto-rotated, so in html image, it is displayed in original format which is 90 degree rotated counter-clockwise. This is the reason why my image is rotated from UI viewpoint.

Sunday, July 28, 2013

WebRTC Acronyms

ICE: Interactive Connectivity Establishment (It is a framework to allow browsers to connect peers)
STUN: Session Traversal Utililities for NAT (It is a protocol to discover public address and determine if there is any restrictions in the router)
NAT: Network Address Translation (It is to give device, connecting to router, a public IP)
TURN: Traversal Using Relays around NAT (It is to bypass Symmetric NAT restriction by connecting to TURN server and relaying all information through TURN server)
SDP: Session Description Protocol (It is a standard to describe multimedia content of the connection such as resolution, format, codec, encryption etc metadata, simply put, it is media info)
Signal Channel it is sort of channel of communication to exchange information before establish a connection. The information is called offer (peer A)/answer (peer B).
ICE Candidate: It is to exchange information about the network connection. It is connectivity info which details the available methods the peer is able to communicate.

All information is from below blog which is very easy to understand these acronyms.

Sunday, July 21, 2013

Am I online or offline?

HTML5 provides APIs to let user check if user_agent is online or offline, but unfortunately different browser vendors implement differently. From my testing, Chrome is the only browser which detects network connectivity and provides "correct" online/offline information. While Firefox etc is checking if user_agent is in "Work Offline" mode, so it returns true even though network connectivity is lost. Due to this inconsistency across browsers,  the two "ideal" ways (check navigator.onLine, or window.ononline/onoffline event) will NOT work.

There are two possible solutions to overcome this and provide online/offline status.
1. AppCache error event (applicationCache.onerror, applicationCache.addEventListener('error')) - pay attention to reaching applicationCache size limit.
2. XHR (long polling predicable resource on server, if timeout either server is down or network connectivity is lost)

Friday, June 21, 2013

Turn off autocapitalize on iOS Safari

By default on iOS Safari input text or textarea enables automatic correction and capitalization to streamline mobile typing. However, sometimes, we don't want this, for instance username input text.

We can add autocapitalize="off" autocorrect="off" two attributes to disable this.

When I tested on iOS6.1.4, input email, input passsword don't auto capitalize the first character. Also show correct keyboard.

We can use HTML5 new input types to better control keyboard display
Text: <input type="text" /> <!-- display a standard keyboard -->
Telephone: <input type="tel" /> <!-- display a telephone keypad -->
URL: <input type="url" /> <!-- display a URL keyboard -->
Email: <input type="email" /> <!-- display an email keyboard -->
Zip Code: <input type="text" pattern="[0-9]*" /> <!-- display a numeric keyboard -->

For details, check out

Wednesday, June 19, 2013

Build your first Mobile App with HTML5, jQuery, PhoneGap & APIs

Here are the key takeaways from this 1-day free event sponsored by

jQuery Mobile
Check out for details. It is evolving fast, and it is 1.3.x version now. jQuery Mobile is not jQuery mobile version, it is more like jQuery UI mobile version (but not exactly). When we use jQuery Mobile, we usually needs jQuery and jQuery mobile CSS to get things work.

Other mobile web framework and libraries?

Mobile Prototyping Tool (Recommended in jQuery Mobile website, and apigee team uses it too)

Port HTML5/CSS3/Javascript based Web app to Native app. It is more like a bridge. - Adobe Cloud build service

PhoneGap Alternatives

More about HTML5

Topics we covered in this event
Prototyping using codiqa
jQuery Mobile
Android developer tool (ADT)
Xcode and simulators
apigee API service
Security (sandbox)

Topics we didn't cover in this event
Push notifications
File Storage
Social Graph
Local capabilities
3rd party integration
Legacy integration
code execution

Python built-in HTTP server
You can quickly launch a webserver to test mobile web if you have Python installed
python -m SimpleHTTPServer 8080

Companies mentioned in this event

Here are my thoughts
Why Mobile Web?
- Write once run every device?
- One stack fits all?
- Better upgrade options (fast release cycles)?

Why not Mobile Web?
- Performance?
- HTML5 API limitation?
- Native User Experience?
- Offline limitation?

Native or Web or Hybrid app?
- It depends

Sunday, June 16, 2013

More about HTML Email Template

Today I came across these 2 great articles regarding HTML email templates, and they are must to read resources if you are new to HTML email template writing. Last year I did some email template composing, and lots of gotchas and questions are addressed in these two links.

Here are key points I copied and pasted here for future reference :
Part 1: General introduction
If you are already familiar with web development, forget everything you know about it.

The worst thing you can do is get angry that you can’t use DIVs or that margin isn’t fully supported. So forget everything you know about semantic HTML and the latest CSS spec.

The best way to test is using Litmus or Email on Acid. I recommend taking out an unlimited plan with either of these companies because being able to test frequently is really important.

The two services that I use the most are MailChimp and Campaign Monitor.

Image-reliant emails with no text are more likely to be marked as SPAM and so are emails with really long image filenames.

Run a SPAM test through your testing account with Litmus or Email on Acid before you send your email, to make sure all your hard work isn’t headed straight for the Junk folder.

Frameworks like the HTML Email Boilerplate are full of wonderful tricks and snippets that you can implement piece by piece. However, if you are just starting out I don’t recommend using it as a starting point as it contains a lot of elements that you won’t need. Boilerplates can often make it more difficult to troubleshoot any issues if there is a lot of unused code in your file.

Using an XHTML doctype generally has the fewest quirks and inconsistencies between documents. I use XHTML 1.0 Transitional because it has proven itself to be the most reliable doctype in my experience.

The viewport meta tag is telling the device to set the viewable area to the width of the device’s screen. It also sets the initial scale to ‘normal’ which is neither zoomed in nor out.

Email is All About Nesting Tables, you need to use lots and lots of nested tables because neither the colspan nor rowspan attributes are properly supported.

Again, because of the lack of standards support, it’s not a great idea to use standard tags like h1, h2, h3 or p.  Your best bet is to place every block of text into its own cell and apply inline styling to that cell

You can’t apply multiple classes to things in HTML email because it is not supported. Every element can have a maximum of one class.

You can’t use shorthand for things like font size (i.e. style="font: 8px/14px Arial, sans-serif;") because it is not supported.

It’s good to give your images names that are short and meaningful because it will improve your spam score.

It’s also a really great idea to try to keep your entire email as small as humanly possible: under 100kb is ideal but not always possible, under 250kb is pretty standard.

For your main container elements always set the size in pixels. You can then use percentages inside your containing element if you wish.

Responsive Email templates

Part 2: Build Template from Scratch
If an attribute exists in HTML, use that instead of CSS

Always remember to use the full six characters of a hex code, as three character shorthand won’t always work.

When using padding in email, you must always specify every single value (top, right, bottom and left) otherwise you can get unpredictable results. Note that it’s safe to use padding on TD tags but not on P tags or DIVs.

We’ll insert our image, adding alt text and adding style="display:block;" which is a common fix that stops some email clients adding gaps underneath your images.

If the contents of your header are really important to your message, don’t use an image-only header. Remember, images are blocked by default for most clients, so if there is an aspect of your email that is crucial, never include it as an image.

If you always have pixel widths on everything, you can end up with a lot of values to override with media queries. If your nested table widths are based on percentages, then when you adjust the width of the parent element, everything will adapt accordingly.

Because we want a ‘margin’ in between these two cells, but margin isn’t supported, we’ll create a three-column table with an empty cell between the two outer columns.

Be sure to zero your font-size and line-height and add a a non-breaking space character &nbsp; in the margin cell.

We’ll also set the valign to "top" for both cells so that they will vertically align to the top, even if one column has more text than the other. The default vertical alignment is "middle".

As we need multiple rows, we’ll nest yet another table because we can’t use any colspan or rowspan tags.

Let’s run this through the W3C Validator to make sure nothing is bad or broken.

Next we’re going to run a test through Litmus to make sure the structure of our email works great.

Time to turn off the borders and see it looking beautiful. Go through and replace every occurrence of border="1" with border="0".

As a final touch, I’m going to add 30px of padding to the bottom of the very first cell, to prevent our email from stopping abruptly at the bottom in some webmail clients (like Apple Mail), and 10px of padding at the top, so that our blue header has a little bit of breathing room.

If you have used any comments, get rid of them. Some email clients can choke on comments so it’s wisest not to have any unnecessary code anywhere in your files.

postMessage only works for IFRAMES/FRAMES in IE9

From this blog, the limitation of IE9 postMessage implementation impacts cross window/tab communications, at least for this windows browser. Firefox, Chrome, Safari, Opera seem to implement well. Through postMessage and onMessage interfaces, it is a convenient, efficient and secure way to do cross window/tab/frame communications, even cross domains.

Though parent and child window can easily access eachother’s DOM, a common way to get a value from one window to another is by setting a value on a hidden input field of a form in the other window. Therefore, the solution is adding a form to your page and using hidden form elements to transfer data back and forth between windows.

Here is one jquery plugin which encapsulates all the form building, event handler details.

Friday, June 7, 2013

SecurityError: The operation is insecure.

How to resolve this? This error appears if secure HTTP (https://) tries to connect non-secure websocket (ws://) servers.

We tested this issue through below test site across browsers, and found most browsers throw SecurityError

IE 9 [no websocket support]
IE 10 [no]
Chrome [ok]
FireFox [no]
Opera [no]

Safari [ok]
Chrome [ok]
FireFox [no]
Opera [no]

Firefox (v21) has a flag to control this (network.websocket.allowInsecureFromHTTPS from about:config)

Tuesday, May 28, 2013

Cherry pickup (Brentwood, Gilroy)

Where:     Lopez Ranch
1801 Orchard Lane
PO BOX #807
Brentwood, CA 94513
(925) 634-4433

Where:     Laird Ranch
3150 Sellers Ave
Brentwood, CA 94513
(925) 998-5769

Where:     Heritage Family Farm
2500 Concord Ave.
Brentwood, CA 94513
(925) 642-7653

Where:     Bacchini's Fruit Tree
2010 Walnut Blvd.
Brentwood, CA 94513
(925) 634-3645

Where:     Bloomfield Cherries
501 Payne Ave.
1/2 mile west of Walnut
Brentwood, CA 94513
(925) 550-5540

Where:     Chavez U-Pick Cherries
South side of Marsh Creek Road between Walnut Blvd. and Sellers
, CA
(925) 625-3994

Where:     DC's Extraordinary Cherries
2012 Marsh Creek Road
1/4 Mile West of Highway 4 Bypass on Marsh Creek Road, One mile
Brentwood, CA 94513
(925) 516-4495

Where:     Maggiore Cherry Ranch
Camino Diablo Rd.
1/2 mile East of Vasco Road
Byron, CA 94514
(925) 634-4176

Where:     Maggiore Ranches
Camino Diablo Rd.
1/2 mile East of Vasco Road
Byron, CA 94514
(925) 634-4176

Where:     Mike's U-Pick
3230 Concord Ave.
Brentwood, CA 94513
(925) 698-7459

Where:     Nunn Better Farms
Sellers Avenue
Between Sunset Road and Chestnut StreetBrentwood, CA
Brentwood, CA
(925) 634-2148

Where:     Papini Family Orchards
301 Sellers Ave.
Brentwood, CA 94513
(925) 759-6735

Where:     Papini Farms #2
301 Sellers Ave.
Brentwood, CA 94513
(925) 759-6735

Where:     Pease Ranch
25175 Marsh Creek Road
Brentwood, CA 94513
(925) 634-4646

Where:     Pomeroy Farm
1600 Eureka Ave.
PO BOX #67
Brentwood, CA 94513

Where:     RC U-Pick Cherries
4401 Sellers Ave.
Brentwood, CA 94513
(925) 679-3011 


Buckley u-Pick Cherry Farms
2950 Leavesley Rd
Gilroy, CA 95020
(408) 842-4697

Lazy K Ranch Cherry U-pick
3465 Susie Ln
Gilroy, CA 95020
(408) 888-5431

Gizdich Farms, (Strawberry, apple U-pick)
55 Peckham Rd., Watsonville.