Creating a development environment for WordPress.

Although the default installation for WordPress meets my minimum requirements, there are several visual and other changes I’m considering that I don’t want to experiment with using the live site.   So before I go any further,  I’ve decided to set up a development environment.

Step 1: Creating a virtual development machine.

To prevent unnecessary overhead on my system, and also to simplify testing and backups, a few years ago, I standardized on doing all my development work using using virtual machines, this lets me have any combination of os/tools/services required for a development project stored in one, easily backed up and portable file.   Currently I’m using Oracle VM Virtual Box, so hopefully Oracle doesn’t start charging for this currently free application.

I’ve decided to install Windows XP as the guest OS for now, mainly because I have an extra licensed copy.

After installing the OS, including IIS, then the patches, and the Guest additions, I have a basic OS and webserver ready for use.  I recommend making a backup of the VM file at this point, you can then clone the backup, and use the clone as the starting point new projects, with both the OS and IIS ready to go.

Personally, I don’t bother install a virus scanner on the guest OS, instead, I simply do not surf the web from within the virtual machine (with the exception of FTP to and from my live server), instead I download all files and updates using the host OS, and then move them to the guest OS using a virtual shared folder.

Step 2: Setting up the development environment for WordPress.

Before I began this step, I checked the version of PHP and MySQL installed by my hosting company, luckily they have the latest versions of both installed.

  1. Downloaded and installed MySQL server 5.5
  2. Downloaded and installed MySQL workbench 5.2
  3. Downloaded and installed PHP 5
  4. Pointed my IIS default website to the folder I wanted to use as the root of my dev-site
  5. Enabled directory browsing in IIS for the site (find this makes dev work much easier.)
  6. Created a quick “hello world” php file to make sure everything was working.
  7. Created a test db using MySQL workbench to make sure that the server was working.

Step 3: Copying my live WordPress site to development.

Because I had already installed WordPress on my hosting, creating the development environment was pretty straight foward:

  1. I FTP’d the contents of my live-site to the dev-site folder I created in Step 2.4
  2. Loaded up the browser in my virtual machine, and pointed the location to “localhost”
  3. Up came my website, with the php running on my dev machine, but the site is still pointing to the MySQL server of my live site.  I want a dev-site completely detached from the live site.
  4. I opened the wp-config.php file found in the root of my dev-site, the file contains the following:
    1. DB_NAME – the name of the database schema created by my hosting company for WordPress
    2. DB_USER – the user name that WordPress uses to access the database
    3. DB_PASSWORD – the password for that user, this should be a long random string, if not, you should see how you can get it changed.
    4. DB_HOST – the IP address of the MySQL server on my host.   I copied this line, commented out the original, and changed it to “127.0.0.1″
  5. Using MySQL Workbench, under Server Administrator:
    1. I created a new Server Instance, I called wp-live, using the information from Step 2.
      • I connected to the live-db using the new Server Instance.
      • I used the Data Dump feature to export a Self-Contained File (.sql), I called wp-snapshot.sql, containing the contents of my live-db.
      • I closed the new instance
    2. I connected to the my dev-db, using the local instance created when installed MySQL, called Local instance: MySQL.
      • I used the Data Dump feature to import the wp-snapshot.sql into the dev-db, this created a duplicate of information in my live-db in my dev-db, including the same DB_NAME.
      • I used the  Accounts feature to create an account with the same name and password as DB_USER, and DB_PASSWORD from Step 3.2, and gave the account the DBManager role.
  6. To make sure that I was definitely using the dev-db not the live-db, I disconnected my system from the internet.
  7. I loaded up the browser in my virtual machine, and pointed the location to “localhost”
  8. The page content loads, so the dev-db is working, but there is no formatting.   Taking a quick look at the HTML, I see that links still contain stevenksavage.com.

Step 4: Changing the domain for my WordPress development site.

The answer was fairly simple, I simply add the following lines to my wp-config.php:

I now have a development environment for WordPress that I can use to start experimenting with themes, templates and plugins without affected my live-site.

Transferring my old content to the transitional site.

One of my key requirements was to transfer  the content from my old site to the new site without breaking any links from external sites.

There are two reasons for this:

  • Referred visitors.
  • Search Engine Ranking.

The best way to move a page an let everyone know that it is a permanent move is to send the 301 Moved permanently, header.    Because old site was done in ColdFusion 8, the solution was fairly straight forward.

First, I added the onMissingTemplate to my old application.cfc file.

