<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0"> <channel><title>SitePoint » Learn CSS | HTML5 | JavaScript | Wordpress | Tutorials-Web Development | Reference | Books and More</title> <link>http://www.sitepoint.com</link> <description /> <lastBuildDate>Mon, 21 May 2012 05:40:39 +0000</lastBuildDate> <language>en</language> <sy:updatePeriod>hourly</sy:updatePeriod> <sy:updateFrequency>1</sy:updateFrequency> <generator>http://wordpress.org/?v=3.3.1</generator> <xhtml:meta xmlns:xhtml="http://www.w3.org/1999/xhtml" name="robots" content="noindex" /> <atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/SitepointFeed" /><feedburner:info uri="sitepointfeed" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><item><title>Stopping Abusive Clients: The Complete Process</title><link>http://feedproxy.google.com/~r/SitepointFeed/~3/3RrvOMc1a7U/</link> <comments>http://www.sitepoint.com/stopping-abusive-clients-the-complete-process/#comments</comments> <pubDate>Mon, 21 May 2012 02:33:41 +0000</pubDate> <dc:creator>John Tabita</dc:creator> <category><![CDATA[Freelancing]]></category> <category><![CDATA[Sell Your Services]]></category> <category><![CDATA[Selling Web Design Services]]></category> <category><![CDATA[Web Pro Business]]></category> <category><![CDATA[Work Smarter]]></category> <category><![CDATA[Business]]></category> <category><![CDATA[clients]]></category> <category><![CDATA[freelance]]></category> <category><![CDATA[freelancing]]></category> <category><![CDATA[sales]]></category> <category><![CDATA[selling]]></category> <category><![CDATA[selling your services]]></category> <category><![CDATA[small business]]></category> <guid isPermaLink="false">http://www.sitepoint.com/?p=54749</guid> <description><![CDATA[<img
width="50" height="50" src="http://www.sitepoint.com/wp-content/uploads/1/files/2012/05/stop-abusive-clients-50x50.jpg" class="attachment-thumbnail wp-post-image" alt="SONY DSC" title="SONY DSC" />In the final installment of his series, Putting a Stop to Abusive Clients, John Tabita shows you how to put it all together in a complete, comprehensive process to end the abuse once and for all.]]></description> <content:encoded><![CDATA[<img
width="50" height="50" src="http://www.sitepoint.com/wp-content/uploads/1/files/2012/05/stop-abusive-clients-50x50.jpg" class="attachment-thumbnail wp-post-image" alt="SONY DSC" title="SONY DSC" /><p></p><p>This is the 11th and final installment of my series, <a
title="Putting a Stop to Abusive Clients" href="http://www.johntabita.com/abusive-clients/" target="_blank">Putting a Stop to Abusive Clients</a>. I hope I’ve made it clear that the solution is not to continually complain and blame clients if they treat you badly, but to take responsibility and make the appropriate changes to your business practices.</p><p>An important “best practice” for your business is to have a system for selling your services and managing the sales process. When I first started out, I didn’t realize I needed a process, one with a beginning, middle, and end. Not having one meant I typically started off badly, fumbled around in the middle, and didn’t really know when (or if) it really ended. By not knowing how to close (end) the process by asking for the sale, I allowed it to fade into “maybeland,” which is the worst place to be when your income depends on whether you sell or not.</p><p>Having a clearly-defined process allows you to build in checks and balances, to define and manage client expectations. Not having one means clients can walk all over you—either unintentional or deliberately—and you wind up feeling abused. So here in a nutshell is the process I followed for many years … once I figured out I needed one, that is.<div
id='div-gpt-ad-1328644474660-10' style='width:728px; height:90px;'> <script type='text/javascript'>googletag.cmd.push(function() { googletag.display('div-gpt-ad-1328644474660-10'); });</script> </div></p><h2>Preliminary Consultation</h2><p>When I make contact with a potential client, the first step is to determine how viable of a prospect he or she really is. Rather than immediately scheduling a meeting, I’m going to have a preliminary phone call to determine two things:</p><ol><li>Are they truly serious about the project?</li><li>Can they afford to pay for a top-end site like I’m going to provide, or are they just looking for the cheapest option available?</li></ol><p>If you’ve read my <strong>27.5 Must-Ask Questions for Consultative Selling</strong>, then you already know some questions to ask. I want to learn a little bit about the company and his business goals and objectives. At some point in the conversation, I’m going to ask some variation of this question:</p><p>“My prices start at $X,XXX. Were you prepared to spend that?” Unless I get a positive response, I’m not hurrying out to meet with him any time soon.</p><p>It’s tempting to skip this crucial first step, or to avoid asking the hard questions and just set up a meeting. But if you want to<a
title="Stop Wasting Time with Prospects Who Aren’t Serious" href="http://www.sitepoint.com/stop-wasting-time-with-prospects-who-arent-serious/" target="_blank"> stop wasting time with prospects who aren’t serious</a>, I highly recommend you don’t.</p><h2>Preparation</h2><p>If the initial conversation warrants a meeting, I’m going to do some research in order to be able to ask some intelligent questions. I want to walk in knowing as much as I can about the company, its owners, and their business model. In this day and age, there’s no excuse for ignorant questions like, “What exactly is it you do here?”</p><h2>Needs Analysis</h2><p>The heart of consultative selling is asking questions and actually listening to the answer (as opposed to thinking about what you’re going to say next). My <strong>27.5 Must-Ask Questions for Consultative Selling</strong> are very direct and to-the-point, and it takes a bit of courage to bring yourself to ask them … especially the first time.</p><p>It helps if you don’t get down to business right away. Think of it like this: the questions you ask should go from general to specific. At some point you’re going to ask some quasi-confidential questions, like how much would he like to increase revenue. But a more appropriate question to begin with might be, “How did you get started in this industry?”</p><p>Before you jump into the deep end, you need to break the ice. I’ve heard it said that prospects who want to get straight down to business really want to get straight down to “How much is this going to cost me?”</p><h2>Recommendation</h2><p>At some point, you’ll need to turn the information-gathering conversation into a diagnosis. Once you feel you sufficiently understand the prospect’s business goal, needs, and objectives, you can begin to offer suggestions and solutions.</p><p>The trick is to <a
title="Stop Giving Away So Much Free Information!" href="http://www.sitepoint.com/stop-giving-away-so-much-free-information/" target="_blank">avoid giving away too much free information</a>. You do that by discussing the WHY, agreeing upon the WHAT, and ignoring the HOW. Forget about the technical stuff you love talking about. To get the prospect’s commitment to do business with you, you only need to establish and agree upon two things you:</p><p>1. What he’s trying to accomplish, his “big picture” objective<br
/> 2. That you’re the one to help him accomplish it</p><h2>Engagement</h2><p>There comes a point when it’s time to close the deal and ask for the engagement. There are many ways to do this, but I always liked to ask a simple question: “Are you ready to move forward?” (You do this after you’ve discussed all there is to discus and recapped the entire conversation, asking if there’s anything that needs to be added.)</p><p>If your prospect says, “yes,” he’d like to move forward, you need to establish the next step. For a lot years, that meant spending several hours preparing a detailed proposal—that is, until I learned how to <a
title="Stop Writing Proposals to Win Business" href="http://www.sitepoint.com/stop-writing-proposals-to-win-business/" target="_blank">stop writing proposals to win business</a>.</p><p>If you establish and agree upon items #1 and #2 above, then you ought to be able to obtain the prospect’s verbal agreement, conditional on price, without ever writing a proposal. Once you do, it’s a simple thing to <a
title="Stop Doing the Same Things and Expecting Different Results" href="http://www.sitepoint.com/stop-doing-the-same-things-and-expecting-different-results/" target="_blank">prepare a cost estimate without turning it into a comprehensive project plan</a>. Whether I did that on the spot or went back to the office depended on the size and complexity of the project. Once I had a price, I got back in touch to get his agreement.</p><h2>Finalize</h2><p>Now it’s time to finalize the agreement. If the prospect has agreed to the price, you return to his place of business with your final, written document in hand (based on everything discussed during the Needs Analysis and Recommendation steps), then sit down with him and go over every clause in detail. To prevent future problems like <a
title="Stop Waiting to Get Paid! How to Collect Even when Your Client Delays" href="http://www.sitepoint.com/stop-waiting-to-get-paid-how-to-collect-even-when-your-client-delays/" target="_blank">waiting to get paid when your client delays</a>, <a
title="Stop Making Endless Design Changes" href="http://www.sitepoint.com/stop-making-endless-design-changes/" target="_blank">making endless design changes</a>, or <a
title="Stop the Slippery Slope of Scope Creep" href="http://www.sitepoint.com/stop-the-slippery-slope-of-scope-creep/" target="_blank">avoiding the slippery slope of scope creep</a>, you must <a
title="Stop Getting Walked on and Set Some Boundaries Already" href="http://www.sitepoint.com/stop-getting-walked-on-and-set-some-boundaries-already/" target="_blank">stop getting walked on and set some boundaries</a>. That’s exactly what you’re doing here, by managing expectation up-front, in a face-to-face conversation, instead of after the fact.</p><h2>The Final Word</h2><p>There are many ways to skin this cat; this just happens to be the way I skin it. You may develop a process that’s similar or completely different. Steal mine, borrow from it, or make up your own. But come up with one that works for you, then refine it until you get it right. It will do wonders for your business and will put an end to abusive clients, misunderstandings, and mismanaged expectations and once and for all.</p><p
style="text-align: right"><em><a
href="http://www.sxc.hu/profile/duchesssa" target="_blank">Image credit</a></em></p><div
style="border-width: 1px;border-style: solid;border-color: #d5d5d5;padding: 8px;margin-top: 30px;margin-bottom: 30px;background: #e8e8e8">It’s not too late to get my free guide, <strong>27.5 Must-Ask Questions for Consultative Selling</strong>. Just <a
title="Twitter | @johntabita" href="http://twitter.com/johntabita" target="_blank">follow me on Twitter</a> and I’ll send you a link.</div><p>This is part 11 of the series <strong>Putting a Stop to Abusive Client Behavior</strong>:</p><ol><li><a
title="Stop Client Abuse of Web Designers Now!" href="http://www.sitepoint.com/stop-client-abuse-of-web-designers-now/" target="_blank">Stop Client Abuse of Web Designers Now!</a></li><li><a
title="Stop the Abuse! 7 Steps to a Well-Trained Client" href="http://www.sitepoint.com/stop-the-abuse-7-steps-to-a-well-trained-client/" target="_blank">Stop the Abuse! 7 Steps to a Well-Trained Client</a></li><li><a
title="Stop Wasting Time with Prospects Who Aren’t Serious" href="http://www.sitepoint.com/stop-wasting-time-with-prospects-who-arent-serious/" target="_blank">Stop Wasting Time with Prospects Who Aren’t Serious</a></li><li><a
title="Stop Giving Away So Much Free Information!" href="http://www.sitepoint.com/stop-giving-away-so-much-free-information/" target="_blank">Stop Giving Away So Much Free Information!</a></li><li><a
title="Stop Writing Proposals to Win Business" href="http://www.sitepoint.com/stop-writing-proposals-to-win-business/" target="_blank">Stop Writing Proposals to Win Business</a></li><li><a
title="Stop Doing the Same Things and Expecting Different Results" href="http://www.sitepoint.com/stop-doing-the-same-things-and-expecting-different-results/" target="_blank">Stop Doing the Same Things and Expecting Different Results</a></li><li><a
title="Stop Waiting to Get Paid! How to Collect Even when Your Client Delays" href="http://www.sitepoint.com/stop-waiting-to-get-paid-how-to-collect-even-when-your-client-delays/" target="_blank">Stop Waiting to Get Paid! How to Collect Even when Your Client Delays</a></li><li><a
title="Stop Getting Walked on and Set Some Boundaries Already" href="http://www.sitepoint.com/stop-getting-walked-on-and-set-some-boundaries-already/" target="_blank">Stop Getting Walked on and Set Some Boundaries Already</a></li><li><a
title="Stop the Slippery Slope of Scope Creep" href="http://www.sitepoint.com/stop-the-slippery-slope-of-scope-creep/" target="_blank">Stop the Slippery Slope of Scope Creep</a></li><li><a
title="Stop Making Endless Design Changes" href="http://www.sitepoint.com/stop-making-endless-design-changes/" target="_blank">Stop Making Endless Design Changes</a></li></ol> <span
id="pty_trigger"></span><div
style='padding:20px 0px 50px 0px;'><div
style='float:left;padding-left:40px;'><div
id='div-gpt-ad-1335489406190-0' style='width:300px; height:100px;'> <script type='text/javascript'>googletag.cmd.push(function() { googletag.display('div-gpt-ad-1335489406190-0'); });</script> </div></div><div
style='float:right;padding-right:40px;'><div
id='div-gpt-ad-1335489406190-1' style='width:300px; height:100px;'> <script type='text/javascript'>googletag.cmd.push(function() { googletag.display('div-gpt-ad-1335489406190-1'); });</script> </div></div><div
style='clear:both'></div></div><div
style='clear:both'></div><div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/SitepointFeed?a=3RrvOMc1a7U:nxDXv1pjZFU:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/SitepointFeed?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/SitepointFeed?a=3RrvOMc1a7U:nxDXv1pjZFU:qj6IDK7rITs"><img src="http://feeds.feedburner.com/~ff/SitepointFeed?d=qj6IDK7rITs" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/SitepointFeed?a=3RrvOMc1a7U:nxDXv1pjZFU:gIN9vFwOqvQ"><img src="http://feeds.feedburner.com/~ff/SitepointFeed?i=3RrvOMc1a7U:nxDXv1pjZFU:gIN9vFwOqvQ" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/SitepointFeed/~4/3RrvOMc1a7U" height="1" width="1"/>]]></content:encoded> <wfw:commentRss>http://www.sitepoint.com/stopping-abusive-clients-the-complete-process/feed/</wfw:commentRss> <slash:comments>0</slash:comments> <feedburner:origLink>http://www.sitepoint.com/stopping-abusive-clients-the-complete-process/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=stopping-abusive-clients-the-complete-process</feedburner:origLink></item> <item><title>An Introduction to C</title><link>http://feedproxy.google.com/~r/SitepointFeed/~3/XC5vO2nn0_0/</link> <comments>http://www.sitepoint.com/an-introduction-to-c/#comments</comments> <pubDate>Sat, 19 May 2012 15:00:53 +0000</pubDate> <dc:creator>Surabhi Saxena</dc:creator> <category><![CDATA[Web Tech]]></category> <guid isPermaLink="false">http://www.sitepoint.com/?p=53509</guid> <description><![CDATA[C. You've all heard about it, but how much do you actually know about it? In this piece, Surabhi introduces us to this powerful language.]]></description> <content:encoded><![CDATA[<p></p><p><strong>Introduction</strong></p><p>C is a general purpose, structured programming language.  Its instructions consist of terms that resemble algebraic expressions, augmented by certain English keywords such as if, else, for, do and while.  In this respect it resembles high level structured programming languages such as Pascal and Fortran.  C also contains additional features, that allow it to be used at a lower level, thus bridging the gap between machine language and high level language.  This flexibility allows C to be used for systems programming as well as for applications programming.  Therefore C is called a <strong><em>middle level language.  </em></strong></p><p>C is characterized by the ability to write very concise source programs, due in part to the large number of operators included within the language.  It has a relatively small instruction set, though actual implementations include extensive library functions which enhance the basic instructions.  C encourages users to create their own library fuctions.</p><p>An important characteristic of C is that its programs are highly portable.  The reason for this is that C relegates most computer dependent features to its library functions.  Thus, every version of C is accompanied by its own set of library functions which are relatively standardized.  Therefore most C programs can be processed on many different computers with little or no alteration.<div
id='div-gpt-ad-1328644474660-10' style='width:728px; height:90px;'> <script type='text/javascript'>googletag.cmd.push(function() { googletag.display('div-gpt-ad-1328644474660-10'); });</script> </div></p><p><strong>History of C:</strong></p><p>C was developed in the 1970&#8242;s by <strong>Dennis Ritchie</strong> at <strong>Bell Telephone Laboratories</strong>,Inc. (now a part of AT&amp;T).  It is an outgrowth of two earlier languages, called BCPL and B, which were also developed at Bell Laboratories.</p><p>The <strong>Combined Programming Language(CPL)</strong> was developed at Cambridge University in 1963 with the goal of developing a common programming language which can be used to solve different types of problems on various hardware platforms.  However it turned out to be too complex, hard to learn and difficult to implement.  Subsequently in 1967, a subset of CPL, <strong>Basic CPL(BCPL)</strong> was developed by <strong>Martin Richards</strong> incorporating only the essential features.  However it was not found to be sufficiently powerful.  Around the same time another subset of CPL, a language called <strong>B</strong> was developed by <strong>Ken Thompson</strong> at Bell Labs.  However it also turned out to be insufficient . Then, in 1972, Dennis Ritchie at Bell Labs developed the C language incorporating the best features of both BCPL and B.</p><p>C was largely confined to use within Bell Labs until 1978, when Brian Kernighan and Ritchie published a definitive description of the language . The <strong>Kerninghan and Ritchie description of C</strong> is commonly referred to as <em><strong>&#8216;K &amp;R C&#8217;</strong></em>.</p><p>Following the publication of &#8216;K&amp;R C&#8217;,computer professionals, impressed with C&#8217;s many desirable features, began to promote the use of C.  By the mid 1980&#8242;s the popularity of C had become widespread-many c compilers and interpreters had been written for computers of all sizes and many commercial application programs had been developed.  Moreover, many commercial software products that had originally been written in other languages were rewritten in C in order to take advantage of its efficiency and portability.</p><p>Early commercial implementations of C differed a little from Kerninghan and Ritchie&#8217;s original description, resulting in minor incompatibilities between different implementations.  As a result, <strong>the American National Standards Institute(ANSI committee X3J11)</strong>  developed a standardized definition of C.  Virtually all commercial compilers and interpreters adhere to the ANSI standard.  Many provide additional features of their own.</p><p><strong>C and Systems Programming:</strong></p><p>There are several features of C, which make it suitable for systems programming.  They are as follows:</p><ul><li>C is a machine independent and highly portable language.</li><li>It is easy to learn; it has only 28 keywords.</li><li>It has a comprehensive set of operators to tackle business as well as scientific applications with ease.</li><li>Users can create their own functions and add to the C library to perform a variety of tasks.</li><li>C language allows the manipulation of bits, bytes and addresses.</li><li>It has a large library of functions.</li><li>C operates on the same data types as the computer, so the codes generated are fast and efficient.</li></ul><p><strong>Structure of a C Program:</strong></p><p>Every C program consists of one or more modules called <strong><em>functions. </em></strong>One of the functions must be called <strong><em>main</em></strong>. The program will always begin by executing the <em>main</em> function, which may access other functions. The main function is normally,but not necessarily located at the beginning of the program. The group of statements within main( ) are executed sequentially. When the closing brace of main( ) is encountered, program execution stops and control is returned to the operating system.</p><p>Any other function defintions must be defined separately, either ahead or after main( ).  Each function must contain:</p><p>1.  A <strong><em>function heading</em></strong>, which consists of the <strong><em>function name</em></strong>, followed by an optional list of arguments, enclosed in parantheses.</p><p>2.  A <strong><em>return type</em></strong> written before the function name.  It denotes the type of data that the function will return to the program.</p><p>3.  A list of <strong><em>argument declarations</em></strong>, if arguments are included in the heading.</p><p>4.  A <strong><em>compound statement</em></strong>, which comprises the remainder of the function.</p><p>The arguments(also called parameters) are symbols that represent information being passed between the function and other parts of the program.</p><p>Each compound statement is enclosed between a pair of braces{ }.  The braces may contain one or more elementary statements (called <strong><em>expression statements</em></strong>) and other compound statements. Thus compound statements may be nested one within another.  Each expression statement must end with a semicolon(;).</p><p><strong><em>Comments (remarks)</em></strong> may appear anywhere within a program as long as they are enclosed within the delimiters /* and */.  Comments are used for documentation and are useful in identifying the program&#8217;s principal features or in explaining the underlying logic of various program features.</p><p><span
style="text-decoration: underline"><strong>Components of C Language:</strong></span></p><p>There are five main components of the C Language:-</p><p>1. <strong>The character set:</strong> C uses the uppercase letters A to Z, the lowercase letters a to z, the digits 0 to 9 and certain special characters as building blocks to form basic program elements(e. g.  constants, variables, expressions, statements etc. ).</p><p>2. <strong>Data Types:</strong> The C language is designed to handle five <em>primary data types, </em>namely, <em>character, integer, float, double and void;</em> and <em>secondary data types </em>like<em> array, pointer, structure, union and enum. </em></p><p><strong>3. </strong><strong>Constants:</strong> A constant<strong> </strong>is a fixed value entity that does not change its value throughout program execution.</p><p>4. <strong>Variables:</strong> A variable is an entity whose value can change during program execution.  They are used for storing input data or to store values generated as a result of processing.</p><p>5. <strong>Keywords:</strong> Keywords are <strong><em>reserved</em></strong> words which have been assigned specific meanings in the C language.  Keywords cannot be used as variable names.</p><p>The components of C language will be discussed in greater detail in the following articles.  This section gives only a brief introduction to the components of C.</p><p><strong>Example 1:</strong> The following program reads in the radius of a circle, calculates the area and then prints the result.</p><pre style="padding-left: 30px">/* program to calculate the area of a circle*/
#include&lt;stdio. h&gt; /*Library file access*/
#include&lt;conio. h&gt; /*Library file access*/
void main( )            /* Function Heading*/
    {
       float radius, area; /*Variable declarations*/
       /*Output Statement(prompt)*/
       printf("Enter the radius :");
      /*Input Statement*/
      scanf("%f", &amp;radius);
      /*Assignment Statement*/
      area = 3. 14159*radius*radius;
      /*Output Statement*/
      printf("Area of the circle :", area);
       getch( );
     }</pre><p
style="padding-left: 30px">Program output:-</p><p
style="padding-left: 30px">Enter the radius: 3</p><p
style="padding-left: 30px">Area of the circle: 28. 27431</p><p>The following points must be considered to understand the above program:-</p><p>1. The program is typed in lowercase. C is <strong>case sensitive</strong> i. e.  uppercase and lowercase characters are not equivalent in C. It is customary to type C instructions in lowercase.  Comments and messages(such as those printed using <code>printf() )</code> can be typed in anycase.</p><p>2. The first line is a comment that identifies the purpose of the program.</p><p>3. The instruction<strong> #include &lt;stdio. h&gt;</strong> contains a reference to a special file called stdio. h . This file contains the definition of certain functions required to read and print data such as printf() and scanf() . It is a header file and hence the extension . h.</p><p>4. Similarly <strong>#include &lt;conio. h&gt;</strong> links the file conio. h which is another header file that contains the definitions of functions used for reading and printing data at the console.  The function <strong><code>getch()</code></strong> is defined in conio. h.  # denotes a preprocessor directive.  More about this in a later article.</p><p>5. The instruction <strong>void main()</strong> is a heading for the function main( ).  The keyword <strong>void</strong> denotes the return type of main and indicates that the function does not return any value to the program after the program has finished executing. The empty parantheses ( ) after main indicates that this function does not include any arguments. Program execution always begins from main( ).</p><p>6.  The remaining five lines of the program are indented and enclosed in a pair of braces { }. These five lines comprise the compound statement within the function main( ).</p><p>7.  The instruction <strong>float radius, area;</strong>  is a <strong><em>variable declaration. </em></strong> It establishes the symbolic names &#8216;radius&#8217; and &#8216;area&#8217; as floating point variables. These variables can accept values of type &#8216;float &#8216; i. e numbers containing a decimal point or an exponent.</p><p>8.  The next four instructions are <strong><em> expression statements. </em></strong>The instruction <strong>printf(&#8220;Enter the radius :&#8221;);</strong> generates a request for information namely,the value for the radius.  This statement generates a prompt where the user enters the value .</p><p>9.  The value of the radius is read into (or stored in) the variable <em>radius </em>with the help of the scanf ( ) function.  The instruction<strong> scanf(&#8220;%f&#8221;, &amp;radius);</strong> is used for reading data.   &#8220;%f&#8221; is a <strong><em>conversion character</em></strong> which is used to accept a floating point value.</p><p>10.  The next instruction, <strong>area = 3. 14159*radius*radius;</strong> is called an <strong><em> assignment statement. </em></strong>This instruction calculates the area by using the value of radius entered by the user and assigns the value to the variable <em>area. </em></p><p>11.  The next printf( ) statement prints the message <em>Area of the circle </em>followed by the calculated area.</p><p>12.  The statement <strong>getch();</strong> is used to pause the screen so that you can read the output.  If getch( ) is not used the screen will just flash and go away.  This function waits for the user to input some character(as it accepts a character as input), after the program has finished executing. Any key present on the keyboard pressed by the user is accepted by the getch function as input and its ASCII value is returned to main( ).</p><p><strong>Example2:</strong> Below is a variation of the above program:</p><pre>/*program to calculate the area of a circle using a user defined function*/
#include &lt;stdio. h&gt;
#include &lt;conio. h&gt;
#define PI 3. 14159
float process(float radius);/*function prototype*/
void main()
    {
      float area,radius;
      printf("\n Enter the radius:");
      scanf("%f", &amp;radius);
      area= process(radius);
      printf("Area =%f", area);
      getch();
     }
float process( float r);
     {
     float a; /*local variable declaration*/
     a= PI*r*r;
     return(a);
     }</pre><p>This version utilizes a separate programmer defined function called <strong><em>process</em></strong>, to calculate the area.  Within this function, r is an argument (also called a parameter) that accepts the value of radius supplied to <strong><em> process</em></strong> from <strong><em>main</em></strong>, and a is the calculated result returned to main.  A reference to the function appears in main( ), within the statement area= process(radius);</p><p>In this statement, the value of area being returned from the function <em>process </em>is stored in the variable area.</p><p>The main function is preceeded by a function prototype, which indicates that there is a user defined function called process which is defined after main and that it accepts a floating point argument and returns a floating point value.  If the user defined function <em>process, </em>was defined before main( ), the function prototype would,generally, have not been required.</p><p>More explanation about this when I write about functions in a later article.</p><p>This program also contains a <strong><em>symbolic constant, PI, </em></strong>which represents the numeric value 3. 14159.  This is a form of shorthand that exists for the programmers convenience.  When the program is actually compiled, the symbolic constant will automatically be replaced by its numerical value.  The output of this program is the same as that of the previous program.</p><p>This article was a brief introduction, it gives an idea of C programming. The next article will talk about the fundamental concepts of C which include the C character set, Identifiers and keywords, data types in detail, constants,variables, variable declarations, expressions, statements and symbolic constants .</p> <span
id="pty_trigger"></span><div
style='padding:20px 0px 50px 0px;'><div
style='float:left;padding-left:40px;'><div
id='div-gpt-ad-1335489406190-0' style='width:300px; height:100px;'> <script type='text/javascript'>googletag.cmd.push(function() { googletag.display('div-gpt-ad-1335489406190-0'); });</script> </div></div><div
style='float:right;padding-right:40px;'><div
id='div-gpt-ad-1335489406190-1' style='width:300px; height:100px;'> <script type='text/javascript'>googletag.cmd.push(function() { googletag.display('div-gpt-ad-1335489406190-1'); });</script> </div></div><div
style='clear:both'></div></div><div
style='clear:both'></div><div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/SitepointFeed?a=XC5vO2nn0_0:zNUHHiaOhQw:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/SitepointFeed?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/SitepointFeed?a=XC5vO2nn0_0:zNUHHiaOhQw:qj6IDK7rITs"><img src="http://feeds.feedburner.com/~ff/SitepointFeed?d=qj6IDK7rITs" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/SitepointFeed?a=XC5vO2nn0_0:zNUHHiaOhQw:gIN9vFwOqvQ"><img src="http://feeds.feedburner.com/~ff/SitepointFeed?i=XC5vO2nn0_0:zNUHHiaOhQw:gIN9vFwOqvQ" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/SitepointFeed/~4/XC5vO2nn0_0" height="1" width="1"/>]]></content:encoded> <wfw:commentRss>http://www.sitepoint.com/an-introduction-to-c/feed/</wfw:commentRss> <slash:comments>5</slash:comments> <feedburner:origLink>http://www.sitepoint.com/an-introduction-to-c/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=an-introduction-to-c</feedburner:origLink></item> <item><title>Use Functions.php to Create an Advanced WordPress Theme</title><link>http://feedproxy.google.com/~r/SitepointFeed/~3/6PENxjJU5oY/</link> <comments>http://www.sitepoint.com/taking-advantage-of-the-functions-php-file-to-create-an-advanced-theme-with-user-defined-options/#comments</comments> <pubDate>Fri, 18 May 2012 15:00:33 +0000</pubDate> <dc:creator>Vladislav Davidzon</dc:creator> <category><![CDATA[wordpress]]></category> <guid isPermaLink="false">http://www.sitepoint.com/?p=53456</guid> <description><![CDATA[One of the best-kept secrets when it comes to WordPress theme design is the power that can be wielded by a well-crafted &#8220;functions.php&#8221; file. This file resides within the theme&#8217;s main folder and is separate from the side-wide functions file which WordPress uses to produce its basic and included functions. When put to good use, [...]]]></description> <content:encoded><![CDATA[<p></p><p>One of the best-kept secrets when it comes to WordPress theme design is the power that can be wielded by a well-crafted &#8220;functions.php&#8221; file. This file resides within the theme&#8217;s main folder and is separate from the side-wide functions file which WordPress uses to produce its basic and included functions. When put to good use, it can extend the functionality of both the theme itself, and the WordPress Dashboard.</p><p>One of the most common uses for this custom functions file is the creation of a theme-specific control panel that allows users to determine theme appearance options on their own, without so much as a single edit to the theme&#8217;s actual files. It&#8217;s the perfect option for novice users and has real benefits for theme developers.</p><h2>Why is it Important to Develop a Theme Control Panel?</h2><p>It&#8217;s certainly true that any WordPress theme can be designed strictly as a set of PHP template files without any interaction with the Dashboard at all. In fact, that&#8217;s how the majority of themes designed by the wider WordPress community currently function. But that&#8217;s limiting, especially given the appeal of this particular content management software to a large subset of first-time bloggers, web design novices, and newcomers to the idea of content management at large.<div
id='div-gpt-ad-1328644474660-10' style='width:728px; height:90px;'> <script type='text/javascript'>googletag.cmd.push(function() { googletag.display('div-gpt-ad-1328644474660-10'); });</script> </div></p><p>Using PHP arrays and functions to create a custom control panel gives a developer far wider credit and appeal among the 60&nbsp;million people who constitute the WordPress user base. And it ensures they won&#8217;t dump a theme because they can&#8217;t figure out how to customize things like the color of links, the image in the site&#8217;s masthead, or whether the sidebar resides on the left or right side of the page. Giving these new users a way to alter a theme using point-and-click options keeps them in the fold longer, guides them toward more advanced techniques, and contributes to the sterling reputation enjoyed by WordPress among both new and advanced users. Creating this control panel is easy; it takes just a few steps and some basic PHP knowledge to complete.</p><h2>Step 1: Create a &#8220;Functions.php&#8221; File to Do the Job</h2><p>If you&#8217;re like most WordPress theme designers, you&#8217;ve probably crafted one or more themes that simply don&#8217;t have a &#8220;functions.php&#8221; file because you saw no need to add functions to the existing set of WordPress features. In that case, it&#8217;s time to create a file in the appropriate directory so that the Dashboard can be told which settings to customize, how to customize them, and how users should be presented with their options. This functions file should be created in the following directory:</p><pre>
/public_html/wp-content/themes/relevant-theme-folder/
</pre><p>Feel free to create the file in a text editor, save it with a <code>.php</code> file extension, and then upload it to the server. This will allow for direct editing of the file, which is simply easier than managing the same file in both a remote and local location. When the file has been created and uploaded, open it for editing and proceed.</p><h2>Step 2: Define Theme Control Panel Variables for Easy Functions Coding</h2><p>The next step in the process is to start the new &#8220;functions.php&#8221; file with two variables that will ease the process of developing custom functions and settings input for users. After the starting PHP tag, two lines of code will be placed in the file:</p><pre>
$longname = "Advanced Theme with a Control Panel";
$formname = "advanced";
</pre><p>These two variables will be used throughout the Dashboard control panel page that is being created. The initial <code>$longname</code> variable should contain the name of the theme, identical to the theme&#8217;s name as determined in the opening lines of its &#8220;style.css&#8221; file. This will display as the title of the control panel page, the title of the link to the control panel&#8217;s page in the Dashboard sidebar, and in some other areas of the theme. The shorter <code>$formname</code> variable will be used to identify each settings selection form element on the control panel page, which is generated in the ensuing steps.</p><h2>Step 3: Getting Comfortable with PHP Arrays and Initializing the Beginning of the Function</h2><p>The entire process of specifying which settings can be customized will be done using a series of PHP arrays that define and fulfill certain variables. These arrays are identical in every way, except for the first series of arrays, which actually declares the page&#8217;s title to users and begins the process of printing the settings onto the control panel page:</p><pre>
$prefs = array (
  array ( "name" => $longname." Customization Settings",
          "type" => "title"),
  array ( "type" => "open"),
  &#8942;
</pre><p>In this array, the <code>$prefs</code> variable is defined using several variables and it&#8217;s available for use in the creation of PHP functions a few steps later. The title of the page is the first thing that we define using this array, and it uses the <code>$longname</code> variable for consistency. The text after <code>$longname</code> can be customized to a user&#8217;s desires, but remember that this title will have to be consistent in the sidebar link to the control panel, as well.</p><h2>Step 4: Defining a Customization for the Theme&#8217;s Display</h2><p>Next, we define an array for every single option that a user can customize, from header images to footer text and everything in between. The things that can be customized are entirely up to the theme developer, but it&#8217;s important to remember that a PHP array must be created for each option. Additionally, every array must include a number of variables and definitions that help print the options on the page and give their selection meaning:</p><pre>
array (
  "name" => "Homepage Welcome Text",
  "desc" => "This text will display immediately above entries to greet new visitors and inform them of the latest happenings going on at your website.",
  "id" => $formname."_hello",
  "type" => "text",
  "std" => "Welcome to my home on the internet! I've had some really popular posts lately, which you might want to check out. These posts are below. Enjoy your stay!",)
),
</pre><p>This is the only option array we will be defining, so it was closed with double parentheses and a comma. If this was only the first of many arrays, it would be closed with just one parentheses and trailed by a comma. Please keep this in mind, as an erroneous double-comma will close the entire array and lead to a large number of printed PHP errors on the administration page if there are arrays after this closing statement.</p><p>In the example above, several variables are defined that name the setting itself, describe its function, name the form element, and set the standard (or default) text to be displayed on a theme user&#8217;s homepage. The variables above work as follows:</p><ul><li>&#8220;name&#8221; is the printed name of the setting and must be a descriptive title for the form element.</li><li>&#8220;desc&#8221; describes what the setting customizes and why a user might wish to put their custom approach in print.</li><li>&#8220;id&#8221; is the identification of the HTML form element that is printed on the page, for database and CSS styling purposes.</li><li>&#8220;type&#8221; defines which kind of HTML element is being printed on the page, including checkboxes, radio buttons, text boxes, and drop-down selections.</li><li>&#8220;std&#8221; is the default setting for the user-customizable option. It can be the default option in a drop-down list, the checkbox or radio button selected by default, or the standard text placed into a text box that a user can rewrite or delete.</li></ul><p>Each of these variables must be defined uniquely from all the others in the same array. No form can have the same name, title, or ID. The type and default options can obviously be the same or similar, but there&#8217;s little reason for them to be and users may find themselves quite confused in that case.</p><p>When the array of options has been completed, it&#8217;s time to close up shop and print a simple line that brings the series of arrays to an end:</p><pre>
array("type" => "close"));
</pre><h2>Step 5: Turning a Bunch of Arrays into a Valid Control Panel Page</h2><p>The PHP arrays are the most important part of the process when it comes to defining user customizations. However, they are virtually useless unless they&#8217;re paired with a printed control panel page. That must be done with a complex PHP function that is placed in &#8220;functions.php&#8221; directly below the arrays themselves:</p><pre>
function advanced_customizations_page() {
  global $longname, $formname, $prefs;
  if ($_GET['page'] == basename(__FILE__)) {
    if ('save' == $_REQUEST['action']) {
      foreach ($prefs as $value) {
        update_option($value['id'], $_REQUEST[ $value['id'] ]);
      }
      foreach ($prefs as $value) {
        if (isset($_REQUEST[ $value['id'] ])) {
          update_option($value['id'], $_REQUEST[ $value['id'] ]);
        }
        else {
          delete_option($value['id']);
        }
      }
      header("Location: themes.php?page=functions.php&#038;saved=true");
      die;
    }
    else if ('reset' == $_REQUEST['action']) {
      foreach ($prefs as $value) {
        delete_option($value['id']);
      }
    header("Current location: themes.php?page=functions.php&#038;reset=true");
    die;
  }
}
add_menu_page($longname." Customization Settings", "".$longname." Customization Settings", 'edit_themes', basename(__FILE__), 'advanced_customizations_page');
function advanced_customizations_page() {
  global $longname, $formname, $prefs;
  if ($_REQUEST['saved']) echo '
<div id="message">
Success! '.$themename.' customization settings have been saved.
</div>
';
  if ($_REQUEST['reset']) echo '
<div id="message">
Success! '.$themename.' settings have been reset.
</div>
';
&#8942;
?>
</pre><p>The three functions above are essential to the process. The first one instructs the control panel to print the settings arrays onto the page and save the information into database cells, which are created on the fly. The second function creates a link in the Dashboard sidebar that leads to the new theme options page. And the final set of functions prints confirmation of user activity so that they&#8217;re not left to assume whether or not they&#8217;ve been successful in customizing their installed WordPress theme.</p><h2>Step 6: Printing Form Elements and Finishing the Last Steps</h2><p>The hard work of PHP coding is now effectively finished, but the production of HTML must now be completed. Every customized WordPress options page is styled the same way; the WordPress software wraps these pages in a <code>div</code> tag:</p><pre>
<div id="wrap">
</div>
</pre><p>This tells the standard WordPress stylesheet to apply to the text boxes, drop-down boxes, textual elements, and other design cues on the page. Within this HTML, both the <code>$longname</code> and <code>$formname</code> variables can be used for expediency in producing code and uniquely-named form elements. Each type of form element (text, select, checkbox, etc.) must be individually styled and surrounded by the following PHP tag:</p><pre>
< ?php case "checkbox": ?>
</pre><p>Code is placed within this tag to style checkboxes, and then the code is closed with another tag that tells the software to move on to the next set of HTML code if a checkbox is not the current element being displayed and styled:</p><pre>
< ?php break; case "select": ?>
</pre><p>With these tags in place, and every HTML form element completely styled, the custom themes options page is now complete. Be sure to test the completed page for HTML or PHP errors, and make sure that the preferences defined in the Dashboard are being reflected on the page&#8217;s index and other templates after selection. If everything checks out, the process is complete and the results can be shared with the wider WordPress community.</p> <span
id="pty_trigger"></span><div
style='padding:20px 0px 50px 0px;'><div
style='float:left;padding-left:40px;'><div
id='div-gpt-ad-1335489406190-0' style='width:300px; height:100px;'> <script type='text/javascript'>googletag.cmd.push(function() { googletag.display('div-gpt-ad-1335489406190-0'); });</script> </div></div><div
style='float:right;padding-right:40px;'><div
id='div-gpt-ad-1335489406190-1' style='width:300px; height:100px;'> <script type='text/javascript'>googletag.cmd.push(function() { googletag.display('div-gpt-ad-1335489406190-1'); });</script> </div></div><div
style='clear:both'></div></div><div
style='clear:both'></div><div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/SitepointFeed?a=6PENxjJU5oY:4_rLGO4DzvY:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/SitepointFeed?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/SitepointFeed?a=6PENxjJU5oY:4_rLGO4DzvY:qj6IDK7rITs"><img src="http://feeds.feedburner.com/~ff/SitepointFeed?d=qj6IDK7rITs" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/SitepointFeed?a=6PENxjJU5oY:4_rLGO4DzvY:gIN9vFwOqvQ"><img src="http://feeds.feedburner.com/~ff/SitepointFeed?i=6PENxjJU5oY:4_rLGO4DzvY:gIN9vFwOqvQ" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/SitepointFeed/~4/6PENxjJU5oY" height="1" width="1"/>]]></content:encoded> <wfw:commentRss>http://www.sitepoint.com/taking-advantage-of-the-functions-php-file-to-create-an-advanced-theme-with-user-defined-options/feed/</wfw:commentRss> <slash:comments>1</slash:comments> <feedburner:origLink>http://www.sitepoint.com/taking-advantage-of-the-functions-php-file-to-create-an-advanced-theme-with-user-defined-options/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=taking-advantage-of-the-functions-php-file-to-create-an-advanced-theme-with-user-defined-options</feedburner:origLink></item> <item><title>What’s New in Chrome 19</title><link>http://feedproxy.google.com/~r/SitepointFeed/~3/qTmJU-qF1q8/</link> <comments>http://www.sitepoint.com/chrome-19-whats-new/#comments</comments> <pubDate>Thu, 17 May 2012 17:24:05 +0000</pubDate> <dc:creator>Craig Buckler</dc:creator> <category><![CDATA[CSS3]]></category> <category><![CDATA[Discussion]]></category> <category><![CDATA[Gems]]></category> <category><![CDATA[JavaScript]]></category> <category><![CDATA[News & Trends]]></category> <category><![CDATA[Open Source]]></category> <category><![CDATA[Opinion]]></category> <category><![CDATA[Web Tech]]></category> <category><![CDATA[browser]]></category> <category><![CDATA[chrome]]></category> <category><![CDATA[Google Tutorials & Articles]]></category> <guid isPermaLink="false">http://www.sitepoint.com/?p=54727</guid> <description><![CDATA[<img
width="50" height="50" src="http://www.sitepoint.com/wp-content/uploads/1/files/2011/05/518-chrome-11-50x50.png" class="attachment-thumbnail wp-post-image" alt="518-chrome-11" title="518-chrome-11" />Craig looks at several interesting features which have appeared in Google Chrome 19.]]></description> <content:encoded><![CDATA[<img
width="50" height="50" src="http://www.sitepoint.com/wp-content/uploads/1/files/2011/05/518-chrome-11-50x50.png" class="attachment-thumbnail wp-post-image" alt="518-chrome-11" title="518-chrome-11" /><p></p><p>I doubt you noticed but Chrome 19 was released this week. I rarely mention Chrome&#8217;s updates because, well, they&#8217;re rarely worth mentioning. However, I&#8217;ve discovered a few hidden gems in the latest browser&hellip;</p><h2>Tab Syncing</h2><p>The big new feature is tab syncing. If you&#8217;re using Chrome on two or more PCs/smartphones, you <em>should</em> see an <em>&#8220;Other devices&#8221;</em> link on the new tab page. Click it and you can open synchronized links. I say <em>&#8220;should&#8221;</em> because I haven&#8217;t been able to get it working.</p><p>Tab syncing has been available in Firefox for a while so I&#8217;m surprised it&#8217;s taken quite so long to appear in Chrome. Hopefully, you&#8217;ll have better luck than I did.</p><h2>CSS3 calc() Support</h2><p>The webkit team has finally implemented one of my favorite CSS3 features: the little-known <a
href="http://www.sitepoint.com/css3-calc-function/">calc() function</a>. It allows you to define calculated dimensions, e.g.</p><pre><code>
#myelement { width: calc(50% - 2em + 4px); }
</code></pre><p>Chrome supports calc() with the -webkit prefix. Firefox uses -moz and IE9 is happy without prefixes. To use it effectively, you&#8217;ll need fallback code such as:<div
id='div-gpt-ad-1328644474660-10' style='width:728px; height:90px;'> <script type='text/javascript'>googletag.cmd.push(function() { googletag.display('div-gpt-ad-1328644474660-10'); });</script> </div></p><pre><code>
#myelement
{
	width: 46%;
	width: -webkit-calc(50% - 2em + 4px);
	width: -moz-calc(50% - 2em + 4px);
	width: -o-calc(50% - 2em + 4px);
	width: calc(50% - 2em + 4px);
}
</code></pre><h2>Combined Settings Page</h2><p>Choosing tool &gt; Settings now displays a side menu with History, Extensions, Settings and Help. The Help page provides a couple of links and the update checker which normally appears on the &#8220;About&#8221; dialog <em>(will that disappear soon?)</em></p><h2>New JavaScript/ECMAScript 5.1 (Harmony) Features</h2><p>A number of <a
href="http://blog.chromium.org/2012/02/future-of-javascript-take-peek-today.html">experimental JavaScript features</a> have made their way from the Harmony specification into Chrome&#8217;s V8 engine. However, they&#8217;re not available by default &#8212; you&#8217;ll need to &#8220;Enable Experimental JavaScript&#8221; in <a
href="http://www.sitepoint.com//flags" class="broken_link">chrome://flags</a>. Language structures such as collections and proxies look great, but it&#8217;ll be some time before they&#8217;re available in all browsers.</p><h2>Security and Bug Fixes</h2><p>21 issues have been fixed in Chrome 19 and Google has paid almost $15,000 to eagle-eyed security hackers.</p><p>Chrome has remained fast and stable. It looks set to knock IE from the top of the <a
href="http://www.sitepoint.com/browser-trends-may-2012/">browser usage chart</a> during the summer of 2012. I&#8217;m not convinced any other vendor can prevent Google&#8217;s domination of the web and the software we use to access it.</p> <span
id="pty_trigger"></span><div
style='padding:20px 0px 50px 0px;'><div
style='float:left;padding-left:40px;'><div
id='div-gpt-ad-1335489406190-0' style='width:300px; height:100px;'> <script type='text/javascript'>googletag.cmd.push(function() { googletag.display('div-gpt-ad-1335489406190-0'); });</script> </div></div><div
style='float:right;padding-right:40px;'><div
id='div-gpt-ad-1335489406190-1' style='width:300px; height:100px;'> <script type='text/javascript'>googletag.cmd.push(function() { googletag.display('div-gpt-ad-1335489406190-1'); });</script> </div></div><div
style='clear:both'></div></div><div
style='clear:both'></div><div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/SitepointFeed?a=qTmJU-qF1q8:o5OQPmcJl_4:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/SitepointFeed?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/SitepointFeed?a=qTmJU-qF1q8:o5OQPmcJl_4:qj6IDK7rITs"><img src="http://feeds.feedburner.com/~ff/SitepointFeed?d=qj6IDK7rITs" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/SitepointFeed?a=qTmJU-qF1q8:o5OQPmcJl_4:gIN9vFwOqvQ"><img src="http://feeds.feedburner.com/~ff/SitepointFeed?i=qTmJU-qF1q8:o5OQPmcJl_4:gIN9vFwOqvQ" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/SitepointFeed/~4/qTmJU-qF1q8" height="1" width="1"/>]]></content:encoded> <wfw:commentRss>http://www.sitepoint.com/chrome-19-whats-new/feed/</wfw:commentRss> <slash:comments>5</slash:comments> <feedburner:origLink>http://www.sitepoint.com/chrome-19-whats-new/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=chrome-19-whats-new</feedburner:origLink></item> <item><title>iOS to IE10 Metro: Building Cross-Browser Plugin-Free Experiences</title><link>http://feedproxy.google.com/~r/SitepointFeed/~3/KP6b20CH-Ok/</link> <comments>http://www.sitepoint.com/ios-to-ie10-metro-building-cross-browser-plugin-free-experiences/#comments</comments> <pubDate>Wed, 16 May 2012 15:00:34 +0000</pubDate> <dc:creator>Rey Bango</dc:creator> <category><![CDATA[CSS3]]></category> <category><![CDATA[HTML5]]></category> <category><![CDATA[HTML5 Dev Center]]></category> <guid isPermaLink="false">http://www.sitepoint.com/?p=53753</guid> <description><![CDATA[<img
width="48" height="50" src="http://www.sitepoint.com/wp-content/uploads/1/files/2012/04/rb4-48x50.png" class="attachment-thumbnail wp-post-image" alt="rb4" title="rb4" />If you’ve built a plugin-free browsing experience for the iPad, a few changes will make it ready for the new IE10 plugin-free experience on Windows 8. As more browsers adopt the plugin-free approach, now is a good time to start thinking about it. I’ll show you how to do this in a few steps by [...]]]></description> <content:encoded><![CDATA[<img
width="48" height="50" src="http://www.sitepoint.com/wp-content/uploads/1/files/2012/04/rb4-48x50.png" class="attachment-thumbnail wp-post-image" alt="rb4" title="rb4" /><p></p><p>If you’ve built a plugin-free browsing experience for the iPad, a few changes will make it ready for the new <a
href="http://blogs.msdn.com/b/ie/archive/2011/08/31/browsing-without-plug-ins.aspx">IE10 plugin-free experience on Windows 8</a>. As more browsers adopt the plugin-free approach, now is a good time to start thinking about it. I’ll show you how to do this in a few steps by writing code that works well in all modern browsers.</p><p>Today we’re going to work with a <a
href="http://www.msnbc.msn.com/id/22825103/vp/46802160#46802160">MSNBC plugin-free experience</a> for rich media. It breaks down to two things: styles and scripts.</p><p>To modify the files of MSNBC, I will be using a proxy application known as Fiddler. You can download this tool from <a
href="http://fiddler2.com/fiddler2/">http://fiddler2.com</a>. This tool allows me to modify remote files as though they were on my local machine. If you have direct access to your own site, you can ignore Fiddler, and work directly with your files. Fiddler provides a great way for testing changes without the risk of breaking your live site.</p><h2>Step 1: Declare Standards Mode and Valid Markup for Modern Browsers</h2><p>In order to use the HTML5 elements that we’ll be utilizing below, you’ll first need to ensure that you are operating in standards mode. One way to do this is to include the HTML5 doctype at the top of your document:<div
id='div-gpt-ad-1328644474660-10' style='width:728px; height:90px;'> <script type='text/javascript'>googletag.cmd.push(function() { googletag.display('div-gpt-ad-1328644474660-10'); });</script> </div></p><pre>
&lt;!DOCTYPE html&gt;
</pre><h2>Step 2: Update your CSS Vendor Prefixes</h2><p>The CSS language is undergoing a lot of change as new features are suggested, updated, and standardized. In order to allow developers to learn these new features, browser vendors typically offer experimental implementations via prefixed properties.</p><p>A key part of using vendor prefixes responsibly is to ensure that prefixes from each vendor are included in your site to allow for the broadest level of feature support. In many cases, especially when building an iPad-centric site, you may focus solely on <code>-webkit</code> properties, omitting the prefixes that target other browsers such as <code>-o</code>, <code>-ms</code>, and <code>-moz</code>. The end result of this is that you greatly limit the target devices that can render your plugin-free site as well as provide a degraded experience for users of other modern browsers, many of which could serve up equally engaging functionality.</p><p>For instance, we find the following <a
href="http://www.msnbc.msn.com/id/45230852/a12">on MSNBC</a>:</p><pre>
background: -webkit-gradient(
  linear,
  left top,
  left bottom,
  color-stop(1, rgba(192,192,192,.6)),
  color-stop(0.5, rgba(0,0,0,.6))
);
</pre><p>With the growing trend towards an HTML5 plugin-free experience, it’s important to expand these rules to provide the vendor prefixes of other major browsers as well:</p><pre>
background: -webkit-linear-gradient(
  top, rgba( 0, 0, 0, 0.0 ) 0%, rgba( 0, 0, 0, 0.6 ) 50% );
background: -moz-linear-gradient(
  top, rgba( 0, 0, 0, 0.0 ) 0%, rgba( 0, 0, 0, 0.6 ) 50% );
background: -ms-linear-gradient(
  top, rgba( 0, 0, 0, 0.0 ) 0%, rgba( 0, 0, 0, 0.6 ) 50% );
background: -o-linear-gradient(
  top, rgba( 0, 0, 0, 0.0 ) 0%, rgba( 0, 0, 0, 0.6 ) 50% );
background: linear-gradient(
  top, rgba( 0, 0, 0, 0.0 ) 0%, rgba( 0, 0, 0, 0.6 ) 50% );
</pre><p>While more verbose, the benefits to broad browser feature support certainly outweigh the extra typing involved. In addition, there are a number of great tools that can break down this workload, such as <a
href="http://sass-lang.com/">SASS</a> and <a
href="http://compass-style.org/">Compass</a>, <a
href="http://leaverou.github.com/prefixfree/">-prefix-free</a>, or even <a
href="http://www.asp.net/web-forms/videos/visual-studio-vnext/visual-studio-vnext-videos-css-editor-snippets">CSS Snippets</a> in the upcoming Visual Studio 2011.</p><p>Also, if you’re working predominantly in JavaScript and would like to save time determining which features are supported by your client’s browser, review the instructions in <a
href="http://blogs.msdn.com/b/ie/archive/2011/10/28/a-best-practice-for-programming-with-vendor-prefixes.aspx">A Best Practice for Programming with Vendor Prefixes</a> on the IEBlog.</p><h2>Step 3: Get Rid of Browser Sniffing Methods</h2><p>There are two methods used to determine the capabilities of the user’s browser and device. One method, which unfortunately is somewhat popular, is browser sniffing. This method consists of examining the navigator object for certain patterns or values:</p><pre>
if ( navigator.userAgent.indexOf("iPad") &gt; -1 ) {
  // Load HTML5 Experience
} else {
  // Load Flash Experience
}
</pre><p>The above code looks at the user agent string for the value “iPad”, and if found delivers a plugin-free HTML5 experience. Otherwise, it’s assumed you are on a device that has Flash installed. This will result in a broken experience for non-iPad users who are browsing with plugins disabled, even though their browser is capable of handling HTML5 features.</p><p>Here is an attempt to find the version of Internet Explorer:</p><pre>
if ( tests.IE ) {
  j = /msie.(\d\.\d+)/i;
  k = navigator.userAgent.match(j)[1];
}
</pre><p>The user agent string is tested for a pattern that attempts to target the version number. This pattern looks for a single digit, followed by a period, followed by any number of additional digits. While this test will find values like “MSIE 8.0” and “MSIE 9.0”, it will not identify the latest version of Internet Explorer, which identifies itself as “MSIE 10.0”, as only one digit is expected before the period.</p><p>These are just a couple examples of why browser sniffing is not a best practice. The user agent string is not immutable&mdash;it is a read-write value that is easily changed by plugins, or even the user. Most modern browsers include the ability to easily change this value from their development tools, which some users take advantage of to get around poorly-developed websites.</p><p>If we disable plugins, or visit MSNBC from a device/browser that doesn’t have Flash, we would expect it to attempt a plugin-free experience. Unfortunately, this is not the case. Rather than seeing an HTML5 experience, we’re instead asked to download Flash. This is because the site puts the user in one of two categories: an iPad user, or a Flash-enabled user.</p><p><img
src="http://www.sitepoint.com/wp-content/uploads/1/files/2012/04/rb1.png" alt="MSNBC download Flash message" title="MSNBC download Flash message" class="alignnone size-full wp-image-53761" /></p><h3>Feature Detection</h3><p>Rather than trying to guess what a browser is capable of by sniffing its user agent string (which will fail you eventually), it is much wiser to actually test features directly in the browser. If you wanted to test the browser’s ability to deliver video and audio via HTML5, you could actually attempt to create these elements via JavaScript, and see if the browser understands them. This practice is called <em>feature detection</em>:</p><pre>
if ( !!document.createElement(“video”).canPlayType ) {
  // Load HTML5 Video
} else {
  // Load Flash Video
}
</pre><p>In the above example, we start by testing whether the <code>canPlayType</code> method exists on our newly-created <code>video</code> tag. We’re using double-negation to cast the response to a Boolean. If the browser understands what a <code>video</code> element is, the <code>canPlayType</code> method will be present. If the video element is unknown to the browser, the <code>canPlayType</code> method will not exist. If this test passes, we load our HTML5 video. If the test does not pass, we attempt to load Flash. Deeper feature detection could take place here, because Flash may not be on the machine, or may be disabled.</p><p>Feature detection is the preferred method of determining what a browser is capable of, as there is no guesswork involved. If the browser passes properly-constructed tests, it absolutely supports the features you would like to use.</p><p>Many great tools exist to provide feature tests for you. Once such tool, which provides over 40 tests, is <a
href="http://www.modernizr.com/">Modernizr</a>. This tool creates a global object called “<code>Modernizr</code>” which contains the results of your tests. With Modernizr, testing for HTML5 video support is extremely easy:</p><pre>
if ( Modernizr.video ) {
  // Load HTML5 Video
}
</pre><p>MSNBC engages in browser sniffing to see if the device accessing the page is an iPad or not. Our first step is to remove the browser sniffing code, and replace it with feature detection code.</p><p>Before we can modify browser sniffing code, we first need to locate it. While in Internet Explorer, pressing F12 will pull up our <a
href="http://msdn.microsoft.com/en-us/library/gg589512(v=vs.85).aspx">Developer Tools</a>. Within the tools, open the Script tab and do a search for “userAgent”. This search will seek out any instance of this property name in all of the site’s script files. We’re interested in the result from line 41 of <a
href="http://www.msnbc.msn.com/id/37156949/">http://www.msnbc.msn.com/id/37156949/</a>.</p><p><img
src="http://www.sitepoint.com/wp-content/uploads/1/files/2012/04/rb2.png" alt="MSNBC download Flash message with Internet Explorer Developer Tools open" title="MSNBC download Flash message with Internet Explorer Developer Tools open" class="alignnone size-full wp-image-53762" /></p><p>Now that we know what we want to edit, we can open up Fiddler and load up our traffic. Once Fiddler is opened, perform a hard-refresh (Ctrl+F5 in IE) on the MSNBC page. This results in all of the page sessions being listed in Fiddler.</p><p><img
src="http://www.sitepoint.com/wp-content/uploads/1/files/2012/04/rb3.png" alt="Fiddler - HTTP Debugging Proxy on MSNBC page" title="Fiddler - HTTP Debugging Proxy on MSNBC page" class="alignnone size-full wp-image-53763" /></p><p>Looking carefully, you’ll notice our resource is the third from the top. Next we can set up an <a
href="http://fiddler2.com/Fiddler2/help/AutoResponder.asp">AutoResponder</a> for this session file so that anytime it is requested, a custom file is substituted in the place of the server response:</p><ol><li>Right-click this session and select “Decode Selected Sessions” from the context menu.</li><li>Select the AutoResponder tab on the right.</li><li>Click the “Enable automatic responses” checkbox in the AutoResponder tab.</li><li>Drag the selected session from the left panel into the AutoResponder tab.</li></ol><p>At this point, you should have an entry within your AutoResponder tab with the following rules:</p><ul><li>If URI matches: EXACT:http://www.msnbc.msn.com/id/37156949/</li><li>Then respond with: *200-SESSION_3</li></ul><p>Right-click the entry in the AutoResponder and select <em>Edit Response</em>. In the popup that follows, switch to the SyntaxView tab where we will find the source for this file. As expected, line 41 contains our browser sniffing code:</p><pre>
if ( !(navigator.userAgent.toLowerCase().indexOf("ipad")>-1) ){
  // Flash Experience
}
</pre><p>Rather than test the contents of the <code>userAgent</code>, we’re going to instead look for support for the HTML5 <code>video</code> tag. Switch the above condition to the following:</p><pre>
if ( !document.createElement("video").canPlayType ) {
  // Flash Experience
}
</pre><p>This test checks to see if we cannot use the <code>video</code> element. If <code>canPlayType</code> comes back as undefined, it will be cast to true and the first code block will be entered, setting up the Flash experience.</p><h2>Step 4: Update Touch and Pointer Events</h2><p>Safari supports both a touch event model and a mouse event model. Internet Explorer 10 groups touch, mouse, and stylus events into a single abstract item known as a <code>pointer</code>. In fact, Internet Explorer 10 is the first browser to work for all input types, across all devices. This abstraction cuts down drastically on the amount of effort involved to determine which event model you ought to bind to and how to detect user-interaction. This pointer is then handled through MSPointer events. If necessary, you can determine the type of pointer by accessing the <code>pointerType</code> property.</p><p><img
src="http://www.sitepoint.com/wp-content/uploads/1/files/2012/04/rb4.png" alt="Diagram of funnel containing Pen, Touch, and Mouse, leading to Pointer" title="Diagram of funnel containing Pen, Touch, and Mouse, leading to Pointer" class="alignnone size-full wp-image-53764" /></p><p>As Internet Explorer doesn’t support Apple’s proprietary event model, which includes touch events like <code>touchstart</code>, <code>touchmove</code>, and <code>touchend</code>, MSNBC’s event listeners will need to be amended to listen for MSPointer events like <code>MSPointerDown</code>, <code>MSPointerUP</code>, and <code>MSPointerMove</code>.</p><p>Due to the difference in event model implementations, use a feature detection tool like Modernizr or code like this to target all major event models:</p><pre>
if (window.navigator.msPointerEnabled) {
  myCanvas.addEventListener("MSPointerMove", paint, false);
} else {
  myCanvas.addEventListener("mousemove", paint, false);
  myCanvas.addEventListener(“touchmove”, paint, false);
}
</pre><p>MSNBC only supports touch events, which we will need to change so that visitors who happen to be using a mouse can still interact with the page. Our events are tied up in <a
href="http://www.msnbc.msn.com/id/43662671/15">http://www.msnbc.msn.com/id/43662671/15</a>:</p><pre>
document.addEventListener("touchstart", touchHandler, false);
document.addEventListener("touchmove", touchHandler, false);
document.addEventListener("touchend", touchHandler, false);
</pre><p>We’re going to update this to include the MSPointer events as well:</p><pre>
if (window.navigator.msPointerEnabled) {
  document.addEventListener("MSPointerDown", touchHandler, false);
  document.addEventListener("MSPointerMove", touchHandler, false);
  document.addEventListener("MSPointerUp", touchHandler, false);
} else {
  document.addEventListener("touchstart", touchHandler, false);
  document.addEventListener("touchmove", touchHandler, false);
  document.addEventListener("touchend", touchHandler, false);
  document.addEventListener("mousedown", touchHandler, false);
  document.addEventListener("mousemove", touchHandler, false);
  document.addEventListener("mouseup", touchHandler, false);
}
</pre><p>First, we’re checking for the presence of pointers. Since the MSPointer covers the mouse, fingers, and pens, we don’t need anything else besides them. We fall back, if necessary, to provide both touch and mouse events.</p><p>Next, we need to create cases for these event types in <a
href="http://www.msnbc.com/id/44937131/">http://www.msnbc.com/id/44937131/</a>. Currently, MSNBC starts with the following:</p><pre>
if ( event.type == "touchstart" ) {
  /* Start drag logic */
} else
if ( event.type == "touchmove" ) {
  /* Drag logic */
} else
if ( event.type == "touchend" ) {
  /* Complete drag logic */
}
</pre><p>We’ll modify this to listen for all of the registered event types:</p><pre>
if ( event.type.match( /(down|start)$/i ) ) {
  /* Start drag logic */
} else
if ( event.type.match( /move$/i ) ) {
  /* Drag logic */
} else
if ( event.type.match( /(up|end)$/i ) ) {
  /* Complete drag logic */
}
</pre><p>The above uses the <code>match</code> method and a series of regular expressions to determine which event was raised. If the event raised ends with a case-insensitive “down” or “start”, we begin our drag code. If the event ends with a case-insensitive “move”, we perform the actual drag logic itself. And lastly, if the event ends with a case-insensitive “up” or “end”, we end our dragging event. Note: other events may be caught here as well, like <code>onresizeend</code> and <code>keyup</code>. Be sure to consider this in your project.</p><p>The above is an implementation of Ted Johnson’s solution in <a
href="http://blogs.msdn.com/b/ie/archive/2011/10/19/handling-multi-touch-and-mouse-input-in-all-browsers.aspx">Handling Multi-touch and Mouse Input in All Browsers</a>.</p><p>The drag logic itself initially relies upon the <code>event.targetTouches</code> <a
href="https://developer.mozilla.org/en/DOM/TouchList">TouchList</a>. This member does not exist in Internet Explorer. The drag logic attempts to gather the <code>pageX</code> and <code>pageY</code> properties from the first item in the <em>TouchList</em>, however, in Internet Explorer these values are found directly on the <code>event</code> object:</p><pre>
var curX = event.targetTouches[0].pageX;
</pre><p>Using the logical <code>OR</code> operator, I instruct <code>curX</code> to hold the value of <code>event.pageX</code> as long as <code>event.pageX</code> is present on the <code>event</code> object. If this property is not found, look within the <code>targetTouches</code> list:</p><pre>
var curX = event.pageX || event.targetTouches[0].pageX;
</pre><p>If <code>event.pageX</code> is not found, we fall back to assigning the value of <code>targetTouches[0].pageX</code> to our variable.</p><p>Another important item to keep in mind is that this site initially responds to <code>touchmove</code>. When this event is raised while touching the playlist, the code attempts to reposition the playlist based upon your touch movement. There is no hovering when it comes to touch&mdash;you’re either touching, or you’re not.</p><p>Now that we have mouse events tied into this logic, we have introduced the possibility for hovering. So while <code>touchmove</code> is free to reposition our playlist when it is over the playlist, we don’t want to do the same for <code>mousemove</code>. In fact, we only want the <code>mousemove</code> event to reposition the playlist when the mouse button is pressed.</p><p>For further reading, and examples on how to target all browsers, see <a
href="http://blogs.msdn.com/b/ie/archive/2011/10/19/handling-multi-touch-and-mouse-input-in-all-browsers.aspx">Handling Multi-touch and Mouse Input in All Browsers</a>.</p><h2>Testing Both Experiences</h2><p>Recall our feature detection from earlier, how we first check to see if HTML5 video support is in the user’s browser. If it is, we give them HTML5. If it is not, we give them Flash. One easy way to test our work is to use a browser, or document mode, that doesn’t support HTML5 features. This is very easy to test with Internet Explorer:</p><ol><li>Press F12 to reveal the Developer Tools</li><li>Change your Document Mode to Internet Explorer 7 Standards</li><li>Refresh the page</li></ol><p>If our feature detection condition was written properly, you should now be watching a Flash-based presentation. Switching your <a
href="http://blogs.msdn.com/b/ie/archive/2010/06/16/ie-s-compatibility-features-for-site-developers.aspx">Document Mode</a> back into Internet Explorer 9 Standards (or “Standards” if you’re using IE10), will return you to the HTML5 experience.</p><h2>Get it Done!</h2><p>Hopefully this post helps to define the types of changes that will allow your iOS site to work properly in IE10 Metro and other plugin-free environments. By including best practices such as feature detection and responsibly using vendor prefixes for great new features, you should be able to provide your users with a great experience, regardless of which browser or device they’re using. To assist with testing in other plugin-free environments, download Internet Explorer 10 (currently available only in the Windows 8 CP) and begin testing today!</p> <span
id="pty_trigger"></span><div
style='padding:20px 0px 50px 0px;'><div
style='float:left;padding-left:40px;'><div
id='div-gpt-ad-1335489406190-0' style='width:300px; height:100px;'> <script type='text/javascript'>googletag.cmd.push(function() { googletag.display('div-gpt-ad-1335489406190-0'); });</script> </div></div><div
style='float:right;padding-right:40px;'><div
id='div-gpt-ad-1335489406190-1' style='width:300px; height:100px;'> <script type='text/javascript'>googletag.cmd.push(function() { googletag.display('div-gpt-ad-1335489406190-1'); });</script> </div></div><div
style='clear:both'></div></div><div
style='clear:both'></div><div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/SitepointFeed?a=KP6b20CH-Ok:21kHUJRglUk:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/SitepointFeed?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/SitepointFeed?a=KP6b20CH-Ok:21kHUJRglUk:qj6IDK7rITs"><img src="http://feeds.feedburner.com/~ff/SitepointFeed?d=qj6IDK7rITs" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/SitepointFeed?a=KP6b20CH-Ok:21kHUJRglUk:gIN9vFwOqvQ"><img src="http://feeds.feedburner.com/~ff/SitepointFeed?i=KP6b20CH-Ok:21kHUJRglUk:gIN9vFwOqvQ" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/SitepointFeed/~4/KP6b20CH-Ok" height="1" width="1"/>]]></content:encoded> <wfw:commentRss>http://www.sitepoint.com/ios-to-ie10-metro-building-cross-browser-plugin-free-experiences/feed/</wfw:commentRss> <slash:comments>0</slash:comments> <feedburner:origLink>http://www.sitepoint.com/ios-to-ie10-metro-building-cross-browser-plugin-free-experiences/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=ios-to-ie10-metro-building-cross-browser-plugin-free-experiences</feedburner:origLink></item> <item><title>Two New Proposals to Solve the CSS3 Vendor Prefix Crisis</title><link>http://feedproxy.google.com/~r/SitepointFeed/~3/jvswTdgA9NU/</link> <comments>http://www.sitepoint.com/css3-vendor-prefix-crisis-solutions-2/#comments</comments> <pubDate>Tue, 15 May 2012 15:41:07 +0000</pubDate> <dc:creator>Craig Buckler</dc:creator> <category><![CDATA[CSS Tutorials]]></category> <category><![CDATA[CSS3]]></category> <category><![CDATA[Discussion]]></category> <category><![CDATA[HTML & CSS]]></category> <category><![CDATA[HTML5]]></category> <category><![CDATA[News & Trends]]></category> <category><![CDATA[Web Tech]]></category> <category><![CDATA[CSS]]></category> <category><![CDATA[HTML5 Dev Center]]></category> <category><![CDATA[HTML5 Tutorials & Articles]]></category> <category><![CDATA[vendor prefixes]]></category> <guid isPermaLink="false">http://www.sitepoint.com/?p=54609</guid> <description><![CDATA[<img
width="50" height="50" src="http://www.sitepoint.com/wp-content/uploads/1/files/2012/02/641-css-vendor-prefix-crisis-50x50.jpg" class="attachment-thumbnail wp-post-image" alt="641-css-vendor-prefix-crisis" title="641-css-vendor-prefix-crisis" />Craig discusses two new proposals which could prevent the CSS3 vendor prefix catastrophe before it begins.]]></description> <content:encoded><![CDATA[<img
width="50" height="50" src="http://www.sitepoint.com/wp-content/uploads/1/files/2012/02/641-css-vendor-prefix-crisis-50x50.jpg" class="attachment-thumbnail wp-post-image" alt="641-css-vendor-prefix-crisis" title="641-css-vendor-prefix-crisis" /><p></p><p>Web developers have been concerned about the <a
href="http://www.sitepoint.com/w3c-css-webkit-prefix-crisis/">vendor prefix crisis</a> since February 2012. To summarize the issue, this is what should happen in an ideal world:</p><ol><li>Vendors implement experimental CSS3 properties using their own prefix, e.g. -webkit-transform, -moz-transform, -ms-transform, -o-transform.</li><li>Developers can use the technologies today without breaking cross-browser compatibility. Properties can be listed with their prefixed and unprefixed names to ensure they work everywhere.</li><li>Once a property becomes a W3C recommendation, all browser vendors can provide a stable unprefixed property, e.g. transform.</li><li>Optionally, developers can remove the prefixed properties from their stylesheets. However, it&#8217;s not strictly necessary if the unprefixed property is defined last and CSS cascade rules apply.</li></ol><p>This is what occurs in the real world:</p><ol><li>Vendors implement experimental CSS3 properties using their own prefix. In some cases, vendors promote them as an HTML5 <em>&#8220;standard&#8221;</em> even if they&#8217;re device-specific or never submitted to the W3C.</li><li>Some developers use the proprietary property from a single vendor, e.g. only -webkit-transform. This might be owing to ignorance, laziness or because they&#8217;re testing a limited number of devices.</li><li>Once a property becomes a W3C recommendation, all browser vendors can provide a stable unprefixed property, e.g. transform&hellip;</li><li>but developers neglect to change their stylesheets. The site looks good in some browsers but worse in others even when they support the standard W3C specification.</li><li>The vendors become concerned and add support for other prefixes into their browser, i.e. <a
href="http://www.sitepoint.com/opera-css3-webkit-prefix/">Opera implements the -webkit prefix for some properties</a>. The prefix process is broken and, while it&#8217;s too early to predict the outcome, the majority of developers consider it to be a bad move.</li></ol><p>We have discussed the issues at length on SitePoint; <a
href="http://www.sitepoint.com/css3-vendor-prefix-crisis-solutions/">there are no easy solutions</a>. However, two interesting proposals have been raised by W3C members during the past week.<div
id='div-gpt-ad-1328644474660-10' style='width:728px; height:90px;'> <script type='text/javascript'>googletag.cmd.push(function() { googletag.display('div-gpt-ad-1328644474660-10'); });</script> </div></p><h2>Option 1: Unprefixed Properties are Supported From Day One</h2><p>The first proposal comes from Florian Rivoal, Opera&#8217;s W3C representative:</p><blockquote><p> When a browser vendor implements a new CSS feature, it should support it, from day 1, both prefixed and unprefixed, the two being aliased. If a style sheet contains both prefixed and unprefixed, the last one wins, according to the cascade.</p><p>Authors should write their style sheets using the unprefixed property, and only add a prefixed version of the property (below the unprefixed one) if they discover a bug or inconsistency that they need to work around in a particular browser.</p><p>If a large amount of content accumulates using the a particular vendor prefix to work around an issue with the early implementation in that browser, the vendor could decide to freeze the behavior of the prefixed property while continuing to improve the unprefixed one.</p></blockquote><p>For example, you could use the following transform code in your CSS:</p><pre><code>
transform: rotate(30deg);
</code></pre><p>The property would be ignored by all browsers which had not implemented transforms. If there were a difference between two or more implementations, e.g. webkit browsers rotated anti-clockwise by default, you could override the property accordingly, e.g.</p><pre><code>
transform: rotate(30deg);
-webkit-transform: rotate(-30deg);
</code></pre><p>It&#8217;s a simple solution and easy to implement. Most existing stylesheets would continue to work and prefixed properties would rarely be necessary. In most cases, you would never need to update your CSS again.</p><p>However, what would happen if webkit changed rotation to the W3C-approved clockwise direction? Developers would need to fix their stylesheets by removing or rearranging the <code>-webkit-transform: rotate(-30deg);</code> property. Unfortunately, not everyone uses the same version of the webkit engine at the same time. You could encounter a situation where your site works in Chrome but not in Safari for several months.</p><h2>Option 2: A New Vendor-Draft Modifier</h2><p>The second proposal comes from Fran&ccedil;ois Remy:</p><blockquote><p> Let&#8217;s introduce the &#8220;!vendor-draft&#8221; value modifier. I propose we use unprefixed properties from start, but with a token explaining which version of the property we built our CSS for:<br
/> <code>border-radius: 3px !webkit-draft;</code></p><p>Any browser which is not webkit but implemented border-radius in a way that is compatible with the &#8220;webkit draft&#8221; can support the declaration. This is different from vendor prefixes: other browsers don&#8217;t impersonate webkit, they just acknowledge they support one specific property the way the webkit draft defines it. Browsers which are not compatible with that draft will just ignore the declaration. Browsers that change their implementation of a property are encouraged to iterate their &#8220;!vendor-draft&#8221; flag (using a version number, if appropriate).</p></blockquote><p>This solves the issue by changing the property value rather than its name (in a similar way to the <code>!important</code> modifier). Again, the following transform code could be used:</p><pre><code>
transform: rotate(30deg);
</code></pre><p>But a default anti-clockwise rotation could be fixed in any browser adhering to a webkit specification:</p><pre><code>
transform: rotate(30deg);
transform: rotate(-30deg) !webkit-draft;
</code></pre><p>If a browser subsequently supported the W3C specification, the second property would be ignored.</p><p>It would also be possible to implement draft versioning, e.g.</p><pre><code>
transform: rotate(30deg);
transform: rotate(-30degrees) !webkit-draft;
transform: rotate(-30deg) !webkit-draft-2;
</code></pre><p>It&#8217;s a flexible solution which finally addresses the issue of properties evolving over time.</p><p>Unfortunately, it&#8217;s more difficult to implement and could take months to appear in browsers even if all vendors agreed today. It may be technically better, but it&#8217;s a fundamentally different approach which could break existing stylesheets. In the short term, vendors would probably support both prefixes and value modifiers &#8212; and that would lead to confusion.</p><p>I like both solutions. From a coding perspective, vendor-draft modifiers seems the most logical option but I doubt it can be considered until vendors <em>&#8220;complete&#8221;</em> CSS3 and begin work on CSS4.</p><p>Supporting unprefixed properties is more practical but will certainly cause versioning issues which couldn&#8217;t be fixed in CSS alone. But perhaps that&#8217;s the price you pay for using experimental technology?</p><p>Do you have a preference for either of these options? Or is it too late to prevent a vendor prefix catastrophe?</p> <span
id="pty_trigger"></span><div
style='padding:20px 0px 50px 0px;'><div
style='float:left;padding-left:40px;'><div
id='div-gpt-ad-1335489406190-0' style='width:300px; height:100px;'> <script type='text/javascript'>googletag.cmd.push(function() { googletag.display('div-gpt-ad-1335489406190-0'); });</script> </div></div><div
style='float:right;padding-right:40px;'><div
id='div-gpt-ad-1335489406190-1' style='width:300px; height:100px;'> <script type='text/javascript'>googletag.cmd.push(function() { googletag.display('div-gpt-ad-1335489406190-1'); });</script> </div></div><div
style='clear:both'></div></div><div
style='clear:both'></div><div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/SitepointFeed?a=jvswTdgA9NU:ikOCNkvrzRI:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/SitepointFeed?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/SitepointFeed?a=jvswTdgA9NU:ikOCNkvrzRI:qj6IDK7rITs"><img src="http://feeds.feedburner.com/~ff/SitepointFeed?d=qj6IDK7rITs" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/SitepointFeed?a=jvswTdgA9NU:ikOCNkvrzRI:gIN9vFwOqvQ"><img src="http://feeds.feedburner.com/~ff/SitepointFeed?i=jvswTdgA9NU:ikOCNkvrzRI:gIN9vFwOqvQ" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/SitepointFeed/~4/jvswTdgA9NU" height="1" width="1"/>]]></content:encoded> <wfw:commentRss>http://www.sitepoint.com/css3-vendor-prefix-crisis-solutions-2/feed/</wfw:commentRss> <slash:comments>33</slash:comments> <feedburner:origLink>http://www.sitepoint.com/css3-vendor-prefix-crisis-solutions-2/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=css3-vendor-prefix-crisis-solutions-2</feedburner:origLink></item> <item><title>An Overview of the Web Storage API</title><link>http://feedproxy.google.com/~r/SitepointFeed/~3/6YgqxQxVO1U/</link> <comments>http://www.sitepoint.com/an-overview-of-the-web-storage-api/#comments</comments> <pubDate>Tue, 15 May 2012 15:00:11 +0000</pubDate> <dc:creator>Colin Ihrig</dc:creator> <category><![CDATA[HTML5]]></category> <category><![CDATA[JavaScript]]></category> <category><![CDATA[HTML5 Dev Center]]></category> <guid isPermaLink="false">http://www.sitepoint.com/?p=54156</guid> <description><![CDATA[<img
width="50" height="32" src="http://www.sitepoint.com/wp-content/uploads/1/files/2012/05/shutterstock_59314054-50x32.jpg" class="attachment-thumbnail wp-post-image" alt="shutterstock_59314054" title="shutterstock_59314054" />Web developers have long yearned for a way to store data long term. Cookies are an option, but they can only store 4KB of data.  Additionally, cookies are sent to the server with each HTTP request. This means that cookies, especially large ones, can consume considerable network bandwidth.  There have been other attempts to implement storage techniques, [...]]]></description> <content:encoded><![CDATA[<img
width="50" height="32" src="http://www.sitepoint.com/wp-content/uploads/1/files/2012/05/shutterstock_59314054-50x32.jpg" class="attachment-thumbnail wp-post-image" alt="shutterstock_59314054" title="shutterstock_59314054" /><p></p><p
style="text-align: justify" dir="ltr">Web developers have long yearned for a way to store data long term. Cookies are an option, but they can only store 4KB of data.  Additionally, cookies are sent to the server with each HTTP request. This means that cookies, especially large ones, can consume considerable network bandwidth.  There have been other attempts to implement storage techniques, but for the most part they have been hacks.  Then, along came HTML5 and the <a
title="Web Storage" href="http://dev.w3.org/html5/webstorage/" target="_blank">Web Storage API</a> to the rescue.</p><p
style="text-align: justify">The Web Storage API defines two types of storage areas ― local storage and session storage.  Local storage is persistent data which remains until it is explicitly deleted, or until the browser&#8217;s cache is cleared.  According to the specification, browsers should allocate at least 5MB of local storage per domain.  The second storage type, session storage, is also persistent data, however the data is tied to a &#8220;top-level browsing context&#8221; (i.e. a browser tab or window).  Session data remains until it is either deleted or the browsing context is closed.  Session storage is particularly useful when a user is interacting with multiple instances of the same website.  In such a situation, using local storage could result in the different instances overwriting each others data.<div
id='div-gpt-ad-1328644474660-10' style='width:728px; height:90px;'> <script type='text/javascript'>googletag.cmd.push(function() { googletag.display('div-gpt-ad-1328644474660-10'); });</script> </div></p><p
style="text-align: justify">The two types of storage areas are accessed through global objects named &#8220;localStorage&#8221; and &#8220;sessionStorage&#8221;.  Both storage areas implement the exact same API.  Data is stored as key/value pairs, and all data is stored in string form.  When adding data to storage, it is implicitly converted to a string.  However, when the string data is retrieved from storage it needs to be explicitly converted to the appropriate data type using functions such as <a
title="parseInt() Documentation" href="https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/parseInt" target="_blank">parseInt()</a>.  When dealing with objects, the <a
title="Native Browser Support for JSON (Part 1 of 2)" href="http://cjihrig.com/blog/native-browser-support-for-json-part-1/" target="_blank">JSON.parse()</a> and <a
title="Native Browser Support for JSON (Part 2 of 2)" href="http://cjihrig.com/blog/native-browser-support-for-json-part-2-of-2/" target="_blank">JSON.stringify()</a> methods should be used for serialization and deserialization.</p><h1>Detecting Storage Support</h1><p
style="text-align: justify" dir="ltr">The Web Storage API, like many other HTML5 features, is not supported by all browsers.  To check if a browser supports storage, use the function shown below.  The function checks for the existence of the global &#8220;localStorage&#8221; object.  A similar function could be created to check for session storage, but it can be safely assumed that if one storage area exists, then so does the other.</p><pre>function localStorageSupported() {
 try {
  return "localStorage" in window &amp;&amp; window["localStorage"] !== null;
 } catch (e) {
  return false;
 }
}</pre><h1 style="text-align: justify">Storing Data</h1><p
style="text-align: justify">Data is added to storage using the setItem() method.  setItem() takes a key and value as arguments.  If the key does not already exist in storage, then the key/value pair is added.  If the key is already present, then the value is updated.  Several example setItem() usages are shown below.  The examples show how to add data of various types to local and session storage.  Notice that the &#8220;key&#8221; argument must always be a string, while the type of &#8220;value&#8221; can vary.</p><pre style="text-align: justify">localStorage.setItem("key", "value");
sessionStorage.setItem("foo", 3.14);
localStorage.setItem("bar", true);
sessionStorage.setItem("baz", JSON.stringify(object));</pre><p
style="text-align: justify" dir="ltr">Data can also be added to storage using object property assignment statements.  The previous setItem() examples have been rewritten below using assignment statements. Note that the assignment to &#8220;key&#8221; on the first line will fail silently.  This is because the storage areas have a built in function named key() that will be covered later.  For this reason, the API methods are the preferred way to access storage.</p><pre style="text-align: justify">localStorage.key = "value"; // this fails silently
sessionStorage.foo = 3.14;
localStorage["bar"] = true;
sessionStorage["baz"] = JSON.stringify(object);</pre><p
style="text-align: justify">If a site attempts to store too much data, eventually the browser’s storage quota will be exceeded and an exception will be thrown.  To handle this case, try-catch blocks should be used when storing data.  An example of this is shown below.</p><pre>try {
 localStorage.setItem("key", "value");
} catch (e) {
 alert("Exceeded Storage Quota!");
}</pre><h1 style="text-align: justify">Reading Stored Data</h1><p
style="text-align: justify">To read data from storage, the getItem() method is used.  getItem() takes a lookup key as its sole argument.  If the key exists in storage, then the corresponding value is returned.  If the key does not exist, then null is returned.  The following examples use the getItem() method to retrieve the data stored in the setItem() examples.</p><pre style="text-align: justify">var string = localStorage.getItem("key");
var number = sessionStorage.getItem("foo");
var boolean = localStorage.getItem("bar");
var object = JSON.parse(sessionStorage.getItem("baz"));</pre><p
style="text-align: justify">Stored data can also be accessed by reading properties of the &#8220;localStorage&#8221; and &#8220;sessionStorage&#8221; objects.  The previous getItem() examples have been rewritten below using object property syntax.</p><pre style="text-align: justify">var string = localStorage.key;
var number = sessionStorage.foo;
var boolean = localStorage["bar"];
var object = JSON.parse(sessionStorage["baz"]);</pre><h1 style="text-align: justify">Iterating Over Stored Data</h1><p
style="text-align: justify">Often times, it is necessary to programmatically loop over all of the items in storage.  The loop&#8217;s upper bound is determined by the &#8220;length&#8221; property of the particular storage area.  The stored keys can be retrieved one at a time using the key() method.  key() takes a single integer parameter that acts as an index to the storage area.  An example of looping over each key/value pair in &#8220;localStorage&#8221; is shown below.  Of course, session storage can be processed in a similar fashion by substituting &#8220;sessionStorage&#8221; for &#8220;localStorage&#8221;.</p><pre style="text-align: justify">for (var i = 0; i &lt; localStorage.length; i++) {
 var key = localStorage.key(i);
 var value = localStorage.getItem(key);
 // do something with the key and value
}</pre><h1 style="text-align: justify">Deleting Stored Data</h1><p
style="text-align: justify">When data is no longer needed, it should be explicitly removed.  This is especially true for local storage, as it will persist even after the browser is closed.  To delete individual key/value pairs from storage, the removeItem() method is used.  The removeItem() method takes the key to be deleted as its only parameter.  If the key is not present then nothing will happen.  Examples of the removeItem() method are shown below.</p><pre style="text-align: justify">localStorage.removeItem("key");
sessionStorage.removeItem("foo");
localStorage.removeItem("bar");
sessionStorage.removeItem("baz");</pre><p
style="text-align: justify">The delete operator can also be used to remove stored data.  The previous example is rewritten below using delete instead of removeItem().</p><pre style="text-align: justify">delete localStorage.key;
delete sessionStorage.foo;
delete localStorage["bar"];
delete sessionStorage["baz"];</pre><p
style="text-align: justify" dir="ltr">While removeItem() is used to delete individual pieces of data, the clear() method is used to delete all stored data.  Usages of the clear() method are shown below.</p><pre style="text-align: justify">localStorage.clear();
sessionStorage.clear();</pre><h1 style="text-align: justify">The storage Event</h1><p
style="text-align: justify">A user can potentially have several instances of the same site open at any given time.  Changes made to a storage area in one instance need to be reflected in the other instances.  The Web Storage API accomplishes this synchronization using the &#8220;storage&#8221; event.  When a storage area is changed, a &#8220;storage&#8221; event is fired for any other tabs/windows that are sharing the storage area.  Note that a &#8220;storage&#8221; event is <em>not</em> fired for the tab/window that changes the storage area.</p><p
style="text-align: justify">Storage areas can be changed by calls to setItem(), removeItem(), and clear().  However, not all calls to these methods actually change the storage area.  For example, calling clear() on an empty storage area or removeItem() on a key that does not exist will not change the storage area, and therefore will not fire an event.</p><p
style="text-align: justify">The &#8220;storage&#8221; event object has several fields of interest which are described below.  Following the description of the fields is an example &#8220;storage&#8221; event handler.</p><ul
style="text-align: justify"><li>&#8220;key&#8221; ― This field is the key argument of setItem() or removeItem(), or null when clear() caused the event to be fired.</li><li>&#8220;newValue&#8221; ― The &#8220;value&#8221; argument to setItem() is reflected in this field.  Calls to removeItem() and clear() cause this field to be null.</li><li>&#8220;oldValue&#8221; ― This field holds the key&#8217;s value prior to a call to setItem() or removeItem().  Calls to clear() cause this field to be null.</li><li>&#8220;url&#8221; ― The &#8220;url&#8221; field stores the address of the page whose storage area was affected.</li><li>&#8220;storageArea&#8221; ― The &#8220;storageArea&#8221; field corresponds to the local or session storage area that was changed.</li></ul><pre style="text-align: justify">window.addEventListener("storage", function(event) {
 var key = event.key;
 var newValue = event.newValue;
 var oldValue = event.oldValue;
 var url = event.url;
 var storageArea = event.storageArea;
 // handle the event
});</pre><h1 style="text-align: justify">Example Page</h1><p
style="text-align: justify">The following code implements a sample page for manipulating local storage.  The page is also available online <a
title="Web Storage Example" href="http://www.cjihrig.com/development/html5/storage.htm" target="_blank">here</a>.  The example covers the entire local storage API, including the &#8220;storage&#8221; event.  In order to see the &#8220;storage&#8221; event in action, the page must be open in at least two separate tabs/windows of the same browser.  The &#8220;storage&#8221; event will also only work if the page is served over HTTP (i.e. the file:// protocol will not work).</p><pre style="text-align: justify">&lt;!DOCTYPE html&gt;
&lt;html&gt;
&lt;head&gt;
 &lt;title&gt;Web Storage Example&lt;/title&gt;
 &lt;meta charset="UTF-8" /&gt;
 &lt;script&gt;
  "use strict";
  window.addEventListener("load", function(event) {
   var key = document.getElementById("key");
   var value = document.getElementById("value");
   var add = document.getElementById("add");
      var remove = document.getElementById("remove");
      var clear = document.getElementById("clear");
      var content = document.getElementById("content");
   add.addEventListener("click", function(event) {
        if (key.value !== "") {
     try {
           localStorage.setItem(key.value, value.value);
     } catch (e) {
      alert("Exceeded Storage Quota!");
     }
          refreshContents();
        }
      });
      remove.addEventListener("click", function(event) {
        if (key.value !== "") {
          localStorage.removeItem(key.value);
          refreshContents();
        }
      });
      clear.addEventListener("click", function(event) {
        localStorage.clear();
        refreshContents();
      });
      window.addEventListener("storage", function(event) {
        var k = event.key;
        var newValue = event.newValue;
        var oldValue = event.oldValue;
        var url = event.url;
        var storageArea = event.storageArea;
        alert("EVENT:\n" + k + "\n" + newValue + "\n" + oldValue + "\n" + url + "\n" + storageArea);
        refreshContents();
      });
      function refreshContents() {
        var str = "";
        for (var i = 0, len = localStorage.length; i &lt; len; i++) {
          var k = localStorage.key(i);
          var v = localStorage.getItem(k);
          str += "'" + k + "' = '" + v + "'&lt;br /&gt;";
        }
    key.value = "";
    value.value = "";
        content.innerHTML = str;
      }
      refreshContents();
    });
  &lt;/script&gt;
