<?xml version="1.0" encoding="UTF-8"?> <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/"
xmlns:atom="http://www.w3.org/2005/Atom"
xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
><channel><title>profeshunl newbie &#187; Code</title> <atom:link href="http://pronewb.com/category/code/feed" rel="self" type="application/rss+xml" /><link>http://pronewb.com</link> <description>Random ramblings of a profeshunl newbie</description> <lastBuildDate>Mon, 12 Apr 2010 14:03:14 +0000</lastBuildDate> <language>en</language> <sy:updatePeriod>hourly</sy:updatePeriod> <sy:updateFrequency>1</sy:updateFrequency> <generator>http://wordpress.org/?v=3.2.1</generator> <xhtml:meta xmlns:xhtml="http://www.w3.org/1999/xhtml" name="robots" content="noindex" /> <item><title>MongoDB as in huMONGOus, not retarded</title><link>http://pronewb.com/mongodb-as-in-humongous-not-retarded</link> <comments>http://pronewb.com/mongodb-as-in-humongous-not-retarded#comments</comments> <pubDate>Mon, 12 Apr 2010 11:01:43 +0000</pubDate> <dc:creator>william</dc:creator> <category><![CDATA[Code]]></category> <category><![CDATA[bson]]></category> <category><![CDATA[chunks of data]]></category> <category><![CDATA[database]]></category> <category><![CDATA[GridFS]]></category> <category><![CDATA[insert]]></category> <category><![CDATA[json]]></category> <category><![CDATA[MongoDB]]></category> <category><![CDATA[MongoFS]]></category> <category><![CDATA[MySQL]]></category> <category><![CDATA[NoSQL]]></category> <category><![CDATA[php]]></category> <category><![CDATA[PHPClasses]]></category> <category><![CDATA[phpize]]></category> <category><![CDATA[range of data]]></category> <category><![CDATA[rdbms]]></category> <category><![CDATA[remove]]></category> <category><![CDATA[star wars]]></category> <category><![CDATA[update]]></category><guid
isPermaLink="false">http://pronewb.com/?p=284</guid> <description><![CDATA[Unlike the rest of the known world, I won't write anything on the iPad. Yet. While pondering life's great mysteries, such as how you can evade paying your bills, I felt it was time to write something about databases. You see the connection, right? Good, because I don't. A search for MongoDB resulted in "only" 1,2 million results. That means that if and when this article gets indexed by the Google, it will constitute no less than ~ 8.33 × 10^7 % of the relevant search results. Goodie! In short, this article will cover MongoDB and how you can use it with PHP. Good times ahead so if you're a killjoy, you're not welcome.No related posts.]]></description> <content:encoded><![CDATA[<p><a
href="http://pronewb.com/wp-content/uploads/mongodb_large.jpg"><img
class="alignleft size-medium wp-image-315" title="MongoDB" src="http://pronewb.com/wp-content/uploads/mongodb_large-300x163.jpg" alt="MongoDB" width="300" height="163" /></a>Unlike the <a
title="iPad @ engadget" href="http://www.engadget.com/tag/ipad" target="_blank">rest</a> <a
title="iPad @ tuaw" href="http://www.tuaw.com/tag/ipad" target="_blank">of</a> <a
title="iPad @ gizmodo" href="http://gizmodo.com/tag/ipad" target="_blank">the</a> <a
title="iPad @ Techcrunch" href="http://techcrunch.com/tag/ipad/" target="_blank">known</a> <a
title="iPad @ CNet" href="http://news.cnet.com/crave/?categoryId=10442813&amp;tag=mncol;tags" target="_blank">world</a>, I won&#8217;t write anything on the <a
title="iPad @ apple.com" href="http://www.apple.com/ipad/" target="_blank">iPad</a>. Yet. Instead, I&#8217;m still in the process of writing the upcoming parts of my <a
title="Popurls Clone with PHP, jQuery, awesomeness - shameless self promotion" href="http://pronewb.com/a-popurls-clone-with-php-jquery-awesomeness" target="_blank">Popurls Clone</a> series and as per usual, it takes a lot more time than expected. In combination with a massive amount of bills, life is good! As it turns out, you actually need to &#8220;work&#8221; in order to get &#8220;money&#8221;. How, when and why did we agree upon that? That&#8217;s just as stupid as, say, doing a fully animated Star Wars <a
title="Star Wars - The Clone Wars" href="http://www.starwars.com/theclonewars/" target="_blank">prequel/sequel</a> to take place during the Clone Wars. Oh, <a
title="I see what you did there..." href="http://www.dahmus.org/blogimg/fry-see-what-you-did-there.jpg" target="_blank">wait</a>&#8230; While pondering life&#8217;s great mysteries, such as how you can evade paying your bills, I felt it was time to write something about databases. You see the connection, right? Good, because I don&#8217;t. A quick <a
title="Let me google that for you - MySQL" href="http://www.lmgtfy.com/?q=MySQL" target="_blank">Google search</a> for <a
title="MySQL" href="http://dev.mysql.com/" target="_blank">MySQL</a> rendered roughly 117 million results so I figured that another article about it would be kinda superfluous. A search for <a
title="MongoDB" href="http://www.mongodb.org/" target="_blank">MongoDB</a> on the other hand resulted in &#8220;only&#8221; 1,2 million results. Much better. That means that if and when this article gets indexed by <a
title="Bushism. Classic" href="http://www.youtube.com/watch?v=90DKubFKwVo" target="_blank">the Google</a>, it will constitute no less than ~ 8.33 × 10<sup>-7</sup> % of the relevant search results, in stark contrast to the ~ 5.88 × 10<sup>-9</sup> %, should I&#8217;ve written some stuff about MySQL. Goodie! In short, this article will cover MongoDB and how you can use it with PHP. Good times ahead so if you&#8217;re a killjoy, you&#8217;re not welcome.</p><hr
/><h4>A brief introduction to MongoDB</h4><p>First of all, MongoDB is not a relational database management system (<a
title="RDBMS @ wikipedia" href="http://en.wikipedia.org/wiki/Relational_database_management_system" target="_blank">RDBMS</a>) such as MySQL. A relational DBMS is based on a relational model, based on <a
title="First-order logic @ wikipedia" href="http://en.wikipedia.org/wiki/First-order_logic" target="_blank">first-order predicate logic</a> as proposed by <a
title="Edgar Frank Codd" href="http://en.wikipedia.org/wiki/Edgar_F._Codd" target="_blank">Edgar Frank Codd</a> in 1969. Data and its internal relationships are more often than not stored as <a
title="Tables (database) @ wikipedia" href="http://en.wikipedia.org/wiki/Table_(database)" target="_blank">tables</a>. These tables are what constitute the relations. The tables are organized using a kind of model of vertical columns and rows where there are a specified number of columns but the number of rows are, in theory, infinite. The data is fetched via queries using <a
title="SQL @ wikipedia" href="http://en.wikipedia.org/wiki/SQL" target="_blank">SQL</a>. But enough about that &#8211; we&#8217;re here to talk about MongoDB which is a part of the <a
title="NoSQL @ wikipedia" href="http://en.wikipedia.org/wiki/NoSQL" target="_blank">NoSQL</a> movement. In NoSQL there are basically three kinds of databases; column oriented, key-value pairs and <a
title="Document oriented database" href="http://en.wikipedia.org/wiki/Document-oriented_database" target="_blank">document oriented</a>. MongoDB employs the latter kind. A document in this context is a structure of data with a given number of properties. These properties can be strings, numbers, arrays or objects, etc. If you&#8217;ve dabbled with associative arrays or objects in PHP, you&#8217;ll know what this means. You can also group documents in collections. Also, there are something called sub-documents which are pretty much what you&#8217;d think they&#8217;d be.</p><hr
/><script type="text/javascript">google_ad_client="pub-8939939010469559";google_ad_slot="9013590878";google_ad_width=468;google_ad_height=60;</script><script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js"></script></p><hr
/>In the case of MongoDB, we have no <a
title="Database schema @ wikipedia" href="http://en.wikipedia.org/wiki/Database_schema" target="_blank">schema</a> to play with but the power lies in the fact that we get to play with JSON-like structures. And JSON is good, right? MongoDB is written in C++, it just hit version 1.4.0 and it stores data using <a
title="BSON" href="http://www.bsonspec.org/" target="_blank">BSON</a>, which is a &#8220;binary-encoded serialization of JSON-like documents&#8221;. Thankfully, there&#8217;s a native PHP extension. So the first thing you&#8217;d want to do is <a
title="D´oh" href="http://www.politicalbyline.com/wp-content/uploads/2009/06/homer-doh-square.jpg" target="_blank">install it</a>. <a
title="Download MongoDB" href="http://www.mongodb.org/display/DOCS/Downloads" target="_blank">Download</a> the appropriate package and perhaps read the <a
title="MongoDB Quickstart" href="http://www.mongodb.org/display/DOCS/Quickstart" target="_blank">Quickstart</a>. Assuming you use <a
title="PECL homepage" href="http://pecl.php.net/" target="_blank">PECL</a>, which you should, you can install it easily with the following command;</p><pre class="chili"><code class="php">pecl install mongo</code></pre><p>or you can do it manually by <a
title="MongoDB extension" href="http://pecl.php.net/package/mongo" target="_blank">downloading</a> the source</p><pre class="chili"><code class="php">phpize
./configure --enable-mongo
make install</code></pre><p>The install should have created an extension for you and put it in the extension directory. You may need to edit your PHP.ini and add</p><pre class="chili"><code class="php">extension=mongo.so</code></pre><p>where appropriate (hint: maybe where the other extensions are defined). If you get an error in the lines of &#8220;phpize: comand not found&#8221;, <a
title="Install PECL how-to" href="http://au2.php.net/manual/en/install.pecl.php" target="_blank">this page</a> is for you. If you&#8217;re on linux, a quick fix is to install <strong>php5-dev</strong> with apt-get or <strong>php-devel </strong>with yum. Restart your webserver. <a
title="Do it from starsky and hutch" href="http://theedmontonian.com/wp-content/uploads/2009/10/196217268_1703431390_AMC-MP-Starsky-Hutch-BenOwen.jpg" target="_blank">Do it</a>. If you&#8217;re interested in MongoDB but loathe PHP (god knows you have your reasons), there are <a
title="MongoDB drivers" href="http://www.mongodb.org/display/DOCS/Drivers" target="_blank">drivers</a> for other languages, such as C# and .NET (why are you reading this?), Clojure (you pervert), ColdFusion (oh no, you dideeent), Python (you&#8217;re all right) or Ruby (pff).</p><hr
/><h4>I feel the vibe</h4><p>Let&#8217;s do this. Connect to your brand spanking new Mongo database at localhost (default port is 27017)</p><pre class="chili"><code class="php">$the_mongo_connection = new Mongo();</code></pre><p>Or if you&#8217;d like to connect to a remote host</p><pre class="chili"><code class="php">$the_mongo_connection = new Mongo("10.0.0.2[:optional_port]");</code></pre><p><strong>Pro tip:</strong> use a persistent connection. New connections to the database can be very slow. Let this quote borrowed from <a
title="Connecting to Mongo @ php.net" href="http://www.php.net/manual/en/mongo.connecting.php" target="_blank">php.net</a> serve as a cautionary, um, well, <a
title="Tautology" href="http://en.wikipedia.org/wiki/Tautology_(rhetoric)" target="_blank">example</a>;</p><pre class="chili"><code class="php">for ($i=0; $i&amp;lt;1000; $i++) {
    $m = new Mongo();
}</code></pre><p>This will take roughly 18 seconds to execute. Yes, 18. That&#8217;s like an eternity on the Internets. If we use a persistent connection like so;</p><pre class="chili"><code class="php">for ($i=0; $i&amp;lt;1000; $i++) {
    $m = new Mongo("localhost:27017", array("persist" =&gt; "x"));
}</code></pre><p>&#8230;we&#8217;re down to 0.02 seconds. So, yeah, persistent may be the way to go. And by &#8220;may&#8221; I mean &#8220;do it, ass hat&#8221;. If you&#8217;re wondering about the &#8220;x&#8221; in the last piece of code, it&#8217;s because persistent connections need a unique identifier string.</p><p>The name of the database can use almost any character in the ASCII range, except a blank space, a period or just an empty string. You can actually name a database &#8220;null&#8221; if you&#8217;d like. Might be fun just to piss people off. Selecting a database can be done in two ways and isn&#8217;t harder than</p><pre class="chili"><code class="php">$db = $the_mongo_connection-&gt;name_of_database;
$db = $the_mongo_connection-&gt;selectDB('name_of_database');</code></pre><p>The latter is to be preferred if you&#8217;re using wonky characters in your database name, such as a comma, a slash or something like that. Valid, but it&#8217;ll break your code into millions and millions of pieces if you don&#8217;t use the quoted selectDB(). Now we need to select collection to work with. You might say that this is similar to selecting a table in a RDBMS. And you&#8217;d be correct. Gold star for you.</p><pre class="chili"><code class="php">$sweet_collection = $db-&gt;name_of_collection;
$sweet_collection = $db-&gt;selectCollection('name_of_collection');</code></pre><p>Sweet. Let&#8217;s do some tangible, hands-on exercises, mm&#8217;kay? <a
title="Mm'kay" href="http://www.youthink.com/quiz_images/quiz1262outcome4.gif" target="_blank">Mm&#8217;kay</a>.</p><hr
/><h4>The insert [note to self: penis joke here]</h4><p>For this part, I&#8217;ll go with something stupid, like pretend that we&#8217;re creating a database of DVD&#8217;s. Cheezy, but it&#8217;ll do. First let&#8217;s set up some <a
title="A Nightmare on Elm Street @ dvdreview.com" href="http://www.dvdreview.com/reviews/pages/3088.shtml" target="_blank">dummy data</a>.</p><pre class="chili"><code class="php">$dvd = array(
    'title' =&gt; 'A Nightmare On Elm Street',
    'slug' =&gt; 'anoes',
    'year' =&gt; '1983',
    'format' =&gt; 'Blu-Ray',
    'screen' =&gt; '16:10',
    'media' =&gt; array(
        'audio' =&gt; array(
            'English - DTS 5.2 HD',
            'Master Audio',
            'English - DD 1.0',
            'French - DD 1.0'
        ),
        'subtitles' =&gt; array(
            'english',
            'french',
            'spanish',
            'spanglish'
        ),
        'extras' =&gt; array(
            'Commentary Tracks',
            'Featurettes',
            'Alternate Endings',
            'Trivia Track'
        )
    ),
    'starring' =&gt; array(
        'Robert Englund',
        'John Saxon',
        'Heather Langenkamp',
        'Johnny Jepp'
    )
);</code></pre><hr
/><script type="text/javascript">google_ad_client="pub-8939939010469559";google_ad_slot="9013590878";google_ad_width=468;google_ad_height=60;</script><script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js"></script></p><hr
/>Yes, Nightmare on Elm Street. Johhny Depp&#8217;s debut movie. As you can see we have a pretty basic multidimensional associative array. The actual code to insert the data I want, you say with a Yoda type of grammar. Sure.</p><pre class="chili"><code class="php">$sweet_collection-&gt;insert($dvd);</code></pre><p>Boom. There is an optional second argument that can be used if you want to check if the insert succeeded or not. If set to true, it will return an array with the status of the insert. That is, the the array will be returned with the _id assigned by Mongo. Think about the lack of need to call insert_id() or similar. Sweet, huh? If the insert was not successful, it will return a boolean which represents if the array provided was not empty. Empty arrays will not be inserted. Let&#8217;s try that out. Assuming we just executed the insert above, that insert gets a unique id (the key is &#8220;_id&#8221; &#8211; try to echo out your last insert id with echo $dvd['_id'];) and then fire this little baby;</p><pre class="chili"><code class="php">try {
    $sweet_collection-&gt;insert($dvd, true);
}
catch(MongoCursorException $e) {
    echo "Why you wanna play me like dat? That movie ID already exists in the DB!";
}</code></pre><p>Pretty nice, huh? One more thing about the id &#8211; MongoDB creates a <a
title="MongoId" href="http://www.php.net/manual/en/class.mongoid.php" target="_blank">unique id</a> if non is supplied manually. The MongoId is an object and not a string. It&#8217;s the MongoDB equivalent to an autoincrement in RDBMS. Each id is 12 bytes &#8211; 4+3+2+3. The first four bytes are a timestamp. The following three are a hash of the client machine&#8217;s hostname, the next two are &#8220;the lease significant bytes of the process id running the script&#8221; and the last three bytes are an incrementing value. Food for thought.</p><hr
/><h4>The update</h4><p>As you may or may not have noticed, there are some minor mistakes in the data above. Oops. Guess we&#8217;ll have to update. Funny how these things work out! There are a couple of handy dandy modifier operations to make our Mongo life a little bit easier. The syntax is as follows;</p><pre class="chili"><code class="php">update( [criteria], [objNew], [upsert], [multi] );</code></pre><ul><li><strong>criteria</strong> &#8211; query which selects the record to update</li><li><strong>objNew</strong> &#8211; updated object or $ operators (e.g., $inc) which manipulate the object</li><li><strong>upsert</strong> &#8211; if this should be an &#8220;upsert&#8221;; that is, if the record does not exist, insert it</li><li><strong>multi</strong> &#8211; if all documents matching criteria should be updated (the default is to only update the first document found)</li></ul><p>Our criteria would, in this example, be a value we can search for. Let&#8217;s search for the slug, &#8220;anoes&#8221;. We need to update a couple of fields here; the year should be 1984, screen is 16:9, not 16:10, the english audio is 5.1 surround, not 5.2, obviously, and there is no &#8216;spanglish&#8217; subtitle. Before we do the actual update, we should discuss the modifier operations that are available. Using these modifiers, we&#8217;re able to do atomic updates! Yes, that last sentence deserved an exclamation mark. Shut up.</p><ul><li><strong>$inc</strong> &#8211; increments the value by the factor you provide. If the value is not present, the key is set to that value.</li><li><strong>$set</strong> &#8211; sets the value for a specified key.</li><li><strong>$unset</strong> &#8211; deletes given key and value.</li><li><strong>$push</strong> &#8211; append the specified value to the key if an array is present. If not, an array is set to the key. If  the key is present but not an array, an error condition is raised.</li><li><strong>$pushAll</strong> &#8211; append each value in the value array to the key. Works similar to $push.</li><li><strong>$addToSet</strong> &#8211; adds value to the array only if it&#8217;s not in the array already.</li><li><strong>$pop</strong> &#8211; removes the first or last element of the array. Use &#8220;1&#8243; to remove the last, and &#8220;-1&#8243; to remove the  first.</li><li><strong>$pull</strong> &#8211; removes all occurrences of the specified value from the key if the key is an array. If the key&#8217;s there but is not an array, an error is raised.</li><li><strong>$pullAll</strong> &#8211; removes all occurrences of each value in the array given from the key. If the key is there but isn&#8217;t an array &#8211; you guessed it &#8211; an error is raised.</li></ul><p>Still here? no?, I&#8217;ll wait some more then.</p><p>Okay, so how do we update our movie info? Like so;</p><pre class="chili"><code class="php">$criteria = array(
    'slug' =&gt; 'anoes'
);