<cffunction name="onMissingTemplate" access="public" returntype="string">
  <cfargument name="requested" type="string" required="true"
     hint="I am the template that the user requested." />
</cffunction>

Next, because I wanted to map specific pages to their new location, I added

<cffunction name="onMissingTemplate" access="public" returntype="string">
  <cfargument name="requested" type="string" required="true"
     hint="I am the template that the user requested." />
  <cfset template="/index.php">
  <cfscript>
     if(findNoCase("/content/500/1.en.cfm",requested)) template = "/?page_id=2";
     else if(findNoCase("/content/500/2.en.cfm",requested)) template = "/?p=60";
  </cfscript>
  <cfheader statuscode="301" statustext="Moved permanently">
  <cfheader name="Location"  value="#template#">
</cffunction>

The final step is to delete all the old .cfm pages on my site. Now whenever someone goes to an old link, they will be send a 301 message, and redirected to the pages new WordPress address.

Starting up the project to create a transitional site

As I mentioned in my last post, the first project will be to create a transitional site that will let me keep my older content, but also let me gather feedback on the new site I develop the final version.

In the past I relied mainly following a mental plan for developing and modifying my site, but to help create content for the new site, and based on lessons learned from my time as a BA and project manager, I plan to take and discuss a more analytical approach.   So, before I begin, I’m going to create an initial plan based on recommendations from Prince2

  1. Identify the primary stakeholders and their key requirements.
  2. Decide what approach I’m going to take with the project.
  3. Document lessons learned from my past experience creating a website, what worked/what didn’t, and also look at industry best practices
  4. Identify my target audience, if I’m the only audience for the site, there isn’t much point in continuing, so what are the needs of these other, unknown users?
  5. The initial scope.
  6. Come up with possible solutions for how the site can be built, and if necessary based on the options, identify the remaining stakeholders and their key requirements.
  7. Pick a solution
  8. Plan for the implementation

Primary Stakeholders and their key requirements.

There are only two, myself, and my hosting company.

My key requirements

  1. I want to get something launched as soon as possible so I can start getting user feedback on content, design and technology for the new site as it is developed.
  2. Must be able to move my existing content to the new site, and be able to use 301 redirects (permanent move) so I don’t break links from external sites.
  3. Must be able to control the look and feel of the site
  4. Solution must not be sole source, I don’t want to be locked in to a specific vendor.
  5. Must allow me to backup my content, and the comments from users

My hosting site’s key requirements

These requirements are based on my current hosting service, and may change if the desired solution needs different functionality.

  • Must use one of the technologies support by the hosting service, currently Coldfusion, PHP, or ASP.NET
  • Must not compromise the servers.

What approach am I going to take

I’m going to follow an iterative process, for several reasons:

  • As I mentioned in my key requirements, I want to get something launched as soon as possible, an iterative approach will allow me to set up my site to meet my minimum requirements, and then add / enhance in the future..
  • I’ve personally had more success and experience with an iterative approach than any of the other software development lifecycles, especially for web projects that have a habit of going on indefinitely.
  • I will not be doing this full time, so if I wait until all I have the perfect site, the site will never get launched.

Lessons learned

  • Focus on the content first, technology and design second.   In the past I’ve started thinking about the design and technology too soon, and then had difficulty fitting the content in to the site.
  • Pick the best solution, not simply the most interesting, or the easiest.   In the past I’ve created my on solution for both amusement and knowledge, with my shift from web developer to business analyst and project manager, my web design skills are not currently up to date, so should I spend the effort on updating my skills, or simply use an existing solution (e.g. wordpress, drupal etc.)

Identify the target audience (the users)

My target audience are other business analysts, project managers and developers that I may be able to help, or that can help me as I learn and practice a variety of skills and techniques.   So, in general my target audience is educated, technically savvy, and is looking for, and/or has knowledge in one or more of these areas.

The scope

The scope for this project is to pick a solution that will let me start posting documents like this so I can gather comments on feedback,  and to port any legacy information I want to keep to the new solution.   Any other enhancements,visual or otherwise will be treated as new projects.

Possible Solutions

For all of these projects there are three main options: build (custom), use an existing solution (buy, open source etc.), or create a hybrid (some customization some existing).   I found in most cases it’s the third option.  But for this project I’m going to try and go with an existing, open source solution for the initial launch, so whatever I pick has meet the key requirements out of the box.

So my first step is to look at what solutions my hosting service provides.

  • Joomala
  • Kentico CMS for ASP.NET
  • Mura for Coldfusion
  • WordPress