&lt;/head&gt;
&lt;body&gt;
  Key:  &lt;input type="text" id="key" /&gt;&lt;br /&gt;
  Value: &lt;input type="text" id="value" /&gt;&lt;br /&gt;
  &lt;input type="button" id="add" value="Add to Storage" /&gt;&amp;nbsp;
  &lt;input type="button" id="remove" value="Remove from Storage" /&gt;&amp;nbsp;
  &lt;input type="button" id="clear" value="Clear Storage" /&gt;&lt;br /&gt;
  Contents of Local Storage:&lt;br /&gt;
  &lt;span id="content"&gt;&lt;/span&gt;
&lt;/body&gt;
&lt;/html&gt;</pre><h1 style="text-align: justify">Things to Remember</h1><ul><li>Local storage persists until it is explicitly deleted or the browser&#8217;s cache is cleared.</li><li>Session storage persists until it is explicitly deleted or the browsing context is closed.</li><li>Data stored by one browser is not accessible by another browser.  For example, data stored by Chrome is not seen by Firefox.</li><li>Objects should be stored as JSON strings.</li><li>For security reasons, sensitive data should not be stored, especially in local storage.</li><li>Changes to a storage area cause a &#8220;storage&#8221; event to be fired.</li><li>As with many other HTML5 features, web storage is not yet implemented consistently.</li></ul><p><small><a
href="http://www.shutterstock.com/cat.mhtml?lang=en&#038;search_source=search_form&#038;version=llv1&#038;anyorall=all&#038;safesearch=1&#038;searchterm=storage&#038;search_group=#id=59314054&#038;src=e0f1864e9ad3dfdce4483f891a30273f-1-0">Storage</a> image via Shutterstock</small></p> <span
id="pty_trigger"></span><div
style='padding:20px 0px 50px 0px;'><div
style='float:left;padding-left:40px;'><div
id='div-gpt-ad-1335489406190-0' style='width:300px; height:100px;'> <script type='text/javascript'>googletag.cmd.push(function() { googletag.display('div-gpt-ad-1335489406190-0'); });</script> </div></div><div
style='float:right;padding-right:40px;'><div
id='div-gpt-ad-1335489406190-1' style='width:300px; height:100px;'> <script type='text/javascript'>googletag.cmd.push(function() { googletag.display('div-gpt-ad-1335489406190-1'); });</script> </div></div><div
style='clear:both'></div></div><div
style='clear:both'></div><div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/SitepointFeed?a=6YgqxQxVO1U:zAJuAcBPIDA:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/SitepointFeed?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/SitepointFeed?a=6YgqxQxVO1U:zAJuAcBPIDA:qj6IDK7rITs"><img src="http://feeds.feedburner.com/~ff/SitepointFeed?d=qj6IDK7rITs" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/SitepointFeed?a=6YgqxQxVO1U:zAJuAcBPIDA:gIN9vFwOqvQ"><img src="http://feeds.feedburner.com/~ff/SitepointFeed?i=6YgqxQxVO1U:zAJuAcBPIDA:gIN9vFwOqvQ" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/SitepointFeed/~4/6YgqxQxVO1U" height="1" width="1"/>]]></content:encoded> <wfw:commentRss>http://www.sitepoint.com/an-overview-of-the-web-storage-api/feed/</wfw:commentRss> <slash:comments>1</slash:comments> <feedburner:origLink>http://www.sitepoint.com/an-overview-of-the-web-storage-api/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=an-overview-of-the-web-storage-api</feedburner:origLink></item> <item><title>Ubuntu 12.04 LTS Precise Pangolin: Networking tips and tricks</title><link>http://feedproxy.google.com/~r/SitepointFeed/~3/t7q0amNT1IQ/</link> <comments>http://www.sitepoint.com/ubuntu-12-04-lts-precise-pangolin-networking-tips-and-tricks/#comments</comments> <pubDate>Mon, 14 May 2012 15:00:50 +0000</pubDate> <dc:creator>Jonathan Hobson</dc:creator> <category><![CDATA[Web Tech]]></category> <category><![CDATA[WebOS]]></category> <category><![CDATA[Ubuntu]]></category> <guid isPermaLink="false">http://www.sitepoint.com/?p=54343</guid> <description><![CDATA[<img
width="50" height="39" src="http://www.sitepoint.com/wp-content/uploads/1/files/2012/04/ubuntu-50x39.png" class="attachment-thumbnail wp-post-image" alt="ubuntu" title="ubuntu" />Networking is often regarded to be complicated and very difficult to manage but as it forms an essential role in the day-to-day use of your computer the purpose of this article is to expose a few &#8216;tips and tricks&#8217; that will serve to improve your computers connectivity and overall performance by showing you how easy [...]]]></description> <content:encoded><![CDATA[<img
width="50" height="39" src="http://www.sitepoint.com/wp-content/uploads/1/files/2012/04/ubuntu-50x39.png" class="attachment-thumbnail wp-post-image" alt="ubuntu" title="ubuntu" /><p></p><p>Networking is often regarded to be complicated and very difficult to manage but as it forms an essential role in the day-to-day use of your computer the purpose of this article is to expose a few &#8216;tips and tricks&#8217; that will serve to improve your computers connectivity and overall performance by showing you how easy it is to take control of Ubuntu 12.04, LTS Precise Pangolin.</p><p>So let&#8217;s get started &#8230;</p><h2>What is my local IP address</h2><p>It may be a easy question to begin with, but in a world of complexity it is often the simple questions that get overlooked.</p><h3>Using the graphical tools:</h3><p>Right click on the &#8216;networking icon&#8217; in the top panel of the Ubuntu desktop and choose &#8216;Connection Information&#8217; as shown below:</p><p><a
href="http://www.sitepoint.com/?attachment_id=54344" rel="attachment wp-att-54344"><img
class="alignnone size-full wp-image-54344" src="http://www.sitepoint.com/wp-content/uploads/1/files/2012/05/u1.jpg" alt="" width="500" height="486" /></a></p><p>The resulting dialogue box will then provide feedback on your current settings.</p><h3>Using the command line interface:</h3><p>On the other hand, for those individuals who are beginning to enjoy the power of Terminal or for those of you who use a server (via the Console or Putty or similar).<div
id='div-gpt-ad-1328644474660-10' style='width:728px; height:90px;'> <script type='text/javascript'>googletag.cmd.push(function() { googletag.display('div-gpt-ad-1328644474660-10'); });</script> </div></p><p>If you have a wireless based connection, run:</p><pre>iwconfig</pre><p>If you have a &#8216;wired&#8217; connection, run</p><pre>ifconfig</pre><p>The results for &#8216;ifconfig&#8217; will look something like this:</p><pre>eth0      Link encap:Ethernet  HWaddr 00:1d:92:65:09:e1
          inet addr:192.168.1.100  Bcast:192.168.1.255  Mask:255.255.255.0
          inet6 addr: fe80::21d:92ff:fe65:9e1/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:510 errors:0 dropped:0 overruns:0 frame:0
          TX packets:315 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:80353 (80.3 KB)  TX bytes:38731 (38.7 KB)
          Interrupt:42 Base address:0xa000
