Archive: Web

Page 1 of 5 1 2 3 4 5

May 12, 2008

Cross browser session data with Javascript

By storing data in the window.name property, you can store data between page loads and across domains without ever sending a cookie to a server. Thomas Frank created the sessvars.js library which makes use of this browser quirk, allowing you to store up to 2 MB of client-side session data.

This is really powerful for a few reasons:

  • client-side, you can store way more data than allowed by traditional cookies
  • none of the data is transferred explicitly to the server, minimizing bandwidth used for each page request
  • allows you to talk between pages in different domains

Keep in mind that anything you store via this mechanism will be visible to any other site that a person visits, so this is best for storing non-sensitive data that you want to retain between page loads. This would be great for caching returned AJAX data that you would otherwise have to refetch and reprocess.

Session variables without cookies

Posted by Jason Striegel | May 12, 2008 07:26 PM
Ajax, Web | Permalink | Comments (0) | TrackBack | Digg It | Tag w/del.icio.us

May 9, 2008

Processing.js - visualization library for Javascript

jsprocessing_20080509.jpg

John Resig, of jQuery fame, released a port of the Processing visualization language for Javascript. Seriously, John is on fire:

The first portion of the project was writing a parser to dynamically convert code written in the Processing language, to JavaScript. This involves a lot of gnarly regular expressions chewing up the code, spitting it out in a format that the browser understands.