$objNew = array(
    '$inc' =&gt; array(
        'year' =&gt; 1
    ),
    '$set' =&gt; array(
        'screen' =&gt; '16:9',
        'media.audio.0' =&gt; 'English - DTS 5.2 HD'
    );
    '$unset' =&gt; array(
        'media.subtitles.3' =&gt; 1
    );
);

$sweet_collection-&gt;update(
    $criteria,
    $objNew
);</code></pre><p>The last two arguments are not set since we&#8217;re not updating multiple records, nor do we want it to upsert. As you may have noticed, you can target a certain index in the array &#8211; see media.audio.0 and media.subtitles.3. Pretty nice. But what if you don&#8217;t know the index? Then you&#8217;re screwed. Go home.</p><hr
/><script type="text/javascript">google_ad_client="pub-8939939010469559";google_ad_slot="9013590878";google_ad_width=468;google_ad_height=60;</script><script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js"></script></p><hr
/>No, not really. There is something called the positional operator and it&#8217;s represented by the $ sign. Use it to find an array entry and manipulate it. For example, let&#8217;s update the audio this way instead.</p><pre class="chili"><code class="php">$sweet_collection-&gt;update(
    array(
        'media.audio.$' =&gt; 'English - DTS 5.2 HD'
    ),
    array(
        '$set' =&gt; 'English - DTS 5.1 HD'
    )
);</code></pre><p>Note that the $ only applies to the first matched item in the query. This may be changed in the future, but as of now, no.</p><hr
/><h4>Fetch, Bobo, fetch! Good boy.</h4><p>Okay, then. How do we actually fetch our data? In many ways, as it turns out. Queries in MongoDB support both <a
title="Conditional Operators @ MongoDB" href="http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-ConditionalOperators%3A%3C%2C%3C%3D%2C%3E%2C%3E%3D" target="_blank">conditional operators</a> (less than, greater than, etc, no equals, in (much like SQL&#8217;s &#8220;in&#8221;), mod, and much more), <a
title="Regular Expressions @ MongoDB" href="http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-RegularExpressions" target="_blank">regular expressions</a> and has a terminology, or, rather, methods, that work similar to SQL syntax. Here&#8217;s a quick reference &#8211; the MongoDB method to the left and its MySQL equivalent to the right.</p><ul><li><strong>sort() </strong>- ORDER BY</li><li><strong>limit()</strong> &#8211; LIMIT (chocking, I know)</li><li><strong>group()</strong> &#8211; GROUP BY</li></ul><p>Sorry, I thought that list would be longer. You also have the following to toy around with;</p><ul><li><strong>skip()</strong> &#8211; allows you to specify at which object the database should begin returning results. Cool. Think paging results.</li><li><strong>count()</strong> &#8211; returns the number of objects. It counts at server level instead of client level.</li><li><strong>snapshot()</strong> &#8211; this makes sure that no duplicates are returned or objects were missed which were present at both the start and at the end of the query&#8217;s execution &#8211; even if the objects were updated. Short query responses &#8211; less than 1 MB  are aways snapshotted.</li></ul><hr
/><script type="text/javascript">google_ad_client="pub-8939939010469559";google_ad_slot="9013590878";google_ad_width=468;google_ad_height=60;</script><script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js"></script></p><hr
/>Having said that, now&#8217;s the time to get to know <strong><a
title="find with MongoDB @ php.net" href="http://us.php.net/manual/en/mongocollection.find.php" target="_blank">find()</a></strong> and <strong><a
title="find one with mongodb @ php.net" href="http://us.php.net/manual/en/mongocollection.findone.php" target="_blank">findOne()</a></strong>. These functions lets you query a specified collection. Basically, you tell it which collection to query and which fields to return. Say we have a number of entries in our DVD database and we want to find titles released from 1980 up to 1990, we could write something like;</p><pre class="chili"><code class="php">$years = array('x' =&gt; array( '$gte' =&gt; 1980, '$lt' =&gt; 1990 ));
$best_movies_evar = $sweet_collection-&gt;find( $years );</code></pre><p>Conditional operators FTW. findOne() works the same way but it returns a single element instead. It returns the record or null if it fails. Let&#8217;s say you need to paginate your results as the last query return a massive amount of titles. And right now, you need ten results, starting from title number 30. No biggie.</p><pre class="chili"><code class="php">$num_movies = $best_movies_evar-&gt;total();
$best_movies_evar-&gt;limit(10)-&gt;skip(30);
foreach ( $best_movies_evar $sweet_movie ) {
    var_dump( $sweet_movie );
}</code></pre><p>Note that queries are actually not executed until the result is requested. That means you can refine your results before actually fetching them, like we did above. Got it? Nice. <a
title="Nice @ south park" href="http://www.youtube.com/watch?v=8hdbns1Xdk0" target="_blank">Niiccceeeeee</a>.</p><hr
/><h4>Aww, that&#8217;s nice. C-click. Deleted!</h4><p>Sooner or later, you&#8217;ll want to delete a record or two hundred. Easy enough.</p><pre class="chili"><code class="php">$field_to_remove = array(
    'year' =&gt; 1984
);
$sweet_collection-&gt;remove( $field_to_remove );</code></pre><p>This would remove any document with the year 1983. If you want to remove the first document found, pass <em>true</em> as the second parameter and you&#8217;re good to go, sparky.</p><hr
/><h4>Now you can create an index, too!</h4><p>This should be filed under optimisation, bot whatever. You can create indexes in MongoDB which is just gravy. Let&#8217;s create an index based on year of release in our sweet sweet DVD collection database. It&#8217;s as simple as calling <strong><a
title="ensure index in mongodb @ php.net" href="http://php.net/manual/en/mongocollection.ensureindex.php" target="_blank">ensureIndex()</a></strong>. Pass an array with the keys you want o have as an index and either &#8220;1&#8243; or &#8220;-1&#8243; 1 for ascending and -1 descending.</p><pre class="chili"><code class="php">
$sweet_collection-&gt;ensureIndex(
    array(
        'year' =&gt; 1
    )
);</code></pre><p>&#8230; and that&#8217;s it. There are however some options you may pass in an associative array in the second parameter.</p><ul><li><strong>unique</strong> &#8211; creates a unique index.</li><li><strong>dropDups</strong> &#8211;  If a duplicate value exists while creating an index, drop all but one value.</li><li><strong>background</strong> &#8211; create indexes in the background while other operations are taking place. It&#8217;s synchronous by default, so set this to true to make it asynchronous.</li><li><strong>safe</strong> &#8211; check if thecreation of an index succeeded. If it failed, a MongoCursosException is thrown</li><li><strong>name</strong> &#8211; specify an index name, should Mongo complains about the index name being too long while you&#8217;re indexing many keys ot once.</li></ul><p>So let&#8217;s say we want to create two indexes instead of just one, make it unique, have it work in th ebackground and see if it worked.</p><pre class="chili"><code class="php">try {
    $sweet_collection-&gt;ensureIndex(
        array(
            'slug' =&gt; 1,
            'title =&gt; -1
        ),
        array(
            'unique' =&gt; 1,
            'background =&gt; 1,
            'safe' =&gt; 1
        )
    );
}
catch(MongoCursorException $e) {
    echo "Oh, hells noes!";
}</code></pre><p>I think you get the general idea here. You can&#8217;t create unique indexes on non-unique values, of course. Shoudl we have two or more identical titles or slugs, the unique index will fail, whch actually is quite probable in this example. Fun, huh? That&#8217;ll teach you to copy paste code without checking what it does.</p><p>I think that&#8217;ll suffice for now. As a closing hint, I&#8217;d like to point you to a sweet package on <a
title="PHPClasses" href="http://www.phpclasses.org/" target="_blank">phpclasses.org</a> by <a
title="Cesar D. Rodas @ phpclasses.org" href="http://cesarodas.com/" target="_blank">Cesar D. Rodas</a>. It&#8217;s called <a
title="MongoFS @ phpclasses.org" href="http://www.phpclasses.org/package/6086-PHP-Store-and-get-data-in-MongoDB-GridFS-like-files.html" target="_blank">MongoFS</a> and allows you to store and get data in MongoDB GridFS like files. See, MongoDB stores large objects as chunks of data as well as its metadata. It stores it in chunks are BSON objects in MongoDB are limited to  4 MB in size. The chunk approach allows you to fetch a range of data, which could come in handy. Of course, there are articles covering GridFS already, so I&#8217;ll just point you to <a
title="GridFS @ snailinaturtleneck.com" href="http://www.snailinaturtleneck.com/blog/2010/02/11/mongo-mailbag-2-updating-gridfs-files/" target="_blank">them</a> instead (by &#8220;them&#8221; I mean &#8220;this specific article&#8221; &#8211; deal with it). Definitely worth checking out.</p><p>No related posts.</p>]]></content:encoded> <wfw:commentRss>http://pronewb.com/mongodb-as-in-humongous-not-retarded/feed</wfw:commentRss> <slash:comments>14</slash:comments> </item> <item><title>A Popurls Clone with PHP, jQuery, Awesomeness</title><link>http://pronewb.com/a-popurls-clone-with-php-jquery-awesomeness</link> <comments>http://pronewb.com/a-popurls-clone-with-php-jquery-awesomeness#comments</comments> <pubDate>Tue, 23 Mar 2010 13:21:57 +0000</pubDate> <dc:creator>william</dc:creator> <category><![CDATA[Code]]></category> <category><![CDATA[aggregator]]></category> <category><![CDATA[clone]]></category> <category><![CDATA[css]]></category> <category><![CDATA[cssglobe]]></category> <category><![CDATA[delicious]]></category> <category><![CDATA[digg]]></category> <category><![CDATA[dzone]]></category> <category><![CDATA[eagle eye]]></category> <category><![CDATA[engadget]]></category> <category><![CDATA[feeds]]></category> <category><![CDATA[i can haz teh c0d3z]]></category> <category><![CDATA[IDNA]]></category> <category><![CDATA[javascript]]></category> <category><![CDATA[jquery]]></category> <category><![CDATA[nerd]]></category> <category><![CDATA[php]]></category> <category><![CDATA[popurls]]></category> <category><![CDATA[reddit]]></category> <category><![CDATA[sexy]]></category> <category><![CDATA[simplepie]]></category> <category><![CDATA[spanky]]></category> <category><![CDATA[tooltip]]></category> <category><![CDATA[tuaw]]></category> <category><![CDATA[tutorial]]></category> <category><![CDATA[wired]]></category> <category><![CDATA[xhtml]]></category><guid
isPermaLink="false">http://pronewb.com/?p=242</guid> <description><![CDATA[Good people of the Internets, I know a good deal of you frequently visit some sort of social website and/or aggregator such as Popurls, Reddit, Digg, Developer Zone, or what have you. After a deep and thorough analysis of my visitor statistics (read: pulling data out of my ass), many of you seem to like [...]Related posts:<ol><li><a
href='http://pronewb.com/hands-on-tips-for-php-security' rel='bookmark' title='Hands-on tips for PHP security'>Hands-on tips for PHP security</a></li></ol>]]></description> <content:encoded><![CDATA[<p><a
href="http://pronewb.com/wp-content/uploads/popruls_clone_1.jpg"><img
class="alignleft size-medium wp-image-274" title="Popurls clonw ith PHP, Jquery, Awesomeness" src="http://pronewb.com/wp-content/uploads/popruls_clone_1-300x163.jpg" alt="Popurls clonw ith PHP, Jquery, Awesomeness" width="300" height="163" /></a>Good people of <a
title="Bushism - the internets" href="http://www.albinoblacksheep.com/flash/internets" target="_blank">the Internets</a>, I know a good deal of you frequently visit some sort of social website and/or aggregator such as <a
title="Popurls.com" href="http://popurls.com" target="_blank">Popurls</a>, <a
title="Reddit.com" href="http://reddit.com" target="_blank">Reddit</a>, <a
title="Digg" href="http://digg.com" target="_blank">Digg</a>, <a
title="Developer Zone" href="http://dzone.com" target="_blank">Developer Zone</a>, or what have you. After a deep and thorough analysis of my visitor statistics (read: pulling data out of my ass), many of you seem to like articles about PHP. This is not surprising, as PHP is a very <a
title="Statistics" href="http://www.tiobe.com/index.php/content/paperinfo/tpci/index.html" target="_blank">popular</a> (scripting) language. Then again, why anybody would want to read my incoherent ramblings is still a mystery to me. If you&#8217;re reading this, kudos! You officially have nothing better to do. Encouraging, isn&#8217;t it? Btw, Reddit, thanks for /r/nsfw/.</p><p>Since I have a crazy workload right now, I feel this is the perfect time to write a quick n&#8217; dirty tutorial on how to build your very own Popurls. Impress your friends and/or boss with a nifty, hand made news aggregator. Yes, very buzz word friendly. This is part one of a series of articles where we start from this article&#8217;s code and later on expand it to employ a simple admin interface for the feeds as well as pulling our content and playing with it in Flash using ActionScript 3 and from there build a sweet little Flash widget. I am weirdly excited about this to the point of scaring myself, so let&#8217;s STFU and get started. If you want to see a demo, well, you&#8217;re in luck. <a
title="Popurls Clone Demo" href="http://pronewb.com/sandbox/popurls-clone.php" target="_blank">Go there</a>!</p><hr
/><h4>Abstract</h4><p>What we&#8217;re going to do is use SimplePie to fetch an array of feeds of different formats, cache them and output the whole shebang. Then we&#8217;re gonna style it with some CSS and use some simple jQuery interactivity to sweeten the deal.</p><hr
/><h4>SimplePie is simple, not related to pi, tastes like it</h4><p>We&#8217;ll start, obviously, with the back end. I should start with confessing that I&#8217;m an avid fan of the <a
title="KeepIt Simple Stupid @ wkipedia" href="http://en.wikipedia.org/wiki/KISS_principle" target="_blank">KISS</a> and <a
title="Don't Repeat Yourself @ wikipedia" href="http://en.wikipedia.org/wiki/Don't_repeat_yourself " target="_blank">DRY</a> principles. Instead of building our <a
title="Reinventing the wheel" href="http://en.wikipedia.org/wiki/Reinventing_the_wheel" target="_blank">very own feed parser</a>, we&#8217;ll use the excellent <a
title="SimplePie" href="http://simplepie.org/ " target="_blank">SimplePie</a> class together with the <a
title="IDNA Convert Class" href="http://www.phpclasses.org/browse/package/1509.html" target="_blank">IDNA Convert</a> class. Don&#8217;t worry, the last one is bundled with the <a
title="SimplePie 1.2 Download" href="http://github.com/rmccue/simplepie/downloads" target="_blank">SimplePie 1.2 download</a>. The IDNA Convert class helps us, amongst other things, to handle feeds where the domain name is internationalized according to <a
title="RFC 3490" href="http://www.faqs.org/rfcs/rfc3490.html" target="_blank">RFC 3490</a>, <a
title="RFC 3491" href="http://www.faqs.org/rfcs/rfc3491.html" target="_blank">3491</a>, <a
title="RFC 3492" href="http://www.faqs.org/rfcs/rfc3492.html" target="_blank">3492</a> and <a
title="RFC 3454" href="http://www.faqs.org/rfcs/rfc3454.html" target="_blank">3454</a>. IDNA is optional but as long as we already have it, why the fuck not?</p><p>First things first. Are you ready, willing and able to harness the awesomeness that is SimplePie? Assuming you have downloaded the package, unzipped/untarred it and uploaded to your web server/LAMP/WAMP, direct yourself to</p><pre class="chili"><code class="php">http://[your_server]/[simplepie_path]/compatibility_test/sp_compatibility_test.php</code></pre><hr
/><script type="text/javascript">google_ad_client="pub-8939939010469559";google_ad_slot="9013590878";google_ad_width=468;google_ad_height=60;</script><script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js"></script></p><hr
/>Great success? Good, then <a
title="Let's a go" href="http://www.entertonement.com/clips/lhgrkvtfhh--Mario-Let's-GoMario-Nintendo-64-Mario-Kart-64-" target="_blank">let&#8217;s get started</a>. As a side note, if you want to explore all the goodies that you get to play with , go to the SimplePie Documentation, which is a comprehensive <a
title="SmplePie API Documentation" href="http://simplepie.org/wiki/reference/start" target="_blank">API documentation</a>.</p><hr
/><h4>Getting dirty</h4><p>Before continuing, I should point out that SimplePie has automagical caching. It&#8217;s quite sweet. Just create a folder in the same directory as the SimplePie class called cache and chmod it so that the script may write to it. Let&#8217;s start by including the SimplePie library and the aforementioned IDNA Class as well ass initializing SimplePie and tell it which feeds to use. For the remainder of this article, I&#8217;ll assume that SimplePie is in the root of your folder and IDNA is in the folder idn.</p><pre class="chili"><code class="php">require_once('simplepie.inc');
require_once('idn/idna_convert.class.php');

$popurls = new SimplePie();
$popurls-&gt;set_feed_url(
    array(
        'http://feeds.digg.com/digg/popular.rss',
        'http://www.reddit.com/.rss',
        'http://feeds.delicious.com/v2/rss/',
        'http://www.dzone.com/links/feed/frontpage/rss.xml',
        'http://feeds.wired.com/wired/index',
        'http://www.tuaw.com/rss.xml',
        'http://www.engadget.com/rss.xml'
    )
);</code></pre><p>I twelve or so lines o&#8217; code, we&#8217;ve done the dirty work for fetching the feeds that we want o play with. And who said dealing with code is hard? Pff. Thankfully, the SimplePie method <strong>set_feed_url</strong> accepts an array which makes our lives so much easier. Before getting down to the nitty gritty of displaying the feeds, you should start out with setting a parameter called <strong>set_item_limit</strong>. It does what you think, namely, limiting the number of items to return from each feed. If you don&#8217;t, chances are that you&#8217;ll have to wait for a long, long, looong time before actually seeing anything on your screen. That&#8217;ll make you come back here and add some snarky comment, claiming that the c0dez dun work lulz, n00b. Fair enough, the blog is called profeshunl newbie, but still. It&#8217;s about kharma. For our first proof-of-concept, a limit of three items per feed should suffice. While we&#8217;re at it, we&#8217;ll initialize the feeds and make sure that it&#8217;s served with UTF-8.</p><pre class="chili"><code class="php">$popurls-&gt;set_item_limit(3);
$popurls-&gt;init();
$popurls-&gt;handle_content_type();</code></pre><p>Not that hard, was it? Told you so. Now let&#8217;s set up a very simple XHTML structure below the PHP block in order to display the goods. For this part of the article, well settle for displaying the content in tables. Don&#8217;t try validating the code, though. It may seem a little bit slow the first time you runt this script, which is expected. When your browser&#8217;s done, check the cache directory. There should be seven .spc files there.</p><pre class="chili"><code class="php">&lt;!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"&gt;
&lt;html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"&gt;
&lt;head&gt;
    &lt;title&gt;p0wnurls&lt;/title&gt;
        &lt;style type="text/css"&gt;
        body {
        font-family: 'Lucida Grande', Helvetica, Arial, sans-serif;
        font-size:10px;
    }
    table {
        border-bottom: 3px solid #eeeeee;
        margin: 20px 0 0 0;
        padding: 0 0 20px 0;
        font-size: 10px;
        width: 100%;
    }
    td {
        vertical-align: top;
        border-bottom: 1px solid #f3f3f3;
    }
    .label {
        font-weight: bold;
        width: 150px;
    }
    &lt;/style&gt;
&lt;/head&gt;
&lt;body&gt;
    &lt;h1&gt;p0wnurls&lt;/h1&gt;

    &lt;!-- Yes, you love tables as much as I do --&gt;

    &lt;?
    // Loop through each items
    foreach ( $popurls-&gt;get_items() as $feed_item ) {
        // Create a reference to the current item's parent feed
        $feed_parent = $feed_item-&gt;get_feed();
    ?&gt;

        &lt;table&gt;
            &lt;tr&gt;
                &lt;td class="label"&gt;Favicon:&lt;/td&gt;&lt;td&gt;&lt;?php echo $feed_parent-&gt;get_favicon(); ?&gt; (&lt;img src="&lt;?php echo $feed_parent-&gt;get_favicon(); ?&gt;"&gt;)&lt;/td&gt;
            &lt;/tr&gt;
            &lt;tr&gt;
                &lt;td class="label"&gt;Permalink:&lt;/td&gt;&lt;td&gt;&lt;?php echo $feed_item-&gt;get_permalink(); ?&gt;&lt;/td&gt;
            &lt;/tr&gt;
            &lt;tr&gt;
                &lt;td class="label"&gt;Title:&lt;/td&gt;&lt;td&gt;&lt;?php echo $feed_item-&gt;get_title(); ?&gt;&lt;/td&gt;
            &lt;/tr&gt;
            &lt;tr&gt;
                &lt;td class="label"&gt;Date:&lt;/td&gt;&lt;td&gt;&lt;?php echo $feed_item-&gt;get_date(); ?&gt;&lt;/td&gt;
            &lt;/tr&gt;
            &lt;tr&gt;
                &lt;td class="label"&gt;Content:&lt;/td&gt;&lt;td&gt;&lt;?php echo $feed_item-&gt;get_description(); ?&gt;&lt;/td&gt;
            &lt;/tr&gt;
            &lt;tr&gt;
                &lt;td class="label"&gt;Description:&lt;/td&gt;&lt;td&gt;&lt;?php echo $feed_item-&gt;get_description(); ?&gt;&lt;/td&gt;
            &lt;/tr&gt;
            &lt;tr&gt;
                &lt;td class="label"&gt;Parent Permalink:&lt;/td&gt;&lt;td&gt;&lt;?php echo $feed_parent-&gt;get_permalink(); ?&gt;&lt;/td&gt;
            &lt;/tr&gt;
            &lt;tr&gt;
                &lt;td class="label"&gt;Parent Title:&lt;/td&gt;&lt;td&gt;&lt;?php echo $feed_parent-&gt;get_title(); ?&gt;&lt;/td&gt;
            &lt;/tr&gt;
        &lt;/table&gt;

    &lt;?php
    }
    ?&gt;
&lt;/body&gt;
&lt;/html&gt;</code></pre><p>Still here? <a
title="Nice. Niiccceeeeeee." href="http://www.youtube.com/watch?v=8hdbns1Xdk0" target="_blank">Nice</a>. As you can see, more often than not the description is the same as the content. Also, we need to strip away the tags and crap that we don&#8217;t need. Basically, we only want the raw text. Let&#8217;s add a row to each table and see what we can come up with, <a
title="Mmm'kay" href="http://aftergradavenues.files.wordpress.com/2009/04/office-space.jpg" target="_blank">mm&#8217;kay</a>? Let&#8217;s try something like</p><pre class="chili"><code class="php">&lt;tr&gt;
    &lt;td class="label"&gt;Description Stripped:&lt;/td&gt;&lt;td&gt;&lt;?php echo html_entity_decode(strip_tags($feed_item-&gt;get_description()), ENT_QUOTES, 'UTF-8'); ?&gt;&lt;/td&gt;
&lt;/tr&gt;
</code></pre><p>Boom. Much better. <strong><a
title="html_entity_decode at php.net" href="http://php.net/manual/en/function.html-entity-decode.php" target="_blank">html_entity_decode</a></strong> will convert <a
title="html entities" href="http://www.w3schools.com/tags/ref_entities.asp" target="_blank">html entities</a> to their should-be characters. SInce we don&#8217;t need any images or, really, any inline elements, we&#8217;ll use <a
title="strip_tags at php.net" href="http://" target="_blank"><strong>strip_tags</strong></a>. Note that strip_tags does not in any way validate the HTML it parses. If the HTML is borked, it may lead to unexpected results, which is fancy talk for &#8220;it&#8217;ll blow up in your face and have you sleeping in the shower&#8221;. If you want to, you can always roll your own stripping mechanism with a <a
title="Regular expression hoo-haa" href="http://kev.coolcavemen.com/2007/03/ultimate-regular-expression-for-html-tag-parsing-with-php/" target="_blank">regular expression</a>.  I wouldn&#8217;t recommend it, but if you&#8217;re the adventurous type or just don&#8217;t trust strip_tags, go ahead! The last link provides you with the following regex;</p><pre class="chili"><code class="php">$regex = "/&lt;\/?\w+((\s+(\w|\w[\w-]*\w)(\s*=\s*(?:\".*?\"|'.*?'|[^'\"&gt;\s]+))?)+\s*|\s*)\/?&gt;/i";</code></pre><p>…which should suffice as a starting point for you. And if you want to just strip whitespace, how about</p><pre class="chili"><code class="php">$regex = '/(?:(?&lt;=\&gt;)|(?&lt;=\/\&gt;))(\s+)(?=\&lt;\/?)/';</code></pre><p>which was found over <a
title="Strip whitespace regex" href="http://www.blog.highub.com/regular-expression/php-regex-regular-expression/php-regex-remove-whitespace-from-html/" target="_blank">here</a>.</p><p>Now that we know how to fetch the information we need, there is one thing that need to be sorted out. The default action for SimplePie is to aggregate all the feeds. This means that they&#8217;re all in one big list o&#8217; items, sorted by date. Normally this would be fine, but we want a per feed sorting mechanism, right? Right. If you don&#8217;t you can safely skip this part. Then again, if you skip it, the rest of this article will be reeeally confusing.</p><hr
/><h4>Are we there yet?</h4><p>I like playing with arrays, so let&#8217;s expand our initial code a bit. Let&#8217;s make an associative array of it and add a key for each feed. Let&#8217;s go with a nice name of the source domain. Manually for now. If you don&#8217;t like nested foreach loops, now&#8217;s your time to look away.</p><pre class="chili"><code class="php">// Include SP
require_once('simplepie.inc');
require_once('idn/idna_convert.class.php');

// Instantiate a source array with domain short name as key and feed URL as value
$_source = array(
    'digg'=&gt;'http://feeds.digg.com/digg/popular.rss',
    'reddit'=&gt;'http://www.reddit.com/.rss',
    'delicious'=&gt;'http://feeds.delicious.com/v2/rss/',
    'dzone'=&gt;'http://www.dzone.com/links/feed/frontpage/rss.xml',
    'wired'=&gt;'http://feeds.wired.com/wired/index',
    'tuaw'=&gt;'http://www.tuaw.com/rss.xml',
    'engadget'=&gt;'http://www.engadget.com/rss.xml'
);

// Instantiate empty array
$_sorted = array();

// Loop through the source array
foreach ( $_source as $_feed_key=&gt;$_feed_value ) {

    // Instantiate new SP
    $_feed = new SimplePie();
    $_feed-&gt;set_feed_url($_feed_value);
    $_feed-&gt;init();

    // Loop through the items of the current feed
    foreach ( $_feed-&gt;get_items(0, 3) as $__item ) {

        // Add title, favicon and permalink to feed and items to the sorted array
        $_sorted[$_feed_key]['title'] = $_feed-&gt;get_title();
        $_sorted[$_feed_key]['favicon'] = $_feed-&gt;get_favicon();
        $_sorted[$_feed_key]['permalink'] = $_feed-&gt;get_permalink();
        $_sorted[$_feed_key]['feed_items'][] = array(
            'title' =&gt; $__item-&gt;get_title(),
            'date' =&gt; $__item-&gt;get_date(),
            'permalink' =&gt; $__item-&gt;get_permalink(),
            'content' =&gt; html_entity_decode(strip_tags($__item-&gt;get_description()), ENT_QUOTES, 'UTF-8')
        );
    } 

}</code></pre><p>Short and sweet. Try a <strong>print_r( $_sorted );</strong> and view source. Looks neat, doesn&#8217;t it? Note that set_item_limit has been removed in favor of specifying an offset and a limit to <strong>get_items()</strong> instead. set_item_limit wouldn&#8217;t work at all. As you can see from the date values, the items are sorted in ascending order. Jut the way we want it. The content part may be way too long though. We only need something like the first 100 characters of it to function as an excerpt. Let&#8217;s truncate the content. Yes, let&#8217;s. Add some sort of truncation function such as</p><pre class="chili"><code class="php">// Truncate string
function truncate( $string, $length=100 )
{

    // Is it shorter than out string? If so, return it as is.
    if( strlen( $string ) &lt;= $length )
    {
        return $string;
    }

    // No? Well, regex and substr the fuck out of that string and append an ellipsis at the end.
    return preg_replace('/\s+?(\S+)?$/', '', substr($string, 0, $length)).'...';
}</code></pre><p>After that it&#8217;s only a matter of wrapping the value for the content key with the truncate function in the inner foreach loop</p><pre class="chili"><code class="php">$_sorted[$_feed_key]['feed_items'][] = array(
    'title' =&gt; $__item-&gt;get_title(),
    'date' =&gt; $__item-&gt;get_date(),
    'permalink' =&gt; $__item-&gt;get_permalink(),
    'content' =&gt; truncate(html_entity_decode(strip_tags( $__item-&gt;get_content() ), ENT_QUOTES, 'UTF-8'))
);</code></pre><hr
/><script type="text/javascript">google_ad_client="pub-8939939010469559";google_ad_slot="9013590878";google_ad_width=468;google_ad_height=60;</script><script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js"></script></p><hr
/>Looking good, right? As you may notice, some feeds actually don&#8217;t have any content or just have a &#8220;submitted by…&#8221; kind of string, which no fun. Let&#8217;s add an ugly conditional that checks if the content is empty or, in this case, the feed is from Reddit. In that case, we&#8217;ll use the title as excerpt instead.</p><pre class="chili"><code class="php">// Get the content
$_content = $__item-&gt;get_content();

// If it's empty or if it's Reddit...
if ( empty( $_content ) || $_feed_key == 'reddit')
{
    // Jut use the title
    $_content = $__item-&gt;get_title();
} 

$_sorted[$_feed_key]['feed_items'][] = array(
    'title' =&gt; $__item-&gt;get_title(),
    'date' =&gt; $__item-&gt;get_date(),
    'permalink' =&gt; $__item-&gt;get_permalink(),
    'content' =&gt; truncate(html_entity_decode(strip_tags( $_content ), ENT_QUOTES, 'UTF-8'))
);</code></pre><p>Much better. However, we need to rearrange and restyle our code a bit. And lets get rid of those horrible tables and go with unordered lists instead.</p><pre class="chili"><code class="php">&lt;!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"&gt;
&lt;html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"&gt;
&lt;head&gt;
    &lt;title&gt;p0wnurls&lt;/title&gt;
    &lt;style type="text/css"&gt;
       body {
        font-family: 'Lucida Grande', Helvetica, Arial, sans-serif;
        font-size:10px;
    }
    ul {
        border-bottom: 3px solid #eeeeee;
        font-size: 10px;
        width: 100%;
    }
    ul li ul {
        border-bottom:0;
        margin-bottom:20px;
    }
    ul li ul li {
        border-bottom:1px solid #f3f3f3;
    }
    .label {
        font-weight: bold;
        padding: 0 10px 0 0;
    }
    .actual_feed_items {
        margin: 10px;
    }
    &lt;/style&gt;
&lt;/head&gt;
&lt;body&gt;
    &lt;h1&gt;p0wnurls&lt;/h1&gt;

    &lt;?
    foreach ( $_sorted as $feed_name=&gt;$feed )
    {
    ?&gt;

        &lt;h2&gt;&lt;?php echo $feed_name . ' | ' . $feed['title']; ?&gt;&lt;/h2&gt;
        &lt;ul&gt;
            &lt;li&gt;
                &lt;span class="label"&gt;Favicon:&lt;/span&gt;&lt;span&gt;&lt;?php echo $feed['favicon']; ?&gt; (&lt;img src="&lt;?php echo $feed['favicon']; ?&gt;"&gt;)&lt;/span&gt;
            &lt;/li&gt;
            &lt;li&gt;
                &lt;span class="label"&gt;Permalink:&lt;/span&gt;&lt;span&gt;&lt;?php echo $feed['permalink']; ?&gt;&lt;/span&gt;
            &lt;/li&gt;
            &lt;li&gt;
                     &lt;?php
                     foreach ( $feed['feed_items'] as $feed_item ) {
                     ?&gt;

                    &lt;ul class="actual_feed_items"&gt;
                        &lt;li&gt;
                            &lt;span class="label"&gt;Title:&lt;/span&gt;&lt;span&gt;&lt;?php echo $feed_item['title']; ?&gt;&lt;/span&gt;
                        &lt;/li&gt;
                        &lt;li&gt;
                            &lt;span class="label"&gt;Permalink:&lt;/span&gt;&lt;span&gt;&lt;?php echo $feed_item['permalink']; ?&gt;&lt;/span&gt;
                        &lt;/li&gt;
                        &lt;li&gt;
                            &lt;span class="label"&gt;Date:&lt;/span&gt;&lt;span&gt;&lt;?php echo $feed_item['date']; ?&gt;&lt;/span&gt;
                        &lt;/li&gt;
                        &lt;li&gt;
                            &lt;span class="label"&gt;Content:&lt;/span&gt;&lt;span&gt;&lt;?php echo $feed_item['content']; ?&gt;&lt;/span&gt;
                        &lt;/li&gt;
                    &lt;/ul&gt;
                     &lt;?php
                     }
                     ?&gt;
            &lt;/li&gt;
        &lt;/ul&gt;

    &lt;?php
    }
    ?&gt;
&lt;/body&gt;
&lt;/html&gt; </code></pre><hr
/><h4>So, are we there yet?</h4><p>Starting to see the resemblance to Popurls? No? You douche. Well, actually, me neither. So lets fix that. First off, let&#8217;s add a container that we center on the screen. Then we&#8217;ll divide the feeds into columns of three. Then do some hacky crap to add a div after every third column. After that, we&#8217;ll divide each feed&#8217;s items in two &#8211; the top half is shown and the other part is hidden until we press a link. After that, we should style it like Popurls and include jQuery. Let&#8217;s begin with the body. This may seem a little messy. And that&#8217;s because it is.</p><pre class="chili"><code>&lt;body&gt;

    &lt;div id="container"&gt;
    &lt;h1&gt;p0wnurls&lt;/h1&gt;
    &lt;?
    $i = 1;
    foreach ( $_sorted as $feed_name=&gt;$feed )
    {
    ?&gt;
        &lt;div class="feed_container"&gt;
            &lt;div class="feed_title"&gt;&lt;a href="&lt;?php echo $feed['permalink']; ?&gt;" title="&lt;?php echo $feed['title']; ?&gt;"&gt;&lt;img src="&lt;?php echo $feed['favicon']; ?&gt;" alt="&lt;?php echo $feed['title']; ?&gt;" /&gt; &lt;?php echo $feed_name; ?&gt;&lt;/a&gt;&lt;/div&gt;
                &lt;ul class="feed_items"&gt;
                    &lt;?php
                    $j = 0;
                    foreach ( $feed['feed_items'] as $feed_item )
                    {
                        // If we've reached half of our feed items, split to a new unordered list
                        if ( $j == $half_feed_items )
                        {
                        ?&gt;

                        &lt;li&gt;
                            &lt;div class="more"&gt;&lt;/div&gt;
                            &lt;ul class="feeds_extra"&gt;

                     &lt;?php
                        }
                        ?&gt;
                        &lt;li&gt;
                                &lt;a href="&lt;?php echo $feed_item['permalink']; ?&gt;" title="&lt;?php echo $feed_item['title']; ?&gt;" class="tooltip"&gt;&lt;?php echo $feed_item['title']; ?&gt;&lt;/a&gt;
                                &lt;span&gt;&lt;?php echo $feed_item['content']; ?&gt;&lt;/span&gt;
                        &lt;/li&gt;
                    &lt;?php
                        $j[imagine_two_plus_signs_here];
                        // When we've reached to total number of feed items, close the ul up
                        if ( $j == $total_feed_items )
                        {
                    ?&gt;
                        &lt;/ul&gt;&lt;/li&gt;
                    &lt;?php
                        }
                     }
                     ?&gt;
                &lt;/ul&gt;
        &lt;/div&gt;
        &lt;?php
        // If the remainder of i divided by 3 is 0 - add a clearing div
        if ( ($i%3) == 0 ) {
        ?&gt;
            &lt;div class="clear"&gt;&lt;/div&gt;
        &lt;?php
        }
        $i[imagine_two_plus_signs_here];
        ?&gt;
    &lt;?php
    }
    ?&gt;
    &lt;/div&gt;
&lt;/body&gt;</code></pre><p>Don&#8217;t go copy/pasting that code &#8211; as it turns out, my code highlighting script of choice in combination with WordPress strips away any plus signs, rendering the loops somewhat&#8230; lacking&#8230; Hm. Just check that $i and $j get incremented in the end of each loop and you should be fine. I added two very stealthy clues as to where to add the plus signs. Look for the clues, eagle eye, and report back later. Notice the rearrangement of code. We use the title for the permalink anchor as, well, the title, and put the content in a span. As a courtesy for all those of you who prefer to echo the content instead of multiple opening and closing php tags, here&#8217;s the inner loop for you to play with;</p><pre class="chili"><code class="php">$j = 0;
foreach ( $feed['feed_items'] as $feed_item )
{
    if ( $j == $half_feed_items )
    {
        echo '
    &lt;li&gt;
        &lt;div class="more"&gt;&lt;/div&gt;
        &lt;ul class="feeds_extra"&gt;
        ';
    }
    echo '
    &lt;li&gt;
            &lt;a href="' . $feed_item['permalink'] . '" title="' . $feed_item['title'] . '" class="tooltip"&gt;' . $feed_item['title'] . '&lt;/a&gt;
            &lt;span&gt;' . $feed_item['content'] . '&lt;/span&gt;
    &lt;/li&gt;
    ';
    $j  ;

    // Have we printed the last feed item? If so, close the ul up
    if ( $j == $total_feed_items )
    {
        echo '&lt;/ul&gt;&lt;/li&gt;';
    }
}</code></pre><p>Next up &#8211; CSS. This is nothing special and shouldn&#8217;t be hard to follow.</p><pre class="chili"><code class="css">body {
        font-family: 'Lucida Grande', Helvetica, Arial, sans-serif;
        font-size:12px;
        text-align:center;
        background :#000000;
        color: #f3f3f3;
    }
    a {
        text-decoration:none;
        color: #83bacf;
    }
    #container {
        width:960px;
        margin: 0 auto;
        text-align:left;
    }
    .feed_container {
        float:left;
        width:320px;
        display:inline;
    }
    ul {
        padding: 5px 5px 5px 0;
        margin:0;
    }
    ul &gt; li {
        list-style-type: none;
        margin:0;
        padding:0;
    }
    ul li span {
        display:none;
    }
    .feed_items li {
        padding: 5px 0;
        border-top: 1px solid #505050;
    }
    .more {
        display:block;
        background:#505050;
        height:10px;
    }
    .feeds_extra {
        display:none;
    }
    .clear {
        clear:both;
        padding: 0 0 10px 0;
    }
    #tooltip {
        position:absolute;
        border:2px solid #afa06b;
        background:#e4dd9c;
        padding: 5px;
        color:#333;
        display:none;
        width: 320px;
        text-align:left;
    }</code></pre><p>Nothing fancy. The container has a width of 960 pixels and each feed gets a third each to play with. We added a dark background and colored the anchors blue and the tooltip yellowish. It matches Popurls color scheme. I think. We&#8217;ve added the necessary code for the tooltip as well. Speaking of tooltip, let&#8217;s include jQuery and the tooltip script. I&#8217;m going with jQuery 1.4.2 and a neat little tooltip that I found on <a
