Tuesday, July 27, 2010

To Death with Internet Explorer 6/7

As a developer, I am often plagued with one simple question: how will this page look in IE6/7? The answer is, being several years after their initial releases, very simple: bad.

I'm an evolving developer, as most of you (if you are reading this) are. The web is a very transformative application development platform. Every two or three weeks, as it seems, something new is being done with the Web. With the advent of Web 2.0, the way that we design/develop Web applications has dramatically changed -- if not totally replaced -- the methods of yesteryear.

The truth of the matter is that major Web browser vendors (Microsoft excluded) have adhered their development techniques to include the feedback of we Web developers insofar as our individual feedback on how their implementation drastically (or in-drastically) affects our development process. They have, as companies, done the right thing in altering their development road-map to provide us with a more standardized way of creating and implementing a better user system.

The simple reality is, from the "John Doe"-user perspective, that user agents (AKA browsers) should be hand-picked based on their features, not their implementation of -- what should be STANDARDS-BASED -- HTML, CSS, and JavaScript.

So why the big fuss about Internet Explorer? Well, going back almost a decade (at least), Internet Explorer was the de-facto web browser of the common surfer. Window has always been an integral part of computing, in general. Internet Explorer, being a base application in Windows, has thusly always been involved. Considering that roughly 70% of the world population -- in computer terms -- uses Windows, IE is a relevant platform. Considering that people don't like to change their habits (again, speaking in general), if they are used to IE, then IE is where they'll stay.

So, we developers are constantly faced with having to make our applications more usable. No one likes to see "This site doesn't work with IE," notices. They see that and, generally, they exit the site in an expeditious manner or just deal with the inconsistencies. Knowing that, we are faced with design/development alternatives from all other browsers into IE.

As one person stated (I'm a little too tired for direct linking), 20% of a Web developer's time (and money) is spent on making an application work on sub-8.0-releases of IE ... which brings me to my point: Why standardize a Web application for an out-dated system? The answer is, shockingly, very simple: We shouldn't.

Why? Not only are IE 6 and 7 outdated, but IE 8 comes as a "critical" upgrade in Windows. Microsoft realizes that -- if things keep going the way that they were -- they will lose at least half of their audience if they don't make their experience more comfortable. Those who continue to stick with Windows versions that are outdated generally don't apply to this post. They don't surf the web much and, if they do, don't particularly care about whether their application works as it is supposed to so long as it just ... works. Most intelligent developers provide a backwards-compatible way to view the Web (i.e. text only). That accounts for most of their techniques. Providing content for IE 6/7 should not deviate from that principal. Those browsers should be considered the same as incompatible versions of, per se, Mozilla, Firefox, Safari, Opera, Netscape (dead and gone), etc.

The problem too much with IE 6/7 is that they rely solely on various vendor-specific CSS, JavaScript, and DOM implementations. Nothing renders the way it is supposed to.

All of this jabbering and I've still yet to actually answer my one question: Why continue to develop for a browser that is dead and gone? The answer: Don't. Internet Explorer versions previous to 8.0 are years (if not decades) old. Most of the audience we developers -- as well as our clients -- care about (approximately 70% of the Web) have upgraded to 8.0 because it is flagged -- by Microsoft -- as a 'critical' upgrade from previous versions. Almost all users will regard a 'critical upgrade' from the vendor as law. That said, newer versions of Windows (i.e. Vista Service Pack 1 and Windows 7) include IE 8. Most (intelligent) Windows users will (would have) upgrade(ed). So, the days of developing for a long-dead system have come and gone.

Saturday, January 16, 2010

I just have to say ...

It is truly remarkable what a little HTML, CSS, and jQuery can accomplish. jQuery is an outstanding JavaScript library meant to help in DOM manipulation. I'm working on a few jQuery plugins meant to enhance the user interface. These plugins will be generally available as soon as I have them finished to my liking.

I just wanted to comment on how much I love jQuery. You can find it here: jQuery - the "write less; do more" JavaScript library.

Friday, November 6, 2009

Mass Hysteria

About a year ago, give or take, I heared something that was rather intriguing to me. Someone in my family made mention that Nostradomus had predicted the end of the world. Considering that I had heared the claim before, I simply dismissed the divulge as blind ignorance and proceeded to go my way. But I was quickly stopped in my tracks when the next thing that was muttered entered into my ears. "This prediction also coincides with the Mayan's long-count calendar coming to an end," the person said.

I thought to myself, "Oh, really? Is there something to that?" The person continued the information to me with the percieved date: December 21st, 2012. That was all I needed to do my research.

You must understand, before I continue, that I have done a lot of research on a lot of different topics ranging from Biochemestry to Inter-Stellar Travel to Web development (my current profession) to Social Sciences to Dark Matter and everything else in the spaces between spaces. I find great enjoyment in expanding my ever-widening knowledge of events, theories, logistics, skillties, and so on. I spent a great deal of my free-time researching just about anything that peeks my interest. Yes, I've even researched sexuality. To wrap it up, I'm a think-tank and an enthusiastic learner. You may as well go ahead and label me a nerd because that's exactly what I am.

The point is, I'm not one to simply dismiss an idea, theory, or concept lightly. I do cover all of my grounds. So, when the date reached my ears, I figured, "What the hell; it could be true."

I'm not complaining about the many hours (weeks) I spent on researching the topic (I still do, from time to time), but I am complaining that it was all for nothing. Well, maybe it wasn't all for nothing. I did learn a great deal about certain events that have and will take place, not necessarily bringing about the "end of the world" as these "predictions" justify. The truth is that I enjoyed the time spent researching this idea.

So, what follows here on out are my remarks on the whole "2012" mass hysteria.

Going back into my research, I decided to start with the date bestowed on me: December 21st, 2012. Wow, that returned approximately 11,100,000 results. The most notable thing about this date is the way it is written. If you write it in standard American abbreviation, you come up with 12-21-12. The numbers, as you can see, are reversible. This poses a common problem. Many of the world's previous "end of times" scenarios revolved around reversible dates. Namely 06-06-06 which translates to some to be "666", the number of the beast. That's where I believe this whole phenomena started. So, jumping right into it, I'll make my points.


Firstly, if the "sensitive" or "top secret" information that people seem to be divulging were so "sensitive" or "top secret", the United States Government, as well as other countries around the globe, would have taken measures to silence those individuals/groups. Consider the movie "The Core". Although it was a fictitious Hollywood portrayal of "what if"s, it does exact one key point: the governments of the world would take any and all measures to keep an event such as this from going public. In that case, they had a "best of the best" hacker control the flow of information on the Internet. Specifically, his job was to wipe out any mention of their project or end-of-the-World scenarios online. Another movie, "Armageddon," as well as "Deep Impact," also portray the government's efforts to conceal the event until such time as it can be addressed and dealt-with properly. My point is that (not to be too dramatic) the governments of the world would go to any great length to erase the information that these incredible individuals share - up to and including assasinating them - if it were, indeed, threatening information.

We have seen this kind of thing before, so it's not so far-fetched as I'm sure some readers are bound to dismiss it as.

My next point turns over to these so-called images and videos depicting one of the cataclysmic antagonists of the "2012" event. Surrounding the "2012" phenomena is a planet dubbed "Planet X" or "Nibiru". One thing is fact about Nibiru (that's what I'll refer to it as from here on out) is that ancient Sumarians believed in its existence as well as the existence of its inhabitants - the Anunaki. There is scientific evidence of depictions and writings carved into Sumarian tablets, statues, obelisks, temple walls, etc. Now, whether Nibiru was an actual planet, a representation of the "Heavens" (which, Sumarians did write about), or simply a representation of the state of belief is truthfully unclear. We can merely interpret what they wrote. The Anunaki, on the other hand, were what the Sumarians believed to be "angels" or "God-like beings". This much is clear and is documented in several credible texts.

Back to the depictions this point was meant to debunk, I'd like to address that at least ONE government official and ONE head-of-the-flock scientist/astronomer, if these images and videos were in fact real, would condone the validity of the said depictions. I'm not talking about some low-ranking, retired offical. No, I'm talking about someone whom is already in the main stream - per se the President of the United States or Stephen Hawking - and is credible. When Jimmy Carter claimed, in public, that he had witnessed a UFO, the American - indeed the world - population started to question, "Are we really alone?" And, from that, many more government officals came forward with their testimonies that they, too, had seen UFOs or had direct contact with an alien craft or, indeed, an alien. Now, agencies such as NASA are investigating these, as well as other, claims. (I am not advocating that UFOs are, in fact, real, I'm simply stating the significance of involvement by figureheads in the community whom do advocate the existence of UFOs.)