It works "fairly well" (in that it's able to handle anything that the processing.org web site throws at it) but I'm sure its total scope is limited (until a proper parser is involved). I felt bad about tackling this using regular expressions until I found out that the original Processing code base did it in the same manner (they now use a real parser, naturally).

The full 2D API is implemented, with the exclusion of some features here and there between browsers (Firefox 3 is pretty full featured). You can interact with the Processing API directly from standard Javascript. This lets you make use of these drawing features by simply instantiating a Processing object, and then calling its various drawing methods.

Another capability is to write code natively in the Processing language. This allows you to make use of extended language features such as method overloading and classic inheritance, though it looks like type information is pretty much ignored.

John has many of the demos from processing.org working. Most of them are going to peg your CPU, but this is some seriously cool stuff to see working in a first release.

Javascript just got a lot more interesting.

Processing.js
Processing: open source data visualization language

Posted by Jason Striegel | May 9, 2008 09:36 PM
Ajax, Data, Firefox, Software Engineering, Web | Permalink | Comments (0) | TrackBack | Digg It | Tag w/del.icio.us

May 1, 2008

Server-side Google Analytics

Peter van der Graaf did a little analysis of the URLs that are generated by the Google Analytics Javascript API and put together a very useful tutorial for building Analytics-enabled applications without the use of Javascript.

When you look at the analytics javascript code you see that it combines several sets of data into an image request. This image request sends the right data to Google (not the javascript). When you know what url you should use for the image, you can call the image directly and send the same data. Of course you need to be able to request the image url and that isn't easy from another image, rss feed or pdf. This is why we request it "server side".

You can add the code to the PHP that drives a blog site, for instance, and generate page views when your RSS feed is hit. You can even write a very simple script to proxy images and downloads, which will let you track hit data for all files on your site, not just the html pages viewed by a javascript enabled browser.

Taken a step further, you could even use this on the client side, triggering analytics views from standalone Flash apps or even desktop applications.

The one thing you need to keep in mind is that server-side analytics requests will appear to come from your server, not the client's machine. So while you can track page views and download events this way, you'll loose a lot of the information about your user base. Because of this, it would probably make sense to use a separate tracking ID for the server side events.

Google Analytics Without Javascript

Posted by Jason Striegel | May 1, 2008 08:27 PM
Google, PHP, Statistics, Web, Web Site Measurement | Permalink | Comments (0) | TrackBack | Digg It | Tag w/del.icio.us

April 29, 2008

Stop XSS attacks with SafeHTML

If you allow user-contributed content in your site, you run into the problem of dealing with user supplied HTML in a safe manner. The most secure way of dealing with things, of course, is to strip or escape all HTML from user input fields. Unfortunately, there are many situations where it would be nice to allow a large subset of HTML input, but block out anything potentially dangerous.

SafeHTML is a lightweight PHP user input sanitizer that does just that. Just run any input field through the SafeHTML filter and any javascript, object tags, or layout breaking tags will be stripped from the supplied text. It also does a reasonable job of correcting any gnarly, malformed code, which is also a common problem with user-contributed data.

Using it is easy. Just instantiate the SafeHTML object and call its parse method:

require_once('classes/safehtml.php');

$safehtml =& new SafeHTML();

if ( isset( $_POST["inputfield"] ) )
{
  $inputfield=$_POST["inputfield"];
  $cleaninput = $safehtml->parse($inputfield);
}

This will take the posted "inputfield" parameter, strip any baddies, XHTMLify what's left, and the result will be stored in the $cleaninput variable. It's a simple addition to your code, and a lot more straightforward than trying to roll your own.

My only beef with the package is that it's written with a default allow policy, stripping out tags that are in its deleteTags array, but essentially allowing anything else through. If you'd rather only let through tags that you specifically want to allow, I'd recommend adding an allowTags array and adjusting the _openHandler method, adding the following after the deleteTags check:

if ( ! in_array($name, $this->allowTags)) {
  return true;
}

You'll need to fill allowTags with everything you know to be safe and welcome, and you may miss a few that people will end up wanting to legitimately use, but this is easily corrected and the default deny policy is much safer in the long run.

SafeHTML - an anti-XSS HTML parser, written in PHP

Posted by Jason Striegel | Apr 29, 2008 08:49 PM
Network Security, PHP, Web | Permalink | Comments (4) | TrackBack | Digg It | Tag w/del.icio.us

April 22, 2008

Encoding JPEGs client-side in AS3

I've been doing a bunch of Flash Actionscript 3 development lately at work, and one of my favorite features with the new drawing API is the ease and speed with which you can rasterize vector data and manipulate image bitmaps.

What's killer is that Adobe's as3corelib addon library finally gives us some essential tools that have been sorely lacking, none the least of which is a client side JPEG encoder. With this, you can turn any drawable object like a sprite or a movieclip into a ByteArray holding the compressed JPEG data in just a few lines of code. It's as simple as this:

import com.adobe.images.JPGEncoder;

var clipbmp:BitmapData = new BitmapData (aclip.width, aclip.height);
clipbmp.draw(aclip);

var jpgEnc:JPGEncoder = new JPGEncoder(90);
var jpgbytes:ByteArray = jpgEnc.encode(clipbmp);

This turns the "aclip" sprite or movieclip into a rasterized, flattened, BitmapData object. The BitmapData is then run through the JPEG encoder with the quality setting of 90 and you're left with the raw JPEG-compressed image in a ByteArray object. The as3corelib also provides a PNG encoder, with which you can just use the static method PNGEncoder.encode(clipbmp).

This is perfect for saving a capture of user-generated artwork to the server. Just set the data member of a URLRequest object to the ByteArray and post it. For more detailed information on how to put all the pieces together, Henry Jones has a really thorough post of compressing JPEG data and pinging it off a server to force an image download.

Unfortunately, to trigger a JPEG download, you still need to post the image data up to a server script and have it echo it back to the browser. The difference now, though, is that you can do the compression on the client end, saving both server CPU time and the time to upload the image data. This means saving a large image is a few second process instead of taking a minute and a half.

Actionscript 3 Core Library (as3corelib)

Posted by Jason Striegel | Apr 22, 2008 10:03 PM
Flash, Software Engineering, Web | Permalink | Comments (2) | TrackBack | Digg It | Tag w/del.icio.us

April 13, 2008

Nice overview of the YouTube API

I caught this self-referential tutorial on YouTube today which walks you through the basics of the YouTube API. It appears to be quite simple to develop Javascript or Flash applications that can control or interact with the YouTube player, or even completely reskin the interface.

What I didn't know until recently was that the API has provisions for allowing your application to upload videos and post comments. You can even authenticate users and allow them to interact with the YouTube backend through your private application. It looks like you can do just about everything programatically except remove the YouTube watermark on the video.

YouTube Developer's Guide
Developer API Blog

Posted by Jason Striegel | Apr 13, 2008 11:12 PM
Ajax, Flash, Web, YouTube | Permalink | Comments (1) | TrackBack | Digg It | Tag w/del.icio.us

April 11, 2008

Automatic outbound link analytics with jQuery

I had the challenge of adding Google Analytics tracking code to all the outbound links on a site I've been working on. There are hundreds of these links scattered around the site, so rather than try and edit a bunch of links, manually adding onclick handlers in an error-prone fashion, I decided to get lazy and write some code to handle it for me.

First I was thinking about doing some sort of regular expression search and replace throughout the site and database, but that reminded me of CSS3 selectors and their ability to do simple pattern matching. I've seen people apply a special style to outbound links this way, so after a few minutes of monkeying around with things, I now have a chunk of jQuery that will automatically track clicks on all outbound links.

Here it is, in a nutshell:

jQuery(function($){

   // Match all anchor tags in the "maincontent" div with
   // urls that begin with "http" but don't contain the
   // string "yourwebsite.com"
   $('#maincontent a[href^="http"]').not('a[href*="yourwebsite.com"]').click(function(){

     try {

     // Get the href url and toss out the "http://"
     var href = $(this).attr('href');
     if ( href.indexOf("://") > 0 ) {

       // Track the page in Google Analytics as
       // "/tracking/outbound/www.somesite.com/foo"
       var outbound = '/tracking/outbound/' + href.split("://",2)[1];
       pageTracker._trackPageview(outbound);

       }
     } catch( e ) {}
   }
}

With this running, all of my internal pages get tracked as usual, and any external links will appear as pageviews that look like "/tracking/outbound/www.somesite.com/foo".

If you link out to many different pages on several sites, keeping the full site url in the tracking code and building these deep paths is particularly useful. Google Analytics will allow you to drill down into the tree like it was normal content and quickly pull numbers on how many total outbound clicks you received (/tracking/outbound), how many went to www.somesite.com (/tracking/outbound/www.somesite.com), and how many people clicked out to a particular page on the site.

This saved me quite a bit of time and is immensely more flexible than any other outbound tracking method I've used. I hope this helps someone else. Drop me a line in the comments if this works out for you.

Update: it looks like I wasn't the first to do this. An article by Rebecca Murphey shows how to do something similar, while also adding the referring post title to the tracking code. Pretty cool stuff, I must say.

Posted by Jason Striegel | Apr 11, 2008 10:57 PM
Ajax, Google, Statistics, Web, Web Site Measurement | Permalink | Comments (0) | TrackBack | Digg It | Tag w/del.icio.us

April 8, 2008

Relational database using jQuery and HTML tables

Here's a novel use for the HTML <TABLE> tag: storing client side database tables. Nick Kallen came up with a slick hack that uses the jQuery syntax to perform simple selects and joins on HTML tables. By using CSS3 selectors, you can easily target fields which match or contain your search terms, and Nick's jQuery-based API provides a simple query language, similar to a rudimentary SQL:

Today I was thinking aloud about Tree Regular Expressions and how they might make a nice query language for document databases like CouchDB. Someone pointed out that CSS3 selectors might make a great concrete syntax for this. One thing lead to another and I thought, why not build a relational database in HTML? So I did. I even got inner joins working.

Let's start with a few tables:

<table class="users">
  <tr>
    <td class="id">1</td>
    <td class="first_name">amy</td>
    <td class="last_name">bobamy</td>
  </tr> 
  ...
</table>
<table class="photos">
  <tr>
    <td class="id">1</td>
    <td class="user_id">1</td>
    <td class="url">http://www.example.com/foo.png</td>
  </tr> 
</table>

Now we can express some queries:

$('.users')
  .where('.id:eq(1)')
  .select('*')

This is equivalent to SELECT * FROM users WHERE id = 1

$('.users')
  .where('.id:eq(1)')
  .select('.id, .name')

This is equivalent to SELECT id, name FROM users WHERE id = 1

How cool is that? Check out Nick's blog post for an example of text search and an inner join. The API in his jquery.db.js is quite straightforward and only about 50 lines of code. Adding a sort function shouldn't be too difficult.

I'm pretty much convinced now that jQuery is black magic.


Building a relational database using jQuery and <TABLE> tags
Download the jquery.db.js library

Posted by Jason Striegel | Apr 8, 2008 10:02 PM
Ajax, SQL, Software Engineering, Web | Permalink | Comments (1) | TrackBack | Digg It | Tag w/del.icio.us

March 28, 2008

CSS ad blocking for Firefox and Safari

Using Firefox's CSS-based chrome feature or Safari's advanced stylesheet preferences and a little clever CSS coding, you can disable most banner ads, making them invisible in your browser. This technique is considerably easier and more flexible than setting up a private DNS server or proxy to filter out images from ad-serving domains.

The trick is setting up a number of CSS rules that use "*=" substring selection on an element's properties. For instance, matching an IFRAME tag with the SRC parameter containing doubleclick would look like IFRAME[SRC*="doubleclick"] and matching an anchor tag with an HREF containing a url with "ads." in it would look like A:link[HREF*="ads."]. Giving the style "display: none ! important" to all of the possible combinations and adding the stylesheet to your browser's chrome effectively turns off the ad-serving web. The site below has a comprehensive CSS file that's been tailored to assassinate ads from most networks.

To be honest, I didn't realize that you could do this type of parameter matching and subselection in CSS, so it's worth looking at the CSS source for that alone. If you don't use it for this purpose, perhaps the technique will come in handy for something else you are working on.

Better Ad Blocking for Firefox, Mozilla, Camino, and Safari
Ad Blocking userContent.css

Posted by Jason Striegel | Mar 28, 2008 09:20 PM
Firefox, Life, Lifehacker, Mac, Web | Permalink | Comments (0) | TrackBack | Digg It | Tag w/del.icio.us

Design Coding: web standards rap

Next time you're trying to explain the importance of web standards in modern web design and development, just let this video do the talking for you.

The Poetic Prophet (AKA The SEO Rapper) is back with another marketing rap. This time he describes how web standards and proper design can affect the ranking and conversion of pages on your site.

I know this isn't the usual fare here, but I feel I'd be remiss in my duties if I didn't include it in our compendium of all things hack.

Posted by Jason Striegel | Mar 28, 2008 08:00 PM
Music, Web, YouTube | Permalink | Comments (2) | TrackBack | Digg It | Tag w/del.icio.us

March 21, 2008

Easiest cross-browser CSS min-height

Enforcing a minimum height for block elements in HTML is one of those few CSS tricks that you can't live without. There are still enough folks using IE6, unfortunately, and it doesn't support the min-height or min-width CSS parameters. This has caused the invention of a number of different hacks and browser-conditional style sheets to get the desired effect.

Many of the different methods work well, but after trying a number of them, I can say that the following method is the easiest to use and is compatable across all common versions of Firefox, Safari, and IE. Many of you are probably already using this method—it's not new—but for those of you who aren't, give it a try. It should save you a lot of headaches.

Cross Browser min-height

.foo {
min-height:100px;
height: auto !important;
height: 100px;
}

This works because all of the more recent browsers will understand and respect the min-height setting as well as the !important designation. So in the example above, the block will be given the min-height setting you specify, and the height:auto will take precendence over the height:100px, even though it appears earlier in the code. With content shorter than 100px, the min-height setting is observed, and with content that is longer, the block is sized to fit the content.

In the case of older versions of IE, neight the min-height parameter nor the !important designation are supported. Instead, the browser essentially sees a height:auto, immediately followed by a height:100px, and the latter takes precendence. Lucky for us, height parameter in older versions of IE function exactly like the min-height parameter. When content expands past the size of the element, it grows to accommodate it. When content is shorter, the specified height is respected.

I don't find myself using it as much, but this also works with min-width:

Cross Browser min-width

.bar {
min-width:100px;
width: auto !important;
width: 100px;
}

Posted by Jason Striegel | Mar 21, 2008 08:31 PM
Web | Permalink | Comments (7) | TrackBack | Digg It | Tag w/del.icio.us

February 25, 2008

Botanicalls Twitter: flora tweets

botanicalls_20080225.jpg

With Monday finally wrapping up, it's time to start thinking about next weekend. Why not spend it Twitter-enabling your house plants?

Botanicalls Twitter answers the question: What's up with your plant? It offers a connection to your leafy pal via online Twitter status updates that reach you anywhere in the world. When your plant needs water, it will post to let you know, and send its thanks when you show it love.

I've managed to make it through the winter with only two plant casualties so far. There isn't a whole lot I can do about the scarcity of light in Minneapolis, but with a little Arduino hacking I could at least remove watering issues from the equation.

Botanicalls Twitter - Link

Posted by Jason Striegel | Feb 25, 2008 08:42 PM
Electronics, Home, Life, Web | Permalink | Comments (0) | TrackBack | Digg It | Tag w/del.icio.us

February 14, 2008

Nifty Corners: roundtangles made simple

niftycorners_20080214.gif

Since the border-radius CSS parameter has been too slow in coming and rounded corners don't seem to be going out of style any time soon, everyone web developer I know has their own personal brand of CSS background-image and DIV gymnastics for creating smooth-cornered roundtangles. Besides the extra load time that's required to download all those corner images, it's just a lot of extra work. The general principle of unnecessary work is against my slacker sensibilities, which is why the Nifty Corners Cube javascript library caught my attention.

Nifty Corners uses Javascript to dynamically add rounded corners to HTML elements at runtime, without the use of images. You can choose a corner style and tell Nifty Corners what CSS id, class or element to apply it to. The javascript function will dynamically alter the specified elements, drawing 1px high DIV strips at the top and bottom of the element to give it the rounded corners. The effect can be used for everything from rounded content areas to tab-menus.

It won't solve every problem—rounded borders, in particular, are still a bit of a nuisance—but it'll make your work a lot easier for many design challenges and it's compatible with Firefox, Safari and IE 5.5-7.0.

Nifty Corners Cube - Link

Posted by Jason Striegel | Feb 14, 2008 08:57 PM
Web | Permalink | Comments (2) | TrackBack | Digg It | Tag w/del.icio.us

February 8, 2008

HOWTO: cross-browser alpha PNGs

bulb_png24-nq8.png

If you're a web designer, here's a tool that's going to make your life a lot better. Seriously, in no time you'll be dropping shadows like Galileo dropped the orange.

Transparent GIFs only have a single bit of transparency—a pixel is either totally transparent, or it's completely opaque. 24 bit PNG images, on the other hand, have a bona fide alpha channel, allowing your images to have a full range of transparency. Problem is, they have poor browser support in IE.

The indexed PNG 8 format is similar to the GIF format, and I had always thought that it only allowed boolean transparency. It turns out the PNG 8 format is a little more clever. You still have a 256 color index palette like the GIF format, but the format allows for each index to have its own transparency level, and that level can be set at any amount of opacity!

Here's the real kicker. Even old versions of IE support the PNG 8 format to some degree. So on Firefox, Safari, and IE 7 you can have full alpha support without using any of the quirky IE specific PNG hacks. Older versions of IE will still display your alpha PNGs, but they will revert to a GIF-like all or nothing transparency. Any portion of the image which is semi-transparent will be forced to fully transparent.

To sum it up, the PNG8 alpha format gives you complete cross browser alpha transparency for all modern browsers, and it degrades gracefully for older versions of IE that some people may still be using. As an example, the image above is a semi-transparent PNG8. Most of you will see the blue gradient fade around the edge of the light bulb. Those of you with older versions of IE will see a hard edge around the bulb, similar to what you'd get with a GIF.

Correction: my example is a little goofed, as the blue in the image obtained a partial transparency during the quantization process. IE users will only see some of the bottom portion of the bulb, specifically colors that didn't match the transparent portion in the RGB space. For normal drop-shadow overlays, this does not usually pose a problem. Remember, though, that converting to PNG8 means bringing thousands of color and alpha values down to 256. If your solid colors get mapped to a partially transparent index, they will disappear in older versions of IE.

A coworker introduced me to this today and showed me how Fireworks has an export option for PNG 8 that enables this full-alpha mode. I hadn't been aware of it, because Photoshop has no such feature, only allowing GIF-like transparency for 8 bit PNGs. Unfortunately, I really hate hate have a hard time with Fireworks, and I don't want to purchase it.

A little searching, though, and I found pngnq, a command line tool that will quantize a PNG24 image into a 256 color PNG8 image with alpha transparency. Here's how you use it:

  1. Export ("save for web" in Photoshop) your image in the RGBA PNG-24 format
  2. At the command line, run "pngnq filename.png"
  3. The image will be converted and the output named filename-nq8.png

To install pngnq, just grab the binary from the link below and copy the pngnq executable to somewhere in your path. In OS X, you can put it in /usr/local/bin and add that to your PATH variable (or just toss it it /usr/bin). The program requires the libpng library in order to run. This isn't pre-installed on a Mac for some reason, so you'll have to build it from source, use Fink, or use the installer at the site conveniently listed below.

pngnq - Link
libpng installer for OS X - Link

Posted by Jason Striegel | Feb 8, 2008 09:51 PM
Web | Permalink | Comments (7) | TrackBack | Digg It | Tag w/del.icio.us

January 20, 2008

ie7.js: Force Internet Explorer to behave

IE7 is a JavaScript library to make Microsoft Internet Explorer behave like a standards-compliant browser. It fixes many HTML and CSS issues and makes transparent PNG work correctly under IE5 and IE6.

This is great. By adding the ie7.js script to your site code, you effectively force all older browser versions to function as IE7 does. Now that IE7 is out, there's a second script (you guessed it: ie8.js) that brings IE7 clients almost completely up to standards-spec.

If you're a web developer, you know how frustrating it can be to get things to display correctly in all browsers. Instead of resorting to trial-and-error methods and applying various random hacks to make things work, these javascript libraries have condensed all of the necessary hacks into a single library, so you can code normally and pretend they don't even exist. As MS releases product updates, you can get the latest javascript library and put it in place without too much worry about having to tweak your site to make it render properly in newer browser versions.

ie7-js: Make MSIE behave like a standards-compliant browser - Link

Posted by Jason Striegel | Jan 20, 2008 06:54 PM
Web | Permalink | Comments (2) | TrackBack | Digg It | Tag w/del.icio.us

Page 1 of 5 1 2 3 4 5

Bloggers

Welcome to the Hacks Blog!

Brian Jepson.Brian Jepson


Jason Striegel.Jason Striegel


Philip Torrone.Phillip Torrone



See all of the books in the Hacks Series!
Advertise here.

Recent Posts

www.flickr.com
photos in Hacks More photos in Hacks