title="Easiest Tooltip and Image Preview Using jQuery" href="http://cssglobe.com/post/1695/easiest-tooltip-and-image-preview-using-jquery" target="_blank">css globe</a>. The only problem is the way that script works. We have to alter it a bit in order to have it display our content in the tooltip. No biggie. We only need to change one line of code, namely line 21 from</p><pre class="chili"><code class="javascript">this.t = this.title;</code></pre><p>to</p><pre class="chili"><code class="javascript">this.t = $(this).siblings().html();</code></pre><p>so that it looks for content in our sibling span instead of the anchor&#8217;s title. Life&#8217;s good, right? Assuming that you put your javascript files in the root of your project, add some javascript in the head of the page</p><pre class="chili"><code class="html">&lt;script type="text/javascript" src="jquery.min.js"&gt;&lt;/script&gt;
&lt;script type="text/javascript" src="tooltip.js"&gt;&lt;/script&gt;
&lt;script type="text/javascript"&gt;
$(document).ready(function(){
    $(".more").live("click", function(){
        $(this).parent().find('.feeds_extra').toggle();
    });
});
&lt;/script&gt;</code></pre><p>Simple. <a
title="Live at jquery.com" href="http://api.jquery.com/live/" target="_blank">live()</a> adds a handler to the event for all elements that match the selector no matte rif they&#8217;re in the DOM now or are added later. <a
title="Bind at jquery.com" href="http://api.jquery.com/bind/" target="_blank">bind</a>(&#8216;click&#8217;, function(){ &#8230; }); would also do if that&#8217;s your preference. With me so far? I thought so. Let&#8217;s add the finishing touches to our main PHP code vlock so that it actually works. Who knew, right? We need to add two variables.</p><pre class="chili"><code class="php">$total_feed_items = 10;
$half_feed_items = round( $total_feed_items/2 );</code></pre><p>They&#8217;re used in the inner loop in the document body. Really, they are. We also need to change the hard coded value in the inner foreach loop to use our variable. Also note that we changed the number of feed items form 3 to 10.</p><pre class="chili"><code class="php">foreach ( $_feed-&gt;get_items(0, $total_feed_items) as $__item )</code></pre><p>To sum up, our PHP block should look something like this (comments removed)</p><pre class="chili"><code class="php">function truncate( $string, $length=100 )
{
    if( strlen( $string ) &lt;= $length )
    {
        return $string;
    }
    return preg_replace('/\s ?(\S )?$/', '', substr($string, 0, $length)).' ...';
}

require_once('simplepie.inc');
require_once('idn/idna_convert.class.php');

$_source = array(
    'digg'=&gt;'http://feeds.digg.com/digg/popular.rss',
    'reddit'=&gt;'http://www.reddit.com/.rss',
    'delicious'=&gt;'http://feeds.delicious.com/v2/rss/',
    'dzone'=&gt;'http://www.dzone.com/links/feed/frontpage/rss.xml',
    'wired'=&gt;'http://feeds.wired.com/wired/index',
    'tuaw'=&gt;'http://www.tuaw.com/rss.xml',
    'engadget'=&gt;'http://www.engadget.com/rss.xml'
);

$_sorted = array();

$total_feed_items = 10;
$half_feed_items = round( $total_feed_items/2 );

foreach ( $_source as $_feed_key=&gt;$_feed_value )
{
    $_feed = new SimplePie();
    $_feed-&gt;set_feed_url($_feed_value);
    $_feed-&gt;init();

    foreach ( $_feed-&gt;get_items(0, $total_feed_items) as $__item )
    {
        $_content = $__item-&gt;get_content();

        if ( empty( $_content ) || $_feed_key == 'reddit')
        {
            $_content = $__item-&gt;get_title();
        } 

        $_sorted[$_feed_key]['title'] = $_feed-&gt;get_title();
        $_sorted[$_feed_key]['favicon'] = $_feed-&gt;get_favicon();
        $_sorted[$_feed_key]['permalink'] = $_feed-&gt;get_permalink();
        $_sorted[$_feed_key]['feed_items'][] = array(
            'title' =&gt; truncate($__item-&gt;get_title()),
            'date' =&gt; $__item-&gt;get_date(),
            'permalink' =&gt; $__item-&gt;get_permalink(),
            'content' =&gt; truncate(html_entity_decode(strip_tags( $_content ), ENT_QUOTES, 'UTF-8'))
        );
    } 

}</code></pre><hr
/><script type="text/javascript">google_ad_client="pub-8939939010469559";google_ad_slot="9013590878";google_ad_width=468;google_ad_height=60;</script><script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js"></script></p><hr
/>YMMV. And the entire HTML page should look similar to this;</p><pre class="chili"><code class="html">&lt;!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"&gt;
&lt;html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"&gt;
&lt;head&gt;
    &lt;meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /&gt;
    &lt;title&gt;p0wnurls&lt;/title&gt;

    &lt;style type="text/css"&gt;
    body {
        font-family: 'Lucida Grande', Helvetica, Arial, sans-serif;
        font-size:12px;
        text-align:center;
        background :#000000;
        color: #f3f3f3;
    }
    a {
        text-decoration:none;
        color: #83bacf;
    }
    #container {
        width:960px;
        margin: 0 auto;
        text-align:left;
    }
    .feed_container {
        float:left;
        width:320px;
        display:inline;
    }
    ul {
        padding: 5px 5px 5px 0;
        margin:0;
    }
    ul &gt; li {
        list-style-type: none;
        margin:0;
        padding:0;
    }
    ul li span {
        display:none;
    }
    .feed_items li {
        padding: 5px 0;
        border-top: 1px solid #505050;
    }
    .more {
        display:block;
        background:#505050;
        height:10px;
    }
    .feeds_extra {
        display:none;
    }
    .clear {
        clear:both;
        padding: 0 0 10px 0;
    }
    #tooltip {
        position:absolute;
        border:2px solid #afa06b;
        background:#e4dd9c;
        padding: 5px;
        color:#333;
        display:none;
        width: 320px;
        text-align:left;
    }

    &lt;/style&gt;
        &lt;script type="text/javascript" src="jquery.min.js"&gt;&lt;/script&gt;
        &lt;script type="text/javascript" src="tooltip.js"&gt;&lt;/script&gt;
        &lt;script type="text/javascript"&gt;
        $(document).ready(function(){
            $(".more").live("click", function(){
                $(this).parent().find('.feeds_extra').toggle();
            });
        });
        &lt;/script&gt;