Now, I could do a detailed analysis on the pros and cons of each, or look a different options, such as Drupal etc.   But, I will leave that to the next project, for now I just need something to meet my minimum requirements.

I had heard of WordPress before, and decided to try it first, so looking again at my key requirements:

  1. I want to get something launched as soon as possible so I can start getting user feedback on content, design and technology for the new site as it is developed. YES, WordPress provides comments.
  2. Must be able to move my existing content to the new site, and be able to use 301 redirects (permanent move) so I don’t break links from external sites. YES, I can back date the posts, so that the created dates will remain the same for my original content.
  3. Must be able to control the look and feel of the site. YES through templates.
  4. Solution must not be sole source, I don’t want to be locked in to a specific vendor. YES, currently open source, and has a very large community of support.
  5. Must allow me to backup my content, and the comments from users. YES, I can backup the MySQL database.

Picking the solution

As you can see, I went with WordPress for my transitional site, I’m sure the other options could have also worked, and may still end up being my final choice.  But until I’ve finished my requirements analysis for my new site, this will have to do.

Creating a business case for my new website

Over the past few months I’ve been debating resurrecting my old website.   I’ve had some form of web presence since the mid 90s when the best browser out was Netscape 1.1, but about 5 years ago I found I had less and less interest in maintaining a personal site, and between life and a career change, there has been little time for the web development services that I used to provide.   Finally I froze my site in June 2008, and haven’t looked back since.

Today, I decided to apply what I’ve learned over the past few years as a business analyst and see if there is a business case for resurrecting my site.

For this entry, I’m going to follow the recommendations of Prince2 for the content of a business case.

Reasons:

Over the years I’ve built up a reputation at work and with friends as someone that is knowledgeable in web development, project management and business analysis, when searching my name under Google my current site appears on the first page, but is woefully out of date and does not give a good impression of my current skills or knowledge.   So my main reason is pride, I either need to make the decision to update the site, or put it out of it’s misery.

Options:

  1. Terminate my current site. With my current career path, do I need a website at all? Or can I use one of the social media sites such as LinkedIn or Facebook?
    • Pros: little effort, will no longer have to pay hosting costs or domain registration fees.   Already have LinkedIn and Facebook accounts.
    • Cons: I currently have a fairly high Google ranking for my site, showing up on the first page when you search for my name, if I close the domain, and later decide I do need a site, I will have to rebuild my ranking.   If I rely on LinkedIn and Facebook I’m at their mercy of their longevity (remember myspace?), and their rules for content and structure
  2. Patch my current site. Simply update design and technology, but leave the content alone.
    • Pros: little effort, allows me to update my web development skills.
    • Cons: without new content, the site will continue to lose relevance, and will not represent or assist my current career path.
  3. Replace my current site. Update the look, feel, and content of my site to better represent my current career path.
    • Pros: Allows me to update my web development skills, and will allow me to demonstrate, and hopefully improve my skills in project management and business analysis.
    • Cons:  Time, I will need to create and maintain the design, technology, and content for the site.   Cost, I will need to continue paying hosting and domain registration fees, and there may be additional costs depending on how I choice to develop and maintain the site e.g. build, buy, customize, or hybrid.

Expected Benefits:

I believe there are three expected benefits that drive the creation of any type of publication: financial gain, recognition, and/or knowledge:

Financial gain: do I want to make money, either directly by selling products or services, and/or indirectly by gaining an audience and recognition, and then generating profits through advertising, speaking engagements, associated publications, and/or merchandising.

Increased recognition: of myself, or an idea I believe in, do I want to be noticed, become a leader, or share my thoughts, actions or ideals, either for the benefit of my ego, or from a belief that others could benefit from what I know?

Increased knowledge: do I want to harness the knowledge and experience of others for my personal improvement and enjoyment.

For my analysis I’m using the Prince2 definition of a benefit as “any measurable improvement that is perceived as an advantage”.

Currently, my main interest is knowledge, next, by creating a site instead of simply commenting on other sites, I hope to gain some recognition, and yes, eventually I hope for financial gain.

Expected Dis-Benefits:

This is a term prince2 came up with, it’s awkward, but at least it’s clear.

Time involvement: this site will take away from my personal time.

Costs:

There will be the fees for hosting and domain registration, otherwise, the major cost will be in terms of my personal time.  The time for the content will be the most significant, and I have enough technical skill to either develop my own design and technology, or tap into the free/open source community without of having to purchase a solution.

