<?xml version="1.0" encoding="UTF-8"?>
<!-- generator="wordpress/2.2.2" -->
<rss version="2.0"
	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/"
	>

<channel>
	<title>PinkCrow Blog</title>
	<link>http://blogs.pinkcrow.net</link>
	<description>Pink news and stuff</description>
	<pubDate>Tue, 18 Sep 2007 13:27:06 +0000</pubDate>
	<generator>http://wordpress.org/?v=2.2.2</generator>
	<language>en</language>
			<item>
		<title>If you like tennis</title>
		<link>http://blogs.pinkcrow.net/if-you-like-tennis/69/</link>
		<comments>http://blogs.pinkcrow.net/if-you-like-tennis/69/#comments</comments>
		<pubDate>Tue, 18 Sep 2007 13:25:38 +0000</pubDate>
		<dc:creator>Valeriu Buzila</dc:creator>
		
		<category><![CDATA[General]]></category>

		<guid isPermaLink="false">http://blogs.pinkcrow.net/if-you-like-tennis/69/</guid>
		<description><![CDATA[
]]></description>
			<content:encoded><![CDATA[<p><a href="http://blogs.pinkcrow.net/wp-content/uploads/2007/09/bnjlinks-tennis.jpg" title="if you like tennis"><img src="http://blogs.pinkcrow.net/wp-content/uploads/2007/09/bnjlinks-tennis.jpg" alt="if you like tennis" height="186" width="592" /></a></p>
]]></content:encoded>
			<wfw:commentRss>http://blogs.pinkcrow.net/if-you-like-tennis/69/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Stimati angajati</title>
		<link>http://blogs.pinkcrow.net/stimati-angajati/67/</link>
		<comments>http://blogs.pinkcrow.net/stimati-angajati/67/#comments</comments>
		<pubDate>Fri, 14 Sep 2007 12:11:03 +0000</pubDate>
		<dc:creator>Valeriu Buzila</dc:creator>
		
		<category><![CDATA[General]]></category>

		<guid isPermaLink="false">http://blogs.pinkcrow.net/stimati-angajati/67/</guid>
		<description><![CDATA[Stimati angajati,
Va rugam sa recoltati si sa predati fiecare la departamentul resurse
umane 2 ml. de sange si 2 g. fecale, deorece dorim sa stabilim daca
aveti munca in sange sau va cacati pe ea.
CONDUCEREA
]]></description>
			<content:encoded><![CDATA[<p>Stimati angajati,</p>
<p>Va rugam sa recoltati si sa predati fiecare la departamentul resurse<br />
umane 2 ml. de sange si 2 g. fecale, deorece dorim sa stabilim daca<br />
aveti munca in sange sau va cacati pe ea.</p>
<p>CONDUCEREA</p>
]]></content:encoded>
			<wfw:commentRss>http://blogs.pinkcrow.net/stimati-angajati/67/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Simply JavaScript: The Three Layers of the Web</title>
		<link>http://blogs.pinkcrow.net/simply-javascript-the-three-layers-of-the-web/66/</link>
		<comments>http://blogs.pinkcrow.net/simply-javascript-the-three-layers-of-the-web/66/#comments</comments>
		<pubDate>Tue, 04 Sep 2007 11:15:00 +0000</pubDate>
		<dc:creator>Valeriu Buzila</dc:creator>
		
		<category><![CDATA[Software]]></category>

		<guid isPermaLink="false">http://blogs.pinkcrow.net/simply-javascript-the-three-layers-of-the-web/66/</guid>
		<description><![CDATA[&#8220;Once upon a time, there was &#8230; ‘A king!&#8217; my little readers will say right away. No, children, you are wrong. Once upon a time there was a piece of wood &#8230;&#8221;
&#8211;The Adventures of Pinocchio
You can do a lot without JavaScript. Using Hypertext Markup Language (HTML &#8212; throughout this article, we&#8217;ll refer to HTML and [...]]]></description>
			<content:encoded><![CDATA[<p><strong><em>&#8220;Once upon a time, there was &#8230; ‘A king!&#8217; my little readers will say right away. No, children, you are wrong. Once upon a time there was a piece of wood &#8230;&#8221;</em><br />
&#8211;<em>The Adventures of Pinocchio</em></strong></p>
<p>You can do a lot without <a href="http://www.sitepoint.com/glossary.php?q=J#term_9" class="glossary" title="JavaScript is a Web scripting language most commonly used for client-side applications.">JavaScript</a>. Using Hypertext Markup Language (<a href="http://www.sitepoint.com/glossary.php?q=H#term_75" class="glossary" title="HTML stands for HyperText Markup Language.">HTML</a> &#8212; throughout this article, we&#8217;ll refer to HTML and <a href="http://www.sitepoint.com/glossary.php?q=X#term_63" class="glossary" title="XHTML is a reformulation of HTML 4 as an XML 1.0 application.">XHTML</a> as just HTML. Which you choose is up to you, and doesn&#8217;t have a much to do with JavaScript. In case it matters to you, the HTML code we&#8217;ll present in this article will be valid XHTML 1.0 Strict), you can produce complex documents that intricately describe the content of a page &#8212; and that content&#8217;s meaning &#8212; to the minutest detail. In this chapter from the new <a href="http://www.sitepoint.com/books/javascript1/" class="sublink"><em>Simply Javascript</em></a> (you can also <a href="http://www.sitepoint.com/popup/popup.php?zone=2&amp;popupid=97" class="sublink">download this article</a>, along with two others, as a PDF), I&#8217;ll show you that by using Cascading Style Sheets (<a href="http://www.sitepoint.com/glossary.php?q=C#term_8" class="glossary" title="CSS, or Cascading Style Sheets, comprise styling and formatting rules that are applied to Web documents.">CSS</a>), you can present that content in myriad ways, with variations as subtle as a single color, as striking as replacing text with an image.</p>
<p>No matter how you dress it up, though, HTML and CSS can only achieve an animatronic monstrosity that wobbles precariously when something moves nearby. It&#8217;s when you wheel in the JavaScript that you really can breathe life into your Pinocchio, lifting you as its creator from humble shop clerk to web design mastery!</p>
<p>But whether your new creation has the graceful stride of a runway model, or the shuffling gait of Dr. Frankenstein&#8217;s monster, depends as much on the quality of its HTML and CSS origins as it does on the JavaScript code that brought it to life.</p>
<p>Before we learn to work miracles, therefore, let&#8217;s take a little time to review how to build web sites that look good both inside <em>and</em> out, and see how JavaScript fits into the picture.</p>
<p><strong>Keep &#8216;em Separated</strong></p>
<p>Not so long ago, professional web designers would gleefully pile HTML, CSS, and JavaScript code into a single file, name it <code>index.html</code> (or <code>default.htm</code>, if they had been brainwashed by Microsoft), and call it a web page. I&#8217;ve conceptualized this as something like Figure 1. You can still do this today, but be prepared for your peers to call it something rather less polite.</p>
<p><a href="http://i2.sitepoint.com/graphics/threelayers_mess.png" class="beatbox"><em>Figure 1. A single-file mess (click to view image)</em><img src="http://i2.sitepoint.com/graphics/threelayers_mess.png" height="336" width="400" /></a></p>
<p>Somewhere along the way, web designers realized that the code they write when putting together a web page does three fundamental things:</p>
<ul>
<li>It describes the <em>content</em> of the page.</li>
<li>It specifies the <em>presentation</em> of that content.</li>
<li>It controls the <em>behavior</em> of that content.</li>
</ul>
<p>They also realized that keeping these three types of code separate, as depicted in Figure 2, “Separation of concerns,&#8221; made their jobs easier, and helped them to make web pages that work better under adverse conditions, such as when users have JavaScript disabled in their browsers.</p>
<p>Computer geeks have known about this for years, and have even given this principle a geeky name: the <em>separation of concerns</em>.</p>
<p><a href="http://i2.sitepoint.com/graphics/threelayers_separation.png" class="beatbox"><em>Figure 2. The separation of concerns (click to view image)</em><img src="http://i2.sitepoint.com/graphics/threelayers_separation.png" height="227" width="400" /></a></p>
<p>Now, realizing this is one thing, but actually <em>doing</em> it is another &#8212; especially if you&#8217;re not a computer geek. I <em>am</em> a computer geek, and I&#8217;m tempted to do the wrong thing all the time.</p>
<p>I&#8217;ll be happily editing the HTML code that describes a web page&#8217;s content, when suddenly I&#8217;ll find myself thinking how nice that text would look if it were in a slightly different shade of gray, if it were nudged a little to the left, and if it had that hee-larious photocopy of my face I made at the last SitePoint office party in the background. Prone to distraction as I am, I want to make those changes right away. Now which is easier: opening up a separate CSS file to modify the page&#8217;s style sheet, or just typing those style properties into the HTML code I&#8217;m already editing?</p>
<p>Like behaving yourself at work functions, keeping the types of code you write separate from one another takes discipline. But once you understand the benefits, you too will be able to summon the willpower it takes to stay on the straight and narrow.</p>
<p><strong>Three Layers</strong></p>
<p>Keeping different kinds of code as separate as possible is a good idea in any kind of programming. It makes it easier to reuse portions of that code in future projects, it reduces the amount of duplicate code you end up writing, and it makes it easier to find and fix problems months and years later.</p>
<p>When it comes to the Web, there&#8217;s one more reason to keep your code separate: it lets you cater for the many different ways in which people access web pages.</p>
<p>Depending on your audience, the majority of your visitors may use well-appointed desktop browsers with cutting-edge CSS and JavaScript support, but many might be subject to corporate IT policies that force them to use older browsers, or to browse with certain features (like JavaScript) disabled.</p>
<p>Visually impaired users often browse using screen reader or screen magnifier software, and for these users your slick visual design can be more of a hindrance than a help.</p>
<p>Some users won&#8217;t even <em>visit</em> your site, preferring to read content feeds in RSS or similar formats if you offer them. When it comes time to build these feeds, you&#8217;ll want to be able to send your HTML content to these users without any JavaScript or CSS junk.</p>
<p>The key to accommodating the broadest possible range of visitors to your site is to think of the Web in terms of <em>three layers</em>, which conveniently correspond to the three kinds of code I mentioned earlier. These layers are illustrated in Figure 3, “The three layers of the Web.&#8221;</p>
<p><a href="http://i2.sitepoint.com/graphics/threelayers_3layers.png" class="beatbox"><em>Figure 3. The three layers of the Web (click to view image)</em><img src="http://i2.sitepoint.com/graphics/threelayers_3layers.png" height="206" width="400" /></a></p>
<p>When building a site, we work through these layers from the bottom up:</p>
<ol>
<li>We start by producing the <em>content</em> in HTML format. This is the base layer, which any visitor using any kind of browser should be able to view.</li>
<li>With that done, we can focus on making the site look better, by adding a layer of <em>presentation</em> information using CSS. The site will now look good to users able to display CSS styles.</li>
<li>Lastly, we can use JavaScript to introduce an added layer of interactivity and dynamic <em>behavior</em>, which will make the site easier to use in browsers equipped with JavaScript.</li>
</ol>
<p>If we keep the HTML, CSS, and JavaScript code separate, we&#8217;ll find it much easier to make sure that the content layer remains readable in browsing environments where the presentation and/or behavior layers are unable to operate. This “start at the bottom&#8221; approach to web design is known in the trade as <em>progressive enhancement</em>.</p>
<p>Let&#8217;s look at each of these layers in isolation to see how we can best maintain this separation of code.</p>
<p><em><a href="http://www.sitepoint.com/glossary.php?q=H#term_75" class="glossary" title="HTML stands for HyperText Markup Language.">HTML</a> for Content</em></p>
<p>Everything that&#8217;s needed to read and understand the content of a web page belongs in the HTML code for that page &#8212; nothing more, nothing less. It&#8217;s that simple. Web designers get into trouble when they forget the K.I.S.S. principle (Keep It Simple, Stupid) and cram non-content information into their HTML code, or alternatively move some of the page&#8217;s content into the <a href="http://www.sitepoint.com/glossary.php?q=C#term_8" class="glossary" title="CSS, or Cascading Style Sheets, comprise styling and formatting rules that are applied to Web documents.">CSS</a> or <a href="http://www.sitepoint.com/glossary.php?q=J#term_9" class="glossary" title="JavaScript is a Web scripting language most commonly used for client-side applications.">JavaScript</a> code for the page.</p>
<p>A common example of non-content information that&#8217;s crammed into pages is <em>presentational HTML</em> &#8212; HTML code that describes how the content should <em>look</em> when it&#8217;s displayed in the browser. This can include old-fashioned HTML tags like <code>&lt;b&gt;</code>, <code>&lt;i&gt;</code>, <code>&lt;u&gt;</code>, <code>&lt;tt&gt;</code>, and <code>&lt;font&gt;</code>:</p>
<p><code>&lt;p&gt;Whatever you do, &lt;a href="666.html"&gt;<em>&lt;font color=&#8221;red&#8221;</em>&gt;don&#8217;t<br />
click this link<em>&lt;/font&gt;</em>&lt;/a&gt;!&lt;/p&gt;</code></p>
<p>It can take the form of inline CSS applied with the style attribute:</p>
<p><code>&lt;p&gt;Whatever you do, &lt;a href="666.html" <em>style=&#8221;color: red;&#8221;</em>&gt;don&#8217;t<br />
click this link&lt;/a&gt;!&lt;/p&gt;</code></p>
<p>It can also include the secret shame of many well-intentioned web designers: CSS styles applied with presentational class names:</p>
<p><code>&lt;p&gt;Whatever you do, &lt;a href="666.html" <em>class=&#8221;red&#8221;</em>&gt;don&#8217;t click<br />
this link&lt;/a&gt;!&lt;/p&gt;</code></p>
<p><em><strong>Presentational Class Names?</strong> If that last example looks okay to you, you&#8217;re not alone, but it&#8217;s definitely bad mojo. If you later decide you want that link to be yellow, you&#8217;re either stuck updating both the class name and the CSS styles that apply to it, or living with the embarrassment of a class named “red&#8221; that is actually styled yellow. <em>That&#8217;ll</em> turn your face yellow &#8212; er, red!</em></p>
<p>Rather than embedding presentation information in your HTML code, you should focus on the <em>reason</em> for the action &#8212; for example, you want a link to be displayed in a different color. Is the link especially important? Consider surrounding it with a tag that describes the emphasis you want to give it:</p>
<p><code>&lt;p&gt;Whatever you do, &lt;<em>em</em>&gt;&lt;a href=&#8221;evil.html&#8221;&gt;don&#8217;t click this<br />
link&lt;/a&gt;&lt;/<em>em</em>&gt;!&lt;/p&gt;</code></p>
<p>Is the link a warning? HTML doesn&#8217;t have a tag to describe a warning, but you could choose a CSS class name that conveys this information:</p>
<p><code>&lt;p&gt;Whatever you do, &lt;a href="evil.html" <em>class=&#8221;warning&#8221;</em>&gt;don&#8217;t<br />
click this link&lt;/a&gt;!&lt;/p&gt;</code></p>
<p>You can take this approach too far, of course. Some designers mistake tags like &lt;h1&gt; as presentational, and attempt to remove this presentational code from their HTML:</p>
<p><code>&lt;p class="heading"&gt;A heading with an identity crisis&lt;/p&gt;</code></p>
<p>Really, the presentational information that you should keep out of your document is the font, size, and color in which a heading is to be displayed. The fact that a piece of text is a heading <em>is</em> part of the content, and as such should be reflected in the HTML code. So this code is perfectly fine:</p>
<p><code>&lt;h1&gt;A heading at peace with itself&lt;/h1&gt;</code></p>
<p>In short, your HTML should do everything it can to convey the meaning, or <em>semantics</em> of the content in the page, while steering clear of describing how it should look. Web standards geeks call HTML code that does this <em>semantic markup</em>.</p>
<p>Writing semantic markup allows your HTML files to stand on their own as meaningful documents. People who, for whatever reason, cannot read these documents by viewing them in a typical desktop web browser will be better able to make sense of them this way. Visually impaired users, for example, will be able to use assistive software like screen readers to listen to the page as it&#8217;s read aloud, and the more clearly your HTML code describes the content&#8217;s meaning, the more sense tools like these will be able to make of it.</p>
<p>Best of all, however, semantic markup lets you apply new styles (presentation) and interactive features (behavior) without having to make many (or, in some cases, any!) changes to your HTML code.</p>
<p><em>CSS for Presentation</em></p>
<p>Obviously, if the content of a page should be entirely contained within its HTML code, its style &#8212; or presentation &#8212; should be fully described in the CSS code that&#8217;s applied to the page.</p>
<p>With all the work you&#8217;ve done to keep your HTML free of presentational code and rich with semantics, it would be a shame to mess up that file by filling it with snippets of CSS.</p>
<p>As you probably know, CSS styles can be applied to your pages in three ways:</p>
<p><strong>inline styles:</strong><br />
<code>&lt;a href="evil.html" <em>style=&#8221;color: red;&#8221;</em>&gt;</code><br />
Inline styles are tempting for the reasons I explained earlier: you can apply styles to your content as you create it, without having to switch gears and edit a separate style sheet. But as we saw in the previous section, you&#8217;ll want to avoid inline styles like the plague if you want to keep your HTML code meaningful to those who cannot see the styles.</p>
<p><strong>embedded styles:</strong><br />
<code>&lt;style type="text/css"&gt;<br />
<em>.warning {<br />
color: red;<br />
}</em><br />
&lt;/style&gt;<br />
&amp;#8942;<br />
&lt;a href=&#8221;evil.html&#8221; <em>class=&#8221;warning&#8221;</em>&gt;</code><br />
Embedded styles keep your markup clean, but tie your styles to a single document. In most cases, you&#8217;ll want to share your styles across multiple pages on your site, so it&#8217;s best to steer clear of this approach as well.</p>
<p><strong>external styles:</strong><br />
<code>&lt;link rel="stylesheet" href="styles.css" /&gt;<br />
&amp;#8942;<br />
&lt;a href="evil.html" <em>class=&#8221;warning&#8221;</em>&gt;<br />
<strong>Example 1.1.</strong> styles.css</code></p>
<p><code><em>.warning {<br />
color: red;<br />
}</em></code><br />
External styles are really the way to go, because they let you share your styles between multiple documents, they reduce the amount of code browsers need to download, and they also let you modify the look of your site without having to get your hands dirty editing HTML.</p>
<p>But you knew all that, right? We&#8217;re dealing with a JavaScript book, after all, so let&#8217;s talk about the JavaScript that goes into your pages.</p>
<p><em>JavaScript for Behavior</em></p>
<p>As with CSS, you can add JavaScript to your web pages in a number of ways.</p>
<p>You can embed JavaScript code directly in your HTML content:<br />
<code>&lt;a href="evil.html" <em>onclick=&#8221;JavaScript code here&#8221;</em>&gt;</code></p>
<p>You can include JavaScript code at the top of your HTML document in a &lt;script&gt; tag:<br />
<code>&lt;script type="text/javascript"&gt;&lt;!--//--&gt;&lt;![CDATA[//&gt;&lt;!--<br />
<em>JavaScript code here</em><br />
//&#8211;&gt;&lt;!]]&gt;&lt;/script&gt;<br />
&amp;#8942;<br />
&lt;a href=&#8221;evil.html&#8221; <em>class=&#8221;warning&#8221;&gt;</em></code></p>
<p><em><strong>CDATA?</strong> If you&#8217;re wondering what all that gobbledygook is following the <code>&lt;script&gt;</code> tag and preceding the <code>&lt;/script&gt;</code> tag, that&#8217;s what it takes to legitimately embed JavaScript in an <a href="http://www.sitepoint.com/glossary.php?q=X#term_63" class="glossary" title="XHTML is a reformulation of HTML 4 as an XML 1.0 application.">XHTML</a> document without confusing web browsers that don&#8217;t understand XHTML (like Internet Explorer).</em></p>
<p>If you write your page with HTML instead of XHTML, you can get away with this much simpler syntax:<br />
<code>&lt;script type="text/javascript"&gt;<br />
JavaScript code here<br />
&lt;/script&gt;</code></p>
<p>You can put your JavaScript code in a separate file, then link to that file from as many HTML documents as you like:<br />
<code>&lt;script type="text/javascript" src="script.js"&gt;&lt;/script&gt;<br />
&amp;#8942;<br />
&lt;a href="evil.html" <em>class=&#8221;warning&#8221;</em>&gt;<br />
<strong>Example 1.2.</strong> script.js <strong>(excerpt)</strong><br />
<em>JavaScript code here</em></code></p>
<p>Guess which method you should use.</p>
<p>Writing JavaScript that enhances <a href="http://www.sitepoint.com/glossary.php?q=U#term_60" class="glossary" title="Usability refers to the ease with which a user can use an interface to achieve their goals.">usability</a> without cluttering up the HTML document(s) it is applied to, without locking out users that have JavaScript disabled in their browsers, and without interfering with <em>other</em> JavaScript code that might be applied to the same page, is called <em>unobtrusive scripting</em>.</p>
<p>Unfortunately, while many professional web developers have clued in to the benefits of keeping their CSS code in separate files, there is still a lot of JavaScript code mixed into HTML out there. By showing you the <em>right</em> way to use JavaScript, we hope to help change that.</p>
<p><strong>The Right Way</strong></p>
<p>So, how much does all this stuff really matter? After all, people have been building web sites with HTML, CSS, and JavaScript mixed together for years, and for the majority of people browsing the Web, those sites have worked.</p>
<p>Well, as you come to learn JavaScript, it&#8217;s arguably more important to get it right than ever before. JavaScript is by far the most powerful of the three languages that you&#8217;ll use to design web sites, and as such it gives you unprecedented freedom to completely mess things up.</p>
<p>As an example, if you really, really like JavaScript, you could go so far as to put everything &#8212; content, presentation, and behavior &#8212; into your JavaScript code. I&#8217;ve actually seen this done, and it&#8217;s not pretty &#8212; especially when a browser with JavaScript disabled comes along.</p>
<p>Even more telling is the fact that JavaScript is the only one of these three languages that has the ability to hang the browser, making it unresponsive to the user.</p>
<p>Therefore, we&#8217;ll do our darnedest to show you the right way to use JavaScript, not just because it keeps your code tidy, but because it helps to keep the Web working the way it&#8217;s meant to &#8212; by making content <a href="http://www.sitepoint.com/glossary.php?q=A#term_61" class="glossary" title="Accessibility deals with the issues of making online content available for experience, enjoyment, and use by all visitors, including those who do not fit the standard "Web user" mould.">accessible</a> to as many people as possible, no matter which web browser they choose to use.</p>
<p><strong>JavaScript Libraries</strong></p>
<p>As I mentioned, one of the benefits of keeping different kinds of code separate is that it makes it easier to take code that you&#8217;ve written for one site and reuse it on another. Certain JavaScript maniacs (to be referred to from this point on as “people&#8221;) have taken the time to assemble vast <em>libraries</em> of useful, unobtrusive JavaScript code that you can download and use on your own web sites for free.</p>
<p>Throughout <a href="http://www.sitepoint.com/books/javascript1/" class="sublink"><em>Simply Javascript</em></a>, we build each of the examples from scratch &#8212; all of the JavaScript code you need can be found right there. Since there isn&#8217;t always time to do this in the real world, however, and because libraries are quickly becoming an important part of the JavaScript landscape, we&#8217;ll also look at how the popular JavaScript libraries do things whenever the opportunity presents itself.</p>
<p>Here are the libraries that we use in the book:</p>
<ul>
<li><a href="http://www.prototypejs.org/" class="sublink">Prototype</a></li>
<li><a href="http://script.aculo.us/" class="sublink">script.aculo.us</a></li>
<li><a href="http://developer.yahoo.com/yui/" class="sublink">Yahoo! User Interface Library (YUI)</a></li>
<li><a href="http://dojotoolkit.org/" class="sublink">Dojo</a></li>
<li><a href="http://jquery.com/" class="sublink">jQuery</a></li>
<li><a href="http://mootools.net/" class="sublink">MooTools</a></li>
</ul>
<p><em><strong>Not All Libraries are Created Equal</strong> Watch out for sites offering snippets of JavaScript code for you to copy and paste into your web pages to achieve a particular effect. There is a lot of free code out there, but not all of it is good. In general, the good libraries come in the form of JavaScript (<code>.js</code>) files that you can link into your pages unobtrusively, instead of pasting JavaScript directly into your HTML code. If you don&#8217;t feel confident to judge whether a particular JavaScript library is good or bad, ask for some advice in the SitePoint Forums, or just stick with the libraries I just mentioned &#8212; they&#8217;re all very good.</em></p>
<p><strong>Let&#8217;s Get Started!</strong></p>
<p>Enough preaching &#8212; you checked out this article to learn JavaScript, right? Clean HTML and CSS are nice and all, but it&#8217;s time to take the plunge into the third layer of the Web: behavior. The chapters of <a href="http://www.sitepoint.com/books/javascript1/" class="sublink"><em>Simply Javascript</em></a> that follow the one from which this article is reproduced deal in greater depth with this topic &#8212; and because we&#8217;re feeling generous, we&#8217;ve decided to throw them in for your delectation! So don&#8217;t forget to <a href="http://www.sitepoint.com/popup/popup.php?zone=2&amp;popupid=97" class="sublink">download this chapter as a PDF</a>, as well as Chapter 2: Programming with JavaScript and Chapter 3: Document Access.</p>
<p>In Chapter 2, you&#8217;ll learn that as JavaScript is a programming language, you must get your head around the way computer programs work &#8212; which to some extent means learning to think like a computer &#8212; in order to use it most effectively. The simple concepts introduced in this chapter &#8212; statements, variables, expressions, loops, functions, and objects &#8212; are the building blocks for every JavaScript program you&#8217;ll ever write.</p>
<p>And Chapter 3? While certain people enjoy writing JavaScript code for its own sake, you wouldn&#8217;t want to run into them in a dark alley at night. As a well-adjusted web developer, you&#8217;ll probably want to use JavaScript to make changes to the contents of your web pages using the Document Object Model (<a href="http://www.sitepoint.com/glossary.php?q=D#term_39" class="glossary" title="A DOM, or Document Object Model, is a tree representation of the structure of Web document.">DOM</a>). Lucky for you, we wrote a whole chapter to show you how!</p>
<p>Then, of course, <a href="http://www.sitepoint.com/books/javascript1/toc.php" class="sublink">there&#8217;s more&#8230;</a></p>
<p>Get ready to start using some cool (and unobtrusive) JavaScript!</p>
]]></content:encoded>
			<wfw:commentRss>http://blogs.pinkcrow.net/simply-javascript-the-three-layers-of-the-web/66/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Nifty Navigation Using CSS</title>
		<link>http://blogs.pinkcrow.net/nifty-navigation-using-css/65/</link>
		<comments>http://blogs.pinkcrow.net/nifty-navigation-using-css/65/#comments</comments>
		<pubDate>Tue, 04 Sep 2007 11:10:39 +0000</pubDate>
		<dc:creator>Valeriu Buzila</dc:creator>
		
		<category><![CDATA[Software]]></category>

		<guid isPermaLink="false">http://blogs.pinkcrow.net/nifty-navigation-using-css/65/</guid>
		<description><![CDATA[Unless you limit yourself to one-page web sites, you&#8217;ll need to design navigation. In fact, navigation is among the most important parts of any web design, and requires a great deal of thought if visitors are to move around your site easily.
Making site navigation easy is one area in which CSS really comes into its [...]]]></description>
			<content:encoded><![CDATA[<p><strong>Unless you limit yourself to one-page web sites, you&#8217;ll need to design navigation. In fact, navigation is among the most important parts of any web design, and requires a great deal of thought if visitors are to move around your site easily.</strong></p>
<p>Making site navigation easy is one area in which <a href="http://www.sitepoint.com/glossary.php?q=C#term_8" class="glossary" title="CSS, or Cascading Style Sheets, comprise styling and formatting rules that are applied to Web documents.">CSS</a> really comes into its own. Older methods of creating navigation tended to rely on lots of images, nested tables, and <a href="http://www.sitepoint.com/glossary.php?q=J#term_9" class="glossary" title="JavaScript is a Web scripting language most commonly used for client-side applications.">JavaScript</a> &#8212; all of which can seriously affect the <a href="http://www.sitepoint.com/glossary.php?q=U#term_60" class="glossary" title="Usability refers to the ease with which a user can use an interface to achieve their goals.">usability</a> and <a href="http://www.sitepoint.com/glossary.php?q=A#term_61" class="glossary" title="Accessibility deals with the issues of making online content available for experience, enjoyment, and use by all visitors, including those who do not fit the standard "Web user" mould.">accessibility</a> of a site. If your site cannot be navigated using a device that doesn&#8217;t support JavaScript, for example, not only are you blocking users who have turned JavaScript off, but you&#8217;re also locking out text-only devices such as screen readers and search engine robots &#8212; they&#8217;ll never get past your home page to index the content of your site. If your design clients don&#8217;t care about accessibility, tell them their clunky menu is stopping them from achieving a decent search engine ranking!</p>
<p>CSS allows you to create attractive navigation that, in reality, is no more than text &#8212; text that can be marked up in such a way as to ensure that it&#8217;s both <a href="http://www.sitepoint.com/glossary.php?q=A#term_61" class="glossary" title="Accessibility deals with the issues of making online content available for experience, enjoyment, and use by all visitors, including those who do not fit the standard "Web user" mould.">accessible</a> and understandable by all those who can&#8217;t physically see your design, but still want to get to your content. In this chapter, we&#8217;ll look at a variety of solutions for creating CSS-based navigation. Some are suited to implementation on an existing site, to make it load more quickly, and boost its accessibility by replacing an old-fashioned, image-based navigation. Others are more suited to incorporation within a pure CSS layout.</p>
<p>Before you begin, you might want to <a href="http://www.sitepoint.com/popup/popup.php?zone=2&amp;popupid=99" class="sublink">download this article in PDF format</a>, so you can use it offline, at your leisure. The PDF also includes other chapters from <a href="http://www.sitepoint.com/books/cssant2/" class="sublink"><em>The CSS Anthology: 101 Essential Tips, Tricks and Hacks</em></a> on using CSS with images, and accessibility and alternative devices.</p>
<p>But now, on with the show.</p>
<h5>How do I style a structural list as a navigation menu?</h5>
<p>For new sites, you&#8217;re likely to be trying to avoid using tables for layout, or using them only where absolutely necessary. Therefore, a navigation solution that doesn&#8217;t involve tables is useful; also, by eradicating table elements, you&#8217;ll find that your page contains far less markup.</p>
<h5><em>Solution</em></h5>
<p>A navigation system is simply a list of places that users can visit on the site. Therefore, an unordered list is the ideal way to mark up your navigation. The navigation in Figure 1 is marked up as a list, and styled using CSS, as you can see.</p>
<p><a href="http://i2.sitepoint.com/graphics/navigation_using-styled-list.png" class="beatbox"><em>Creating navigation by styling a list (click to view image)</em><img src="http://i2.sitepoint.com/graphics/navigation_using-styled-list.png" height="297" width="400" /></a><br />
<code>&lt;!DOCTYPE <a href="http://www.sitepoint.com/glossary.php?q=H#term_75" class="glossary" title="HTML stands for HyperText Markup Language.">html</a> PUBLIC &#8220;-//<a href="http://www.sitepoint.com/glossary.php?q=W#term_49" class="glossary" title="The World Wide Web Consortium (W3C) - A consortium of industry leaders for drafting Web standards.">W3C</a>//DTD <a href="http://www.sitepoint.com/glossary.php?q=X#term_63" class="glossary" title="XHTML is a reformulation of HTML 4 as an XML 1.0 application.">XHTML</a> 1.0 Strict//EN&#8221;<br />
&#8220;http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd&#8221;&gt;<br />
&lt;html xmlns=&#8221;http://www.w3.org/1999/xhtml&#8221; lang=&#8221;en-US&#8221;&gt;<br />
&lt;head&gt;<br />
&lt;title&gt;Lists as navigation&lt;/title&gt;<br />
&lt;meta http-equiv=&#8221;content-type&#8221;<br />
content=&#8221;text/html; charset=utf-8&#8243; /&gt;<br />
&lt;link rel=&#8221;stylesheet&#8221; type=&#8221;text/css&#8221; href=&#8221;listnav1.css&#8221; /&gt;<br />
&lt;/head&gt;<br />
&lt;body&gt;<br />
&lt;div id=&#8221;navigation&#8221;&gt;<br />
&lt;ul&gt;<br />
&lt;li&gt;&lt;a href=&#8221;#&#8221;&gt;Recipes&lt;/a&gt;&lt;/li&gt;<br />
&lt;li&gt;&lt;a href=&#8221;#&#8221;&gt;Contact Us&lt;/a&gt;&lt;/li&gt;<br />
&lt;li&gt;&lt;a href=&#8221;#&#8221;&gt;Articles&lt;/a&gt;&lt;/li&gt;<br />
&lt;li&gt;&lt;a href=&#8221;#&#8221;&gt;Buy Online&lt;/a&gt;&lt;/li&gt;<br />
&lt;/ul&gt;<br />
&lt;/div&gt;<br />
&lt;/body&gt;<br />
&lt;/html&gt;<br />
#navigation {<br />
width: 200px;<br />
}<br />
#navigation ul {<br />
list-style: none;<br />
margin: 0;<br />
padding: 0;<br />
}<br />
#navigation li {<br />
border-bottom: 1px solid #ED9F9F;<br />
}<br />
#navigation li a:link, #navigation li a:visited  {<br />
font-size: 90%;<br />
display: block;<br />
padding: 0.4em 0 0.4em 0.5em;<br />
border-left: 12px solid #711515;<br />
border-right: 1px solid #711515;<br />
background-color: #B51032;<br />
color: #FFFFFF;<br />
text-decoration: none;<br />
}</code></p>
<h5><em>Discussion</em></h5>
<p>To create navigation based on an unordered list, first create your list, placing each navigation link inside a <code>li</code> element:</p>
<p><code>&lt;ul&gt;<br />
&lt;li&gt;&lt;a href="#"&gt;Recipes&lt;/a&gt;&lt;/li&gt;<br />
&lt;li&gt;&lt;a href="#"&gt;Contact Us&lt;/a&gt;&lt;/li&gt;<br />
&lt;li&gt;&lt;a href="#"&gt;Articles&lt;/a&gt;&lt;/li&gt;<br />
&lt;li&gt;&lt;a href="#"&gt;Buy Online&lt;/a&gt;&lt;/li&gt;<br />
&lt;/ul&gt;</code></p>
<p>Next, wrap the list in a <code>div</code> with an appropriate ID:</p>
<p><code>&lt;div id="navigation"&gt;<br />
&lt;ul&gt;<br />
&lt;li&gt;&lt;a href="#"&gt;Recipes&lt;/a&gt;&lt;/li&gt;<br />
&lt;li&gt;&lt;a href="#"&gt;Contact Us&lt;/a&gt;&lt;/li&gt;<br />
&lt;li&gt;&lt;a href="#"&gt;Articles&lt;/a&gt;&lt;/li&gt;<br />
&lt;li&gt;&lt;a href="#"&gt;Buy Online&lt;/a&gt;&lt;/li&gt;<br />
&lt;/ul&gt;<br />
&lt;/div&gt;</code></p>
<p>As Figure 2 shows, this markup looks fairly ordinary with the browser&#8217;s default styles applied.</p>
<p><a href="http://i2.sitepoint.com/graphics/navigation_unstyled-list-basic.png" class="beatbox"><em>A very basic, unstyled list (click to view image)</em><img src="http://i2.sitepoint.com/graphics/navigation_unstyled-list-basic.png" height="298" width="400" /></a></p>
<p>The first thing we need to do is style the container in which the navigation sits &#8212; in this case, <code>#navigation</code>:</p>
<p><code>#navigation {<br />
width: 200px;<br />
}</code></p>
<p>I&#8217;ve given <code>#navigation</code> a width. If this navigation system were part of a CSS page layout, I&#8217;d probably add some positioning information to this ID as well.</p>
<p>Next, we style the list:</p>
<p><code>#navigation ul {<br />
list-style: none;<br />
margin: 0;<br />
padding: 0;<br />
}</code></p>
<p>As Figure 3 illustrates, the above rule removes list bullets and the indented margin that browsers apply, by default, when displaying a list.</p>
<p><a href="http://i2.sitepoint.com/graphics/navigation_list-no-indent-bullets.png" class="beatbox"><em>Viewing the list after indentation and bullets are removed (click to view image)</em><img src="http://i2.sitepoint.com/graphics/navigation_list-no-indent-bullets.png" height="295" width="400" /></a></p>
<p>The next step is to style the <code>li</code> elements within <code>#navigation</code>, to give them a bottom border:</p>
<p><code>#navigation li {<br />
border-bottom: 1px solid #ED9F9F;<br />
}</code></p>
<p>Finally, we style the link itself:</p>
<p><code>#navigation li a:link, #navigation li a:visited  {<br />
font-size: 90%;<br />
display: block;<br />
padding: 0.4em 0 0.4em 0.5em;<br />
border-left: 12px solid #711515;<br />
border-right: 1px solid #711515;<br />
background-color: #B51032;<br />
color: #FFFFFF;<br />
text-decoration: none;<br />
}</code></p>
<p>Most of the work is done here, creating CSS rules to add left and right borders, remove the underline, and so on. The first property declaration in this rule sets the <code>display</code> property to <code>block</code>. This causes the link to display as a block element, meaning that the whole area of each navigation &#8220;button&#8221; is active when you move the cursor over it &#8212; the same effect you&#8217;d see if you used an image for the navigation.</p>
<h5>Can I use CSS and lists to create a navigation system with subnavigation?</h5>
<p>Sometimes, more than one navigation level is necessary &#8212; but is it possible to create multi-leveled navigation using styled lists in CSS?</p>
<h5><em>Solution</em></h5>
<p>The perfect way to display subnavigation within a navigation system is to create a sublist within a list. The two levels of navigation will be easy to understand when they&#8217;re marked up in this way &#8212; even in browsers that don&#8217;t support CSS.</p>
<p>To produce multi-level navigation, we create a nested list and style the colors, borders, and link properties of the new list&#8217;s items:</p>
<p><code>&lt;!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"<br />
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"&gt;<br />
&lt;html xmlns="http://www.w3.org/1999/xhtml" lang="en-US"&gt;<br />
&lt;head&gt;<br />
&lt;title&gt;Lists as navigation&lt;/title&gt;<br />
&lt;meta http-equiv="content-type"<br />
content="text/html; charset=utf-8" /&gt;<br />
&lt;link rel="stylesheet" type="text/css" href="listnav_sub.css" /&gt;<br />
&lt;/head&gt;<br />
&lt;body&gt;<br />
&lt;div id="navigation"&gt;<br />
&lt;ul&gt;<br />
&lt;li&gt;&lt;a href="#"&gt;Recipes&lt;/a&gt;<br />
&lt;ul&gt;<br />
&lt;li&gt;&lt;a href="#"&gt;Starters&lt;/a&gt;&lt;/li&gt;<br />
&lt;li&gt;&lt;a href="#"&gt;Main Courses&lt;/a&gt;&lt;/li&gt;<br />
&lt;li&gt;&lt;a href="#"&gt;Desserts&lt;/a&gt;&lt;/li&gt;<br />
&lt;/ul&gt;<br />
&lt;/li&gt;<br />
&lt;li&gt;&lt;a href="#"&gt;Contact Us&lt;/a&gt;&lt;/li&gt;<br />
&lt;li&gt;&lt;a href="#"&gt;Articles&lt;/a&gt;&lt;/li&gt;<br />
&lt;li&gt;&lt;a href="#"&gt;Buy Online&lt;/a&gt;&lt;/li&gt;<br />
&lt;/ul&gt;<br />
&lt;/div&gt;<br />
&lt;/body&gt;<br />
&lt;/html&gt;</code></p>
<p><code>#navigation {<br />
width: 200px;<br />
}<br />
#navigation ul {<br />
list-style: none;<br />
margin: 0;<br />
padding: 0;<br />
}<br />
#navigation li {<br />
border-bottom: 1px solid #ED9F9F;<br />
}<br />
#navigation li a:link, #navigation li a:visited  {<br />
font-size: 90%;<br />
display: block;<br />
padding: 0.4em 0 0.4em 0.5em;<br />
border-left: 12px solid #711515;<br />
border-right: 1px solid #711515;<br />
background-color: #B51032;<br />
color: #FFFFFF;<br />
text-decoration: none;<br />
}<br />
#navigation li a:hover {<br />
background-color: #711515;<br />
color: #FFFFFF;<br />
}<br />
#navigation ul ul {<br />
margin-left: 12px;<br />
}<br />
#navigation ul ul li {<br />
border-bottom: 1px solid #711515;<br />
margin:0;<br />
}<br />
#navigation ul ul a:link, #navigation ul ul a:visited {<br />
background-color: #ED9F9F;<br />
color: #711515;<br />
}<br />
#navigation ul ul a:hover {<br />
background-color: #711515;<br />
color: #FFFFFF;<br />
}</code></p>
<p>The result of these additions is shown in Figure 4.</p>
<p><a href="http://i2.sitepoint.com/graphics/navigation_css-list-subnav.png" class="beatbox"><em>The CSS list navigation containing subnavigation (click to view image)</em><img src="http://i2.sitepoint.com/graphics/navigation_css-list-subnav.png" height="442" width="400" /></a></p>
<h5><em>Discussion</em></h5>
<p>Nested lists are a perfect way to describe the navigation system that we&#8217;re working with here. The first list contains the main sections of the site; the sublist under <strong>Recipes</strong> shows the subsections within the <strong>Recipes</strong> category. Even without any <a href="http://www.sitepoint.com/glossary.php?q=C#term_8" class="glossary" title="CSS, or Cascading Style Sheets, comprise styling and formatting rules that are applied to Web documents.">CSS</a> styling, the structure of the list is still clear and comprehensible, as you can see in Figure 5.</p>
<p><a href="http://i2.sitepoint.com/graphics/navigation_sense-without-css.png" class="beatbox"><em>The navigation remaining logical without the CSS (click to view image)</em><img src="http://i2.sitepoint.com/graphics/navigation_sense-without-css.png" height="446" width="400" /></a></p>
<p>The <a href="http://www.sitepoint.com/glossary.php?q=H#term_75" class="glossary" title="HTML stands for HyperText Markup Language.">HTML</a> that we use to mark up this list simply nests the sublist inside the <code>li</code> element of the appropriate main item:</p>
<p><code>&lt;ul&gt;<br />
&lt;li&gt;&lt;a href="#"&gt;Recipes&lt;/a&gt;<br />
&lt;ul&gt;<br />
&lt;li&gt;&lt;a href="#"&gt;Starters&lt;/a&gt;&lt;/li&gt;<br />
&lt;li&gt;&lt;a href="#"&gt;Main Courses&lt;/a&gt;&lt;/li&gt;<br />
&lt;li&gt;&lt;a href="#"&gt;Desserts&lt;/a&gt;&lt;/li&gt;<br />
&lt;/ul&gt;<br />
&lt;/li&gt;<br />
&lt;li&gt;&lt;a href="#"&gt;Contact Us&lt;/a&gt;&lt;/li&gt;<br />
&lt;li&gt;&lt;a href="#"&gt;Articles&lt;/a&gt;&lt;/li&gt;<br />
&lt;li&gt;&lt;a href="#"&gt;Buy Online&lt;/a&gt;&lt;/li&gt;<br />
&lt;/ul&gt;</code></p>
<p>With this HTML, and without any changes to the CSS, the menu will display as shown in Figure 6, &#8220;The sublist taking on the styles of the main navigation&#8221;, where the <code>li</code> elements inherit the styles of the main menu.</p>
<p><a href="http://i2.sitepoint.com/graphics/navigation_sublist-mainnav-styles.png" class="beatbox"><em>The sublist taking on the styles of the main navigation (click to view image)</em><img src="http://i2.sitepoint.com/graphics/navigation_sublist-mainnav-styles.png" height="438" width="400" /></a></p>
<p>Let&#8217;s add a style rule for the nested list to communicate visually that it&#8217;s a submenu, and not part of the main navigation:</p>
<p><code>#navigation ul ul {<br />
margin-left: 12px;<br />
}</code></p>
<p>This rule will indent the nested list so that it&#8217;s in line with the right edge of the border for the main menu, as demonstrated in Figure 7.</p>
<p><a href="http://i2.sitepoint.com/graphics/navigation_indent-subnav.png" class="beatbox"><em>The indented subnavigation (click to view image)</em><img src="http://i2.sitepoint.com/graphics/navigation_indent-subnav.png" height="440" width="400" /></a></p>
<p>Let&#8217;s add some simple styles to the <code>li</code> and <code>a</code> elements within the nested list to complete the effect:</p>
<p><code>#navigation ul ul li {<br />
border-bottom: 1px solid #711515;<br />
margin: 0;<br />
}<br />
#navigation ul ul a:link, #navigation ul ul a:visited {<br />
background-color: #ED9F9F;<br />
color: #711515;<br />
}<br />
#navigation ul ul a:hover {<br />
background-color: #711515;<br />
color: #FFFFFF;<br />
}</code></p>
<h5>How do I make a horizontal menu using CSS and lists?</h5>
<p>So far, we&#8217;ve dealt with vertical navigation &#8212; the kind of navigation that will most likely be found in a column to the left or right of a site&#8217;s main content area. However, site navigation is also commonly found as a horizontal menu close to the top of the document.</p>
<h5><em>Solution</em></h5>
<p>As Figure 8 shows, this type of menu can be created using styled lists in CSS. The <code>li</code> elements must be set to display inline so that each list item does not display on its own line.</p>
<p><a href="http://i2.sitepoint.com/graphics/navigation_css-horizontal-list.png" class="beatbox"><em>Using CSS to create horizontal list navigation (click to view image)</em><img src="http://i2.sitepoint.com/graphics/navigation_css-horizontal-list.png" height="169" width="400" /></a></p>
<p>Here&#8217;s the HTML and CSS that creates this display:</p>
<p><code>&lt;!DOCTYPE html PUBLIC "-//<a href="http://www.sitepoint.com/glossary.php?q=W#term_49" class="glossary" title="The World Wide Web Consortium (W3C) - A consortium of industry leaders for drafting Web standards.">W3C</a>//DTD <a href="http://www.sitepoint.com/glossary.php?q=X#term_63" class="glossary" title="XHTML is a reformulation of HTML 4 as an XML 1.0 application.">XHTML</a> 1.0 Strict//EN&#8221;<br />
&#8220;http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd&#8221;&gt;<br />
&lt;html xmlns=&#8221;http://www.w3.org/1999/xhtml&#8221; lang=&#8221;en-US&#8221;&gt;<br />
&lt;head&gt;<br />
&lt;title&gt;Lists as navigation&lt;/title&gt;<br />
&lt;meta http-equiv=&#8221;content-type&#8221;<br />
content=&#8221;text/html; charset=utf-8&#8243; /&gt;<br />
&lt;link rel=&#8221;stylesheet&#8221; type=&#8221;text/css&#8221; href=&#8221;listnav_horiz.css&#8221; /&gt;<br />
&lt;/head&gt;<br />
&lt;body&gt;<br />
&lt;div id=&#8221;navigation&#8221;&gt;<br />
&lt;ul&gt;<br />
&lt;li&gt;&lt;a href=&#8221;#&#8221;&gt;Recipes&lt;/a&gt;&lt;/li&gt;<br />
&lt;li&gt;&lt;a href=&#8221;#&#8221;&gt;Contact Us&lt;/a&gt;&lt;/li&gt;<br />
&lt;li&gt;&lt;a href=&#8221;#&#8221;&gt;Articles&lt;/a&gt;&lt;/li&gt;<br />
&lt;li&gt;&lt;a href=&#8221;#&#8221;&gt;Buy Online&lt;/a&gt;&lt;/li&gt;<br />
&lt;/ul&gt;<br />
&lt;/div&gt;<br />
&lt;/body&gt;<br />
&lt;/html&gt;</code></p>
<p><code>#navigation {<br />
font-size: 90%;<br />
}<br />
#navigation ul {<br />
list-style: none;<br />
margin: 0;<br />
padding: 0;<br />
padding-top: 1em;<br />
}<br />
#navigation li {<br />
display: inline;<br />
}<br />
#navigation a:link, #navigation a:visited {<br />
padding: 0.4em 1em 0.4em 1em;<br />
color: #FFFFFF;<br />
background-color: #B51032;<br />
text-decoration: none;<br />
border: 1px solid #711515;<br />
}<br />
#navigation a:hover {<br />
color: #FFFFFF;<br />
background-color: #711515;<br />
}</code></p>
<h5><em>Discussion</em></h5>
<p>To create the horizontal navigation, we start with a list that&#8217;s identical to the one we created for our vertical list menu:</p>
<p><code>&lt;div id="navigation"&gt;<br />
&lt;ul&gt;<br />
&lt;li&gt;&lt;a href="#"&gt;Recipes&lt;/a&gt;&lt;/li&gt;<br />
&lt;li&gt;&lt;a href="#"&gt;Contact Us&lt;/a&gt;&lt;/li&gt;<br />
&lt;li&gt;&lt;a href="#"&gt;Articles&lt;/a&gt;&lt;/li&gt;<br />
&lt;li&gt;&lt;a href="#"&gt;Buy Online&lt;/a&gt;&lt;/li&gt;<br />
&lt;/ul&gt;<br />
&lt;/div&gt;</code></p>
<p>We style the <code>#navigation</code> container to apply some basic font information, as we did with the vertical navigation. In a CSS layout, this ID would probably also contain some additional styles that determine the navigation&#8217;s position on the page:</p>
<p><code>#navigation {<br />
font-size: 90%;<br />
}</code></p>
<p>In styling the <code>ul</code> element, we remove the list bullets and default indentation applied to the list by the browser:</p>
<p><code>#navigation ul {<br />
list-style: none;<br />
margin: 0;<br />
padding: 0;<br />
padding-top: 1em;<br />
}</code></p>
<p>The property that transforms our list from a vertical to a horizontal display is applied to the <code>li</code> element:<br />
<code>#navigation li {<br />
display: inline;<br />
}</code></p>
<p>After we set the <code>display</code> property to <code>inline</code>, the list looks like Figure 9.</p>
<p><a href="http://i2.sitepoint.com/graphics/navigation_list-menu-horizontal.png" class="beatbox"><em>Displaying the list menu horizontally (click to view image)</em><img src="http://i2.sitepoint.com/graphics/navigation_list-menu-horizontal.png" height="174" width="400" /></a></p>
<p>All that&#8217;s left for us to do is to style the links for our navigation:</p>
<p><code>#navigation a:link, #navigation a:visited {<br />
padding: 0.4em 1em 0.4em 1em;<br />
color: #FFFFFF;<br />
background-color: #B51032;<br />
text-decoration: none;<br />
border: 1px solid #711515;<br />
}<br />
#navigation a:hover {<br />
color: #FFFFFF;<br />
background-color: #711515;<br />
}</code></p>
<p>If you&#8217;re creating boxes around each link, as I have here, remember that, in order to make more space between the text and the edge of its container, you&#8217;ll need to add more left and right padding to the links. To create more space between the navigation items, add left and right margins to the links.</p>
<h5>How do I create button-like navigation using CSS?</h5>
<p>Navigation that appears to be composed of clickable buttons is a feature of many web sites. This kind of navigation is often created using images to which effects are applied to make the edges look beveled and button-like. Often, some <a href="http://www.sitepoint.com/glossary.php?q=J#term_9" class="glossary" title="JavaScript is a Web scripting language most commonly used for client-side applications.">JavaScript</a> code is used to swap in another image, so the button appears to depress when the user holds the cursor over it or clicks on the image.<br />
Is it possible to create such button-like navigation systems using only CSS? Absolutely!</p>
<h5><em>Solution</em></h5>
<p>Creating a button effect like that shown in Figure 10 is possible, and fairly straightforward, using CSS. The effect&#8217;s success hinges on your use of the CSS border properties.</p>
<p><a href="http://i2.sitepoint.com/graphics/navigation_button-style-css.png" class="beatbox"><em>Building button-like navigation with CSS (click to view image)</em><img src="http://i2.sitepoint.com/graphics/navigation_button-style-css.png" height="178" width="400" /></a></p>
<p>Here&#8217;s the code you&#8217;ll need:</p>
<p><code>&lt;!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"<br />
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"&gt;<br />
&lt;html xmlns="http://www.w3.org/1999/xhtml" lang="en-US"&gt;<br />
&lt;head&gt;<br />
&lt;title&gt;Lists as navigation&lt;/title&gt;<br />
&lt;meta http-equiv="content-type"<br />
content="text/html; charset=utf-8" /&gt;<br />
&lt;link rel="stylesheet" type="text/css" href="listnav_button.css"<br />
/&gt;<br />
&lt;/head&gt;<br />
&lt;body&gt;<br />
&lt;div id="navigation"&gt;<br />
&lt;ul&gt;<br />
&lt;li&gt;&lt;a href="#"&gt;Recipes&lt;/a&gt;&lt;/li&gt;<br />
&lt;li&gt;&lt;a href="#"&gt;Contact Us&lt;/a&gt;&lt;/li&gt;<br />
&lt;li&gt;&lt;a href="#"&gt;Articles&lt;/a&gt;&lt;/li&gt;<br />
&lt;li&gt;&lt;a href="#"&gt;Buy Online&lt;/a&gt;&lt;/li&gt;<br />
&lt;/ul&gt;<br />
&lt;/div&gt;<br />
&lt;/body&gt;<br />
&lt;/html&gt;</code></p>
<p><code>#navigation {<br />
font-size:90%<br />
}<br />
#navigation ul {<br />
list-style: none;<br />
margin: 0;<br />
padding: 0;<br />
padding-top: 1em;<br />
}<br />
#navigation li {<br />
display: inline;<br />
}<br />
#navigation a:link, #navigation a:visited {<br />
margin-right: 0.2em;<br />
padding: 0.2em 0.6em 0.2em 0.6em;<br />
color: #A62020;<br />
background-color: #FCE6EA;<br />
text-decoration: none;<br />
border-top: 1px solid #FFFFFF;<br />
border-left: 1px solid #FFFFFF;<br />
border-bottom: 1px solid #717171;<br />
border-right: 1px solid #717171;<br />
}<br />
#navigation a:hover {<br />
border-top: 1px solid #717171;<br />
border-left: 1px solid #717171;<br />
border-bottom: 1px solid #FFFFFF;<br />
border-right: 1px solid #FFFFFF;<br />
}</code></p>
<h5><em>Discussion</em></h5>
<p>To create this effect, we&#8217;ll use the horizontal list navigation described in the section called &#8220;How do I make a horizontal menu using CSS and lists?&#8221; However, to create the button look, we&#8217;ll use different colored borders at the top and left than we use for the bottom and right sides of each button. By giving the top and left edges of the button a lighter colored border than we assign to the button&#8217;s bottom and right edges, we create a slightly beveled effect:</p>
<p><code>#navigation a:link, #navigation a:visited {<br />
margin-right: 0.2em;<br />
padding: 0.2em 0.6em 0.2em 0.6em;<br />
color: #A62020;<br />
background-color: #FCE6EA;<br />
text-decoration: none;<br />
border-top: 1px solid #FFFFFF;<br />
border-left: 1px solid #FFFFFF;<br />
border-bottom: 1px solid #717171;<br />
border-right: 1px solid #717171;<br />
}</code></p>
<p>We reverse the border colors for the hover state, which creates the effect of the button being pressed:</p>
<p><code>#navigation a:hover {<br />
border-top: 1px solid #717171;<br />
border-left: 1px solid #717171;<br />
border-bottom: 1px solid #FFFFFF;<br />
border-right: 1px solid #FFFFFF;<br />
}</code></p>
<p>Try using heavier borders, and changing the background images on the links, to create effects that suit your design.</p>
<h5>How do I create tabbed navigation with <a href="http://www.sitepoint.com/glossary.php?q=C#term_8" class="glossary" title="CSS, or Cascading Style Sheets, comprise styling and formatting rules that are applied to Web documents.">CSS</a>?</h5>
<p>Navigation that appears as tabs across the top of the page is a popular navigation choice. Many sites create tabs using images. However, this approach suffers from the problems associated with text contained in images, which we discussed in the section called &#8220;How do I replace image-based navigation with CSS?&#8221; However, it is possible to create a tab effect by combining background images and text styled with CSS.</p>
<h5><em>Solution</em></h5>
<p>The tabbed navigation shown in Figure 11 can be created by styling a horizontal list.</p>
<p><a href="http://i2.sitepoint.com/graphics/navigation_tabbed-style-css.png" class="beatbox"><em>Using CSS to create tabbed navigation (click to view image)</em><img src="http://i2.sitepoint.com/graphics/navigation_tabbed-style-css.png" height="269" width="400" /></a></p>
<p>Here&#8217;s the <a href="http://www.sitepoint.com/glossary.php?q=H#term_75" class="glossary" title="HTML stands for HyperText Markup Language.">HTML</a> and CSS that creates this effect:</p>
<p><code>&lt;!DOCTYPE html PUBLIC "-//<a href="http://www.sitepoint.com/glossary.php?q=W#term_49" class="glossary" title="The World Wide Web Consortium (W3C) - A consortium of industry leaders for drafting Web standards.">W3C</a>//DTD <a href="http://www.sitepoint.com/glossary.php?q=X#term_63" class="glossary" title="XHTML is a reformulation of HTML 4 as an XML 1.0 application.">XHTML</a> 1.0 Strict//EN&#8221;<br />
&#8220;http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd&#8221;&gt;<br />
&lt;html xmlns=&#8221;http://www.w3.org/1999/xhtml&#8221; lang=&#8221;en-US&#8221;&gt;<br />
&lt;head&gt;<br />
&lt;title&gt;Lists as navigation&lt;/title&gt;<br />
&lt;meta http-equiv=&#8221;content-type&#8221;<br />
content=&#8221;text/html; charset=utf-8&#8243; /&gt;<br />
&lt;link rel=&#8221;stylesheet&#8221; type=&#8221;text/css&#8221; href=&#8221;tabs.css&#8221; /&gt;<br />
&lt;/head&gt;<br />
&lt;body id=&#8221;recipes&#8221;&gt;<br />
&lt;div id=&#8221;header&#8221;&gt;<br />
&lt;ul id=&#8221;tabnav&#8221;&gt;<br />
&lt;li class=&#8221;recipes&#8221;&gt;&lt;a href=&#8221;#&#8221;&gt;Recipes&lt;/a&gt;&lt;/li&gt;<br />
&lt;li class=&#8221;contact&#8221;&gt;&lt;a href=&#8221;#&#8221;&gt;Contact Us&lt;/a&gt;&lt;/li&gt;<br />
&lt;li class=&#8221;articles&#8221;&gt;&lt;a href=&#8221;#&#8221;&gt;Articles&lt;/a&gt;&lt;/li&gt;<br />
&lt;li class=&#8221;buy&#8221;&gt;&lt;a href=&#8221;#&#8221;&gt;Buy Online&lt;/a&gt;&lt;/li&gt;<br />
&lt;/ul&gt;<br />
&lt;/div&gt;<br />
&lt;div id=&#8221;content&#8221;&gt;<br />
&lt;h1&gt;Recipes&lt;/h1&gt;<br />
&lt;p&gt;Lorem ipsum dolor sit amet, &#8230; &lt;/p&gt;<br />
&lt;/div&gt;<br />
&lt;/body&gt;<br />
&lt;/html&gt;</code></p>
<p><code>body {<br />
font: .8em/1.8em verdana, arial, sans-serif;<br />
background-color: #FFFFFF;<br />
color: #000000;<br />
margin: 0 10% 0 10%;<br />
}</code></p>
<p><code>#header {<br />
float: left;<br />
width: 100%;<br />
border-bottom: 1px solid #8DA5FF;<br />
margin-bottom: 2em;<br />
}</code></p>
<p><code>#header ul {<br />
margin: 0;<br />
padding: 2em 0 0 0;<br />
list-style: none;<br />
}</code></p>
<p><code>#header li {<br />
float: left;<br />
background-image: url("images/tab_left.<a href="http://www.sitepoint.com/glossary.php?q=G#term_24" class="glossary" title="GIF stands for Graphics Interchange Format, and is an image file format commonly used for palette-based images.">gif</a>&#8220;);<br />
background-repeat: no-repeat;<br />
margin: 0 1px 0 0;<br />
padding: 0 0 0 8px;<br />
}</code></p>
<p><code>#header a {<br />
float: left;<br />
display: block;<br />
background-image: url("images/tab_right.gif");<br />
background-repeat: no-repeat;<br />
background-position: right top;<br />
padding: 0.2em 10px 0.2em 0;<br />
text-decoration: none;<br />
font-weight: bold;<br />
color: #333366;<br />
}</code></p>
<p><code>#recipes #header li.recipes,<br />
#contact #header li.contact,<br />
#articles #header li.articles,<br />
#buy #header li.buy {<br />
background-image: url("images/tab_active_left.gif");<br />
}</code></p>
<p><code>#recipes #header li.recipes a,<br />
#contact #header li.contact a,<br />
#articles #header li.articles a,<br />
#buy #header li.buy a {<br />
background-image: url("images/tab_active_right.gif");<br />
background-color: transparent;<br />
color:#FFFFFF;<br />
}</code></p>
<h5><em>Discussion</em></h5>
<p>The tabbed navigation approach I&#8217;ve used here is a basic version of <a href="http://www.alistapart.com/articles/slidingdoors/" class="sublink">Douglas Bowman&#8217;s Sliding Doors of CSS method</a>, which is a tried and tested technique for creating a tabbed interface. The structure that I&#8217;ve given to the navigation menu is the same kind of simple unordered list that we&#8217;ve worked with so far, except that each list item is assigned a <code>class</code> attribute that describes the link it contains. We&#8217;ve also wrapped the entire list in a <code>div</code> with an <code>id</code> of <code>header</code>. The technique takes its name from the two images used to implement it &#8212; one overlaps the other, and the images slide apart as the text size increases.</p>
<p>You&#8217;ll need four images to create this effect: two to create the regular tab color, and two to use when the tab is the currently selected (highlighted) tab. The images I&#8217;ve used in this example are shown in Figure 12. As you can see, they&#8217;re far wider and taller than would generally be necessary for a tab?this provides plenty of space for the tab to &#8220;grow&#8221; if the user&#8217;s browser is configured to display text at a very large size.</p>
<p><a href="http://i2.sitepoint.com/graphics/navigation_files-for-tabs.png" class="beatbox"><em>The image files used to create the tabs (click to view image)</em><img src="http://i2.sitepoint.com/graphics/navigation_files-for-tabs.png" height="211" width="400" /></a></p>
<p>Here&#8217;s the basic list of navigation items:</p>
<p><code>&lt;div id="header"&gt;<br />
&lt;ul id="tabnav"&gt;<br />
&lt;li class="recipes"&gt;&lt;a href="#"&gt;Recipes&lt;/a&gt;&lt;/li&gt;<br />
&lt;li class="contact"&gt;&lt;a href="#"&gt;Contact Us&lt;/a&gt;&lt;/li&gt;<br />
&lt;li class="articles"&gt;&lt;a href="#"&gt;Articles&lt;/a&gt;&lt;/li&gt;<br />
&lt;li class="buy"&gt;&lt;a href="#"&gt;Buy Online&lt;/a&gt;&lt;/li&gt;<br />
&lt;/ul&gt;<br />
&lt;/div&gt;</code></p>
<p>The first step is to style the container that surrounds the navigation. We&#8217;re going to give our header a simple bottom border for the purposes of this exercise, but on a real-world site this container may hold other elements in addition to our tabs (such as a logo or search field):</p>
<p><code>#header {<br />
float: left;<br />
width: 100%;<br />
border-bottom: 1px solid #8DA5FF;<br />
margin-bottom: 2em;<br />
}</code></p>
<p>As you&#8217;ll have noticed, we float the header to the left. We&#8217;ll also float the individual list items; floating the container that houses them ensures that they remain contained once they&#8217;re floated, and that the border will display below them.</p>
<p>Next, we create a style rule for the <code>ul</code> element inside the header:</p>
<p><code>#header ul {<br />
margin: 0;<br />
padding: 2em 0 0 0;<br />
list-style: none;<br />
}</code></p>
<p>This rule removes the bullets and alters the margin and padding on our list &#8212; we&#8217;ve added two ems of padding to the top of the <code>ul</code> element. Figure 13 shows the results of our work so far.</p>
<p><a href="http://i2.sitepoint.com/graphics/navigation_styled_ul.png" class="beatbox"><em>Displaying the navigation after styling the /#c#/ul/#ec#/ element (click to view image)</em><img src="http://i2.sitepoint.com/graphics/navigation_styled_ul.png" height="271" width="400" /></a></p>
<p>Now we need to style the list items:</p>
<p><code>#header li {<br />
float: left;<br />
background-image: url("images/tab_left.gif");<br />
background-repeat: no-repeat;<br />
margin: 0 1px 0 0;<br />
padding: 0 0 0 8px;<br />
}</code></p>
<p>This rule uses the <code>float</code> property to position the list items horizontally while maintaining the block-level status of each. We then add the first of our &#8220;sliding door&#8221; images &#8212; the thin left-hand side of the tab &#8212; as a background image. A single-pixel right margin on the list item creates a gap between one tab and the next. Figure 14 shows that the left-hand tab image now appears for each tab.</p>
<p><a href="http://i2.sitepoint.com/graphics/navigation_tabs-reflect-new-style.png" class="beatbox"><em>The navigation tabs reflecting the new styles (click to view image)</em><img src="http://i2.sitepoint.com/graphics/navigation_tabs-reflect-new-style.png" height="271" width="400" /></a></p>
<p>Next, we style the links, completing the look of our tabs in their unselected state. The image that forms the right-hand side of the tab is applied to each link, completing the tab effect:</p>
<p><code>#header a {<br />
float: left;<br />
display: block;<br />
background-image: url("images/tab_right.gif");<br />
background-repeat: no-repeat;<br />
background-position: right top;<br />
padding: 0.2em 10px 0.2em 0;<br />
text-decoration: none;<br />
font-weight: bold;<br />
color: #333366;<br />
}</code></p>
<p>The results are shown in Figure 15.</p>
<p><a href="http://i2.sitepoint.com/graphics/navigation_tabs-style-links.png" class="beatbox"><em>Styling the navigation links (click to view image)</em><img src="http://i2.sitepoint.com/graphics/navigation_tabs-style-links.png" height="270" width="400" /></a></p>
<p>If you increase the text size in the browser, you can see that the tabs neatly increase in size too. In fact, they do so without overlapping and without the text protruding out of the tab &#8212; this is because we have used images that allow plenty of room for growth.</p>
<p>To complete the tab navigation, we need to highlight the tab that corresponds to the currently displayed page. You&#8217;ll recall that each list item has been assigned a unique class name. If we assign to the <code>body</code> element an ID that has a value equal to the value of each list item class, CSS can do the rest of the work:</p>
<p><code>&lt;body id="recipes"&gt;</code></p>
<p>Although it looks like a lot of code, the CSS code that styles the tab matching the <code>body</code> ID is relatively straightforward. The images I&#8217;ve used are exact copies of the left and right images that we applied to the tabs, but they&#8217;re a different color, which produces the effect of one tab appearing to be highlighted.</p>
<p>Here&#8217;s the CSS:</p>
<p><code>#recipes #header li.recipes,<br />
#contact #header li.contact,<br />
#articles #header li.articles,<br />
#buy #header li.buy {<br />
background-image: url("images/tab_active_left.gif");<br />
}</code></p>
<p><code>#recipes #header li.recipes a,<br />
#contact #header li.contact a,<br />
#articles #header li.articles a,<br />
#buy #header li.buy a {<br />
background-image: url("images/tab_active_right.gif");<br />
background-color: transparent;<br />
color: #FFFFFF;<br />
}</code></p>
<p>With these rules in place, specifying an ID of <code>recipes</code> to our body will cause the <strong>Recipes</strong> tab to be highlighted, specifying contact will cause the <strong>Contact Us</strong> tab to be highlighted, and so on. The results of this work are shown in Figure 16.</p>
<p><em><strong>Identifying a Useful Technique</strong><br />
The technique of adding an ID to the body element can be very useful. For example, you may have different color schemes for different sections of your site, to help the user identify which section they&#8217;re using. You can simply add the section name to the body element and make use of it within the style sheet, as we did in this example.</em></p>
<p><a href="http://i2.sitepoint.com/graphics/navigation_highlight-contact-us.png" class="beatbox"><em>Highlighting the Contact Us tab (click to view image)</em><img src="http://i2.sitepoint.com/graphics/navigation_highlight-contact-us.png" height="267" width="400" /></a></p>
<p><script src="http://www.sitepoint.com/adjs.php?region=79&amp;did=adz&amp;adtype=vertical" type="text/javascript"></script>       <span></span></p>
<h5>How do I create rollovers in <a href="http://www.sitepoint.com/glossary.php?q=C#term_8" class="glossary" title="CSS, or Cascading Style Sheets, comprise styling and formatting rules that are applied to Web documents.">CSS</a> without using <a href="http://www.sitepoint.com/glossary.php?q=J#term_9" class="glossary" title="JavaScript is a Web scripting language most commonly used for client-side applications.">JavaScript</a>?</h5>
<p>CSS-based navigation can provide some really interesting effects, but there are still some effects that require the use of images. Is it possible to enjoy the advantages of text-based navigation and still use images?</p>
<h5><em>Solution</em></h5>
<p>It is possible to combine images and CSS to create JavaScript-free rollovers. This solution is based on a technique described at <a href="http://wellstyled.com/css-nopreload-rollovers.html" class="sublink">WellStyled.com</a>. Here&#8217;s the code you&#8217;ll need:</p>
<p><code>&lt;!DOCTYPE html PUBLIC "-//<a href="http://www.sitepoint.com/glossary.php?q=W#term_49" class="glossary" title="The World Wide Web Consortium (W3C) - A consortium of industry leaders for drafting Web standards.">W3C</a>//DTD <a href="http://www.sitepoint.com/glossary.php?q=X#term_63" class="glossary" title="XHTML is a reformulation of HTML 4 as an XML 1.0 application.">XHTML</a> 1.0 Strict//EN&#8221;<br />
&#8220;http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd&#8221;&gt;<br />
&lt;html xmlns=&#8221;http://www.w3.org/1999/xhtml&#8221; lang=&#8221;en-US&#8221;&gt;<br />
&lt;head&gt;<br />
&lt;title&gt;Lists as navigation&lt;/title&gt;<br />
&lt;meta http-equiv=&#8221;content-type&#8221;<br />
content=&#8221;text/html; charset=utf-8&#8243; /&gt;<br />
&lt;link rel=&#8221;stylesheet&#8221; type=&#8221;text/css&#8221; href=&#8221;images.css&#8221; /&gt;<br />
&lt;/head&gt;<br />
&lt;body&gt;<br />
&lt;ul id=&#8221;nav&#8221;&gt;<br />
&lt;li&gt;&lt;a href=&#8221;#&#8221;&gt;Recipes&lt;/a&gt;&lt;/li&gt;<br />
&lt;li&gt;&lt;a href=&#8221;#&#8221;&gt;Contact Us&lt;/a&gt;&lt;/li&gt;<br />
&lt;li&gt;&lt;a href=&#8221;#&#8221;&gt;Articles&lt;/a&gt;&lt;/li&gt;<br />
&lt;li&gt;&lt;a href=&#8221;#&#8221;&gt;Buy Online&lt;/a&gt;&lt;/li&gt;<br />
&lt;/ul&gt;<br />
&lt;/body&gt;<br />
&lt;/html&gt;</code></p>
<p><code>ul#nav {<br />
list-style-type: none;<br />
padding: 0;<br />
margin: 0;<br />
}<br />
#nav a:link, #nav a:visited {<br />
display: block;<br />
width: 150px;<br />
padding: 10px 0 16px 32px;<br />
font: bold 80% Arial, Helvetica, sans-serif;<br />
color: #FF9900;<br />
background: url("peppers.<a href="http://www.sitepoint.com/glossary.php?q=G#term_24" class="glossary" title="GIF stands for Graphics Interchange Format, and is an image file format commonly used for palette-based images.">gif</a>&#8220;) top left no-repeat;<br />
text-decoration: none;<br />
}<br />
#nav a:hover {<br />
background-position: 0 -69px;<br />
color: #B51032;<br />
}<br />
#nav a:active {<br />
background-position: 0 -138px;<br />
color: #006E01;<br />
}</code></p>
<p>The results can be seen in Figure 17, but to enjoy the full effect I suggest you try it for yourself. Don&#8217;t forget to click on a link or two!</p>
<p><a href="http://i2.sitepoint.com/graphics/navigation_completed-uses-images.png" class="beatbox"><em>Using images to advantage in the completed menu (click to view image)</em><img src="http://i2.sitepoint.com/graphics/navigation_completed-uses-images.png" height="293" width="400" /></a></p>
<h5><em>Discussion</em></h5>
<p>This solution offers a means of using images in your navigation without having to resort to preloading lots of separate files.</p>
<p>The navigation has three states, but these states aren&#8217;t depicted using three separate images. Instead, we use one large image that contains images for all three states, as shown in Figure 18.</p>
<p><a href="http://i2.sitepoint.com/graphics/pepper-three-states.gif" class="beatbox"><em>The pepper image containing images for all three rollover states (click to view image)</em><img src="http://i2.sitepoint.com/graphics/pepper-three-states.gif" height="167" width="19" /></a></p>
<p>The navigation is marked up as a simple list:</p>
<p><code>&lt;ul id="nav"&gt;<br />
&lt;li&gt;&lt;a href="#"&gt;Recipes&lt;/a&gt;&lt;/li&gt;<br />
&lt;li&gt;&lt;a href="#"&gt;Contact Us&lt;/a&gt;&lt;/li&gt;<br />
&lt;li&gt;&lt;a href="#"&gt;Articles&lt;/a&gt;&lt;/li&gt;<br />
&lt;li&gt;&lt;a href="#"&gt;Buy Online&lt;/a&gt;&lt;/li&gt;<br />
&lt;/ul&gt;</code></p>
<p>We control the display of the background image within the declaration block for the navigation links. However, because the image is far bigger than the area required for this element, we only see the yellow pepper at first:</p>
<p><code>#nav a:link, #nav a:visited {<br />
display: block;<br />
width: 150px;<br />
padding: 10px 0 16px 32px;<br />
font: bold 80% Arial, Helvetica, sans-serif;<br />
color: #FF9900;<br />
background: url("peppers.gif") top left no-repeat;<br />
text-decoration: none;<br />
}</code></p>
<p>When the <code>:hover</code> state is activated, the background image moves up the exact number of pixels required to reveal the red pepper. In this example, I had to move it by 69 pixels, but this figure will vary depending on the image that you use. You could probably work it out mathematically, or you could do as I do and simply increment the background position a few pixels at a time, until it appears in the right location on hover:</p>
<p><code>#nav a:hover {<br />
background-position: 0 -69px;<br />
color: #B51032;<br />
}</code></p>
<p>When the <code>:active</code> state is activated, the background image shifts again, this time to display the green pepper when the link is clicked:</p>
<p><code>#nav a:active {<br />
background-position: 0 -138px;<br />
color: #006E01;<br />
}</code></p>
<p>That&#8217;s all there is to it! The effect can fall apart if the user resizes the text in the browser to a larger font, which allows the edges of the hidden images to display. You can anticipate this eventuality to some degree by leaving quite a large space between each of the three images &#8212; keep this in mind when preparing your images.</p>
<p><em><strong>Image Flickering in Internet Explorer</strong><br />
This technique sometimes causes the navigation to &#8220;flicker&#8221; in Internet Explorer. In my tests, this only tends to be a problem when the image is larger than the ones we&#8217;ve used here; however, if your navigation items flicker, a well-documented remedy is available.</em></p>
<h5>How can I create pure CSS drop-down menus?</h5>
<p>In the previous section, we learned to create image- and JavaScript-free rollovers. Can the same be achieved for drop-down menus?</p>
<h5><em>Solution</em></h5>
<p>The answer is yes &#8230; but the resulting menus don&#8217;t work in Internet Explorer 6! Nevertheless, Figure 19 illustrates this interesting technique, which will become more useful as Internet Explorer 7 gains market share.</p>
<p><a href="http://i2.sitepoint.com/graphics/navigation_css-only-drop-down.png" class="beatbox"><em>Creating a CSS-only drop-down menu (click to view image)</em><img src="http://i2.sitepoint.com/graphics/navigation_css-only-drop-down.png" height="202" width="400" /></a></p>
<p>Here&#8217;s the markup used for this example:</p>
<p><code>&lt;!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"<br />
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"&gt;<br />
&lt;html xmlns="http://www.w3.org/1999/xhtml" lang="en-US"&gt;<br />
&lt;head&gt;<br />
&lt;title&gt;CSS Flyout menus&lt;/title&gt;<br />
&lt;meta http-equiv="content-type"<br />
content="text/html; charset=utf-8" /&gt;<br />
&lt;link rel="stylesheet" type="text/css" href="menus.css" /&gt;<br />
&lt;/head&gt;<br />
&lt;body&gt;<br />
&lt;ul id="nav"&gt;<br />
&lt;li&gt;&lt;a href="#"&gt;Starters&lt;/a&gt;<br />
&lt;ul&gt;<br />
&lt;li&gt;&lt;a href=""&gt;Fish&lt;/a&gt;&lt;/li&gt;<br />
&lt;li&gt;&lt;a href=""&gt;Fruit&lt;/a&gt;&lt;/li&gt;<br />
&lt;li&gt;&lt;a href=""&gt;Soups&lt;/a&gt;&lt;/li&gt;<br />
&lt;/ul&gt;<br />
&lt;/li&gt;<br />
&lt;li&gt;&lt;a href="#"&gt;Main courses&lt;/a&gt;<br />
&lt;ul&gt;<br />
&lt;li&gt;&lt;a href=""&gt;Meat&lt;/a&gt;&lt;/li&gt;<br />
&lt;li&gt;&lt;a href=""&gt;Fish&lt;/a&gt;&lt;/li&gt;<br />
&lt;li&gt;&lt;a href=""&gt;Vegetarian&lt;/a&gt;&lt;/li&gt;<br />
&lt;/ul&gt;<br />
&lt;/li&gt;<br />
&lt;li&gt;&lt;a href="#"&gt;Desserts&lt;/a&gt;<br />
&lt;ul&gt;<br />
&lt;li&gt;&lt;a href=""&gt;Fruit&lt;/a&gt;&lt;/li&gt;<br />
&lt;li&gt;&lt;a href=""&gt;Puddings&lt;/a&gt;&lt;/li&gt;<br />
&lt;li&gt;&lt;a href=""&gt;Ice Creams&lt;/a&gt;&lt;/li&gt;<br />
&lt;/ul&gt;<br />
&lt;/li&gt;<br />
&lt;/ul&gt;<br />
&lt;/body&gt;<br />
&lt;/html&gt;</code></p>
<p>And here are the style rules to implement this effect:</p>
<p><code>body {<br />
font: 1em Verdana, Arial, sans-serif;<br />
background-color: #FFFFFF;<br />
color: #000000;<br />
margin: 1em 0 0 1em;<br />
}<br />
#nav, #nav ul {<br />
padding: 0;<br />
margin: 0;<br />
list-style: none;<br />
}<br />
#nav li {<br />
float: left;<br />
position: relative;<br />
width: 10em;<br />
border: 1px solid #B0C4DE;<br />
background-color: #E7EDF5;<br />
color: #2D486C;<br />
font-size: 80%;<br />
margin-right: 1em;<br />
}<br />
#nav a:link, #nav a:visited {<br />
display: block;<br />
text-decoration: none;<br />
padding-left: 1em;<br />
color: #2D486C;<br />
}<br />
* html #nav a {<br />
width: 100%;<br />
}<br />
#nav ul {<br />
display: none;<br />
position: absolute;<br />
padding: 0;<br />
}<br />
#nav ul li {<br />
border: 0 none transparent;<br />
border-bottom: 1px solid #E7EDF5;<br />
border-top: .5em solid #FFF;<br />
background-color: #F1F5F9;<br />
font-size: 100%;<br />
margin-bottom: -1px;<br />
margin-top: 1px;<br />
padding: 0;<br />
}<br />
#nav li:hover ul {<br />
display: block;<br />
}</code></p>
<h5><em>Discussion</em></h5>
<p>Though this attractive and easy effect will not work in Internet Explorer 6, it is supported by several other, newer browsers. This solution allows you to create a drop-down menu without using any JavaScript at all. The technique is based on the <a href="http://www.alistapart.com/articles/dropdowns/" class="sublink">Suckerfish Dropdowns solution</a> detailed on A List Apart.</p>
<p>The menus themselves are based on simple unordered lists. The top-level menu items consist of one main list; the items that fall under each main item are contained in nested lists:</p>
<p><code>&lt;ul id="nav"&gt;<br />
&lt;li&gt;&lt;a href="#"&gt;Starters&lt;/a&gt;<br />
&lt;ul&gt;<br />
&lt;li&gt;&lt;a href=""&gt;Fish&lt;/a&gt;&lt;/li&gt;<br />
&lt;li&gt;&lt;a href=""&gt;Fruit&lt;/a&gt;&lt;/li&gt;<br />
&lt;li&gt;&lt;a href=""&gt;Soups&lt;/a&gt;&lt;/li&gt;<br />
&lt;/ul&gt;<br />
&lt;/li&gt;<br />
&amp;#8942;</code></p>
<p>As you can see in Figure 20, when styles aren&#8217;t applied to the menu, the page displays as a logically structured, unordered list with subsections that are easy to spot.</p>
<p><a href="http://i2.sitepoint.com/graphics/lists-logical-no-css.png" class="beatbox"><em>Displaying lists logically in browsers that don&#8217;t support CSS (click to view image)</em><img src="http://i2.sitepoint.com/graphics/lists-logical-no-css.png" height="278" width="400" /></a></p>
<p>To begin with, we style the top-level menu, removing its list style. We also float the list items to the left so that they stack horizontally. The list items are given a <code>position</code> value of <code>relative</code> so that we can position our fly-out menus within them later on:</p>
<p><code>#nav, #nav ul {<br />
&amp;#8942;<br />
list-style: none;<br />
}<br />
#nav li {<br />
float: left;<br />
position: relative;<br />
width: 10em;<br />
&amp;#8942;<br />
margin-right: 1em;<br />
}</code></p>
<p>We coerce the links in the menu to display as blocks, so they fill the rectangular areas defined by the menu items. Internet Explorer 6 (and earlier) doesn&#8217;t recognize this; however, setting the width of each link to 100% ensures that our clickable region expands to fill the containing block.</p>
<p><code>#nav a:link, #nav a:visited {<br />
display: block;<br />
&amp;#8942;<br />
}<br />
* html #nav a {<br />
width: 100%;<br />
}</code></p>
<p>Next, we style the nested lists that constitute our fly-out menus so that, by default, they are not displayed (<code>display: none</code>). We do, however, specify that absolute positioning is to be used when they <em>are</em> displayed, so that they don&#8217;t affect the flow of the rest of the document:</p>
<p><code>#nav ul {<br />
display: none;<br />
position: absolute;<br />
&amp;#8942;<br />
}</code></p>
<p>To prevent our fly-out menu list items from being floated horizontally the way the main menu items are, we need to set their <code>float</code> property to <code>none</code>:</p>
<p><code>#nav ul li {<br />
float: none;<br />
&amp;#8942;<br />
}</code></p>
<p>Finally, we use the <code>:hover</code> pseudo-class to display the fly-out menu within any main menu item when the cursor is moved over it:</p>
<p><code>#nav li:hover ul {<br />
display: block;<br />
}</code></p>
<p>With these basic CSS rules in place, the menus display as shown in Figure 21.</p>
<p><a href="http://i2.sitepoint.com/graphics/navigation_menu-alters-basic-css.png" class="beatbox"><em>Altering the menu display with the addition of basic CSS (click to view image)</em><img src="http://i2.sitepoint.com/graphics/navigation_menu-alters-basic-css.png" height="214" width="400" /></a></p>
<p>This code initially sets the nested lists to <code>display: none</code>. When the user hovers the cursor over a main menu list item, the property of the nested list within that list item is set to <code>display: block</code>, and the menu appears. However, this approach doesn&#8217;t work in Internet Explorer, as in that browser the <code>:hover</code> pseudo-class works only on links &#8212; not on any other element.</p>
<p>The rest of the CSS simply applies visual styles to make the menus look good.</p>
<p><em><strong>Falling Between the Cracks</strong><br />
When a fly-out menu opens, the user must move the cursor down to the fly-out menu items to select one. If, in this motion, the cursor moves outside of the list item that opened the fly-out menu, the menu will close immediately, as the <code>:hover</code> pseudo-class will no longer be in effect.</em></p>
<p><em>Looking at the style rules for this page, you can see that we use absolute positioning to display the nested list over the top of the rest of the page content without disturbing it.</em></p>
<p><em>In theory, we should be able to leave a little space between the top-level menu item and the fly-out menu simply by adding margin to the top of the list; however, in Internet Explorer 7 the fly-out menu will disappear if the cursor passes over a margin area, rendering the menu unusable. Instead, I&#8217;ve created the effect by applying a white border to the top of the menu.</em></p>
<p><em>I&#8217;ve also added a very small margin to the top of each list item, and a negative margin of the same amount to the bottom. This has the effect of shifting our menu down by one pixel &#8212; just enough to ensure that our white border doesn&#8217;t cover up the bottom of our top-level menu item.</em></p>
<p><code>#nav ul li {<br />
border: 0 none transparent;<br />
border-bottom: 1px solid #E7EDF5;<br />
border-top: .5em solid #FFF;<br />
background-color: #F1F5F9;<br />
font-size: 100%;<br />
margin-bottom: -1px;<br />
margin-top: 1px;<br />
padding: 0;<br />
}</code></p>
<p><em><strong><a href="http://www.sitepoint.com/glossary.php?q=A#term_61" class="glossary" title="Accessibility deals with the issues of making online content available for experience, enjoyment, and use by all visitors, including those who do not fit the standard "Web user" mould.">Accessibility</a> Concerns</strong><br />
When you&#8217;re using any drop-down menu &#8212; with or without JavaScript &#8212; make sure that users who don&#8217;t see the full effect of the menus are still able to move around your site.</em></p>
<p><em>In the case of this example, users who don&#8217;t have CSS support will see the expanded nested lists, and will be able to navigate through the site. Anyone who uses a browser that doesn&#8217;t support the display of the submenus, such as Internet Explorer 6, will still be able to navigate so long as the pages to which the top-level menu items link contain links to all the pages in that section&#8217;s submenu.</em></p>
<p><em>Any menu system that prevents users whose browsers don&#8217;t support it from navigating the site is bad news.</em></p>
<h5>Summary</h5>
<p>This chapter has discussed a range of different ways in which we can create navigation using structurally sound markup, and provided examples that can be used as starting points for your own experiments.</p>
<p>On existing sites where a full redesign is not possible, introducing a CSS-based navigation system can be a good way to improve the site&#8217;s accessibility and load speed without affecting its look and feel in a big way.</p>
<p>Where to next? <a href="http://www.sitepoint.com/popup/popup.php?zone=2&amp;popupid=99" class="sublink">Download this article in PDF format</a>, and you&#8217;ll also receive two other chapters:</p>
<ul>
<li>Chapter 3, CSS and Images, which demonstrates the basics of working with images and answers common image-related questions</li>
<li>Chapter 8, Accessibility and Alternative Devices, which moves through the basics of separating content from presentation before dealing with questions of alternative style sheets and addressing users&#8217; particular accessibility needs</li>
</ul>
<p>And don&#8217;t forget to check out the <a href="http://www.sitepoint.com/books/cssant2/toc.php" class="sublink">Table of Contents</a> for more on what&#8217;s in <a href="http://www.sitepoint.com/books/cssant2/" class="sublink"><em>The CSS Anthology: 101 Essential Tips, Tricks and Hacks</em></a>.</p>
<p><script src="http://www.sitepoint.com/adjs.php?region=79&amp;did=adz&amp;adtype=vertical" type="text/javascript"></script>       <span></span></p>
]]></content:encoded>
			<wfw:commentRss>http://blogs.pinkcrow.net/nifty-navigation-using-css/65/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Developing with the Facebook Platform and PHP</title>
		<link>http://blogs.pinkcrow.net/developing-with-the-facebook-platform-and-php/64/</link>
		<comments>http://blogs.pinkcrow.net/developing-with-the-facebook-platform-and-php/64/#comments</comments>
		<pubDate>Tue, 04 Sep 2007 11:06:08 +0000</pubDate>
		<dc:creator>Valeriu Buzila</dc:creator>
		
		<category><![CDATA[Software]]></category>

		<guid isPermaLink="false">http://blogs.pinkcrow.net/developing-with-the-facebook-platform-and-php/64/</guid>
		<description><![CDATA[At the end of May this year, the Facebook team announced major changes to the package&#8217;s developer tools, known as the Facebook Platform. Although the platform itself had been available for several months prior to this release, a host of new features were announced at f8, the Facebook developer event in San Francisco. This launch [...]]]></description>
			<content:encoded><![CDATA[<p><strong>At the end of May this year, the Facebook team <a href="http://developers.facebook.com/news.php?blog=1&amp;story=21" class="sublink">announced major changes</a> to the package&#8217;s developer tools, known as the Facebook Platform. Although the platform itself had been available for several months prior to this release, a host of new features were announced at f8, the Facebook developer event in San Francisco. This launch generated a lot of press coverage &#8212; from <a href="http://online.wsj.com/public/article/SB117971397890009177-wjdKPmjAqS_9ZZbwiRp_CoSqvwQ_20070620.html" class="sublink">the Wall Street Journal</a> to <a href="http://www.techcrunch.com/2007/05/24/facebook-launches-facebook-platform-they-are-the-anti-myspace/" class="sublink">TechCrunch.</a> But the important question is: why should you care? </strong></p>
<p><a href="http://i2.sitepoint.com/graphics/facebooklogo.png" class="beatbox"><em>The face of Facebook (click to view image)</em><img src="http://i2.sitepoint.com/graphics/facebooklogo.png" height="94" width="250" /></a></p>
<p>According to Alexa, <a href="http://www.alexa.com/data/details/traffic_details?url=http://www.facebook.com" class="sublink">Facebook is one of the top 20 sites on the Web</a>, and it has some impressive statistics:</p>
<ul>
<li>The site&#8217;s growth is around 3% per week, which equates to 100,000 new users per day.</li>
<li>50% of registered users visit the site every day.</li>
<li>The site attracts more traffic than eBay: 40 billion page views per month, which equates to an average of 50 pages per user, per day.</li>
</ul>
<p>Just looking at these statistics should start you thinking about the ways in which you can leverage this level of traffic to benefit your own web site. If you could tap into the Facebook userbase, you could very easily and quickly increase the audience&#8217;s awareness of your brand, product, service, or web site.</p>
<p>Let&#8217;s consider a real-world example. I&#8217;m currently working on <a href="http://www.welovelocal.com/" class="sublink">welovelocal.com</a>, a UK directory that allows its users to find and review businesses. While this isn&#8217;t necessarily a new idea, the site adds a social element whereby users can view reviews from their friends to find out about businesses that other users with similar interests are reviewing. And by leveraging Facebook, a site like this can significantly increase its exposure to a given user&#8217;s network of friends.</p>
<p>For example, if Stacy, a welovelocal user, writes a review about a restaurant, that review will be published to Stacy&#8217;s Facebook news feed. All of Stacy&#8217;s friends on Facebook will be able to see that she&#8217;s written a new review, and can click through to welovelocal to read it.</p>
<p>Can you see the potential?</p>
<p>You can work with the Facebook Platform in many ways, including creating apps that exist just within Facebook itself. However, I feel that the greatest potential lies with integrating Facebook into an existing site, and that&#8217;s what I&#8217;ll cover in this article.</p>
<p>The news feed is perhaps the most important element of the platform, as it adds a real viral element to any kind of notification you send out &#8212; being able to reach the entire network of friends for any of your users is certainly a great feature. But there are many other avenues by which content can be communicated to users. For example, you can:</p>
<ul>
<li>Add a link to your own site from the left-hand menu bar of a user&#8217;s Facebook profile page, as shown below.</li>
</ul>
<p><a href="http://i2.sitepoint.com/graphics/sidebar.png" class="beatbox"><em>A link has been added to a Facebook sidebar (click to view image)</em><img src="http://i2.sitepoint.com/graphics/sidebar.png" height="274" width="134" /></a></p>
<ul>
<li>Add to a user&#8217;s profile a content box that contains whatever content you like. With welovelocal, we use this to display the user&#8217;s latest five reviews, complete with ratings and links back to the actual reviews on our site, as shown here.</li>
</ul>
<p><a href="http://i2.sitepoint.com/graphics/profile.png" class="beatbox"><em>A content box displaying a user&#8217;s last five reviews (click to view image)</em><img src="http://i2.sitepoint.com/graphics/profile.png" height="256" width="403" /></a></p>
<ul>
<li>Send requests to users to perform certain actions. For example, you could retrieve a list of your users&#8217; friends, and send a request to all of them to add your app to their Facebook profiles.</li>
<li>Upload photos, create albums, get photos, and manage photos within Facebook. One use for this might be to access the photos a user has added to their Facebook account and pull them into your site, or to push photos that have been uploaded to your site back to Facebook.</li>
</ul>
<h5>How Do I Use It?</h5>
<p>In this article, we&#8217;ll walk through the basics of using the Facebook platform using PHP 5. If you&#8217;re interested in integrating your site with Facebook using another language, there is plenty of information on the Facebook developers&#8217; wiki:</p>
<ul>
<li><a href="http://wiki.developers.facebook.com/index.php/ASP.NET" class="sublink">ASP.NET</a></li>
<li><a href="http://wiki.developers.facebook.com/index.php/ASP_%28VBScript%29/" class="sublink">ASP(VBScript)</a></li>
<li><a href="http://wiki.developers.facebook.com/index.php/ColdFusion" class="sublink">ColdFusion</a></li>
<li><a href="http://wiki.developers.facebook.com/index.php/C%2B%2B" class="sublink">C++</a></li>
<li><a href="http://wiki.developers.facebook.com/index.php/C" class="sublink">C#</a></li>
<li><a href="http://wiki.developers.facebook.com/index.php/Java" class="sublink">Java</a></li>
<li><a href="http://wiki.developers.facebook.com/index.php/Perl" class="sublink">Perl</a></li>
<li><a href="http://wiki.developers.facebook.com/index.php/PHP" class="sublink">PHP</a></li>
<li><a href="http://wiki.developers.facebook.com/index.php/Python" class="sublink">Python</a></li>
<li><a href="http://wiki.developers.facebook.com/index.php/Using_Ruby_on_Rails_with_Facebook_Platform" class="sublink">Ruby on Rails</a></li>
<li><a href="http://wiki.developers.facebook.com/index.php/ASP.NET" class="sublink">VB.NET</a></li>
</ul>
<p>I was fortunate (or unfortunate) to develop the welovelocal application prior to the official platform release in May. This meant that I had to write my own code to call the functions. There is an official PHP 5 library as well as an unofficial PHP 4 version (see the PHP link above) that you can probably use to get up and running more quickly and easily than I did. However, in order to gain a proper understanding of how the platform works, it&#8217;s worth looking at the raw interactions that take place.</p>
<h5>First Steps</h5>
<p>You must register for an API key before you can access the Facebook Platform. To do this, you&#8217;ll need to sign up for a Facebook account, then add the &#8220;Developer&#8221; application to your Facebook account. You can do so by following the very simple instructions at <a href="http://www.facebook.com/developers" class="sublink">www.facebook.com/developers</a>. Once it&#8217;s added, you&#8217;ll find that the Developer application is very much like a normal Facebook group, but it has an additional link near the top of the page called &#8220;My Applications&#8221; which, when clicked, will display a list of all the Facebook applications that you have registered.</p>
<p>Once you&#8217;ve registered, you need to generate a key. Click the Apply for another key link and you&#8217;ll be walked through the process of creating a Facebook application. There are a number of fields that you can provide optional information to, all of which are explained in the <a href="http://developers.facebook.com/step_by_step.php" class="sublink">quick start guide</a> on the <a href="http://developers.facebook.com/" class="sublink">Facebook Developers site</a>.</p>
<p>Your application is actually now ready to be used, although it won&#8217;t do anything! Depending on what you want your application to do, your users may need to perform a number of steps to install your app into their Facebook accounts. The process usually consists of them clicking an Install link, then confirming the request, as shown here.</p>
<p><a href="http://i2.sitepoint.com/graphics/addapplication.png" class="beatbox"><em>Adding an application to a Facebook account (click to view image)</em><img src="http://i2.sitepoint.com/graphics/addapplication.png" height="352" width="393" /></a></p>
<p>Once the application is added, it will appear in the user&#8217;s news feed and on their mini-feed, both of which are viewable by all their friends &#8212; your first bit of free publicity!</p>
<h5>Authentication</h5>
<p>Your application is ready to be used, but of course you&#8217;ll want to provide some content for your user. The two most important features for web site owners are:</p>
<ul>
<li>the ability to publish items to the news feed</li>
<li>the ability to add a profile box</li>
</ul>
<p>Before you can use either of these pieces of functionality, you need to authenticate the current user with the Facebook platform.</p>
<p>Each call to the Facebook Platform API requires a session key that identifies the user who&#8217;s logged in and is using the system. To obtain this key, you must make a call to the Facebook API that redirects the user to log in to the Facebook web site and authorize the request.</p>
<p>One hurdle here is that this authorization provides a session key that only lasts for a certain period of time &#8212; around 24 hours. A key that didn&#8217;t expire would be much more useful. Fortunately, we can obtain such a key by following these two steps, which I&#8217;ll explain in more detail in a moment:</p>
<ol>
<li>First, ask the user to authorize your application so that it can access the user&#8217;s account on Facebook. This returns auth token 1, which generates a session key that expires after 24 hours.</li>
<li>Then, ask the user to generate auth token 2, which they should then paste into a form on your web site. With this token in place, you&#8217;ll be able to generate a session key that never expires.</li>
</ol>
<p>Once you have the final token, you can request a permanent session key by calling the <code>facebook.auth.getSession</code> function.</p>
<p>But first, allow me to elaborate on those two steps.</p>
<p><strong><em>Step 1 - Obtaining Auth Token 1</em></strong></p>
<p>From your web site, direct your user to Facebook using a URL appended with your API key, like this:  <code>www.facebook.com/login.php?api_key=APIKEY</code> (where APIKEY should be replaced with your own API key). If the user is not currently logged in, they&#8217;ll be asked to do so.</p>
<p>The user will then be asked to accept any terms of service you set, and will be redirected to the callback URL that you specified when creating the application. This can be changed by editing your application through the Developer link in Facebook&#8217;s sidebar.</p>
<p>With the redirect in place, Facebook will append <code>?auth_token=TOKEN</code> to the URL, using an actual authentication token. You can use this token with the <code>facebook.auth.getSession</code> function; it&#8217;s available as a <code>GET</code> variable in PHP.</p>
<p>However, because we want to get an infinite session, that <code>auth</code> token is actually irrelevant &#8212; we need to get another token that we can use to get a permanent session key. If we were not interested in an infinite session, this is where we would stop. We could use the <code>auth</code> token with the <code>facebook.auth.getSession</code> function below.</p>
<p><strong><em>Step 2 - Obtaining Auth Token 2</em></strong></p>
<p>Once your user has returned to your site after logging into Facebook, you&#8217;ll need to send them to <code>www.facebook.com/code_gen.php?api_key=APIKEY</code>. Back on the Facebook site, the user will be asked to generate a token that will be displayed to them. They must then copy and paste it into a form on your web site &#8212; it&#8217;s not passed through via <code>GET</code>/<code>POST</code>. It&#8217;s up to you to create a form that accepts this token from your user.</p>
<p>Once the user has submitted this second token to your site, you&#8217;ll need to call the <code>facebook.auth.getSession</code> function, passing the token as a parameter. This will finally return a session key that you can use continuously to authenticate that user; this key could, for example, be stored in the database alongside the user&#8217;s account for easy retrieval in the future.</p>
<p>It&#8217;s important to note that, should the user delete your application from their Facebook account, they&#8217;ll need to repeat this authentication process in order to use your Facebook application. You should therefore provide the option for the user to reset their Facebook integration and set it up again. If you&#8217;re storing the user&#8217;s session key in the database, this task would simply involve deleting that session key and taking the user through the two-step authentication process above.</p>
<h5>Calling <code>facebook.auth.getSession</code></h5>
<p>Now that you have an authentication token, you&#8217;ll need to get yourself a session key for the current user. This key is passed to every other Facebook API call, to identify the user upon which your application is conducting an action.</p>
<p>Because we&#8217;re not using a library provided by Facebook, we&#8217;ll need to manually construct the HTTP query that we&#8217;ll send to Facebook, and write some code to process the response. With every call, you must provide three required values, as <a href="http://developers.facebook.com/documentation.php?v=1.0&amp;doc=auth" class="sublink">described on the Facebook web site</a>:</p>
<ul>
<li><code>method</code> - The first parameter is the method name. The method must be one of those exposed by the API documentation, or the API will return error code 3 (with message Unknown method).</li>
<li><code>api_key</code> - The vendor-specific API key corresponding to the site making the API call. This is the same key that we used in the login request, as provided to you when you registered your application.</li>
<li><code>sig</code> - The signature for the method call.</li>
</ul>
<p>The signature is generated as described by this pseudocode:</p>
<p><code>args = <a href="http://www.sitepoint.com/glossary.php?q=%23#term_72" class="glossary" title="An array is a single variable with compartments, each of which can hold a value. ">array</a> of args to the request, formatted in arg=val pairs<br />
sorted_array = alphabetically_sort_array_by_keys(args);<br />
request_str = concatenate_in_order(sorted_array);<br />
signature = md5(concatenate(request_str, secret))</code></p>
<p>Rather than having to do this manually every time you need to perform an HTTP query, I&#8217;ve written a short <code>do_facebook_request()</code> function that is <a href="http://www.sitepoint.com/examples/facebook/facebook.zip" class="sublink">available for download</a>. This takes the optional parameters that are to be sent for a specific API function, as well as the name of that function. It constructs and sends the request, then returns the result:</p>
<p><code>do_facebook_request.php<br />
&lt;?php<br />
/**<br />
* Sends an API request to Facebook<br />
*<br />
* @param array $parameters Array of parameters to send<br />
* @param string $method The API function to call<br />
* @return array Returns array of data returned<br />
*/<br />
function do_facebook_request($parameters, $method)<br />
{<br />
if (empty($parameters) || empty($method))<br />
{<br />
return false;<br />
}</p>
<p>// Build Facebook args<br />
// http://developers.f8.facebook.com/documentation.php?v=1.0&amp;doc=auth<br />
$data['api_key'] = 'API KEY';<br />
$data['method'] = $method;<br />
$data['v'] = '1.0';</p>
<p>// Loop through and set as array<br />
foreach ($parameters as $key =&gt; $value)<br />
{<br />
$data[$key] = $value;<br />
}</p>
<p>// Sort<br />
ksort($data);</p>
<p>$args = '';</p>
<p>foreach ($data as $key =&gt; $value)<br />
{<br />
$args .= $key.'='.$value;<br />
}</p>
<p>$data['sig'] = md5($args.'secret');</p>
<p>// Get a Facebook session<br />
$response = do_post_request('http://api.facebook.com/restserver.php', $data);</p>
<p>// Handle <a href="http://www.sitepoint.com/glossary.php?q=X#term_3" class="glossary" title="eXtensible Markup Language, or XML, is a text markup language designed for the easy sharing of data.">XML</a><br />
$xml = simplexml_load_string($response);</p>
<p>return $xml;<br />
}</p>
<p>/**<br />
* Sends a POST request with necessary parameters<br />
* Code based on http://netevil.org/node.php?nid=937<br />
* We use HTTP here. See http://uk2.php<a href="http://www.sitepoint.com/glossary.php?q=%23#term_2" class="glossary" title=".NET is an application framework from Microsoft.">.net</a>/manual/en/wrappers.http.php<br />
*<br />
* @param string $url The URL to perform the POST on. Include http://<br />
* @param array $data The data to POST in array format<br />
* @param array $optional_headers Any HTTP headers. See http://www.php.net/manual/sv/function.header.php or http://www.faqs.org/rfcs/rfc2616<br />
* @param string $method The method for the request. Defaults to POST<br />
* @return string The response<br />
*/<br />
function do_post_request($url, $data, $optional_headers = NULL, $method = &#8216;POST&#8217;)<br />
{<br />
// Just defining some parameters for the request here<br />
// See http://uk2.php.net/manual/en/wrappers.http.php#AEN268663 for additional context options<br />
$params = array(&#8217;http&#8217; =&gt; array(&#8217;method&#8217; =&gt; $method, &#8216;content&#8217; =&gt; http_build_query($data)));</p>
<p>if ($optional_headers !== NULL) // Add in any additional headers<br />
{<br />
$params[&#8217;http&#8217;][&#8217;header&#8217;] = $optional_headers;<br />
}</p>
<p>// Makes it easier to add additional parameters such<br />
// as any optional HTTP headers as set above<br />
$context = stream_context_create($params);</p>
<p>$fp = @fopen($url, &#8216;rb&#8217;, false, $context);</p>
<p>if (!$fp)<br />
{<br />
return false;<br />
}</p>
<p>$response = @stream_get_contents($fp);</p>
<p>if ($response === false)<br />
{<br />
fclose($fp);<br />
return false;<br />
}</p>
<p>fclose($fp);</p>
<p>return $response;<br />
}<br />
?&gt;</code></p>
<p>The code is part of a class I wrote for the welovelocal application, and is based on <a href="http://netevil.org/node.php?nid=937" class="sublink">the code provided in Wez Furlong&#8217;s blog</a>. You&#8217;ll need to replace the API_KEY on line 20 with your own key, as well as the secret on line 40 to generate the signature. The secret is a string generated by Facebook, and is displayed underneath your API key on the My Applications section of the Developer application within Facebook.<br />
Here&#8217;s an example in which we&#8217;re calling the <code>do_facebook_request</code> function:</p>
<p><code>$xml = do_facebook_request(array('auth_token' =&gt; $token), 'facebook.auth.getSession');</code></p>
<p>After the request has been processed, the <code>$xml</code> variable will contain something that looks like this:</p>
<p><code>&lt;?xml version="1.0" encoding="UTF-8"?&gt;<br />
&lt;auth_getSession_response xmlns="http://api.facebook.com/1.0/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://api.facebook.com/1.0/ http://api.facebook.com/1.0/facebook.xsd"&gt;<br />
&lt;session_key&gt;5f34e11bfb97c762e439e6a5-8055&lt;/session_key&gt;<br />
&lt;uid&gt;8055&lt;/uid&gt;<br />
&lt;expires&gt;&lt;/expires&gt;<br />
&lt;/auth_getSession_response&gt;</code></p>
<p>This is the <code>session_key</code> that you can store and use for all subsequent requests. See the <a href="http://developers.facebook.com/documentation.php?v=1.0&amp;method=auth.getSession" class="sublink">auth.getSession</a> documentation for detailed information.</p>
<h5>The User Profile Box</h5>
<p>Displaying contributed content as part of users&#8217; profiles is a great way for users to show off the work they&#8217;ve done on your web site. With welovelocal, we let people list their latest reviews on their profile, so that their friends can read what they&#8217;ve been writing. This concept could be extended for photos, news articles, game high scores &#8212; almost anything, really.</p>
<p>Facebook uses its own subset of the <a href="http://www.sitepoint.com/glossary.php?q=H#term_75" class="glossary" title="HTML stands for HyperText Markup Language.">HTML</a> language to allow you to put rich content in a user&#8217;s profile without opening security issues or destroying the layout of a site. This markup language is called FBML &#8212; Facebook Markup Language &#8212; and is <a href="http://developers.facebook.com/documentation.php?v=1.0&amp;doc=fbml" class="sublink">well documented on the Facebook developer web site</a>.</p>
<p>Pushing the content to a profile is very simple &#8212; you generate the FBML within your code, then send it to the API, which makes the content live. The function is called <a href="http://developers.facebook.com/documentation.php?v=1.0&amp;method=profile.setFBML" class="sublink">facebook.profile.setFBML</a> and requires you to provide both the session key we obtained earlier and the actual FBML you want to display.</p>
<p>Creating FBML is very straightforward and is well explained in the official documentation, so I won&#8217;t go into any detail here. You can use the <a href="http://developers.facebook.com/tools.php?fbml" class="sublink">FBML test console</a> to see a preview of what the output will look like.</p>
<p>Once you&#8217;ve written the FBML, you can use the <code>do_facebook_request()</code> function to send it to Facebook&#8217;s API:</p>
<p><code>$xml = do_facebook_request(array('session_id' =&gt; 'idhere', 'call_id' =&gt; microtime(), 'markup' =&gt; $markup), 'facebook.profile.setFBML');</code></p>
<p>You&#8217;ll notice a <code>call_id</code> as the final parameter that we passed to the <code>do_facebook_request</code> function. This is a unique ID for the request. Facebook recommends that you use the current time in milliseconds, which is available via the <a href="http://www.php.net/microtime" class="sublink"><code>microtime()</code></a> function.</p>
<p>And that&#8217;s it &#8212; the profile content will appear immediately!</p>
<h5>News Feeds</h5>
<p>The news feed in Facebook is a summary of everything that&#8217;s going on with your friends &#8212; it&#8217;s something of a history of their interactions with the site. Through a friend&#8217;s news feed, you can:</p>
<ul>
<li>find out what they&#8217;re doing with status updates (like <a href="http://twitter.com/" class="sublink">Twitter</a>)</li>
<li>learn who they&#8217;ve become friends with</li>
<li>see when they&#8217;ve updated their profiles</li>
</ul>
<p>&#8230; as well as almost anything else that happens to them on Facebook. I&#8217;m sure you&#8217;ll agree that being able to post items to all of a user&#8217;s friends is a great way to publicize activity that&#8217;s occurring on your own web site.</p>
<p>You can publish a news item to the feed of a single user, or to the feeds of all the friends of a specific user. Next up, we&#8217;re going to look at the latter task &#8212; using the <a href="http://developers.facebook.com/documentation.php?v=1.0&amp;method=feed.publishActionOfUser" class="sublink"><code>feed.publishActionOfUser</code></a> function &#8212; as this is the most useful for notifying people about things that are happening on your own site.</p>
<p>While the <code>feed.publishActionOfUser</code> function allows you to send up to four images (which is ideal for sites that use graphical content), to keep things simple, I&#8217;ll keep this example to the simple task of sending text.</p>
<p>When sending a news item you must specify a title (max. 40 characters), but you can also optionally provide body text. The title will be displayed in bold, and the body text in regular paragraph styling. The body text is usually used to elaborate on the details contained in the title.</p>
<p>Facebook allows the use of certain tags in the title and body. These tags allow you to display context-sensitive information, such as the name of the user and a link to the profile. So, if I were to send the following request to post information to my friends:</p>
<p><code>&lt;fb:userlink uid="profileowner"/&gt; wrote a new review.</code></p>
<p>It would show up as:</p>
<p><q>David Mytton (Network Name) wrote a new review.</q>My name would be linked to my Facebook profile, and the Network Name would be replaced with the network through which the person viewing the news feed knows me (for example, university name, club name, or the like).</p>
<p>To prevent spamming, Facebook imposes limits on the number of times you can send out news items. This is <a href="http://developers.facebook.com/documentation.php?v=1.0&amp;method=feed.publishActionOfUser" class="sublink">explained in detail in the developer documentation</a>.</p>
<p>As we saw earlier, you can also use the <code>do_facebook_request</code> function to send out a news feed, like so:</p>
<p><code>$params['call_id'] = microtime();<br />
$params['session_id'] = 'idhere';<br />
$params['title'] = '&lt;fb:userlink uid="profileowner"/&gt; wrote a new review';<br />
$params['body'] = '&lt;a href="http://www.welovelocal.com/business/'.$business['url_company'].'/#r'.$review_id.'"&gt;Read the full review...&lt;/a&gt;';<br />
do_facebook_request($params, 'facebook.feed.publishActionOfUser');</code></p>
<h5>Spreading your Wings</h5>
<p>We&#8217;ve touched on just a few of the key Facebook Platform functions in this article, but there are plenty of other features that you could utilize to push more content out to Facebook.</p>
<p><em>User Data</em> - <a href="http://developers.facebook.com/documentation.php?v=1.0&amp;method=users.getInfo" class="sublink">Documentation</a></p>
<p>Once you&#8217;ve authenticated the user, you can grab almost all of their profile data (though the data available may be limited depending on their privacy settings). Of course, one should use this data responsibly &#8212; one approach that comes to mind is to use it to pre-populate a lot of the fields on your own site, to save the user having to enter the same data twice.</p>
<p><em>Events</em> - <a href="http://developers.facebook.com/documentation.php?v=1.0&amp;method=events.get" class="sublink">Documentation</a></p>
<p>As any given user tends to connect with many friends on Facebook, the site is often used to organize social events. The Facebook API allows you to tap into this and return a list of all the events that a user can see, based on certain criteria. The criteria by which you can filter this data include start and end dates, and whether the user has indicated that they will attend the event.</p>
<p>You could use this feature to present a calendar to your users, so that they can plan other events around other commitments they have in place with their friends.</p>
<p><em>Groups</em> - <a href="http://developers.facebook.com/documentation.php?v=1.0&amp;method=groups.get" class="sublink">Documentation</a></p>
<p>Similar to the ways in which you can use events data, you can use the Facebook API to find out which groups a user belongs to, and retrieve a list of members of those groups. This could be useful to combine with the notifications API, for example, to send requests to all users in a group to join your web site. Of course, this approach could be seen as <a href="http://www.facebook.com/developers/message.php?id=26" class="sublink">spamming</a>, so you would definitely need to ensure that the content you broadcast is relevant.</p>
<p><em>Photo Uploads</em> - <a href="http://developers.facebook.com/documentation.php?v=1.0&amp;doc=photoupload" class="sublink">Documentation</a></p>
<p>Facebook has over 60 million photos uploaded every week, and <a href="http://blog.facebook.com/blog.php?post=2406207130" class="sublink">160TB of photo storage is currently available</a>, which makes it an extremely popular way to share photos. Using the API, you can:</p>
<ul>
<li>create a new album to store photos</li>
<li>retrieve a list of the existing albums, to choose which one to upload photos to</li>
<li>upload photos to the site</li>
<li>retrieve photos from a specific album, or from all photos across the entire site to which the current user has access</li>
</ul>
<p>This means that you could present a user with a list of their Facebook photos, and provide them with the ability to display them on your own site. They could also do the reverse: copy photos from your site to Facebook, thereby allowing all their friends to see them.</p>
<h5>Summary</h5>
<p>This article looked at some of the ways in which you can integrate your web site with Facebook. Whether you choose to utilize only one small aspect of the Web&#8217;s fastest growing community, or embrace it with open arms, the Facebook API is a powerful tool both to enhance the experience for existing users, and to attract new users by driving traffic to your site</p>
]]></content:encoded>
			<wfw:commentRss>http://blogs.pinkcrow.net/developing-with-the-facebook-platform-and-php/64/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Easy Ajax with jQuery</title>
		<link>http://blogs.pinkcrow.net/easy-ajax-with-jquery/63/</link>
		<comments>http://blogs.pinkcrow.net/easy-ajax-with-jquery/63/#comments</comments>
		<pubDate>Tue, 04 Sep 2007 11:01:35 +0000</pubDate>
		<dc:creator>Valeriu Buzila</dc:creator>
		
		<category><![CDATA[Software]]></category>

		<guid isPermaLink="false">http://blogs.pinkcrow.net/easy-ajax-with-jquery/63/</guid>
		<description><![CDATA[Ajax is changing web applications, giving them a responsiveness that&#8217;s unheard of beyond the desktop. But behind all the hype, there&#8217;s not much to Ajax &#8212; (X)HTML, JavaScript, and XML are nothing new, and in this tutorial, I&#8217;ll show you how to simplify the process of adding Ajax to your application even further with the [...]]]></description>
			<content:encoded><![CDATA[<p><strong><a href="http://www.sitepoint.com/glossary.php?q=A#term_73" class="glossary" title="AJAX stands for Asynchronous JavaScript and XML.">Ajax</a> is changing web applications, giving them a responsiveness that&#8217;s unheard of beyond the desktop. But behind all the hype, there&#8217;s not much to Ajax &#8212; (X)<a href="http://www.sitepoint.com/glossary.php?q=H#term_75" class="glossary" title="HTML stands for HyperText Markup Language.">HTML</a>, <a href="http://www.sitepoint.com/glossary.php?q=J#term_9" class="glossary" title="JavaScript is a Web scripting language most commonly used for client-side applications.">JavaScript</a>, and <a href="http://www.sitepoint.com/glossary.php?q=X#term_3" class="glossary" title="eXtensible Markup Language, or XML, is a text markup language designed for the easy sharing of data.">XML</a> are nothing new, and in this tutorial, I&#8217;ll show you how to simplify the process of adding Ajax to your application even further with the help of jQuery, a popular JavaScript library.</strong></p>
<h5>What&#8217;s Ajax?</h5>
<p>You&#8217;ve probably heard about Ajax before, or at least used an Ajax-based application &#8212; Gmail, for instance. Quite simply, Ajax is a technique for handling external data through JavaScript asynchronously, without reloading the entire page. SitePoint offers <a href="http://www.sitepoint.com/article/take-command-ajax" class="sublink">a good introduction to Ajax</a>. Jesse James Garrett is credited with coining the term in <a href="http://adaptivepath.com/publications/essays/archives/000385.php" class="sublink">this article</a>.</p>
<p>Unfortunately, in-depth tutorials on practical ways to enter the world of Ajax are few and far between. To add to the problem, the <code>XMLHttpRequest</code> class used by Ajax isn&#8217;t very easy for beginning web developers to use. Luckily, a number of JavaScript libraries offer an easier way. Today I&#8217;ll show you how jQuery &#8212; one of these libraries &#8212; allows you to easily add Ajax to your application.</p>
<h5>What&#8217;s jQuery?</h5>
<p>jQuery is another mature JavaScript library that offers some features that the others do not. Admittedly, it&#8217;s not exactly as lightweight as some of the other offerings: jQuery comes in at 19kb, while moo.fx is only 3kb. You can read more about jQuery at <a href="http://jquery.com/#el#/,%20and%20see%20the%20article,%20/#l#/http://www.sitepoint.com/article/javascript-library" class="sublink">The JavaScript Library World Cup</a> for a comparison of a few other JavaScript libraries that offer similar functionality.</p>
<h5>Assumed Knowledge</h5>
<p>To complete this tutorial, you&#8217;ll need some basic JavaScript knowledge. If you know any C-style languages, you&#8217;ll get the hang of JavaScript in no time. Just think curly braces, function declarations, and optional semicolons at the end of each line (they&#8217;re not optional with jQuery, though). If you&#8217;re keen to get started with JavaScript, see <a href="http://www.wdvl.com/Authoring/JavaScript/Tutorial/" class="sublink">this excellent, concise JavaScript tutorial</a> designed for programmers. Also, since we&#8217;re talking about web applications, a basic knowledge of HTML is required.</p>
<h5>jQuery 101</h5>
<p>Let&#8217;s walk through a quick introduction to jQuery. To be able to use it in your pages, you&#8217;ll first need to download the library. You can <a href="http://jquery.com/src/" class="sublink">download the latest version</a> &#8212; 1.1.2 at the time of writing. jQuery&#8217;s methodology is simple: find things, do stuff. We select elements from the document (via the <a href="http://www.sitepoint.com/glossary.php?q=D#term_39" class="glossary" title="A DOM, or Document Object Model, is a tree representation of the structure of Web document.">DOM</a>) using the jQuery function, aliased as <code>$()</code>. This handy function acts just like <a href="http://www.sitepoint.com/article/ajax-jquery/document.getElementById%28%29" class="sublink">document.getElementById()</a>, except that instead of only supporting IDs, it supports <a href="http://www.sitepoint.com/glossary.php?q=C#term_8" class="glossary" title="CSS, or Cascading Style Sheets, comprise styling and formatting rules that are applied to Web documents.">CSS</a> selectors and some XPath selectors; and, instead of returning one element, it can return an <a href="http://www.sitepoint.com/glossary.php?q=%23#term_72" class="glossary" title="An array is a single variable with compartments, each of which can hold a value. ">array</a> of elements. Okay, so maybe a better description of <code>$()</code> is that it&#8217;s like <code>document.getElementById()</code> on steroids.</p>
<p>We then use functions to perform actions on our selections. For example, to append the text &#8220;Hello World!&#8221; to all divs with the class <code>'foo'</code>, then set the color to red, we&#8217;d use the following code:</p>
<p><code>$("div.foo").append("Hello World!").css("color","red");</code></p>
<p>Easy! Normally, this task would require two lines of code, like so:</p>
<p><code>$("div.foo").append("Hello World!");<br />
$("div.foo").css("color","red");</code></p>
<p>jQuery&#8217;s chainable methods allow us to write much more compact code than other JavaScript libraries. There are functions in jQuery that don&#8217;t need an object, as they work independently, and many of the Ajax functions fall into this group. For example, the post function, which we will soon make use of, is called by typing <code>$.post(parameters)</code>. For more jQuery functions, check the <a href="http://docs.jquery.com/" class="sublink">online documentation</a> or <a href="http://visualjquery.com/" class="sublink">visualjquery.com</a>.</p>
<h5>Example 1 - Our First Ajax Application</h5>
<p>As an example, we&#8217;re going to make an interactive concept generator. Basically, this involves our selecting two terms at random from a list, then combining them to create a phrase. For this exercise, we&#8217;ll use web 2.0 buzzwords (&#8217;Mashup&#8217;, &#8216;Folksonomy&#8217;, &#8216;Media&#8217; and so on), and normally we&#8217;d fetch these terms from a flat file. To save you from downloading every single combination (or at least every element) in JavaScript, we&#8217;re going to generate it on the fly at the server end, and fetch it for the client with jQuery. jQuery integrates perfectly with normal JavaScript, so you&#8217;ll find it an easy task to work it into your code.</p>
<p><strong><em><a href="http://www.sitepoint.com/glossary.php?q=S#term_14" class="glossary" title="Server-side code is executed on the web server before being sent to the end user. ">Server-side</a> Code (PHP)</em></strong></p>
<p>To keep it simple, we&#8217;ll use the basic code below to create our concept generator. Don&#8217;t worry about how it works, just look at what it does: it outputs a randomised quote. Note that this code doesn&#8217;t output XML &#8212; it merely outputs raw text:</p>
<p><code>&lt;?php<br />
header("<a href="http://www.sitepoint.com/glossary.php?q=C#term_21" class="glossary" title="Cache, pronounced "cash", refes to a stored copy of (or pointers to) previously accessed data. ">Cache</a>-Control: no-cache&#8221;);<br />
// Ideally, you&#8217;d put these in a text file or a database.<br />
// Put an entry on each line of &#8216;a.txt&#8217; and use $prefixes = file(&#8221;a.txt&#8221;);<br />
// You can do the same with a separate file for $suffixes.<br />
$prefixes = array(&#8217;Mashup&#8217;,'2.0&#8242;,&#8217;Tagging&#8217;,'Folksonomy&#8217;);<br />
$suffixes = array(&#8217;Web&#8217;,'Push&#8217;,'Media&#8217;,&#8217;<a href="http://www.sitepoint.com/glossary.php?q=G#term_62" class="glossary" title="Graphical User Interface">GUI</a>&#8216;);<br />
// This selects a random element of each array on the fly<br />
echo $prefixes[rand(0,count($prefixes)-1)] . &#8221; is the new &#8221;<br />
. $suffixes[rand(0,count($prefixes)-1)];<br />
// Example output: Tagging is the new Media<br />
?&gt;</code></p>
<p>Here, I&#8217;ve used the <code>Cache-Control</code> header response because Internet Explorer has a habit of <a href="http://www.sitepoint.com/glossary.php?q=C#term_21" class="glossary" title="Cache, pronounced "cash", refes to a stored copy of (or pointers to) previously accessed data. ">caching</a> pages that have the same URL, even if the content between the pages differs. Obviously, that defeats the purpose of our script &#8212; the production of a new quote on every load. We could have used jQuery to include a random number in the URL that would then be discarded, but it&#8217;s easier to address this caching issue on the server side than the client side.</p>
<p><strong><em>Client-side Code (HTML)</em></strong></p>
<p>Let&#8217;s start creating the HTML for the front end, then work our Ajax into it. All we need on the page is a button that users can click to request another quote, and a div into which we&#8217;ll put the quote once we&#8217;ve received it from the server. We&#8217;ll use jQuery to select this div and load the quote into it, and we&#8217;ll reference the div by its <code>id</code>. If we wanted to, we could use jQuery to load the quote into multiple elements, with the help of a class, but an id is all we need for now. Let&#8217;s make this the content of our body element:</p>
<p><code>&lt;input type="submit" id="generate" value="Generate!"&gt;<br />
&lt;div id="quote"&gt;&lt;/div&gt;</code></p>
<p>We can put the quote itself inside the div. Normally, we&#8217;d have a lengthy <code>onSubmit</code> event for the button (the input with the id <code>'generate'</code>). Sometimes, we&#8217;d have an <code>onSubmit</code> event handler that called a JavaScript function. But with jQuery, we don&#8217;t even need to touch the HTML &#8212; we can separate behaviour (the event handler) from the structure (the page HTML) with ease.</p>
<p><strong><em>Client-side Code (jQuery)</em></strong></p>
<p>It&#8217;s time to bring our back end together with our front end using jQuery. I mentioned earlier that we can select elements from the DOM with jQuery. First, we have to select the button and assign an <code>onClick</code> event handler to it. Within the code for this event, we can select the div and load the content of our script into it. Here&#8217;s the syntax for the click event handler:</p>
<p><code>$("element expression").click(function(){<br />
// Code goes here<br />
});</code></p>
<p>As you probably already know, if we were to select this element in CSS, the <code>#</code> would identify that we were making our selection using the element&#8217;s <code>id</code> attribute. You can use exactly the same syntax with jQuery. Therefore, to select the button with the id <code>'generate'</code> (which we gave it above), we can use the element expression <code>#generate</code>. Also, be aware that this syntax defines our event handler as an anonymous function within the event itself.</p>
<p><a href="http://novemberborn.net/sifr/explained/terminology" class="sublink">Mark Wubben&#8217;s JavaScript Terminology page</a> offers a great explanation of anonymous functions, if you&#8217;d like to know more.</p>
<p>We&#8217;re going to use one of jQuery&#8217;s higher level Ajax functions, <code>load()</code>. Let&#8217;s assume that our generator script is saved as <code>script.php</code>. Let&#8217;s integrate it with our client side with the help of the <code>load()</code> function:</p>
<p><code>$("#generate").click(function(){<br />
$("#quote").load("script.php");<br />
});</code></p>
<p>That&#8217;s it: three lines of code, and we have fully functioning Ajax random quote generator! Well, almost.</p>
<p>The problem with JavaScript is that code that&#8217;s not within a function is executed as soon as the browser reaches it during rendering &#8212; not once the page has finished rendering. As such, this code will try to attach to an element that has not yet loaded. Normally, we&#8217;d use <code>window.onload</code> to deal with this issue. However, the limitation with that approach is that <code>window.onload</code> is called once everything has finished loading &#8212; images and all. We&#8217;re not interested in waiting for those images &#8212; it&#8217;s just the DOM that we want access to.</p>
<p>Fortunately, jQuery has <code>$(document).ready()</code>, which, as its name suggests, is executed when the DOM is ready to be manipulated.</p>
<p><strong><em>The Complete Code</em></strong></p>
<p>Here&#8217;s the complete code, including the <code>$(document).ready</code> wrapper and some basic HTML and CSS:</p>
<p><code>&lt;html&gt;<br />
&lt;head&gt;<br />
&lt;title&gt;Ajax with jQuery Example&lt;/title&gt;<br />
&lt;script type="text/JavaScript" src="jquery.js"&gt;&lt;/script&gt;<br />
&lt;script type="text/JavaScript"&gt;<br />
$(document).ready(function(){<br />
$("#generate").click(function(){<br />
$("#quote p").load("script.php");<br />
});<br />
});<br />
&lt;/script&gt;<br />
&lt;style type="text/css"&gt;<br />
#wrapper {<br />
width: 240px;<br />
height: 80px;<br />
margin: auto;<br />
padding: 10px;<br />
margin-top: 10px;<br />
border: 1px solid black;<br />
text-align: center;<br />
}<br />
&lt;/style&gt;<br />
&lt;/head&gt;<br />
&lt;body&gt;<br />
&lt;div id="wrapper"&gt;<br />
&lt;div id="quote"&gt;&lt;p&gt; &lt;/p&gt;&lt;/div&gt;<br />
&lt;input type="submit" id="generate" value="Generate!"&gt;<br />
&lt;/div&gt;<br />
&lt;/body&gt;<br />
&lt;/html&gt;</code></p>
<p>This code is also included in <a href="http://www.sitepoint.com/examples/jquery/ajax-jquery-demo.zip" class="sublink">this downloadable zip file</a>. Remember, this code assumes the jQuery library has been saved as <code>jquery.js</code> in the same folder as the PHP script and the HTML front end. Now that you&#8217;re familiar with jQuery, let&#8217;s move on to something more complicated: form elements and XML handling. This is true Ajax!</p>
<h5>Example 2 - Chat with jQuery</h5>
<p>To demonstrate the true power of jQuery, we&#8217;re going to make a fully featured <a href="http://www.sitepoint.com/glossary.php?q=A#term_73" class="glossary" title="AJAX stands for Asynchronous JavaScript and XML.">Ajax</a> chat application. This will allow users to post messages, and automatically update itself &#8212; all without any page refreshes. As we&#8217;re now dealing with a slightly more complex application, I&#8217;ll also take you deeper into jQuery, demonstrating other handy functions.</p>
<p>First, we&#8217;ll plan out the application. We won&#8217;t need much for this app &#8212; a front end, a back end, and the jQuery library. However, there will be a fair bit of code for both the back and front ends of the app, so our basic plan will let you know what to expect from the system.</p>
<p><strong><em>Planning the Server Side</em></strong></p>
<p>The back end of our application needs to process message submissions and output the messages. With this in mind, let&#8217;s put together a rough outline of the back-end code:</p>
<ul>
<li>connect to database</li>
<li>if a message was submitted
<ul>
<li>insert message into database</li>
<li>delete old messages</li>
</ul>
</li>
<li>fetch messages from the database and display as <a href="http://www.sitepoint.com/glossary.php?q=X#term_3" class="glossary" title="eXtensible Markup Language, or XML, is a text markup language designed for the easy sharing of data.">XML</a></li>
</ul>
<p>As you can see, it&#8217;s all very simple and straightforward. You can use this plan as a guide if you have to write a back end in another language.</p>
<p><strong><em>Planning the Client Side</em></strong></p>
<p>The front end has to call the back end using Ajax, similarly to the approach we used in the first example. It has to handle the submission of the message-posting form, and update the chat window with newly submitted messages at regular intervals. However, we&#8217;re going to add another feature here &#8212; we&#8217;ll use <a href="http://unixtimestamp.com/" class="sublink">the current UNIX timestamp</a> to determine which messages have already been downloaded, and only fetch the new messages, reducing <a href="http://www.sitepoint.com/glossary.php?q=B#term_56" class="glossary" title="Bandwidth is a measure of the amount of date that can be transferred between computers over the Internet.">bandwidth</a> usage and server load. Here&#8217;s a rough outline of the front-end code:</p>
<ul>
<li>on page load
<ul>
<li>set current timestamp to 0 (all messages will be posted after this, i.e. all messages will be fetched)</li>
<li>call function to fetch new messages</li>
</ul>
</li>
<li>function: fetch new messages
<ul>
<li>send request to server using POST</li>
<li>call function to parse XML response</li>
<li>add a timer to call this function after a second (increase frequency if server load is too high)</li>
</ul>
</li>
<li>function: parse XML of new messages
<ul>
<li>set current timestamp as specified in the XML</li>
<li>if status code returned is &#8216;2&#8242;, no new messages, so end the function call</li>
<li>else, for each message in the response, add this to the top of the message window in this format:
<ul>
<li><strong>author:</strong> message</li>
</ul>
</li>
</ul>
</li>
<li>on form submit:
<ul>
<li>send request to server using POST, specifying:
<ul>
<li>author name (user-specified)</li>
<li>message text (user-specified)</li>
<li>action noting that this is a post request</li>
<li>timestamp of the last request to the server</li>
</ul>
</li>
<li>empty content of the message input box so that the user can start typing another message</li>
<li>call function to parse XML response (so that message posted is visible immediately)</li>
</ul>
</li>
</ul>
<p>This plan may seem far more complex than the back end, but thanks to jQuery, the code involved is fairly short.</p>
<p><strong><em>Planning the Database</em></strong></p>
<p>We&#8217;ll use a <a href="http://www.sitepoint.com/glossary.php?q=M#term_12" class="glossary" title="MySQL is a free, fast, open source database.">MySQL</a> database to store the messages (although any SQL database will work, with a few tweaks to the code). We need a table with four columns: a column for the id of each message, two text columns to store the author of the message and the message itself, and a numerical timestamp column for our UNIX timestamps. Here&#8217;s the query that creates the table:</p>
<p><code>CREATE TABLE `messages` (<br />
`id` int(7) NOT NULL auto_increment,<br />
`user` varchar(255) NOT NULL,<br />
`msg` text NOT NULL,<br />
`time` int(9) NOT NULL,<br />
PRIMARY KEY  (`id`)<br />
);</code></p>
<p>Because we can&#8217;t tell what length the message will be, we&#8217;ll use a text field for now.</p>
<p><strong><em><a href="http://www.sitepoint.com/glossary.php?q=S#term_14" class="glossary" title="Server-side code is executed on the web server before being sent to the end user. ">Server-side</a> Code (XML)</em></strong></p>
<p>In building the back end, let&#8217;s first decide what the back end should output (to determine the interface between the back end and front end), and work backwards from there. Here&#8217;s a simple XML structure:</p>
<p><code>&lt;?xml version="1.0"?&gt;<br />
&lt;response&gt;<br />
&lt;status&gt;1&lt;/status&gt;<br />
&lt;time&gt;1170323512&lt;/time&gt;<br />
&lt;message&gt;<br />
&lt;author&gt;John Citizen&lt;/author&gt;<br />
&lt;text&gt;Hello world!&lt;/text&gt;<br />
&lt;/message&gt;<br />
&lt;message&gt;<br />
&lt;author&gt;John Citizen&lt;/author&gt;<br />
&lt;text&gt;Hello world again!&lt;/text&gt;<br />
&lt;/message&gt;<br />
&lt;/response&gt;</code></p>
<p>Notice that I&#8217;ve added the tag <code>'status'</code>, with the value of <code>'1'</code>. As I mentioned above, a status code of <code>1</code> will represent a successful request with new messages, <code>2</code> as successful without new messages. Each instance of the message tag includes the author and his or her message.</p>
<p><strong><em>Server-side Code (<a href="http://www.sitepoint.com/glossary.php?q=P#term_1" class="glossary" title="PHP, or Hypertext Preprocessor, is an open source, server-side programming language.">PHP</a>)</em></strong></p>
<p>Now, to the back end. I&#8217;ll have to do this in PHP, but because the output is XML you can write the back end in any language &#8212; <a href="http://www.sitepoint.com/glossary.php?q=P#term_44" class="glossary" title="Perl is one of the original  server side scripting languages.">Perl</a>, <a href="http://www.sitepoint.com/glossary.php?q=A#term_4" class="glossary" title="Active Server Pages, or ASP, is Microsoft's IIS based server side scripting architecture.">ASP</a>, whatever you like. Let&#8217;s start it logically by defining some configuration values so that we can easily change them later. We need database connection details, the number of messages we want to store in the database (databases can handle thousands of rows, so this figure can be set fairly high), and the number of messages to display when the user enters the chat. Here&#8217;s the code:</p>
<p><code>$dbhost = "<a href="http://www.sitepoint.com/glossary.php?q=L#term_42" class="glossary" title=""Localhost" is an alias for the computer system the user is working on. It's also accessible through the 127.0.0.1 address.">localhost</a>&#8220;;<br />
$dbuser = &#8220;root&#8221;;<br />
$dbpass = &#8220;&#8221;;<br />
$dbname = &#8220;chat&#8221;;<br />
$store_num = 10;<br />
$display_num = 10;</code></p>
<p>Now we need to get on to the basics of the back end itself. A database connection is required, but we also need to make sure that Internet Explorer doesn&#8217;t <a href="http://www.sitepoint.com/glossary.php?q=C#term_21" class="glossary" title="Cache, pronounced "cash", refes to a stored copy of (or pointers to) previously accessed data. ">cache</a> the request, and that the output is treated as XML. To make sure we&#8217;re able to identify any errors in the code, we&#8217;ll set error reporting to &#8220;all errors&#8221;. And to easily work with the request data, we&#8217;ll set a variable for every parameter in the request; each variable will take as its value the value of the request parameter. These few lines do the trick:</p>
<p><code>error_reporting(E_ALL);<br />
header("Content-type: text/xml");<br />
header("Cache-Control: no-cache");<br />
$dbconn = mysql_connect($dbhost,$dbuser,$dbpass);<br />
mysql_select_db($dbname,$dbconn);<br />
foreach($_POST as $key =&gt; $value)<br />
$$key = mysql_real_escape_string($value, $dbconn);</code></p>
<p>The foreach line looks through all the POST data, and creates a variable for every parameter and assigns it a corresponding value (e.g. <code>path/to/file.php?variable=value</code> would set <code>$variable</code> to <code>"value"</code>). This simplifies the process of grabbing request data, as we don&#8217;t have to specify it manually.</p>
<p>Next we get to the main functionality. It&#8217;s at this point that we handle the insertion of messages into the database, and the retrieval of the latest few messages based on the number of messages to be displayed, as defined in <code>$display_num</code>. I mentioned when we planned the front end that we would specify an action stating that a message was being submitted. We now need to check for this action &#8212; let&#8217;s assign the parameter <code>'action'</code> a value of <code>'postmsg'</code> to specify that we&#8217;re performing this check and insert the data as a new row in the database; we&#8217;ll insert the current UNIX timestamp in the database while we&#8217;re at it.</p>
<p>However, we also need to clean out the database. Depending on your database space limits, you may want to restrict the number of posts stored. Generally, logging of messages is frowned upon, so I&#8217;ve decided to store ten messages by default. We&#8217;ll use a function to grab the id of the last inserted row, and determine the rows to delete based on the value of that <code>id</code>. For example, if we insert the eleventh message, we&#8217;ll subtract the number of stored messages (10) from the <code>id</code> of the latest one (11) which gives us the <code>id</code> threshold (in this case, 1). We can then delete all messages that have an <code>id</code> equal to or less than that threshold, which in this example would result in us deleting the first message. And, thanks to SQL, we can do this all in one query.</p>
<p>Here&#8217;s the snippet that checks for the <code>'postmsg'</code> action, inserts the message into the database, and cleans it out on the fly as well:</p>
<p><code>if(@$action == "postmsg")<br />
{<br />
mysql_query("INSERT INTO messages (`user`,`msg`,`time`)<br />
VALUES ('$name','$message',".time().")");<br />
mysql_query("DELETE FROM messages WHERE id &lt;= ".<br />
(mysql_insert_id($dbconn)-$store_num),$dbconn);<br />
}</code></p>
<p>Developers using other server side technologies should be able to write equivalent code easily enough. Notice that we call the time function to grab the current UNIX timestamp. We can safely assume that the value that time returns will probably not change during script execution (even on a slow server, this script executes in under one hundredth of a second). So when we return a timestamp to the front end later, we can just call the time function again and the value should still be reliable.</p>
<p>The code that&#8217;s left handles the job of fetching the latest messages from the database and outputting them as XML. This is where the XML I outlined above comes into play. However, the bulk of the code lies in the MySQL query. We utilize the power of SQL to handle most of the processing tasks, so that script execution time isn&#8217;t affected. Here are the requirements for our SQL query:</p>
<ul>
<li>It should fetch only the author and text of each message.</li>
<li>It should only fetch messages that have not been downloaded before &#8212; the client has a timestamp of the latest request, so this timestamp can be inserted into the SQL query.</li>
<li>It should order the messages so that the latest comes last, allowing them to be output in reverse order.</li>
<li>It should limit the number of messages fetched to the number defined in the configuration.</li>
</ul>
<p>Anyone who&#8217;s familiar with SQL will agree that this is all fairly simple stuff. For the rest of us, here&#8217;s the code that does the trick. First, the query:</p>
<p><code>$messages = mysql_query("SELECT user,msg<br />
FROM messages<br />
WHERE time&gt;$time<br />
ORDER BY id ASC<br />
LIMIT $display_num",$dbconn);</code></p>
<p>The rest of the code is elementary. If no results are returned, set the status code to 0; otherwise, set it to 1. Output the initial XML, the XML for each message, and the final XML. That&#8217;s all! Here&#8217;s the code:</p>
<p><code>if(mysql_num_rows($messages) == 0) $status_code = 2;<br />
else $status_code = 1;</p>
<p>echo "&lt;?xml version=\"1.0\"?&gt;\n";<br />
echo "&lt;response&gt;\n";<br />
echo "\t&lt;status&gt;$status_code&lt;/status&gt;\n";<br />
echo "\t&lt;time&gt;".time()."&lt;/time&gt;\n";<br />
while($message = mysql_fetch_array($messages))<br />
{<br />
echo "\t&lt;message&gt;\n";<br />
echo "\t\t&lt;author&gt;$message[user]&lt;/author&gt;\n";<br />
echo "\t\t&lt;text&gt;$message[msg]&lt;/text&gt;\n";<br />
echo "\t&lt;/message&gt;\n";<br />
}<br />
echo "&lt;/response&gt;";</code></p>
<p>The final code is all in the attached zip file, so don&#8217;t worry about copying this into your text editor. Now that the back end is finished, we can move on to the fun work &#8212; the <a href="http://www.sitepoint.com/glossary.php?q=H#term_75" class="glossary" title="HTML stands for HyperText Markup Language.">HTML</a> and jQuery!</p>
<p><strong><em><a href="http://www.sitepoint.com/glossary.php?q=C#term_15" class="glossary" title="Client-side code is sent to web browser and executed by the browser's rendering engine. ">Client-side</a> Code (HTML)</em></strong></p>
<p>Before we head into the jQuery, we need to prototype the HTML of the page. This way, when we have to work out which elements we are selecting to fetch or update using jQuery, we know what to do. We won&#8217;t need much: a wrapper div, a paragraph for the messages, and a form with fields for the user&#8217;s name and message, along with a Submit button. A briefly displayed loading message would add a final touch &#8212; we can remove this at the appropriate time using jQuery. Here&#8217;s the HTML:</p>
<p><code>&lt;div id="wrapper"&gt;<br />
&lt;p id="messagewindow"&gt;&lt;span id="loading"&gt;Loading...&lt;/span&gt;&lt;/p&gt;<br />
&lt;form id="chatform"&gt;<br />
Name: &lt;input type="text" id="author" /&gt;<br />
Message: &lt;input type="text" id="msg" /&gt;<br />
&lt;input type="submit" value="ok" /&gt;&lt;br /&gt;<br />
&lt;/form&gt;<br />
&lt;/div&gt;</code></p>
<p><strong><em><a href="http://www.sitepoint.com/glossary.php?q=C#term_15" class="glossary" title="Client-side code is sent to web browser and executed by the browser's rendering engine. ">Client-side</a> Code (jQuery)</em></strong></p>
<p>Now, on to the jQuery front end. First, we need to declare the timestamp of the current message as 0, and call the function that loads the messages from the server:</p>
<p><code>timestamp = 0;<br />
updateMsg();</code></p>
<p>Next, we&#8217;ll write the code for the form submission. jQuery allows us to add an event hook for the form&#8217;s submit event, as though we were adding an <code>onSubmit</code> event within the <a href="http://www.sitepoint.com/glossary.php?q=H#term_75" class="glossary" title="HTML stands for HyperText Markup Language.">HTML</a> itself, except that we don&#8217;t have to touch the HTML. Here&#8217;s the submit event:</p>
<p><code>$("form#chatform").submit(function(){ /* Code */ });</code></p>
<p>Here we&#8217;re using <a href="http://www.sitepoint.com/glossary.php?q=C#term_8" class="glossary" title="CSS, or Cascading Style Sheets, comprise styling and formatting rules that are applied to Web documents.">CSS</a> selector syntax to refer to the form element with an <code>id</code> of <code>'chatform'</code>. As soon as we&#8217;re into the form submission code, we can fire off a POST request to the server using jQuery&#8217;s <code>$.post</code>. Within the call to <code>$.post</code>, we can select the values of the form elements on the page on the basis of their <code>id</code>s, as we determined earlier. With this in mind, we can dive into our <a href="http://www.sitepoint.com/glossary.php?q=A#term_73" class="glossary" title="AJAX stands for Asynchronous JavaScript and XML.">Ajax</a> call:</p>
<p><code>$.post("backend.<a href="http://www.sitepoint.com/glossary.php?q=P#term_1" class="glossary" title="PHP, or Hypertext Preprocessor, is an open source, server-side programming language.">php</a>&#8220;,{ message: $(&#8221;#msg&#8221;).val(),<br />
name: $(&#8221;#author&#8221;).val(), action: &#8220;postmsg&#8221;, time: timestamp }, function(<a href="http://www.sitepoint.com/glossary.php?q=X#term_3" class="glossary" title="eXtensible Markup Language, or XML, is a text markup language designed for the easy sharing of data.">xml</a>) {</code></p>
<p>Notice that the <a href="http://www.sitepoint.com/glossary.php?q=%23#term_72" class="glossary" title="An array is a single variable with compartments, each of which can hold a value. ">array</a> of parameters to be passed in the request is enclosed with curly braces. If you have more parameters, simply separate them with commas and use the format presented here, <a href="http://www.json.org/" class="sublink">JSON-style</a>. You can also use jQuery&#8217;s Ajax functions to send a GET request that expects a JSON-style response, and have jQuery convert the response text into an easy-to-use format. Bear in mind, though, that this capability is only available for the GET request type, not the POST request type we use for our chat system. As such, we&#8217;ll stick with plain XML for the moment.</p>
<p>Now, let&#8217;s look at handling the XML response. Since we&#8217;re all for code reuse, we&#8217;ll create a function that handles the XML and call it now:</p>
<p><code>addMessages(xml);</code></p>
<p>We&#8217;ll write this function later so that we can finish off the form submission event code. The code we&#8217;ve written so far is all we need for our <code>$.post</code> callback function, so we can close it off and add a return false; line. This line fails using the standard browser form submission error code. The browser doesn&#8217;t send the user to another page to submit the form &#8212; we&#8217;ve already handled the form submission, so the browser doesn&#8217;t need to. Here&#8217;s the event code in its entirety:</p>
<p><code>$("form#chatform").submit(function(){<br />
$.post("backend.php",{<br />
message: $("#msg").val(),<br />
name: $("#author").val(),<br />
action: "postmsg",<br />
time: timestamp<br />
}, function(xml) {<br />
addMessages(xml);<br />
});<br />
return false;<br />
});</code></p>
<p>Now, let&#8217;s get back to the <code>addMessages()</code> function, which handles the response xml. It&#8217;s quite simple, making use of jQuery&#8217;s <a href="http://www.sitepoint.com/glossary.php?q=D#term_39" class="glossary" title="A DOM, or Document Object Model, is a tree representation of the structure of Web document.">DOM</a> manipulation and traversing functions. Remember that I mentioned the status code before? Now&#8217;s the time to handle it:</p>
<p><code>if($("status",xml).text() == "2") return;</code></p>
<p>I haven&#8217;t mentioned context in jQuery yet. The XML in this function call tells jQuery to look not inside the document HTML, but in the XML that the server sent us.</p>
<p>That line of code checks for a status code of 2, representing a successful request that resulted in us having no new messages to add to the window. The <code>'return'</code> keyword terminates the function call. Next, we set the timestamp to the timestamp in the XML:</p>
<p><code>timestamp = $("time",xml).text();</code></p>
<p>Again, this fetches the text value of the <code>&lt;time&gt;</code> tag in the XML.</p>
<p>Now we can move on to jQuery&#8217;s array iteration function, <code>each()</code>. jQuery has an interesting way of handling array iteration. We use a standard selector statement, and the <code>each()</code> function is passed one parameter &#8212; a function to handle each instance of the matched elements. In this case, the elements are the instances of the <code>&lt;message&gt;</code> tag in the server response, each instance representing a message to be displayed. One parameter &#8212; the <code>id</code> of the instance &#8212; is passed to the function. We can use this, with jQuery&#8217;s <code>get()</code> function, to grab a new context &#8212; the actual XML of the <code>&lt;message&gt;</code> tag. This is how we select it:</p>
<p><code> $("message",xml).each(function(id) {<br />
message = $("message",xml).get(id);</code></p>
<p>We can then select elements by passing the context <code>'message'</code> to the jQuery <code>/ $</code> function. Now that we have all the data we need, we must add it to the top of the message window on the page. The message window has the id <code>'messagewindow'</code>, so we select it using <code>$("#messagewindow")</code> and use the <code>prepend()</code> function to add our data:</p>
<p><code>$("#messagewindow").prepend("&lt;b&gt;"+$("author",message).text()+<br />
"&lt;/b&gt;: "+$("text",message).text()+<br />
"&lt;br /&gt;");</code></p>
<p>That&#8217;s all there is to it! Putting it all together, here&#8217;s the code for the function:</p>
<p><code>function addMessages(xml) {<br />
if($("status",xml).text() == "2") return;<br />
timestamp = $("time",xml).text();<br />
$("message",xml).each(function(id) {<br />
message = $("message",xml).get(id);<br />
$("#messagewindow").prepend("&lt;b&gt;"+$("author",message).text()+<br />
"&lt;/b&gt;: "+$("text",message).text()+<br />
"&lt;br /&gt;");<br />
});<br />
}</code></p>
<p>Finally, we need the <code>updateMsg</code> function we called at the very beginning of our code. This function has to query the server for new messages, and call the above <code>addMessages</code> function with the response. It also has to set a timeout to call itself after a set period of time, which makes the chat window update automatically. To begin, we don&#8217;t need to submit anything to the server besides a timestamp, so this is our <code>$.post</code> call:</p>
<p><code>$.post("backend.php",{ time: timestamp }, function(xml) {</code></p>
<p>As I noted before, we also need to remove the loading message at this point, so we call jQuery&#8217;s remove function on the span:</p>
<p><code>$("#loading").remove();</code></p>
<p>Then, we&#8217;ve received our xml response in the object <code>'xml'</code>, so we pass it to our <code>addMessages</code> function:</p>
<p><code>addMessages(xml);</code></p>
<p>We round it off with a call to the <a href="http://www.sitepoint.com/glossary.php?q=J#term_9" class="glossary" title="JavaScript is a Web scripting language most commonly used for client-side applications.">JavaScript</a> <code>setTimeout()</code> function, which executes specified code after a specified interval. Here&#8217;s the whole function put together:</p>
<p><code>function updateMsg() {<br />
$.post("backend.php",{ time: timestamp }, function(xml) {<br />
$("#loading").remove();<br />
addMessages(xml);<br />
});<br />
setTimeout('updateMsg()', 4000);<br />
}</code></p>
<p><strong><em>Putting it All Together</em></strong></p>
<p>Now we can put all of the pieces of the puzzle together. The code is, as I mentioned, available in <a href="http://www.sitepoint.com/examples/jquery/ajax-jquery-demo.zip" class="sublink">this downloadable zip file</a>. However, you can peruse it here, where I&#8217;ve added a bit of HTML and CSS for layout:</p>
<p><code>&lt;html&gt;<br />
&lt;head&gt;<br />
&lt;title&gt;Ajax with jQuery Example&lt;/title&gt;<br />
&lt;script type="text/JavaScript" src="jquery.js"&gt;&lt;/script&gt;<br />
&lt;script type="text/JavaScript"&gt;<br />
$(document).ready(function(){<br />
timestamp = 0;<br />
updateMsg();<br />
$("form#chatform").submit(function(){<br />
$.post("backend.php",{<br />
message: $("#msg").val(),<br />
name: $("#author").val(),<br />
action: "postmsg",<br />
time: timestamp<br />
}, function(xml) {<br />
$("#msg").empty();<br />
addMessages(xml);<br />
});<br />
return false;<br />
});<br />
});<br />
function addMessages(xml) {<br />
if($("status",xml).text() == "2") return;<br />
timestamp = $("time",xml).text();<br />
$("message",xml).each(function(id) {<br />
message = $("message",xml).get(id);<br />
$("#messagewindow").prepend("&lt;b&gt;"+$("author",message).text()+<br />
"&lt;/b&gt;: "+$("text",message).text()+<br />
"&lt;br /&gt;");<br />
});<br />
}<br />
function updateMsg() {<br />
$.post("backend.php",{ time: timestamp }, function(xml) {<br />
$("#loading").remove();<br />
addMessages(xml);<br />
});<br />
setTimeout('updateMsg()', 4000);<br />
}<br />
&lt;/script&gt;<br />
&lt;style type="text/css"&gt;<br />
#messagewindow {<br />
height: 250px;<br />
border: 1px solid;<br />
padding: 5px;<br />
overflow: auto;<br />
}<br />
#wrapper {<br />
margin: auto;<br />
width: 438px;<br />
}<br />
&lt;/style&gt;<br />
&lt;/head&gt;<br />
&lt;body&gt;<br />
&lt;div id="wrapper"&gt;<br />
&lt;p id="messagewindow"&gt;&lt;span id="loading"&gt;Loading...&lt;/span&gt;&lt;/p&gt;<br />
&lt;form id="chatform"&gt;<br />
Name: &lt;input type="text" id="author" /&gt;<br />
Message: &lt;input type="text" id="msg" /&gt;<br />
&lt;input type="submit" value="ok" /&gt;&lt;br /&gt;<br />
&lt;/form&gt;<br />
&lt;/div&gt;<br />
&lt;/body&gt;<br />
&lt;/html&gt;</code></p>
<p>So, with 22 lines of JavaScript, eight lines of HTML, and around 50 lines of PHP, we now have a fully functional Ajax web application. Try it out, and integrate it into your own site. Build your own Ajax application, using these techniques and your own ideas. Take this code and modify it to build something new. If you aren&#8217;t comfortable with generating and handling XML, stick with using your web application to generate HTML, and using <code>load()</code> to bring it to the client. Then, once you get the hang of it, try out an application that utilises the full power of XML using tag attributes and jQuery&#8217;s <code>attr()</code> function &#8212; you&#8217;ll be amazed at just how powerful Ajax with jQuery can be.</p>
]]></content:encoded>
			<wfw:commentRss>http://blogs.pinkcrow.net/easy-ajax-with-jquery/63/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Whip Up a Yahoo! Mashup Using PHP</title>
		<link>http://blogs.pinkcrow.net/whip-up-a-yahoo-mashup-using-php/62/</link>
		<comments>http://blogs.pinkcrow.net/whip-up-a-yahoo-mashup-using-php/62/#comments</comments>
		<pubDate>Tue, 04 Sep 2007 10:58:25 +0000</pubDate>
		<dc:creator>Valeriu Buzila</dc:creator>
		
		<category><![CDATA[Software]]></category>

		<guid isPermaLink="false">http://blogs.pinkcrow.net/whip-up-a-yahoo-mashup-using-php/62/</guid>
		<description><![CDATA[So, you want to create your own mashup? Great! Mashups &#8212; web applications that grab information from different external sources and mix it together in new and exciting ways &#8212; are fun to build, popular with users, and oh-so-very Web 2.0. 
Web services, a collection of standards and data formats that enable web applications to [...]]]></description>
			<content:encoded><![CDATA[<p><strong>So, you want to create your own mashup? Great! Mashups &#8212; web applications that grab information from different external sources and mix it together in new and exciting ways &#8212; are fun to build, popular with users, and oh-so-very Web 2.0. </strong></p>
<p>Web services, a collection of standards and data formats that enable web applications to communicate with each other and share data, are the core technology behind mashups. They allow developers to directly feed data from databases without having to resort to messy screen-scraping, and enable developers to build rich content applications that make information more useful to users.</p>
<p>These days, numerous companies publish public APIs for their various web services. In this article, I&#8217;ll show you how to use the powerful collection of Yahoo! APIs to build a mashup with <a href="http://www.sitepoint.com/glossary.php?q=P#term_1" class="glossary" title="PHP, or Hypertext Preprocessor, is an open source, server-side programming language.">PHP</a> 5. First we&#8217;ll take a look at what APIs are, and the various offerings from Yahoo! that we can take advantage of. I&#8217;ll demonstrate how to search the web using Yahoo!&#8217;s entire database with only three lines of code, then take you through the process of building an entire application to search for &#8216;Pizza&#8217; in &#8216;Palo Alto, CA&#8217; with only 25 lines of PHP code.</p>
<p>This tutorial assumes a decent knowledge of PHP 5 &#8212; specifically, that you&#8217;re comfortable with the basic syntax, classes and objects, and have some basic background on web services. Take a look at the <a href="http://en.wikipedia.org/wiki/Web_services" class="sublink">Wikipedia article on web services</a> and <a href="http://www.sitepoint.com/subcat/php-tutorials/" class="sublink">SitePoint&#8217;s other PHP tutorials</a> if you think you may have trouble with these.</p>
<h5>The Yahoo! Developer Network</h5>
<p><a href="http://developer.yahoo.com/" class="sublink">The Yahoo! Developer Network</a> is the central reference site for all Yahoo! APIs and a way of connecting with developers and enabling them to provide Yahoo!-powered services in their applications. Check it out for more in-depth reference information.</p>
<p><strong><em>Available APIs</em></strong></p>
<p>A quick glance through the sidebar of the developer network homepage reveals just how many APIs Yahoo! provides. Many of the standard Yahoo! services have public APIs available, such as <a href="http://developer.yahoo.com/search" class="sublink">Search</a>, <a href="http://developer.yahoo.com/maps/" class="sublink">Maps</a> and <a href="http://developer.yahoo.com/answers/" class="sublink">Answers</a>, and each API has its own set of documentation. A number of startups acquired by Yahoo! also provide APIs to their services, including <a href="http://del.icio.us/help/api/" class="sublink">del.icio.us</a>, <a href="http://developer.yahoo.com/flickr/" class="sublink">Flickr</a> and <a href="http://upcoming.yahoo.com/services/api/" class="sublink">Upcoming.org</a>, although each of these APIs is handled differently &#8212; check their documentation for details. Here&#8217;s a quick summary of the most popular ones.</p>
<p><strong>Flickr</strong></p>
<p>One of the most popular APIs available from Yahoo!, the Flickr web services offer access to all the photos on Flickr, photo meta data, tags and more. Popular uses of the API include visualizing locations on maps, galleries, posters and games. You can find links to examples on the <a href="http://www.flickr.com/services/" class="sublink">Flickr</a> services page including <a href="http://labs.systemone.at/retrievr/" class="sublink">Retrievr</a>, an image search engine that allows you to search for images matching your hand-drawn sketch.</p>
<p><a href="http://i2.sitepoint.com/graphics/retrievr2.thumb.png" class="beatbox"><em>Searching for images on retrievr.com (click to view image)</em><img src="http://i2.sitepoint.com/graphics/retrievr2.thumb.png" height="335" width="400" /></a></p>
<p><strong>Yahoo! Maps</strong></p>
<p>The Yahoo! maps API is extremely powerful and allows you to create interactive maps with high quality geographic imagery, adding the power of visual location to your web application. Popular applications of the API include mapping journeys and locating users. <a href="http://runningmap.com/" class="sublink">Runningmap.com</a> is an excellent example of the Yahoo! Maps API, allowing you to plot your exercise routes and check your distances and other interesting statistics.</p>
<p><a href="http://i2.sitepoint.com/graphics/markers.thumb.png" class="beatbox"><em>A map on Runningmap.com (click to view image)</em><img src="http://i2.sitepoint.com/graphics/markers.thumb.png" height="250" width="399" /></a></p>
<p><strong>Yahoo! Search</strong></p>
<p>Want to build a search function for your web site, or add related links to your web application? One of the more traditional APIs from Yahoo!, the Search API allows powerful querying of the Yahoo! web search database. Christian Langreiter offers a <a href="http://www.langreiter.com/exec/yahoo-vs-google.html" class="sublink">comparison of Yahoo and Google search results</a> in one of his mashups.</p>
<p><a href="http://i2.sitepoint.com/graphics/yahoogoogle.thumb.png" class="beatbox"><em>The application compares Yahoo! and Google results (click to view image)</em><img src="http://i2.sitepoint.com/graphics/yahoogoogle.thumb.png" height="253" width="400" /></a></p>
<p>Each API has different usage restrictions, so check the relevant guidelines before you begin to develop an application. Some APIs have rate limiting &#8212; for example, the Web Search API is restricted to 5000 queries per IP address per 24 hour period. In addition, not all APIs can be used for commercial purposes. Yahoo! requires developers to register their applications with the developer network to receive an application ID, and include this application ID in each request they make to an API. While this data doesn&#8217;t affect rate limiting, it allows Yahoo! to monitor API usage and contact developers if needed. You can <a href="http://search.yahooapis.com/webservices/register_application" class="sublink">get an application ID</a> &#8212; and you&#8217;ll need one to try out the sample code in this article.</p>
<h5>Consuming the Yahoo! APIs</h5>
<p>All the standard Yahoo! APIs are <a href="http://en.wikipedia.org/wiki/REST" class="sublink">RESTful in nature</a>; data is accessed via standard HTTP requests, where query parameters are passed to the API through the URL. What this means is that you can fetch data from the API as easily as you would fetch the <a href="http://www.sitepoint.com/glossary.php?q=H#term_75" class="glossary" title="HTML stands for HyperText Markup Language.">HTML</a> source of any web page, and you can test requests using any browser that will render <a href="http://www.sitepoint.com/glossary.php?q=X#term_3" class="glossary" title="eXtensible Markup Language, or XML, is a text markup language designed for the easy sharing of data.">XML</a>. Take this sample URL:</p>
<p><code>http://api.search.yahoo.com/WebSearchService/V1/webSearch?<br />
appid=YahooDemo&amp;query=SitePoint&amp;results=2</code></p>
<p>Try it out &#8212; <a href="http://api.search.yahoo.com/WebSearchService/V1/webSearch?appid=YahooDemo&amp;query=SitePoint&amp;results=2" class="sublink">visit the URL in your browser</a> and take a look at the XML output. Since the output is XML, however,  we need to parse the response XML with <a href="http://www.sitepoint.com/glossary.php?q=P#term_1" class="glossary" title="PHP, or Hypertext Preprocessor, is an open source, server-side programming language.">PHP</a> in order to make use of it. A number of classes and XML parsing functions are readily available for PHP, but Yahoo! goes a step further: it provides an option to get all the output data in serialized form. This means that you can quickly fetch the data, run it through the <a href="http://php.net/unserialize" class="sublink"><code>unserialize</code></a> function and start working with the data immediately. To get PHP serialized output, just append <code>&amp;output=php</code> to the query string. Here&#8217;s a simple script that searches the web for &#8220;SitePoint&#8221; using the web search API, all in three effective lines of code:</p>
<p><code>&lt;?php<br />
$output = file_get_contents(<br />
'http://api.search.yahoo.com/WebSearchService/V1/'.<br />
'webSearch?appid=your-app-id-here'.<br />
'&amp;query=SitePoint'.<br />
'&amp;results=2'.<br />
'&amp;output=php'<br />
);<br />
$output = unserialize($output);<br />
echo '&lt;code&gt;'.print_r($output,TRUE).'&lt;/code&gt;';<br />
?&gt;</code></p>
<p>Examining this snippet, we see that we first fetch the data in PHP format using the <a href="http://php.net/file_get_contents/" class="sublink"><code>file_get_contents</code></a> function, then convert it to an associative <a href="http://www.sitepoint.com/glossary.php?q=%23#term_72" class="glossary" title="An array is a single variable with compartments, each of which can hold a value. ">array</a> with unserialize, before outputting a dump of the array with <code>print_r</code>. I should note here that to be able to use <code>file_get_contents</code> to open a URL requires the  <code>allow_url_fopen</code> setting to be enabled in <code>php.ini</code>. Check with your host if you&#8217;re not sure if this setting is in place. Let&#8217;s take a look at the output.  <code>$output['ResultSet']['Result']</code> contains the data we&#8217;re looking for. Here&#8217;s  a snippet of the first search result:</p>
<p><code>[Title] =&gt; SitePoint : New Articles, Fresh Thinking for Web Developers and Designers<br />
[Summary] =&gt; Network of sites that provice information, tools, and resources for internet-focused businesses and web developers, including WebmasterBase.com, eCommerceBase.com, and PromotionBase.com.<br />
[Url] =&gt; http://www.sitepoint.com/</code></p>
<p>Compare this with the first result for the term &#8220;SitePoint&#8221; on the official Yahoo! Search site and you&#8217;ll see it&#8217;s the same.</p>
<p><a href="http://i2.sitepoint.com/graphics/searchresult.thumb.png" class="beatbox"><em>Result for a search on  (click to view image)</em><img src="http://i2.sitepoint.com/graphics/searchresult.thumb.png" height="48" width="400" /></a></p>
<p>All the data you would normally get through a Yahoo! search is available through the API! Forget messy screen scraping &#8212; Yahoo! makes it easy to get the search results directly. With another few lines of code, we can turn our array into a full search results page. You can probably already see how to make a search engine with the Yahoo! web search API here &#8212; it&#8217;s that simple! Building your own search engine from scratch would usually involve buying a data centre and spending years spidering the web, but Yahoo! provides all the data free of charge (with usage restrictions, of course). You may have heard of <a href="http://rollyo.com/" class="sublink">rollyo.com</a>, a site that lets you create your search engine. Well, Rollyo is built using the Yahoo! APIs. With just a few lines of PHP, we can query the Yahoo! web search API, parse the API output, extract the data, format it and output it &#8212; that&#8217;s a lot of power to have available at your fingertips.</p>
<p>Most of the Yahoo! APIs are just as easy to use as Web Search, and Yahoo! provides a <a href="http://developer.yahoo.com/search/rest.html" class="sublink">guide to constructing REST queries</a> if you need further information about fetching data from the APIs. Each API method has a documentation page outlining the parameters available, return values, possible output formats (XML, PHP, etc.) and potential errors. It should be noted that all parameters are URL encoded, so <code>php code</code> should become <code>php+code</code>, or the API may return unexpected output. PHP&#8217;s inbuilt <a href="http://php.net/urlencode" class="sublink"><code>urlencode</code></a> function is sufficient for this task. As a general guide, each service has a base URL something like the following:</p>
<p><code>http://api.search.yahoo.com/WebSearchService/V1/webSearch</code></p>
<p>Each service requires certain parameters, one of which will be your application ID, and most services will have a query parameter. In the previous example search, we use the parameters <code>appid</code>, <code>query</code>, <code>results</code> and <code>output</code>. In this case, <code>appid</code> is the application ID, <code>query</code> is what we are searching for (&#8221;SitePoint&#8221;) and <code>output</code> is the format we want the API output in (<code>php</code> for serialized PHP form, optional). The <code>results</code> parameter is optional, however I use it here to limit the output to two search results in order to reduce server load. If you don&#8217;t need the standard 10 results, limiting the output through the results parameter is highly advisable. We append a question mark and the parameters to the URI, separating each parameter with an ampersand (<code>&amp;</code>)  and using the standard <code>option=value</code> format, just like any other HTTP request.</p>
<p>So now that you&#8217;ve had a gentle introduction to the usage of Yahoo! APIs, how they behave and what they provide access to, let&#8217;s take things up a notch and look at how we can actually put these APIs to good use.</p>
<h5>PHP 5 and the Yahoo! APIs</h5>
<p>PHP 5 has a number of features that help us make effective use of the Yahoo! APIs. PHP 5&#8217;s improved internal <a href="http://www.sitepoint.com/glossary.php?q=O#term_10" class="glossary" title="An programming methodology involving the building of abstracted code objects designed to interact with each other. ">OOP</a> support enables developers to efficiently build applications, and we can take advantage of this by using classes to rapidly develop libraries that make use of the Yahoo! APIs. The introduction of the <code>file_get_contents</code> function allows easy querying of the APIs, and as I mentioned before, PHP has the added advantage of receiving serialized output from most of the APIs with inbuilt parsing functions. Even though the <a href="http://php.net/manual/en/ref.http.php" class="sublink">HTTP extension</a> is available in PHP 5, we won&#8217;t need it for low-end API consumption. PHP 5 developers can easily query the APIs, parse the output, deal with errors and make use of the data without too much trouble.</p>
<p><strong><em>Quick and Easy Mashups</em></strong></p>
<p>To demonstrate the power of the Yahoo! APIs, we&#8217;re going to put together a very simple, practical application using PHP 5 and various Yahoo! APIs. What we want to do is query the local search API for data from Yahoo! Local, where users discuss and rate local attractions, businesses and so on. Then we&#8217;ll place that data on a map, showing geographically where those attractions are located.</p>
<p><strong>YahooAPI Client Class in PHP 5</strong></p>
<p>To make our lives easier, we&#8217;re going to use a PHP class that helps us to query the Yahoo! APIs. The base class needs to have the following functionality:</p>
<ul>
<li>Set the web service to be used.</li>
<li>Add parameters to the request.</li>
<li>Execute the call to the remote API.</li>
<li>Fetch the output.</li>
</ul>
<p>I&#8217;ve built a very simple, extensible class to do just this, called <code>YahooAPI</code> &#8212; take a look in the <a href="http://www.sitepoint.com/examples/yahooapi/YahooAPIarchive.zip" class="sublink">code archive for this article</a>. While I won&#8217;t go into the details of the <code>YahooAPI</code> class, using it is very easy. In the previous example we searched for &#8220;SitePoint&#8221; on the Web. The same task can be achieved very easily with the class:</p>
<p><code>$api = new YahooAPI();<br />
$api-&gt;setAppID('your-app-id-here');<br />
$api-&gt;setService('http://api.search.yahoo.com/WebSearch<br />
Service/V1/'.<br />
'webSearch');<br />
$api-&gt;setParam('output','php');<br />
$api-&gt;setParam('query','SitePoint');<br />
$api-&gt;setParam('results','2');<br />
$output = $api-&gt;doAPICall();</code></p>
<p>This is exactly the same as the previous search example, except that now we use the client class. In this case, using the class is more verbose, but with more complex and repeated calls to the API, using the class can save time and simplify maintenance.</p>
<p><strong>Manipulating Data from API Calls</strong></p>
<p>Now that we have everything we need to get to work, I&#8217;ll show you how to easily manipulate data from the Yahoo! APIs.</p>
<p>Let&#8217;s use our new YahooAPI class to search for &#8216;Pizza&#8217; in &#8216;Palo Alto, CA&#8217; using the Local Search API. Take a look at <a href="http://developer.yahoo.com/search/local/V3/localSearch.html" class="sublink">the documentation page</a> for the latest version of the local search API. This is the base URL for the service:</p>
<p><code>http://local.yahooapis.com/Local<br />
SearchService/V3/localSearch</code></p>
<p>So we&#8217;ll call the <code>setService</code> method of the <code>YahooAPI</code> class and give it the base URL. Looking through the request parameters in the documentation, we&#8217;ll need to submit the <code>'appid'</code>, <code>'query'</code> and <code>'location'</code> parameters. After we set the required application ID, we then need to choose a location &#8212; we&#8217;ll use a city and state for now &#8212; and a query. Let&#8217;s say we&#8217;re searching for &#8216;Pizza&#8217; in &#8216;Palo Alto, CA&#8217;. In simple, procedural PHP code using the <code>YahooAPI</code> class, the search would look something like this:</p>
<p><code>$api = new YahooAPI();<br />
$api-&gt;setService('http://local.yahooapis.com/LocalSearch<br />
Service/V3/'.<br />
'localSearch');<br />
$api-&gt;setAppID('your-app-id-here');<br />
$api-&gt;setParam('output','php');<br />
$api-&gt;setParam('query','pizza');<br />
$api-&gt;setParam('location','Palo Alto, CA');<br />
$output = $api-&gt;doAPICall();</code></p>
<p>The call to the API here is the same as fetching</p>
<p><code>http://local.yahooapis.com/LocalSearch<br />
Service/V3/localSearch?appid=your-app-id-here&amp;<br />
query=pizza&amp;location=Palo+Alto,+CA</code></p>
<p>through any method, so take a look at that URL in your web browser. Clearly the information we&#8217;re looking for is within each <code>&lt;Result&gt;</code> node, and all <code>&lt;Result&gt;</code> nodes are within one big <code>&lt;ResultSet&gt;</code> node. The PHP version that we&#8217;re fetching has exactly the same structure as the XML, except that it&#8217;s in an easily usable array. After fetching all that data into the <code>$output</code> variable, all we have to do is iterate over the <code>$output['ResultSet']['Result']</code> elements and fetch the data we need. Try it out &#8212; add the following code after the previous example and run it on your web server:</p>
<p><code>foreach($output['ResultSet']['Result'] as $result) {<br />
echo $result['Title'].'&lt;br/&gt;';<br />
}</code></p>
<p>You should receive something like the following output:</p>
<p><code>Patxi's Chicago Pizza<br />
Papa Murphys Pizza Take &amp; Bake<br />
New York Pizza<br />
Round Table Pizza Palo Alto<br />
Domino's Pizza<br />
California Pizza Kitchen<br />
Pizza My Heart<br />
Ramonas Pizza<br />
Round Table Pizza Palo Alto<br />
Spot A Pizza</code></p>
<p><strong><code>LocalSearch</code> Client Class in <a href="http://www.sitepoint.com/glossary.php?q=P#term_1" class="glossary" title="PHP, or Hypertext Preprocessor, is an open source, server-side programming language.">PHP</a> 5</strong></p>
<p>Now let&#8217;s extend the <code>YahooAPI</code> class to query the Yahoo! Local Search API. We can easily create a class that manages all this work for us. Instead of the previous procedural code, if we extend the <code>YahooAPI</code> class  and create some appropriately-named methods &#8212; for example <code>locationSearch($query, $location)</code> &#8212; we can further simplify the process of interacting with the APIs.</p>
<p>I&#8217;ve written an example class that generally covers everything we need for interacting with the Local Search API. It has three main methods: <code>locationSearch</code>, <code>positionSearch</code> and <code>extractResults</code>. Here&#8217;s the code:</p>
<p><code>&lt;?php<br />
require_once('yahooapi.class.php');<br />
class LocalSearch extends YahooAPI<br />
{</code></p>
<p>The constructor method sets the basic properties we&#8217;ll always need for each Local Search API request:</p>
<p><code>  public function __construct()<br />
{<br />
$this-&gt;setParam('output','php');<br />
$this-&gt;setService('http://local.yahooapis.com/'.<br />
'LocalSearchService/V3/localSearch');<br />
$this-&gt;setAppID('your-app-id-here');<br />
}</code></p>
<p>The two search methods represent different ways of performing a search, depending on whether or not we have a location name or exact GPS coordinates. They simply set the required parameters and call the <code>doAPICall</code> method of the parent <code>YahooAPI</code> class:</p>
<p><code>  public function locationSearch($query,$in_location)<br />
{<br />
$this-&gt;setParam('query',$query);<br />
$this-&gt;setParam('location',$in_location);<br />
return $this-&gt;doAPICall();<br />
}</p>
<p>public function positionSearch($lat,$long)<br />
{<br />
$this-&gt;setParam('query','*');<br />
$this-&gt;setParam('latitude',$lat);<br />
$this-&gt;setParam('longitude',$long);<br />
return $this-&gt;doAPICall();<br />
}</code></p>
<p>The <code>extractResults</code> method saves us entering <code>['ResultSet']['Result']</code> all the time when we want to output the results, because the data we need will always be within that part of the returned <a href="http://www.sitepoint.com/glossary.php?q=%23#term_72" class="glossary" title="An array is a single variable with compartments, each of which can hold a value. ">array</a>:</p>
<p><code>  public function extractResults()<br />
{<br />
$return = $this-&gt;getResults();<br />
$return = $return['ResultSet']['Result'];<br />
return $return;<br />
}<br />
}<br />
?&gt;</code></p>
<p>You&#8217;ll find a copy of the code in <a href="http://www.sitepoint.com/examples/yahooapi/YahooAPIarchive.zip" class="sublink">the archive for the article</a>. Keep it handy because we&#8217;ll be using it in our example mashup. We&#8217;ll also build a similar class for the Maps API later, as it has some slightly different requirements.</p>
<p>Our example &#8220;pizza&#8221; search, executed using our new <code>LocalSearch</code> class, now looks like this:</p>
<p><code>require_once('localsearch.class.php');</p>
<p>$localSearch = new LocalSearch();<br />
$localSearch-&gt;locationSearch('Pizza','Palo Alto, CA');<br />
$output = $localSearch-&gt;extractResults();</code></p>
<p>That&#8217;s much easier, don&#8217;t you think?</p>
<p><strong>Yahoo! Maps <a href="http://www.sitepoint.com/glossary.php?q=A#term_73" class="glossary" title="AJAX stands for Asynchronous JavaScript and XML.">AJAX</a> API</strong></p>
<p>Perform a quick web search and you could find the web sites for these pizza places, each of which would list the restaurant&#8217;s address. But why would you go to all that trouble when Yahoo! provides all this data in the returned array &#8212; as well as latitude and longitude information? Here&#8217;s an example of the data returned:</p>
<p><code>[Title] =&gt; Patxi's Chicago Pizza<br />
[Address] =&gt; 441 Emerson St<br />
[City] =&gt; Palo Alto<br />
[State] =&gt; CA<br />
[Phone] =&gt; (650) 473-9999<br />
[Latitude] =&gt; 37.445265<br />
[Longitude] =&gt; -122.163432</code></p>
<p>Now that we have the location information, we need to figure out how to plot it on a map. Yahoo! provides <a href="http://developer.yahoo.com/maps/rest/V1/mapImage.html" class="sublink">a map image API</a>, offering raw images of maps in <a href="http://www.sitepoint.com/glossary.php?q=P#term_26" class="glossary" title="PNG stands for Portable Network Graphics, and is an image file format for loss-less compression of images.">PNG</a> format, and (in theory) we could use GD to draw markers on the map. However, since we&#8217;re building a web application, we can instead use the <a href="http://developer.yahoo.com/maps/ajax/index.html" class="sublink">Maps AJAX API</a> to generate a <a href="http://www.sitepoint.com/glossary.php?q=U#term_67" class="glossary" title="A User Interface (UI) is the face or shopfront  through which a user interacts with an application.">UI</a>-friendly, interactive Yahoo! maps display. We can then add markers to the map in preset positions, using the bundled functions. (Note that the Maps AJAX API isn&#8217;t really an Ajax API! In fact, there isn&#8217;t any real Ajax at all &#8212; that is, there are no XMLHttpRequest calls &#8212; but due to the fact that the term Ajax has come to represent any web page technology that uses <a href="http://www.sitepoint.com/glossary.php?q=J#term_9" class="glossary" title="JavaScript is a Web scripting language most commonly used for client-side applications.">JavaScript</a> and doesn&#8217;t need to reload the web page to update itself, Ajax would be the best way to describe it.)</p>
<p>Unlike the other Yahoo! APIs, the Maps AJAX API isn&#8217;t a REST-based web service. Instead, you have to include a JavaScript file on your page, create an instance of the map in a container on the page (usually a <code>&lt;div&gt;</code>) and manipulate it through JavaScript calls. Luckily, the HTML and JavaScript required are quite simple. Take a look at the <code>mapoutput.php</code> example in <a href="http://www.sitepoint.com/examples/yahooapi/YahooAPIarchive.zip" class="sublink">the code archive</a>. This is all the JavaScript you&#8217;ll need to generate the map:</p>
<p><code>var ymap = new YMap(document.getElementById('mC'),YAHOO_MAP_REG);<br />
var mPoint = new YGeoPoint(37.4041960114344,-122.008194923401);<br />
ymap.drawZoomAndCenter(mPoint, 3);<br />
var marker = new YMarker(mPoint);<br />
marker.addLabel('A');<br />
marker.addAutoExpand('&lt;div class="mp"&gt;Some Text&lt;/div&gt;');<br />
ymap.addOverlay(marker);</code></p>
<p>The first line creates a new instance of the <code>YMap</code> class, and assigns it to the element on the page with an ID of <code>'mC'</code>. The second argument represents the desired map type, in this case a regular map rather than satellite imagery, <code>YAHOO_MAP_SAT</code>, or a hybrid of the two, <code>YAHOO_MAP_HYB</code>. The second line creates a <code>YGeoPoint</code> object, a point on the map based on latitude and longitude coordinates, while the third line calls the map object and tells it to centre itself on this new point and display the map, at a zoom level of 3.</p>
<p>The final three lines of JavaScript create a <code>YMarker</code> object, a visual map marker that expands to reveal some extra content when it&#8217;s moused over. Our challenge is to generate all this with PHP, and to make the job easy, we&#8217;re going to build a class that generates all the code for us.</p>
<h5>Mashup Time!</h5>
<p>Now that we&#8217;ve sorted out how to query the APIs and deal with the data, it&#8217;s mashup time! As I mentioned before, we&#8217;ll create a simple application that finds places with the local search API and, using the latitude and longitude coordinates from the returned search data, marks the exact locations of these places on a map from the maps API. And of course we&#8217;ll wrap all the functionality up in a simple PHP class. The AJAX map API uses JavaScript code, so we&#8217;ll use our PHP class to generate the required JavaScript based on the returned search data.</p>
<p>First, we&#8217;ll start by querying the Maps API. I&#8217;ll use the client class for the local search API, which I demonstrated earlier, to execute this sample query: &#8216;Pizza&#8217; in &#8216;Palo Alto, CA&#8217;. We need an instance of the <code>LocalSearch</code> class, and we&#8217;ll use its locationSearch method to execute the API query. The <code>extractResults</code> method will give us the data that we want to work with. Now that we&#8217;ve built our client classes, all this can be achieved in three lines of code:</p>
<p><code>$localSearch = new LocalSearch();<br />
$localSearch-&gt;locationSearch('Pizza','Palo Alto, CA');<br />
$apiOutput = $localSearch-&gt;extractResults();</code></p>
<p>Let&#8217;s take a step back for a moment and call <code>print_r($apiOutput)</code> to see what we have. The array <code>$apiOutput</code> now contains a number of sub-<a href="http://www.sitepoint.com/glossary.php?q=%23#term_72" class="glossary" title="An array is a single variable with compartments, each of which can hold a value. ">arrays</a>, each of which is a single search result and contains (among other things) a &#8216;Title&#8217;, &#8216;Latitude&#8217; and &#8216;Longitude&#8217;. That&#8217;s all we need for the moment, so let&#8217;s quickly extract this information and delete the rest:</p>
<p><code>foreach($apiOutput as $id =&gt; $result)<br />
{<br />
$points[$id] = array($result['Title'],<br />
$result['Latitude'],<br />
$result['Longitude']);<br />
}</code></p>
<p>Here are some sample values from our newly defined <code>$points</code> array:</p>
<p><code>[0] =&gt; Array<br />
(<br />
[0] =&gt; Patxi's Chicago Pizza<br />
[1] =&gt; 37.445265<br />
[2] =&gt; -122.163432<br />
)</p>
<p>[1] =&gt; Array<br />
(<br />
[0] =&gt; Papa Murphys Pizza Take &amp; Bake<br />
[1] =&gt; 37.433243<br />
[2] =&gt; -122.129291<br />
)</code></p>
<p>For each marker we want to put on our map, we need to know its position, and we need some summary text that we can have appear when the user mouses over it. In this case, when visitors mouse over one of our markers, we&#8217;ll show them the name of the place.</p>
<p>Now that we have all our locality information, we come to the tricky bit &#8212; generating the map HTML and JavaScript. Basically, our map code consists of two distinct sections &#8212; the <code>&lt;head&gt;</code> HTML and <a href="http://www.sitepoint.com/glossary.php?q=C#term_8" class="glossary" title="CSS, or Cascading Style Sheets, comprise styling and formatting rules that are applied to Web documents.">CSS</a> (for the map container), and the <code>&lt;body&gt;</code> HTML and JavaScript. The <code>&lt;body&gt;</code> includes the container <code>&lt;div&gt;</code> for the map and some JavaScript for the Maps AJAX API. For each marker we want to add to the map, we need a JavaScript <code>YGeoPoint</code> object to define its position, and a <code>YMarker</code> object to be the marker itself. We then customise the marker through the <code>addLabel</code> and <code>addAutoExpand</code> methods (many more are <a href="http://developer.yahoo.com/maps/ajax/V3/reference.html#YMarker" class="sublink">documented here</a>) before placing it on the map using the map object&#8217;s <code>addOverlay</code> method. We&#8217;ll now create a PHP class that takes care of generating all of this JavaScript code, and call it <code>AjaxMap</code>.</p>
<p>Here&#8217;s a summary of the methods our class will have:</p>
<ul>
<li><code>getHeadHTML</code> for generating <code>&lt;head&gt;</code> code</li>
<li><code>getMapScript</code> for generating <code>&lt;body&gt;</code> code</li>
<li><code>initMarker</code> for generating code for each marker</li>
</ul>
<p>We&#8217;ll also add some helper methods for customising the map:</p>
<ul>
<li><code>setMapType</code> for choosing between maps, satellite images, and hybrids</li>
<li><code>setMapContainer</code> for setting the ID of the map container <code>&lt;div&gt;</code></li>
<li><code>addMarker</code> for adding markers to the map</li>
</ul>
<p>Let&#8217;s begin our <code>AjaxMap</code> class:</p>
<p><code>&lt;?<a href="http://www.sitepoint.com/glossary.php?q=P#term_1" class="glossary" title="PHP, or Hypertext Preprocessor, is an open source, server-side programming language.">php</a><br />
require_once(&#8217;yahooapi.class.php&#8217;);<br />
class AjaxMap<br />
{<br />
private $mapContainer;<br />
private $mapType;<br />
private $markers = <a href="http://www.sitepoint.com/glossary.php?q=%23#term_72" class="glossary" title="An array is a single variable with compartments, each of which can hold a value. ">array</a>();<br />
public $showZoom;<br />
public $showPan;</code></p>
<p>We begin by including the <code>YahooAPI</code> class, which we&#8217;ll use to generate the Yahoo! API calls. Our class has three private properties: <code>$mapContainer</code> will contain the ID of the <a href="http://www.sitepoint.com/glossary.php?q=H#term_75" class="glossary" title="HTML stands for HyperText Markup Language.">HTML</a> element acting as the map container, <code>$mapType</code> will represent the type of map desired and must be one of <code>YAHOO_MAP_REG</code>, <code>YAHOO_MAP_SAT</code> or <code>YAHOO_MAP_HYB</code>, and the final private property, <code>$markers</code> will contain an array of map location markers. The API offers the ability to add zoom and pan controls, so we&#8217;ll add the public properties <code>$showZoom</code> and <code>$showPan</code>, which can be set to <code>true</code> when required.</p>
<p>So, first to the easy methods: <code>getHeadHTML</code>, the set functions and <code>addMarker</code>. All the <code>getHeadHTML</code> method needs to do is return a <code>&lt;script&gt;</code> tag referencing the Yahoo! <a href="http://www.sitepoint.com/glossary.php?q=A#term_73" class="glossary" title="AJAX stands for Asynchronous JavaScript and XML.">AJAX</a> Map API:</p>
<p><code>public function getHeadHTML()<br />
{<br />
return '&lt;script type="text/<a href="http://www.sitepoint.com/glossary.php?q=J#term_9" class="glossary" title="JavaScript is a Web scripting language most commonly used for client-side applications.">javascript</a>&#8221; &#8216;.<br />
&#8217;src=&#8221;http/api.maps.yahoo.com/ajaxymap?v=3.0&amp;appid=your-app<br />
-id-here&#8221;&gt;&#8217;.<br />
&#8220;&lt;/script&gt;\n&#8221;;<br />
}</code></p>
<p>The set functions are just as simple &#8212; they act as wrapper methods for modifying private properties. Here&#8217;s the code:</p>
<p><code>  public function setMapContainer($id)<br />
{<br />
$this-&gt;mapContainer = $id;<br />
}<br />
public function setMapType($type)<br />
{<br />
$this-&gt;mapType = $type;<br />
}</code></p>
<p>The <code>addMarker</code> method will add a new map marker entry to the private $markers array and takes a latitude value, a longitude value and description text as its arguments:</p>
<p><code>  public function addMarker($lat,$long,$descr)<br />
{<br />
$this-&gt;markers[] = array($lat,$long,$descr);<br />
}</code></p>
<p><code>initMarker</code> is a private method called for each of the desired map markers and generates the JavaScript code required for the marker:</p>
<p><code>  private function initMarker($id,$lat,$long,$descr,$init_geo = TRUE)<br />
{<br />
$js = '';<br />
if($init_geo) $js .= "\nvar mPoint$id = ".<br />
"new YGeoPoint($lat,$long);\n";<br />
$js .= "var currmarker = new YMarker(mPoint$id);\n";<br />
$js .= "currmarker.addLabel('$id');\n";<br />
$js .= "currmarker.addAutoExpand('&lt;div class=\"mp\"&gt;".<br />
addslashes($descr)."&lt;/div&gt;');\n";<br />
$js .= "ymap.addOverlay(currmarker);\n\n";<br />
return $js;<br />
}</code></p>
<p><code>initMarker</code> takes all the information about the marker &#8212; latitude and longitude for position, a short description and some notes, plus a unique <code>'id'</code> parameter &#8212; and generates the JavaScript we need in order to draw the marker. The <code>$init_geo</code> parameter for <code>initMarker</code> indicates whether or not we need to create a <code>YGeoPoint</code> object for the marker; this may already have been done.</p>
<p>All that&#8217;s left to do is bring everything together within the main JavaScript block. The <code>getMapScript</code> method will generate this JavaScript and assign it to the <code>$js</code> variable:</p>
<p><code>  public function getMapScript()<br />
{<br />
$js = '';</code></p>
<p>First, we have to initialise a <code>YMap</code> object. This is our main map object which will handle the drawing and customisation of the map. The first part is simple &#8212; we output the code required to create a new <code>YMap</code> object:</p>
<p><code>    $js .= 'var ymap = new YMap(document.getElementById(\''.<br />
$this-&gt;mapContainer.'\'),'.$this-&gt;mapType.");\n";</code></p>
<p>In this instance, the properties <code>$mapContainer</code> and <code>$mapType</code> include the relevant information about the map, so <code>setMapType</code> and <code>setMapContainer</code> should be called before <code>getMapScript</code>.</p>
<p>Next, we output the JavaScript to add the zoom and pan controls if <code>$showZoom</code> and <code>$showPan</code> are set to <code>true</code>. To add a zoom control in JavaScript, we use the <code>addZoomShort</code> method of the <code>YMap</code> object, and <code>addPanControl</code> for a pan control:</p>
<p><code>    if($this-&gt;showZoom) $js .= "ymap.addZoomShort();\n";<br />
if($this-&gt;showPan) $js .= "ymap.addPanControl();\n";</code></p>
<p>We may have a number of markers to display, but the map can only be centred on one of them. To keep it simple, we&#8217;ll remove the last marker from the main set of markers, centre the map on it and draw it on the map before proceeding to draw the remaining markers. Obviously, none of this is needed if no markers are to be drawn on the map, so we check that markers exist here too. Here&#8217;s the code that outputs the JavaScript required for centring the map on the last marker, and drawing that marker:</p>
<p><code>    if(count($this-&gt;markers) &gt; 0)<br />
{<br />
$lastmarker = array_pop($this-&gt;markers);<br />
$js .= 'var mPoint'.count($this-&gt;markers).' = new YGeoPoint('.<br />
$lastmarker[0].','.$lastmarker[1].");\n";</p>
<p>$js .= 'ymap.drawZoomAndCenter(mPoint'.count($this-&gt;markers).<br />
", 3);\n";</p>
<p>$js .= $this-&gt;initMarker(count($this-&gt;markers), $lastmarker[0],<br />
$lastmarker[1], $lastmarker[2],<br />
FALSE);</code></p>
<p>First we check if there are more than <code>0</code> markers (that is, we see if any have been set), and if so, extract the last of these markers and use that marker&#8217;s data to write the JavaScript required to create a new <code>YGeoPoint</code> object. We then output the JavaScript required to draw the map, centre it on our last marker and set the zoom level to 3. In JavaScript, we do this via the <code>drawZoomAndCenter</code> method of the <code>YMap</code> object. We then call our <code>initMarker</code> function to generate the rest of the JavaScript, and through its last parameter, tell it not to output the JavaScript to create a <code>YGeoPoint</code> object, as we&#8217;ve already taken care of it.</p>
<p>Finally, we generate the code for each remaining marker by quickly iterating over the markers array, calling <code>initMarker</code> for each one and returning the <code>$js</code> string variable:</p>
<p><code>      foreach($this-&gt;markers as $id=&gt;$obj)<br />
{<br />
$js .= $this-&gt;initMarker($id,$obj[0],$obj[1],$obj[2],TRUE);<br />
}<br />
}<br />
return $js;<br />
}<br />
}<br />
?&gt;</code></p>
<p>That also represents the end of our <code>AjaxMap</code> class!</p>
<p>Now we just have to use our local search class and <code>AjaxMap</code> class in a proper application. I&#8217;ve put together a quick demonstration. First we need to include our two classes:</p>
<p><code>&lt;?php<br />
require_once('localsearch.class.php');<br />
require_once('ajaxmap.class.php');</code></p>
<p>Next, we use our local search class to search for &#8220;pizza&#8221;. We collect the locations from our search results and store them in an array called <code>$points</code>:</p>
<p><code>$localSearch = new LocalSearch();<br />
$localSearch-&gt;locationSearch('Pizza','Palo Alto, CA');<br />
$apiOutput = $localSearch-&gt;extractResults();</p>
<p>foreach($apiOutput as $id =&gt; $result)<br />
{<br />
$points[$id] = array($result['Title'],<br />
$result['Latitude'],<br />
$result['Longitude']);<br />
}<br />
unset($apiOutput);</code></p>
<p>We then create a new <code>AjaxMaps</code> object and add to it all our locations:</p>
<p><code>$ajaxMap = new AjaxMap();<br />
$ajaxMap-&gt;setMapContainer('mC');<br />
$ajaxMap-&gt;setMapType('YAHOO_MAP_REG');<br />
$ajaxMap-&gt;showPan = true;<br />
$ajaxMap-&gt;showZoom = true;</p>
<p>foreach($points as $point)<br />
{<br />
$ajaxMap-&gt;addMarker($point[1],$point[2],$point[0]);<br />
}<br />
?&gt;</code></p>
<p>Now that all our location markers have been added to our <code>AjaxMap</code> object, the only task that&#8217;s left to do is write the page HTML and output the JavaScript:</p>
<p><code>&lt;!DOCTYPE html public "-//<a href="http://www.sitepoint.com/glossary.php?q=W#term_49" class="glossary" title="The World Wide Web Consortium (W3C) - A consortium of industry leaders for drafting Web standards.">W3C</a>//DTD <a href="http://www.sitepoint.com/glossary.php?q=X#term_63" class="glossary" title="XHTML is a reformulation of HTML 4 as an XML 1.0 application.">XHTML</a> 1.0 Transitional//EN&#8221;<br />
&#8220;http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd&#8221;&gt;<br />
&lt;html xmlns=&#8221;http://www.w3.org/1999/xhtml&#8221;&gt;<br />
&lt;head&gt;<br />
&lt;?php echo $ajaxMap-&gt;getHeadHTML(); ?&gt;<br />
&lt;style&gt;<br />
#mC {<br />
height: 500px;<br />
width: 500px;<br />
}<br />
.mp {<br />
width:160px;<br />
height:50px;<br />
}<br />
&lt;/style&gt;<br />
&lt;/head&gt;<br />
&lt;body&gt;<br />
&lt;div id=&#8221;mC&#8221;&gt;&lt;/div&gt;<br />
&lt;script type=&#8221;text/javascript&#8221;&gt;<br />
&lt;?php echo $ajaxMap-&gt;getMapScript(); ?&gt;<br />
&lt;/script&gt;<br />
&lt;/body&gt;<br />
&lt;/html&gt;</code></p>
<p>The entire script is available in the code archive. Set your application IDs, load it up on your web server, and with any luck you should see something like this:</p>
<p><a href="http://i2.sitepoint.com/graphics/pizzalocations.thumb.png" class="beatbox"><em>Our app in action! (click to view image)</em><img src="http://i2.sitepoint.com/graphics/pizzalocations.thumb.png" height="303" width="400" /></a></p>
<p>Congratulations! You&#8217;ve just built a mashup using the Yahoo! APIs. With a bit of tweaking, you could add search functionality, allowing the user to look for more than just &#8216;Pizza&#8217; in &#8216;Palo Alto, CA&#8217;. You could even integrate the functionality into an existing application (although be aware of the terms of use for both APIs). The possibilities are endless.</p>
<h5>Where to From Here?</h5>
<p>As you can see, exploiting the Yahoo! APIs with PHP5 to create useful mashups is a piece of cake, and there are many interesting applications that can be built with the data. Rasmus Lerdorf himself has written <a href="http://toys.lerdorf.com/archives/35-GeoCool%21.html" class="sublink">a similar article</a>, taking a more in depth look at the Yahoo! Geocoding API, and how to easily use it with PHP5. It&#8217;s also worth noting that while we&#8217;ve used the <code>output=php</code> parameter throughout this article, most of the APIs also offer JSON output for use via Ajax. The <a href="http://developer.yahoo.com/php/" class="sublink">Yahoo! Developer Network&#8217;s PHP Developer Center</a> has an excellent collection of tutorials, code samples and other resources for consuming the APIs with PHP5.</p>
<p>Also check out <a href="http://gallery.yahoo.com/" class="sublink">Yahoo&#8217;s Application Gallery</a> for inspiration and to see some great web apps built with various Yahoo! APIs, If you build an interesting application, submit it to the gallery for some excellent exposure and useful feedback</p>
]]></content:encoded>
			<wfw:commentRss>http://blogs.pinkcrow.net/whip-up-a-yahoo-mashup-using-php/62/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Generating Spreadsheets with PHP and PEAR</title>
		<link>http://blogs.pinkcrow.net/generating-spreadsheets-with-php-and-pear/61/</link>
		<comments>http://blogs.pinkcrow.net/generating-spreadsheets-with-php-and-pear/61/#comments</comments>
		<pubDate>Tue, 04 Sep 2007 10:52:50 +0000</pubDate>
		<dc:creator>Valeriu Buzila</dc:creator>
		
		<category><![CDATA[Software]]></category>

		<guid isPermaLink="false">http://blogs.pinkcrow.net/generating-spreadsheets-with-php-and-pear/61/</guid>
		<description><![CDATA[In the last article Getting Started with PEAR, you got the PEAR Package Manager up and running. Now, it’s time to put PEAR to good use with PEAR::Spreadsheet_Excel_Writer, a library for generating Excel spreadsheets.
Here’s what we’ll cover today:

Introducing PEAR::Spreadsheet_Excel_Writer
Finding your way around: introducing the API
Adding Cell Formatting: eye candy matters
Adding Excel Functions: C1 + D1 [...]]]></description>
			<content:encoded><![CDATA[<p><strong>In the last article <a href="http://www.sitepoint.com/article/getting-started-with-pear" rel="external" class="sublink">Getting Started with PEAR</a>, you got the PEAR Package Manager up and running. Now, it’s time to put <a href="http://pear.php.net/" rel="external" class="sublink">PEAR</a> to good use with <a href="http://pear.php.net/Spreadsheet_Excel_Writer" rel="external" class="sublink">PEAR::Spreadsheet_Excel_Writer</a>, a library for generating Excel spreadsheets.</strong></p>
<p>Here’s what we’ll cover today:</p>
<ul>
<li>Introducing PEAR::Spreadsheet_Excel_Writer</li>
<li>Finding your way around: introducing the API</li>
<li>Adding Cell Formatting: eye candy matters</li>
<li>Adding Excel Functions: C1 + D1 = 2!</li>
</ul>
<p>Be aware that I’m assuming you have a rudimentary knowledge of Excel, but nothing too serious. You don’t even have to own a copy — all the examples here work equally well with <a href="http://www.openoffice.org/" rel="external" class="sublink">OpenOffice Calc</a>.</p>
<h5>Introducing PEAR::Spreadsheet_Excel_Writer</h5>
<p>Let’s face it — although you and I may be preoccupied with <a href="http://www.sitepoint.com/glossary.php?q=X#term_3" class="glossary" title="eXtensible Markup Language, or XML, is a text markup language designed for the easy sharing of data.">XML</a> markup, tabbed browsing, editors like Emacs and VI, and minimizing the use of system resources, the rest of the computer-using world is happily chugging away with the likes of Microsoft Office. And although they may be moderately impressed by the amazing things you can do with an <a href="http://www.sitepoint.com/glossary.php?q=H#term_75" class="glossary" title="HTML stands for HyperText Markup Language.">HTML</a> table, when it comes to dealing with numbers, Excel is pretty much a standard.</p>
<p>More to the point, Excel is widely used by those dealing with finance and money. In other words, the Accounts department that’s failed to pay your bill on time is probably using it. Make the accountants’ lives easier, and they might return the favour…</p>
<p>Wouldn’t it be great if you could provide your customers access to downloadable numerical data in the form of an Excel spreadsheet? The good news is that you can, with <a href="http://pear.php.net/Spreadsheet_Excel_Writer" rel="external" class="sublink">PEAR::Spreadsheet_Excel_Writer</a>.</p>
<p>“Impossible!” you cry. “Excel uses some proprietary Microsoft file format. This can’t be done!”</p>
<p>Yes, it can. Spreadsheet_Excel_Writer generates the “real thing”, complete with Excel functions, formatting and all. No, we’re not talking generating comma separated files here, or using the <a href="http://www.php.net/COM" rel="external" class="sublink">COM</a> extension (or any other extension, for that matter). This is written in pure PHP and will work just as well from a <a href="http://www.sitepoint.com/glossary.php?q=U#term_22" class="glossary" title="Multi-user, multitasking Operating System and set of specifications">UNIX</a>-based Web server as it does from a Windows-based server — and there’s no need to bug your hosting provider. In short, PEAR::Spreadsheet_Excel_Writer, with additional magic from <a href="http://pear.php.net/OLE" rel="external" class="sublink">PEAR::OLE</a>, “understands” Microsofts Excel file formats.</p>
<p>Let’s take a moment to tip our hats to <a href="http://www.xavier-noguer.com/" rel="external" class="sublink">Xavier Noguer</a>, who’s done an amazing job in bringing all this to PHP, with help from <a href="http://www.appelsiini.net/%7Etuupola/" rel="external" class="sublink">Mika Tuupola</a> for Spreadsheet_Excel_Writer.</p>
<p>Now, without further <a href="http://www.sitepoint.com/glossary.php?q=A#term_29" class="glossary" title="ADO.NET stands for ActiveX Data Objects for .NET. It refers to the suite of data access technologies used to manipulate databases. ">ado</a>, and armed with full knowledge of PEAR’s package manager, which you installed successfully last month (right?), let’s start by downloading the libraries. Open up your command prompt and type:</p>
<p><code>$ pear install OLE<br />
$ pear install Spreadsheet_Excel_Writer</code></p>
<p>That’s it. We’re ready for action!</p>
<p><strong>Important Note!</strong> I used PEAR::OLE version 0.5 and PEAR::Spreadsheet_Excel_Writer version 0.7 for the examples in this article. Be warned that things may change with future releases.</p>
<h5>Finding your Way Around</h5>
<p>To kick things off, let’s generate a very simple spreadsheet.</p>
<p><code>&lt;?php<br />
// Include PEAR::Spreadsheet_Excel_Writer<br />
require_once "Spreadsheet/Excel/Writer.php";</code></p>
<p>// Create an instance<br />
$xls =&amp; new Spreadsheet_Excel_Writer();</p>
<p>// Send HTTP headers to tell the browser what’s coming<br />
$xls-&gt;send(”test.xls”);</p>
<p>// Add a worksheet to the file, returning an object to add data to<br />
$sheet =&amp; $xls-&gt;addWorksheet(’Binary Count’);</p>
<p>// Write some numbers<br />
for ( $i=0;$i&lt;11;$i++ ) {<br />
// Use PHP’s decbin() function to convert integer to binary<br />
$sheet-&gt;write($i,0,decbin($i));<br />
}</p>
<p>// Finish the spreadsheet, dumping it to the browser<br />
$xls-&gt;close();<br />
?&gt;</p>
<p>Filename: example_1.php</p>
<p>Point your browser to the script and, assuming it knows about Excel (or OpenOffice Calc), up pops a spreadsheet, containing the numbers 0 to 10 as binary.</p>
<p><strong>Storing Files</strong></p>
<p>The spreadsheet is dynamically rendered in this case — nothing is stored on the server. If you want to generate a file instead, you can cut out the processing required to generate a sheet that hasn’t changed simply by passing the constructor a legal path and filename, and avoiding sending the HTTP headers, like so:</p>
<p><code>&lt;?php<br />
// Has a spreadsheet been created?<br />
if ( !file_exists('sheets/binary.xls') ) {</code></p>
<p>// Include PEAR::Spreadsheet_Excel_Writer<br />
require_once “Spreadsheet/Excel/Writer.php”;</p>
<p>// Create an instance, passing the filename to create<br />
$xls =&amp; new Spreadsheet_Excel_Writer(’sheets/binary.xls’);</p>
<p>// Add a worksheet to the file, returning an object to add data to<br />
$sheet =&amp; $xls-&gt;addWorksheet(’Binary Count’);</p>
<p>// Write some numbers<br />
for ( $i=0;$i&lt;11;$i++ ) {<br />
// Use PHP’s decbin() function to convert integer to binary<br />
$sheet-&gt;write($i,0,decbin($i));<br />
}</p>
<p>// Finish the spreadsheet, dumping it to the browser<br />
$xls-&gt;close();<br />
}<br />
?&gt;</p>
<p>Your spreadsheet is ready for download <a href="http://www.sitepoint.com/article/sheets/binary.xls" rel="external" class="sublink">here</a></p>
<p>Filename: example_2.php</p>
<p>If you’re using a UNIX-based system, remember to modify the permissions of the directory in which you’re storing the spreadsheet, so PHP can write to it.</p>
<p><strong>API Overview</strong></p>
<p>OK, we’re done with the basics. To get the most out of PEAR::Spreadsheet_Excel_Writer, you need to know a little bit more about the API, though. The API documentation that is available <a href="http://pear.php.net/manual/en/package.fileformats.spreadsheet-excel-writer.php" rel="external" class="sublink">on the PEAR Website</a> is out of date right now (it’s grown a lot, it seems, since that version of the documentation was generated). Thankfully, the authors have, for the most part, added inline documentation to the code, so you can make your own API docs by downloading <a href="http://www.phpdoc.org/" rel="external" class="sublink">phpDocumentor</a> and pointing it at a directory that contains all the<br />
Spreadsheet_Excel_Writer source code. If you need help getting started with phpDocumentor (and will excuse the sales pitch), it’s discussed in Volume 2: Applications of <a href="http://www.sitepoint.com/books/phpant1/" rel="external" class="sublink">The PHP Anthology</a>.</p>
<p>The main class that you’ll always begin work with, <em>Spreadsheet_Excel_Writer</em>, represents the point of access to all other classes in the library. It provides two important factory methods (which are actually defined in the parent class <em>Spreadsheet_Excel_Writer_Workbook</em>:</p>
<ul>
<li><code>addWorksheet()</code> - returns an instance of <em>Spreadsheet_Excel_Writer_Worksheet</em>. A large part of the work is done with instances of this class (as above), allowing you to write to the cells of a single sheet (an Excel spreadsheet is a Workbook containing one or more Worksheets).</li>
<li><code>addFormat()</code> - returns an instance of <em>Spreadsheet_Excel_Writer_Format</em>, which is used to add the visual formatting of cells in a Worksheet.</li>
</ul>
<p>The library contains three other classes of which you should be aware, although you may not find yourself having to work with them directly:</p>
<ul>
<li><em>Spreadsheet_Excel_Writer_Validator</em> makes it possible to add cell validation rules. Right now, there’s basically no documentation for this class. It seems to be experimental code, so I’ll be avoiding it here. Basically, it appears to provide the ability to perform basic validation on data entered into an Excel cell by an end user. More complex rules, such as validating against a list of cells, can be implemented by extending the class. The Spreadsheet_Excel_Writer_Workbook class provides the method <code>addValidator()</code> to create an instance of the validation while the Spreadsheet_Excel_Writer_Worksheet allows validators to be assigned to cells with the <code>setValidation()</code> method.</li>
<li><em>Spreadsheet_Excel_Writer_Parser</em>, which is a parser for Excel spreadsheet functions that allows you to check whether a function is valid Excel syntax. This may help you trap errors when adding functions to the spreadsheet within PHP.</li>
<li>Finally, <em>Spreadsheet_Excel_Writer_BIFFwriter</em> is used to generate the Binary File Format for storing Excel files. If you’re interested in Excel hacking, it may be interesting to study what it’s doing but, otherwise, the library hides you from this class completely, so you don’t need to worry about it.</li>
</ul>
<p><strong>Zero Index Confusion</strong></p>
<p>One method of note, which we saw in the above example, is the <code>Spreadsheet_Excel_Writer_Worksheet::write()</code> method, which you’ll be using a lot to add data to cells. It can be slightly confusing if you’re used to the way cells are addressed in Excel.</p>
<p>The first argument to <code>write()</code> is the <em>row number</em>. The first row number, at the top of the spreadsheet, is 0 (zero) in <a href="http://www.sitepoint.com/glossary.php?q=P#term_50" class="glossary" title="The PHP Extension and Application Repository - a framework and distribution system for reusable PHP components">PEAR</a>::Spreadsheet_Excel_Writer, not 1, as it is in Excel.</p>
<p>The second argument is the <em>column number</em>. Now, columns in Excel are identified with letters of the alphabet, not numbers, so you’ll just have to get used to translating between the two. The letter F is 6th in the alphabet, so the second argument is… 5 (of course!) — the leftmost column is 0 (zero) in PEAR::Spreadsheet_Excel_Writer, so you need to subtract one to get the column number.</p>
<p>The third argument to <code>write()</code> is the data to put into the cell; there’s an optional forth argument, used to apply visual formatting to the cell.</p>
<p>There are many more methods in the Spreadsheet_Excel_Writer_Worksheet class, such as for freezing and thawing parts of the sheet, and formatting the sheet, as a whole, for printing. I’ll touch on some of these in later examples but you’ll have to explore the majority for yourself.</p>
<h5>Adding Cell Formatting</h5>
<p>So, how about making the spreadsheet look pretty? We can accomplish this with PEAR::Spreadsheet_Excel_Writer using the <code>addFormat()</code> function to fetch an object of type Spreadsheet_Excel_Writer_Format. We apply the formatting to this object using the (large number of) methods it provides, then pass it the <code>write()</code> method of Spreadsheet_Excel_Writer_Worksheet to assign the formatting to a particular cell we’ve added.</p>
<p>For the sake of a “real world” example, let’s say I want to give users of my online shop, phpPetstore.com, the ability to download a “receipt” for the items they just bought as a Workbook containing a single Worksheet.</p>
<p>I begin my worksheet with the usual stuff:</p>
<p><code>&lt;?<a href="http://www.sitepoint.com/glossary.php?q=P#term_1" class="glossary" title="PHP, or Hypertext Preprocessor, is an open source, server-side programming language.">php</a><br />
require_once “Spreadsheet/Excel/Writer.php”;</code></p>
<p>// Create workbook<br />
$xls =&amp; new Spreadsheet_Excel_Writer();</p>
<p>// Create worksheet<br />
$cart =&amp; $xls-&gt;addWorksheet(’phpPetstore’);</p>
<p>Next (blessed with the knowledge that I’ll only be using four columns), I’ll add a title to the sheet, merging some cells in which to place it. Here, you get your first taste of how formatting is done:</p>
<p><code>// Some text to use as a title for the worksheet<br />
$titleText = 'phpPetstore: Receipt from ' . date('dS M Y');</code></p>
<p>// Create a format object<br />
$titleFormat =&amp; $xls-&gt;addFormat();</p>
<p>// Set the font family - Helvetica works for OpenOffice calc too…<br />
$titleFormat-&gt;setFontFamily(’Helvetica’);</p>
<p>// Set the text to bold<br />
$titleFormat-&gt;setBold();</p>
<p>// Set the text size<br />
$titleFormat-&gt;setSize(’13?);</p>
<p>// Set the text color<br />
$titleFormat-&gt;setColor(’navy’);</p>
<p>// Set the bottom border width to “thick”<br />
$titleFormat-&gt;setBottom(2);</p>
<p>// Set the color of the bottom border<br />
$titleFormat-&gt;setBottomColor(’navy’);</p>
<p>// Set the alignment to the special merge value<br />
$titleFormat-&gt;setAlign(’merge’);</p>
<p>// Add the title to the top left cell of the worksheet,<br />
// passing it the title string and the format object<br />
$cart-&gt;write(0,0,$titleText,$titleFormat);</p>
<p>// Add three empty cells to merge with<br />
$cart-&gt;write(0,1,”,$titleFormat);<br />
$cart-&gt;write(0,2,”,$titleFormat);<br />
$cart-&gt;write(0,3,”,$titleFormat);</p>
<p>// The row height<br />
$cart-&gt;setRow(0,30);</p>
<p>// Set the column width for the first 4 columns<br />
$cart-&gt;setColumn(0,3,15);</p>
<p id="adz" class="vertical">&nbsp;</p>
<p>Notice first that I got the formatting object by calling <code>addFormat()</code> via the $xls object that represents the entire spreadsheet. I then apply some specific formatting to the object (method names like <code>setBold()</code> speak for themselves — see the API docs for a full list of formatting methods).</p>
<p>Once I’m done formatting, I call <code>write()</code> on the Worksheet object $cart to add to a cell, passing the formatting object as the forth argument.</p>
<p>One unusual thing I’ve done here is to merge four cells. By calling setAlign(’merge’) on the formatting object (normally you’d use something like ‘left’, ‘right’ or ‘center’), I’ve told Spreadsheet_Excel_Writer that it should merge all cells that have this formatting applied to them. This is why I created three empty cells and applied the formatting to them.</p>
<p>Using <code>setRow()</code> allows me to modify the height of the row, making it bigger than the default Excel row height. This method has further optional formatting arguments that allow you, for example, to apply a format object to an entire row. Likewise, for <code>setColumn()</code>, I can set the column width and optionally apply further formatting. The difference is that <code>setRow()</code> applies to a single row only, while <code>setColumn()</code> is applied to a range of columns.</p>
<p>So far, so good. Now, I need some data to add to the sheet. To avoid complicating the example (by involving a database), I’ll use an indexed <a href="http://www.sitepoint.com/glossary.php?q=%23#term_72" class="glossary" title="An array is a single variable with compartments, each of which can hold a value. ">array</a> of associative <a href="http://www.sitepoint.com/glossary.php?q=%23#term_72" class="glossary" title="An array is a single variable with compartments, each of which can hold a value. ">arrays</a>, which we can pretend is the result of an SQL select:</p>
<p><code>$items = array (<br />
array( 'description'=&gt;'Parrot'  ,'price'=&gt;34.0,  'quantity'=&gt;1),<br />
array( 'description'=&gt;'Snake'  ,'price'=&gt;16.5,  'quantity'=&gt;2),<br />
array( 'description'=&gt;'Mouse'  ,'price'=&gt;1.25,  'quantity'=&gt;10),<br />
);</code></p>
<p>The “columns in the database” are the keys of the second order arrays; ‘description’, ‘price’ and ‘quantity’, so the next thing we need to do is to add the column headings along with an additional ‘Total’ heading that I’ll use later on:</p>
<p><code>// Set up some formatting<br />
$colHeadingFormat =&amp; $xls-&gt;addFormat();<br />
$colHeadingFormat-&gt;setBold();<br />
$colHeadingFormat-&gt;setFontFamily('Helvetica');<br />
$colHeadingFormat-&gt;setBold();<br />
$colHeadingFormat-&gt;setSize('10');<br />
$colHeadingFormat-&gt;setAlign('center');</code></p>
<p>// An array with the data for the column headings<br />
$colNames = array(’Item’,&#8217;Price($)’,&#8217;Quantity’,&#8217;Total’);</p>
<p>// Add all the column headings with a single call<br />
// leaving a blank row to look nicer<br />
$cart-&gt;writeRow(2,0,$colNames,$colHeadingFormat);</p>
<p>You’ve already seen the formatting. What you haven’t seen before is the <code>writeRow()</code> method. This essentially does the same thing as <code>write()</code>, but allows you to insert an array of data, from left to right, beginning at the specified row and column number. It makes a handy short cut to reduce lines of code.</p>
<p>One further thing I want to do is to make sure the column headings will always be visible as we scroll through the list of items. In Excel, this is possible by “freezing” a “pane” — selecting a block of cells that will “hover” while a user scrolls through the data, allowing them to see the column headings (in this case) that tell them what the data represents. The same is possible with PEAR::Spreadsheet_Excel_Writer:</p>
<p><code>// The cell group to freeze<br />
// 1st Argument - vertical split position<br />
// 2st Argument - horizontal split position (0 = no horizontal split)<br />
// 3st Argument - topmost visible row below the vertical split<br />
// 4th Argument - leftmost visible column after the horizontal split<br />
$freeze = array(3,0,4,0);</code></p>
<p>// Freeze those cells!<br />
$cart-&gt;freezePanes($freeze);</p>
<p>Note that “freezing” was applied directly via the Worksheet object $cart, rather than via a formatting object, because it applied to a collection of cells. Formatting, on the other hand, is applied to individual cells.</p>
<p>Finally, I loop through the items in the cart, adding the data to the sheet:</p>
<p><code>// Pseudo data<br />
$items = array (<br />
array( 'description'=&gt;'Parrot'  ,'price'=&gt;34.0,  'quantity'=&gt;1),<br />
array( 'description'=&gt;'Snake'  ,'price'=&gt;16.5,  'quantity'=&gt;2),<br />
array( 'description'=&gt;'Mouse'  ,'price'=&gt;1.25,  'quantity'=&gt;10),<br />
);</code></p>
<p>// Use this to keep track of the current row number<br />
$currentRow = 4;</p>
<p>// Loop through the data, adding it to the sheet<br />
foreach ( $items as $item ) {<br />
// Write each item to the sheet<br />
$cart-&gt;writeRow($currentRow,0,$item);<br />
$currentRow++;<br />
}</p>
<p>There’s nothing particularly new here, except that you’ll find it becomes important to keep track of row and column numbers as you loop through data, because these are needed to insert the data into the correct place.</p>
<p>That’s basically it. If you’re new to <a href="http://www.sitepoint.com/glossary.php?q=O#term_10" class="glossary" title="An programming methodology involving the building of abstracted code objects designed to interact with each other. ">OOP</a> in PHP, this may, at first glance, be a little intimidating, but you’ll notice that all the methods are well named to the point where you can usually guess their purpose just by looking at them. The notion of fetching one object from another may be new, but when you think about it, it makes sense that you create a Worksheet object by calling the <code>addWorksheetSheet()</code> method of the Workbook object and that you add formatting objects to a cell at the point where you <code>write()</code> to the Worksheet.</p>
<h5>Adding Excel Functions</h5>
<p>Now, you’re able to make a spreadsheet that looks nice but, as any Excel Pro can tell you, simply displaying raw data isn’t very useful. Life gets really interesting when you start using Excel’s functions (and perhaps you own) to perform calculations on the raw data and turn it into something more interesting.</p>
<p>Now I’m <em>not</em> an Excel master (and this is not about to turn into an Excel tutorial) but it is clear that my shopping cart receipt needs to be cleverer, so I need to add some calculations based on the data I’ve already added. For each row, I want to display the “total item cost” — the raw data contains the unit price on the item and the number of items purchased:</p>
<p><code>"total item cost" = "unit price" * "number of items purchased"</code></p>
<p>In terms of Excel, to calculate the total for the item on the fifth row, the formula might be:</p>
<p><code>[Cell D5] =PRODUCT(B5:C5)</code></p>
<p>To accomplish this with <a href="http://www.sitepoint.com/glossary.php?q=P#term_50" class="glossary" title="The PHP Extension and Application Repository - a framework and distribution system for reusable PHP components">PEAR</a>::Spreadsheet_Excel_Writer, I need to modify slightly the code that loops through the data:</p>
<p><code>// Use this to keep track of the current row number<br />
$currentRow = 4;</code></p>
<p>// Loop through the data, adding it to the sheet<br />
foreach ( $items as $item ) {<br />
// Write each item to the sheet<br />
$cart-&gt;writeRow($currentRow,0,$item);</p>
<p>// Remember Excel starts counting rows from #1!<br />
$excelRow = $currentRow + 1;</p>
<p>// Create a <a href="http://www.sitepoint.com/glossary.php?q=P#term_1" class="glossary" title="PHP, or Hypertext Preprocessor, is an open source, server-side programming language.">PHP</a> string containing the formula<br />
$formula = ‘=PRODUCT(B’ . $excelRow . ‘:C’ . $excelRow .’)&#8217;;</p>
<p>// Add the formula to the row<br />
$cart-&gt;writeFormula($currentRow,3,$formula);</p>
<p>$currentRow++;<br />
}</p>
<p>Adding the formula itself is pretty easy — we simply use the <code>writeFormula()</code> method. But most important (and confusing) is what I mentioned earlier — Excel begins to count rows from 1, while PEAR::Spreadsheet_Excel_Writer begins at 0 (zero), so, when creating functions, I need to remember this or I’ll be referring to the wrong cells. This is why I created the variable <code>$excelRow</code>, which is the <code>$currentRow</code> plus one. You may think this a design flaw on behalf of the authors, but remember: in PHP, like most programming languages, indexed <a href="http://www.sitepoint.com/glossary.php?q=%23#term_72" class="glossary" title="An array is a single variable with compartments, each of which can hold a value. ">arrays</a> begin with a zero index. Trying to bump them forward by one just to play nice with Excel would likely have lead to many bugs and maintenance headaches. If it really annoys you, knock up some functions to translate between the two.</p>
<p>So, now my sheet displays the item totals on each row. But what about totaling the totals, so the customers can see the figure that will appear on their credit card bill? For this, it’s simply a matter of adding all the item totals together and displaying the result in another cell.</p>
<p>In Excel terms, I need to use the <code>SUM()</code> function to add item totals, which appear in column D:</p>
<p><code>[Grand Total Cell] =SUM(D5:D7)</code></p>
<p>To fit this into the spreadsheet, after the loop has finished, I add the following:</p>
<p><code>// The first row as Excel knows it - $currentRow was 4 at the start<br />
$startingExcelRow = 5;</code></p>
<p>// The final row as Excel<br />
// (which is the same as the currentRow once the loop ends)<br />
$finalExcelRow = $currentRow;</p>
<p>// Excel formal to sum all the item totals to get the grand total<br />
$gTFormula = &#8216;=SUM(D&#8217;.$startingExcelRow.&#8217;:D&#8217;.$finalExcelRow.&#8217;)';</p>
<p>// Some more formatting for the grand total cells<br />
$gTFormat =&amp; $xls-&gt;addFormat();<br />
$gTFormat-&gt;setFontFamily(&#8217;Helvetica&#8217;);<br />
$gTFormat-&gt;setBold();<br />
$gTFormat-&gt;setTop(1); // Top border<br />
$gTFormat-&gt;setBottom(1); // Bottom border</p>
<p>// Add some text plus formatting<br />
$cart-&gt;write($currentRow,2,&#8217;Grand Total:&#8217;,$gTFormat);</p>
<p>// Add the grand total formula along with the format<br />
$cart-&gt;writeFormula($currentRow,3,$gTFormula,$gTFormat);</p>
<p>Again it gets even more exciting, but keeping track of the Excel row numbers is mostly a case of remembering to add one to whichever variable has been tracking the PEAR::Spreadsheet_Excel_Writer row numbers. Notice also that I can apply formatting to the output produced by the formula.</p>
<p>Finally, I finish of my shopping cart receipt by sending the spreadsheet straight to the browser:</p>
<p><code>// Send the Spreadsheet to the browser<br />
$xls-&gt;send("phpPetstore.xls");<br />
$xls-&gt;close();<br />
?&gt;</code><br />
Filename: phpPetstore.php</p>
<p>That’s it. The spreadsheet is ready to download. The finished code is available <a href="http://www.sitepoint.com/examples/pearexcel/excel_code.zip" rel="external" class="sublink">here</a>.</p>
<p><strong>Wrap Up</strong></p>
<p>As you’ve seen, PEAR::Spreadsheet_Excel_Writer offers pretty much everything you need to build a useful spreadsheet, including formatting and functions. And, because you’re tapping into Excel’s functionality as well, you’ve got a lot of power at your disposal.</p>
<p>The API is tidy and, once you get used to it, easy to work with. The classes are also well structured, so scaling what I’ve done here up to a workbook that contains numerous, interrelated sheets is relatively easily accomplished. Be aware, though, that as you’ve seen here, you can end up with some pretty lengthy scripts if you’re not careful, particularly as formatting has to be defined in fine detail. If you have a need to do some serious work with PEAR::Spreadsheet_Excel_Writer it’s worth considering the opportunities for building in re-use early. You may find there’s a particular cell format that keeps cropping up all over, and could be better placed in a class and re-used. If you’re building a workbook containing many similar worksheets (e.g. Sales figures broken down with a worksheet for each region), writing classes to act as a template (design pattern hint) that generates the sheets may save a lot of effort.</p>
<p>Overall, PEAR::Spreadsheet_Excel_Writer is great addition to your PHP toolbox you’re your users are bugging you because they can’t get the “view” they want on the data you deliver to them with <a href="http://www.sitepoint.com/glossary.php?q=H#term_75" class="glossary" title="HTML stands for HyperText Markup Language.">HTML</a>, Spreadsheet_Excel_Writer provides a handy alternative to implementing a never-ending list of new features. What’s more, it creates a “wow” factor with which you can impress a potential client — particularly if the client in question uses Excel as their daily bread and butter.</p>
<p>The subject of PHP and Excel becomes even more interesting when you consider <a href="http://www.jedox.com/" rel="external" class="sublink">Jedox’s Worksheet Server</a>, a tool for <em>reading</em> (here we were just writing) Excel spreadsheets, and generating PHP applications from them. But that’s a story for another time…</p>
]]></content:encoded>
			<wfw:commentRss>http://blogs.pinkcrow.net/generating-spreadsheets-with-php-and-pear/61/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Get In The Google Top 10 - Post Title Optimization</title>
		<link>http://blogs.pinkcrow.net/get-in-the-google-top-10-post-title-optimization/59/</link>
		<comments>http://blogs.pinkcrow.net/get-in-the-google-top-10-post-title-optimization/59/#comments</comments>
		<pubDate>Tue, 04 Sep 2007 10:43:24 +0000</pubDate>
		<dc:creator>Valeriu Buzila</dc:creator>
		
		<category><![CDATA[General]]></category>

		<guid isPermaLink="false">http://blogs.pinkcrow.net/get-in-the-google-top-10-post-title-optimization/59/</guid>
		<description><![CDATA[Post Title Optimization is one of the most important things you need to do for getting good or great results in the SERPs. When you know how to choose a title for your post than you can get a lot of traffic from the search engines!
Optimizing Post Title Includes:
1. Choosing your title carefully - it [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://bp0.blogger.com/_B0VP18_SRcc/RpjSghy0JLI/AAAAAAAAALg/M-vCcy9p1iM/s1600-h/Capture2.jpg" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}"><img src="http://bp0.blogger.com/_B0VP18_SRcc/RpjSghy0JLI/AAAAAAAAALg/M-vCcy9p1iM/s320/Capture2.jpg" style="cursor: pointer" id="BLOGGER_PHOTO_ID_5087047235384124594" border="0" /></a>Post Title Optimization is one of the most important things you need to do for getting good or great results in the <a href="http://www.webopedia.com/TERM/S/SERP.html">SERPs</a>. When you know how to choose a title for your post than you can get a lot of traffic from the search engines!</p>
<p><span style="font-size: 130%"><span style="font-weight: bold">Optimizing Post Title Includes:</span></span></p>
<p><span style="font-weight: bold">1. Choosing your title carefully</span> - it means that you use the title that is most likely to be used for a given term<br />
<span style="font-weight: bold">2. Use the term in your post</span> - mention the term on the <span style="font-style: italic">beginning</span> of the post and in the <span style="font-style: italic">end</span> of your post.<br />
<span style="font-weight: bold">3. Comment and mention the term</span> - Respond to someone&#8217;s comment and mention the term in the comment<br />
Recently I have done a little research on how to get in the Google Top 10 for several search terms and I&#8217;ve been more than successful.</p>
<p><span style="font-weight: bold">Here&#8217;s an example</span>: I wanted to rank in the Google&#8217;s top 10 search results for the term &#8220;<a href="http://www.google.com/search?hl=en&amp;q=add+categories+to+blogger&amp;btnG=Search">add categories to blogger</a>&#8221; which is a very often used term in the search engines. The term specified shows up 22.200.000 on search results and it&#8217;s not that easy to get in the first 10 pages of the search, not to say in the top 10!</p>
<p>But, by carefully choosing the post title for my post and doing some post title optimization <span style="font-size: 130%"><span style="font-weight: bold">I got into top 5</span></span> of the search results for that term! Try typing in the term &#8220;add categories to blogger&#8221; or &#8220;adding categories to blogger&#8221; or even &#8220;adding categories to blogspot&#8221; and you&#8217;ll see my blog showing up in the 5th place!</p>
]]></content:encoded>
			<wfw:commentRss>http://blogs.pinkcrow.net/get-in-the-google-top-10-post-title-optimization/59/feed/</wfw:commentRss>
		</item>
		<item>
		<title>SEO Series Batch 7 - Top 5 Google Ranking Factors</title>
		<link>http://blogs.pinkcrow.net/seo-series-batch-7-top-5-google-ranking-factors/58/</link>
		<comments>http://blogs.pinkcrow.net/seo-series-batch-7-top-5-google-ranking-factors/58/#comments</comments>
		<pubDate>Tue, 04 Sep 2007 10:41:26 +0000</pubDate>
		<dc:creator>Valeriu Buzila</dc:creator>
		
		<category><![CDATA[General]]></category>

		<guid isPermaLink="false">http://blogs.pinkcrow.net/seo-series-batch-7-top-5-google-ranking-factors/58/</guid>
		<description><![CDATA[SEO Series continues and the linky love is getting bigger every time. Today I will show you the most important search engine factors that Google&#8217;s algorithm known as &#8220;Googlebot&#8221; values the most. . SEOMoz released a document about the Google&#8217;s algorithm and how it works and here are top 5 positive and top 5 negative [...]]]></description>
			<content:encoded><![CDATA[<p>SEO Series continues and the linky love is getting bigger every time. Today I will show you the most important search engine factors that Google&#8217;s algorithm known as &#8220;Googlebot&#8221; values the most. . SEOMoz released a <a href="http://www.seomoz.org/article/search-ranking-factors">document</a> about the Google&#8217;s algorithm and how it works and here are top 5 positive and top 5 negative factors from that document.</p>
<p><span style="font-weight: bold; color: #33cc00">Top 5 Positive Factors:</span></p>
<p><span style="font-style: italic">1. Keyword Use In Title Tag</span> - In my opinion the most important factor for getting great search engine rankings!<a href="http://makemoneywithkassper.blogspot.com/2007/07/get-in-google-top-10-post-title.html"></a><br />
<span style="font-style: italic">2. Global Link Popularity Of The Site</span><br />
<span style="font-style: italic">3. Anchor Text Of Incoming Links</span><br />
<span style="font-style: italic">4. Link Popularity Within The Site</span><br />
<span style="font-style: italic">5. Age Of The Site</span></p>
<p><span style="font-weight: bold; color: #cc0000">Top 5 Negative Factors:</p>
<p></span><span style="font-style: italic">1. Server Is Often Inaccessible To Googlebot</span><br />
<span style="font-style: italic">    2. Content Which Is Very Similar Or Duplicate to Existing Content On The Web</span><br />
<span style="font-style: italic">    3. External Links To Low Quality Sites</span><br />
<span style="font-style: italic">    4. Participation In Link Schemes or Actively Selling Links</span><br />
<span style="font-style: italic">    5. Duplicate Meta Tags On More Pages</span></p>
]]></content:encoded>
			<wfw:commentRss>http://blogs.pinkcrow.net/seo-series-batch-7-top-5-google-ranking-factors/58/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Google Begins Hosting News on Site</title>
		<link>http://blogs.pinkcrow.net/google-begins-hosting-news-on-site/57/</link>
		<comments>http://blogs.pinkcrow.net/google-begins-hosting-news-on-site/57/#comments</comments>
		<pubDate>Tue, 04 Sep 2007 08:25:41 +0000</pubDate>
		<dc:creator>Valeriu Buzila</dc:creator>
		
		<category><![CDATA[General]]></category>

		<guid isPermaLink="false">http://blogs.pinkcrow.net/google-begins-hosting-news-on-site/57/</guid>
		<description><![CDATA[  In a landmark development, Google has reportedly started hosting content produced by USA&#8217;s Associated Press (AP), Agence France Presse (AFP), Britain&#8217;s Press Association, and the Canadian Press, instead of just directing readers to other destinations.
While Google had already bought rights to display content produced by all 4 news services in question, the search [...]]]></description>
			<content:encoded><![CDATA[<p><!-- matter starts --> <span class="boxcontents"> In a landmark development, Google has reportedly started hosting content produced by USA&#8217;s Associated Press (AP), Agence France Presse (AFP), Britain&#8217;s Press Association, and the Canadian Press, instead of just directing readers to other destinations.</span></p>
<p>While Google had already bought rights to display content produced by all 4 news services in question, the search major&#8217;s news section continued to link readers to other Web sites so as to be able to read stories and view photographs over there.<br />
<center><br />
</center>The latest development however means that visitors, who for instance want to read an AP story, can remain on Google&#8217;s Web site unless they choose to click on a link that allows them read the same story elsewhere.So, while the change might not even get noticed by Google users though it augurs well for the company, it will certainly make a huge difference to the hundreds of stories and photographs distributed each day by AP, AFP, Press Association, and the Canadian Press.</p>
<p>It might result in diminished traffic to other media sites where these stories and photos are also to be found. In turn, it might help reduce online advertising revenue of newspapers and broadcasters, managing to become a prime source of irritation for them.</p>
<p>Ever since both AP and AFP have raised concerns about the search engine infringing on their copyrights, Google has been negotiating licensing deals with them. The company has also reached licensing agreements with the Press Association and the Canadian Press around the same time.</p>
<p>Meanwhile, financial terms of Google&#8217;s latest deals have not been disclosed.</p>
]]></content:encoded>
			<wfw:commentRss>http://blogs.pinkcrow.net/google-begins-hosting-news-on-site/57/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Intex Updates Notebook Portfolio</title>
		<link>http://blogs.pinkcrow.net/intex-updates-notebook-portfolio/56/</link>
		<comments>http://blogs.pinkcrow.net/intex-updates-notebook-portfolio/56/#comments</comments>
		<pubDate>Tue, 04 Sep 2007 08:24:23 +0000</pubDate>
		<dc:creator>Valeriu Buzila</dc:creator>
		
		<category><![CDATA[Gadgets]]></category>

		<guid isPermaLink="false">http://blogs.pinkcrow.net/intex-updates-notebook-portfolio/56/</guid>
		<description><![CDATA[   Intex Technologies has reportedly unveiled its latest notebook range comprising 4 models: the Challenger 012 DW, Performer 032 DW, Achiever 026 DW, and Achiever 026 CW.
The Challenger 012 DW is a Wi fi enabled notebook, designed specially for working professionals.
It features: Intel&#8217;s Core Duo processor 1.86 GHZ, DVD dual drive, 667 FSB [...]]]></description>
			<content:encoded><![CDATA[<p> <!-- matter starts --> <span class="boxcontents"> Intex Technologies has reportedly unveiled its latest notebook range comprising 4 models: the Challenger 012 DW, Performer 032 DW, Achiever 026 DW, and Achiever 026 CW.</span></p>
<p>The Challenger 012 DW is a Wi fi enabled notebook, designed specially for working professionals.</p>
<p>It features: Intel&#8217;s Core Duo processor 1.86 GHZ, DVD dual drive, 667 FSB &amp; 2 MB L2 cache, 1 GB DDR-2 memory, 100 GB hard drive, inbuilt Web camera, and embedded 4-in-1 card reader.The notebook has 2x built-in-speakers, 1x Mini IEEE 1394a port, and 1 xS- Video jack for TV output (HDTV support by transfer cable). Other features include: 12.1-inch wide LCD screen, 1x External CRT monitor output, Bluetooth for fast data transfer, and longer battery life.</p>
<p>Equipped with One Express Card/54(34) Slot and a Kensington lock, the notebook weighs 1.9 kg and costs Rs 39,900.</p>
<p>The Performer 032 DW is targeted at frequent travelers and features: Intel&#8217;s Centrino Core Duo processor, Wi-Fi with Intel wireless LAN, 14.1-inch wide screen, 100 GB hard disk, DVD Dual Drive, and card reader.</p>
<p>The notebook includes features such as: Bluetooth, 1.3 MP camera, 512 MB memory card, audio line out, mic-in, VGA out port, S-Video out, and 3D Stereo enhanced sound system. It costs Rs 36,900.</p>
<p>The Achiever 026 DW and the Achiever 026 CW are designed for students, the SOHO and SME segment. The notebooks come with a 14.1-inch wide screen display, the Celeron model, and Intel&#8217;s 1.86 GHz processor.</p>
<p>The 026 DW and the 026 CW have 512 MB of memory space, and a hard drive of 100 GB and 60 GB respectively to help students store large amount of valuable information on their systems.</p>
<p>The Achiever 026 DW and the 026 CW are available for Rs 26,900 and Rs 24,900 respectively.</p>
<p align="center"><img src="http://images.techtree.com/ttimages/story/83101_image14.jpg" align="middle" border="0" /></p>
]]></content:encoded>
			<wfw:commentRss>http://blogs.pinkcrow.net/intex-updates-notebook-portfolio/56/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Get Ready for the Fall Job Hunting Season</title>
		<link>http://blogs.pinkcrow.net/get-ready-for-the-fall-job-hunting-season/55/</link>
		<comments>http://blogs.pinkcrow.net/get-ready-for-the-fall-job-hunting-season/55/#comments</comments>
		<pubDate>Tue, 04 Sep 2007 08:20:52 +0000</pubDate>
		<dc:creator>Valeriu Buzila</dc:creator>
		
		<category><![CDATA[General]]></category>

		<guid isPermaLink="false">http://blogs.pinkcrow.net/get-ready-for-the-fall-job-hunting-season/55/</guid>
		<description><![CDATA[The Tuesday after Labor Day is the second busiest day each year for job hunters. 


In the job hunting world, there are two peak seasons yearly in which most disenchanted workers set their marks and get set to go. The first is in early January, on the heels of New Year&#8217;s resolutions by bored workers [...]]]></description>
			<content:encoded><![CDATA[<p><span class="articledeck"><strong>The Tuesday after Labor Day is the second busiest day each year for job hunters.</strong> </span><br />
<!--[if !supportLineBreakNewLine]--><br />
<!--[endif]--><o:p></o:p></p>
<p><!--talkback count-->In the job hunting world, there are two peak seasons yearly in which most disenchanted workers set their marks and get set to go. The first is in early January, on the heels of New Year&#8217;s resolutions by bored workers across the land promising themselves they&#8217;ll find more inspiring work that year. <o:p></o:p></p>
<p>The second is the day after Labor Day, when the sight of kids going off to college and school starting anew reminds workers in a state of job ennui of when they, too, used to be enthused about learning new things. <o:p></o:p></p>
<p>But recruiters urge that if you think you could be in the former camp by the year&#8217;s end, you might want to think about jumping in now, and ERE, a community of recruiters around the world, is offering job seekers tips to land their next job. <o:p></o:p></p>
<p><strong>1. Don&#8217;t Quit Your Day Job </strong><o:p></o:p></p>
<p>No matter how loathsome your job is, and how frustrated you are with the amount of time you&#8217;ve been on the job hunt, recruiters discourage job seekers from quitting their current jobs before having found a new one. <o:p></o:p></p>
<p>Though many will tell you that it&#8217;s because you really don&#8217;t know how long it will take until you find your next job, and if it is a long time it will do your resume a disservice, the real truth is that an unemployed job hunter reeks of more desperation than one who knows where their next paycheck is coming from. <o:p></o:p></p>
<p>&#8220;You don&#8217;t want to seem like a job-hopper,&#8221; said Elaine Rigoli, business writer for ERE. &#8220;From a recruiter&#8217;s perspective, if you&#8217;re unemployed and hanging out on job boards all day, you might seem desperate. They want the people who are hard workers and may not even know that they are looking. They&#8217;re called the passive candidates, or passive majority.&#8221; <o:p></o:p></p>
<p><strong>2. See and Be Seen</strong> <o:p></o:p></p>
<p>Increasing one&#8217;s visibility is key when looking for a new job, and the good news is that the Internet has made it even easier to network without leaving your desk. Posting on blogs, starting your own and keeping your social networking profiles up-to-date are widely used ways to increase one&#8217;s professional network. Speaking at conferences, writing for magazines and Web sites, and networking with professional organizations ensure that when it&#8217;s time to move the job hunt forward, you&#8217;ve got lots of resources to tap into. <o:p></o:p></p>
<p>&#8220;Don&#8217;t just sit there. Get out there and meet people. This goes along with not just quitting your job and expecting the next one to come along. If you&#8217;re involved in IT organizations and active on technology boards, recruiters may already know who you are,&#8221; said Rigoli. <o:p></o:p></p>
<p><!-- start ziffimage //--><strong>3. Reinvent Yourself</strong> <o:p></o:p></p>
<p>More than any other line of work, technology requires that its professionals stay on the ball, working constantly to keep their skills sharp and relevant. Recruiters suggest that job seekers go one step further and learn complementary skills to the IT skills they may already have, and find new uses for your talent. <o:p></o:p></p>
<p>&#8220;Keep your skills sharp. Stay aware of the ways you can take advantage of your knowledge by networking. Find new places that people are looking for your skills,&#8221; said Rigoli. <o:p></o:p></p>
<p><strong>4. Don&#8217;t Discount Smaller Job Boards</strong> <o:p></o:p></p>
<p>It would be naïve to ignore the market share of Monster, CareerBuilder and HotJobs when launching your IT job hunt, but it would be risky to limit your job seeking to only the big sharks. Within the IT profession, there are dozens of job boards for technology professionals alone, all of which boast a lower signal-to-noise ratio for workers who don&#8217;t want to wade through irrelevant job ads. <o:p></o:p></p>
<p><!-- start ziffsection //--><!-- start ziffimage //--><o:p></o:p></p>
<p><!-- end ziffsection //-->In the IT profession, the more options can be the merrier. IT pros know that IT jobs aren&#8217;t just in computer and technology professions, but any company in the world with computers at their employees&#8217; desks. <o:p></o:p></p>
<p>&#8220;There are so many niche job boards from itjobs.com to jobs.slashdot.org and computerwork.com, not to mention dice.com, which according to one poll was where a full 17 percent of computer professionals went to find jobs,&#8221; said Rigoli. <o:p></o:p></p>
<p>&#8220;But if you&#8217;re willing to look into the health care industry, or higher education IT, there are boards for all of these employers as well. Whatever you do, don&#8217;t limit your search unnecessarily.&#8221; <o:p></o:p></p>
<p><strong>5. Consider Smaller Companies </strong><o:p></o:p></p>
<p>If Microsoft wants to hire two, or 2,000, new IT professionals, it barely has to market itself before it is flooded with so many applications that it would impossible to read every one. But the technology profession is flooded with small IT shops and partner companies who need people with hands-on IT knowledge. They just may not have the overhead or able bodies to go out and find them, and even if they can find them, they cannot afford to train them. <o:p></o:p></p>
<p>&#8220;They can&#8217;t take raw talent out of the university and train them for a year,&#8221; Celia Harper-Guerra, director of talent at Cisco Systems, in San Jose, Calif., told eWEEK in June. &#8220;A Microsoft can have a one-year training program to become a systems administrator or an engineer. But a small company cannot afford to have a person out of work for a year,&#8221; <o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
]]></content:encoded>
			<wfw:commentRss>http://blogs.pinkcrow.net/get-ready-for-the-fall-job-hunting-season/55/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Programming Grads Meet a Skills Gap in the Real World</title>
		<link>http://blogs.pinkcrow.net/programming-grads-meet-a-skills-gap-in-the-real-world/54/</link>
		<comments>http://blogs.pinkcrow.net/programming-grads-meet-a-skills-gap-in-the-real-world/54/#comments</comments>
		<pubDate>Tue, 04 Sep 2007 08:19:56 +0000</pubDate>
		<dc:creator>Valeriu Buzila</dc:creator>
		
		<category><![CDATA[General]]></category>

		<guid isPermaLink="false">http://blogs.pinkcrow.net/programming-grads-meet-a-skills-gap-in-the-real-world/54/</guid>
		<description><![CDATA[What programmers learn in college and what they need in the work force are out of sync. 
Despite the best laid plans of colleges and universities, there remains a skills gap between what computer science graduates learn in their undergraduate years and what they need to become proficient in a typical at-work environment. 
In short, [...]]]></description>
			<content:encoded><![CDATA[<p><span class="articledeck"><strong>What programmers learn in college and what they need in the work force are out of sync. </strong></span></p>
<p><!--talkback count-->Despite the best laid plans of colleges and universities, there remains a skills gap between what computer science graduates learn in their undergraduate years and what they need to become proficient in a typical at-work environment. <o:p></o:p></p>
<p>In short, many people on both sides of the equation—teachers as well as potential employers—say the educational system is not doing enough to keep pace with the ever-changing needs of IT, and that entering the work force often is as much of an educational experience as is college, particularly for programmers. <o:p></o:p></p>
<p>Ari Zilka, chief technology officer at Terracotta, in <st1:city w:st="on">San  Francisco</st1:city>, said he knows very well about the skills gap, as he worked his way through college in the high-tech business while attending the <st1:placetype w:st="on">University</st1:placetype> of <st1:placename w:st="on">California</st1:placename>, <st1:city w:st="on"><st1:place w:st="on">Berkeley</st1:place></st1:city>. <o:p></o:p></p>
<p>&#8220;I found that UC Berkeley had an excellent curriculum but not only was my schooling lagging behind work, it became very hard to even go to school because work had me learning the concepts and their applicability and nuances that teachers didn&#8217;t even seem to know.&#8221; <o:p></o:p></p>
<p>Zilka noted that many of the new hires he&#8217;s seen during his career continue to echo the same sentiments as he did. <o:p></o:p></p>
<p>Some of the things the school didn&#8217;t teach Zilka and many who are now entering the work force include issues around communication, development skills, and business and product design. <o:p></o:p></p>
<p>On the communication front, Zilka said, &#8220;Presentation skills are critical, and selling and influencing peers is critical.&#8221; Some of the development skills that schools might emphasize more include design patterns, coding style and practices, scalability and performance tuning, and a focus on the entire software development lifecycle, Zilka said. He noted that things like quality assurance, unit testing, and stage and release are not usually taught. <o:p></o:p></p>
<p>Moreover, Zilka said he and his friends used to joke that they would walk out of school knowing mathematical theory, but nothing they would actually use in work. <o:p></o:p></p>
<p>&#8220;In reality, I find that if your school was strong and you learned compilers, OSes [operating systems], hardware design, database design, advanced math and statistics, and the like, you find ways to apply all that theory but you don&#8217;t learn how to be a developer or a sys admin or any of that,&#8221; Zilka said. <o:p></o:p></p>
<p><!-- start ziffsection //--><!-- start ziffimage //--><o:p></o:p></p>
<p><!-- end ziffsection //-->Bjarne Stroustrup, the creator of the C++ language and a computer science professor at <st1:place w:st="on"><st1:placename w:st="on">Texas</st1:placename>  <st1:placename w:st="on">A&amp;M</st1:placename> <st1:placetype w:st="on">University</st1:placetype></st1:place>, said, &#8220;There is a gap. It is hard to precisely characterize because there are so many different kinds of jobs,&#8221; he said. However, &#8220;It is important to remember that universities should educate—for a life time of further learning—not train for specific tasks.&#8221; <o:p></o:p></p>
<p>Yet, &#8220;That said, many students have no clue about software development and couldn&#8217;t program their way out of a paper bag—that&#8217;s unnecessary and puts them into a bad situation even if their primary job function is not programming.&#8221; <o:p></o:p></p>
<p>For example, said Stroustrup, &#8220;inter-face design, testing, use of scripting is often not taught, at best, students are assumed to absorb it by osmosis. Most don&#8217;t and equate programming with fiddling with tiny programs. At TAMU [<st1:place w:st="on"><st1:placename w:st="on">Texas</st1:placename> <st1:placename w:st="on">A&amp;M</st1:placename> <st1:placetype w:st="on">University</st1:placetype></st1:place>], we are trying to address that. I think a bachelor&#8217;s is too short time; for most jobs you really need a masters—there is too much to learn for just four years.&#8221; <o:p></o:p></p>
<p>Rawn Shah, IBM developerWorks Community Programs Manager, agreed with Stroustrup. Shah works for IBM in <st1:place w:st="on"><st1:city w:st="on">Tucson</st1:city>,  <st1:state w:st="on">Ariz.</st1:state></st1:place> <o:p></o:p></p>
<p>&#8220;Today, some of the most sought after developers are those who work with environments and ideas that are complex,&#8221; Shah said. &#8220;The opportunities to do those are harder to find at the basic university level, but are much more obvious at the masters or Ph.D level.&#8221; <o:p></o:p></p>
<p>Bill Scherlis, director of the Institute for Software Research at Carnegie Mellon University, which is home of one of the premier computer science programs in the U.S., acknowledges the skills gap and said CMU is working to help address the gap. <o:p></o:p></p>
<p>&#8220;We hear it all the time from our colleagues in industry that university graduates have programming skills and technical knowledge, but they are somehow not equipped to take on software engineering&#8221; roles in the corporate environment, Scherlis said. <o:p></o:p></p>
<p>&#8220;When graduates join organizations [after college] they are often shocked to realize they are dealing with limited resources, deadlines, fuzz requirements, requirements that change weekly, applications that scale, the use of frameworks and libraries, existing code—that may be bad code with bad design decisions, issues of interaction within and among teams, and having to develop code that is secure,&#8221; Scherlis said. <o:p></o:p></p>
<p>Those are some of the challenges students are faced with that they may not have faced in school, he said. &#8220;And we are crafting responses into the curriculum,&#8221; Scherlis said. &#8220;We have to introduce our students to the mission of real engineering and collaboration.&#8221; <o:p></o:p></p>
<p>One way to do that is to foster more team development, Scherlis said. &#8220;They get experience and deal with the realities of interacting with other individuals.&#8221; Indeed, Scherlis said, the school encourages computer science students to take a course in social psychology to better understand how teams work because team development is such a key part of the corporate development environment today. <o:p></o:p></p>
<p>In fact, the school sponsors collaborative projects between an external organization looking for real solutions to IT problems and student teams at CMU. &#8220;And education is secondary to the external organization; they are truly looking to our teams to help them with a problem first and foremost,&#8221; Scherlis said. So both parties benefit. <o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
]]></content:encoded>
			<wfw:commentRss>http://blogs.pinkcrow.net/programming-grads-meet-a-skills-gap-in-the-real-world/54/feed/</wfw:commentRss>
		</item>
		<item>
		<title>50 cent snoop dog pussycat dolls BEP vs. manelisti</title>
		<link>http://blogs.pinkcrow.net/50-cent-snoop-dog-pussycat-dolls-bep-vs-manelisti/53/</link>
		<comments>http://blogs.pinkcrow.net/50-cent-snoop-dog-pussycat-dolls-bep-vs-manelisti/53/#comments</comments>
		<pubDate>Mon, 03 Sep 2007 19:35:32 +0000</pubDate>
		<dc:creator>Valeriu Buzila</dc:creator>
		
		<category><![CDATA[General]]></category>

		<guid isPermaLink="false">http://blogs.pinkcrow.net/50-cent-snoop-dog-pussycat-dolls-bep-vs-manelisti/53/</guid>
		<description><![CDATA[
http://www.youtube.com/watch?v=RXmuKvPPsXg

]]></description>
			<content:encoded><![CDATA[<div id="vvq4ba05621c9410" class="vvqbox vvqyoutube" style="width:425px;height:335px;">
<p><a href="http://www.youtube.com/watch?v=RXmuKvPPsXg">http://www.youtube.com/watch?v=RXmuKvPPsXg</a></p>
</div>
]]></content:encoded>
			<wfw:commentRss>http://blogs.pinkcrow.net/50-cent-snoop-dog-pussycat-dolls-bep-vs-manelisti/53/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Google Earth’s Hidden Surprise: A Flight Simulator</title>
		<link>http://blogs.pinkcrow.net/google-earth%e2%80%99s-hidden-surprise-a-flight-simulator/52/</link>
		<comments>http://blogs.pinkcrow.net/google-earth%e2%80%99s-hidden-surprise-a-flight-simulator/52/#comments</comments>
		<pubDate>Mon, 03 Sep 2007 05:47:51 +0000</pubDate>
		<dc:creator>Valeriu Buzila</dc:creator>
		
		<category><![CDATA[General]]></category>

		<guid isPermaLink="false">http://blogs.pinkcrow.net/google-earth%e2%80%99s-hidden-surprise-a-flight-simulator/52/</guid>
		<description><![CDATA[We’ve always known that Google has wanted to challenge Microsoft’s desktop dominance in a number of areas, but to date we didn’t know that extended to gaming.Hidden inside Google Earth is a secret Flight Simulator that takes full advantage of Google’s extensive satellite imagery.
To access the hidden feature, open Google Earth and hit Command+Option+A (note [...]]]></description>
			<content:encoded><![CDATA[<p>We’ve always known that Google has wanted to challenge Microsoft’s desktop dominance in a number of areas, but to date we didn’t know that extended to gaming.Hidden inside Google Earth is a secret Flight Simulator that takes full advantage of Google’s extensive satellite imagery.</p>
<p>To access the hidden feature, open Google Earth and hit Command+Option+A (note it must be capital A) or Ctrl+Alt+A if you’re using a Windows Machine.</p>
<p>The Google Earth Flight Simulator comes with two aircraft options, a F16 Viper and the more manageable SR22 4 seater. Players have the option of commencing the game from their current location in Google Earth or can pick from a list of pre-determined runways. Control instructions can be found <a href="http://earth.google.com/intl/en/userguide/v4/flightsim/index.html" onclick="javascript:urchinTracker ('/outbound/earth.google.com');">here<img src="http://i.ixnp.com/images/v2.20/t.gif" id="snap_com_shot_link_icon" class="snap_preview_icon" style="border: 0pt none ; margin: 0pt ! important; padding: 1px 0pt 0pt; font-style: normal; font-weight: normal; font-family: 'trebuchet ms',arial,helvetica,sans-serif; float: none; position: static; left: auto; top: auto; line-height: normal; background-image: url('http://i.ixnp.com/images/v2.20/theme/silver/palette.gif'); background-color: transparent; width: 14px; height: 12px; background-position: -799px 0pt; background-repeat: no-repeat; text-decoration: none; visibility: visible; display: inline" /></a>.</p>
<p>Overall the game play is fairly simple in terms of control, but the striking difference is flying over real pictures of locations. I took a quick flight from San Francisco International, headed North to the Golden Gate then turn back over the city before heading towards the Valley. It wasn’t perfect, but it was as good visually as the paid Microsoft Flight Simulator, and in terms of actually presenting real objects it was better.</p>
<p>Thanks to <a href="http://marco-za.blogspot.com/2007/08/google-earth-flight-simulator.html" onclick="javascript:urchinTracker ('/outbound/marco-za.blogspot.com');">Marco<img src="http://i.ixnp.com/images/v2.20/t.gif" id="snap_com_shot_link_icon" class="snap_preview_icon" style="border: 0pt none ; margin: 0pt ! important; padding: 1px 0pt 0pt; font-style: normal; font-weight: normal; font-family: 'trebuchet ms',arial,helvetica,sans-serif; float: none; position: static; left: auto; top: auto; line-height: normal; background-image: url('http://i.ixnp.com/images/v2.20/theme/silver/palette.gif'); background-color: transparent; width: 14px; height: 12px; background-position: -799px 0pt; background-repeat: no-repeat; text-decoration: none; visibility: visible; display: inline" /></a> for the how-to.</p>
<p><img src="http://www.techcrunch.com/wp-content/flightsim1.png" title="flightsim1.png" alt="flightsim1.png" align="left" height="243" width="280" /><br />
<img src="http://www.techcrunch.com/wp-content/sim1.jpg" title="sim1.jpg" alt="sim1.jpg" align="left" height="243" width="280" /></p>
<p><!-- sphereit end --></p>
]]></content:encoded>
			<wfw:commentRss>http://blogs.pinkcrow.net/google-earth%e2%80%99s-hidden-surprise-a-flight-simulator/52/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Top IT Starting Salaries</title>
		<link>http://blogs.pinkcrow.net/top-it-starting-salaries/51/</link>
		<comments>http://blogs.pinkcrow.net/top-it-starting-salaries/51/#comments</comments>
		<pubDate>Mon, 03 Sep 2007 05:44:07 +0000</pubDate>
		<dc:creator>Valeriu Buzila</dc:creator>
		
		<category><![CDATA[General]]></category>

		<guid isPermaLink="false">http://blogs.pinkcrow.net/top-it-starting-salaries/51/</guid>
		<description><![CDATA[

IT starting salaries vary widely depending on which field you choose. More than $37,000 separates the highest paying job from the lowest paying job in eWEEK&#8217;s list of IT starting salaries nationwide. 		
&#160;











]]></description>
			<content:encoded><![CDATA[<table border="0" cellpadding="0" cellspacing="0" width="100%">
<tr>
<td valign="top" width="65%"><span class="Article_Deck"><strong>IT starting salaries vary widely depending on which field you choose. More than $37,000 separates the highest paying job from the lowest paying job in eWEEK&#8217;s list of IT starting salaries nationwide.</strong> 		</span></td>
<td align="right" valign="top" width="35%">&nbsp;</td>
</tr>
<tr>
<td class="Article_Posts" colspan="2" align="left">
<table border="0" cellpadding="0" cellspacing="0" width="100%">
<tr>
<td class="content10" width="100%"><img src="http://common.ziffdavisinternet.com/util_get_image/18/0,1425,i=187057,00.gif" align="left" height="243" width="280" /></td>
</tr>
</table>
</td>
</tr>
</table>
]]></content:encoded>
			<wfw:commentRss>http://blogs.pinkcrow.net/top-it-starting-salaries/51/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Who&#8217;s afraid of Google?</title>
		<link>http://blogs.pinkcrow.net/whos-afraid-of-google/50/</link>
		<comments>http://blogs.pinkcrow.net/whos-afraid-of-google/50/#comments</comments>
		<pubDate>Mon, 03 Sep 2007 05:42:37 +0000</pubDate>
		<dc:creator>Valeriu Buzila</dc:creator>
		
		<category><![CDATA[General]]></category>

		<guid isPermaLink="false">http://blogs.pinkcrow.net/whos-afraid-of-google/50/</guid>
		<description><![CDATA[The world&#8217;s internet superpower faces testing times






&#160;








&#160;


RARELY if ever has a company risen so fast in so many ways as Google, the world&#8217;s most popular search engine. This is true by just about any measure: the growth in its market value and revenues; the number of people clicking in search of news, the nearest pizza [...]]]></description>
			<content:encoded><![CDATA[<p><font face="verdana,geneva,arial,sans serif" size="-1"><strong>The world&#8217;s internet superpower faces testing times</strong></font><br />
<br clear="all" /></p>
<table align="center" border="0" cellpadding="2" cellspacing="0" width="304">
<tr>
<td valign="top">
<table align="right" border="0" cellpadding="0" cellspacing="2">
<tr>
<td align="right" valign="top">&nbsp;</td>
</tr>
</table>
</td>
</tr>
<tr>
<td valign="bottom"><img src="http://www.economist.com/images/20070901/3507LD1.jpg" border="0" height="224" width="300" /></td>
</tr>
<tr>
<td valign="top">&nbsp;</td>
</tr>
</table>
<p><!--back--><font face="verdana,geneva,arial,sans serif" size="-1">RARELY if ever has a company risen so fast in so many ways as Google, the world&#8217;s most popular search engine. This is true by just about any measure: the growth in its market value and revenues; the number of people clicking in search of news, the nearest pizza parlour or a satellite image of their neighbour&#8217;s garden; the volume of its advertisers; or the number of its lawyers and lobbyists.</font></p>
<p><font face="verdana,geneva,arial,sans serif" size="-1">Such an ascent is enough to evoke concerns—both paranoid and justified. The list of constituencies that hate or fear Google grows by the week. Television networks, book publishers and newspaper owners feel that Google has grown by using their content without paying for it. Telecoms firms such as America&#8217;s <font size="-1">AT&amp;T</font> and Verizon are miffed that Google prospers, in their eyes, by free-riding on the bandwidth that they provide; and it is about to bid against them in a forthcoming auction for radio spectrum. Many small firms hate Google because they relied on exploiting its search formulas to win prime positions in its rankings, but dropped to the internet&#8217;s equivalent of Hades after Google tweaked these algorithms. </font></p>
<p><cf_floatingcontent></cf_floatingcontent><font face="verdana,geneva,arial,sans serif" size="-1">And now come the politicians. Libertarians dislike Google&#8217;s deal with China&#8217;s censors. Conservatives moan about its uncensored videos. But the big new fear is to do with the privacy of its users. Google&#8217;s business model (see <a href="http://www.economist.com/opinion/displaystory.cfm?story_id=9719610">article</a>) assumes that people will entrust it with ever more information about their lives, to be stored in the company&#8217;s “cloud” of remote computers. These data begin with the logs of a user&#8217;s searches (in effect, a record of his interests) and his responses to advertisements. Often they extend to the user&#8217;s e-mail, calendar, contacts, documents, spreadsheets, photos and videos. They could soon include even the user&#8217;s medical records and precise location (determined from his mobile phone).</font><br />
<font face="verdana, geneva, arial, sans serif"><strong><a title="more_jp_morgan_than_bill_gates" name="more_jp_morgan_than_bill_gates"></a>More JP Morgan than Bill Gates</strong></font></p>
<p><font face="verdana,geneva,arial,sans serif" size="-1">Google is often compared to Microsoft (another enemy, incidentally); but its evolution is actually closer to that of the banking industry. Just as financial institutions grew to become repositories of people&#8217;s money, and thus guardians of private information about their finances, Google is now turning into a custodian of a far wider and more intimate range of information about individuals. Yes, this applies also to rivals such as Yahoo! and Microsoft. But Google, through the sheer speed with which it accumulates the treasure of information, will be the one to test the limits of what society can tolerate.</font></p>
<p><font face="verdana,geneva,arial,sans serif" size="-1">It does not help that Google is often seen as arrogant. Granted, this complaint often comes from sour-grapes rivals. But many others are put off by Google&#8217;s cocksure assertion of its own holiness, as if it merited unquestioning trust. This after all is the firm that chose “Don&#8217;t be evil” as its corporate motto and that explicitly intones that its goal is “not to make money”, as its boss, Eric Schmidt, puts it, but “to change the world”. Its ownership structure is set up to protect that vision. </font></p>
<p><font face="verdana,geneva,arial,sans serif" size="-1">Ironically, there is something rather cloudlike about the multiple complaints surrounding Google. The issues are best parted into two cumuli: a set of “public” arguments about how to regulate Google; and a set of “private” ones for Google&#8217;s managers, to do with the strategy the firm needs to get through the coming storm. On both counts, Google—contrary to its own propaganda—is much better judged as being just like any other “evil” money-grabbing company.</font><br />
<font face="verdana, geneva, arial, sans serif"><strong><a title="grab_the_money" name="grab_the_money"></a>Grab the money</strong></font></p>
<p><font face="verdana,geneva,arial,sans serif" size="-1">That is because, from the public point of view, the main contribution of all companies to society comes from making profits, not giving things away. Google is a good example of this. Its “goodness” stems less from all that guff about corporate altruism than from Adam Smith&#8217;s invisible hand. It provides a service that others find very useful—namely helping people to find information (at no charge) and letting advertisers promote their wares to those people in a finely targeted way.</font></p>
<p><font face="verdana,geneva,arial,sans serif" size="-1"> Given this, the onus of proof is with Google&#8217;s would-be prosecutors to prove it is doing something wrong. On antitrust, the price that Google charges its advertisers is set by auction, so its monopolistic clout is limited; and it has yet to use its dominance in one market to muscle into others in the way Microsoft did. The same presumption of innocence goes for copyright and privacy. Google&#8217;s book-search product, for instance, arguably helps rather than hurts publishers and authors by rescuing books from obscurity and encouraging readers to buy copyrighted works. And, despite Big Brotherish talk about knowing what choices people will be making tomorrow, Google has not betrayed the trust of its users over their privacy. If anything, it has been better than its rivals in standing up to prying governments in both America and China.</font></p>
<p><font face="verdana,geneva,arial,sans serif" size="-1">That said, conflicts of interest will become inevitable—especially with privacy. Google in effect controls a dial that, as it sells ever more services to you, could move in two directions. Set to one side, Google could voluntarily destroy very quickly any user data that it collects. That would assure privacy, but it would limit Google&#8217;s profits from selling to advertisers information about what you are doing, and make those services less useful. If the dial is set to the other side and Google hangs on to the information, the services will be more useful, but some dreadful intrusions into privacy could occur.</font></p>
<p><font face="verdana,geneva,arial,sans serif" size="-1">The answer, as with banks in the past, must lie somewhere in the middle; and the right point for the dial is likely to change, as circumstances change. That will be the main public interest in Google. But, as the bankers (and Bill Gates) can attest, public scrutiny also creates a private challenge for Google&#8217;s managers: how should they present their case?</font></p>
<p><font face="verdana,geneva,arial,sans serif" size="-1"> One obvious strategy is to allay concerns over Google&#8217;s trustworthiness by becoming more transparent and opening up more of its processes and plans to scrutiny. But it also needs a deeper change of heart. Pretending that, just because your founders are nice young men and you give away lots of services, society has no right to question your motives no longer seems sensible. Google is a capitalist tool—and a useful one. Better, surely, to face the coming storm on that foundation, than on a trite slogan that could be your undoing. </font></p>
]]></content:encoded>
			<wfw:commentRss>http://blogs.pinkcrow.net/whos-afraid-of-google/50/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Points of Attack: PHP and Ajax</title>
		<link>http://blogs.pinkcrow.net/points-of-attack-php-and-ajax/49/</link>
		<comments>http://blogs.pinkcrow.net/points-of-attack-php-and-ajax/49/#comments</comments>
		<pubDate>Sun, 02 Sep 2007 14:17:00 +0000</pubDate>
		<dc:creator>Valeriu Buzila</dc:creator>
		
		<category><![CDATA[Software]]></category>

		<guid isPermaLink="false">http://blogs.pinkcrow.net/points-of-attack-php-and-ajax/49/</guid>
		<description><![CDATA[It’s easy to get caught up in the dynamic potential of Ajax. But with innumerable possibilities also comes increased risk. If security isn’t a major concern, it should be.Consider a registration form built out of PHP. Any aspect of your script that accepts and processes data is a potential point of attack. If you add [...]]]></description>
			<content:encoded><![CDATA[<p>It’s easy to get caught up in the dynamic potential of Ajax. But with innumerable possibilities also comes increased risk. If security isn’t a major concern, it should be.Consider a registration form built out of PHP. Any aspect of your script that accepts and processes data is a potential point of attack. If you add Ajax, what you’re doing is increasing the complexity of the application and, by extension, introducing greater vulnerability. More points of entry equal a larger attack surface, and that means potential problems for your application.</p>
<p>Consider the sequence of a user trying to select a username in a standard PHP and MySQL form. Information is entered into the fields, data is then submitted to the server to be checked against a database of existing names, and an error message is returned to the user. There is one point of attack in this scenario—the form processor. But what happens when the form is submitted using an Ajax validator?</p>
<p>The Ajax verification process is simplified because results are returned in real time. Although the form would still be submitted for validation against an existing database of stored usernames, the Ajax tool quickens the process by providing immediate feedback on the likelihood any given username is available. Although the Ajax implementation is more user friendly, the total points of attack have doubled—the original form processor and the username validation. There are two useful techniques for minimizing points of attack.</p>
<p>First, you should keep all related entry points within the same script. If you’re validating an unusually long form then try and use the same PHP script for the entire validation. You wouldn’t want to use individual scripts to validate a number of fields, although I’m not sure why you’d want to do this. Second, you should consider using standard functions for processing user input. You probably don’t want HTML tags in your database, so it’s a good idea to use PHPs built in functions. It makes sense to use strip_tags() for removing unnecessary tags and then running mysql_real_escape_string() prior to database insertion.</p>
<p>The rule of thumb is to use PHPs existing functions because they’ve been rigorously tested by many developers.</p>
<p>• htmlentities: outputs in literal tags<br />
• mysql_real_escape_string: prevents SQL injection and error<br />
• preg_quote: safe to use in a regular expression<br />
• preg_replace: removes unwanted characters from a string<br />
• strip_tags: removes any HTML tags from a string</p>
]]></content:encoded>
			<wfw:commentRss>http://blogs.pinkcrow.net/points-of-attack-php-and-ajax/49/feed/</wfw:commentRss>
		</item>
		<item>
		<title>OpenAjax Alliance - A Remarkable First Year</title>
		<link>http://blogs.pinkcrow.net/openajax-alliance-a-remarkable-first-year/48/</link>
		<comments>http://blogs.pinkcrow.net/openajax-alliance-a-remarkable-first-year/48/#comments</comments>
		<pubDate>Sun, 02 Sep 2007 14:12:11 +0000</pubDate>
		<dc:creator>Valeriu Buzila</dc:creator>
		
		<category><![CDATA[Software]]></category>

		<guid isPermaLink="false">http://blogs.pinkcrow.net/openajax-alliance-a-remarkable-first-year/48/</guid>
		<description><![CDATA[The OpenAjax Alliance is a consortium of companies that are active in the 
AJAX industry. It was founded on May 15, 2006, concluded a governing Members Agreement in October 2006 and now has more than 80 member organizations, including industry giants such as Adobe, BEA, Cisco, ESRI, Fidelity, Google, IBM, Microsoft, Mozilla, Oracle, SAP, and [...]]]></description>
			<content:encoded><![CDATA[<p class="MsoNormal">The OpenAjax Alliance is a consortium of companies that are active in the <city w:st="on"></city></p>
<place w:st="on">AJAX</place> industry. It was founded on May 15, 2006, concluded a governing Members Agreement in October 2006 and now has more than 80 member organizations, including industry giants such as Adobe, BEA, Cisco, ESRI, Fidelity, Google, IBM, Microsoft, Mozilla, Oracle, SAP, and Sun. The alliance’s home page at <a href="http://www.openajax.org/" title="http://www.openajax.org">http://www.openajax.org</a> shows the full list of members. <img src="http://res.sys-con.com/story/aug07/421046/OpenAjax_226.gif" align="right" hspace="12" vspace="12" />The alliance pursues both technical and marketing initiatives. Its technical initiatives are centered on <city w:st="on"></city></p>
<place w:st="on">AJAX</place> interoperability. Its marketing initiatives focus on educational materials that help IT managers and Web developers be successful with <city w:st="on"></city></p>
<place w:st="on">AJAX</place>. The OpenAjax Alliance collects no fees from its members and therefore has no dedicated staff. All participation is provided by the member organizations on a voluntary basis. Given this background, the activities after approximately one year of operation are remarkable. This article summarizes the OpenAjax Alliance’s many accomplishments to date and its plans for the future. <span style="font-weight: bold">Organizational Accomplishments</span><br />
Since the kick-off meeting in May 2006, the organization has:</p>
<ul>
<li>Grown to 86 members (as of early August 2007)</li>
<li>Established a formal IP policy where each member has agreed to a royalty-free patent covenant for technologies defined within OpenAjax specifications</li>
<li>Established a lightweight formal governance model, where the members elect a Steering Committee of seven member organizations. In the first election, the members elected Dojo Foundation, Eclipse Foundation, IBM, Nexaweb, TIBCO, Zend, and Zimbra to the Steering Committee.</li>
<li>Agreed to a formal Development Process for establishing Working Groups and advancing Specifications</li>
<li>Approved Three Working Groups – Marketing, Interoperability, and IDE – and launched Four Task Forces (Server, Communications Hub, Security and <city w:st="on">
<place w:st="on">Mobile</place></city>)</li>
</ul>
<p class="MsoNormal"><a title="White__papers" name="White__papers"></a></p>
<p><span style="font-weight: bold">White Papers</span><br />
The Marketing Working Group has responsibility for OpenAjax Alliance’s communication, educational, and promotional activities. This group has published a series of white papers (found at <a href="http://www.openajax.org/White%20Papers.html" title="http://www.openajax.org/White%20Papers.html">http://www.openajax.org/White%20Papers.html</a>) that help Web developers and IT managers learn how to be successful with <city w:st="on"></city></p>
<place w:st="on">AJAX</place>. The first five white papers are:</p>
<ul>
<li>“Introducing <city w:st="on">
<place w:st="on">AJAX</place></city> and OpenAjax”</li>
<li>“When Does <city w:st="on">
<place w:st="on">AJAX</place></city> Make Business Sense”</li>
<li>“Next-Generation Applications Using <city w:st="on">
<place w:st="on">AJAX</place></city> and OpenAjax”</li>
<li>“Successful Deployment of <city w:st="on">
<place w:st="on">AJAX</place></city> and OpenAjax”</li>
<li>“<city w:st="on">
<place w:st="on">AJAX</place></city> and Mashup Security”</li>
</ul>
<p class="MsoNormal"><a title="OpenAjax_Hub" name="OpenAjax_Hub"></a><span style="font-weight: bold">OpenAjax Hub</span><br />
To date, the most important product to come out of the Interoperability Working Group is release 1.0 of the OpenAjax Hub. The “Hub” is a small amount of standard JavaScript (&lt; 3K after compaction) that enables multiple <city w:st="on"></city></p>
<place w:st="on">AJAX</place> runtimes used within the same Web page to communicate with each other via the Hub’s publish/subscribe engine.In the past year, the alliance studied use cases and requirements, authored a complete specification, developed an open source reference implementation, and produced a comprehensive test suite for OpenAjax Hub 1.0. There were two different “InteropFests” where multiple <city w:st="on"></city></p>
<place w:st="on">AJAX</place> toolkits used the Hub in sample applications to verify its feature set and the quality of the open source reference implementation. The alliance is just beginning work on OpenAjax Hub 1.1, which is likely to extend the publish/subscribe features from Hub 1.0 to address Comet-style server-push communications, cross-frame messaging and secure mashups.</p>
<p class="MsoNormal"><a title="OpenAjax_Registry" name="OpenAjax_Registry"></a></p>
<p><strong>OpenAjax Registry </strong>The Interoperability Working Group has begun work on the OpenAjax Registry, which will provide a centralized, industry-wide <city w:st="on">AJAX</city> toolkit and JavaScript global object registration authority that helps prevent JavaScript object collision within complex <city w:st="on"></city></p>
<place w:st="on">AJAX</place> applications. At this point, the process and rules for the “Registry” are under active development. <city w:st="on"></city></p>
<place w:st="on"><strong>AJAX</strong></place><strong> Developer Tools (IDEs) </strong>In the spring of 2007, the alliance approved an IDE Working Group that is addressing interoperability issues between <city w:st="on">AJAX</city> toolkits and <city w:st="on"></city></p>
<place w:st="on">AJAX</place> developer tools (i.e., IDEs). The working group will specify a standard metadata format for describing the UI controls and JavaScript APIs within a given <city w:st="on"></city></p>
<place w:st="on">AJAX</place> toolkit. The metadata standard will enable an AJAX IDE to populate its widget palettes with icons, auto-generate property editor dialogs, and offer completion/code assist for JavaScript APIs. The working group includes participants who are associated with Adobe Dreamweaver, Aptana, Eclipse AJAX Toolkit Framework, Microsoft ASP.NET AJAX, Microsoft Visual Studio, TIBCO, and NetBeans. The working group has completed its work on use cases and requirements and has begun work on the metadata specification.</p>
<p class="MsoNormal"><a title="Ajax_Security" name="Ajax_Security"></a></p>
<p><city w:st="on"></city></p>
<place w:st="on"><strong>AJAX</strong></place><strong> Security </strong>The Security Task Force began its work in June 2007. Its first product was the white paper titled “<city w:st="on"></city></p>
<place w:st="on">AJAX</place> and Mashup Security,” which was written and published in collaboration with the Marketing Working Group. The task force has begun work on a wiki page that serves as a central information launching point for <city w:st="on">AJAX</city> developers to learn about <city w:st="on"></city></p>
<place w:st="on">AJAX</place> security concerns and techniques for addressing them. Going forward, the Security Task Force is likely to collaborate closely with the Interoperability Working Group on any OpenAjax Hub 1.1 efforts around secure mashups. <span style="font-weight: bold">Mobile </span><city w:st="on" style="font-weight: bold"></city></p>
<place w:st="on">AJAX</place> The alliance has recently launched its Mobile AJAX Task Force. The task force is working on a Mobile AJAX white paper that will summarize the current state of affairs with Mobile AJAX and provide guidance to developers to successfully deliver Mobile AJAX applications today. The task force also has begun investigations into what the OpenAjax Alliance might do in the area of mobile device APIs. <strong>Emerging Efforts around <city w:st="on"></city></p>
<place w:st="on">AJAX</place> Performance and Searchability </strong>The members of the OpenAjax Alliance are in the process of establishing two new task forces. One, called the Production AJAX Management Task Force, will center on <city w:st="on"></city></p>
<place w:st="on">AJAX</place> runtime performance monitoring. The other, called the AJAX Searchability Task Force, will focus on improving the ability of search engines to do a better job of indexing</p>
<place w:st="on"><city w:st="on">AJAX</city></place> applications. <span style="font-weight: bold">OpenAjax Conformance Trust Brand</span><br />
The Marketing Working Group has established a long-term promotional vision centered on the OpenAjax Conformance trust brand. OpenAjax Conformance is shorthand for the set of conformance requirements that OpenAjax Alliance will place on <city w:st="on"></city></p>
<place w:st="on">AJAX</place> technologies, products and applications. Conformance is defined by OpenAjax Alliance specifications and facilitated by the alliance’s open source efforts. The OpenAjax Alliance will promote OpenAjax Conformance among all stakeholders in the <city w:st="on"></city></p>
<place w:st="on">AJAX</place> industry. OpenAjax Conformance provides the following benefits to IT managers and the <city w:st="on"></city></p>
<place w:st="on">AJAX</place> developer community:</p>
<ul>
<li>Seamless integration of multiple <city w:st="on">
<place w:st="on">AJAX</place></city> products and technologies within the same Web application, particularly with applications that use mashup techniques</li>
<li>Greater certainty about product choices, where OpenAjax Conformance plays a similar role in the <city w:st="on">
<place w:st="on">AJAX</place></city> community as the Good Housekeeping Seal does with consumer products</li>
<li>Lower training costs, lower development costs, and faster delivery of Web 2.0 innovations due to industry adoption of common approaches that build from OpenAjax standards</li>
<li>Interchangeability of OpenAjax Conformant products, so that customers can choose among multiple vendors and change vendors in the future</li>
</ul>
<p class="MsoNormal"><span style="font-weight: bold">Conclusion</span><br />
In just over one year, the OpenAjax Alliance has compiled a strong record of accomplishment. It has established key legal and organizational processes. The Marketing Working Group has produced valuable education materials for IT managers and <city w:st="on"></city></p>
<place w:st="on">AJAX</place> developers. The Interoperability Working Group has completed OpenAjax Hub 1.0. The next year promises further contributions to the industry on multiple fronts.</p>
]]></content:encoded>
			<wfw:commentRss>http://blogs.pinkcrow.net/openajax-alliance-a-remarkable-first-year/48/feed/</wfw:commentRss>
		</item>
		<item>
		<title>PHP Multiple Vulnerabilities</title>
		<link>http://blogs.pinkcrow.net/php-multiple-vulnerabilities/47/</link>
		<comments>http://blogs.pinkcrow.net/php-multiple-vulnerabilities/47/#comments</comments>
		<pubDate>Sun, 02 Sep 2007 14:11:32 +0000</pubDate>
		<dc:creator>Valeriu Buzila</dc:creator>
		
		<category><![CDATA[Software]]></category>

		<guid isPermaLink="false">http://blogs.pinkcrow.net/php-multiple-vulnerabilities/47/</guid>
		<description><![CDATA[Some vulnerabilities have been reported in PHP, where some have unknown impacts and others can be exploited by malicious users to bypass certain security restrictions.
1) An error with unknown impact exists within the &#8220;money_format()&#8221; function when processing &#8220;%i&#8221; and &#8220;%n&#8221; tokens.
2) An unspecified error exists within the &#8220;zend_alter_ini_entry()&#8221; function. This can be exploited to trigger [...]]]></description>
			<content:encoded><![CDATA[<p>Some vulnerabilities have been reported in PHP, where some have unknown impacts and others can be exploited by malicious users to bypass certain security restrictions.</p>
<p>1) An error with unknown impact exists within the &#8220;money_format()&#8221; function when processing &#8220;%i&#8221; and &#8220;%n&#8221; tokens.</p>
<p>2) An unspecified error exists within the &#8220;zend_alter_ini_entry()&#8221; function. This can be exploited to trigger a memory_limit interruption.</p>
<p>3) Two integer overflow errors exist within the &#8220;gdImageCreate()&#8221; and &#8220;gdImageCreateTrueColor()&#8221; functions in ext/gd/libgd/gd.c. These can be exploited to cause a heap-based buffer overflow via overly large integer values passed as parameters to e.g. the &#8220;imagecreatetruecolor()&#8221; PHP function.</p>
<p>4) Two integer overflow errors exist within the &#8220;gdImageCopyResized()&#8221; function in ext/gd/libgd/gd.c. These can be exploited to cause a heap-based buffer overflow via overly large integer values passed as parameters to the &#8220;imagecopyresized()&#8221; or &#8220;imagecopyresampled()&#8221; PHP functions.</p>
<p>Successful exploitation of vulnerabilities #3 and #4 may allow execution of arbitrary code, which may lead to security restrictions (e.g. the &#8220;disable_functions&#8221; directive) being bypassed, but requires that PHP is configured to use gd.</p>
<p>5) An error exists within the handling of SQL queries containing &#8220;LOCAL INFILE&#8221; inside the MySQL and MySQLi extensions. This can be exploited to bypass the &#8220;open_basedir&#8221; and &#8220;safe_mode&#8221; directives.</p>
<p>6) An error exists when processing &#8220;session_save_path()&#8221; and &#8220;ini_set()&#8221; functions called from a &#8220;.htaccess&#8221; file. This can be exploited to bypass the &#8220;open_basedir&#8221; and &#8220;safe_mode&#8221; directives.</p>
<p>7) An unspecified error exists within the &#8220;glob()&#8221; function. This can be exploited to bypass the &#8220;open_basedir&#8221; directive.</p>
<p> <img src='http://blogs.pinkcrow.net/wp-includes/images/smilies/icon_cool.gif' alt='8)' class='wp-smiley' /> An unspecified error exists within the session extension. This can potentially be exploited to bypass the &#8220;open_basedir&#8221; directive when the session file is a symlink.</p>
<p>The vulnerabilities are reported in PHP versions prior to 5.2.4.</p>
<p><strong>Solution</strong>:<br />
Update to PHP version 5.2.4.<br />
<a href="http://www.php.net/downloads.php" target="_blank">http://www.php.net/downloads.php</a></p>
<p><strong>Provided and/or discovered by</strong>:<br />
1) The vendor credits Stanislav Malyshev.<br />
2) The vendor credits Stefan Esser.<br />
3, 4) Mattias Bengtsson and Philip Olausson.<br />
5) The vendor credits Stanislav Malyshev. Also reported by Mattias Bengtsson and Philip Olausson.<br />
6) The vendor credits Maksymilian Arciemowicz.<br />
7) The vendor credits dr.<br />
 <img src='http://blogs.pinkcrow.net/wp-includes/images/smilies/icon_cool.gif' alt='8)' class='wp-smiley' /> The vendor credits  c.i.morris.</p>
]]></content:encoded>
			<wfw:commentRss>http://blogs.pinkcrow.net/php-multiple-vulnerabilities/47/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Google Takes AJAX Debugger Out of Beta</title>
		<link>http://blogs.pinkcrow.net/google-takes-ajax-debugger-out-of-beta/46/</link>
		<comments>http://blogs.pinkcrow.net/google-takes-ajax-debugger-out-of-beta/46/#comments</comments>
		<pubDate>Sun, 02 Sep 2007 14:10:15 +0000</pubDate>
		<dc:creator>Valeriu Buzila</dc:creator>
		
		<category><![CDATA[Software]]></category>

		<guid isPermaLink="false">http://blogs.pinkcrow.net/google-takes-ajax-debugger-out-of-beta/46/</guid>
		<description><![CDATA[Google has long maintained that AJAX is the future (and the now) of the Web, and even refers to the click-and-wait method as &#8220;the yesterweb.&#8221; But for developers, AJAX is a pain, especially when debugging for browser quirks. Those struggling, then, may be happy to know that the Google Web Toolkit is now out of [...]]]></description>
			<content:encoded><![CDATA[<p><strong><strong>Google has long maintained that AJAX is the future (and the now) of the Web, and even refers to the click-and-wait method as &#8220;the yesterweb.&#8221; But for developers, AJAX is a pain, especially when debugging for browser quirks. Those struggling, then, may be happy to know that the Google Web Toolkit is now out of beta with version 1.4.</strong></strong></p>
<p>And it&#8217;s true, the Web has evolved well beyond basic HTML and is full-on Web 2.0, where sites like Facebook allow developers to develop applications, mashups, and gadgets for its users.</p>
<p>The roadblocks are the various browsers out there and creating an application that works on all of them is not just difficult but time consuming. So it&#8217;s rather nice of Google to offer up an open source solution like GWT that aims to speed up the debugging process.</p>
<p>Once the front-end Java programming language is written, the GWT compiler converts Java classes to browser-compliant JavaScript and HTML.</p>
<p>Bruce Johnson and Dan Peterson of the Google Web Toolkit Team write:</p>
<blockquote><p><em>In addition to making debugging far easier, GWT&#8217;s unique compilation-based approach to AJAX has the nice property that it rewards developers for good software engineering practices. Java source code that is clear and organized can be easily optimized by the GWT compiler, which is a nice antidote to the frequent hack-and-slash approach that&#8217;s all too common in JavaScript development. As your application grows, the GWT compiler begins to pay off in even bigger ways. </em></p></blockquote>
<p>Unused code is automatically removed so that scripts are smaller and pages load faster. Complex code can be automatically coalesced and simplified. Most importantly, because the Java language is statically typed, many common errors can be caught during development rather than production.</p>
<p>Google&#8217;s <a href="http://code.google.com/webtoolkit/download.html" title="download">Web Toolkit Version 1.4 for Windows</a> can be downloaded at the company&#8217;s code website, and is licesensed under the Apache 2.0 open source license.</p>
]]></content:encoded>
			<wfw:commentRss>http://blogs.pinkcrow.net/google-takes-ajax-debugger-out-of-beta/46/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Free framework looks to simplify Ajax development</title>
		<link>http://blogs.pinkcrow.net/free-framework-looks-to-simplify-ajax-development/45/</link>
		<comments>http://blogs.pinkcrow.net/free-framework-looks-to-simplify-ajax-development/45/#comments</comments>
		<pubDate>Sun, 02 Sep 2007 14:09:21 +0000</pubDate>
		<dc:creator>Valeriu Buzila</dc:creator>
		
		<category><![CDATA[Software]]></category>

		<guid isPermaLink="false">http://blogs.pinkcrow.net/free-framework-looks-to-simplify-ajax-development/45/</guid>
		<description><![CDATA[&#160;
Adobe is focusing on less-technical persons, while many libraries like jQuery focus on Web developers to utilise and extend their library code.
Adobe states that the Spry framework for Ajax is meant primarily for users who are Web design professionals or advanced nonprofessional Web designers. It is not intended as a full Web application framework for [...]]]></description>
			<content:encoded><![CDATA[<p id="story" class="clearfix">&nbsp;</p>
<p class="smdeck">Adobe is focusing on less-technical persons, while many libraries like jQuery focus on Web developers to utilise and extend their library code.</p>
<p>Adobe states that the Spry framework for Ajax is meant primarily for users who are Web design professionals or advanced nonprofessional Web designers. It is not intended as a full Web application framework for enterprise-level Web development. With that said, here&#8217;s a look at getting and using it.</p>
<p><strong>It is free</strong></p>
<p>The Spry framework is currently at a prerelease version of 1.5. It is <a href="http://www.adobe.com/cfusion/entitlement/index.cfm?e=labs_spry">freely available</a> from the Adobe Labs site; it does require registration with a valid e-mail address to complete the download. You download it in a single, compressed file. And, you can extract and install it to a directory on a Web server to be up and running in minutes.</p>
<p>As an example, I downloaded and installed it on a local development machine running Microsoft Internet Information Server (IIS) in the following directory:</p>
<p><code>c:inetpubwwwrootspry_p1_5_051707</code></p>
<p>Using this directory, the samples included with the download are easily accessed via the following local URL on the machine:</p>
<p><code>http://localhost/samples/index.html</code></p>
<p><strong>Three easy pieces</strong></p>
<p>Spry is made available for use in your applications via the <a href="http://labs.adobe.com/technologies/eula/spry.html">BSD License</a>. The framework includes three main sections of functionality: Data, Widgets, and Effects.</p>
<p><strong>|&gt; </strong><strong>Data:</strong> The Data API includes various functions for working with XML-based data. Spry creates datasets by making calls to the XML data sources URLs. Datasets can be tied together in a master/detail relationship, as well as easily displayed by tying them to regions of a page.<br />
<strong>|&gt; </strong><strong>Widgets:</strong> The Widget API allows you to tie together HTML, CSS, and JavaScript code for user interaction. The HTML defines its structure, CSS defines its presentation, and JavaScript defines its behavior, such as responding to user actions.<br />
<strong>|&gt; </strong><strong>Effects:</strong> The Effects API provides the ability to easily apply visual enhancements to almost any element on an HTML page. The current iteration of the framework includes the following effects: fade, highlight, blind up/down, slide up/down, grow, shake, and squish. Spry uses the script.aculo.us library for some effects.<br />
The APIs are available in the JavaScript library files installed with the framework. They are located in the includes subdirectory of the Spry installation.</p>
<p><strong>Drawbacks</strong></p>
<p>One of the most frustrating aspects of Web development is ensuring an application works in various browsers. This involves ensuring the application degrades gracefully to work in browsers with minimal capabilities, including a lack of JavaScript support. With JavaScript being a central player in the AJAX acronym, a lack of it means it just won&#8217;t work.</p>
<p>This is where the application should be designed to work without Ajax, and the Spry framework has not been designed to gracefully degrade. In fact, it does not work if JavaScript is disabled in the browser; you must keep this in mind if you use Spry. The onus of graceful degradation rests with the developer.</p>
<p>Another concern with the Spry framework is the use of nonstandard attributes for HTML elements like the DIV tag. This type of design can cause pages using such code to not function in certain browsers. Adobe says the current version of Spry has been tested with Firefox 1.5, Internet Explorer 6, Safari 2.0.3, and Netscape 7.2. You can find more details on this point and other issues in the <a href="http://labs.adobe.com/wiki/index.php/Spry:FAQ">Spry framework FAQ</a>.</p>
<p><strong>My impressions</strong></p>
<p>I find the Spry library a bit more complex than expected given its target audience of the less-than-JavaScript-savvy Web designer community. While it is easy to create data sources based upon XML, using these data sources relied upon my JavaScript knowledge. I did like the various features of the toolkit, but it makes me wonder how much a person with limited JavaScript knowledge will able to accomplish with Spry.</p>
<p><strong>Spry gives you another option</strong></p>
<p>Once upon a time it was hard to locate JavaScript libraries that simplified incorporating Ajax functionality in a Web application, but now the number of freely available libraries is a bit overwhelming. The niche aspect of the Spry framework for Ajax is that Adobe is targeting Web designers who are less technical. The framework does provide cool and usable features via its data support, as well as widgets and effects.</p>
<p>Have you worked with the Adobe Spry framework or any other freely available JavaScript libraries? Share your experience and preferences with the Web development community.</p>
]]></content:encoded>
			<wfw:commentRss>http://blogs.pinkcrow.net/free-framework-looks-to-simplify-ajax-development/45/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Microsoft Silverlight - a visual feast</title>
		<link>http://blogs.pinkcrow.net/microsoft-silverlight-a-visual-feast/44/</link>
		<comments>http://blogs.pinkcrow.net/microsoft-silverlight-a-visual-feast/44/#comments</comments>
		<pubDate>Sun, 02 Sep 2007 14:08:39 +0000</pubDate>
		<dc:creator>Valeriu Buzila</dc:creator>
		
		<category><![CDATA[Software]]></category>

		<guid isPermaLink="false">http://blogs.pinkcrow.net/microsoft-silverlight-a-visual-feast/44/</guid>
		<description><![CDATA[A major new development from Microsoft is Silverlight – a cross-browser, cross-platform plugin which is designed to deliver a rich, interactive online media experience. It leverages off existing programming languages like AJAX, VB, C#, Python and Ruby, and can integrate with just about anything that’s out there.
At the recent Microsoft Tech.Ed 2007 convention I caught [...]]]></description>
			<content:encoded><![CDATA[<p>A major new development from Microsoft is Silverlight – a cross-browser, cross-platform plugin which is designed to deliver a rich, interactive online media experience. It leverages off existing programming languages like AJAX, VB, C#, Python and Ruby, and can integrate with just about anything that’s out there.</p>
<p>At the recent Microsoft Tech.Ed 2007 convention I caught up with Michael Kordahi, a Silverlight product evangelist to find what makes Silverlight tick.</p>
<p><span class="inline middle"><a href="http://www.apcmag.com/" onclick="launch_popup(7039, 640, 426); return false;" target="_blank"><img src="http://apcmag.com/system/files/images/DSC_0006.article-width.JPG" alt="Michael Kordahi" title="Michael Kordahi" class="image article-width" align="left" height="266" width="400" /></a><span class="caption" style="width: 398px"><strong>Michael Kordahi</strong></span></span></p>
<hr size="2" width="100%" /><strong>MK:</strong> The easiest way to describe Silverlight is that it&#8217;s a plug in for your browser which allows you to experience rich interactive content. If you consider the internet stack today, you have HTML, HTML scripting where you can modify bits of the DOM, and then Ajax came along and loaded with it with really nice, rich content. Ajax does a fantastic job and it&#8217;s all Javascript, really. We think the next level up is something like Silverlight, which sits within your browser but instead of being part of the DOM, it&#8217;s a plug in.<strong>JB:</strong>    An ActiveX control?</p>
<p><strong>MK:</strong> Well that depends on the browser – it’s an ActiveX control on IE and an add-in for Firefox. It also runs fine on Safari and Opera. Essentially it&#8217;s a rich bit of code that runs anywhere within the browser - it can fill the entire browser or just parts of the screen. But it allows you to add interactivity with animation and media. Then there’s the next level again which is based on WPF. WPF allows you to create rich desktop apps that touch the GPU so you can create graphics-intensive browser applications. You can also touch local file systems to cache video and interact directly with .NET. If the world was all Vista, WPF would be a beautiful thing. You can do really rich stuff like zooming into infinite levels of detail because at that point you’re touching the graphics hardware of your machine. You can do great things like creating 3D spinning spheres and all that sort of stuff.</p>
<p>Silverlight is focused on being cross browser and cross platform so that anybody can use it, so it’s best to think of it as a browser-based plugin. Silverlight 1.0 is in RC (Release Candidate) at the moment and the final release will be out soon. 1.0 is all scriptable via Javascript which we’re finding to be of great value for developers - there’s not much of a learning curve for them to start using it straight away.</p>
<p>Orcas is the next release for Visual Studio. From my personal experience, one of the biggest improvements in it is the Javascript capabilities. Now you can do telesense, colour code, bit bugging&#8230;all sorts of things, and you can fully interact with the Silverlight object.</p>
<p>The two values of that are:</p>
<p>(a) you’re using a model that you understand, but</p>
<p>(b) you have the ability to interface with other non-specific pages.</p>
<p>If you look at what Discovery Channel did recently – Discovery Channel Asia – they built a site called Never Miss TV. If you missed a show on the Discovery Channel you can go on the website and watch last night’s episodes of the shows. But the bit that they didn’t have right was the video playback method, which they had a lot of trouble with. Now they’ve got Windows Media server at the backend and it&#8217;s all streaming WMV.</p>
<p>What they did was build a Silverlight player which gave them the basic player framework with slider controls and volumes but the rest of the site was all HTML and AJAX. So when you add a playlist or sign-in, you’re doing it through their existing site but then when they want the media player to play a video, they just pull a method on the player and play the video. And that’s the real advantage of being able to interact with the Silverlight object via Javascript.</p>
<p>So that’s version 1.0. Version 1.1 is in alpha release at the moment and that adds a layer on top, which will enable you to have a runtime on the player. It comes with a CLR which is the common language runtime, which is a cut-down version of .NET Framework. You can write C# code, IronRuby, IronPython or Javascript. There’s a whole bunch of demos demonstrating how fast the performance is. It&#8217;s going to bring a whole bunch of languages which people already know and understand and allow them to do Silverlight as well.</p>
<p>It’s secure as well – it exists in a virtual environment. The browser essentially controls what happens at the system level to ensure you can’t do anything malicious. It&#8217;s the same on the Mac too - it&#8217;s a virtual environment that looks the same on the Mac and on the PC.</p>
<p>The significant thing about this – and this is a problem that many companies are faced with today – is that there’s a lot of investment in Windows Media backend infrastructure. There’s all this WMV content out on the web. How do you put that in the browser? You can embed the media player, and write a whole bunch of code to make it run on non-IE browsers, but it&#8217;s not the most pleasant nor the easiest way to go.</p>
<p>That’s one of the fundamental things Silverlight addresses. It allows you to create using a cross-platform standard. If a video opens on a Mac it will look exactly the same as on Windows. It allows you to use one standard interface to deliver Windows Media to the client and add richness to it so things like video overlays, tracking and menus work seamlessly.</p>
<p><strong>JB:</strong>    What tools do you need to build your own Silverlight container?</p>
<p><strong>MK:</strong>    There’s a suite of products called <a href="http://www.microsoft.com/expression/" target="_blank">Expression Suite</a> which came out in April, which is composed of four products – there’s Expression Web, Expression Blend, Expression Design and Expression Media. If you go to silverlight.net there’s information on all those products, as well as a load of Silverlight demos. Expression Web is essentially a web editing tool - HTML, Javascript and CSS.</p>
<p>FrontPage has kind of gone onto a new life as part of the Office Suite and is very much focused on creating content within SharePoint. Internal office productivity stuff. Expression Web is really about considering standards when you’re building sites. So one of the biggest bits of feedback from FrontPage is that it&#8217;s actually too clever. It adds a whole bunch of features that you didn’t want it to do. So what Expression Web does is it&#8217;s very much built around CSS, everything happens in DIVs and it&#8217;s very much a web based, web standards orientated tool.</p>
<p><strong>JB:</strong>    Very similar to Dreamweaver in that aspect.</p>
<p><strong>MK:</strong> They fulfil the same requirements. So that’s Expression Web. Expression Blend is probably the most significant product in the suite in my opinion. Expression Blend is where you create canvases. Expression Blend is a very designer-orientated illustration tool so that you can create canvases in a visual environment.</p>
<p>Then, all the images and assets components of your projects sit in Expression Media. But Blend is where your designer will design and create the canvases, so that’s really the most important application. Significantly Blend produces something called <a href="http://msdn2.microsoft.com/en-us/library/ms752059.aspx" target="_blank">XAML</a> and that’s the key - eXtensible Application Markup Language. When a designer uses Blend and paints a canvas they produce this XML file called XAML. A Visual Studio developer can open the same file. So the Visual Studio developer goes away and works on their aspect of the application, while at the same time the designer can continue to refine the interface.</p>
<p>What happens today is that when a designer goes and designs a site, there’s a point where they have to stop working and hand it over to a developer. Then any changes which come from a designer after that become difficult to implement because the developer has already started to do their thing. What XAML allows you to do is have the project exist in the XML file format end-to-end, so even though they use some nice design tools, it&#8217;s all unified across the XML file format. The developer codes off that XML file format and they can collaborate for longer. In terms of developer and designer workflow, that’s fairly significant. They’re not using two separate file formats to do things.</p>
<p>You can play around with it XAML now – if you go to <a href="http://silverlight.net/" target="_blank">silverlight.net</a> you can download a copy of it. One of the nicest things about Silverlight video playback is that you can flip into full screen mode, and it’s true full screen video rather than simply upscaled video. So you can add controls and keep the interface and the experience in a full screen mode, just like you would in Windows Media Player. page.</p>
<p>Go to silverlight.net and you’ll get the install experience. There are loads of demos and presentations, but you must watch the major league baseball video. It&#8217;s actually one big Silverlight ad but the whole idea is to keep the fan watching the game. So you’re watching the game and all of a sudden your favourite baseballer hits and you can click on the ball and bring up stats. As you’re watching it an overlay happens, like an transferring overlay, with all stats on that player or that game or whatever. Then you can drill down and do stuff while you’re still watching – you never have to deal with a popup window and you never navigate away from the game. Then you can slide that overlay away and pull up other.</p>
<p><span class="inline middle"><a href="http://www.apcmag.com/" onclick="launch_popup(7040, 509, 234); return false;" target="_blank"><img src="http://apcmag.com/system/files/images/silverlight_04.article-width.jpg" alt="Installing Silverlight 1.0" title="Installing Silverlight 1.0" class="image article-width" align="left" height="184" width="400" /></a><span class="caption" style="width: 398px"><strong>Installing Silverlight 1.0</strong></span></span></p>
<p>Then, as part of the buddy system, your friend is doing something else and he says ‘Dude you’ve got to check it out – Billy Bob went and hit a home run’ or whatever. They click on a link and they send it to you within the same Silverlight interface. You get a little alert and a video plays with the relevant content. So you’re still watching the game as well as a little video of Billy Bob hitting the ball. You click on that, it goes full screen and the game goes into digital picture mode. At no point in time do you ever stop watching this game.</p>
<p>So this is stuff that’s hard to do today. Without writing a full game and really hard core desktop stuff, it&#8217;s hard to keep the experience immersive in a way that still maintains performance.</p>
<p><span class="inline middle"><a href="http://www.apcmag.com/" onclick="launch_popup(7041, 640, 551); return false;" target="_blank"><img src="http://apcmag.com/system/files/images/silverlight_05.article-width.jpg" alt="Zero Gravity - an application written in Silverlight 1.1 Alpha" title="Zero Gravity - an application written in Silverlight 1.1 Alpha" class="image article-width" align="left" height="344" width="400" /></a><span class="caption" style="width: 398px"><strong>Zero Gravity - an application written in Silverlight 1.1 Alpha</strong></span></span></p>
<p><strong>JB:</strong>    How dependant is all of this on high bandwidth availability?</p>
<p><strong>MK:</strong> Well, bandwidth is bandwidth andSilverlight doesn’t change that equation. If you’ve got low bandwidth and high quality video then clearly you’re going to have issues with it.</p>
<p>So as a content provider, decisions get made early on. Usually what happens is that you can do multi-streaming. So you can select your stream when you start and you can choose the low bandwidth version or the high bandwidth version. But from a developer point of view because it&#8217;s all driven by XAML, it&#8217;s actually pretty lightweight. Regardless of the video that you might be pumping through, it&#8217;s fairly light because you’ve got this XML which defines your app, then as you bring content in like buddy lists, you’re not doing major refreshes. You’re just bringing in bits of XML and adding that to the canvas at design time.</p>
<p><strong>JB:</strong> It sounds ideal for stuff like IPTV on a media centre especially if you’ve got ADSL2+ and a nice widescreen TV. Are there any plans on that sort of take-up or is it still all a bit too new?</p>
<p><strong>MK:</strong> Vista Media Centre is kind of a separate story. With VMC you have a guaranteed desktop platform, so you know what you’re working with. With Silverlight you’re working with Macs, PCs, slow machines, fast machines&#8230;it’s all different. With Vista Media Centre, you know you’ve got a Vista machine, you know you’ve got a decent graphics card, you know exactly what capabilities you have. So that’s why a lot of the Vista Media Centre add-ons that you see are actually written in WPF.</p>
<p>I haven’t talked enough about WPF and we will run out of time if I go down that path. But they share a lot of similar technologies – you create WPF through Blend and Visual Studio. On the media centre side you’d probably write WPF rather than Silverlight. One of my favourite Vista Media Centre addins is written by a guy in Melbourne - it attaches to Flickr and allows you to navigate a Flickr account. It&#8217;s a total media centre experience based around Flickr photos. You can go to your friends and look at their photos and all that kind of stuff. Having said that, you can bring up Silverlight through a media centre and distribute it through an extender. So a VMC app can be Silverlight, WPF, or even HTML if you really want to disappointingly use one. But the recommended way to write VMC apps is definitely WPF or MCML which is Media Centre Markup Language and that’s the hardcore way to write VMC apps.</p>
<p>They all share similar kind of attributes but the ones that are most closely related are Silverlight and WPF and then it basically comes down to rich versus richer. If you wanted the richest most possible experience, you’d go WPF. But you have to consider that it&#8217;s running on .NET, so if you want to be able to reach the greatest amount of customers you’d use Silverlight.</p>
]]></content:encoded>
			<wfw:commentRss>http://blogs.pinkcrow.net/microsoft-silverlight-a-visual-feast/44/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Code to unlock iPhone cracked - CNN.com</title>
		<link>http://blogs.pinkcrow.net/code-to-unlock-iphone-cracked-cnncom/43/</link>
		<comments>http://blogs.pinkcrow.net/code-to-unlock-iphone-cracked-cnncom/43/#comments</comments>
		<pubDate>Sun, 02 Sep 2007 13:49:20 +0000</pubDate>
		<dc:creator>Valeriu Buzila</dc:creator>
		
		<category><![CDATA[Gadgets]]></category>

		<guid isPermaLink="false">http://blogs.pinkcrow.net/code-to-unlock-iphone-cracked-cnncom/43/</guid>
		<description><![CDATA[ LOS ANGELES (CNN) &#8212; A group of anonymous software developers said they will soon start selling a program that will allow iPhone owners to use the hugely popular device on cell phone systems around the world and not just with AT&#38;T.
     	 	 	 	 	 	 	 	 	 [...]]]></description>
			<content:encoded><![CDATA[<p> <strong><strong>LOS ANGELES (CNN)</strong></strong> &#8212; A group of anonymous software developers said they will soon start selling a program that will allow iPhone owners to use the hugely popular device on cell phone systems around the world and not just with AT&amp;T.</p>
<p><!--startclickprintexclude-->     	 	 	 	 	 	 	 	 	 		 			 		 		 	 	 		 			 				 			 			 				 			 		 	 	 		 			 		 		 		 	 	 	 	 	 		 			 		 			 		 			 		 			 		 			 		 			 		 			 		 			 		 			 		 			 		 	 	 		 			 				 				 			 			 			 		 	 	 	 	 			 			 				 					 					    <!-- REAP --><!-- PURGE: /2007/TECH/09/01/apple.iphone/art.iphone.afp.gi.jpg --><!-- KEEP --></p>
<p class="cnnStoryPhotoBox">
<p id="cnnImgChngr" class="cnnImgChngr"><!----><!--===========IMAGE============--><img src="http://i.l.cnn.net/cnn/2007/TECH/09/01/apple.iphone/art.iphone.afp.gi.jpg" title="art.iphone.afp.gi.jpg" alt="art.iphone.afp.gi.jpg" align="left" border="0" height="219" width="292" /><!--===========/IMAGE===========--></p>
<p class="cnnStoryPhotoCaptionBox">
<p class="cnn3pxTB9pxLRPad"><!--===========CAPTION==========-->Apple&#8217;s iPhone is yet to go on sale outside the U.S.<!--===========/CAPTION=========--></p>
<p class="cnnWireBoxFooter"><img src="http://edition.cnn.com/.element/img/2.0/mosaic/base_skins/baseplate/corner_wire_BL.gif" height="4" width="4" /></p>
<p><!-- /PURGE: /2007/TECH/09/01/apple.iphone/art.iphone.afp.gi.jpg --><!-- /REAP --> 				 			 			 			 			 		 	 	  <!--endclickprintexclude--> Apple&#8217;s iPhone, released in the United States two months ago, was engineered to operate for the first two years only on the AT&amp;T system through an exclusive arrangement between Apple and AT&amp;T. It has not yet been sold outside of the U.S.</p>
<p>Los Angeles software consultant Brett Schulte, who is not affiliated with the developers, demonstrated the software for CNN Friday evening.</p>
<p>An iPhone that had the new software appeared to work on the T-Mobile system just seconds after Schulte replaced the AT&amp;T SIM card with a T-Mobile SIM card.</p>
<p>&#8220;It&#8217;s completely software hacked,&#8221; Schulte said. &#8220;There&#8217;s no case opening required. It&#8217;s not required to do any kind of disassembly.&#8221; It took Schulte about two minutes to unlock the iPhone.</p>
<p>The developers would not give CNN their last names, saying &#8220;We don&#8217;t want to be hounded.&#8221;</p>
<p>The said they would start selling the software, which they haven&#8217;t yet priced, as soon as their online payment and customer service systems are ready. They&#8217;re also waiting for more information from their lawyers.</p>
<p>Apple spokeswoman Jennifer Bowcock told CNN her company has no comment.</p>
<p>AT&amp;T spokesman Mark Siegel said he couldn&#8217;t speculate on the legality of unlocking the phone, but he added, &#8220;When you sign up, you&#8217;re signing a two-year contract. You&#8217;re obligated to pay the bill.&#8221;</p>
<p>&#8220;When people buy the iPhone it&#8217;s clear from our materials it&#8217;s designed to operate exclusively on AT&amp;T,&#8221; Siegel said.</p>
<p>Schulte, however, said it is possible to buy an iPhone without being contractually obligated to AT&amp;T.</p>
<p>The developers recently created a Web site &#8212; iPhoneSIMfree.com &#8212; but there is very little information on it and no direct way for anyone to purchase the software. Internet records showed they bought the domain name less than two weeks ago.</p>
<p>Two members of the group, who identified themselves only as &#8220;John&#8221; and &#8220;Liu,&#8221; told CNN in a phone interview that a core group of six people on three continents worked to unlock the iPhone as a hobby.</p>
<p>They said they are fans of Apple products who thought the iPhone should be made accessible to people who cannot use AT&amp;T.</p>
<p>&#8220;I&#8217;m not in America and I can&#8217;t use it,&#8221; said Liu, who would not reveal the country in which he lives. &#8220;It&#8217;s not fair.&#8221;</p>
<p>Asked if he thought modifying the iPhone was legal, he said &#8220;That&#8217;s a very good question. I truly believe it is.&#8221;</p>
<p>John and Liu said they have not been contacted by either Apple or AT&amp;T, but said that could change the moment their software goes on sale.</p>
<p>Earlier this month, a teenager figured out a way to unlock the iPhone, but his method required disassembly of the unit.</p>
]]></content:encoded>
			<wfw:commentRss>http://blogs.pinkcrow.net/code-to-unlock-iphone-cracked-cnncom/43/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Vista reaches crunchtime with SP1</title>
		<link>http://blogs.pinkcrow.net/vista-reaches-crunchtime-with-sp1/42/</link>
		<comments>http://blogs.pinkcrow.net/vista-reaches-crunchtime-with-sp1/42/#comments</comments>
		<pubDate>Sun, 02 Sep 2007 13:48:49 +0000</pubDate>
		<dc:creator>Valeriu Buzila</dc:creator>
		
		<category><![CDATA[Software]]></category>

		<guid isPermaLink="false">http://blogs.pinkcrow.net/vista-reaches-crunchtime-with-sp1/42/</guid>
		<description><![CDATA[It is an axiom in IT that you shouldn&#8217;t buy a new operating system until after the release of the first service pack.
Perhaps more than any other Microsoft operating system release, Windows Vista is making slow progress and gripes about the new OS are not hard to find. I&#8217;ve been using it for the last [...]]]></description>
			<content:encoded><![CDATA[<h2>It is an axiom in IT that you shouldn&#8217;t buy a new operating system until after the release of the first service pack.</h2>
<p><font face="Verdana" size="2">Perhaps more than any other Microsoft operating system release, Windows Vista is making slow progress and gripes about the new OS are not hard to find.</font> <font face="Verdana" size="2">I&#8217;ve been using it for the last few months and have to say, the more I get to know Vista, the less I like it. My major bugbear is it&#8217;s slow. Slow to start and slow to stop. Then there are the driver issues - not directly Microsoft&#8217;s fault but very directly Microsoft&#8217;s problem.</font><br />
<font face="Verdana" size="2">Other users will have different gripes, but I&#8217;m a simple soul. I wish I&#8217;d opted for XP.</font><br />
<font face="Verdana" size="2">Anyway, everything that has happened to date could yet be forgotten. XP itself was subject to similar scrutiny and criticism when it was released, but now has a lot of fans. It is an axiom in IT that you shouldn&#8217;t buy a new operating system (correction: a new Microsoft operating system) until after the release of the first service pack. Vista Service Pack 1 now looms.</font><br />
<font face="Verdana" size="2">On Microsoft&#8217;s Windows Vista blog last week came official news of SP1. Microsoft product manager Nick White first pointed out that the company no longer relies on service packs as the sole way of updating Windows. Windows Update makes sure this improvement process happens fairly constantly with two performance and improvement updates pushed out last week.</font><br />
<font face="Verdana" size="2">White then goes on to reassure Vista users that Microsoft is working with partners to ensure driver compatibility (yay!).</font><br />
<font face="Verdana" size="2">&#8220;</font><font face="Verdana" size="2">In addition to updates we’ve previously released, SP1 will contain changes focused on addressing specific reliability and performance issues we’ve identified via customer feedback, supporting new types of hardware, and adding support for several emerging standards,&#8221; White says. &#8220;SP1 also makes additional improvements to the IT administration experience.  We didn’t design SP1 as a vehicle for releasing new features; however, some existing components do gain enhanced functionality in SP1.&#8221;</font><br />
<font face="Verdana" size="2">All well and good, except the SP1 White is talking about is still an SP1 beta, due in the &#8220;next few weeks&#8221;. SP1 itself is &#8220;targetted for release&#8221; in the first quarter of 2008.</font><br />
<font face="Verdana" size="2">Jon DeVaan, senior vice president of the Windows Core Operating System division at Microsoft, fleshes out the detail.</font><br />
<font face="Verdana" size="2">&#8220;I should start by saying that one thing people shouldn’t expect to see is new features, although some existing components and features will be enhanced,&#8221; he says.</font><br />
<font face="Verdana" size="2">&#8220;For example, we’ve added support in BitLocker drive encryption for encrypting multiple volumes on the PC, and have improved printer management by simplifying printing to a local printer from within a Terminal Server session. Service packs typically are not vehicles for new features, and the same will be true with Windows Vista SP1.&#8221;</font><br />
<font face="Verdana" size="2">DeVaan says SP1 will contain changes to address feedback from customers (also known as complaints). SP1 will address reliability and performance issues, such as copying files and shutdown time. </font><br />
<font face="Verdana" size="2">&#8220;It will support new types of hardware and emerging standards, like EFI (Extensible Firmware Interface) and ExFat (a new file format that will be used in flash memory storage and consumer devices),&#8221; he says. </font><br />
<font face="Verdana" size="2">&#8220;It will also include some management, deployment, and support improvements, such as adding the ability to detect and correct common file sharing problems to network diagnostics.&#8221;</font><br />
<font face="Verdana" size="2">Make no mistake, for many prospective buyers SP1 will be crunchtime. Loyal Microsoft customer organisations such as Kiwibank have said they are not ready for Vista because of hardware constraints (Computerworld August 20). Carter Holt, more worryingly, indicated last week it may skip Vista altogether because it can&#8217;t see the benefits. And then there are worrying signs of Apple gaining major momentum in the laptop market.</font><br />
<font face="Verdana" size="2">SP1 has to be good.</font></p>
]]></content:encoded>
			<wfw:commentRss>http://blogs.pinkcrow.net/vista-reaches-crunchtime-with-sp1/42/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Microsoft to release Vista fixes in 2008</title>
		<link>http://blogs.pinkcrow.net/microsoft-to-release-vista-fixes-in-2008/41/</link>
		<comments>http://blogs.pinkcrow.net/microsoft-to-release-vista-fixes-in-2008/41/#comments</comments>
		<pubDate>Sun, 02 Sep 2007 13:44:51 +0000</pubDate>
		<dc:creator>Valeriu Buzila</dc:creator>
		
		<category><![CDATA[Software]]></category>

		<guid isPermaLink="false">http://blogs.pinkcrow.net/microsoft-to-release-vista-fixes-in-2008/41/</guid>
		<description><![CDATA[                         SEATTLE - Microsoft Corp. said Wednesday it will release a major package of updates and fixes for the Windows Vista operating system in the first half of 2008.he company said [...]]]></description>
			<content:encoded><![CDATA[<p class="entry">                         SEATTLE - Microsoft Corp. said Wednesday it will release a major package of updates and fixes for the Windows Vista operating system in the first half of 2008.he company said a “beta” test version of Service Pack 1 will be released “in a few weeks to a moderate sized audience.” The SP1 beta includes updates Microsoft has already made to the operating system it started selling to consumers at the end of January.</p>
<p>The service pack fixes some common problems that cause computers to crash or freeze, Microsoft said, including compatibility problems with some newer graphics cards, external monitors and printer drivers. Microsoft said it also fixed some problems users had with putting their PCs to sleep and waking them up again.</p>
<p>The company said SP1 is also expected to improve battery performance, increase the speed of copying files and help Internet Explorer run faster on Vista.</p>
<p>The Redmond, Wash.-based software maker said SP1 also brings several security improvements.</p>
<p>Microsoft said it expects to release Service Pack 3 for Windows XP, Vista’s predecessor, in the first half of 2008 as well, but in a statement added that it “should not significantly change the Windows XP experience.”</p>
<p>In the past, some of Microsoft’s business clients used the release of a service pack as a sign that a new operating system was stable enough to install. Analysts have said Vista seems more reliable out of the box than past versions of Windows, and that businesses need not wait for the service pack.</p>
]]></content:encoded>
			<wfw:commentRss>http://blogs.pinkcrow.net/microsoft-to-release-vista-fixes-in-2008/41/feed/</wfw:commentRss>
		</item>
		<item>
		<title>PHP - Encode and decode data using the ASCII85 algorithm</title>
		<link>http://blogs.pinkcrow.net/php-encode-and-decode-data-using-the-ascii85-algorithm/33/</link>
		<comments>http://blogs.pinkcrow.net/php-encode-and-decode-data-using-the-ascii85-algorithm/33/#comments</comments>
		<pubDate>Sun, 02 Sep 2007 13:12:59 +0000</pubDate>
		<dc:creator>Valeriu Buzila</dc:creator>
		
		<category><![CDATA[Software]]></category>

		<guid isPermaLink="false">http://blogs.pinkcrow.net/php-encode-and-decode-data-using-the-ascii85-algorithm/33/</guid>
		<description><![CDATA[This class can be used to encode and decode data using the ASCII85 algorithm.
It can take a string of data and encode it with the ASCII85 algorithm. It can also do the opposite, i.e. extract the original data from an encoded string using the same algorithm.
http://phpclasses.bizland.ro/browse/package/4052.html
]]></description>
			<content:encoded><![CDATA[<p>This class can be used to encode and decode data using the ASCII85 algorithm.</p>
<p>It can take a string of data and encode it with the ASCII85 algorithm. It can also do the opposite, i.e. extract the original data from an encoded string using the same algorithm.</p>
<p><a href="http://phpclasses.bizland.ro/browse/package/4052.html">http://phpclasses.bizland.ro/browse/package/4052.html</a></p>
]]></content:encoded>
			<wfw:commentRss>http://blogs.pinkcrow.net/php-encode-and-decode-data-using-the-ascii85-algorithm/33/feed/</wfw:commentRss>
		</item>
		<item>
		<title>PHP - Compress and uncompress data with LZW algorithm</title>
		<link>http://blogs.pinkcrow.net/php-compress-and-uncompress-data-with-lzw-algorithm/32/</link>
		<comments>http://blogs.pinkcrow.net/php-compress-and-uncompress-data-with-lzw-algorithm/32/#comments</comments>
		<pubDate>Sun, 02 Sep 2007 13:12:11 +0000</pubDate>
		<dc:creator>Valeriu Buzila</dc:creator>
		
		<category><![CDATA[Software]]></category>

		<guid isPermaLink="false">http://blogs.pinkcrow.net/php-compress-and-uncompress-data-with-lzw-algorithm/32/</guid>
		<description><![CDATA[This class can be used to compress and uncompress data with the LZW algorithm in pure PHP code.
It can take a string of data and compress it with the LZW algorithm. It can also do the opposite, i.e. extract the original data from compressed string using the same algorithm.
http://phpclasses.bizland.ro/browse/package/4051.html
]]></description>
			<content:encoded><![CDATA[<p>This class can be used to compress and uncompress data with the LZW algorithm in pure PHP code.</p>
<p>It can take a string of data and compress it with the LZW algorithm. It can also do the opposite, i.e. extract the original data from compressed string using the same algorithm.</p>
<p><a href="http://phpclasses.bizland.ro/browse/package/4051.html">http://phpclasses.bizland.ro/browse/package/4051.html</a></p>
]]></content:encoded>
			<wfw:commentRss>http://blogs.pinkcrow.net/php-compress-and-uncompress-data-with-lzw-algorithm/32/feed/</wfw:commentRss>
		</item>
		<item>
		<title>PHP Multi-thread Simulation</title>
		<link>http://blogs.pinkcrow.net/php-multi-thread-simulation/31/</link>
		<comments>http://blogs.pinkcrow.net/php-multi-thread-simulation/31/#comments</comments>
		<pubDate>Sun, 02 Sep 2007 13:11:35 +0000</pubDate>
		<dc:creator>Valeriu Buzila</dc:creator>
		
		<category><![CDATA[Software]]></category>

		<guid isPermaLink="false">http://blogs.pinkcrow.net/php-multi-thread-simulation/31/</guid>
		<description><![CDATA[This class can emulate the execution of program threads using separate HTTP requests to the same script.
It establishes an HTTP connection to the same Web server to execute the same PHP script. It sends a request passing the name a function to execute and an argument to be passed to that function.
The requested script executes [...]]]></description>
			<content:encoded><![CDATA[<p>This class can emulate the execution of program threads using separate HTTP requests to the same script.</p>
<p>It establishes an HTTP connection to the same Web server to execute the same PHP script. It sends a request passing the name a function to execute and an argument to be passed to that function.</p>
<p>The requested script executes some code that detects the thread execution request and calls the specified function.</p>
<p>When the thread request script ends, the return values of the called function is returned as a serialized string.</p>
<p>The calling script can execute other tasks while the thread script runs. The results may be collected later when the thread script ends.</p>
<p><a href="http://phpclasses.bizland.ro/browse/package/3953.html">http://phpclasses.bizland.ro/browse/package/3953.html</a></p>
]]></content:encoded>
			<wfw:commentRss>http://blogs.pinkcrow.net/php-multi-thread-simulation/31/feed/</wfw:commentRss>
		</item>
	</channel>
</rss>