lo        Link encap:Local Loopback
          inet addr:127.0.0.1  Mask:255.0.0.0
          inet6 addr: ::1/128 Scope:Host
          UP LOOPBACK RUNNING  MTU:16436  Metric:1
          RX packets:108 errors:0 dropped:0 overruns:0 frame:0
          TX packets:108 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0
          RX bytes:8176 (8.1 KB)  TX bytes:8176 (8.1 KB)</pre><p>And because the command line provides us with additional opportunities, if you would like to quickly identify all the available ethernet devices on your computer, you can run</p><pre>ifconfig -a | grep eth</pre><p>The result will look something like this:</p><pre>eth0      Link encap:Ethernet  HWaddr 00:1d:92:65:09:e1</pre><p>Well done, but just before we finish-up I would like to take this opportunity to show you another useful command that can help identify all the network interfaces available to your system. Known as the &#8216;lshw&#8217; command, this tool will not only detail your ethernet devices but it will also provide a plethora of information on your hardware&#8217;s &#8216;other&#8217; capabilities.</p><p>To use this tool, simply run the following command and wait a few seconds whilst Ubuntu quieries your devices:</p><pre>sudo lshw -class network</pre><p>And the result will look something like this:</p><pre>  *-network
       description: Ethernet interface
       product: RTL8111/8168B PCI Express Gigabit Ethernet controller
       vendor: Realtek Semiconductor Co., Ltd.
       physical id: 0
       bus info: pci@0000:02:00.0
       logical name: eth0
       version: 01
       serial: 00:1d:92:65:09:e1
       size: 100Mbit/s
       capacity: 1Gbit/s
       width: 64 bits
       clock: 33MHz
       capabilities: pm vpd msi pciexpress bus_master cap_list rom ethernet physical tp mii 10bt 10bt-fd 100bt 100bt-fd 1000bt 1000bt-fd autonegotiation
       configuration: autonegotiation=on broadcast=yes driver=r8169 driverversion=2.3LK-NAPI duplex=full firmware=N/A ip=192.168.1.160 latency=0 link=yes multicast=yes port=MII speed=100Mbit/s
       resources: irq:43 ioport:d800(size=256) memory:feaff000-feafffff memory:feac0000-feadffff</pre><p>Sometimes you&#8217;ve just &#8216;gotta&#8217; love the details, but now we know something about our computer we can begin to take control :-)</p><h2>How do I create a static IP address with the Network Manager</h2><p>The following instruction shows you how to create a fixed (or static) IP address with the Network Manager.</p><p>This approach is best suited to all desktop users who may require the need to keep the functionality of the Network Manager or for those that use netbooks, laptops and and other wireless connections that may require a DHCP based option in the future. Don&#8217;t worry, it is all very simple:</p><p>Click the network menu on the top panel (the &#8216;up/down&#8217; arrows icon) and select &#8216;Edit Connections&#8217;.</p><p>Alternatively you can choose System Settings &gt; Network &gt; Choose your &#8216;Network Connection&#8217; from the left hand panel and select &#8216;Options&#8217;.</p><p><a