Major Risks:

There is little risk to increasing my personal knowledge, but there are several major risks associated with both recognition and profit by creating a website.

  • Success, if the site is successful, the time requirements (reviewing and responding to comments) and hosting costs (bandwidth) could become excessive.   This risk will not be mitigated, the benefits of success out weigh the negatives.
  • Audience hijacking, if I succeed in getting recognition, it is possible that I could also gain the notice of groups that want to hijack my audience for their own benefit, anything from spamming advertisements, or code injection, to trying to take over the entire site.  This risk can be mitigated through best practices and the implementation of captcha  or a review process for comments.
  • Profit sharing, if I succeed in generating a profit from the site, and the success of the site is in part due to the site’s contributors, will the contributors request a portion of the profit?  This risk can be mitigated by the creation of a terms of use for my site, clearly describing the rights of contributors.

Based on these options, my current decision is to split the work in to multiple projects, the first to put a transitional site, which will provide the minimum solution replace my current site, and provide a forum for the discussing new topics, and so I can also discuss options for the long term solution as they are developed, and then any additional projects to actually build the long term solution.

I don’t want to plan to far ahead for the simple fact that I’m not fully committed to the project yet, so in my next entry I will plan out the tasks that will give me a better idea of the scope of this project.

CFSelect: getting ‘bind’ to work with selected values

Problem addressed

This article provides a workaround allowing you to specify the selected items for cfselect when using the new AJAX bind function.

Solution

My example is a modification of the cfselect example taken from livedocs:

Upload fixColdfusionAjax.js to your site, and call the file using the script tag

<head>
 <title>your page</title>
 <script src="/{path}/fixColdfusionAjax.js></script>
</head>
<cffunction name="getValues" access="remote">
 <cfscript>
  VAR LOCAL = structNew();
  LOCAL.array = arrayNew(2);
  LOCAL.array[1][1] = "0";
  LOCAL.array[1][2] = "-- relationships --";
  LOCAL.array[1][3] = false; // not selected
  LOCAL.array[2][1] = "1";
  LOCAL.array[2][2] = "author";
  LOCAL.array[2][3] = true; // selected 
  LOCAL.array[3][1] = "2";
  LOCAL.array[3][2] = "publisher";
  LOCAL.array[3][3] = true; // selected (can have multiple values selected)
  return LOCAL.array;
 </cfscript>
</cffunction>

I will show a live example once I migrate this site to CF 8

Background

I’ve been slowly working on a new version of this site, and as part of the back end I wanted to use Coldfusion’s new AJAX features for <CFForm>.

I quickly discovered that for some really bizarre reason, when you use the “bind” attribute to get the values for an option list <CFSELECT>
you can’t indicate which options are selected.

I searched the net and found some work around’s by Todd Sharp
and Ray Camdem but they seemed a bit awkward to me.

So, I decided to take a look at Coldfusion’s AJAX javascript. After some digging I found out the problem was really simple to fix.

I’ve created the file fixColdfusionAjax.js, that contains JavaScript that over-rides a function from Coldfusion’s cfajax.js code library to add support for selecting options

Determining what browsers to support

I started designing sites in the mid 90s, and know how to create layouts on many of the older browsers. The question is do I need to anymore?

I want my site to be functional on all browsers capable of supporting HTML 2.0 (the first official standard).

I define functional as capable of achieving an intended purpose, in the case of this site, the purpose is conveying information to a user.

But I want this site to more than functional, I want it to be enjoyable to use and visually appealing. Unfortunately all browsers are not equal, so I need to determine which browsers I should make an effort to provide with an enhanced version of my site, and which browsers will be served a minimal, but still fully functional version.

Luckily I have a friend who can give me a copy of the browser usage statistics for Environment Canada’s
WeatherOffice website, perhaps one of the most widely used, general audience websites in Canada. (who doesn’t check the weather?)

Statistics

During a 1 week period in June 2008, the site received 9,220,090 unique sessions and 560,016,029 hits.

2,520,877 (25%) of the sessions were generated by sources that did not provide any browser information. This is the strongest argument I’ve seen for not using server side browser detection.

The following tables shows the browser usage based on both sessions and hits. I’ve taken out any stats from bots and data scraping services (mget, ColdFusion etc.), or where the browser name wasn’t provided.