Going back to the first point, if this information was indeed sensitive, the governments of the world would do their part in destroying the information (i.e. the videos and pictures). Alas, those mockeries are still aplenty (not-to-mention annoying).

Another piece of the picture puzzle is the abundance of video and photo editing software available on the market. Everything from the high-priced Adobe line to the low-end Ulead line, not-to-mention the integrated Windows and Mac OSX software available, are capable of handling the simple video and photo manipulation that takes place in those mediocre-at-best videos and photographs. It isn't difficult (give me about twenty minutes or so on any 4-minute video and I'll have you convinced you're looking at Nibiru) to do what these amateurs do with said media.

To make my third point, I'd like to stay on the Nibiru track. Nibiru, as I said, is a highly hypothetical planet. It is said that this planet is on a dual orbit around our Sun and another star out beyond the Kupier Belt. That would, in theory, put the furthest position of Nibiru in the 467AU range (one AU (astronomical unit) is about 93 million miles) from our Sun. The closest distance to its own parent star is said to be about 60AU which is almost twice the distance as Neptune is from our Sun (30.06AU). At such a distance (we know that both Neptune and Pluto are ice cold), how can we say that Nibiru would be a habitable enough planet to support life, which is the claim that interpreters of Sumarian text - notably Zecharia Sitchin - is the home planet of the Anunaki (previously mentioned).