&lt;/head&gt;
&lt;body&gt;

    &lt;div id="container"&gt;
    &lt;h1&gt;p0wnurls&lt;/h1&gt;
    &lt;?
    $i = 1;
    foreach ( $_sorted as $feed_name=&gt;$feed )
    {
    ?&gt;
        &lt;div class="feed_container"&gt;
            &lt;div class="feed_title"&gt;&lt;a href="&lt;?php echo $feed['permalink']; ?&gt;" title="&lt;?php echo $feed['title']; ?&gt;"&gt;&lt;img src="&lt;?php echo $feed['favicon']; ?&gt;" alt="&lt;?php echo $feed['title']; ?&gt;" /&gt; &lt;?php echo $feed_name; ?&gt;&lt;/a&gt;&lt;/div&gt;
                &lt;ul class="feed_items"&gt;
                    &lt;?php
                    $j = 0;
                    foreach ( $feed['feed_items'] as $feed_item )
                    {
                        // If we've reached half of our feed items, split to a new unordered list
                        if ( $j == $half_feed_items )
                        {
                        ?&gt;

                        &lt;li&gt;
                            &lt;div class="more"&gt;&lt;/div&gt;
                            &lt;ul class="feeds_extra"&gt;

                     &lt;?php
                        }
                        ?&gt;
                        &lt;li&gt;
                                &lt;a href="&lt;?php echo $feed_item['permalink']; ?&gt;" title="&lt;?php echo $feed_item['title']; ?&gt;" class="tooltip"&gt;&lt;?php echo $feed_item['title']; ?&gt;&lt;/a&gt;
                                &lt;span&gt;&lt;?php echo $feed_item['content']; ?&gt;&lt;/span&gt;
                        &lt;/li&gt;
                    &lt;?php
                        $j[imagine_two_plus_signs_here];
                        // When we've reached to total number of feed items, close the ul up
                        if ( $j == $total_feed_items )
                        {
                    ?&gt;
                        &lt;/ul&gt;&lt;/li&gt;
                    &lt;?php
                        }
                     }
                     ?&gt;
                &lt;/ul&gt;
        &lt;/div&gt;
        &lt;?php
        // If the remainder of i divided by 3 is 0 - add a clearing div
        if ( ($i%3) == 0 ) {
        ?&gt;
            &lt;div class="clear"&gt;&lt;/div&gt;
        &lt;?php
        }
        $i[imagine_two_plus_signs_here];
        ?&gt;
    &lt;?php
    }
    ?&gt;
    &lt;/div&gt;