Browser Statistics sorted by browser
Browser Sessions Hits % Sessions % Hits
BlackBerry 4.x 43837 188943 0.70% 0.04%
Camino 1.x 3054 124852 0.05% 0.02%
Firefox 3.x 105234 5659781 1.67% 1.09%
Firefox 2.x 1278739 67244027 20.32% 13.00%
Firefox 1.5.x 9343 552669 0.15% 0.11%
Firefox 1.0.x 6042 302606 0.10% 0.06%
Internet Explorer 7.x 2891272 263756941 45.94% 51.00%
Internet Explorer 6.x 1281147 151078184 20.36% 29.21%
Internet Explorer 5.5.x 6665 380050 0.11% 0.07%
Internet Explorer 5.0.x 11531 943658 0.18% 0.18%
Internet Explorer 4.x 1915 103569 0.03% 0.02%
Konqueror 3.x 1998 145516 0.03% 0.03%
Lynx 2.x 5023 93375 0.08% 0.02%
Mozilla 1.8.x 8486 405939 0.13% 0.08%
Mozilla Compatible Agent 5.x 152894 3305201 2.43% 0.64%
Mozilla Compatible Agent 4.x 25947 1982971 0.41% 0.38%
Mozilla Compatible Agent 2.x 60103 665915 0.96% 0.13%
Netscape 8.x 2258 342230 0.04% 0.07%
Netscape 7.x 19354 1136969 0.31% 0.22%
Netscape 4.x 3054 95394 0.05% 0.02%
Opera 9.x 32912 2648685 0.52% 0.51%
Opera 7.5.x 2399 55305 0.04% 0.01%
Safari 525.x 264615 12089821 4.20% 2.34%
Safari 523.x 32868 1443125 0.52% 0.28%
Safari 419.x 23912 1374575 0.38% 0.27%
Safari 312.x 18839 1059306 0.30% 0.20%
Totals: 6293441 517179607 100% 100%

Analysis

Do not interpret these percentages as absolutes. Caching, proxies, support for cookies, browser spoofing, etc. all influence these numbers. That said, given the size of the data set the weights are still pretty heavy in favour of certain browsers.

  • ~99% of the visitors to the site are using browsers that have reliable XHTML and CSS level 2 support either directly or through known workarounds.
  • ~2.5 million sessions did not provide any browser information, so I should not use any server side browser detection based on the user agent string.
  • Based on the differences between sessions and hits, it would appear that IE makes many more server requests compared to the other browsers, a possible caching issue?
  • IE 5.x and 6.x are still widely used and their known quirks will need to be supported.
  • Looking at the IE 5.x stats in detail, I found that usage of MAC IE 5.x was down to 0.08% of all the sessions.
  • Some people are still using Netscape 4, and IE 4, so I will still need to hide javascript and hide css from these browsers, and carefully format my XHTML to prevent crashes.
  • Handheld browsing is making steady gains (blackberry stats)

Decisions

Based on the above analysis I feel comfortable that designing to standards (XHTML, CSS2)
will allow me to provide a visually pleasing experience to the majority of visitors to my site.

  • I will no longer provide table layouts for older browsers.
  • I will no longer create layouts for Mac IE, Netscape 4, or IE 4. Users of these browsers will recieve unstyled content.
  • I will continue to create custom stylesheets for WIN IE 5.x/6.x+ (to deal with their unique quirks). All other
    browsers will recieve a standard stylesheet or recieve no style sheet at all.
  • I will continue to test my site under Mac IE, Netscape 4 and IE 4 to ensure that they do not crash.
  • I will create a handheld layout.
  • I will not use server side browser detection.

The following table lists the different features I plan to use for my site layout (this list may grow as I design my site), and based on the previous table, the approximate percentage of users that are using a browser that supports the feature.

Support for browser features
Feature % Users Browsers
position:fixed 75% IE 7.x,Safari,Firefox,Opera 7.x+, Netscape 7.x+
position:fixed (hacked) 95% IE 5.x+,Safari,Firefox,Opera 7.x+, Netscape 7.x+
png 24bit alpha 75% IE 7+,Safari,Firefox,Opera 7.x+, Netscape 7.x+
png 24bit alpha (hacked) 95% IE 5.5+,Safari,Firefox,Opera 7.x+, Netscape 7.x+
png 8bit alpha ? ?

Browser Specific Stylesheets

Problems addressed

  • How to Use Different CSS Style Sheets For Different Browsers
  • Dealing with Inconsistencies in how Cascading Stylesheets are rendered by different browsers
  • Older browsers crashing when trying to load and render modern stylesheets

Solution

I have used conditional comments and avoided CSS hacks as much as possible to prevent future compatible issues.