It is also proposed (as outlined here) by Andy Lloyd that Nibiru and its parent star both orbit our Sun and that Nibiru orbits between those two stars as their star orbits ours (that sounds rather complicated, although he does - while I don't agree - explain in understandable detail his theory).

I'm actually kind of skipping off subject, here. Nibiru having inhabitant life doesn't tie into the whole "2012" phenomena, which is the basis of this topic. However, the planet's existence - if it does exist - itself does tie into the theory. It is alleged by "2012" enthusiasts that Nibiru may impact Earth or come close enough to Earth to wreak havoc on its inhabitants. However, I propose that if Nibiru even existed, it would have either collected planets in our solar system and added it to its own; upset the asteroid belt in our solar system; or caused other unseable problems with our own system. Not only that, but again, notable people would have made discoveries and released such information to the public already.


Having made all of those points debunking "2012" theorists, I do have a few points that may be of interest to anyone who has made it this far in this article.

There are a few things you should consider before making your own judgments on the matter. One event that could have effect on us is the crossing of our solar system over the galactic equator. The Galactic Equator is a plane that slices our galaxy - the Milky Way - in half along its planar center. If you know anything about the cosmos, you know that almost all galaxies (not all, but a large portion) are disc-like in shape. They are flat and circular-ish. The Milky Way is a spiral-class disc galaxy. It follows the same pattern, but has arms that extend out. Think of it sort-of as a really big hurricane, except that in the "eye" is a large concentration of stars, gasses, and bodies of hard matter. Our solar system rests at the tip of one of the arms that extend from the center. If you take a cross-section of our galaxy and draw a straight line through it (from left to right), you have the Galactic Equator. What significance does the Galactic Equator have? Well, simply put, it is the gravitational epicenter for the X plane of the Galaxy (3-dimentional spaces have three planes: the X (left to right; width), Y (top to bottom; height), and Z (forward to back; depth)).

Our solar system is on a wavy path that moves, along the Y axis, below and above the X axis of the Milky Way galaxy - the Galactic Equator. From peak (top-most of a wave) to the trough (bottom-most of a wave), it takes about 3,600 years for our solar system to complete its movement. Some time between the years 2008 and 2015, our solar system will cross the exact center of the X axis of our galaxy. Remember, I said that the GE is the "gravitational epicenter" for our galaxy. What that means is that gravity in our solar system will be at an all time high (for our lifetimes) and could disturb planetary orbits - for any or all planets - as well as astroidal orbits in objects floating in both the asteroid belt (between Mars and Jupiter) and the Kuiper belt (beyond Pluto). Not only that, but it is agreed by many that the Earth, as well as a couple other planets, will be between our Sun and the Galactic Center (center of orbital gravity in a galaxy; not to be confused with the Galactic Equator). That means a direct "argument" between the gravitational forces of the Sun and the Galactic Center (all the stars, hard matter, gasses, etc. in the center of our galaxy) which will be fighting for the orbit of our planet as well as the orbit of other planets and other asteroid/meteors. It is believed that the mass of the Earth and, indeed, other planets in coincidence with the relatively close orbit to the Sun that the Sun's gravitational pull will outweigh that of the distant Galactic Center of the Milky Way. However, the smaller objects, namely the asteroids and meteors in the aforementioned asteroid and Kuiper belts are almost free-floating in which the Galactic Center could win the battle. What that means is that several small, free-floating objects could be, in turn, thrust into Earth and other planets, not to mention the posibility that the moon itself could have its course altered. This, in turn, could be catastrophic. Considering that the Sun should be blocking most objects that could threaten the Earth - remember, we'll be between the Sun and the Galactic Center - it is unlikely that such an event could occur. It is, however, possible.

Another possibility is that any change in the Earth's orbit could increase or decrease the Electromagnetic Field. If the Earth's rotational speed slows or hastens, the EM Field could weaken or strengthen respectively. A change in gravitaional pull, on either the Sun's or the Galactic Center's part, could trigger this event. If the Earth's EM Field weakens, interstellar particles or solar winds (a lethal combination of dust and microwaves (radiation)) could leak through which could, in turn, literally boil our planet. If the EM Field strenthens, our healthy dose of Solar radiations (specifically solar light) will decrease, causing winters to be longer and more harsh and summers/springs to be much more wet and cold. Also, plants/animals would not have enough vitamin C (provided by our Sun) to sustain life and would, thus, decrease and, eventually, go extinct. We humans would have to embrace other, more harsh means of survival. I'd hate to imagine what that means. I'd like to turn your attension over to what happened to the dinosaurs: a metorite struck earth throwing up a suffocating blanket of ash and dust that the Sun was powerless to penetrate causing animals in general to die off because they hadn't enough plants to survive (which also ties in to the "throwing asteroids/meteors around" theory outlined above). Moving through the Galactic Equator may increase/decrease our rotational speed.

Another effect of moving through the Galactic Equator may be a polar shift. A polar shift is when a planet tilts further on its axis. Right now, the Earth sits on a 23° axis. If the Earth had a polar shift, it could move from, per se, 23° to 33°. In essence, that could put the US right in the center of the North Pole and, again per se, Alaska right on the Equator. Imagine what that could do. The US would freeze over - rapidly - and the former North Pole's iceburgs would melt - again, rapidly. That would basically kill all life adapted to the North American climates as well as dramatically raise the global water level (creating massive tidal waves and Tsunamis). Though, that is just the beginning of the possible effects and the idea of a polar shift is still rather abstract. It has happened before on our planet as well as others. However, it is not a definite "going to happen" event.

More information about the Galactic Alignment can be found here. Although this video was meant as a factual, informative video, it has been used by many to "justify" their beliefs.

One other possible theory, which most of us may be aware of, is that of a climate shift. For many decades, if not centuries, natural and unnatural gasses in the atmosphere have caused Earth's climate to steadily heat up. What happens is those natural and unnatural gasses disallow heat - provided from our Sun - to dissipate from the Troposphere (innermost part of the atmosphere) and out through the Exosphere (outermost part of the atmosphere). The Earth requires a delicate balance between hot and cold to maintain its climates. Naturally, this disallowance of heat dissipation causes heat to centralize in certain areas and spread out, causing other areas which should remain cold to rise in temperature over time. This steadily increasing global temperature causes ice concentrations - particularly in the North Pole and in Antartica - to melt. This is called "global warming"; the effect itself is known as the "Greenhouse Effect". The induction of fresh water, that stored in glaciers in the aformentioned polar regions, into the central North-Atlantic Current - which requires a very delicate ballance between fresh and salt water in association with cold and hot winds sweeping the water - is disrupting the salt water content and, thus, doesn't retain as much heat as it was meant to. Now, that current is moving more and more cold air into the areas that should be warmer which, in turn, pushes hot air into those areas that should remain cold. What that does is increases the water level due to all of the ice that is melting in the polar caps. (That was a rather recursive little paragraph.) If the water levels increase too dramatically, it will cause the North-Atlantic Current to alter its course and will cause large super-storms to form. Those super-storms could bring super-cool winds from the upper Troposphere (-247°F) to reach the Earth's surface. When, and if, that happens, we're talking about a major shift in planetary climates - no more t-shirts and shorts. All plants and animals that were geared towards relatively warm climates would not be able to survive such a dramatic decrease in temperature and would, thus, perish.

For that possibility, the governments of the world - spearheaded by our own - are working together to form a new, renewable, clean form of energy based on that the Sun naturally provides: fission. That, in itself, is another article.


With all of that information in hand, I'd like to conclude with saying that while there are several posibilities - not to mention the ever-famous (or infamous, depending on your point of view) Biblical "Armageddon" (the battle between Heaven and Hell; God and Satan) - nothing is set in stone. No one has the wisdom, right, or knowledge to say, with any amount of factual certainty, that the world will end on any given date. The simple fact that the Mayan Long-Count Calendar comes to an end on a given date has nothing to do with the life-span of our planet. If the world does come to an end, it will do so on its own time, not our predicted time.

In the mean time, I believe that whomever believes all the crap surrounding December 21st, 2012 you are either in for a rude awakening, are stupid, or need to schedule yourself a CAT scan or psychological evaluation.

Friday, June 19, 2009

Well...

A few days ago, I started drawing a picture for one of my fellow co-workers. She's quite a gorgeous young woman and thought she'd make an interesting angel (I have a thing for winged creatures). To my amazement, the drawing is turning out quite well. I've definitely topped myself.

The piece is being done on 16.5" x 14" paper using pencil and ink. The ink is more-or-less for the outlines while the pencil is used to (obviously) sketch the work, butt also for shading. I don't use hatching for shading; I use pencil gradients. I thought about potentially adding color, but as she is fairly darkly tanned, I thought the skin-tones would be the most tricky. Besides, my best drawings have almost always been black 'n white.

So far so good, however. I showed her a snap-shot of the work-in-progress and she is VERY excited about it.

It is hers upon completion; it should be done by Monday. For anyone interested, it'll be uploaded to deviantART.com then.

Tuesday, June 9, 2009

Alternative File Input Fields

Introduction


Before I begin, you should know that this method utilizes PHP, JavaScript, xhtml, and CSS. You should have at least an intermediate-level understanding of the said technologies before using this implementation method. Also, before you begin, it is wise to download and install an up-to-date version of the php_browscap.ini file on your server. Without going into much detail, you can find information on the issue here and here. And here's an up-to-date php_browscap.ini.


I have almost never found a need to provide an alternative <input type="file">, but today I found one. The question I had is, "Why do people need to know the path on their own computer to the file they've chosen? Don't they only need to know the file name?" The answer is simple: All they need is the file name as to provide a double-check. So, the problem arose, "Well, how do I then hide the text-box (or label, as is the case in Apple Safari) and only display the file name?"


The Investigation


I searched the web for possibilities. I found a work-around that replaced the file input field with a text box and image, while the input field still remained—although transparent and working. That didn't quite solve my problem as the whole 'file path' thing still remained. I found, using JavaScript, a way to extract the file name and insert that into a by-side label (<div> in this case), but that still didn't solve the 'file path' issue.


So, I did a little case study in Internet Explorer, Opera, Firefox, and Safari (using their default themes, of course, and under Windows Vista). What I did is captured a screen-shot of each browser with the file input field without any CSS. Then I checked their inferred measurements using each client's respective developer tool/DOM browser. What I extracted is the width and height dimensions, as well as the left and top positions of each browser's file input field's 'browse' button. That information could easily allow me to use CSS absolute positioning inside a relatively-positioned element to hide the text-box of the file input field.


The problem was the inconsistent implementation of the <input type="file"> between each Web client. Internet Explorer, in my mind, has the more politically correct implementation, whereas Firefox, Opera, and particularly Safari mangle what I would picture the perfect implementation to be. In Safari's case, they did away with the text-box altogether and included a not-to-spec text label that only includes the file name as well as an icon representing their inferred file type of the chosen file. That was particularly shoddy in my mind, although their reasoning behind the endeavor is dually noted and understood (an attempt to avoid potential security flaws).


For the three aforementioned browsers, other than Internet Explorer, the text displayed on the 'browse' button was also different, as was the type-face used to display the information. That provides more problems: the width, height, left position, and top position would differ between the clients respectively and that change could not programmatically be accounted for. Sure, I could use CSS to augment the type-face and font-size, but that doesn't change the fact that word(s) chosen to represent the word "browse" differed, once again.


So, my only alternative was to dynamically write CSS dependent on each browser, which brings me to my point and the implementation I'm about to provide.


The Solution


A long while back—years, if I remember correctly—I wrote a PHP code class that can determine—using PHP's built-in browser functionality and the php_browscap.ini file—the user agent being used on the client side. I had never found a use for it until now: the dynamic creation of browser-specific CSS, not using JavaScript (as JavaScript is sometimes disabled by over-paranoid users). Note that the JavaScript to be used should be safely ignored by such individuals' browsers and merely only provides access to the label we're going to use to display the file to be uploaded to the user.


The xhtml


So, now we get to the code. Here's a look at the base HTML that we'll use to show the <input type="file">:


<form action="/path/to/action/file.php" enctype="multipart/form-data" method="post">
<div class="fileInputContainer">
<input class="fileInput" id="fileInput" name="fileInput" type="file" />
</div>
<div class=
"fileInputLabel" id="fileInputLabel"></div>
</form>

As you can see, the xhtml is fairly simple in design. Remember: all forms that are to submit files should have an enctype="multipart/form-data" declaration and the method should be set to post, not get.


The PHP Code Class ( HYPONIQS_Browser_Lite )


Now that we have the basic skeleton of the xhtml, we have to decide which browser the user is using and how we're going to display the element in question based on that browser. That's where the server-side PHP code class comes in. Here's a look at that class in its simplistic entirety. A few more browsers are provided than we're going to use, but they are involved so that this class can be used inside third-party development environments (namely Adobe Dreamweaver and ActiveState Komodo) that I use regularly. Anyway, the code:


<?php
// Browser_Lite.php
class HYPONIQS_Browser_Lite
{
private $browserTag;
public $browserInfo;

public $isDreamweaver = false;
public $isFirefox = false;
public $isGecko = false;
public $isIE = false;
public $isKomodo = false;
public $isMozilla = false;
public $isNavigator = false;
public $isOpera = false;
public $isSafari = false;
public $isSeaMonkey = false;
public $isUnknown = false;

public $platform;

public $version;
public $versionMajor;
public $versionMinor;

public function __construct()
{
$this->browserTag = $_SERVER['HTTP_USER_AGENT'];

// we must suppress any errors here (if the browscap php.ini
// directive is not set, it throws an E_WARNING)
$this->browserInfo = @get_browser();

$this->getPlatform();
$this->getUA();
$this->getUAVersion();
}

public function getPlatform()
{
// There is a problem, here: this relies on an up-to-date
// php_browscap.ini file on the server-side. This fails
// if the php_browscap.ini is not up-to-date or if the
// path to the php_browscap.ini file is not set in the
// server's php.ini file.
//
// So, as a precaution, we're going to make sure that the
// $this->browserInfo initialized properly. If so, we can
// get the OS the user is on.
if (is_object($this->browserInfo)) {
$this->platform = $this->browserInfo->platform;

// if not, we'll specify an unknown OS
} else {
$this->platform = 'Unknown Operating System';
}

return true;
}

public function getUA()
{
// this represents the class variable $browserTag to minimize code
$bTag = $this->browserTag;

// Internet Explorer uses the Microsoft HTML (MSHTML) rendering engine
if (strstr($bTag, 'MSIE')) {
$this->isIE = true;

// Opera uses their own rendering engine (unnamed)
} elseif (strstr($bTag, 'Opera')) {
$this->isOpera = true;

// Safari uses the KHTML rendering engine
} elseif (strstr($bTag, 'Safari') && !strstr($bTag, 'Dreamweaver')) {
$this->isSafari = true;

// this is just for GP (General Practice)
// check if Adobe Dreamweaver's internal browser
// could be used with something like "$isContentRenderable = false";
//
// Dreamweaver also uses Apple's KHTML rendering engine
} elseif (strstr($bTag, 'MMHttp') || strstr($bTag, "Dreamweaver")) {
$this->isDreamweaver = true;

// all of the following browsers use the Gecko rendering engine
} elseif (strstr($bTag, 'Mozilla') && (!$this->isIE &&
!$this->isOpera &&
!$this->isSafari))
{
$this->isGecko = true;

// check if Netscape Navigator
if (strstr($bTag, 'Navigator')) {
$this->isNavigator = true;

// this is just for GP (General Practice)
// check if ActiveState Komodo's internal browser
// could be used with something like "$isContentRenderable = false";
} elseif (strstr($bTag, 'Komodo')) {
$this->isKomodo = true;

// check if Firefox
} elseif (strstr($bTag, 'Firefox') && (!$this->isNavigator &&
!$this->isKomodo))
{
$this->isFirefox = true;

// check if SeaMonkey
} elseif (strstr($bTag, 'SeaMonkey')) {
$this->isSeaMonkey = true;

// if all else fails, it's the Mozilla Web Browser (father of Firefox)
} else {
$this->isMozilla = true;
}

// no known browser support
} else {
$this->isUnknown = true;
}

return true;
}

public function getUAStrings()
{
if ($this->isIE) {
$engine = 'MSHTML';
$browser = 'Internet Explorer';
} elseif ($this->isOpera) {
$engine = 'Internal (unknown)';
$browser = 'Opera';
} elseif ($this->isSafari) {
$engine = 'KHTML';
$browser = 'Safari';
} elseif ($this->isDreamweaver) {
$engine = 'Adobe; KHTML';
$browser = 'Dreamweaver';
} elseif ($this->isGecko) {
$engine = 'Gecko';

if ($this->isFirefox) {
$browser = 'Mozilla Firefox';
} elseif ($this->isNavigator) {
$browser = 'Netscape Navigator';
} elseif ($this->isKomodo) {
$browser = 'ActiveState Komodo';
} elseif ($this->isSeaMonkey) {
$browser = 'Mozilla SeaMonkey';
} elseif ($this->isMozilla) {
$browser = 'Mozilla';
}
} else {
$engine = 'Unknown';
$browser = 'Unknown or unsupported';
}

return array($browser, $engine);
}

public function getUAVersion()
{
$bTag = $this->browserTag;
$expression = '';

if ($this->isIE) {
$expression = '/MSIE ([\w\d.]*);/';
} elseif ($this->isOpera) {
$expression = '/Opera\/([\w\d.]*)/ ';
} elseif ($this->isSafari) {
$expression = '/Version\/([\w\d.]*)/ ';
} elseif ($this->isDreamweaver) {
if (strstr($bTag, 'Dreamweaver')) {
$expression = '/Dreamweaver\/([\w\d.]*)/ ';
} else {
$expression = '/Version:([\w\d.]*)/ ';
}
} elseif ($this->isGecko) {
if ($this->isFirefox) {
$expression = '/Firefox\/([\w\d.]*)/i';
} elseif ($this->isNavigator) {
$expression = '/Navigator\/([\w\d.]*)/i';
} elseif ($this->isKomodo) {
$expression = '/Komodo\/([\w\d.]*)/i';
} elseif ($this->isMozilla) {
$expression = '/Mozilla\/([\w\d.]*)/i';
} elseif ($this->isSeaMonkey) {
$expression = '/SeaMonkey\/([\w\d.]*)/i';
}
} else {
$this->version = 0;
$this->versionMajor = 0;
$this->versionMinor = 0;

return true;
}

if (preg_match($expression, $bTag)) {
preg_match($expression, $bTag, $matches);

$subVersions = explode('.', $matches[1]);
$this->version = $matches[1];
$this->versionMajor = (isset($subVersions[0])) ? (int) $subVersions[0] : 0;
$this->versionMinor = (isset($subVersions[1])) ? (int) $subVersions[1] : 0;
}

return true;
}

public function __toString()
{
list ($browser, $engine) = $this->getUAStrings();

$html = '<pre>' . "\n";

$html .= str_replace('/', ': ', $this->browserTag) . "\n\n";
$html .= 'Browser: ' . $browser . "\n";
$html .= 'Browser Version: ' . $this->version . "\n";
$html .= 'Version Major: ' . $this->versionMajor . "\n";
$html .= 'Version Minor: ' . $this->versionMinor . "\n";
$html .= 'Rendering Engine: ' . $engine . "\n";
$html .= 'Operating System: ' . $this->platform . "\n";

$html .= '</pre>' . "\n";

return $html;
}
}
?>

Utilizing this class is simply limited to:


<?php
// include the Browser_Lite.php file
require_once 'Browser_Lite.php';

// instantiate the HYPONIQS_Browser_Lite class
$browser = new HYPONIQS_Browser_Lite();

// check if browser is Internet Explorer
if ($browser->isIE) {
// do something here for Internet Explorer
print 'I am Internet Explorer.';
}
?>

The CSS


Now that we have the PHP code class and the xhtml, here's the CSS we'll be using before augmenting it server-side with PHP:


<style charset="utf-8" media="screen" type="text/css">
div.fileInputLabel {
float: left;
margin-left: 5px;
padding-top: 2px;
}

div.fileInputContainer {

position: relative;
overflow: hidden;
float: left;
/**
* Later, we'll use the PHP code class to dynamically add the
* width and height of the file input container
*/

}

div.fileInputContainer input.fileInput {

position: absolute;
/**
* Later, we'll use the PHP code class to dynamically add the
* left and top position to the file input
*/

}
</style>

The PHP Code Class, xhtml, and CSS Together


Unfortunately, all the "bones"—so to speak—of this tiny application do not have any real grounds separately. We need to put them together for the whole thing to work. A few questions we have first, though.


First off, "What is the width and height of the 'browse' button in each user agent?" The answer is shockingly simple. Through my own investigation, on Windows Vista, that is, the width and height of the 'browse' button is as follows (provided the user agent is using the default UI theme):



  • Internet Explorer

    • width: 79px

    • height: 18px



  • FireFox

    • width: 73px

    • height: 22px



  • Opera

    • width: 72px

    • height: 20px



  • Safari

    • width: 92px

    • height: 20px




Of course, under other operating systems, such as Apple Mac OSX, previous versions of Microsoft Windows, and any Linux/Unix distribution, these dimensions are subject to change. It is likely, however, that they will not be much different.


The second question we have is, "What are the coordinates for the top-left corner of the 'browse' button from the file input element's bounding box?"



  • Internet Explorer

    • left: 156px

    • top: 1px



  • FireFox

    • left: 150px

    • top: 1px



  • Opera

    • left: 133px

    • top: 1px



  • Safari

    • left: 1px

    • top: 1px




As you can see, if there's anything these browsers have in common, it is their top coordinate (this would be on the Y vertices of a plane). Otherwise, each browser has its own rendition of how a file input element should be displayed. That's what we're after.


So, now that we know the dimensions, I'll tell you how this is all aligned, logically speaking. For the most part, the visible area of the file input element will be the button's with by its height. So, we'll use CSS to position the top-left corner of the button with the top-left corner of the containing <div> element. We'll also set the containing <div> element to be equivalent in width and height to the button. This will safely hide all the rest.


There is one other thing I should mention. In Safari, there is an additional 2 pixel margin surrounding the entire <input type="file"> element. Why this is I am uncertain, but it is there. Because of this, we have to account for that additional margin on top and on the left of the element. That's why the object is positioned up and back 3 pixels instead of simply 1.


So, here's a look at the PHP at work:


<?php
// include the Browser_Lite.php file
require_once 'Browser_Lite.php';

// instantiate the HYPONIQS_Browser_Lite class
$browser = new HYPONIQS_Browser_Lite();

// We'll use this variable to decide if the browser being used
// is one we're supporting

$supported = false;

// make sure the browser is one we're supporting
if (
// This example uses Windows Vista; we must make sure the user
// is on Windows Vista

$browser->platform == 'WinVista' &&

// Now we just have to make sure that they are on one of the
// supported browsers

($browser->isIE ||
$browser->isFirefox ||
$browser->isOpera ||
$browser->isSafari)
)
{

$supported = true;
}

// check if browser is Internet Explorer
if ($browser->isIE) {
$width = '79px';
$height = '18px';
$top = '-1px';
$left = '-156px';

// check if browser is Firefox
} elseif ($browser->isFirefox) {
$width = '73px';
$height = '22px';
$top = '-1px';
$left = '-150px';

// check if browser is Opera
} elseif ($browser->isOpera) {
$width = '72px';
$height = '20px';
$top = '-1px';
$left = '-133px';

// check if browser is Safari
} elseif ($browser->isSafari) {
$width = '92px';
$height = '20px';
$top = '-3px';
$left = '-3px';
}
?>

That wasn't too bad, was it? Now, augmenting the CSS is a snap.


So, to put it ALL together, we wind up with this:


<?php
// include the Browser_Lite.php file
require_once 'Browser_Lite.php';

// instantiate the HYPONIQS_Browser_Lite class
$browser = new HYPONIQS_Browser_Lite();

// We'll use this variable to decide if the browser being used
// is one we're supporting

$supported = false;

// make sure the browser is one we're supporting
if (
// This example uses Windows Vista; we must make sure the user
// is on Windows Vista

$browser->platform == 'WinVista' &&

// Now we just have to make sure that they are on one of the
// supported browsers

($browser->isIE ||
$browser->isFirefox ||
$browser->isOpera ||
$browser->isSafari)
)
{

$supported = true;
}

// check if browser is Internet Explorer
if ($browser->isIE) {
$width = '79px';
$height = '18px';
$top = '-1px';
$left = '-156px';

// check if browser is Firefox
} elseif ($browser->isFirefox) {
$width = '73px';
$height = '22px';
$top = '-1px';
$left = '-150px';

// check if browser is Opera
} elseif ($browser->isOpera) {
$width = '72px';
$height = '20px';
$top = '-1px';
$left = '-133px';

// check if browser is Safari
} elseif ($browser->isSafari) {
$width = '92px';
$height = '20px';
$top = '-3px';
$left = '-3px';
}
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns=
"http://www.w3.org/1999/xhtml">
<head>
<title>
Input Type File Experiment</title>
<?php
// Now, we're only including this CSS if the browser being used is supported!
if ($supported) :
?>
<style charset="utf-8" media="screen" type="text/css">
div.fileInputLabel {
float: left;
margin-left: 5px;
padding-top: 2px;
}

div.fileInputContainer {

position: relative;
overflow: hidden;
float: left;
width: <?php echo $width; ?>;
height: <?php echo $height; ?>;
}

div.fileInputContainer input.fileInput {

position: absolute;
left: <?php echo $left; ?>;
top: <?php echo $top; ?>;
}

</style>
<?php
// This is so that we still get a pretty display between the label and the input element
else :
?>
<style charset="utf-8" media="screen" type="text/css">
div.fileInputLabel {
float: left;
margin-left: 5px;
padding-top: 2px;
}

div.fileInputContainer {

position: relative;
float: left;
}

div.fileInputContainer input.fileInput {
}

</style>
<?php
endif;
?>
</head>

<body>

<form action="/path/to/action/file.php" enctype="multipart/form-data" method="post">
<div class="fileInputContainer">
<input class="fileInput" id="fileInput" name="fileInput" type="file" />
</div>
<div class=
"fileInputLabel" id="fileInputLabel"></div>
</form>
</body>
</html>

Didn't I Mention JavaScript?


Now that we have all that stuff out of the way, there's just one more thing we're lacking: the JavaScript.


I found, not too long ago, a simple JavaScript framework for easily manipulating the DOM. That framework is jQuery: The "Write Less, Do More" JavaScript Library. If you're unfamiliar with it, I suggest you take a look-see. It solves many common issues with cross-browser compatibility and makes writing DOM manipulation JavaScript tasks a snap. I highly recommend this application as I have found it quite useful.


Unfortunately, everything in the following code strictly depends on the inclusion of jQuery in your application. You must have a fundamental understanding of the use of that framework in order to completely understand the following. That said, however, jQuery is lightning-fast to learn and comprehend. If you have any JavaScript experience whatsoever, you should be able to catch on pretty quick.


So, on that note, let me explain what we're going to do. Logically, it is fair to assume that we're finally going to solve the initial problem: "How do I hide the text-box (or label, as is the case in Apple Safari) and only display the file name?" The solution, in its entirety, lacks in complication. First, we get the entire (albeit misguided) file path of the selected file. Closely following, we extract simply the file name and then, finally, display that in the label we created using the xhtml markup <div class="fileInputLabel" id="fileInputLabel"></div>.


jQuery makes this task relatively painless. We'll simply utilize its built-in methods for extracting the value of the file input element and transfer only the file name to the label. And, without further ado, here's the code:


<script charset="utf-8" src="jQuery-1.3.2.js" type="text/javascript"></script>
<script charset=
"utf-8" type="text/javascript">
// attach the init function to the WINDOW object
/**
* This function attaches an event handler to the file input element's
* onchange event.
*/

this.init = function ()
{
$('#fileInput').change(fileInputChanged);
};

/**
* This function handles the onchange event of the file input element
*/

fileInputChanged = function ()
{
// get the file path of the selected file by way of the
// file input element's value property

var path = $('#fileInput').val();

// create a RegEx object for searching for backslashes in
// the path

var regEx = /\\/g;

// replace all occurrences of backslashes with forward slashes
// (this makes coding easier)

path = path.replace(regEx, '/');

// get the character index number of the last occurrence of
// a forward slash (directory delimiter)

var lastIndexOffset = path.lastIndexOf('/') + 1;

// the length of the final file name string
var length = path.length - lastIndexOffset;

// get the file name by extracting only the text from the last
// occurrence of a forward slash to the end of the path string

var fileName = path.substr(lastIndexOffset, length);

// finally, make the file name appear in the label we created
$('#fileInputLabel').text(fileName);
};

// When the DOCUMENT object has finished loading (all images,
// stylesheets, scripts, and markup, as well as all other external,
// included files), initialize this script.

$(document).ready(
function ()
{
init();
}
);
</script>

Wrapping Things Up


To close the application, here's a look at the completed code:


<?php
// include the Browser_Lite.php file
require_once 'Browser_Lite.php';

// instantiate the HYPONIQS_Browser_Lite class
$browser = new HYPONIQS_Browser_Lite();

// We'll use this variable to decide if the browser being used
// is one we're supporting

$supported = false;

// make sure the browser is one we're supporting
if (
// This example uses Windows Vista; we must make sure the user
// is on Windows Vista

$browser->platform == 'WinVista' &&

// Now we just have to make sure that they are on one of the
// supported browsers

($browser->isIE ||
$browser->isFirefox ||
$browser->isOpera ||
$browser->isSafari)
)
{

$supported = true;
}

// check if browser is Internet Explorer
if ($browser->isIE) {
$width = '79px';
$height = '18px';
$top = '-1px';
$left = '-156px';

// check if browser is Firefox
} elseif ($browser->isFirefox) {
$width = '73px';
$height = '22px';
$top = '-1px';
$left = '-150px';

// check if browser is Opera
} elseif ($browser->isOpera) {
$width = '72px';
$height = '20px';
$top = '-1px';
$left = '-133px';

// check if browser is Safari
} elseif ($browser->isSafari) {
$width = '92px';
$height = '20px';
$top = '-3px';
$left = '-3px';
}
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns=
"http://www.w3.org/1999/xhtml">
<head>
<title>
Input Type File Experiment</title><script charset="utf-8" src="jQuery-1.3.2.js" type="text/javascript"></script>
<script charset=
"utf-8" type="text/javascript">
// this script will be safely ignored if the user has JavaScript
// disabled or if the browser doesn't support JavaScript
//
// attach the init function to the WINDOW object
/**
* This function attaches an event handler to the file input element's
* onchange event.
*/

this.init = function ()
{
$('#fileInput').change(fileInputChanged);
};

/**
* This function handles the onchange event of the file input element
*/

fileInputChanged = function ()
{
// get the file path of the selected file by way of the
// file input element's value property

var path = $('#fileInput').val();

// create a RegEx object for searching for backslashes in
// the path

var regEx = /\\/g;

// replace all occurrences of backslashes with forward slashes
// (this makes coding easier)

path = path.replace(regEx, '/');

// get the character index number of the last occurrence of
// a forward slash (directory delimiter)

var lastIndexOffset = path.lastIndexOf('/') + 1;

// the length of the final file name string
var length = path.length - lastIndexOffset;

// get the file name by extracting only the text from the last
// occurrence of a forward slash to the end of the path string

var fileName = path.substr(lastIndexOffset, length);

// finally, make the file name appear in the label we created
$('#fileInputLabel').text(fileName);
};

// When the DOCUMENT object has finished loading (all images,
// stylesheets, scripts, and markup, as well as all other external,
// included files), initialize this script.

$(document).ready(
function ()
{
init();
}
);
</script>
<?php
// Now, we're only including this CSS and script if the browser being used is supported!
if ($supported) :
?> <style charset="utf-8" media="screen" type="text/css">
div.fileInputLabel {
float: left;
margin-left: 5px;
padding-top: 2px;
}

div.fileInputContainer {

position: relative;
overflow: hidden;
float: left;
width: <?php echo $width; ?>;
height: <?php echo $height; ?>;
}

div.fileInputContainer input.fileInput {

position: absolute;
left: <?php echo $left; ?>;
top: <?php echo $top; ?>;
}

</style>
<?php
// This is so that we still get a pretty display between the label and the input element
else :
?>
<style charset="utf-8" media="screen" type="text/css">
div.fileInputLabel {
float: left;
margin-left: 5px;
padding-top: 2px;
}

div.fileInputContainer {

position: relative;
float: left;
}

div.fileInputContainer input.fileInput {
}

</style>
<?php
endif;
?>
</head>

<body>

<form action="/path/to/action/file.php" enctype="multipart/form-data" method="post">
<div class="fileInputContainer">
<input class="fileInput" id="fileInput" name="fileInput" type="file" />
</div>
<div class="fileInputLabel" id=
"fileInputLabel"></div>
</form>
</body>
</html>

In Conclusion


Just for peace of mind, I'd like to once again assure you that this solution, as it stands, is meant only to support the most recent versions of Microsoft Internet Explorer, Apple Safari, Mozilla FireFox, and Opera under the Microsoft Windows Vista operating system. If you'd like to support other browsers and/or operating systems, it would take much more investigation into the behaviors of each browser on each operating system. I am not doing that here as this is little more than a starting point for the average developer. I would imagine that supporting a much wider base would require many more hours of investigation than I have already involved myself in.


All that said, I hope this 'solution', as it were, gives you inspiration to pursue a much more complete application based on this one.


I hold no license on this application, although I do ask that you accredit me with the original idea as well as link back to me if you use my code.