href="http://www.sitepoint.com/?attachment_id=54345" rel="attachment wp-att-54345"><img
class="alignnone size-full wp-image-54345" src="http://www.sitepoint.com/wp-content/uploads/1/files/2012/05/u2.jpg" alt="" width="500" height="400" /></a></p><p>Now choose the relevant connection and click edit.</p><p>For example, if you are using a &#8216;wired connection&#8217;, choose the &#8216;wired&#8217; tab to find your connection.</p><p><a
href="http://www.sitepoint.com/?attachment_id=54346" rel="attachment wp-att-54346"><img
class="alignnone size-full wp-image-54346" src="http://www.sitepoint.com/wp-content/uploads/1/files/2012/05/u3.jpg" alt="" width="500" height="583" /></a></p><p>In the resulting dialogue box you should:</p><ul><li>Select the &#8216;IPv4 Settings&#8217; tab and change the &#8216;Method&#8217; to &#8216;Manual&#8217;.</li><li>Click Add and complete each field with your IP address, network mask and default gateway.Always press the &#8216;Enter/Return&#8217; when you&#8217;ve finished typing each address otherwise the dialogue will fail to accept your new settings and the &#8216;save&#8217; button will remain inactive/greyed-out.</li><li>Include the IP addresses of the DNS servers. Multiple addresses should be separated by commas.</li><li>Click Save and close the remaining dialogue boxes.</li></ul><p>And there you go &#8230;</p><p>If all is well you should be able to view web sites and/or view your local network but in some situations and depending on your network topology a reboot may be necessary.</p><p>To confirm your new settings, simply check your connection settings as shown previously (see above)</p><p><strong>But what if I need DHCP again?</strong><br
/> If you ever need to return to a dynamically assigned IP address simply re-run the previous steps. Find your current connection, select the &#8216;IPv4 Settings&#8217; tab and change the &#8216;Method&#8217; to &#8216;Automatic (DHCP)&#8217;. To finalise this reversal click save and reboot (depending on the network conditions and how the DHCP server is configured).</p><h2>Disable the Network Manager and &#8216;hard-code&#8217; a static IP address</h2><p>This solution explains how to create a fixed (or static) IP address without using the Network Manager.</p><p>The Network Manager is a very nice feature, but only suitable for individuals who require dynamically assigned connections or those who require wireless connectivity. Yes, it is true to say that these are both very popular in homes and offices throught the world but for those of us who use and prefer the benefit of a &#8216;wired connection&#8217; using the Network Manager does come at the cost of performance. So this solution uses the traditional approach to &#8216;hard-coding&#8217; your network connection and it is most suitable to those individuals who demand maximum performance or absolute stability.</p><blockquote><p>By using this approach you should note that we will not be removing the Network Manager, merely disabling it with the intention to capitalise on the performance gains by by-passing or side-stepping this device. These performance gains will not only be noticed in terms of network speed but also in terms of the computer in general.</p></blockquote><p>Again, don&#8217;t worry, the process to disable the Network Manager is very simple but it will require us to run various &#8216;commands&#8217; in Terminal in order to complete some steps.</p><p>So let&#8217;s begin by making a backup of our original file.</p><p>In Terminal type:</p><pre>sudo cp /etc/NetworkManager/NetworkManager.conf /etc/NetworkManager/NetworkManager.conf.bak</pre><blockquote><p>This will serve to back-up our original file to &#8216;/etc/NetworkManager/NetworkManager.conf.bak&#8217;. Hopefully you will not need it, but if you ever need to restore the original file simply open Terminal and reverse the command like so: &#8216;sudo cp /etc/NetworkManager/NetworkManager.conf.bak /etc/NetworkManager/NetworkManager.conf&#8217; and reboot.</p></blockquote><p>And with the confidence that we are fully backed-up we shall now proceed to disable the Network Manager.</p><p>In Terminal, type:</p><pre>sudo gedit /etc/NetworkManager/NetworkManager.conf</pre><p>This will open the &#8216;NetworkManager.conf&#8217; file in our text editor.</p><p>Now change:</p><p>managed=false</p><p>to</p><p>managed=true</p><p>So it looks like this:</p><p><a
href="http://www.sitepoint.com/?attachment_id=54347" rel="attachment wp-att-54347"><img
class="alignnone size-full wp-image-54347" src="http://www.sitepoint.com/wp-content/uploads/1/files/2012/05/u4.jpg" alt="" width="500" height="409" /></a></p><p>When done, save the file and close it.</p><blockquote><p>You can re-enable the network manager at any time by simply reversing the steps shown above or by restoring your back-up file. Remember to reboot in order to apply these changes.</p></blockquote><p>Now we have successfully disabled the Network Manager we can proceed to create our Static IP address by making some direct changes to the &#8216;interface&#8217; file; but with safety in mind let&#8217;s begin by making a backup of our original file.</p><p>In Terminal and type:</p><pre>sudo cp /etc/network/interfaces /etc/network/interfaces.bak</pre><blockquote><p>This will back-up our original file to /etc/network/interfaces.bak. Again, it is not expected that we will need it but if you ever need to restore it open Terminal and reverse the command like so: sudo cp /etc/network/interfaces.bak /etc/network/interfaces</p></blockquote><p>Now lets add our static IP address.</p><p>In Terminal type:</p><pre>sudo gedit /etc/network/interfaces</pre><p>Authenticate yourself in the usual way and then replace the file contents as shown below, where xxx represents values relevant to your needs:</p><pre>auto lo
iface lo inet loopback
auto eth0
iface eth0 inet static
	address 	xxx.xxx.xxx.xxx
	netmask 	xxx.xxx.xxx.xxx
	network 	xxx.xxx.xxx.xxx
	broadcast 	xxx.xxx.xxx.xxx
	gateway 	xxx.xxx.xxx.xxx</pre><p>And to help you out, here is an example with an explanation of the values concerned:</p><pre>auto lo