I have found that the majority of browsers support font, colour, and absolute positioning fairly consistently,
so I created a shared.css that contains features that will work with all browsers,
with style sheets below extending the shared stylesheet as required (@include:url…).

00 <style type="text/css">
	@import url('/_site/basic.css'); // must be single quotes
	</style>
01 <!-- WIN IE Style Sheets -->
02 <!--[if IE]>
03  <![if gte IE 5.5]>
04   <![if gte IE 7]><link rel="stylesheet" 
	type="text/css" media="screen,projection" 
	href="/_site/ie_win_7x.css" />
	<![endif]>
05   <![if lt IE 7]><link rel="stylesheet" 
	type="text/css" media="screen,projection" 
	href="/_site/ie_win_5.5x_6x.css" />
	<![endif]>
06  <![endif]>
07  <![if lt IE 5.5]>
08   <link rel="stylesheet"
	type="text/css" media="screen,projection" 
	href="/_site/ie_win.css" />
    <![endif]>
09 <![endif]-->
10 <!-- Everything else -->
11 <!--[if IE]><![if !IE]><![endif]-->
12  <!-- standard : Sam Foster's comment hack (hide from MAC IE) -->
	<style type="text/css" media="screen,projection"> 
	/*\*/ @import url("/_site/standard.css") all; /**/
	</style>
13  <!-- MAC IE : Tantek &##xC7;elik comment hack (only for MAC IE) -->	
	<style type="text/css" media="screen,projection">
	/*\*//*/ @import url("/_site/ie_mac.css"); /**/
	</style>
14 <!--[if IE]><![endif]><![endif]-->
15 <!-- Netscape 4.x Style Sheets (because I can) -->
	<script type="text/javascript">
	<!--//--><![CDATA[//><!-- 