&lt;/body&gt;
&lt;/html&gt;</code></pre><p>See, that wasn&#8217;t so hard, was it? The complete page is available <a
title="Popurls Clone Demo" href="http://pronewb.com/sandbox/popurls-clone.php" target="_blank">here</a> for your viewing pleasure. Again, note the lack of two plus signs in the inner loop. Instead of a nifty &#8220;More&#8221; button, we have a clunky grey bar. I leave it as an exercise for the reader to do something fun with it. That&#8217;s about it for this time. Next time we&#8217;ll see if we can&#8217;t make this code OO and add an admin interface to handle the feeds. Calm down, spanky, we&#8217;ll get there. Now I need to get some sleep. I&#8217;ve been watching <a
title="Dexter on wikipedia" href="http://en.wikipedia.org/wiki/Dexter_(TV_series)" target="_blank">Dexter</a> a whole lot lately and he&#8217;s an inspiration, to say the least. The down side is that the show takes time from quality doing-jack-shit-on-the-Internet time. I have to see what I can do about that.</p><p>Related posts:<ol><li><a
href='http://pronewb.com/hands-on-tips-for-php-security' rel='bookmark' title='Hands-on tips for PHP security'>Hands-on tips for PHP security</a></li></ol></p>]]></content:encoded> <wfw:commentRss>http://pronewb.com/a-popurls-clone-with-php-jquery-awesomeness/feed</wfw:commentRss> <slash:comments>20</slash:comments> </item> <item><title>Hands-on tips for PHP security</title><link>http://pronewb.com/hands-on-tips-for-php-security</link> <comments>http://pronewb.com/hands-on-tips-for-php-security#comments</comments> <pubDate>Thu, 11 Mar 2010 12:00:29 +0000</pubDate> <dc:creator>william</dc:creator> <category><![CDATA[Code]]></category> <category><![CDATA[ajax]]></category> <category><![CDATA[coffee]]></category> <category><![CDATA[csrf]]></category> <category><![CDATA[csrf-magic]]></category> <category><![CDATA[dojo]]></category> <category><![CDATA[escape]]></category> <category><![CDATA[ext]]></category> <category><![CDATA[filter]]></category> <category><![CDATA[filter_input]]></category> <category><![CDATA[filter_input_array]]></category> <category><![CDATA[filter_var]]></category> <category><![CDATA[filter_var_array]]></category> <category><![CDATA[htmlpurifier]]></category> <category><![CDATA[idiots]]></category> <category><![CDATA[inspector gadget]]></category> <category><![CDATA[inspekt]]></category> <category><![CDATA[javascript]]></category> <category><![CDATA[jquery]]></category> <category><![CDATA[kopi luwak]]></category> <category><![CDATA[mootools]]></category> <category><![CDATA[php]]></category> <category><![CDATA[prototype]]></category> <category><![CDATA[sanitize]]></category> <category><![CDATA[security]]></category> <category><![CDATA[sexy]]></category> <category><![CDATA[testing]]></category> <category><![CDATA[token]]></category> <category><![CDATA[triplets]]></category> <category><![CDATA[xss]]></category> <category><![CDATA[yahoo]]></category><guid
isPermaLink="false">http://pronewb.com/?p=164</guid> <description><![CDATA[I got asked to review a fairly large piece of PHP code recently and, whoooo boy, was I in for a treat (treat as in clawing my eyes out with a rusty spoon while listening to Nickelback, as interpreted by Dr Zoidberg. In reverse). No cup of heavenly blessed Kopi Luwak coffee, poured into a cup of golden banana leaves by naked triplets could counter the massive damage done to my corneas or, for that matter, my soul. Or what was left of it.Related posts:<ol><li><a
href='http://pronewb.com/a-popurls-clone-with-php-jquery-awesomeness' rel='bookmark' title='A Popurls Clone with PHP, jQuery, Awesomeness'>A Popurls Clone with PHP, jQuery, Awesomeness</a></li></ol>]]></description> <content:encoded><![CDATA[<p><a
href="http://pronewb.com/wp-content/uploads/php_small.jpg"><img
class="alignleft size-medium wp-image-190" title="PHP Security" src="http://pronewb.com/wp-content/uploads/php_small-300x163.jpg" alt="PHP Security" width="300" height="163" /></a>I got asked to review a fairly large piece of PHP code recently and, whoooo boy, was I in for a treat (treat as in clawing my eyes out with a rusty spoon while listening to Nickelback, as interpreted by <a
title="Dr Zoidberg. Awesome" href="http://en.wikipedia.org/wiki/Doctor_Zoidberg" target="_blank">Dr Zoidberg</a>. In reverse). This magnificent piece of code was an eye opener in many ways and it made me feel a little bit better about myself, to be honest. It employed not only what would be called &#8220;bad practice&#8221;, but also a lot of plain ol&#8217; stupidity. I know you are just dying for examples and I am not one to deny you the satisfaction. Also note that if this resembles your own code in any way, just leave because we <a
title="Banjoy boy from Deliverance" href="http://courses.cit.cornell.edu/ee476/FinalProjects/s2008/hf39_jhf33/hf39_jhf33/deliverance.jpg" target="_blank">don&#8217;t take kindly</a> to you kinds of people, y&#8217;hear? And bring your cousin dad too. The beast contained gems such as</p><pre class="chili"><code class="php">$connect_db = mysql_connect("localhost","username","password");
if (!$connect_db) {
    die('Could not connect becaus of ' . mysql_error());
} else {
    mysql_select_db("some_random_db", $connect_db);
    $command="INSERT INTO table_name ('username', /* some other crap */)
    VALUES ('".$_GET['user']."' /* more crappy crap crap */)";
    if (!mysql_query($command,$connect_db)){
        die('Could not add user because ' . mysql_error());
    }
    echo "&lt;h3&gt;Successfuly added user ".$_GET['user']."&lt;/h3&gt;";
}</code></pre><p
class="clear"><hr
/><script type="text/javascript">google_ad_client="pub-8939939010469559";google_ad_slot="9013590878";google_ad_width=468;google_ad_height=60;</script><script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js"></script><br
/><hr
/></p><p>Spelling errors not omitted. No cup of heavenly blessed <a
title="Kopi Luwak coffee" href="http://en.wikipedia.org/wiki/Kopi_Luwak" target="_blank">Kopi Luwak</a> coffee, poured into a cup of golden banana leaves by naked triplets could counter the massive damage done to my corneas or, for that matter, my soul. Or what was left of it. The kicker was that the developer claimed it was OO and showed me the following &#8220;controller&#8221;. This is paraphrasing a bit, but you&#8217;ll get the general idea.</p><pre class="chili"><code class="php">class MySite
{
    var $page;
    function MySite($page) {
        $this-&gt;page = $page;
        $content = "page.php?page=".$this-&gt;page;
        /*
        This is where page.php returned the entire document
        */
        echo $content;
    }
}
$init =  new MySite($_GET['page']);</code></pre><p>Yum.</p><p>Needless to say, everything was passed around in the URL. Nothing was escaped as it &#8220;would hurt performance&#8221;. The e-mail function only checked that there was an @ in the string. You get the picture. Of course, a refactor, and I use the term loosely as it really was a steaming pile of vomit that would need a complete rewrite, was mission critical and the investors didn&#8217;t like the idea that the site would be down for maintenance for a while. As it turns out, this started as a hobby project that got the attention of somebody with money and decided that it would make a nice platform for a thriving business.</p><p>So this little article will deal with some security related matters such as input filtering. I expect there will be a second part to this as there is a plethora of things to consider, but this&#8217;ll do for now.</p><p>First off, I&#8217;d like to introduce you to a wonderful library without external dependencies called Inspekt. Mr. <a
title="Ed Finkler at Funkatron" href="http://funkatron.com/" target="_blank">Ed Finkler of Funkatron</a> built Inspekt upon the now deprecated Zend_Filter_Input, by <a
title="Chris Shiflett" href="http://shiflett.org/" target="_blank">Chris Shiflett</a>.</p><hr
/><h4>[Insert Inspector Gadget joke here]</h4><p>Inspekt acts as a firewall API between user input and the rest of the application. It takes PHP superglobal arrays, encapsulates their data in an &#8220;cage&#8221; object, and destroys the original superglobal. Data can then be retrieved from the input data object using a variety of accessor methods that apply filtering, or the data can be checked against validation methods.</p><p>Everybody wins! In order to take advantage of this black magic, all you need to do is something like this;</p><pre class="chili"><code class="php">require "Inspekt.php";
$input = Inspekt::makeSuperCage();</code></pre><p>Okay, what have we done here? When the library&#8217;s been required, we create an Inspekt_Supercage &#8211; that&#8217;s a single object that contains each input superglobal as an Inspekt_Cage. Inspekt_Cage objects encapsulate arrays of data. The original array is destroyed so you always have to access the data through the Input_Cage object&#8217;s methods. Say you need to check if $_POST['important_id'] really is an integer. Note that we are extending the introductory example above.</p><pre class="chili"><code class="php">$input-&gt;post-&gt;testInt('important_id');</code></pre><p>If it is not an integer, it will return false. More on that in a bit. What&#8217;s nice about Inspekt is that you can specify the kind of cage to create, i.e. a cage for just $_GET or $_POST, etc. You have the following tools to play with;</p><pre class="chili"><code class="php">Inspekt::makeGetCage(); // Returns an Inspekt_Cage for the $_GET array
Inspekt::makePostCage(); // Returns an Inspekt_Cage for the $_POST array
Inspekt::makeCookieCage(); // Returns an Inspekt_Cage for the $_COOKIE array
Inspekt::makeServerCage(); // Returns an Inspekt_Cage for the $_SERVER array
Inspekt::makeFilesCage() // Returns an Inspekt_Cage for the $_FILES array
Inspekt::makeEnvCage() // Returns an Inspekt_Cage for the $_ENV array</code></pre><p>Isn&#8217;t that nifty? The Inspekt_Supercage has no less than six public properties, such as get for $_GET, post for $_POST, etc. It correlates to the list just above. I promise. You access them by something like the following (again, extended from our first makeSuperCage example);</p><pre class="chili"><code class="php">$input-&gt;get-&gt;testEmail('email');</code></pre><p>If it&#8217;s valid, it will return the value. So, what else do we have in our toolbox? Well, the cage is all good and well, but we need some sort of properties to actually do the filtering or examining values. Let&#8217;s start with some tools for testing, shall we? The testers are neat methods to check the value on a given key. They return the value of the key if it&#8217;s good and false if it fails.</p><pre class="chili"><code class="php">testAlnum (mixed $key)
// Returns value if every character is alphabetic or a digit

testAlpha (mixed $key)
// Returns value if every character is alphabetic

testBetween (mixed $key, mixed $min, mixed $max, [boolean $inc = TRUE])
// Returns value if it is greater than or equal to $min and less than or equal to $max.
// If $inc is set to FALSE, then the value must be strictly greater than $min and strictly less than $max.

testCcnum (mixed $key, [mixed $type = NULL])
// Returns value if it is a valid credit card number format.
// The optional second argument allows developers to indicate the type.

testDate (mixed $key)
// Returns $value if it is a valid date. The date is required to be in ISO 8601 format.

testDigits (mixed $key)
// Returns value if every character is a digit

testEmail (mixed $key)
// Returns value if it is a valid email format

testFloat (mixed $key)
// Returns value if it is a valid float value

testGreaterThan (mixed $key, [mixed $min = NULL])
// Returns value if it is greater than $min

testHex (mixed $key)
// Returns value if it is a valid hexadecimal format

testHostname (mixed $key, [integer $allow = ISPK_HOST_ALLOW_ALL])
// Returns value if it is a valid hostname

testInt (mixed $key)
// Returns value if it is a valid integer value

testIp (mixed $key)
// Returns value if it is a valid IP format

testLessThan (mixed $key, [mixed $max = NULL])
// Returns value if it is less than $max

testOneOf (mixed $key, [ $allowed = NULL])
// Returns value if it is one of $allowed

testPhone (mixed $key, [ $country = 'US'])
// Returns value if it is a valid phone number format. The optional second argument indicates the country.

testRegex (mixed $key, [mixed $pattern = NULL])
// Returns value if it matches $pattern. Uses preg_match() for the matching.

testUri (string $key)
// Returns value if it is a valid URI as defined in http://www.ietf.org/rfc/rfc2396.txt

testZip (mixed $key)
// Returns value if it is a valid US ZIP</code></pre><p>Sexy, isn&#8217;t it? And in order to access your values after they&#8217;ve been filtered, you may use the following methods;</p><pre class="chili"><code class="php">getAlnum (mixed $key)
// Returns only the alphabetic characters and digits in value.

getAlpha (mixed $key)
// Returns only the alphabetic characters in value.

getDigits (mixed $key)
// Returns only the digits in value. This differs from getInt().

getDir (mixed $key)
// Returns dirname(value).

getInt (mixed $key)
// Returns (int) value.

getPath (mixed $key)
// Returns realpath(value).

getPurifiedHTML (string $key)
// This returns the value of the given key passed through the HTMLPurifer object,
// if it is instantiated with Inspekt_Cage::loadHTMLPurifer

getROT13 (string $key)
// Returns ROT13-encoded version

getValue (string $key)
// Retrieves a value from the cage

getRaw (string $key)
// Returns value, unfiltered.

noPath (mixed $key)
// Returns basename(value).

noTags (mixed $key)
// Returns value with all tags removed.

noTagsOrSpecial (mixed $key)
// Returns value with tags stripped and the chars '"&amp;&lt;&gt; and all ascii chars
// under 32 encoded as html entities</code></pre><p>And of course, there is</p><pre class="chili"><code class="php">keyExists (mixed $key)
// Checks if a key exists</code></pre><p>It wouldn&#8217;t be complete if there where no methods for escaping strings prior to database calls. Well, aren&#8217;t we in luck?</p><pre class="chili"><code class="php">escMySQL (mixed $value, [resource $conn = null])
// Escapes the value given with mysql_real_escape_string

escPgSQL (mixed $value, [resource $conn = null])
// Escapes the value given with pg_escape_string

escPgSQLBytea (mixed $value, [resource $conn = null])
// Escapes the value given with pg_escape_bytea</code></pre><p>I should point out that you actually can wrap any array in Inspekt_Cage and not just superglobals, making the library a handy dandy tool for all your filtering and testing needs.</p><pre class="chili"><code class="php">$dirty = array( /* imagine some random, unfiltered values here */ );
$johnny_cage = Inspekt_Cage::Factory($dirty);</code></pre><p>to test some value in the array, just use</p><pre class="chili"><code class="php">$johnny_cage-&gt;testInt('key');</code></pre><p>To get even more nitty gritty, you can use static methods for those one off moments.</p><pre class="chili"><code class="php">Inspekt::isAlnum (mixed $value)
Inspekt::isAlpha (mixed $value)
Inspekt::isBetween (mixed $value, mixed $min, mixed $max, [ $inc = TRUE])
Inspekt::isCcnum (mixed $value, [mixed $type = NULL])
Inspekt::isDate (mixed $value)
Inspekt::isDigits (mixed $value)
Inspekt::isEmail (string $value)
Inspekt::isFloat (string $value)
Inspekt::isGreaterThan (mixed $value, mixed $min)
Inspekt::isHex (mixed $value)
Inspekt::isHostname (mixed $value, [integer $allow = ISPK_HOST_ALLOW_ALL])
Inspekt::isInt (mixed $value)
Inspekt::isIp (mixed $value)
Inspekt::isLessThan (mixed $value, mixed $max)
Inspekt::isOneOf (mixed $value, [ $allowed = NULL])
Inspekt::isPhone (mixed $value, [ $country = 'US'])
Inspekt::isRegex (mixed $value, [mixed $pattern = NULL])
Inspekt::isUri (string $value, [integer $mode = ISPK_URI_ALLOW_COMMON])
Inspekt::isZip (mixed $value)
Inspekt::getAlnum (mixed $value)
Inspekt::getAlpha (mixed $value)
Inspekt::getDigits (mixed $value)
Inspekt::getDir (mixed $value)
Inspekt::getInt (mixed $value)
Inspekt::getPath (mixed $value)
Inspekt::noPath (mixed $value)
Inspekt::noTags (mixed $value)</code></pre><hr
/><h4>Built in goodies</h4><p>If you feel that using a library isn&#8217;t cool enough, or if I haven&#8217;t made the benefits clear, there are some things you ca do for filtering your values. I&#8217;m talking about the often overlooked PHP Filter functions. These are available if you are using at least PHP 5.2. Before continuing, I want to point you to the types of filters available. They&#8217;re <a
title="Validation filters" href="http://www.php.net/manual/en/filter.filters.validate.php" target="_blank">validation filters</a>, <a
title="Sanitizing filters" href="http://www.php.net/manual/en/filter.filters.sanitize.php" target="_blank">sanitizing filters</a>, <a
title="Miscellaneous filters" href="http://www.php.net/manual/en/filter.filters.misc.php" target="_blank">miscellaneous filters</a> and, well, the<a
title="Predefined constans" href="http://www.php.net/manual/en/filter.constants.php" target="_blank"> predefined constants</a>. First off is <strong>filter_var</strong>.</p><p
class="clear"><hr
/><script type="text/javascript">google_ad_client="pub-8939939010469559";google_ad_slot="9013590878";google_ad_width=468;google_ad_height=60;</script><script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js"></script><br
/><hr
/></p><pre class="chili"><code class="php">filter_var ( mixed $variable [, int $filter = FILTER_DEFAULT [, mixed $options ]] )</code></pre><p>filter_var does what you think it does &#8211; it filters a variable with the specified filter. Go tautology! the $filter is specified in the list in the previous paragraph. The $options are an array of options or bitwise disjunction of flags. The function returns the filtered data or false if it fails. A quick example of e-mail validation could be</p><pre class="chili"><code class="php">$is_it_okay = filter_var("some_dude\X00= _@ne@example..com", FILTER_VALIDATE_EMAIL);</code></pre><p>Then there&#8217;s <strong>filter_var_array</strong>, which allows you to check an array of values.</p><pre class="chili"><code class="php">filter_var_array ( array $data [, mixed $definition ] )</code></pre><p>An example could be (borrowed from <a
title="User example from php.net" href=" http://www.php.net/manual/en/function.filter-var-array.php#91341" target="_blank">this place</a>)</p><pre class="chili"><code class="php">$data = array('&lt;strong&gt;bold&lt;/strong&gt;', '&lt;script type="text/javascript"&gt;// &lt;![CDATA[
  javascript
// ]]&gt;&lt;/script&gt;', 'P*}i@893746%%%p*.i.*}}|.dw');
$myinputs = filter_var_array($data,FILTER_SANITIZE_STRING);
var_dump($myinputs);

//OUTPUT:
//formarray(3) { [0]=&gt; string(4) "bold" [1]=&gt; string(10) "javascript"
[2]=&gt; string(26) "P*}i@893746%%%p*.i.*}}|.dw" }</code></pre><p>Then we have <strong>filter_input</strong> which gets an external variable by name and optionally filters it.</p><pre class="chili"><code class="php">filter_input ( int $type , string $variable_name [, int $filter = FILTER_DEFAULT [, mixed $options ]] )</code></pre><p>$type may be either INPUT_GET, INPUT_POST, INPUT_COOKIE, INPUT_SERVER or INPUT_ENV ( INPUT_SESSION and INPUT_REQUEST are not implemented yet). Returns the requested variable on success, false if not or null if the $variable_name is not set (unless you use the flag FILTER_NULL_ON_FAILURE &#8211; in that case it returns false if the variable is not set and null if it fails). Say you want to sanitize $_GET['search'] for special characters. Try something like</p><pre class="chili"><code class="php">$search = filter_input(INPUT_GET, 'search', FILTER_SANITIZE_SPECIAL_CHARS);</code></pre><p>There is also <strong>filter_input_array</strong>, which does what you think it does &#8211; It filters an array instead of just a single variable.</p><pre class="chili"><code class="php">$example_filters = array (
    "url" =&gt; FILTER_VALIDATE_URL,
    "ip" =&gt; FILTER_VALIDATE_IP,
    "temeraturep" =&gt; array(
        "filter"=&gt;FILTER_VALIDATE_INT,
        "options"=&gt;array(
            "min_range"=&gt;1,
            "max_range"=&gt;666
         )
    )
);

$sweetness = filter_input_array(INPUT_POST, $example_filters);</code></pre><p>A quickie is <strong>filter_has_var</strong>, which checks if a variable of a specified type exists or not.</p><pre class="chili"><code class="php">filter_has_var ( int $type , string $variable_name )</code></pre><p>$type can be either INPUT_GET, INPUT_POST, INPUT_COOKIE, INPUT_SERVER or INPUT_ENV.</p><hr
/><h4>CRSFXSSFRSFCSFCSS X XSS SS XX C FFCCCE</h4><p>A note on CRSF and XSS as well, while we&#8217;re at it. Inspekt allows you to run your data through the getPurifiedHTML method which basically runs it through <a
title="htmlpurifier" href="http://htmlpurifier.org/" target="_blank">HTMLPurifier</a> and should provide a reasonable amount of XSS protection. If you have any tips on other XSS prevention projects or functions, please let me know. I stumbled upon a related project, <a
title="CSRF magic. In a good way" href="http://csrf.htmlpurifier.org/" target="_blank">csrf-magic</a>. It uses PHP&#8217;s output buffering to &#8220;dynamically rewrite forms and scripts&#8221; and also check tokens in POST requests. You call it with</p><pre class="chili"><code class="php">include_once 'csrf-magic.php';</code></pre><p>It will even dynamically rewrite AJAX requests that uses XMLHttpRequest, if you want it to. Pretty sweet. It&#8217;s supposed to play along quite nicely with jQuery, MooTools, Prototype, Ext, Dojo, Yahoo UI Library, script.aculo.us and Prototype. There is also an option to set a configuration in the PHP script. Check out the following (borrowed form the bundled readme);</p><pre class="chili"><code class="php">// This gets called if a csrf check fails
function my_csrf_callback() {
    echo "You're doing bad things young man!";
}

function csrf_startup() {

// While csrf-magic has a handy little heuristic for determining whether
// or not the content in the buffer is HTML or not, you should really
// give it a nudge and turn rewriting *off* when the content is
// not HTML. Implementation details will vary.
if (isset($_POST['ajax'])) csrf_conf('rewrite', false);

// This is a secret value that must be set in order to enable username
// and IP based checks. Don't show this to anyone. A secret id will
// automatically be generated for you if the directory csrf-magic.php
// is placed in is writable.
csrf_conf('secret', 'ABCDEFG123456');

// This enables JavaScript rewriting and will ensure your AJAX calls
// don't stop working.
csrf_conf('rewrite-js', '/csrf-magic.js');

// This makes csrf-magic call my_csrf_callback() before exiting when
// there is a bad csrf token. This lets me customize the error page.
csrf_conf('callback', 'my_csrf_callback');

// While this is enabled by default to boost backwards compatibility,
// for security purposes it should ideally be off. Some users can be
// NATted or have dialup addresses which rotate frequently. Cookies
// are much more reliable.
csrf_conf('allow-ip', false);

}

// Finally, include the library
include_once '/path/to/csrf-magic.php';</code></pre><p
class="clear"><hr
/><script type="text/javascript">google_ad_client="pub-8939939010469559";google_ad_slot="9013590878";google_ad_width=468;google_ad_height=60;</script><script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js"></script><br
/><hr
/></p><p>If you would like to roll your own CSRF solution, a simple one can be scripted on a coffee break. When dealing with forms, add a random token to your $_SESSION after calling session_start() such as;</p><pre class="chili"><code class="php">$_SESSION['my_token'] = md5(uniqid(rand(), TRUE));</code></pre><p>And then in the form itself, add a hidden input like so;</p><pre class="chili"><code class="php">&lt;input name="my_token" type="hidden" value="&lt; ?php echo $my_token; ? &gt;" /&gt;</code></pre><p>After submit, you can check if the token is valid with something simple as;</p><pre class="chili"><code class="php">if ($_POST['my_token'] == $_SESSION['my_token']){
    /* Fun stuff */
}</code></pre><p>You may ask, why don&#8217;t we limit the amount of time a token is valid? Yes, well, let&#8217;s do that then.</p><pre class="chili"><code class="php">// Add token and time
$_SESSION['my_token'] = md5(uniqid(rand(), TRUE));
$_SESSION['my_token_time'] = time();

// Assume we now submitted the form, yadda yadda

$are_we_screwed = time() - $_SESSION['my_token_time'];

if ($_POST['my_token'] == $_SESSION['my_token']){
    /* It's all good! Or is it? */
    if ( $are_we_screwed &lt; 60 ) {
        /* Less than a minute to play with */
    } else {
        /* Fail */
    }
}</code></pre><table><tbody><tr><td
valign="top"><img
class="alignleft size-medium wp-image-191" title="Will code HTML for food" src="http://pronewb.com/wp-content/uploads/Will_code_HTML_for_food-247x300.jpg" alt="Will code HTML for food" width="247" height="300" /></td><td
valign="top">There you have it. Some quick tips and/or things to think about. I&#8217;m not sure how I can end this little tidbit, so I&#8217;ll just paste a picture to keep you busy. Mm&#8217;kay?</p><p><strong>Update:</strong> <a
title="Reddit" href="http://www.reddit.com/" target="_blank">Reddit</a> user <a
title="Reddit user pashj" href="http://www.reddit.com/user/pashj" target="_blank">pashj</a> gave me a tip on adding a link to XSS examples so you can test you own project for, well, attack vectors. A classic cheat sheet full of examples is <a
title="XSS cheat sheet at ha.ckers.org" href="http://ha.ckers.org/xss.html" target="_blank">this one</a> over at ha.ckers.org. Try it out! Let me know how it goes.</td></tr></tbody></table><p>Related posts:<ol><li><a
href='http://pronewb.com/a-popurls-clone-with-php-jquery-awesomeness' rel='bookmark' title='A Popurls Clone with PHP, jQuery, Awesomeness'>A Popurls Clone with PHP, jQuery, Awesomeness</a></li></ol></p>]]></content:encoded> <wfw:commentRss>http://pronewb.com/hands-on-tips-for-php-security/feed</wfw:commentRss> <slash:comments>4</slash:comments> </item> <item><title>Random thoughts on JavaScript. Part one of who knows. The basics.</title><link>http://pronewb.com/random-thoughts-on-javascript-part-one-of-who-knows-the-basics</link> <comments>http://pronewb.com/random-thoughts-on-javascript-part-one-of-who-knows-the-basics#comments</comments> <pubDate>Sun, 07 Mar 2010 15:42:48 +0000</pubDate> <dc:creator>william</dc:creator> <category><![CDATA[Code]]></category> <category><![CDATA[commenting]]></category> <category><![CDATA[douglas crockford]]></category> <category><![CDATA[friends with privileges]]></category> <category><![CDATA[globals are evil]]></category> <category><![CDATA[javascript]]></category> <category><![CDATA[namespace]]></category> <category><![CDATA[naming]]></category> <category><![CDATA[notation]]></category> <category><![CDATA[object literals]]></category> <category><![CDATA[oop]]></category> <category><![CDATA[reserved words]]></category> <category><![CDATA[sexy]]></category> <category><![CDATA[typecasting]]></category> <category><![CDATA[variables]]></category> <category><![CDATA[weakly typed]]></category><guid
isPermaLink="false">http://pronewb.com/?p=102</guid> <description><![CDATA[This is going to be some sort of article on JavaScript. I'm still not sure exactly what will come of this, which means that now is your time to turn back. I won't give you any more chances! Here's something to keep you entertained while you think it through. And you may have to increase the volume while you watch it as it is just that mind numbingly awesome. Still here? Cool. I wouldn't be, but you know, to each his own.No related posts.]]></description> <content:encoded><![CDATA[<p><a
href="http://pronewb.com/wp-content/uploads/javascript_thenet.jpg"><img
class="alignleft size-medium wp-image-139" title="Screenshot fomr the movie The Net" src="http://pronewb.com/wp-content/uploads/javascript_thenet-300x163.jpg" alt="Screenshot fomr the movie The Net" width="300" height="163" /></a>This is going to be some sort of article on JavaScript. I&#8217;m still not sure exactly what will come of this, which means that now is your time to turn back. I won&#8217;t give you any more chances! Here&#8217;s <a
title="Trololololololololololo" href="http://trololololololololololo.com/" target="_blank">something to keep you entertained</a> while you think it through. And you may have to increase the volume while you watch it as it is just that mind numbingly awesome.</p><p>Still here? Cool. I wouldn&#8217;t be, but you know, to each his own.</p><p>People much smarter and more patient than me has written <a
title="JavaScript at Wikipedia" href="http://en.wikipedia.org/wiki/JavaScript" target="_blank">a lot</a> about JavaScript. I guess that link should suffice as an article, but that would be a bit of a cop out on my part so I think I&#8217;ll give writing some random thoughts a try. It may just be a couple of pointers or tips. Or not. Hold my hand as we take the leap into the unknown.</p><p>First off, you know that you can <a
title="Try your JavaScript online" href="http://writecodeonline.com/javascript/" target="_blank">try out your JavaScript online</a>, right? Good. Now, let&#8217;s start with some JavaScript basics. And I mean really basic stuff.</p><p
class="clear"><hr
/><script type="text/javascript">google_ad_client="pub-8939939010469559";google_ad_slot="9013590878";google_ad_width=468;google_ad_height=60;</script><script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js"></script><br
/><hr
/></p><h4>Comment your code, but don&#8217;t go crazy with it.</h4><pre class="chili"><code class="javascript">var i = 0; // Declare i and set it to zero</code></pre><p>A bag full of hurt. Use the good ol&#8217; double slash for single line comments as per above. Use block comments for documentation or commenting out pieces of code.</p><pre class="chili"><code class="javascript">/*
This is commented out
Isn't this pretty?
*/</code></pre><h4>Notation, notation, notation</h4><p>In JavaScript, you can access properties of objects in two ways; <em>square bracket</em> notation and <em>dot notation</em>.</p><pre class="chili"><code class="javascript">mySweetObject["property"] // Square bracket notation
mySweetObject.property // Dot notation</code></pre><p>It may be tempting to use the dot notation as it&#8217;s a bit easier to type &#8211; because all coders are lazy, right? The downside of dot notation is that the property name is hard coded and thus can&#8217;t be altered at run time. Bracket notation, however, means that the property name is a string that gets evaluated. This means that you can use a variable, a hard coded string or a function call.  Also, should the property be generated at run time, a bracket notation is required. Let&#8217;s start with a silly little example and say that you have a number of properties named &#8220;myValue1&#8243;, &#8220;myValue2&#8243;, &#8220;myValue3&#8243; and so on. For some reason you need to loop through these properties using a for loop. If you try to access these properties like this</p><pre class="chili"><code class="javascript">mySweetObject.myValue+i</code></pre><p>you&#8217;ll fail. What you need is</p><pre class="chili"><code class="javascript">mySweetObject["myValue"+i]</code></pre><p>Boom, you&#8217;re in. So for the sake of consistency, use square bracket notation. Consistency is good. Repeat as a mantra.</p><h4>Typecasting</h4><p>The wonder that is JavaScript is weakly typed which means that you do not need to cast, or define, the type of data you are using. JavaScript, or rather the runtime system, performs automatic adjustments so you do not need to worry about it. This is either a good thing or a bad thing, depending on your background. Good for new programmers, bad for people used to C or Java (any language with strong typing). There are however times when it can be useful to typecast, such as when you are working with both strings and numbers. Since the plus sign is used both for string concatenation as well as regular addition, you might get some unexpected results. You can cast to three different types &#8211; Boolean, Number and String.</p><pre class="chili"><code class="javascript">myBoolean1 = Boolean(666); // true
myBoolean2 = !! 666; // true
myString1 = String(666); // "666"
myString2 = "" + 666; // "666"
myNumber1 = Number("666"); // 666
myNumber2 = 1 * 666; // 666
</code></pre><p>You can try it out and make sure that it really gets typecasted by alerting with the help of <em>typeof</em>.</p><pre class="chili"><code class="javascript">alert( typeof(myBoolean2) );</code></pre><p>If we&#8217;ve behaved, that should alert &#8220;boolean&#8221;. The <em>Boolean</em> type returns true when the value passed to it is a string with at least one character, a number other than 0 or an object. E contrario it returns false when passed an empty string, the number 0, undefined or null. <em>Number</em> converts the entire value to a number, as compared to <a
title="parseInt at MSDN" href="http://msdn.microsoft.com/en-us/library/1kc6b02f(VS.80).aspx" target="_blank">parseInt()</a> and <a
title="parseFloat at MSDN" href="http://msdn.microsoft.com/en-us/library/t9szttbx(VS.80).aspx" target="_blank">parseFloat()</a>. The latter methods will only convert up to the first invalid character they encounter in a string. &#8220;6.6.6&#8243; with parseInt() becomes &#8220;6&#8243; and becomes &#8220;6.6&#8243; with parseFloat(). Make a good habit of defining the radix with parseInt(). The second argument that you can pass to it and allows you to  convert strings in binary, octal, hexadecimal or any other base into an <a
title="Integer at wikipedia" href="http://en.wikipedia.org/wiki/Integer" target="_blank">integer</a>. This may also be a good time to read up on <a
title="Floating points at wikipedia" href="http://en.wikipedia.org/wiki/Floating_point" target="_blank">floating point</a> values. With Number() you get a &#8220;Not a Number&#8221; error, or the dreaded NaN. <em>String</em> should be a no-brainer. It&#8217;ll convert the value you want to a string, simple as that. What it does is call the <a
title="toStrign at MSDN" href="http://msdn.microsoft.com/en-us/library/tkyfze3b(VS.80).aspx" target="_blank">toString()</a> method. Note that String() will not result in an error for a null or undefined value &#8211; instead you get the string &#8220;null&#8221;.</p><h4>Reserved words</h4><p>This is something that can cause some confusion. I don&#8217;t know why, but I&#8217;ve seen my fair share of code where a developer uses a reserved word as a property name. It makes me kind of sad. The list of reserved words is a rather long one and pasting it here would just take up a lot of space, so instead I&#8217;ll just link to a page that has <a
title="Reserved words at mozilla developer" href="https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Reserved_Words" target="_blank">already done the dirty work</a>. Please, please, please note the words that are reserved for future use, in the brand spanking new JavaScript 2.0 *cough* <a
title="ECMA Script 4.0" href="http://en.wikipedia.org/wiki/ECMAScript" target="_blank">ECMA Script 4.0</a> *cough*. This will also leads us to&#8230;</p><h4>Naming</h4><p>See, there are limitations on the way can name things. You may use upper and lower case letters (<em>a-z</em> and <em>A-Z</em>), digits (<em>0-9</em>), and the underscore character (_). Although you can use other characters, it may break in certain cases. Better safe than sorry, right? Avoid starting names with the underscore character as it&#8217;s not rarely used to indicate privacy (more on that later on). Note that it doesn&#8217;t in itself <em>create</em> privacy.</p><p
class="clear"><hr
/><script type="text/javascript">google_ad_client="pub-8939939010469559";google_ad_slot="9013590878";google_ad_width=468;google_ad_height=60;</script><script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js"></script><br
/><hr
/></p><h4>Declare your variables</h4><p>We know that JavaScript doesn&#8217;t require them to be declared, but, really, is it that hard? No. There is no excuse not to. You declare a variable with the use of the var keyword. Side note: If you come from C, you may need to know that JavaScript does not have block scope so be a good guy, and declare all your variables at the very top of your functions.</p><pre class="chili"><code class="javascript">var myVar;
var myOtherVar = myRandomValue;</code></pre><p>It makes it so much easier to identify undeclared variables that may, brace yourself, be implied globals. Implied globals can cause mayhem (mayhem as in a-minor-inconvenience-I-need-to-shape-up-my-code, not as in genocide). You see, the global object is the one <a
href="http://en.wikipedia.org/wiki/Namespace">namespace</a> to rule them all. It holds, as you may have gathered by now, global variables and top level functions. It doesn&#8217;t take a mastermind to realize that collisions may occur and those collisions are part of the mayhem mentioned earlier. It will <a
href="http://www.sadtrombone.com/">break your code</a>. Basically, all JavaScript files you use run in the same scope which means that if you use globals, implied or not, and a script that loads after yours use the same variable or function names, the latter will replace your variables and functions. And that&#8217;s not good, is it? On a related note, you can declare multiple variables using a single var keyword and a comma separated list or variables.</p><pre class="chili"><code class="javascript">var myVar1 = "Random",
    myVar2 = "Ramblings",
    myVar3 = "Fun stuff", myVar4, myVar5, myVar6;</code></pre><h4>Going global</h4><p>Let&#8217;s back up for a moment and remember that in JavaScript, everything is an object. Or rather, a property of an object. In turn, an object is basically a collection of name-value pairs. The names are strings and values can be objects, numbers, booleans and strings. And a quick note on terminology &#8211; if the value is a function, strictly speaking, it&#8217;s called a method. But what about those functions, you ask? I&#8217;ve seen those around the code, you say. Well, those are actually properties to the window object.</p><pre class="chili"><code class="javascript">function myFunction(myString) {
    alert(myString);
}
</code></pre><p>This little nifty function that alerts the variable string, actually means that we assigned a Function instance to the myFunction property. Functions do not have names. Actually, myFunction is a property of the window object. Does that make sense? It may be a bit more clear if we type it like so:</p><pre class="chili"><code class="javascript">window.myFunction = new Function('myString', 'alert(myString)');
</code></pre><p>Feel a bit better now? Standalone functions are bound to the window object. When you would like to execute myFunction, you would normally type</p><pre class="chili"><code class="javascript">myFunction('alert this string');</code></pre><p>Nothing fancy. This can also be written as</p><pre class="chili"><code class="javascript">window.myFunction('alert this string');</code></pre><p>Remember, we are now dealing with global objects, which is in general a no-no, but nice for a simple explanation. Do you remember how we declared variables? When we type something like</p><pre class="chili"><code class="javascript">var myVar = 'My string'</code></pre><p>we are using a shorthand syntax (object literal &#8211; more on that a few lines down) for</p><pre class="chili"><code class="javascript">var myVar = String('My string');</code></pre><p>And these are also in the window object, i.e.</p><pre class="chili"><code class="javascript">window.myVar = 'My string';
window.myOtherVar = String('My string');</code></pre><h4>Literal this, literal that</h4><p>Thankfully, there are ways around the problem of collisions. One way is to employ <a
title="Object literals at wikipedia" href="http://en.wikipedia.org/wiki/Literal_(computer_science)" target="_blank">object literals</a> (see, I told you we&#8217;d get there) which basically means that you can define your own namespace (read: object or, going with OOP terms, a <a
title="Constructor (OOP) at wikipedia" href="http://en.wikipedia.org/wiki/Constructor_(computer_science)" target="_blank">Constructor</a>. Please note that it is Good Practice™ to capitalize the Constructor. I won&#8217;t in this case, because that&#8217;s just how i roll) and play with it. Or, as specified by the good people at <a
title="Object literals at mozilla dev center" href="https://developer.mozilla.org/en/Core_JavaScript_1.5_Guide/Literals#Object_Literals" target="_blank">Mozilla</a>:</p><blockquote><p>An object literal is a list of zero or more pairs of property names and associated values of an object, enclosed in curly braces ({})</p></blockquote><p>Take this super simple example;</p><pre class="chili"><code class="javascript">var myNameSpace = {
    myFunction:function(data) {
        alert(data);
    }
}</code></pre><p>If you now try to call</p><pre class="chili"><code class="javascript">myFunction('Alert this, you douche');</code></pre><p>it will fail, as there is no property called myFunction in the window object. Instead, you need to call it using</p><pre class="chili"><code class="javascript">myNameSpace.myFunction('Alert this, you douche');</code></pre><p>That works just fine and if a script later on also has a myFunction() (preferrably in its own namespace), there will be no collisions. <a
title="Who's awesome? You're awesome" href="http://www.mediabistro.com/agencyspy/original/whos-awesome.jpg" target="_blank">Goodie!</a> The drawback of this technique is that you always have to go through the name of your object, or namespace. The solution would be to wrap your object in an anonymous function (or lambda). This will protect the scope. Our little snippet above would be typed like this:</p><pre class="chili"><code class="javascript">var myNameSpace = function() {
    function myFunction(data) {
        alert(data);
    }
}();</code></pre><p>Note the addition of the parenthesis on the last line and the ending semicolon. Also, you don&#8217;t need to stray away from the use of function myFunction() if that feels more comfortable. The parenthesis at the end makes the anonymous function execute right away. This is called the Module Pattern. This has the downside &#8211; or upside depending on your goals &#8211; of making myFunction() only available from within myNamespace. Any outside calls will fail (<a
href="http://peter.michaux.ca/articles/module-pattern-provides-no-privacy-at-least-not-in-javascript-tm">except maybe&#8230;</a>). To fix this, you need to make a publicly available return statement.</p><pre class="chili"><code class="javascript">var myNameSpace = function() {
    return {
        myFunction:function(data) {
            alert(data);
        }
    }
}();</code></pre><p>Isn&#8217;t this <a
title="The awesome Susan Boyle laughing" href="http://mrknowsitall.files.wordpress.com/2009/04/susan-boyle-grinning.jpg" target="_blank">fun</a>? myNameSpace.myFunction(&#8216;hey&#8217;); gets you going aaaand you&#8217;re pretty much back where we left off. Let&#8217;s alternate the example;</p><pre class="chili"><code class="javascript">var myNameSpace = function() {
    function myFunction(data) {
        alert(data);
    }
    return {
        pointer:myFunction
    }
}();</code></pre><p>See what we did there? We switched back to the other syntax for the private method and returned a pointer to that method instead. In this case, we call our function with</p><pre class="chili"><code class="javascript">myNameSpace.pointer('hey');</code></pre><p>Pretty sweet, right? The pointer can be as short as you want it and the private function can have any name you want, if that&#8217;s your preference. It makes me cringe a bit to mention public and private methods when dealing with JavaScript, but <a
title="Robot devil" href="http://www.horrornews.net/lists/_horrorlists_top10_film_depictions_of_satan_in_films/images/ephellisotherrobots-tm.jpg" target="_blank">what the hell</a>. Private methods or members are those that are created within the constructor. In the example above, myFunction is only accessible within the constructor myNameSpace and is returned only with the pointer or alias.</p><p>The reason that this works is due to the fact that JavaScript has <a
title="Closures at wikipedia" href="http://en.wikipedia.org/wiki/Closure_(computer_science)" target="_blank">closures</a>. In essence, this means that a function defined within a function always has access to the vars and what have you of its outer function. Think about that for a while. That&#8217;s power, right there. Note that private and privileged methods can only be made when the object in questions is constructed. Public methods on the other hand, can be added ad hoc.</p><p
class="clear"><hr
/><script type="text/javascript">google_ad_client="pub-8939939010469559";google_ad_slot="9013590878";google_ad_width=468;google_ad_height=60;</script><script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js"></script><br
/><hr
/></p><h4>Friends with privileges</h4><p>Although it might not be obvious, you also have the ability to create privileged methods. Privileged methods are accessible from outside the scope and can access private methods and variables. While you can delete or replace a privileged method, you can&#8217;t alter it. This is where you use the keyword <em>this</em>. This points to the method calling object.</p><pre class="chili"><code class="javascript">function Constructor(data) {
    this.name = data;
}</code></pre><p>This means that if we now construct a new object like so</p><pre class="chili"><code class="javascript">var myConstructor = new Constructor('Gandhi');</code></pre><p>myConstructor.name is &#8220;Gandhi&#8221;. Let&#8217;s expand.</p><pre class="chili"><code class="javascript">function Constructor(data) {
    this.name = data;
    this.fetch = function() {
        return this.name;
    }
}</code></pre><p>Okay, what can we do with this little gem of a function? Test it out with something basic like</p><pre class="chili"><code class="javascript">var myConstructor = new Constructor('Gandhi');
alert( myConstructor.fetch() );</code></pre><p>Did it work? Nice. It didn&#8217;t? Fail. Try again. Also try these quick examples:</p><pre class="chili"><code class="javascript">var myConstructor1 = new Constructor('Gandhi');
var myConstructor2 = new Constructor('Shiva');
alert( "myConstructor1's name is "+myConstructor1.fetch() );
alert( "myConstructor2's name is "+myConstructor2.fetch() );</code></pre><p>Did it work? Sweet. That&#8217;s about all I have to write for now. Fret not, there will be many more random thoughts coming quite soon, and not just on JavaScript. I&#8217;d like to leave you with an awesome talk from the JavaScript guru <a
title="Douglas Crockford" href="http://www.crockford.com/" target="_blank">Douglas Crockford</a>. Embedded below is a 45 minutes talk on <em>Quality</em>. It&#8217;s a good watch and, trust me, you&#8217;ll learn something new. It&#8217;ll make your code <a
title="Derek Zoolander. Looks good." href="http://image.guardian.co.uk/sys-images/Arts/Arts_/Pictures/2007/05/02/zoolander460.jpg" target="_blank">look better</a>.</p><div><object
classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" width="512" height="322" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0"><param
name="allowFullScreen" value="true" /><param
name="AllowScriptAccess" value="always" /><param
name="bgcolor" value="#000000" /><param
name="flashVars" value="id=2724346&amp;vid=529579&amp;lang=en-us&amp;intl=us&amp;thumbUrl=http%3A//l.yimg.com/a/i/us/sch/cn/v/v1/w529/529579_100_70.jpeg%3Fx%3D158%26y%3D111%26sig%3DkA.KarKM2jJHPLNqRFLf7w--&amp;embed=1" /><param
name="src" value="http://d.yimg.com/static.video.yahoo.com/yep/YV_YEP.swf?ver=2.2.46" /><param
name="flashvars" value="id=2724346&amp;vid=529579&amp;lang=en-us&amp;intl=us&amp;thumbUrl=http%3A//l.yimg.com/a/i/us/sch/cn/v/v1/w529/529579_100_70.jpeg%3Fx%3D158%26y%3D111%26sig%3DkA.KarKM2jJHPLNqRFLf7w--&amp;embed=1" /><param
name="allowfullscreen" value="true" /><embed
type="application/x-shockwave-flash" width="512" height="322" src="http://d.yimg.com/static.video.yahoo.com/yep/YV_YEP.swf?ver=2.2.46" flashvars="id=2724346&amp;vid=529579&amp;lang=en-us&amp;intl=us&amp;thumbUrl=http%3A//l.yimg.com/a/i/us/sch/cn/v/v1/w529/529579_100_70.jpeg%3Fx%3D158%26y%3D111%26sig%3DkA.KarKM2jJHPLNqRFLf7w--&amp;embed=1" bgcolor="#000000" allowscriptaccess="always" allowfullscreen="true"></embed></object><br
/> <a
href="http://video.yahoo.com/watch/529579/2724346">Douglas Crockford: &#8220;Quality&#8221;</a> @ <a
href="http://video.yahoo.com">Yahoo! Video</a></div><p>No related posts.</p>]]></content:encoded> <wfw:commentRss>http://pronewb.com/random-thoughts-on-javascript-part-one-of-who-knows-the-basics/feed</wfw:commentRss> <slash:comments>0</slash:comments> </item> <item><title>CSS3 pseudo-class selector emulation for IE 5.5 &#8211; 8 and html5 with video</title><link>http://pronewb.com/css3-pseudo-class-selector-emulation-for-ie-5-5-8-and-html5-with-video</link> <comments>http://pronewb.com/css3-pseudo-class-selector-emulation-for-ie-5-5-8-and-html5-with-video#comments</comments> <pubDate>Mon, 01 Mar 2010 22:01:28 +0000</pubDate> <dc:creator>william</dc:creator> <category><![CDATA[Code]]></category> <category><![CDATA[52 framework]]></category> <category><![CDATA[css]]></category> <category><![CDATA[css reset]]></category> <category><![CDATA[css3]]></category> <category><![CDATA[h.264]]></category> <category><![CDATA[html5]]></category> <category><![CDATA[ie]]></category> <category><![CDATA[ie5.5-8]]></category> <category><![CDATA[jar jar]]></category> <category><![CDATA[jquery]]></category> <category><![CDATA[pseudo-class selectors]]></category> <category><![CDATA[sexy]]></category> <category><![CDATA[star wars]]></category> <category><![CDATA[theora]]></category> <category><![CDATA[video]]></category> <category><![CDATA[wtf]]></category><guid
isPermaLink="false">http://pronewb.com/?p=45</guid> <description><![CDATA[While  gathering information as a part of my ongoing plan to be omniscient, if came across something that makes IE behave like a capable browser. Although to be fair, IE 8 is actually not that bad a browser - in the way that Star Wars Episodes 1-3 are not that bad. So, yeah, you do the math. I mean, Jar Jar. Pisses me off just thinking about it.Related posts:<ol><li><a
href='http://pronewb.com/flash-king-of-the-impossible' rel='bookmark' title='Flash, King of the Impossible'>Flash, King of the Impossible</a></li><li><a
href='http://pronewb.com/css-typography-is-fun-really' rel='bookmark' title='CSS typography is fun. Really. If you&#8217;re in to S&amp;M'>CSS typography is fun. Really. If you&#8217;re in to S&#038;M</a></li><li><a
href='http://pronewb.com/a-popurls-clone-with-php-jquery-awesomeness' rel='bookmark' title='A Popurls Clone with PHP, jQuery, Awesomeness'>A Popurls Clone with PHP, jQuery, Awesomeness</a></li></ol>]]></description> <content:encoded><![CDATA[<p><a
href="http://pronewb.com/wp-content/uploads/css3_pseudoselector_html5.jpg"><img
class="alignleft size-medium wp-image-47" title="CSS3 pseudo-selectors for IE and html5 video" src="http://pronewb.com/wp-content/uploads/css3_pseudoselector_html5-300x163.jpg" alt="CSS3 pseudo-selectors for IE and html5 video" width="300" height="163" /></a>While  gathering information as a part of my ongoing plan to be omniscient, if came across something that makes IE behave like a capable browser. Although to be fair, IE 8 is actually not that bad a browser &#8211; in the way that Star Wars Episodes 1-3 are not that bad. So, yeah, you do the math. I mean, Jar Jar. Pisses me off just thinking about it.</p><p><a
title="Keith Clark" href="http://www.keithclark.co.uk/" target="_blank">Mr Keith Clark</a> has been conjuring up some serious magic and created a way to <a
title="CSS3 pseudo-class selector emulation for IE" href="http://www.keithclark.co.uk/labs/ie-css3/" target="_blank">emulate CSS3 pseudo-class selectors</a> alongside the javascript library of your choice. This means that you can use goodies such as :nth-child, :first-of-type, :first-child, :last-child, etc. It&#8217;s a simple as adding</p><pre class="chili"><code class="html""""""""""""">&lt;script type=&quot;text/javascript&quot; src=&quot;[JS_LIBRARY]&quot;&gt;&lt;/script&gt;
&lt;!--[if (gte IE 5.5)&amp;(lte IE 8)]&gt;
&lt;script type=&quot;text/javascript&quot; src=&quot;ie-css3.js&quot;&gt;&lt;/script&gt;
&lt;![endif]--&gt;</code></pre><p>&#8230; in your head tag. But how does it work, I hear you scream. Well, allow me to quote the man himself;</p><blockquote><p>&#8220;First off, ie-css3.js checks the page for known JavaScript libraries and picks the one with the best CSS3 selector support.</p><p>Next, the style sheets on the page are downloaded and each of their selectors are parsed. Any CSS3 pseduo-classes are replaced by a standard CSS class of a similar name. For example: <code>div:nth-child(2)</code> will become <code>div.iecss-nth-child-2</code>. The detected JavaScript library is then used to find the DOM nodes matching the original CSS3 selector and the same CSS class is applied to them.</p><p>Finally, the original stylesheet is replaced with the new version and any elements targeted with CSS3 pseudo-classes will be styled.&#8221;</p></blockquote><p
class="clear"><hr
/><script type="text/javascript">google_ad_client="pub-8939939010469559";google_ad_slot="9013590878";google_ad_width=468;google_ad_height=60;</script><script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js"></script><br
/><hr
/></p><p>As of this writing, the :not selector isn&#8217;t supported but is on its way. There are some caveats, which, to be honest, are not that serious. Except that last bullet point. So don&#8217;t go all ajaxy on me now, y&#8217;hear?</p><ul><li>You have to use a link tag (@import is OK)</li><li>page level style sheets will be ignored</li><li>Style sheets have to be on the same domain as the page itself and can not use file://</li><li>There is no dynamic emulation, which means that once the page has been rendered and the styles have been applied, changes in the DOM will not be updated.</li></ul><p>While on the topic or, rather, something only slightly related, <a
title="52 framework" href="http://52framework.com/" target="_blank">52 framework</a> promises a way to enable you to use the clean, semantic markup of html5 &#8211; today. It employs <a
title="Eric Meyer's CSS Reset" href="http://meyerweb.com/eric/tools/css/reset/" target="_blank">Eric Meyer&#8217;s CSS reset</a>, which is nice in itself, and a grid system that is &#8220;loosely based on the 1kb grid and 960.gs&#8221;, and&#8230; Actually, why are you still here? Just get over there, and check out the <a
title="52 framework documentation" href="http://www.52framework.com/documentation/view/quick_start_guide_with_video/">52 framework docs &#8211; with video</a> as well as the demo. Don&#8217;t forget to check out the source code. can&#8217;t wait to play around with this in a project soon.</p><p>Come to think of it, I should mention a project on Google Code &#8211;  <a
title="HTML5 Media" href="http://code.google.com/p/html5media/">HTML5 Video</a> (or is it HTML5 Media?). This sweet litte package will enable you to embed MPEG-4 files using the H.264 video codec. Or, if you&#8217;re using Firefox 3.6, Ogv files encoded with Theora. If you use them both, you could sexy-up your code with the likings of</p><pre class="chili"><code class="html""""""""""""">&lt;video class=&quot;video&quot; poster=&quot;poster.jpg&quot; width=&quot;640&quot; height=&quot;480&quot; controls autobuffer&gt;
&lt;source src=&quot;my_awesome_movie.mp4&quot; type=&#039;video/mp4; codecs=&quot;avc1.42E01E, mp4a.40.2&quot;&#039;&gt;
&lt;source src=&quot;my_awesome_movie.ogv&quot; type=&#039;video/ogg; codecs=&quot;theora, vorbis&quot;&#039;&gt;
&lt;/video&gt;</code></pre><p>You just try to pretend that isn&#8217;t sexier than the horrible mess that is embed and object tags. Wrapping up, I might as well give you a tip about an awesome <a
title="HTMl 5 canvas cheak sheet" href="http://blog.nihilogic.dk/2009/02/html5-canvas-cheat-sheet.html">HTML 5 Canvas cheat sheet</a> from the people at <a
title="Nihilogic" href="http://blog.nihilogic.dk/">Nihilogic</a>. You&#8217;re welcome.</p><p>Related posts:<ol><li><a
href='http://pronewb.com/flash-king-of-the-impossible' rel='bookmark' title='Flash, King of the Impossible'>Flash, King of the Impossible</a></li><li><a
href='http://pronewb.com/css-typography-is-fun-really' rel='bookmark' title='CSS typography is fun. Really. If you&#8217;re in to S&amp;M'>CSS typography is fun. Really. If you&#8217;re in to S&#038;M</a></li><li><a
href='http://pronewb.com/a-popurls-clone-with-php-jquery-awesomeness' rel='bookmark' title='A Popurls Clone with PHP, jQuery, Awesomeness'>A Popurls Clone with PHP, jQuery, Awesomeness</a></li></ol></p>]]></content:encoded> <wfw:commentRss>http://pronewb.com/css3-pseudo-class-selector-emulation-for-ie-5-5-8-and-html5-with-video/feed</wfw:commentRss> <slash:comments>1</slash:comments> </item> <item><title>CSS typography is fun. Really. If you&#8217;re in to S&amp;M</title><link>http://pronewb.com/css-typography-is-fun-really</link> <comments>http://pronewb.com/css-typography-is-fun-really#comments</comments> <pubDate>Mon, 01 Mar 2010 13:58:02 +0000</pubDate> <dc:creator>william</dc:creator> <category><![CDATA[Code]]></category> <category><![CDATA[bokeh]]></category> <category><![CDATA[css]]></category> <category><![CDATA[font-face]]></category> <category><![CDATA[gradients]]></category> <category><![CDATA[inayaili de León]]></category> <category><![CDATA[jquery]]></category> <category><![CDATA[pagemaker]]></category> <category><![CDATA[paul irish]]></category> <category><![CDATA[photoshoot]]></category> <category><![CDATA[random]]></category> <category><![CDATA[turtle]]></category> <category><![CDATA[tutorial]]></category><guid
isPermaLink="false">http://pronewb.com/?p=29</guid> <description><![CDATA[So I found this article over at Smashing magazine dealing with CSS typography. It's a nice write up of both current and upcoming features - depending on your browser of choice - that will allow you to do some text formatting that I remember doing with Aldus PageMaker.Related posts:<ol><li><a
href='http://pronewb.com/css3-pseudo-class-selector-emulation-for-ie-5-5-8-and-html5-with-video' rel='bookmark' title='CSS3 pseudo-class selector emulation for IE 5.5 &#8211; 8 and html5 with video'>CSS3 pseudo-class selector emulation for IE 5.5 &#8211; 8 and html5 with video</a></li><li><a
href='http://pronewb.com/a-popurls-clone-with-php-jquery-awesomeness' rel='bookmark' title='A Popurls Clone with PHP, jQuery, Awesomeness'>A Popurls Clone with PHP, jQuery, Awesomeness</a></li></ol>]]></description> <content:encoded><![CDATA[<p><a
href="http://pronewb.com/wp-content/uploads/css_typogaphy_small.jpg"><img
class="alignleft size-medium wp-image-32" title="CSS typography is fun. Really." src="http://pronewb.com/wp-content/uploads/css_typogaphy_small-300x163.jpg" alt="CSS typography is fun. Really." width="300" height="163" /></a>So I found <a
title="CSS and the future of text at smashingmagazine" href="http://www.smashingmagazine.com/2010/03/01/css-and-the-future-of-text/" target="_blank">this article</a> over at Smashing Magazine dealing with CSS typography. It&#8217;s a nice write up of both current and upcoming features &#8211; depending on your browser of choice &#8211; that will allow you to do some text formatting that I remember doing with <a
title="Aldus at wikipedia" href="http://en.wikipedia.org/wiki/Aldus" target="_blank">Aldus</a> <a
title="PageMaker at wikipedia" href="http://en.wikipedia.org/wiki/Adobe_PageMaker" target="_blank">PageMaker</a>. Good times. Nice to see that technology is progressing at a steady pace. Competent writer <a
href="http://yaili.com/">Inayaili de León</a> does a fine job going through some common and some not-so-common features such as hyphenation, indentation and hanging punctuation. I&#8217;m quite sure that you&#8217;ll find some new things in there.</p><p>She also covers the wonders of <em>font-face</em>, although I feel there is more to be written on that topic. <a
title="Paul Irish homepage" href="http://paulirish.com/" target="_blank">Paul Irish</a>, Esq, is a handsome fellow that makes jQuery even more fun. He has concocted a &#8220;bulletproof @font-face syntax&#8221; which works really, really well. Even in IE. Yes, in IE. Read all about it <a
title="Bulletproof font-face" href="http://paulirish.com/2009/bulletproof-font-face-implementation-syntax/" target="_blank">over here</a>. Using these methods, you&#8217;ll want to use  a font-face generator, such as <a
title="Fontsquirrel font-face generator" href="http://www.fontsquirrel.com/fontface/generator" target="_blank">this one</a> @ fontsquirrel.com. It will make your online presence a bit more tolerable. But if you use Comic Sans, I will hunt you down. No, really. I&#8217;ll find a way.</p><p
class="clear"><hr
/><script type="text/javascript">google_ad_client="pub-8939939010469559";google_ad_slot="9013590878";google_ad_width=468;google_ad_height=60;</script><script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js"></script><br
/><hr
/></p><p>Yeah, I tent do visit <a
title="Smashing Magazine" href="http://www.smashingmagazine.com/" target="_blank">Smashing Magazine</a> quite frequently even though I&#8217;m not on their payroll. Of course, they have written about typography before, and they have done so very well. One of my favorite articles is <a
title="50 useful design tools for beautiful web typography" href="http://www.smashingmagazine.com/2009/01/27/css-typographic-tools-and-techniques/" target="_blank">50 Useful Design Tools For Beautiful Web Typography</a>, covering everything from free fonts to which fonts are (usually) available on a given user&#8217;s computer. There&#8217;s just too much to mention here. Just go already! oh, and if you need some more CSS centric list o&#8217; links, <a
title="Useful CSS tools" href="http://www.smashingmagazine.com/2008/12/09/50-really-useful-css-tools/" target="_blank">check this out instead</a>.</p><p>If you&#8217;re into the fine art of controlling word wrapping (yeah, good luck with that), hyphenation and spaces, <a
title="Alex Dunae" href="http://dunae.ca/" target="_blank">Alex Dunae</a> has written an article that should make you feel <a
title="Better web typography" href="http://dunae.ca/2009/better-web-typography-with-spaces-and-hyphens/">all warm and fuzzy inside</a>. What&#8217;s so special about his article, you ask? Well, my impatient, link loving visitor, he has actually made some screen shots with how different browsers interpret non-breaking space, soft hyphens and zero-width space. I know, crazy, right?</p><p>Speaking of CSS, CSS3 is shaping up quite nicely and it is a joy to play with. If you want some sort of example in the form of a sleek, sexy menu, <a
title="CSS3 menu" href="http://www.webdesignerwall.com/tutorials/css3-dropdown-menu/" target="_blank">you&#8217;re in luck</a>! It also degrades quite nicely. <a
title="Bokeh effect with CSS3 and jQuery" href="http://www.marcofolio.net/webdesign/pure_css3_bokeh_effect_with_some_jquery_help.html" target="_blank">As another example</a>, you can actually create e sweet <a
title="Bokeh effect at wikipedia" href="http://en.wikipedia.org/wiki/Bokeh" target="_blank">bokeh effect</a> &#8211; using only CSS3 (and some jQuery). Also, <a
title="Photoshoot effect" href="http://tutorialzine.com/2010/02/photo-shoot-css-jquery/" target="_blank">here&#8217;s a cool effect</a> that mimics a photo shoot, using jQuery and CSS. Should be quite nice for image cropping. And you really shouldn&#8217;t miss <a
title="Multiple CSS backrgrounds and gradients" href="http://snook.ca/archives/html_and_css/multiple-bg-css-gradients" target="_blank">this article</a> regarding multiple backgrounds and gradients with CSS! The important thing is to play and try out different techniques until you&#8217;re satisfied, look at it in IE 6, cry, ponder the meaning of life and then start over. That, my friend, is the circle of CSS.</p><p><strong>Update: </strong>I forgot to mention a <a
title="50 CSS3 animations" href="http://www.1stwebdesigner.com/development/50-awesome-css3-animations/" target="_blank">really sweet page</a> with no less than 50 animations, using CSS3 (and some JS here and there). Definitely worth watching!</p><p>On a random note, <a
title="Newly hatched baby turtle" href="http://gallery.photo.net/photo/9888897-md.jpg" target="_blank">here&#8217;s a newly hatched baby turtle</a>. It resembles how I felt this morning.</p><p>Related posts:<ol><li><a
href='http://pronewb.com/css3-pseudo-class-selector-emulation-for-ie-5-5-8-and-html5-with-video' rel='bookmark' title='CSS3 pseudo-class selector emulation for IE 5.5 &#8211; 8 and html5 with video'>CSS3 pseudo-class selector emulation for IE 5.5 &#8211; 8 and html5 with video</a></li><li><a
href='http://pronewb.com/a-popurls-clone-with-php-jquery-awesomeness' rel='bookmark' title='A Popurls Clone with PHP, jQuery, Awesomeness'>A Popurls Clone with PHP, jQuery, Awesomeness</a></li></ol></p>]]></content:encoded> <wfw:commentRss>http://pronewb.com/css-typography-is-fun-really/feed</wfw:commentRss> <slash:comments>2</slash:comments> </item> </channel> </rss>
<!-- Performance optimized by W3 Total Cache. Learn more: http://www.w3-edge.com/wordpress-plugins/

Minified using disk: basic
Page Caching using disk: enhanced (User agent is rejected)
Database Caching 8/72 queries in 0.373 seconds using disk: basic
Object Caching 835/1811 objects using disk: basic

Served from: pronewb.com @ 2013-05-25 11:02:34 -->