iface lo inet loopback
auto eth0
iface eth0 inet static
	address 	192.168.1.100 	(this is my computers IP address)
	netmask 	255.255.255.0 	(this is my subnet mask)
	network 	192.168.1.0	(this is my network base address)
	broadcast 	192.168.1.255	(this is my broadcast address)
	gateway 	192.168.1.254	(this is my gateway/router's ip address)</pre><p>When complete, simply save and close the file and reboot your computer to complete these steps.</p><p>We are re-booting our computer at this point in order to &#8216;dis-engage&#8217; the Network Manager, and once complete you can always re-configure your IP address at any time by making the necessary changes to the &#8216;interfaces&#8217; file (shown above) and using the following command to restart your networking service: &#8216;sudo /etc/init.d/networking restart&#8217;.</p><p>After you restart your computer you will discover (visually) that nothing has changed but as a consequence you should be experiencing a &#8216;more&#8217; responsive computer and network connection.</p><blockquote><p>Should you ever want to re-enable the Network Manager. Simply reverse the steps we have taken above and/or restore you back-up files and reboot and as we created them with the &#8216;cp&#8217; or copy command &#8211; unless you delete them, your original backup files will always remain for future reference.</p></blockquote><h2>Create Virtual Network Adapters (add more than 1 IP address to a single ethernet card)</h2><p>In some situations this can be very useful and as an extension to our previous solution of &#8216;disabling the network manager and hard-coding a static IP address&#8217; I will now show you how to assign more than one IP address to the same ethernet card:</p><p>In Terminal type:</p><pre>sudo gedit /etc/network/interfaces</pre><p>Authenticate yourself and then replace the file contents like so, where xxx represents values relevant to your needs:</p><pre>auto lo
iface lo inet loopback
auto eth0
iface eth0 static
	address 	xxx.xxx.xxx.xxx
	netmask 	xxx.xxx.xxx.xxx
	network 	xxx.xxx.xxx.xxx
	broadcast 	xxx.xxx.xxx.xxx
	gateway 	xxx.xxx.xxx.xxx
auto eth0:0
iface eth0:0 static
	address 	xxx.xxx.xxx.xxx
	netmask 	xxx.xxx.xxx.xxx
	gateway 	xxx.xxx.xxx.xxx</pre><p>And to make this as simple as possible, here is an example:</p><pre>auto lo
iface lo inet loopback
auto eth0
iface eth0 static
	address 	192.168.1.100
	netmask 	255.255.255.0
	network 	192.168.1.0
	broadcast 	192.168.1.255
	gateway 	192.168.1.254
auto eth0:0
iface eth0:0 static
	address 	192.168.1.101
	netmask 	255.255.255.0
	gateway 	192.168.1.254</pre><p>By doing this I will be adding two IP addresses to my a single ethernet card. It will not only have the IP address of 192.168.1.100 but it will also have the alternative address of 192.168.1.101 (as a virtual instance).</p><p>The trick is to follow the virtual naming scheme (i.e. eth0:0, eth0:1, eth0:2 etc &#8230;) and to ensure that every instance maintains a unique IP address. In this way you can create as many &#8216;instances&#8217; of an IP address as required.</p><p>To illustrate this point, let&#8217;s add a third IP address to our example:</p><pre>auto lo
iface lo inet loopback
auto eth0
iface eth0 static
	address 	192.168.1.100
	netmask 	255.255.255.0
	network 	192.168.1.0
	broadcast 	192.168.1.255
	gateway 	192.168.1.254
auto eth0:0
iface eth0:0 static
	address 	192.168.1.101
	netmask 	255.255.255.0
	gateway 	192.168.1.254
iface eth0:1 static
	address 	192.168.1.102
	netmask 	255.255.255.0
	gateway 	192.168.1.254</pre><p>When complete, remember to reboot your computer to apply the changes or open Terminal and type:</p><pre>sudo /etc/init.d/networking restart</pre><p>You can then run &#8216;ifconfig&#8217; to view your new settings.</p><p>Have fun ..!</p><h2>Change your computer&#8217;s hostname</h2><p>You may like your current computer name, or you may want to change it.</p><p>In this short recipe I will show you how to view and change your computer name with relative ease &#8230;</p><p>In Terminal type:</p><pre>sudo gedit /etc/hostname</pre><p>The file will probably look something like this:</p><pre>ubuntu-computername</pre><p>To change the name of your computer, simply delete the existing content and replace as required.</p><p>Remember, the actual name can be anything your want as long as you remember some basic principles:</p><ul><li>Desktops generally use a singular name (as shown above) whereas all servers or &#8216;desktops acting as servers&#8217; should be in the format of computername.computerdomain.suffix.</li><li>On a local network computers should refrain from using the standard or typical internet based suffix or TLD unless your local DNS can account for such similarities.</li><li>Use &#8216;internet friendly&#8217; names and do not use a computer name that already exists on your network.</li><li>Do not use spaces or non-internet friendly characters.</li></ul><p>Once complete, simply choose &#8216;save&#8217;, &#8216;close&#8217; the file and reboot your computer to see the changes.</p><p>Your new computer name will be in the top-left hand side of the login screen but if you missed this or need to confirm your current or new hostname at any time.</p><p>Open Terminal and type:</p><pre>sudo hostname</pre><p>And the result should reflect the changes you made &#8230;</p><h2>Managing the Hosts file</h2><p>The hosts file file consists of a list of IP addresses and corresponding hostnames. Most users may never need to touch this area of their computer but there maybe an occasion when you need to edit the hosts file on your machine. This can because of any number of reasons (i.e. reversing the effect of malicious activity) or it can be because your are trying to make your life that little &#8216;quicker&#8217; buy &#8216;hard-coding&#8217; the address of an internal or external web site. Similarly, if your network contains computers whose IP addresses that are not listed in an existing DNS record, then it is recommended that you add them to the hosts file. So with this in mind I will now show you how to manage you hosts file.</p><p>Before you begin, you can make a back-up of this file by simply typing the following command in to Terminal:</p><pre>sudo cp /etc/hosts /etc/hosts.bak</pre><p>Now, to proceed and customise your hosts file simply return to the command line and type:</p><pre>sudo gedit /etc/hosts</pre><p>A typical desktop file will look like this (simply substitue the example values with those relevant to your computer):</p><pre>127.0.0.1			localhost
127.0.1.1			ubuntu-computername
# The following lines are desirable for IPv6 capable hosts
::1     ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters</pre><p>However, having said that and just for the record, for the &#8216;server&#8217; or &#8216;desktop server&#8217; version of the same file should look more like this:</p><pre>127.0.0.1       localhost.localdomain   localhost
192.168.1.100 	ubuntu-computername.ubuntu-domainname.lan  ubuntu-computername
# The following lines are desirable for IPv6 capable hosts
::1     localhost ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters</pre><p>You will notice that my examples include the IPv6 instruction and this is entirely at your discretion as it depends on whether your network supports it.</p><p>For example, you may ignore these values (not include them or comment them out by placing a &#8216;hash&#8217; character at the beginning of the line) like so if your computer does not use IPv6.</p><pre># The following lines are desirable for IPv6 capable hosts
#::1     ip6-localhost ip6-loopback
#fe00::0 ip6-localnet
#ff00::0 ip6-mcastprefix
#ff02::1 ip6-allnodes
#ff02::2 ip6-allrouters</pre><p>Of course, disabling IPv6 is optional and can sometimes improve performance but if you are in doubt, simply ignore them (but as they sometimes say in &#8216;old blighty&#8217; &#8211; &#8216;don&#8217;t fix what ain&#8217;t broke&#8217;).</p><p>So getting back on track &#8230;</p><p>In your hosts file you may want to include a list or pre-identified servers and workstations in order to speed-up name resolution like so:</p><pre>192.168.1.200		servername1 www servername1.localdomain.lan
192.168.1.200		servername2 mail servername2.localdomain.lan</pre><blockquote><p>In my example I have included an alias in addition to the actual names &#8211; i.e. servername1 is also known as www and servername2 is also known as mail. You do not need to do this as my other examples will show.</p></blockquote><p>Windows (and Mac) users should notice that this process very similar to customisng the &#8216;hosts&#8217; file on any Windows/Mac based operating system and the resulting file could look like this:</p><pre>127.0.0.1			localhost
127.0.1.1			ubuntu-computername
# PUT YOU COMMENT AFTER A HASH (#) FOR REFERENCE - NOT REQUIRED BUT USEFUL
192.168.1.200		www.website1.com
192.168.1.201		www.website2.com
# The following lines are desirable for IPv6 capable hosts
::1     ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters</pre><p>Consequently, my computer will now use the IP address for www.website1.com instead of searching a DNS record thereby ensuring that my ability to view the website in question would be quicker than before.</p><p>Taking this one step further &#8230; and by giving it a little twist.</p><p>For those of you who wish to excercise some &#8216;parental power&#8217; you could easily use this as a way to block direct access to some &#8216;unwanted web sites&#8217; by sending someone who expects to go to www.website1.com to www.website2.com, like so:</p><pre>#192.168.1.200	www.website1.com
192.168.1.201		www.website1.com
192.168.1.201		www.website2.com
192.168.1.202		www.website3.com
192.168.1.123		www.website4.com
192.168.1.167		www.website5.com</pre><p>Notice I have commented out the real address of website1 with a hash (#) and that both website1 and website 2 now have the same IP address &#8230; (the IP address being the actual address of website2)</p><p>It isn&#8217;t a perfect of solution by any means but it is food for thought and can serve as a starting point for future development ;-)</p><h2>How to re-configure DNS resolution</h2><p>The purpose of this section is to show you how to configure the appropriate nameserver to use when resolving IP address to hostnames and vice versa. It is not intended to explain how to configure the system as a name server as this is something I will be covering in a future article. You should only affect this file if you are not using the Network Manager and want to use a static IP address.</p><blockquote><p>The resolv.conf file is the resolver configuration file and it is used to configure workstation or server access to the Internet Domain Name System (DNS). This file defines which nameservers to use and in what order they are tried. You should therefore put the most reliable server first. It is convention that up to three name servers are supported. However, if no nameserver option is given, the resolver will attempt to connect to the name server on the local host.</p></blockquote><p>Resolv.conf still does this, but with the release of the Precise Pangolin a few things have changed, and regardless as to whether you are running a desktop or a server your system is probably running the resolveconf program:</p><p>&#8216;Resolveconf&#8217; is a small program that resides in &#8216;/etc/resolvconf&#8217; that dynamically modifies the nameserver information on boot. It is a useful tool, but for our purposes it can be disruptive, so we are going to work around it by simply adding a new entry to our &#8216;/etc/network/interfaces&#8217; file:</p><p>In Terminal type:</p><pre>sudo gedit /etc/network/interfaces</pre><p>Now add the following nameserver line to your file, changing XXX to something more applicable to your needs:</p><pre>dns-nameservers xxx.xxx.xxx.xxx xxx.xxx.xxx.xxx</pre><p>Similar to the example shown above here is the new file using Google&#8217;s public nameservers:</p><pre>auto lo
iface lo inet loopback
auto eth0
iface eth0 static
	address 	192.168.1.100
	netmask 	255.255.255.0
	network 	192.168.1.0
	broadcast 	192.168.1.255
	gateway 	192.168.1.254
        dns-nameservers 8.8.8.8 8.8.4.4</pre><p>When complete, click &#8216;save&#8217;, then &#8216;close&#8217; the file and reboot to apply the changes.</p><p>On reboot, you can see that the new nameserver information has now been applied to our &#8216;resolve.conf&#8217; file by opening Terminal and typing:</p><pre>cat /etc/resolv.conf</pre><p>Which may look something like this:</p><pre># Dynamic resolv.conf(5) file for glibc resolver(3) generated by resolvconf(8)
#     DO NOT EDIT THIS FILE BY HAND -- YOUR CHANGES WILL BE OVERWRITTEN
nameserver 8.8.8.8
nameserver 8.8.4.4
nameserver 127.0.0.1</pre><p>So having made your changes, to query the DNS capabilities of your system, simply return to the command line and type:</p><pre>nslookup www.sitepoint.com</pre><p>or alternatively try</p><pre>dig www.sitepoint.com</pre><p>And that&#8217;s it for now &#8230; but most of all, have fun :-)</p><p>So until next time &#8230;</p><p>I hope that you continue to enjoy using Ubuntu 12.04 LTS Precise Pangolin.</p> <span
id="pty_trigger"></span><div
style='padding:20px 0px 50px 0px;'><div
style='float:left;padding-left:40px;'><div
id='div-gpt-ad-1335489406190-0' style='width:300px; height:100px;'> <script type='text/javascript'>googletag.cmd.push(function() { googletag.display('div-gpt-ad-1335489406190-0'); });</script> </div></div><div
style='float:right;padding-right:40px;'><div
id='div-gpt-ad-1335489406190-1' style='width:300px; height:100px;'> <script type='text/javascript'>googletag.cmd.push(function() { googletag.display('div-gpt-ad-1335489406190-1'); });</script> </div></div><div
style='clear:both'></div></div><div
style='clear:both'></div><div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/SitepointFeed?a=t7q0amNT1IQ:ONfIBC2ZYWo:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/SitepointFeed?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/SitepointFeed?a=t7q0amNT1IQ:ONfIBC2ZYWo:qj6IDK7rITs"><img src="http://feeds.feedburner.com/~ff/SitepointFeed?d=qj6IDK7rITs" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/SitepointFeed?a=t7q0amNT1IQ:ONfIBC2ZYWo:gIN9vFwOqvQ"><img src="http://feeds.feedburner.com/~ff/SitepointFeed?i=t7q0amNT1IQ:ONfIBC2ZYWo:gIN9vFwOqvQ" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/SitepointFeed/~4/t7q0amNT1IQ" height="1" width="1"/>]]></content:encoded> <wfw:commentRss>http://www.sitepoint.com/ubuntu-12-04-lts-precise-pangolin-networking-tips-and-tricks/feed/</wfw:commentRss> <slash:comments>1</slash:comments> <feedburner:origLink>http://www.sitepoint.com/ubuntu-12-04-lts-precise-pangolin-networking-tips-and-tricks/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=ubuntu-12-04-lts-precise-pangolin-networking-tips-and-tricks</feedburner:origLink></item> <item><title>Get Hired</title><link>http://feedproxy.google.com/~r/SitepointFeed/~3/LuoEhAAKKOg/</link> <comments>http://www.sitepoint.com/get-hired/#comments</comments> <pubDate>Sun, 13 May 2012 23:00:27 +0000</pubDate> <dc:creator>John Tabita</dc:creator> <category><![CDATA[Business]]></category> <category><![CDATA[Find Clients]]></category> <category><![CDATA[Sell Your Services]]></category> <category><![CDATA[Selling Web Design Services]]></category> <category><![CDATA[Web Pro Business]]></category> <category><![CDATA[clients]]></category> <category><![CDATA[Marketing]]></category> <category><![CDATA[sales]]></category> <category><![CDATA[selling]]></category> <category><![CDATA[selling your services]]></category> <category><![CDATA[small business]]></category> <guid isPermaLink="false">http://www.sitepoint.com/?p=54612</guid> <description><![CDATA[<img
width="50" height="50" src="http://www.sitepoint.com/wp-content/uploads/1/files/2012/05/handshake-50x50.jpg" class="attachment-thumbnail wp-post-image" alt="handshake" title="handshake" />In this article, John Tabita give you some simple tips to increase your chances of getting hired.]]></description> <content:encoded><![CDATA[<img
width="50" height="50" src="http://www.sitepoint.com/wp-content/uploads/1/files/2012/05/handshake-50x50.jpg" class="attachment-thumbnail wp-post-image" alt="handshake" title="handshake" /><p></p><p>In my series on <a
title="Putting a Stop to Abusive Clients" href="http://www.johntabita.com/abusive-clients/" target="_blank">Putting a Stop to Abusive Clients</a>, I&#8217;ve talked a lot from the seller’s perspective. But before I put the final wraps on the series, I’m going to take a slight detour to discuss things from the buyer’s side of the fence. Let&#8217;s talk about how to get hired.</p><p>Over the past few days, I’ve had to post two different job opportunities; one for a full-time sales rep, and the other for some contract web work. The responses I’ve gotten have been interesting, to say the least.</p><p>One of the things I deliberately do is include both an email and my direct phone number as contact points. Which you chose may very well mean the difference between getting hired and getting ignored.</p><p>Within minutes of posting the ad for the contract position, I received a phone call. Shortly afterwards, I received a second call from another firm. Both took the time to find out my objectives and what I’m trying to accomplish before talking up their firm.</p><p>The rest sent an email with some variation of “check out my website“ and “call me back.”<div
id='div-gpt-ad-1328644474660-10' style='width:728px; height:90px;'> <script type='text/javascript'>googletag.cmd.push(function() { googletag.display('div-gpt-ad-1328644474660-10'); });</script> </div></p><p>Who do you suppose I’m considering?</p><h2>Hiding behind Web 2.0</h2><p>Recently, my son’s scoutmaster left a voice mail message about an upcoming Eagle ceremony for one of the other boys in his troop, and that his attendance was “mandatory.” The only problem was, all he gave us was the name of the church where the ceremony was being held … no address, no city, nada.</p><p>After a Google search turned up just one church with that name several cities over, I asked my son to confirm if this was indeed the right church. So on the day of the ceremony, he made phone calls and left voice mail messages, trying to find out. No one, not the scoutmaster, his patrol leader nor any of the other boys in his troop responded. Finally, out of desperation, he posted the question on Facebook.</p><p>Within 15 minutes, three boys replied. I fear this does not bode well for the future of our youth.</p><p>Too often, we use Web 2.0 tools to avoid direct interaction. For instance, it’s easy to <a
title="Are You Hiding behind Marketing to Avoid Selling?" href="http://www.johntabita.com/hiding-marketing-avoid-selling/" target="_blank">hide behind marketing to avoid selling</a>. Don’t fall into that trap. When I give you the choice, pick up the phone and call me.</p><p>Why would I say that? Two reasons. One: I’m really, really busy. When you call me, you get first-mover advantage, because you’ve taken a task off my all-too-busy plate—the need to follow up on all the emails responses I received. I really don’t have time to “check out your website,” and then “give you a call.” Besides, your website probably contains the same generic fluff as everyone else’s. How about you demonstrate why you’re different and why I ought to hire you? You can do that by picking up the phone and having an actual conversation with me.</p><p>Reason Number Two is: it shows me you have initiative as well as people skills. You see, if I really have a need, I’m going to want to talk with you to determine if you are someone who can fill that need. If I’m the one hiding behind web 2.0 tools, asking you to communicate with me via email or Facebook, I may not be a genuine prospect at all. I might be someone who’s merely “interested,” or not far enough along in <a
title="What’s a Buying Cycle and Why Should I Care?" href="http://www.sitepoint.com/what%e2%80%99s-a-buying-cycle-and-why-should-i-care/" target="_blank">the buying cycle</a> to waste valuable time with. But if I’ve offered my phone number, than means I’d like to speak with a living, breathing person. That person could be you.</p><p>Here’s another tip: When I ask you to follow up if you haven’t heard back from me by such-and-such date, that might be a test. Calling me back shows me you want the gig.</p><p>What I didn’t mention is that there <em>was</em> a third firm that called; but he got the short straw—my voice mail—and never called back. If you have a genuine lead, keep pursuing it, even if they aren’t returning your calls. If you saw my desk, you’d know why I didn’t call you back.</p><p
style="text-align: right"><em><a
href="http://www.sxc.hu/profile/mikecco" target="_blank">Image credit</a></em></p><div
style="border-width: 1px;border-style: solid;border-color: #d5d5d5;padding: 8px;margin-top: 30px;margin-bottom: 30px;background: #e8e8e8">It’s not too late to get my free guide, <strong>27.5 Must-Ask Questions for Consultative Selling</strong>. Just <a
title="Twitter | @johntabita" href="http://twitter.com/johntabita" target="_blank">follow me on Twitter</a> and I’ll send you a link.</div> <span
id="pty_trigger"></span><div
style='padding:20px 0px 50px 0px;'><div
style='float:left;padding-left:40px;'><div
id='div-gpt-ad-1335489406190-0' style='width:300px; height:100px;'> <script type='text/javascript'>googletag.cmd.push(function() { googletag.display('div-gpt-ad-1335489406190-0'); });</script> </div></div><div
style='float:right;padding-right:40px;'><div
id='div-gpt-ad-1335489406190-1' style='width:300px; height:100px;'> <script type='text/javascript'>googletag.cmd.push(function() { googletag.display('div-gpt-ad-1335489406190-1'); });</script> </div></div><div
style='clear:both'></div></div><div
style='clear:both'></div><div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/SitepointFeed?a=LuoEhAAKKOg:XGRrOKfevG0:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/SitepointFeed?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/SitepointFeed?a=LuoEhAAKKOg:XGRrOKfevG0:qj6IDK7rITs"><img src="http://feeds.feedburner.com/~ff/SitepointFeed?d=qj6IDK7rITs" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/SitepointFeed?a=LuoEhAAKKOg:XGRrOKfevG0:gIN9vFwOqvQ"><img src="http://feeds.feedburner.com/~ff/SitepointFeed?i=LuoEhAAKKOg:XGRrOKfevG0:gIN9vFwOqvQ" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/SitepointFeed/~4/LuoEhAAKKOg" height="1" width="1"/>]]></content:encoded> <wfw:commentRss>http://www.sitepoint.com/get-hired/feed/</wfw:commentRss> <slash:comments>6</slash:comments> <feedburner:origLink>http://www.sitepoint.com/get-hired/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=get-hired</feedburner:origLink></item> <item><title>What do you need to know about HTML5 video</title><link>http://feedproxy.google.com/~r/SitepointFeed/~3/KB27UCF00rE/</link> <comments>http://www.sitepoint.com/what-do-you-need-to-know-about-html5-video/#comments</comments> <pubDate>Sat, 12 May 2012 15:00:55 +0000</pubDate> <dc:creator>Elena Vakhromova</dc:creator> <category><![CDATA[HTML5]]></category> <category><![CDATA[JavaScript]]></category> <category><![CDATA[HTML5 Dev Center]]></category> <guid isPermaLink="false">http://www.sitepoint.com/?p=51903</guid> <description><![CDATA[<img
width="50" height="50" src="http://www.sitepoint.com/wp-content/uploads/1/files/2012/02/HTML5_video-50x50.jpg" class="attachment-thumbnail wp-post-image" alt="HTML5_video" title="HTML5_video" />HTML5 keeps on stunning the Internet community with revolutionary web features. One of the key HTML5 enhancements is the advanced video support. In this post, I'd like to take a deeper look at HTML5 video element and explain its main points in plain English.]]></description> <content:encoded><![CDATA[<img
width="50" height="50" src="http://www.sitepoint.com/wp-content/uploads/1/files/2012/02/HTML5_video-50x50.jpg" class="attachment-thumbnail wp-post-image" alt="HTML5_video" title="HTML5_video" /><p></p><p>HTML5 keeps on stunning the Internet community with revolutionary web features. One of the key HTML5 enhancements is the advanced video support. With a new HTML5 standard, users don&#8217;t need any special plugins to stream video in web browsers both on PC or any portable device. Still in spite of the growing popularity of HTML5 standard, most web developers and designers are reluctant to migrate to the new markup language, maybe because of the absence of a complete HTML5 specification or lack of practical information on HTML5 сoding. In this post, I&#8217;d like to take a deeper look at HTML5 video element and explain its main points in plain English.</p><h2>&lt;video&gt; tag vs. &lt;object&gt; tag</h2><p>The <code>&lt;object&gt;</code> tag referrs to an embedded element within a web page: audio, video, Java applet, ActiveX, PDF, or Flash. The markup for this tag is fairly cryptic. Thus, if you wanted to embed a Flash video into a web page, you had to insert the following code:</p><pre>&lt;object id=0 type="application/x-shockwave-flash" data=player_flv_maxi.swf width=420 height=240
&lt;param name="movie" value=player_flv_maxi.swf /&gt;
&lt;param name="wmode" value="opaque" /&gt;
&lt;param name="allowFullScreen" value="true" /&gt;
&lt;param name="allowScriptAccess" value="sameDomain" /&gt;
&lt;param name="quality" value="high" /&gt;
&lt;param name="menu" value="true" /&gt;
&lt;param name="autoplay" value="false" /&gt;
&lt;param name="autoload" value="false" /&gt;
&lt;param name="FlashVars" value="flv=Wildlife.flv&#038;width=420&#038;height=240&#038;autoplay=0&#038;autoload=0&#038;buffer=5&#038;buffermessage=&#038;playercolor=464646&#038;loadingcolor=999898&#038;buttoncolor=ffffff&#038;buttonovercolor=dddcdc&#038;slidercolor=ffffff&#038;sliderovercolor=dddcdc&#038;showvolume=1&#038;showfullscreen=1&#038;playeralpha=100&#038;title=Wildlife.flv&#038;margin=0&#038;buffershowbg=0" /&gt;
</pre><p>To play this, users can&#8217;t do without a Flash player plugin which is ndispensable for all modern browsers except Google Chrome since the player is already pre-installed in the browser.<div
id='div-gpt-ad-1328644474660-10' style='width:728px; height:90px;'> <script type='text/javascript'>googletag.cmd.push(function() { googletag.display('div-gpt-ad-1328644474660-10'); });</script> </div></p><p>HTML5 introduces the new &lt;video&gt; tag which replaces the former &lt;object&gt; tag for Flash video embedment. The benefits of using HTML5 &lt;video&gt; tag are numerous. It brings not only minimalism and simplicity of video code, but also the ease of search bots to properly index your video file. Website developers can add a video to a page in the same way they would add an image, since the basic markup necessary for &lt;/video&gt;&lt;video&gt; in HTML5 is refreshingly simple and straightforward:</p><pre>&lt;/video&gt;&lt;video width="320" height="240" controls autoplay poster="video.jpg"&gt;
 &lt;source src="movie.mp4" type="video/mp4" /&gt;
 &lt;source src="movie.ogg" type="video/ogg" /&gt;
 Your browser does not support the video tag.
&lt;/video&gt;</pre><p>Such code can be easily composed even by a not tech-savvy specialist. In the simplest way the code may be reduced to:<code>&lt;video src="movie.mp4" controls width="320" height="480"&gt;&lt;/video&gt;</code></p><h2>Video Attributes</h2><p>As you can see, the &lt;video&gt; tag is used just like any other tags in HTML. Between opening and closing tags you can place various attributes to get the video player you want.</p><p>Several of the attributes are boolean (e.g. controls, loop, muted) &#8211; no value is required. So by including or omitting them, you set the value &#8220;true&#8221; or &#8220;false&#8221; respectively.</p><p>HTML5 specialists also recommend inserting the following line within video tag:<br
/> Video not playing? <code>&lt;a href="pics/video.mp4"&gt;</code><code>Download the file</code><code></code> instead.</p><h2>Controls</h2><p>The browsers supporting HTML5 video have the video players already built-in. All of them include a standard set of controls: Play, Pause, Seek, Volume. However, each browser provides its own look for the video player: from the minimal approach of Chrome and IE to the more elaborate controls of Firefox, Opera and Safari.</p><p>If you want to keep controls the same across all browsers, or integrate the player with our website design, you can create our own controls from scratch. Here are some useful resources:</p><li><a
href="http://videojs.com/">VideoJS</a> is an HTML5 video player built with Javascript and CSS;</li><li><a
href="http://sublimevideo.net/">Sublime Video</a> is a sleek cloud-based HTML5 video player with advanced feature set, a paidware;</li><li><a
href="http://www.projekktor.com/index.php">Projekktor</a> is an open source HTML5 video player built with pure JavaScript; it also uses Flash when there is no native H.264 support;</li><li><a
href="http://dev.opera.com/articles/view/custom-html5-video-player-with-css3-and-jquery/">Tutorial</a> “How to build a custom HTML5 video player with jQuery and CSS3” from Opera developers.</li><h2>Video source</h2><p>The &lt;video&gt; tag allows multiple &lt;source&gt; elements which can link to one and the same video in different formats, for example:</p><pre>       &lt;source src='movie.webm' type='video/webm; codecs="vp8.0, vorbis"'/&gt;
       &lt;source src='movie.ogv' type='video/ogg; codecs="theora, vorbis"'/&gt;
       &lt;source src='movie.mp4' type='video/mp4; codecs="avc1.4D401E, mp4a.40.2"'/&gt;</pre><p>As you see, the source tag has two attributes, src and type. The &#8220;type&#8221; attribute specifies the MIME type and possibly a list of codecs, which helps the browser to determine whether it can decode the file. By default, the browser will use the first recognized format. All modern browsers support at least one HTML5 video format.</p><h2>Browser Support</h2><p>For up to date information on browser support, you can check out the <a
href="http://www.youtube.com/html5">YouTube HTML5 Page</a></p><h2>Codecs</h2><p>There&#8217;s a long debate on which video formats/codecs to pursue and consensus hasn&#8217;t been reached yet. As a result, in the draft of HTML5 specification any references to a particular codec were removed. Instead, the following creteria to the video codec were put forward:</p><li>it should have good compression, good image quality, and low decode processor use;</li><li>be royalty-free;</li><li>feature hardware video decoder</li><p>Three codecs were suggested for HTML5 video element: H.264, OGG Theora, and WebM VP8. Here are their advantages and disadvantages.</p><h2>H.264</h2><p><strong>Pros</strong><br
/> It gives good quality video and small file sizes. It outputs excellent video both for low-bandwidth, low-CPU mobile devices and high-bandwidth, high-CPU modern PCs and everything in between. It&#8217;s free for Internet end-users.</p><p><strong>Cons</strong><br
/> The underlying compression mechanisms in H.264 are patented and adopters have to pay royalties for commercial use to a licensing consortium called MPEG-LA.</p><h2>OGG Theora</h2><p><strong>Pros</strong><br
/> It&#8217;s a royalty-free codec and is not encumbered by any known patents other than the original VP3 patents, which have been licensed royalty-free.</p><p><strong>Cons</strong><br
/> Theora generates high quality videos with comparatively larger file sizes. Plus it is a lot harder to find tools to convert to OGG Theora.</p><h2>WebM VP8</h2><p><strong>Pros</strong><br
/> In 2010, Google acquired On2 – the company behind VP8, and published the video codec specification as open source, and all the patents as royalty-free.</p><p><strong>Cons</strong></p><p>While Google claims that WebM has the highest video quality of all the web codecs, most independent sources find that either H.264 is slightly better or there is very little difference between the two. The problem is that it can be very difficult to find tools to encode video to WebM.</p><p>Until a complete consensus on video codecs issue is reached, web developers have to convert video to all these three formats. There&#8217;s some helpful software which deal with HTML5 video preparing:</p><li>Free Video Converter 3.0 by Freemake.com is a Windows software that encodes both desktop and online video to H.264, WebM and Theora OGG, the resulted videos go together with a sample of HTML5 video embedding;</li><li>alternatively, you can receive HTML5 source files as a result of video conversion with the help of the video tools listed here.</li><p>Some webmasters also combine HTML5 &lt;video&ht; element with Flash-based code, so that a video could be played in any browser, including old IE versions.</p><p>No doubt, HTML5 video still has a lot of benefits if compared to Flash. However, it&#8217;s still debatable whether H.264, WebM and Theora OGG will remain the default video formats supported in the video element. And since the specification of HTML5 video formats depends a lot on the decisions of Apple, Microsoft and Google corporations, the future of  the whole new standard seems vague but still promising.</p> <span
id="pty_trigger"></span><div
style='padding:20px 0px 50px 0px;'><div
style='float:left;padding-left:40px;'><div
id='div-gpt-ad-1335489406190-0' style='width:300px; height:100px;'> <script type='text/javascript'>googletag.cmd.push(function() { googletag.display('div-gpt-ad-1335489406190-0'); });</script> </div></div><div
style='float:right;padding-right:40px;'><div
id='div-gpt-ad-1335489406190-1' style='width:300px; height:100px;'> <script type='text/javascript'>googletag.cmd.push(function() { googletag.display('div-gpt-ad-1335489406190-1'); });</script> </div></div><div
style='clear:both'></div></div><div
style='clear:both'></div><div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/SitepointFeed?a=KB27UCF00rE:NYZYQG8s3b8:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/SitepointFeed?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/SitepointFeed?a=KB27UCF00rE:NYZYQG8s3b8:qj6IDK7rITs"><img src="http://feeds.feedburner.com/~ff/SitepointFeed?d=qj6IDK7rITs" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/SitepointFeed?a=KB27UCF00rE:NYZYQG8s3b8:gIN9vFwOqvQ"><img src="http://feeds.feedburner.com/~ff/SitepointFeed?i=KB27UCF00rE:NYZYQG8s3b8:gIN9vFwOqvQ" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/SitepointFeed/~4/KB27UCF00rE" height="1" width="1"/>]]></content:encoded> <wfw:commentRss>http://www.sitepoint.com/what-do-you-need-to-know-about-html5-video/feed/</wfw:commentRss> <slash:comments>10</slash:comments> <feedburner:origLink>http://www.sitepoint.com/what-do-you-need-to-know-about-html5-video/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=what-do-you-need-to-know-about-html5-video</feedburner:origLink></item> <item><title>Celebrate 20 Years of Wolfenstein 3D in Your Browser</title><link>http://feedproxy.google.com/~r/SitepointFeed/~3/88-8YdK3EX8/</link> <comments>http://www.sitepoint.com/wolfenstein-3d-html5-browser-game/#comments</comments> <pubDate>Sat, 12 May 2012 15:00:27 +0000</pubDate> <dc:creator>Craig Buckler</dc:creator> <category><![CDATA[Gems]]></category> <category><![CDATA[HTML & CSS]]></category> <category><![CDATA[HTML5]]></category> <category><![CDATA[JavaScript]]></category> <category><![CDATA[News & Trends]]></category> <category><![CDATA[Opinion]]></category> <category><![CDATA[Reviews]]></category> <category><![CDATA[canvas]]></category> <category><![CDATA[game]]></category> <category><![CDATA[HTML5 Dev Center]]></category> <category><![CDATA[HTML5 Tutorials & Articles]]></category> <guid isPermaLink="false">http://www.sitepoint.com/?p=54596</guid> <description><![CDATA[<img
width="50" height="50" src="http://www.sitepoint.com/wp-content/uploads/1/files/2012/05/673-wolfenstein-browser-50x50.png" class="attachment-thumbnail wp-post-image" alt="673-wolfenstein-browser" title="673-wolfenstein-browser" />Wolfenstein 3D was released 20 years ago. To celebrate the ground-breaking FPS game, you can now play an HTML5 version in your browser.]]></description> <content:encoded><![CDATA[<img
width="50" height="50" src="http://www.sitepoint.com/wp-content/uploads/1/files/2012/05/673-wolfenstein-browser-50x50.png" class="attachment-thumbnail wp-post-image" alt="673-wolfenstein-browser" title="673-wolfenstein-browser" /><p></p><p>Perhaps I&#8217;m showing my age but is it really 20 years since Wolfenstein 3D exploded onto the PC gaming scene? To celebrate that momentous occasion, the full game can now be played online within your browser at:</p><p><a
href="http://wolfenstein.bethsoft.com/"><strong>wolfenstein.bethsoft.com</strong><br
/> <img
src="http://blogs.sitepointstatic.com/images/tech/673-wolfenstein-browser-screen.png" width="500" height="320" alt="Wolfenstein 3D browser version" class="center" style="margin: 5px auto 20px auto" /></a></p><p><em>(Note the game is recommended for those over 12 and banned in Germany and several other countries).</em></p><p>The site states it&#8217;s compatible with IE9, Firefox, Chrome and Safari &#8212; although Opera seems to work if you&#8217;re not too bothered by a few graphical glitches. The game is mouse-enabled (set it within the configuration options) although few PCs had mice in 1992 and you&#8217;ll find keyboard control best.</p><p>Wolfenstein was released as DOS shareware in 1992. The web was largely unknown and bulletin boards were the reserve of rich geeks but, despite a lack of social networks and online file sharing, word spread and so did thousands of 720kB floppy disks. Suddenly, there was a reason to use a PC for more than Lotus-123 spreadsheets.<div
id='div-gpt-ad-1328644474660-10' style='width:728px; height:90px;'> <script type='text/javascript'>googletag.cmd.push(function() { googletag.display('div-gpt-ad-1328644474660-10'); });</script> </div></p><p>So why the fuss? Wolfenstein started the 3D first-person gaming genre. In 1992, there were relatively few 3D games and most resorted to isometric graphics (Marble Madness, Paperboy), wire-frame (Star Wars, Elite, Starglider) or faked overlaid 2D sprites (Outrun, Chase HQ, Space Harrier). True 3D games were available in the arcades (I-Robot, Hard Drivin&#8217;) but they took themselves a little too seriously and couldn&#8217;t be replicated on the 16-bit PCs of the day.</p><p>I remember playing Wolfenstein for the first time; it changed my perceptions about what could be achieved on a PC. While it looks basic today, having the freedom to explore realistic 3D rooms blasting stuff was revolutionary &#8212; and shouldn&#8217;t have been possible given the hardware limitations.</p><p>More importantly, the game was fun; you played a prisoner trying to escape from a Nazi-controlled castle in World War II. The VGA gore was amusing and you could defeat a robotically-enhanced Hitler at the end of the game. That said, not everything was perfect. The walking movement was unrealistically smooth and the corridor map was always rectangular &#8212; combine that with may hours game play and Wolfenstein remains the only game which made me feel genuinely queasy!</p><p>iD Software&#8217;s success with Wolfenstein led to Doom a year later &#8212; it&#8217;s fair to say you wouldn&#8217;t be playing <em>Call of Duty</em> today if it weren&#8217;t for those two ground-breaking games.</p><p>A version of Wolfenstein was released on almost every computer and gaming platform <em>(even Nintendo permitted the gore-fest on their family-friendly consoles, although iD were instructed to replace guard dogs with large rats)</em>. The browser version if faithful to the original DOS version and permits you to play every level. Actually, it probably plays and sounds better than it did on the latest 386 PCs we had in 1992.</p><p>Technically, the game is implemented using JavaScript and HTML5 audio. I first thought it was rendered using a <code>canvas</code> element but, thanks to further investigation by Matt Vaughan (below), it&#8217;s actually 320 horizontally-stacked DIVs which have their background, vertical size and top location modified as you move around. It&#8217;s clever but slightly unusual solution. The full page weight is a little over 800kB of mostly uncompressed JavaScript &#8212; impressive given that most sites use that for their home page.</p><p>But who cares about the technical details &hellip; <a
href="http://wolfenstein.bethsoft.com/"><strong>Happy Birthday Wolfenstein 3D</strong></a> and thanks for 20 great years of great gaming.</p> <span
id="pty_trigger"></span><div
style='padding:20px 0px 50px 0px;'><div
style='float:left;padding-left:40px;'><div
id='div-gpt-ad-1335489406190-0' style='width:300px; height:100px;'> <script type='text/javascript'>googletag.cmd.push(function() { googletag.display('div-gpt-ad-1335489406190-0'); });</script> </div></div><div
style='float:right;padding-right:40px;'><div
id='div-gpt-ad-1335489406190-1' style='width:300px; height:100px;'> <script type='text/javascript'>googletag.cmd.push(function() { googletag.display('div-gpt-ad-1335489406190-1'); });</script> </div></div><div
style='clear:both'></div></div><div
style='clear:both'></div><div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/SitepointFeed?a=88-8YdK3EX8:eGbg1kv-cMg:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/SitepointFeed?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/SitepointFeed?a=88-8YdK3EX8:eGbg1kv-cMg:qj6IDK7rITs"><img src="http://feeds.feedburner.com/~ff/SitepointFeed?d=qj6IDK7rITs" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/SitepointFeed?a=88-8YdK3EX8:eGbg1kv-cMg:gIN9vFwOqvQ"><img src="http://feeds.feedburner.com/~ff/SitepointFeed?i=88-8YdK3EX8:eGbg1kv-cMg:gIN9vFwOqvQ" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/SitepointFeed/~4/88-8YdK3EX8" height="1" width="1"/>]]></content:encoded> <wfw:commentRss>http://www.sitepoint.com/wolfenstein-3d-html5-browser-game/feed/</wfw:commentRss> <slash:comments>9</slash:comments> <feedburner:origLink>http://www.sitepoint.com/wolfenstein-3d-html5-browser-game/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=wolfenstein-3d-html5-browser-game</feedburner:origLink></item> <item><title>SitePoint Podcast #162: Taking Google For A Drive</title><link>http://feedproxy.google.com/~r/SitepointFeed/~3/_Rm7GsQ7E8w/</link> <comments>http://www.sitepoint.com/podcast-162-taking-google-for-a-drive/#comments</comments> <pubDate>Fri, 11 May 2012 22:15:45 +0000</pubDate> <dc:creator>Karn Broad</dc:creator> <category><![CDATA[Podcast]]></category> <category><![CDATA[Google Drive]]></category> <category><![CDATA[marketshare]]></category> <category><![CDATA[silent upgrades]]></category> <guid isPermaLink="false">http://www.sitepoint.com/?p=54592</guid> <description><![CDATA[Episode 162 of The SitePoint Podcast is now available! This week the panel is made up of 3 of our 4 our regular hosts, Patrick O&#8217;Keefe (@ifroggy), Kevin Dees (@kevindees) and Stephan Segraves (@ssegraves). Listen in Your Browser Play this episode directly in your browser &#8212; just click the orange “play” button below: Download this Episode You [...]]]></description> <content:encoded><![CDATA[<p></p><div><p>Episode 162 of The SitePoint Podcast is now available! This week the panel is made up of 3 of our 4 our regular hosts, Patrick O&#8217;Keefe (<a
href="http://twitter.com/ifroggy">@ifroggy</a>), Kevin Dees (<a
href="http://twitter.com/kevindees">@kevindees</a>) and Stephan Segraves (<a
href="http://twitter.com/ssegraves">@ssegraves</a>).</p><h2>Listen in Your Browser</h2><p>Play this episode directly in your browser &#8212; just click the orange “play” button below:</p><p></p><h2>Download this Episode</h2><p>You can download this episode as a standalone MP3 file. Here’s the link:</p><ul><li><a
href="http://media.libsyn.com/media/sitepoint/sitepointpodcast162.mp3">SitePoint Podcast #162: Taking Google For A Drive</a> (MP3, 44:50, 43.0MB)</li></ul><h2>Subscribe to the Podcast</h2><p>The SitePoint Podcast is on iTunes! <a
href="http://itunes.apple.com/WebObjects/MZStore.woa/wa/viewPodcast?id=296180681&amp;s=143441">Add the SitePoint Podcast to your iTunes player</a>. Or, if you don’t use iTunes, you can <a
href="http://www.sitepoint.com/blogs/?feed=podcast">subscribe to the feed directly</a>.</p><h2>Episode Summary</h2><p>The panel discuss Adobe launching a host of Cloud services to go with CS 6 and also kicks off a new website dedicated to the open web. We also take a moment to remember web design pioneer Hillman Curtis and talk about the future of advertising on the Web.<div
id='div-gpt-ad-1328644474660-10' style='width:728px; height:90px;'> <script type='text/javascript'>googletag.cmd.push(function() { googletag.display('div-gpt-ad-1328644474660-10'); });</script> </div></p><p>Here are the main topics covered in this episode:</p><ul><li><a
href="http://techcrunch.com/2012/05/01/comscore-samsung-widens-lead-as-top-mobile-brand-in-u-s-android-51-of-all-smartphones/">ComScore: Samsung Widens Lead As Top Mobile Brand In U.S., Android 51% Of All Smartphones | TechCrunch</a> via <a
href="http://www.revenews.com/cashing-out/cashing-out-week-of-april-29th-may-5th-2012-in-online-marketing-news/">Mobile Marketshare on Revenews.com</a></li><li><a
href="http://thenextweb.com/apps/2012/05/04/foursquare-launches-a-new-history-page-to-search-all-of-your-past-check-ins/">Foursquare Launches New &#8220;History&#8221; Page</a></li><li><a
href="http://davidwalsh.name/silent-browser-upgrades">Silent Browser Upgrades | David Walsh</a></li><li><a
href="http://googleblog.blogspot.com/2012/05/google-hangouts-on-air-broadcast-your.html">Official Google Blog: Google+ Hangouts On Air: broadcast your conversation to the world</a></li><li><a
href="https://drive.google.com/">Google Drive</a></li></ul><p>Browse the full list of links referenced in the show at <a
href="http://delicious.com/sitepointpodcast/162">http://delicious.com/sitepointpodcast/162</a>.</p><h2>Host Spotlights</h2><ul><li>Patrick: <a
href="http://www.youtube.com/user/blamesocietyfilms/videos">BlameSociety Videos</a></li><li>Stephan: <a
href="http://reviewsindepth.com/2011/04/why-everyone-should-learn-to-program/">Reviews In Depth | Why Everyone Should Learn to Program</a></li><li>Kevin: <a
href="http://webdesignledger.com/inspiration/20-inspiring-examples-of-big-backgrounds-in-web-design">20 Inspiring Examples of Big Backgrounds in Web Design | Inspiration</a></li></ul><h2>Interview Transcript</h2><p><strong>Patrick:</strong> Hello and welcome to another edition of the SitePoint Podcast.  This is Patrick O’Keefe and I’m joined today by my usual co-hosts Kevin Dees and Stephan Segraves; hey guys, how’s it going?</p><p><strong>Kevin:</strong> Howdy, howdy.</p><p><strong>Stephan:</strong> Hi.</p><p><strong>Patrick:</strong> As you may notice we are without our other usual fourth co-host, he usually introduces the show, Louis Simoneau, he’s off with important business-like errands to attend to, or something along those lines, and we’ll be holding the fort down today in his absence.  So I guess let’s go ahead and jump into the stories.<br
/> I’ll take the first story today, on TechCrunch there was a story by Ingrid Lunden that caught my eye, it is about mobile hardware and operating system market share for the three months ending in March, this is according to ComScore and I found this story through Revenues.  So the story has essentially three main numbers, like I said, hardware, software and then also usage through mobile, like use a downloaded app, use the browser, etcetera.  So here are some of the numbers: for hardware you have Samsung in the lead with 26% of the market, that is a gain of .7% from the three months ending in December, in other words the previous three-month period.  LG second with 19.3% with a small loss, Apple is third at 14% with a 1.6% gain, then you have Motorola fourth and HTC 5th, Motorola with 12.8% of the market and HTC with 6.0%, and that represents small losses for both of those brands.<br
/> As far as our branding systems go, Google remains in the lead by a healthy margin with 51% of the market, that is a 3.7% change, and then you have Apple at 30.7%, a gain for them as well of just over a percentage point.  And then you have a big loss from Blackberry from Research in Motion moving down to 12.3%, losing 3.7 percentage points.  Microsoft is in at 3.9, a loss for them, and then Symbian, finally, maintains its ground at 1.4%.<br
/> I don’t know, I guess Symbian is what I have, right?  I don’t know what’s in this small, little, cheap pay-as-you-go phone.</p><p><strong>Kevin:</strong> So, looking at these numbers for the platform specifically, not the hardware but the platform side, it comes to my attention that when you think about like jQuery plugins and CSS tricks and all this stuff, it’s like people tend to move towards the iPhone, and yet Android has continued, or Google, has continued to be the platform of choice, and I understand why, people like the iPhone in development for the reason that it’s fairly consistent across their browser space, whereas Android you have different screen sizes per phone, and all this other stuff that really makes it hard to develop for.  But, I think it is worth drawing attention towards.</p><p><strong>Stephan:</strong> Along those lines, why is the environment so much different then, because you see a lot of development for iPhone apps and very little for Android apps, and not very little in the sense that no one’s developing anything, but because you don’t really hear a lot about Android apps, right, the Instagram app was a big deal.  But I think it comes down to Android users aren’t necessarily willing to pay for apps, right.</p><p><strong>Patrick:</strong> There have been a bunch of different articles suggesting just that, and the numbers bear it out that Apple customers, Apple users, IOS mobile users are just more likely to pay for apps, they’re in Apple’s ecosystem.  Whereas the Android is &#8212; the Android platform is a little more, well, it’s more open, but I mean I guess the downside of that some would say that it’s more disjointed; you know, there are different versions, there are different app market places, you know I’m a Kindle user, Kindle Fire, it’s Android, you know it’s not the current version, it’s the version that Amazon took and made to fit their tablet, and they have their own app marketplace that sells both to the Android platform, in the latest version, but also with a particular focus on the Kindle Fire.  And I download a number of apps, and I downloaded probably hundreds of apps by this point, eh, I would say over a hundred, to be conservative, and I’ve paid for &#8212; I want to say I’ve paid for about 30 apps or so, most of which were on sale or half off or some kind of discount is what prompted me and pushed me to buy them then, you get a lot of the free app of the day and other free apps, but yeah, I don’t know, it’s an interesting dilemma, but as a developer it feels like it’s silly to ignore Android.</p><p><strong>Kevin:</strong> Right, I would agree with you there.  I mean and I guess it’s sort of the point I’m trying to make, but more than that, you know I was focusing a little more towards the Web, the Web side of thing, because that’s what I deal with on a daily basis.</p><p><strong>Patrick:</strong> Right.</p><p><strong>Kevin:</strong> And that part of it is with the iPhone your screen size is always going to be the same, right, and I think that’s really &#8212; I’m harping on this because it is kind of a big deal in that when you create an iPhone app you have a set number of pixels, I believe it’s 320 pixels for the low resolution, and 640, this is Portrait mode I believe, yeah, Portrait mode that you would be in, and so like with Android I mean the array is just massive.  And so I’m mostly referring to things like jQuery mobile and that kind of stuff, which do support Android platforms and that kind of thing, but it’s just interesting for me to like look at these numbers and then see the reflection in like when you see the community talking, right, it’s mostly about the iPhone, you rarely see anything about Android when it comes to Web stuff.<br
/> I think that’s a little bit of sort of the culture of the web design community, right, because everybody that makes websites needs to have ‘The Mac’, you know, you can’t use Windows, kind of thing.</p><p><strong>Patrick:</strong> You can’t be like Patrick.</p><p><strong>Kevin:</strong> But it’s true, though, right?</p><p><strong>Patrick:</strong> Right.</p><p><strong>Kevin:</strong> You do have that little bit of this hatred towards anything other than Apple because in design, right, you want it to be beautiful and to be honest a lot of Windows stuff isn’t just breathtaking.</p><p><strong>Patrick:</strong> Right.  Or at least they have that reputation that continues to follow them.</p><p><strong>Kevin:</strong> Right.  And I think it’s good to look at the numbers and see numbers like this to kind of bring you back to reality because you can get lost in this Apple world.</p><p><strong>Patrick:</strong> And they also said that they are &#8212; was data on the mobile content usage, and there are six categories; send a text message to a phone, that number stays steady, 74.3% of Smart Phone and non-Smart Phone, hello, users sent a text to another phone, 50% used downloaded apps, that’s a 2.4 percentage point change, 49.3% used a browser, that’s a gain also of almost two percentage point, 36.1% access a social networking site or blog, which is just a weird categorization to me; you access a social networking site, or any blog, 36.1%, a gain, played games 32.6%, listened to music on a mobile phone 25.3%, both of those gains of 1.2 and 1.5.  So all actions gained moreorless, but still only less than 50% of the Smart Phone and non-Smart Phone of mobile users age 13 and up in the U.S. used a web browser, so not even 50%.<br
/> Is that surprising?  Is that meaningful in any way?</p><p><strong>Kevin:</strong> Yeah, I think like when you look at these numbers I mean it’s growing, right, and I think that’s the key to pull out of this is that mobile is continuing to grow as statistics have shown, and it will only continue to do that in the future.  And the reason that this even pulls at it even more is these are competitor brands and things like that that we’re talking about, right, so it is a saturated space in that companies are taking it seriously and not just because there’s money in it but because there’s like &#8212; there’s brand awareness in it as well because so many people are using it, I mean Microsoft jumped in the game, right.</p><p><strong>Patrick:</strong> Right.  And you know technically speaking back in November I actually accessed the web browser on my cheap pay-as-you-go phone because someone actually &#8212; Chris Cochran, Christopher Cochran who works for webdevestudios.com, which is the company of Brad Williams who was one of the original four hosts on the SitePoint Podcast here, he had developed a website and it was spitting out what mobile browser you were on and adjusting for that, and so he’s like will it even recognize this?  So we pulled it up and sure enough it recognized it; I forget as what, and it took some time, but I did get to Chris’ website, so &#8211;</p><p><strong>Kevin:</strong> That’s awesome.</p><p><strong>Patrick:</strong> I do have a browser.</p><p><strong>Kevin:</strong> Did he reimburse you for the data usage?</p><p><strong>Patrick:</strong> (Laughs) no, he didn’t.  I don’t know what it cost me, probably &#8212; I don’t know, it probably cost me, hmm, I don’t know, fifty cents or something like that.</p><p><strong>Kevin:</strong> To load a web page?</p><p><strong>Patrick:</strong> (Laughs) well spent.</p><p><strong>Kevin:</strong> That’s a soda out of the soda machine, Patrick.</p><p><strong>Patrick:</strong> Yeah.</p><p><strong>Stephan:</strong> I think this breakdown of mobile content usage it would be interesting if they broke it down even more and said which platforms did what more.</p><p><strong>Patrick:</strong> Right, that’s a good point.</p><p><strong>Stephan:</strong> I think that would be cool to see like if &#8212; are Android users using downloaded apps more than web browser stuff?  And I think that may give us more of a look at how people are actually using the phones and whether we should be developing more and more web apps for Android than say regular native apps.  It’s just interesting to me; I think maybe this all brings us back to developing just responsive web applications that aren’t specific to a platform, right, I don’t know.</p><p><strong>Kevin:</strong> Yeah, definitely.  Especially like when you think about the development of just the desktop platform, right, where a lot of stuff you do would be in apps, but since bandwidth has become increasing like web apps aren’t that uncommon and they’ve become quite popular when you think about 37 Signals and companies like that that are built on it, Twitter, social networks, you know.</p><p><strong>Stephan:</strong> Yeah.</p><p><strong>Kevin:</strong> And that goes into the Smart Phone industry as well, right.  So now with 4G LTE, I believe that’s correct, right; I don’t have LTE here or 4G or anything like that.</p><p><strong>Patrick:</strong> Right, sounds right.</p><p><strong>Kevin:</strong> But that’s high, high speed Internet right there, and with that kind of capability there’s no reason, like you were saying, Stephan, that we can’t come to a place where web apps take over the mobile space above built-in apps, and I’m not saying that that’s actually 100% true because, you know, the phone makers are pushing their marketplaces on the phone, and it’s so easy to buy an app, you know.</p><p><strong>Stephan:</strong> Yeah, yeah, but I think you’re absolutely right, there are certain things now that are easier to do on the phone, and you can make it cross-platform available to everyone without having to distribute the application, right, the websites, the distribution point.  So I think the possibilities there are great, and I hope to see more companies push a web application via the actual web interface and not necessarily through an application, a native application.</p><p><strong>Kevin:</strong> Right.</p><p><strong>Patrick:</strong> On a related note, I just saw a story on The Next Web that was reported today, they are recording May 7th, by Anna Heim, it says that Twitter has updated its mobile web version, <a
href="http://mobile.twitter.com/">mobile.twitter.com</a>, and according to their announcement the purpose of the update was to improve the Twitter experience for users who access the platform from feature phone, low bandwidth networks and older browser, so there you go.  It’s a market they want to tap into.</p><p><strong>Stephan:</strong> Cool.  Speaking of web apps and phone apps, Foursquare today launched a new history page so you can search all of your past check-ins, this is being reported on The Next Web, the writer is Drew Olanoff, and he’s just reporting on the feature, and you can search, it shows a map of all your check-ins, and it basically lets you access all your old history data on Foursquare.  A pretty neat little feature, I’ve played with it a little bit, it doesn’t look like you can actually share it with anybody, which is kind of a feature to me; I don’t know if I want everybody stalking my history.</p><p><strong>Patrick:</strong> Yeah, I was curious about that myself, is that something that you can enable or disable, or is it just something that’s out there for the public?</p><p><strong>Stephan:</strong> I don’t see an option to do it, but what’s odd when I go look at my history I can see old comments on my check-ins and the friends that were at the same locations of those check-ins, so that’s kind of cool.</p><p><strong>Patrick:</strong> Yeah, I’m looking actually &#8212; we must be friends so I’m just going to see.  No, we’re not friends, what the heck?</p><p><strong>Stephan:</strong> Man, Patrick!</p><p><strong>Patrick:</strong> Stephan, man, add me now.</p><p><strong>Kevin:</strong> Tsk, tsk.</p><p><strong>Patrick:</strong> Foursquare.com/ifroggy, I have nine total check-ins, so with my non-Smart Phone, or is it called a feature phone, is that kind of the cool name for it, feature phone?  I don’t really check-in, so, I check in from a browser whenever I check-in; last time I did so was last &#8212; I guess that’s October, the Westin Bonaventure Suites and Hotel in Los Angeles.  I don’t know why that’s funny, but, yeah, that’s the last time I checked in, it was October, or September, I’m sorry, September 2011.</p><p><strong>Kevin:</strong> So, Patrick, you’re looking for &#8211;</p><p><strong>Patrick:</strong> I’m looking at my history now.</p><p><strong>Stephan:</strong> What’s cool about all this, to me at least, is that now a simple check-in allows me to build a map of my travels and things, rather than me having to write something down or take a note in my phone or, you know, I’m kind of anal retentive about all this kind of stuff, just remembering where I was and things, so this is useful to me and it gives me another reason to use Foursquare even if I make it private.</p><p><strong>Patrick:</strong> Right.  And I looked at your profile, I can see the last five history and that’s all.</p><p><strong>Stephan:</strong> Yeah, which is cool, I’m glad, I don’t want you going and stalking my last year’s check-ins; if I want to share that information with you I will.</p><p><strong>Kevin:</strong> So if you show up at a Starbucks at five o’clock in the morning you’ll always run into Patrick, right, according to this history.</p><p><strong>Patrick:</strong> Yeah, you’ll run into me if I’m sleepwalking.</p><p><strong>Kevin:</strong> (Laughs) yeah, it’s an interesting story, it reminds me of Google’s Latitude that they put out a while back where you could track your location and kind of your most common places of interest.</p><p><strong>Stephan:</strong> Yeah, it’s neat, it’s neat, so it’s a step in the right direction, I’m sure people won’t like it or they’ll have some complaint about it, but I think it’s a good step.</p><p><strong>Kevin:</strong> Alright, so I have a story on silent browser upgrades, since Mozilla has released version 12 of their browser it’s now silent upgrading time.  And so this has kind of created a little bit of a stir in the web community, but it’s kind of a new thing but not really since Chrome has been doing it for quite a while, but it’s new for Mozilla and Internet Explorer plans to trail them on this, so it’s becoming the trend of the Web now, for desktop browser specifically here, in that the browsers want their latest version on your computer as soon as possible, and I can’t say I disagree with that.<br
/> So this article kind of goes through step-by-step parts of the reasons why it’s a good thing for this to happen, and I like the story in short because it is short, and because it covers some of the practical things and thoughts behind browser silently upgrading themselves.  Some of the points I like are the Internet Explorer example that it has which basically says that because of Internet Explorer 6 sitting stagnant for so long there’s no way to get that upgraded to Internet Explorer 8 even if you’re on XP because you can’t silently upgrade, and so if they had had that everyone, you know, we would have gotten rid of this Internet Explorer 6 issue a lot sooner.<br
/> And so things like user agent sniffing is gone now in replace of feature detection, things like that that you can do, and that UA detection isn’t as good because like if the browser’s upgrading itself then you have to update your script, and so the best way to really detect what version is through the feature detection.  And there are other things, he points out some things, but those two points I think are the biggest for me which is the Internet Explorer.<br
/> And also, thirdly, he makes his first point which is you have to see past your expertise, right, because we’re all kind of webbies, but the normal person they just say well I just click on the blue E and it takes me to the Internet, right, that’s the Internet, the blue E, like they don’t even know that it’s Internet Explorer, and so like that even furthers the point of, you know what, these people aren’t gonna upgrade their browsers because they don’t even know what it is to begin with, like unless there’s a popup on their screen, which people are already wary of, right, because of viruses, especially if you’re a Windows user, you know, it’s like it’s just one of those things where it’s like it’s about time, it’s a breath of fresh air in my opinion.</p><p><strong>Patrick:</strong> I mean the tricky thing here, and of course the kind of other side of this is that, you know, talking about Microsoft, Google, some might think of them as Big Brother in a way, you know, pushing things down at their leisure into your computer, right, and I guess there are cases where &#8212; this isn’t something we want to see proliferate into every application, right, this isn’t something we want, we don’t necessarily want silent upgrades in every piece of software that we have installed on our machine.</p><p><strong>Kevin:</strong> Correct.</p><p><strong>Patrick:</strong> Web browsers are kind of a special case just because they are used to access the wild, wild, Web, right, the wilderness that could be full of who knows; not only do you have the nefarious things like viruses or malware, and they may exploit an outdated browser, but then you have certainly for our audience, the developer concerns, having as much of a consistent experience as possible for a majority of your visitors regardless of the browser that they are using.  And so ensure that you need people to be using similar standards and adhering to similar practices where the browsers will read a certain piece of code the same way, whether the wide variance that exists between say Internet Explorer 6 and even Internet Explorer 10 or Firefox or Chrome.  You know, but there is that concern there, and like I said, this isn’t something you want to see in everything, is it?</p><p><strong>Kevin:</strong> No, not at all, to be honest there’s not much you can do to get around the malicious type of software that they’re just gonna do this anyways, right, I mean they put themselves on your computer just by visiting a website, you don’t even have to click a button sometimes.</p><p><strong>Patrick:</strong> Right.</p><p><strong>Kevin:</strong> And so there are things that the browsers are doing like, for example, Firefox allows you to stop the automatic updates if you want to, so, you know, for example in the comments there’s one fellow here who uses a CMS but he can’t get it to work on many browsers except for Firefox 3, so what does he do, he turns those off and he’s okay.<br
/> You know something I thought was very interesting is I was using Firefox one day and then all of a sudden it just updated without me asking it to, and so I don’t know what happened there.</p><p><strong>Patrick:</strong> You’re like, oh, Firefox you sly devil.</p><p><strong>Kevin:</strong> Yeah.  So like it would have been interesting to have had like a box to select or something, like maybe I did check it and I just didn’t realize it, sort of like Windows XP had before where you would get automatic updates with I believe service pack 2.</p><p><strong>Patrick:</strong> Yeah, and it’s true what you say about popups, because I can say I use my computer and every time I see a popup to upgrade something oftentimes it is Adobe, something Adobe, Adobe Air or &#8211;</p><p><strong>Kevin:</strong> Flash.</p><p><strong>Patrick:</strong> Flash, right, even Acrobat; and sometimes there’s a prompt for Java, to upgrade to the latest version of Java, since I have those notifications on, and then you have a few other things here and there, I use a program called Malware Bites, and once in a while that’ll prompt me for a new version.  But then I go use the computer that my family has that they use, and that’s my brother and my parents, and they’ll just ignore those popups forever (laughs), they will not touch those things until I get there and see the pile-up of, well, everything needs to be updated outside of Windows because Windows will restart, you know, will say we’re gonna do this, you have four hours if you want, but we really need to do this.<br
/> And so, yeah, I mean it’s funny how that is the case.  So it’s a tricky era that we live in where we’re concerned about so many different areas of privacy and control, certainly Facebook is constantly in the news regarding those issues, you have legislation, SOPA, PIPA, SYSA, SYSPA, and anything else that ends with an A.  And then you have those issues and people are going to have concern about their privacy, and yet, they want to allow some of these major companies that are parties to these legislations, sometimes pro, sometimes against, but just to install things onto the computer.  And, on the other hand, you have people like my family who won’t upgrade anything and might be vulnerable, so I don’t know what the &#8212; I guess it is we have to go down this road, and if any company abuses it, and I don’t think any reasonable company will, but there’s always that chance that there’s that one person who does something, you know, it’s gonna be a major news story, and then we’re gonna have CNN talking about, well, Mozilla, Google, they were pushing updates to your computer without your permission, find out more at 11:00.</p><p><strong>Kevin:</strong> Yeah, and they were stealing your data and all your documents and finding out what you wrote to your ex-wife, kind of thing.</p><p><strong>Patrick:</strong> Right, because it’s an issue that once it’s in the mainstream it’s much like the legislation really, a lot of people will talk about it but very few people will understand it.  And that’s exactly the kind of issue that that would be, you know, the news will grab onto it as a headline and it is newsworthy, and if I a company does abuse it, it deserves to be put out there.  But then you create this fear, and 99%, similar to what Mr. Wall says in this blog post, 99% of users don’t care what browsers they’re using, well, that’s the same 99% that won’t understand this issue if it goes wrong.<br
/> But I don’t know, I don’t see any other way, so actually I’m interested to see the browsers kind of widely adopting this practice, and I have to say I like the logo on this blog; have you put your mouse over it?</p><p><strong>Kevin:</strong> I have not, let me try, ooh.</p><p><strong>Patrick:</strong> Put your mouse over that thing.</p><p><strong>Kevin:</strong> Oh my gosh, that’s kind of rockin’ right there, literally.</p><p><strong>Patrick:</strong> It’s kind of like a vinyl record.  It’s like “wiki wiki wiki”.</p><p><strong>Kevin:</strong> I’m a DJ on this website; check it out, what’s up.  Yeah, I think it’s an interesting story and one to watch for, you know, because part of this also is with the silent update thing, right, what happens when, for example, like silent updates maybe for Internet Explorer 8 versus 9, like you can’t get Internet Explorer 9 on Windows XP.  Now there’s good reason for that, but you know situations like that where it’s more than just them trying to update your computer, it’s like a physical limitation of the device you have, and like the conflicts that that creates.</p><p><strong>Patrick:</strong> Yeah, and I was just looking at operating system percentages for the visitors on one of the communities that I manage, and someone asked other members what they were using, and so I posted the, first of all, the operating system itself, and then they wanted a breakdown of Microsoft and the Windows Operating Systems, and I have 57.54% on 7, 28.60% on XP, 13.3% on Vista, and then small percentages beneath that; Windows server 2003 was .37% and then it kind of went down, and we had one visit from Windows ME, this year.<br
/> So, yeah, I mean you have 28.60% of Windows visitors, which represent a majority, and those people won’t be able to get those newer versions of IE, and you still have to, you know, there’s still a sizable part of the website.  So even with automatic upgrades eventually if they don’t upgrade the operating system it seems like the upgrades will come to an end.<br
/> So, speaking of Google, we have a post here from the Google official blog announcing that Google+ Hangouts on Air is now available worldwide, and previously this was a feature that was in Beta.  Basically it allows you to put a live broadcast out there on the Web in Google+ and on your YouTube channel, if you so desire, hangouts have been around for a while, of course, they are kind of one of the Google+ killer features, if you will, get together with a group of people that you know and talk and have a nice video chat; I’ve actually done that with you Kevin.</p><p><strong>Kevin:</strong> Yes, and we also did Turntable that day I believe.</p><p><strong>Patrick:</strong> Yeah, we actually were on, we just kind of shut down the Internet, we broke the tubes.  So, yeah, we were on Google Hangouts and playing around with <a
href="http://turntable.fm/">turntable.fm</a> listening to music as well, so that was fun and I’ve done a few hangouts, I did one actually for Dell in I believe it was February on Community Manager Appreciation Day they did a community manager kind of one-hour event where we did some presentations for ten minutes each, and I participated in that, and Dell has done a bunch of stuff on their Google+ page.  But so the Google Hangouts on Air take you to a different level allowing you to be live to the world.  And if you have a popular YouTube channel that’s another way to engage with your audience, to have a live stream and to have people actually participating with you and talking with you as you’re doing it, and there’s a million different uses for that, obviously, but the thing that struck me about this is there are entire companies that are built to satisfy this need, UStream comes to mind immediately, there’s one that we use for my other podcast, Copyright 2.0 show called SPRAYcast.<br
/> And they have other features, right, you can display questions on the video player, they record the videos, which Google is doing with Google Hangouts on Air, and you can have two people on the screen at one time, you can have four people on at one time on the same kind of screen looking at all four people, there are a lot of different things that you can do with it; Google+ Hangouts allows you to have people on the screen but only one person gets the main camera.  Those are really small differences, and to me if you can be on YouTube live, no offense to UStream or anyone else, but why would you want to be on UStream live?  Is that a fair thought or what do you think about competition in that kind of live streaming space now that Google is essentially saying we are definitely in?</p><p><strong>Stephan:</strong> So my question is when do we do a live stream of the show on this and try it out.</p><p><strong>Patrick:</strong> I don’t know.  I was thinking about that.</p><p><strong>Stephan:</strong> We should give a test drive; if we’re gonna talk about it we should at least try it out.</p><p><strong>Patrick:</strong> Right, well, you know, I haven’t done Google Hangouts on Air, and that’s an interesting point, and if you’re listening to this and you’d be interested in us doing this show live leave a comment at <a
href="http://sitepoint.com/podcast/">sitepoint.com/podcast</a> on this episode and let us know if that’s something that you’d like to watch.  But, yeah, that’d be fun, but yeah, I mean I don’t know, it’s interesting, I’m planning on doing more video stuff this summer, and I think there’s a great opportunity there for a lot of popular YouTubers to kind of take their channel to another level rather than having to, you know, previously it was kind of weird, you have this kind of divide, right, and I think some might argue that YouTube and Google were kind of slow to it, but maybe they were just waiting for the right time, right, the right network, the right bandwidth to kick this feature out, because it does take a lot of bandwidth, and so you had this divide of services that host video, like YouTube, Blip.tv, and so on, and then you have services that hosted live video, you know, you weren’t uploading videos to them, that live video was all that they do, and we did live SitePoint podcasts at WordCamp Raleigh two years in a row and used UStream in both cases to stream that show out, but you know if we were to do it now I don’t see a reason why we wouldn’t use Google+ instead since they are essentially matching the video hosting, the great functionality they have at YouTube, you know all the little things they do whether it be captioning or links in videos or all the great user features with the functionality that these other dedicated startups already had.</p><p><strong>Stephan:</strong> I think one key thing that will increase the YouTube usage, or increase this feature usage, is I think a lot of people were hesitant to go to websites called blip.tv or UStream, or whatever, without knowing what it was and understanding what a live stream was, and they’ll be much more willing to click on something that says YouTube, watch the YouTube video.</p><p><strong>Kevin:</strong> Yes.</p><p><strong>Stephan:</strong> I think that that’s a big selling point for people, it’s known, it’s in their brains, they’ve used it before and so they’re comfortable.  I think that the other services will struggle to fight that with YouTube and with Google.</p><p><strong>Kevin:</strong> Yeah, it’s hard to create that trust that Google has created with its users over the years, in sites like Blip and that kind of thing, and so you’re exactly right, Stephan, right?</p><p><strong>Stephan:</strong> I hope so (laughter).</p><p><strong>Patrick:</strong> You’re all just so right, but here’s the thing, that’s a good point, it’s brand equity, right, it’s brand capital they’ve built up by being in business for so long and having a generally good reputation, and that’s something that Google brings to any industry, right, when they jump in Smart Phones this is Google Smart Phone, this is Google Android, even though it’s branded as Android and it’s open source and there’s that &#8212; I would say that comfortable division that they create to make people feel comfortable with engaging with that operating system, but it’s Google, and you know when Google jumps in a new industry or a new platform they instantly have that, and that’s true right across the board, and that includes Google Drive which just recently launched.  I mean you have established players who are both super well known companies and not so well known companies, you can think of Amazon as one of the really well known ones with their Cloud drive servers, and then you have a lot of Cloud storage services that are out there, Dropbox is pretty well known, but like I used the example of my family earlier, they don’t know Dropbox, you know my parents don’t know what Dropbox is, but they know Google, they do know what Google is, so even in that case Google Drive has that sort of leg up.<br
/> Have you guys had any opportunity to look at Google Drive?</p><p><strong>Kevin:</strong> So I signed up for the service but I have not used it yet, so now instead of Google Documents whenever I go in the browser it says Drive, and that’s about the extent I have used Google Drive.</p><p><strong>Patrick:</strong> A re-branding.</p><p><strong>Kevin:</strong> Right.  So like it would be fun to try out, but to be honest I’m using Dropbox and I’m happy, and I think this is a good thing to talk about here, because not just about Google Drive but also for Dropbox, right, because Dropbox is fulfilling my needs and I’m very happy with Dropbox, so my incentive to even look at Google Drive like is zero because I’m completely, I’m 100% satisfied with Dropbox, Dropbox does everything that it says it will, and so I have absolutely no need maybe outside of price to look at somewhere else.</p><p><strong>Patrick:</strong> That’s the reason I always give people when they say why do you still use that web browser, and they did that when I used IE for many years, why are you still using that instead of Firefox?  Well, because I have no reason.  And I went over to Firefox and people are like why aren’t you on Chrome? Well, I have no reason, and I’m still on Firefox, but that’s an interesting point.  So I haven’t really used Google Drive either, but their feature page makes it pretty clear what they are doing, it’s not just a stored service, like you said, it ties into Google Docs seamlessly, and it incorporates Google’s very powerful search technology, so that’s a benefit to be able to search those archive files.  You can view things in the browser, they say you can view and open over 30 file types right in your browser, including HD video, Adobe Illustrator and Photoshop, even if you don’t have the program installed on your computer, that’s interesting.  And Google Drive also interacts with a number of different apps and has a very powerful sharing interface where you can share files with just the right files that you want to put them out there with, and there’s some discussion element to files and collaborative documents that might remind some, I don’t know, it looks a little like Google Wave to me, though I haven’t really played around with it too much, that might be an erroneous statement, and also Google Drive tracks the changes that you made to your file, so when you hit a save button a newer version was saved, and that was already true for Google Documents and it seems like it might also be true for files that you put up, but I don’t know if that’s the case or not, but that would be interesting if that was an actual feature.  But Google Drive has been talked about for a long time, and it’s interesting to see them finally get it out the door.<br
/> Do you use &#8212; you know you mentioned Dropbox, do you use anything beyond that for Cloud storage or do you backup to the Cloud, Stephan?</p><p><strong>Stephan:</strong> I use Amazon.</p><p><strong>Patrick:</strong> Cloud Drive.</p><p><strong>Stephan:</strong> The Cloud Drive, yeah, to backup some stuff, and I use a service called Crash Plan.</p><p><strong>Patrick:</strong> Okay, Crash Plan, my brother has that also; I got him hooked up on that when he went to college.</p><p><strong>Stephan:</strong> Yeah, it’s a good service.  The coolest thing I saw on here, on this Google Drive features list, was the photo storage and the search by, it can recognize objects.  So that technology right there is unbelievable, so if you upload a picture of a mountain and it’s Everest, and you do a search and it can tell that it’s Everest, that’s amazing.</p><p><strong>Kevin:</strong> That’s a little too personal for me (laughter).  Hey, look, it’s Kevin in 12 of these photos, don’t you know that guy?  Like Google you shouldn’t know my face, that scares me (laughter).</p><p><strong>Patrick:</strong> The thing is it’s gonna be real scary when they notice just parts of your body, like you search Kevin’s arm, oh, Kevin’s arm appeared in 27 photos (laughter), how many photos are Kevin’s fingerprints visible in, oh, 3,627, oh, we won’t do anything with that information.</p><p><strong>Stephan:</strong> Did you mean to look for the arrest record of Kevin.</p><p><strong>Kevin:</strong> Wow.  No, ‘did you mean’ in Google Docs (laughter)</p><p><strong>Patrick:</strong> That’s very funny.</p><p><strong>Stephan:</strong> So I think that’s really cool, and I think one of the scary parts for me and the reason I’m kind of hesitant to try this out is does it index your drive and where does that information go?  And I can’t find anything on all that information yet, I’ve been looking through the privacy while we’ve been on the call by privacy features, but I haven’t seen anything, so if anyone knows out there, any of the listeners, I would love to know what you found regarding what they do with the indexed data on your computer.</p><p><strong>Patrick:</strong> Kevin, I asked Stephan if he used any similar services, he mentioned Crash Plan and then Amazon Cloud Drive, what about yourself?</p><p><strong>Kevin:</strong> Well, since we’re advertising for people, I use Carbonite, and I use Dropbox, and then I use Google Docs, and then I will soon be using the Adobe Cloud, Creative Cloud.</p><p><strong>Patrick:</strong> I just don’t have the bandwidth to use Carbonite and Back Blaze and Crash Plan; I mean it would take decades to get my stuff up.</p><p><strong>Kevin:</strong> You just leave it running overnight.</p><p><strong>Patrick:</strong> Yeah, I know, overnight for a few decades and we’ll be there, you know literally I’m not kidding.</p><p><strong>Stephan:</strong> Yeah, I mean I’m sitting on about a terabyte of data, and I send it to and offsite hard drive, like I don’t use their actual Cloud storage, I just use their service, so it goes to a friend’s computer, which I’m sure he loves when I like upload a bunch of photos, I’m sure his bandwidth really takes a beating (laughs), but I used to have it at my work, I used to have a hard drive sitting at work and I just left it plugged in.</p><p><strong>Kevin:</strong> What’s to be said, I don’t mean to extend this conversation, but what’s to be said for things like photos and music?  When you think about like the iTunes Cloud or Apple Cloud, whatever, the iCloud I guess it’s called.</p><p><strong>Patrick:</strong> A lot of Clouds.</p><p><strong>Kevin:</strong> Amazon mp3 player and their instant video, do you not think that this is where people are going to store their valuables?  Like why put this equity in something that you really can’t protect, and why not put it in the hands of someone that can, even if you don’t physically own a copy, like that’s what I’ve started doing, like all of my music is in Amazon Cloud, so like I don’t need to backup my music, I don’t really backup much of anything other than my documents folder because everything that’s important to me is backed up online within site services, not necessarily on site drives.</p><p><strong>Patrick:</strong> This is interesting because on the Copyright 2.0 show, the other podcast that I host, the mega upload cases is a big story we talk about every week the different updates and developments, and one of the things that came up recently was people wanting access to the files that were on the service, people who used it as a backup service, as a file locker for their files and their documents.  And it’s an interesting question of exactly what you are entitled to legally and what’s fair for you to be entitled to, right, I mean if you sign up with Crash Plan are you entitled to those files forever, are you entitled to the access for those files for how long, I mean companies go out of business as we know, they have financial trouble, they file for Chapter 11, etcetera.  So obviously best practices you get some notice of that happening, but if the service is run poorly, as may have been the case with Mega Upload, then what happens when they get seized or they get shut down.  Me personally I always think you should have something other than the Cloud service for your important documents, I mean that’s just my thinking about it, and the terms of service for any of these services will probably back that up in saying what you are entitled to and what you’re not entitled to.  So there’s this danger and, you know, Brad and Stephan we used to joke with Kevin about the Cloud and how I wouldn’t use Open ID and I wouldn’t trust Cloud Services 100% with all my data, but that’s true for me here as well; I’d love to have it as kind of a backup backup, but putting all your eggs into that basket it’s not without it’s risks.  And truth be told, Amazon and Google aren’t probably going anywhere, but still the same principle applies.</p><p><strong>Kevin:</strong> But with those services you can still download what you have on them to your computer at a moment’s notice.</p><p><strong>Patrick:</strong> Right, but if they get seized tomorrow by the government I mean it’s gonna be too late.</p><p><strong>Kevin:</strong> I would say my laptop has as much chance of being seized by not just the government but by somebody that walks by me in the coffee shop and wants to just snatch my computer away, right.</p><p><strong>Patrick:</strong> Right.  But at the same time there’s a difference between Google and Amazon and Crash Plan and Back Blaze and then Mega Upload and Rapid Share, right, there’s difference, Google and Amazon may have a stronger legal team, right, and they may be doing things a little more appropriately, but then if you’re using these other services that don’t have the same resources or might not be run the same way, you know, it’s just always important to be aware of what you’re getting into and who you’re placing all those files in with.</p><p><strong>Kevin:</strong> We trust banks, right, we trust banks with our money and our, you know, where we deposit at.</p><p><strong>Stephan:</strong> Yeah, for $100,000.00, $250,000.00, yeah.</p><p><strong>Patrick:</strong> Right.  Part of the reason that we trust banks is because they’re backed by the FDIC up to $100,000.00 or $250,000.00, and there’s that insurance plan; that doesn’t exist with Cloud Hosting, you know, and probably won’t.</p><p><strong>Kevin:</strong> Right.</p><p><strong>Stephan:</strong> I guess I’m a little different, I think it depends on what your workflow is, right, or what your use case is; I don’t backup my music, I have a hard drive with the music on it, if it goes out then so be it, I honestly don’t have that much music, and now with web services &#8212; and this comes back to &#8212; we’re coming full circle back to where we were at the beginning of the show, right, I have an app, it’s called Pandora, I can play random music that I want to listen to, I can use RDIO, I could use Spotify, I could use any of these services that are out there to play music without actually having my hard drive.  To me what’s important to backup is my personal stuff, my photographs, my personal documents, and that’s about it really, that’s the only thing I need to backup and make sure it’s anywhere.  But my photographs library is huge, so for me it’s different than what you guys are using it for or not using it for, and I think for everyone it’s going to be the same way and what’s important to them and how they want to back that stuff up and how they want to ensure they have that information when they need it.  Just my two cents.</p><p><strong>Kevin:</strong> Yeah, I agree with you and Patrick, I mean you both used the same keyword which was ‘important’, right, it’s all defining what’s important to that person; if it’s really, really important you’re going to want a physical copy of it, I mean that’s just the brass tacks I guess.</p><p><strong>Stephan:</strong> Yeah, absolutely.</p><p><strong>Patrick:</strong> And Google Drive, if you’re interested, the pricing is as follows: you can get five gigabyte of Google Drive free, and then on top of that they say 10 gigabyte of Gmail and one gigabyte of Picasa, and then for $2.49 a month you can go 25 gigabytes for drive and Picasa, and Gmail is upgraded to 25 gigabytes.  For $4.99 a month you go to 100 gigabytes, that’s 100 gigabytes for Drive and Picasa, and once again your Gmail is upgraded to 25 gigabytes, and beyond that 200 gigabytes up until 16 terabytes you can upgrade your plan, and that ranges from $9.99 a month up to $799.99 a month for a 16 terabytes, so, yes, Google has plans for everyone.</p><p><strong>Kevin:</strong> That sounds a little creepy, Patrick, “Google has plans for everyone,” mwuhahaha (evil laugh).</p><p><strong>Patrick:</strong> And their data.</p><p><strong>Kevin:</strong> Yes, and everything you own.</p><p><strong>Patrick:</strong> Alright, so with that said I think we’ve come to the end of our story segment, and let’s do host spotlights.  Kevin, why don’t you go first.</p><p><strong>Kevin:</strong> So my spotlight comes from <a
href="http://webdesignledger.com/">webdesignledger.com</a>, it’s 20 inspiring examples of big backgrounds in web design, and it’s just really a fun post of pretty inspiring, of course, website screenshots and links to those sites, so check it out, it’s pretty cool.  I mean some of this stuff is pretty neat, but I mean it’s all big background, so.<br
/> big background, so.</p><p><strong>Patrick:</strong> Cool, yeah, you can see kind of a consistent theme, there’s a lot of visual obviously, but not as much text, right, the text is kind of sparse, selective with how the text and what the copy on the page contains.</p><p><strong>Kevin:</strong> Hmm-mm.  It feels very much like an ad in a magazine with navigation.</p><p><strong>Patrick:</strong> Cool.  Stephan what do you have?</p><p><strong>Stephan:</strong> I have a blog post by a man named Dan Haggard, he writes for a website called Reviews in Depth, and his post is called Why Everyone Should Learn to Program.  And Mr. Haggard works at a university, he’s an administrator, and it’s just a nice, long blog post on him writing an application and then showing this application to one of his co-workers and getting them excited to program.  And he just kind of talks and touches on a few things that I think resonate with people who aren’t programmers.  My wife is a math major and I shared this with her and she really enjoyed it because I think it kind of made sense to her, you know, we use a lot of interfaces in our day-to-day lives, the stove you use to cook your dinner, the knife you use to cut your food, the car, the anything, and this kind of touches on how that can be translated into programming and how it’s just an interface for getting things done.<br
/> So, it’s one of those articles that you can use to show someone who’s kind of skeptical on you writing an application, and have them read this and I think they’ll get it a little bit better.</p><p><strong>Patrick:</strong> Very cool.  I myself am not a programmer but I sometimes wish I was.<br
/> And my spotlight is a web video series called Beer and Board Games, it’s by Blame Society Films, and you can find them at <a
href="http://youtube.com/blamesocietyfilms/">youtube.com/blamesocietyfilms</a>.  Basically it is &#8212; Blame Society Films is led by Max Sloane and Aaron Yonda, maybe more popularly known as the guys behind Chad Vader, which is a popular web video series, but they’ve done a bunch of other series as well, and one of my favorites is Beer and Board Games, I watch it regularly with my brother Sean, and they tackle board games popular and obscure.  They’ve done Risk, they’ve done Sex Maniacs, the card game (laughs), so, you know, there are a lot of crazy board games out there, and the shows are just hilarious, they’re kind of &#8212; you know, they’re not three minute YouTube videos, they’re usually about 10 minutes or so, but just great humor, very hilarious and there’s a lot of fun stuff on there channel as well.</p><p><strong>Stephan:</strong> I’ll have to find the Settlers of Catan one; I need to watch that one.</p><p><strong>Patrick:</strong> They haven’t done that one yet, have they?  I’ve never even played that game, I have heard of it.</p><p><strong>Stephan:</strong> (Laughs) it’s a good game.</p><p><strong>Kevin:</strong> Have you heard of Carcassonne?</p><p><strong>Patrick:</strong> Uh, no.</p><p><strong>Kevin:</strong> Ah, man, what’s wrong with you?</p><p><strong>Patrick:</strong> I guess if I come to where you guys are located one day then we can play those games.</p><p><strong>Kevin:</strong> We shall.</p><p><strong>Patrick:</strong> Before we go around the table I’d like to shout out a listener of the show, Chris Trynkiewicz, who is a very literal listener, always commenting on my Google+ posts about the show, so Chris thank you for listening, we really appreciate it.  Chris actually left me a really long comment about something we should talk about on the show, but I didn’t have enough time to review it before we recorded. So thanks again, Chris, and thank you to everyone that listens to the show.<br
/> Let’s go ahead and go around the table.</p><p><strong>Kevin:</strong> Okay, so you can find me <a
href="http://twitter.com/kevindees">@kevindees</a> on Twitter and <a
href="http://kevindees.cc/">kevindees.cc</a> on the Interwebs.</p><p><strong>Stephan:</strong> I’m Stephan Segraves, you can find me on Twitter <a
href="http://twitter.com/ssegraves">@ssegraves</a>, and I blog at <a
href="http://badice.com/">badice.com</a></p><p><strong>Patrick:</strong> And I am Patrick O’Keefe of the iFroggy Network, I blog at <a
href="http://managingcommunities.com/">managingcommunities.com</a>; find me on Twitter <a
href="http://twitter.com/ifroggy">@ifroggy</a>, i-f-r-o-g-g-y.<br
/> You can follow our usual co-host, Louis Simoneau, <a
href="http://twitter.com/rssaddict">@rssaddict</a>, and SitePoint <a
href="http://twitter.com/sitepointdotcom">@sitepointdotcom</a>, that’s sitepoint d-o-t-c-o-m.  You can check out the podcast at <a
href="http://sitepoint.com/podcast/">sitepoint.com/podcast</a> and leave comments on this show or any show, and also subscribe to receive every show automatically.  Email us at podcast@sitepoint.com with your comments and your questions, we’d love to give you our thoughts or read them out on the show.<br
/> The SitePoint podcast is produced by Karn Broad, thank you for listening and we’ll see you next week.</p><p>Theme music by <a
href="http://www.belikewater.ca/">Mike Mella</a>.</p><p>Thanks for listening! Feel free to let us know how we’re doing, or to continue the discussion, using the comments field below.</p></div> <span
id="pty_trigger"></span><div
style='padding:20px 0px 50px 0px;'><div
style='float:left;padding-left:40px;'><div
id='div-gpt-ad-1335489406190-0' style='width:300px; height:100px;'> <script type='text/javascript'>googletag.cmd.push(function() { googletag.display('div-gpt-ad-1335489406190-0'); });</script> </div></div><div
style='float:right;padding-right:40px;'><div
id='div-gpt-ad-1335489406190-1' style='width:300px; height:100px;'> <script type='text/javascript'>googletag.cmd.push(function() { googletag.display('div-gpt-ad-1335489406190-1'); });</script> </div></div><div
style='clear:both'></div></div><div
style='clear:both'></div><div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/SitepointFeed?a=_Rm7GsQ7E8w:g6fkklyQMFY:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/SitepointFeed?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/SitepointFeed?a=_Rm7GsQ7E8w:g6fkklyQMFY:qj6IDK7rITs"><img src="http://feeds.feedburner.com/~ff/SitepointFeed?d=qj6IDK7rITs" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/SitepointFeed?a=_Rm7GsQ7E8w:g6fkklyQMFY:gIN9vFwOqvQ"><img src="http://feeds.feedburner.com/~ff/SitepointFeed?i=_Rm7GsQ7E8w:g6fkklyQMFY:gIN9vFwOqvQ" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/SitepointFeed/~4/_Rm7GsQ7E8w" height="1" width="1"/>]]></content:encoded> <wfw:commentRss>http://www.sitepoint.com/podcast-162-taking-google-for-a-drive/feed/</wfw:commentRss> <slash:comments>1</slash:comments> <enclosure url="http://media.libsyn.com/media/sitepoint/sitepointpodcast162.mp3" length="0" type="audio/mpeg" /> <feedburner:origLink>http://www.sitepoint.com/podcast-162-taking-google-for-a-drive/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=podcast-162-taking-google-for-a-drive</feedburner:origLink></item> <item><title>Scalable Vector Graphics: an Overview</title><link>http://feedproxy.google.com/~r/SitepointFeed/~3/IhBe6RvB0nc/</link> <comments>http://www.sitepoint.com/svg-scalable-vector-graphics-overview/#comments</comments> <pubDate>Fri, 11 May 2012 18:30:38 +0000</pubDate> <dc:creator>Craig Buckler</dc:creator> <category><![CDATA[Client Side Coding]]></category> <category><![CDATA[Design]]></category> <category><![CDATA[HTML & CSS]]></category> <category><![CDATA[HTML5]]></category> <category><![CDATA[Web Tech]]></category> <category><![CDATA[canvas]]></category> <category><![CDATA[HTML5 Dev Center]]></category> <category><![CDATA[SVG]]></category> <guid isPermaLink="false">http://www.sitepoint.com/?p=54386</guid> <description><![CDATA[<img
width="50" height="50" src="http://www.sitepoint.com/wp-content/uploads/1/files/2012/05/672-svg-basics-50x50.png" class="attachment-thumbnail wp-post-image" alt="672-svg-basics" title="672-svg-basics" />Craig provides a concise overview of Scalable Vector Graphics and its associated technologies.]]></description> <content:encoded><![CDATA[<img
width="50" height="50" src="http://www.sitepoint.com/wp-content/uploads/1/files/2012/05/672-svg-basics-50x50.png" class="attachment-thumbnail wp-post-image" alt="672-svg-basics" title="672-svg-basics" /><p></p><p>In my recent article, we discussed <a
href="http://www.sitepoint.com/7-reasons-to-consider-svgs-instead-of-canvas/">7 Reasons to Consider SVGs Instead of Canvas</a>. SVGs are ideal if you require a scalable diagram such as a chart or logo which can be altered or animated using JavaScript DOM methods.</p><p>So &hellip; <em>what are SVGs and how do we use them?</em> This is the first part in a series articles about the vector image format.</p><h2>What Are SVGs?</h2><p>SVGs are vector graphics. Rather than defining the color of each pixel like you would in a bitmap (JPEG, PNG, GIF, BMP etc.), vector graphics define lines and shapes, e.g. draw a black line from co-ordinate 0,0 to 100,100. This has a number of advantages: vectors are easy to modify, generally require smaller files and are scalable to any dimension without losing quality &#8212; which makes them ideal for responsive web design. Bitmaps remain the best choice for photographs or very complex images (note that SVGs can include embedded bitmaps).</p><p><img
src="http://blogs.sitepointstatic.com/images/tech/672-svg-basics-vector.png" width="339" height="267" alt="vector vs bitmap comparison" class="center" style="margin:20px auto" /></p><p>SVG is a royalty-free web standard maintained by the <a
href="http://www.w3.org/Graphics/SVG/">W3C SVG Working Group</a>. Version 1.0 of the technology was originally proposed in 1999. <a
href="http://www.w3.org/TR/SVG11/">Version 1.1</a> is the most recent standard with <a
href="http://www.w3.org/Graphics/SVG/WG/wiki/Roadmap">version 2.0</a> expected in 2013.<div
id='div-gpt-ad-1328644474660-10' style='width:728px; height:90px;'> <script type='text/javascript'>googletag.cmd.push(function() { googletag.display('div-gpt-ad-1328644474660-10'); });</script> </div></p><p>There are a couple of other flavors: <a
href="http://www.w3.org/TR/SVGTiny12/">SVG Tiny</a> and <a
href="http://www.w3.org/TR/SVGMobile/">SVG Mobile</a>. These are simplified profiles or subsets of the full SVG specification which target devices with reduced computational and display capabilities. These standards largely relate to how rendering engines parse the image; an SVG 1.1 file can be rendered on a device which supports SVG Tiny but some effects such as gradients and opacities would not be applied.</p><h2>How are SVGs Defined?</h2><p>SVGs are declared using eXtensible Markup Language (XML). It uses tags like HTML &#8212; the following code draws a white circle with a black border:</p><pre><code>
&lt;circle cx=&quot;100&quot; cy=&quot;100&quot; r=&quot;50&quot; stroke-width=&quot;4&quot; stroke=&quot;#000&quot; fill=&quot;#fff&quot; /&gt;
</code></pre><p>Be aware that XML is stricter than HTML. You cannot, for example, omit a closing tag since this will make the file invalid and the SVG will not be rendered.</p><p>The W3C SVG1.1 specification defines 14 main features:</p><ol><li><strong>Basic shapes</strong>: straight lines, polygons, circles, ellipses, and rectangles with or without rounded corners.</li><li><strong>Paths</strong>: outlined or filled paths containing curved or straight lines.</li><li><strong>Text</strong>: on straight or curved paths in any direction.</li><li><strong>Painting</strong>: fills and outlines using solid colors, gradients, patterns, transparency, and markers (line terminators such as arrow heads).</li><li><strong>Color</strong>: fill and stroke properties defined using standard 3 or 6-digit hex or rgb values.</li><li><strong>Gradients and patterns</strong>: CSS3-like gradient declarations or bitmap backgrounds.</li><li><strong>Clipping, masking and compositing</strong>: using elements to outline regions which can be painted.</li><li><strong>Filters</strong>: effects applied to all elements within a container, e.g. blurring, lighting, color adjustments, etc.</li><li><strong>Linking</strong>: hyperlinks to other documents.</li><li><strong>Interactivity</strong>: attaching event handlers using JavaScript.</li><li><strong>DOM Scripting</strong>: accessing and manipulating SVG elements using the Document Object Model.</li><li><strong>Animation</strong>: built-in animations using Synchronized Multimedia Integration Language (SMIL).</li><li><strong>Fonts</strong>: text glyphs defined in an SVG file which can be used as a standard font.</li><li><strong>Metadata</strong>: titles, descriptions, subjects, creators and other properties about the SVG image.</li></ol><h2>Cascading Stylesheets in SVGs</h2><p>SVGs also support embedded or external CSS rules. Like HTML, the selectors can target tag types or IDs and classes assigned to specific elements. CSS properties and values generally follow element attributes. For example, this CSS renders every circle in the SVG with the same white fill and black border color:</p><pre><code>
circle
{
	stroke: #000;
	fill: #fff;
}
</code></pre><h2>SVG Creation Tools</h2><p>Creating SVGs in a text editor is possible but it&#8217;s a slow process, error-prone and not much fun. Fortunately, there are several open source and commercial tools which allow designers and non-programmers to easily create SVG images:</p><ul><li><a
href="http://www.inkscape.org/">Inkscape</a></li><li><a
href="http://www.openoffice.org/">OpenOffice</a> or <a
href="">LibreOffice</a> Draw</li><li><a
href="http://svg-edit.googlecode.com/svn/branches/2.5.1/editor/svg-editor.html">svg-edit</a></li></ul><p>Therefore, a design team could create a great-looking chart which a programmer can modify by applying real data to specific elements.</p><p>However, note that some graphics packages may not create the most optimal code or apply their own XML extensions.</p><h2>SVG Browser Support</h2><p>Although the technology has been available for more than a decade, SVG use within browsers was held back by Internet Explorer which first provided support in IE9. Today, most desktop and mobile browsers can handle SVGs and it is a recognized HTML5 standard.</p><p>Browser implementations vary, but SVGs can either be:</p><ul><li>viewed as a separate file directly in a web browser.</li><li>embedded as an XML section within an HTML page.</li><li>defined as an external page resource within <code>img</code>, <code>object</code> or the old <code>embed</code> tags (or as an <code>iframe</code>, although that&#8217;s effectively viewing the SVG file)</li><li>set as background image in CSS.</li></ul><p>There are a number of plug-in and shim options if you require SVG support in Internet Explorer 8.0 and below. Several fallback to Vector Markup Language (VML); a technology used in Microsoft products which influenced the SVG standard:</p><ul><li><a
href="http://raphaeljs.com/">Rapha&euml;l</a> &#8212; JavaScript/VML</li><li><a
href="http://www.amplesdk.com/">AmpleSDK</a> &#8212; JavaScript/VML</li><li><a
href="http://code.google.com/p/svgweb/">svgweb</a> &#8212; JavaScript/Flash</li><li><a
href="http://xmlgraphics.apache.org/batik/">Batik</a> &#8212; Java toolkit</li></ul><h2>SVG Performance in Browsers</h2><p>SVG XML must be parsed to render images on-screen and represented in memory as a Document Object Model. As with HTML pages, performance will be affected if you attempt to move or manipulate SVGs containing a large number of elements. In extreme cases, the redraw will be noticeable.</p><p>For this reason, it&#8217;s often preferable to use the HTML5 <code>canvas</code> tag for fast action games with hundreds of animated items. However, you may be able to adopt SVGs for some aspects, e.g. a player&#8217;s spaceship could be a simple SVG which can be moved, rotated, scaled and warped over a <code>canvas</code>-generated background.</p><h2>SVGs and Accessibility</h2><p>Owing to their XML data structure, <a
href="http://www.w3.org/TR/SVG-access/">SVGs provide better accessibility</a> than bitmap images. At a basic level, meta data, short text and long text alternatives can be applied to any SVG image.</p><p>That said, screen reader support is poor. SVGs were not considered a viable browser technology until the release of IE9 so vendors did not consider them a priority. The situation will undoubtedly improve.</p><p>In the short term, you could consider transforming SVG XML into a text-based alternative using XSLT.</p><h2>SVGs and Search Engine Optimization</h2><p>Unlike bitmaps, XML is inherently machine-readable so static SVG files can be read, parsed and indexed by search engine bots. Google has been indexing SVG content since August 2010 and results can be found in the standard and image search systems.</p><p>Replacing a few PNGs with SVGs is unlikely to improve your rankings. However, if you&#8217;re displaying data as images without textual fall-backs, switching to SVGs could offer an SEO boost.</p><p>In my next SVG article we&#8217;ll create our first images without the use of a graphics package!</p> <span
id="pty_trigger"></span><div
style='padding:20px 0px 50px 0px;'><div
style='float:left;padding-left:40px;'><div
id='div-gpt-ad-1335489406190-0' style='width:300px; height:100px;'> <script type='text/javascript'>googletag.cmd.push(function() { googletag.display('div-gpt-ad-1335489406190-0'); });</script> </div></div><div
style='float:right;padding-right:40px;'><div
id='div-gpt-ad-1335489406190-1' style='width:300px; height:100px;'> <script type='text/javascript'>googletag.cmd.push(function() { googletag.display('div-gpt-ad-1335489406190-1'); });</script> </div></div><div
style='clear:both'></div></div><div
style='clear:both'></div><div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/SitepointFeed?a=IhBe6RvB0nc:3poilrWadEQ:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/SitepointFeed?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/SitepointFeed?a=IhBe6RvB0nc:3poilrWadEQ:qj6IDK7rITs"><img src="http://feeds.feedburner.com/~ff/SitepointFeed?d=qj6IDK7rITs" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/SitepointFeed?a=IhBe6RvB0nc:3poilrWadEQ:gIN9vFwOqvQ"><img src="http://feeds.feedburner.com/~ff/SitepointFeed?i=IhBe6RvB0nc:3poilrWadEQ:gIN9vFwOqvQ" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/SitepointFeed/~4/IhBe6RvB0nc" height="1" width="1"/>]]></content:encoded> <wfw:commentRss>http://www.sitepoint.com/svg-scalable-vector-graphics-overview/feed/</wfw:commentRss> <slash:comments>6</slash:comments> <feedburner:origLink>http://www.sitepoint.com/svg-scalable-vector-graphics-overview/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=svg-scalable-vector-graphics-overview</feedburner:origLink></item> <item><title>Add a Web Console to Your Toolbox, Part 2</title><link>http://feedproxy.google.com/~r/SitepointFeed/~3/qc9icwUI3kQ/</link> <comments>http://www.sitepoint.com/add-a-web-console-to-your-toolbox-part-2/#comments</comments> <pubDate>Thu, 10 May 2012 15:00:32 +0000</pubDate> <dc:creator>Jeff Friesen</dc:creator> <category><![CDATA[HTML5]]></category> <category><![CDATA[JavaScript]]></category> <category><![CDATA[HTML5 Dev Center]]></category> <guid isPermaLink="false">http://www.sitepoint.com/?p=54170</guid> <description><![CDATA[<img
width="50" height="28" src="http://www.sitepoint.com/wp-content/uploads/1/files/2012/05/Screen-Shot-2012-05-02-at-4.06.54-PM1-50x28.png" class="attachment-thumbnail wp-post-image" alt="Screen Shot 2012-05-02 at 4.06.54 PM" title="Screen Shot 2012-05-02 at 4.06.54 PM" />A console is a software artifact for reading line-oriented textual input from the keyboard and writing line-oriented textual output to the screen. Part 1 of this two-part series introduced you to a console library for embedding a console in a web page, and demonstrated the usefulness of such a console via a browser shell. Part 2 shows [...]]]></description> <content:encoded><![CDATA[<img
width="50" height="28" src="http://www.sitepoint.com/wp-content/uploads/1/files/2012/05/Screen-Shot-2012-05-02-at-4.06.54-PM1-50x28.png" class="attachment-thumbnail wp-post-image" alt="Screen Shot 2012-05-02 at 4.06.54 PM" title="Screen Shot 2012-05-02 at 4.06.54 PM" /><p></p><p>A <em>console</em> is a software artifact for reading line-oriented textual input from the keyboard and writing line-oriented textual output to the screen. Part 1 of this two-part series introduced you to a console library for embedding a console in a web page, and demonstrated the usefulness of such a console via a browser shell. Part 2 shows you how the console library is implemented.</p><h2>Discover how Console Works</h2><p>The console library is fairly complete, but you might want to extend it with new capabilities (e.g., echo asterisks while inputting a password). Alternatively, you might want to improve performance or implement error checking. Regardless of your purpose, you&#8217;ll need to understand how the library works. The first step in gaining this knowledge is to grasp the library&#8217;s overall architecture. Listing 1 presents an overview.</p><pre>var Console =
{
   init: function(canvasName, numCols, numRows)
         {
         },
   clear: function()
          {
          },
   getLine: function(callback)
            {
            },
   echo: function(msg)
         {
         },
   render: function()
           {
           },
   writeChar: function(ch)
              {
              },
   scroll: function()
           {
           }
}</pre><p><strong>Listing 1:</strong> The console library&#8217;s skeletal structure</p><p>Listing 1 reveals a global object named <code>Console</code> consisting of seven function properties. The first four properties comprise the public API, whereas the last three properties should be considered private and not accessed. This list of properties is far from complete because the <code>init(canvasName, numCols, numRows)</code> function introduces additional properties.<div
id='div-gpt-ad-1328644474660-10' style='width:728px; height:90px;'> <script type='text/javascript'>googletag.cmd.push(function() { googletag.display('div-gpt-ad-1328644474660-10'); });</script> </div></p><table
width="60%" border="1"><tbody><tr><th
bgcolor="#0000c0"><span
style="color: #ffffff;">Note</span></th></tr><tr><td>I could have &#8220;hidden&#8221; the final three properties by introducing expressions such as <code>Console.writeChar = function(ch) { /* code here */ }</code> within <code>init(canvasName, numCols, numRows)</code>. I chose to not do so to keep <code>init(canvasName, numCols, numRows)</code> from getting any longer.</td></tr></tbody></table><h3>Discover <code>init(canvasName, numCols, numRows)</code></h3><p>Listing 2 presents <code>init(canvasName, numCols, numRows)</code>.</p><pre>init: function(canvasName, numCols, numRows)
      {
         var canvas = document.getElementById(<wbr>canvasName); Console.numCols = numCols; Console.numRows = numRows; Console.ctx = canvas.getContext("2d"); Console.ctx.font = "20px/20px monospace"; Console.ctx.textBaseline = "top"; Console.charWidth = Console.ctx.measureText("m").</wbr><wbr>width; Console.charHeight = 20; canvas.width = Console.charWidth*numCols+10; canvas.height = Console.charHeight*numRows+10; Console.buffer = document.createElement("</wbr><wbr>canvas"); Console.buffer.width = canvas.width; Console.buffer.height = canvas.height; Console.bufferCtx = Console.buffer.getContext("2d"</wbr><wbr>); Console.bufferCtx.font = "20px/20px monospace"; Console.bufferCtx.textBaseline = "top"; Console.screen = new Array(numRows); for (var row = 0; row &lt; numRows; row++) Console.screen[row] = new Array(numCols); Console.keyQueue = new Array(); function keyDown(event) { // This function is called by all browsers for backspace. if (event.keyCode == 8) // backspace? { Console.keyQueue.push("\b"); // The following code is needed by Chrome to prevent backspace // from moving back in page history. event.preventDefault(); } } canvas.addEventListener("</wbr><wbr>keydown", keyDown, true); function keyPress(event) { if (event.keyCode == 8) { // The following code is needed by Opera to prevent backspace // from moving back in page history. event.preventDefault(); return; } if (event.keyCode == 13) // return? { Console.keyQueue.push("\n"); return; } var ch = (event.keyCode == 0) ? event.charCode : event.keyCode; if (ch &gt;= 32 &amp;&amp; ch &lt; 127) Console.keyQueue.push(String.</wbr><wbr>fromCharCode(ch)); } canvas.addEventListener("</wbr><wbr>keypress", keyPress, true); canvas.tabIndex = 0; // Place canvas in tab order. canvas.focus(); // Give keyboard focus to canvas. Doesn't work on // Internet Explorer. Console.cursorOn = true; Console.cursorCounter = 0; Console.cursorCounterMax = 5; Console.line = ""; Console.clear(); }</wbr></pre><p><strong>Listing 2:</strong> Initializing the console library</p><p>Listing 2 first obtains a reference to the named <code>&lt;canvas&gt;</code> element and saves the number of columns and number of rows in <code>Console</code> properties for use by other functions. It then obtains a context for drawing on this canvas, and initializes this context to a 20-pixel size monospace font. The text baseline is set to the top of the font so that a character&#8217;s coordinates are relative to its upper-left corner.</p><p>Now that the font has been specified, its character width and height are calculated so that the characters can be positioned properly on the canvas. This information is then used to calculate the width and height of the canvas. An extra 10 pixels is added to the width and height so that a five-pixel border surrounds the canvas (and prevents the cursor from being invisible on the bottom row when viewed in Internet Explorer).</p><p>The next few lines create and initialize a buffer to support double buffering. The goal is to avoid flicker by drawing into the buffer and then copying the buffer contents to the canvas. Various blog posts (e.g., <a
href="http://stackoverflow.com/questions/2795269/does-html5-canvas-support-double-buffering" target="_blank">http://stackoverflow.com/<wbr>questions/2795269/does-html5-</wbr><wbr>canvas-support-double-</wbr><wbr>buffering</wbr></a>) suggest that current browsers support double buffering automatically, whereas older browsers typically don&#8217;t.</p><p>A two-dimensional <code>screen</code> array for storing characters that are echoed to the console is now created. JavaScript implements a two-dimensional array as a one-dimensional row array of one-dimensional column arrays. The <code>Array</code> object is used to create the row array and then, for each row element, a column array whose reference is assigned to the row array element.</p><p>Although each row in this table could potentially store a different number of columns (which is known as a <em>ragged array</em>), I&#8217;ve chosen to fix the number of columns to the value passed to <code>Array</code>&#8216;s constructor. An element in the <code>Screen</code> array is accessed via syntax <code>Console.screen[<em>row</em>][<em>col</em>]</code> &#8211; row and column indexes are zero-based.</p><p>Moving on, the <code>Array</code> object is used to create a <code>keyQueue</code> array for storing character and special keystrokes (e.g., newline). This array behaves as a queue in which keystrokes are added at one end and removed at the other. Code that adds keystrokes to this queue is contained in a pair of event-handling functions that are registered with the canvas to respond to key-down and key-press events.</p><p>The key-down event handler responds to the backspace key only. I would have preferred to handle this key via key-press, but that event handler is not called when backspace is pressed in Internet Explorer, Chrome, or Safari contexts. After adding <code>\b</code> to the queue, key-down executes <code>event.preventDefault()</code> to prevent the current page from being replaced by the previous page in Chrome&#8217;s page history.</p><p>The key-press event handler also responds to the backspace key for Firefox and Opera. It ignores this key under these browsers (it would not be a good idea to add a second <code>\b</code> code to the queue), but executes <code>event.preventDefault()</code> to prevent the current page from being replaced by the previous page in Opera&#8217;s page history.</p><p>The key-press event handler also responds to the Enter/Return key by adding a newline character to the queue, and responds to keys whose codes range from 32 through 126 by calling <code>String</code>&#8216;s<code>fromCharCode()</code> function on the code and adding the equivalent character to the queue. On Firefox, <code>keyCode</code> contains 0 for a character key (e.g., A), and the appropriate code must be obtained from<code>charCode</code>.</p><table
width="60%" border="1"><tbody><tr><th
bgcolor="#0000c0"><span
style="color: #ffffff;">Note</span></th></tr><tr><td>Opera does not support <code>charCode</code>, but <code>keyCode</code> distinguishes between uppercase and lowercase characters in a key-press context.</td></tr></tbody></table><p>HTML provides a <code>tabindex</code> attribute and a <code>tabIndex</code> DOM property for placing elements into tab order. Zero is assigned to the canvas&#8217;s <code>tabIndex</code> property for this purpose. Next, the canvas&#8217;s<code>focus()</code> function is invoked to give this element the keyboard focus. Although focus is given on Firefox, focus is not given on Internet Explorer &#8212; you must press the Tab key once or click the mouse on the canvas.</p><p>The canvas manages a cursor via <code>cursorOn</code>, <code>cursorCounter</code>, and <code>cursorCounterMax</code> properties. The cursor is visible when <code>true</code> is assigned to <code>cursorOn</code> (the default value), and the cursor remains visible until <code>cursorCounter</code> reaches <code>cursorCounterMax</code>, at which point it is reset to 0. It then becomes invisible and remains as such for the same duration.</p><p>There are two final tasks for <code>init(canvasName, numCols, numRows)</code> to perform. First, it assigns the empty string to the <code>line</code> property, which is a buffer for storing characters until Enter/Return is pressed. Second, it invokes the <code>clear()</code> function to clear the console and reset the location of the cursor to the upper-left character position.</p><h3>Discover <code>clear()</code></h3><p>Listing 3 presents <code>clear()</code>.</p><pre>clear: function()
       {
          for (var row = 0; row &lt; Console.numRows; row++)
             for (var col = 0; col &lt; Console.numCols; col++)
                Console.screen[row][col] = " ";
          Console.row = 0;
          Console.col = 0;
          Console.render();
       }</pre><p><strong>Listing 3:</strong> Clearing the console</p><p>Listing 3 clears the console by assigning a space to each <code>screen</code> array element. (Although not very performant, I&#8217;m emphasizing clarity. I could probably speed up the code by leveraging <code>Array</code>&#8216;s<code>splice()</code> function.) It then resets the current cursor position (indicated by <code>Console</code>&#8216;s <code>col</code> and <code>row</code> properties) to the upper-left character position, and renders <code>screen</code>&#8216;s contents onto the canvas. (I discuss <code>render()</code> later.)</p><h3>Discover <code>getLine(callback)</code></h3><p>Listing 4 presents <code>getLine(callback)</code>.</p><pre>getLine: function(callback)
         {
            Console.render(); // update cursor
            if (Console.keyQueue.length == 0)
            {
               if (Console.line.length == 0)
               {
                  if (callback != undefined)
                     callback();
               }
               return null;
            }
            var ch = Console.keyQueue.shift();
            if (ch == "\b") // handle backspace
            {
               if (Console.line.length != 0)
               {
                  Console.line = Console.line.substr(0,
                                                     Console.line.length-1);
                  Console.echo(ch);
               }
               return null;
            }
            Console.echo(ch);
            if (ch == "\n") // handle newline
            {
               var temp = Console.line;
               Console.line = "";
               return temp;
            }
            else
               Console.line += ch;
            return null;
         }</pre><p><strong>Listing 4:</strong> Getting a line of input</p><p>Listing 4 describes a polling function that continually checks for input and processes this input one character at a time. The first task is to show or hide the cursor, and this task is accomplished by invoking <code>Console.render()</code>. Because <code>getLine()</code> is continuously invoked by the console demo and browser shell applications, the illusion of a blinking cursor is maintained.</p><table
width="60%" border="1"><tbody><tr><th
bgcolor="#0000c0"><span
style="color: #ffffff;">Note</span></th></tr><tr><td>The cursor&#8217;s blink rate depends upon the delay value passed to <code>setInterval()</code>. The larger the delay value, the slower the cursor blinks.</td></tr></tbody></table><p>The next task is to determine whether any characters are present in the queue. If the queue is empty, <code>getLine()</code> can return. However, it first needs to invoke any callback function passed as an argument, but can only invoke this function when the <code>line</code> buffer is empty (a line of input is not in progress), to prevent screwing up the input line as demonstrated while discussing the browser shell.</p><p>At this point, the queue contains a character that is subsequently removed. If this character is the backspace, and if the <code>line</code> buffer is not empty, the rightmost character is removed from the buffer and the backspace is echoed to the console to keep the <code>screen</code> array synchronized, and <code>null</code> is returned because a complete line of input is not yet available.</p><p>After echoing the character to the console, <code>getLine()</code> checks the current character to see if it is a newline. If so, the <code>line</code> buffer is reset to the empty string in anticipation of the next line of input, and its previous contents are returned. Otherwise, the current character is appended to this buffer, and <code>null</code> is returned because a complete line of input is not yet available.</p><h3>Discover <code>echo(msg)</code></h3><p>Listing 5 presents <code>echo(msg)</code>.</p><pre>echo: function(msg)
      {
         for (var i = 0; i &lt; msg.length; i++)
            Console.writeChar(msg.charAt(<wbr>i)); Console.render(); }</wbr></pre><p><strong>Listing 5:</strong> Echoing a string to the console</p><p>Listing 5 echoes a string of characters to the console one character at a time, updating the current cursor position in the process. The code employs <code>writeChar(ch)</code> for this purpose, and I will explain this function shortly. After writing out the string, <code>Console.render()</code> is invoked to update the canvas with the contents of the <code>screen</code> array.</p><h3>Discover <code>render()</code></h3><p>Listing 6 presents <code>render()</code>.</p><pre>render: function()
        {
           Console.bufferCtx.fillStyle = "#000"; // black
           Console.bufferCtx.fillRect(0, 0, Console.ctx.canvas.width,
                                      Console.ctx.canvas.height);
           Console.bufferCtx.fillStyle = "#0f0"; // green
           var y = 0;
           for (var row = 0; row &lt; Console.numRows; row++)
           {
              var x = 0;
              for (var col = 0; col &lt; Console.numCols; col++)
              {
                  var s = Console.screen[row][col]+"";
                  Console.bufferCtx.fillText(s, x+5, y+5);
                  x += Console.charWidth;
              }
              y += Console.charHeight;
           }
           if (Console.cursorOn)
              Console.bufferCtx.fillStyle = "#0f0"; // green
           else
              Console.bufferCtx.fillStyle = "#000"; // black
           Console.bufferCtx.fillText("_"<wbr>, Console.col*Console.charWidth+</wbr><wbr>5, Console.row*Console.</wbr><wbr>charHeight+5); if (++Console.cursorCounter == Console.cursorCounterMax) { Console.cursorCounter = 0; Console.cursorOn = !Console.cursorOn; } Console.ctx.drawImage(Console.</wbr><wbr>buffer, 0, 0); }</wbr></pre><p><strong>Listing 6:</strong> Rendering the <code>screen</code> array to the buffer (and more)</p><p>Listing 6 is responsible for rendering the <code>screen</code> array to the buffer and updating the cursor. It renders to the background buffer, and ultimately copies this buffer to the canvas to avoid flicker for those browsers where flicker could occur. The background buffer is first cleared to black to remove potential garbage from a previous rendering.</p><p>After setting the drawing color to green, <code>render()</code> iterates over the <code>screen</code> array, invoking the Canvas API&#8217;s <code>fillText()</code> function to draw each character. An offset of five pixels is added to the character&#8217;s upper-left corner to support an empty border that&#8217;s drawn around the console. Characters are separated horizontally by <code>charWidth</code> pixels and vertically by <code>charHeight</code> pixels.</p><p>The next section of code is responsible for rendering the cursor. An appropriate fill style is chosen based on the value of <code>cursorOn</code>: green when true and black when false. Either a green or black underline is then displayed at the current cursor position. The black underline completely erases what was previously displayed.</p><p>Finally, the cursor&#8217;s on/off interval is established: the cursor is visible over five calls to <code>render()</code> and invisible over five calls to this function. Because <code>render()</code> is called by <code>getLine()</code>, and because<code>getLine()</code> is invoked repeatedly by the application under the control of <code>setInterval()</code>, a blinking cursor is observed.</p><h3>Discover <code>writeChar(ch)</code></h3><p>Listing 7 presents <code>writeChar(ch)</code>.</p><pre>writeChar: function(ch)
           {
              if (ch == "\b")
              {
                 if (Console.col == 0 &amp;&amp; Console.row == 0)
                    return; // cannot backspace past the upper-left corner
                 Console.col--;
                 if (Console.col &lt; 0)
                 {
                    Console.col = Console.numCols-1;
                    Console.row--;
                 }
                 Console.screen[Console.row][<wbr>Console.col] = " "; return; } if (ch == "\n") { Console.col = 0; if (++Console.row &gt;= Console.numRows) Console.scroll(); return; } Console.screen[Console.row][</wbr><wbr>Console.col] = ch; if (++Console.col &gt;= Console.numCols) { Console.col = 0; if (++Console.row &gt;= Console.numRows) Console.scroll(); } }</wbr></pre><p><strong>Listing 7:</strong> Writing a single character to the <code>screen</code> array</p><p>Listing 7 writes its single character argument to the <code>screen</code> array and updates the current cursor position. If the character is a backspace, the appropriate element in the <code>screen</code> array is removed. Otherwise, if the character is a newline, the current row advances and the console scrolls vertically upward when necessary. Otherwise, the character is stored at the current position, which advances and possibly scrolls upward.</p><h3>Discover <code>scroll</code></h3><p>Listing 8 presents <code>scroll()</code>.</p><pre>scroll: function()
        {
           Console.row = Console.numRows-1;
           for (var row = 0; row &lt; Console.numRows-1; row++)
               for (var col = 0; col &lt; Console.numCols; col++)
                  Console.screen[row][col] = Console.screen[row+1][col];
           for (var col = 0; col &lt; Console.numCols; col++)
              Console.screen[Console.<wbr>numRows-1][col] = " "; }</wbr></pre><p><strong>Listing 8:</strong> Scrolling the console upward one row</p><p>Listing 8 performs a simple scrolling operation that moves the contents of the <code>screen</code> array up by one row. The first row&#8217;s contents are replaced by the second row&#8217;s contents, and the final row is set to spaces. I&#8217;ve coded this function for clarity, but it could be improved from a performance perspective.</p><h2>Conclusion</h2><p>Console&#8217;s implementation leaves lots of room for improvement. You can add missing features (e.g., echo asterisks while entering a password), boost <code>screen</code>-oriented loop performance (perhaps via<code>Array</code>&#8216;s <code>splice()</code> function), and make the library more robust through argument validation (e.g., compare what is passed with <code>undefined</code>) and exception throwing. Have fun.</p><table
width="60%" border="1" align="center"><tbody><tr><th
bgcolor="#0000c0"><span
style="color: #ffffff;">Note</span></th></tr><tr><td>All files pertaining to this article are located in <a
href="http://www.sitepoint.com/wp-content/uploads/1/files/2012/05/code.zip" target="_blank">code.zip</a>.</td></tr></tbody></table> <span
id="pty_trigger"></span><div
style='padding:20px 0px 50px 0px;'><div
style='float:left;padding-left:40px;'><div
id='div-gpt-ad-1335489406190-0' style='width:300px; height:100px;'> <script type='text/javascript'>googletag.cmd.push(function() { googletag.display('div-gpt-ad-1335489406190-0'); });</script> </div></div><div
style='float:right;padding-right:40px;'><div
id='div-gpt-ad-1335489406190-1' style='width:300px; height:100px;'> <script type='text/javascript'>googletag.cmd.push(function() { googletag.display('div-gpt-ad-1335489406190-1'); });</script> </div></div><div
style='clear:both'></div></div><div
style='clear:both'></div><div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/SitepointFeed?a=qc9icwUI3kQ:PFGuufU4sg4:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/SitepointFeed?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/SitepointFeed?a=qc9icwUI3kQ:PFGuufU4sg4:qj6IDK7rITs"><img src="http://feeds.feedburner.com/~ff/SitepointFeed?d=qj6IDK7rITs" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/SitepointFeed?a=qc9icwUI3kQ:PFGuufU4sg4:gIN9vFwOqvQ"><img src="http://feeds.feedburner.com/~ff/SitepointFeed?i=qc9icwUI3kQ:PFGuufU4sg4:gIN9vFwOqvQ" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/SitepointFeed/~4/qc9icwUI3kQ" height="1" width="1"/>]]></content:encoded> <wfw:commentRss>http://www.sitepoint.com/add-a-web-console-to-your-toolbox-part-2/feed/</wfw:commentRss> <slash:comments>5</slash:comments> <feedburner:origLink>http://www.sitepoint.com/add-a-web-console-to-your-toolbox-part-2/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=add-a-web-console-to-your-toolbox-part-2</feedburner:origLink></item> </channel> </rss><!-- Performance optimized by W3 Total Cache. Learn more: http://www.w3-edge.com/wordpress-plugins/

Page Caching using memcached
Database Caching 21/31 queries in 0.114 seconds using memcached
Object Caching 3027/3027 objects using memcached

Served from: www.sitepoint.com @ 2012-05-20 22:53:58 -->