16 if(document.layers) { 
	document.write(unescape('%3CLINK%20href%3D%22
	/_site/netscape-4x.css%22%20rel%3D%22
	stylesheet%22%20type%3D%22text/css%22%20/%3E')); }	
17 //--><!]]></script>
  • Basic CSS: line 0
    • uses the @import to hide the style sheet from Netscape 4.x browsers
    • this is the only stylesheet loaded by WIN IE 4.x and MAC IE 4.x
  • Windows IE: lines 1 to 9
    • used downlevel-hidden conditional comments to hide WIN IE style sheets from non-WIN IE browsers and WIN IE 4.x or less
    • used link instead of @import to prevent the IE rendering issue (annoying flash of unformatted content)
    • Lines 3 to 5. I like to use PNGs with alpha transparencies in my layouts and support for PNGs in WIN IE has be ‘unique’ to put it mildly.
      Before WIN IE 5.5 there was no support, WIN IE 5.5 and 6.x provided support using proprietary ‘filters’, and WIN 7.x finally provided native support,
      so I had to create seperate stylesheets for these 3 ranges, e.g. pre 5.5, 5.5 to 6.x, and 7.x
  • Other Browsers: lines 10 to 14
    • used downlevel-revealed conditional comments to hide all non-WIN IE stylesheets from WIN IE 5.x + browsers. (lines 11 to 14)
    • used CSS hacks to filter for MAC IE 4.x/5.x and WIN IE 4.x, luckily these are dead browsers, so this isn’t going to be fixed, but there may be an issue with one of these hacks if a new browser is release with the same bug, but the risk is low
  • Standard: line 12
    • used Sam Foster’s comment hack to hide my standard style sheet from IE Mac,
    • used the media ‘all’ hack to hide from WIN IE 4.x.
    • used the url double quote bug to hide from IE MAC 4.x.
  • MAC IE: line 13
  • Netscape 4.x: line 15 to 17
    • used @import to hide non-WIN IE stylesheets from Netscape 4.x
    • used Javascript to load the stylesheet for Netscape 4.x (Netscape 4.x only renders stylesheets when Javascript is turned on).

Background

Fortunately browsers are moving to more consistent implimentation of standards (e.g. IE 7), unfortunately not everone has updated to the latest versions.

The browser wars are ending, but there are still the old browsers of the 90s and early 2000s that some people still use,
and the bane of my existence IE for the Mac (come on Mac people, switch to Safari or Firefox already).

This all started when for the weatheroffice website I had to find a way to use CSS for layouts, avoid javascript, provide static pages (no server side detection of browsers allowed due to load on the servers), and pass W3C CSS, and XHTML strict verification.

The end result is that my standard.css stylesheet is the default stylesheet for my site, with the other non-standards browsers recieving what they need to deal with their ‘quirks’.

Portable Network Graphics (PNG)

Problem addressed

Using Portable Network Graphics (PNG) as content in IE

One of the most annoying problems designers run in to for Win IE is it’s apparent lack of
support for PNG Alpha transparencies. I say "apparent" because there is a way to display
PNG’s properly in WIN IE 5.5+, it’s just not quite automatic.

Solution

For this I rely on JavaScript to modify the page’s Document Object Model (DOM) to replace <img> tags
with <span> tags with the above AlphaImageLoader filter applied as an inline style, with
the original PNG file as the source. The width and heigth defaults to the files actually width and height unless set in the style sheet.

01 function sf_applyPNGFilter() {  
02  if(document.all&&document.getElementById
	&&(navigator.userAgent.lastIndexOf('mac')==-1)) {
03   for(var i=0; i<document.images.length; i++) { 
04 	// loop through all the images on the page looking for PNG files.
05    o_image = document.images[i];
06    $imageName = o_image.src.toUpperCase();
07    if ($imageName.substring($imageName.length-3, $imageName.length) 
	=="PNG") {
08	/* if the image ends in PNG convert it
09	You will need to re-apply the filter any 
10	time you dynamically add content that contains a PNG file, 
11 	so if the PNG filter has not already been applied to an image, then apply it. 
12	*/
13     if(o_image.style.cssText.indexOf('AlphaImageLoader') == -1){
14      $imageID = (o_image.id) ? 'id="' 
	+ o_image.id + '" ' : '';
15      $imageClass = (o_image.className) ? 'class="' 
	+ o_image.className + '" ' : '';
16      $imageTitle = (o_image.title) ? 'title="' 
	+ o_image.title + '" ' : 'title="' + o_image.alt + '" ';
17      $imageStyle = (o_image.style.cssText) ? o_image.style.cssText + ';' : '';
18      o_image.outerHTML = '<span ' + $imageID + $imageClass + $imageTitle
	+ ' style="' + $imageStyle 
	+ ' width:' + o_image.width 
	+ 'px; height:' + o_image.height + 'px; '
	+ 'filter:progid:DXImageTransform.Microsoft.'
	+ 'AlphaImageLoader(src=\'' + o_image.src + '\');">'
 	+ '</span>';
19      i = i - 1;
20     } //if
21    } //if($imageName...)
22   } //for
23  } //if(document.all...)
24 } //sf_applyPNGFilter
25 // only run this on IE Win, 
	put script call inside of an IE 
	Downlevel-hidden conditional comment for extra security 
if(document.all&&document.getElementById&
&(navigator.userAgent.lastIndexOf('mac')==-1)) 
window.attachEvent("onload", sf_applyPNGFilter);

To make sure this is only runs on WIN IE 5.5+, I place the calling <script> tag inside of a
Downlevel-hidden conditional comment statement.

<!--[if gte IE 5.5]> 
  <script src="/_interface/_javascripts/imageobjectpng.js" 
		type="text/javascript" defer></script>
<![endif]--> 

Portable Network Graphics (PNG) in IE”

Problem addressed

Supporting Alpha chanel transparency in IE using CSS

Solution

As of IE 7.x you no longer need to use filters to support PNG Alpha Channels.

01 div##wantfancypngbackground {
02 /* turn off any current background image in place 
	for other browsers, typically the png */
03  background-image:none; 
04 /* reload the image using WIN IE's proprietary filter */
05  filter: progid:DXImageTransform.Microsoft.AlphaImageLoader
		(src="image.png", 
		sizingMethod="crop|image|scale");}
06 /* sizingMethod: 
07  crop: clips the image to fit the dimessions of the object.
08  image: Default.  Enlarges or reduces the 
	border of the object to fit the dimensions of the image.
09  scale: Stretches or shrinks the image to 
	fill the borders of the object */

Background

One of the most annoying problems designers run in to for Win IE is it’s apparent lack of
support for PNG Alpha transparencies. I say "apparent" because there is a way to display
PNG’s properly in WIN IE 5.5+, it’s just not quite automatic.

For PNG images that are part of the sites content, I rely on JavaScript to modify the page’s Document Object Model (DOM) to replace <img> tags
with <span> tags with the above AlphaImageLoader filter applied as an inline style, with
the original PNG file as the source. The width and heigth defaults to the files actually width and height unless set in the style sheet.

‘Streaming’ Flash FLV video using Coldfusion, PHP or ASP

Problem Addressed

Allowing users to jump to any point in a movie without having to wait for the entire movie to download and without purchasing expensive media server software

Solution

  1. Convert you movie file to an FLV file
  2. Run Buraks – FLV MetaData Injector on the file. This will ‘inject’ the byte position of the videos ‘keyframes’ as additional information in the FLV.
  3. Install either:
  4. Select a player:
<cfsetting enablecfoutputonly="NO">
<!--- the function that sends the feed --->
<cfscript>
 function f_StreamFLV(s_file,i_seek) {
 // i_seek = the byte position of a key frame in the video
 var i_position = i_seek;
 var i_buffer = 10000;
 var byteClass = createObject("java",
 	"java.lang.Byte");
 var byteArray = createObject("java",
 	"java.lang.reflect.Array")
	.newInstance(byteClass.TYPE, i_buffer);
 var context = getPageContext();
 var response = context.getResponse().getResponse();
 var flvinstream = createObject("java",
 	"java.io.FileInputStream");
 // take over control of the feed to the browser
 var flvoutstream = response.getOutputStream();
 byteClass.Init(1);
 flvinstream.init(s_file);
 context.setFlushOutput(false);
 try {
  if(i_seek GT 0) {
   // jump to a location of a key frame
   flvinstream.skip(i_seek);
   // output the header bytes
   flvoutstream.write(toBinary('RkxWAQEAAAAJAAAACQ=='));
  }
  do {
   i_length = flvinstream.read(byteArray,0,i_buffer);
   if (i_length neq -1) {
   flvoutstream.write(byteArray);
   flvoutstream.flush();
  }
  }
	while (i_length neq -1);
	// keep going until there's nothing left to read.
 }
 catch(any excpt) {}
 flvoutstream.flush(); // send any remaining bytes
 response.reset(); // reset the feed to the browser
 flvoutstream.close(); // close the stream to flash
 flvinstream.close(); // close the file stream
}
</cfscript>

<!--- set to false to allow the file name
	to be passed, true for a numeric ID --->
<cfset b_secure = true>

<!--- path for the movie --->
<cfset s_path = ...>
<!--- must use the extended path either in the
	form c:/path/file.flv or c:\\path\\file.flv. --->
<!--- the application.root variable is set
	in my application.cfc file,
and gives the absolute path to the root of my site --->

<cfparam name="position" default="0">
<cfif isNumeric(position)>
 <cfset i_seek = position><cfelse><cfset i_seek = 0>
</cfif>

<!--- create an array for possible movies,
or this could read an XML file, or the vidID
could be used to reference a database record --->
<cfset a_movies=ArrayNew(1)>
<cfset a_movies[1] = "##s_path##movie1.flv">
<cfset a_movies[2] = "##s_path##movie2.flv">
<cfset s_file = a_movies[1]> <!--- set the default movie ---> 

<cfif b_secure>
 <!--- I decided to use a file ID instead
	of a file name to make the script more secure --->
 <cfif isDefined("url.vidID")
 	and isNumeric(url.vidID) and url.vidID LTE arrayLen(a_movies)>
  <cfset s_file = a_movies[url.vidID]>
 </cfif>
<cfelseif isDefined("url.vidFile")>
 <cfset s_file = "##s_path####url.vidFile##">
</cfif>
<cfset f_StreamFLV(s_file,i_seek)>
<cfsetting enablecfoutputonly="NOS">

How this works

When you ‘seek’ to a new position in the movie, the player will determine the location of the nearest key frame (as a byte position) and passes that number to the server.

The server opens a file stream to the video, and seeks to the specified position, outputs the standard FLV header bytes, and then starts sending the file starting at that point.

Background

This is the result of a major geekout weekend, the code works, but could probably use some refactoring.

I was trying to figure out a way to stream video fora hobby site I was planning, and I came across an article on streaming flash FLV files using PHP, great I thought, but I use Coldfusion hosting services (no PHP support), I took a look at the PHP script, and it seemed fairly straight forward, but I wasn’t sure how to do a binary stream in coldfusion, some more research and I found Christian Cantrell’s site, with entries on Byte Arrays and Writing Binary Data to Browser putting this together with some java that I know I managed to create a script for Streaming FLV video via ColdFusion.

For the video, I compressed an AVI file (Space Quest promo video) using sorensen Squeeze 3.5, and injected the key-frame position metadata using Buraks – FLV MetaData Injector